2015-06-14 22:37:19 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 Freie Universität Berlin
|
|
|
|
*
|
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
|
|
* directory for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ingroup tests
|
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Manual test application for UART peripheral drivers
|
|
|
|
*
|
|
|
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
|
|
|
*
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "board.h"
|
|
|
|
#include "shell.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#include "msg.h"
|
|
|
|
#include "ringbuffer.h"
|
|
|
|
#include "periph/uart.h"
|
2016-04-14 16:03:14 +02:00
|
|
|
#include "uart_stdio.h"
|
2018-01-26 10:13:45 +01:00
|
|
|
#include "xtimer.h"
|
2015-06-14 22:37:19 +02:00
|
|
|
|
|
|
|
#define SHELL_BUFSIZE (128U)
|
|
|
|
#define UART_BUFSIZE (128U)
|
|
|
|
|
|
|
|
#define PRINTER_PRIO (THREAD_PRIORITY_MAIN - 1)
|
|
|
|
#define PRINTER_TYPE (0xabcd)
|
|
|
|
|
2018-01-26 10:13:45 +01:00
|
|
|
#define POWEROFF_DELAY (250U * US_PER_MS) /* quarter of a second */
|
|
|
|
|
2016-03-09 19:39:34 +01:00
|
|
|
#ifndef UART_STDIO_DEV
|
|
|
|
#define UART_STDIO_DEV (UART_UNDEF)
|
2015-06-14 22:37:19 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
char rx_mem[UART_BUFSIZE];
|
|
|
|
ringbuffer_t rx_buf;
|
|
|
|
} uart_ctx_t;
|
|
|
|
|
|
|
|
static uart_ctx_t ctx[UART_NUMOF];
|
|
|
|
|
|
|
|
static kernel_pid_t printer_pid;
|
|
|
|
static char printer_stack[THREAD_STACKSIZE_MAIN];
|
|
|
|
|
|
|
|
static int parse_dev(char *arg)
|
|
|
|
{
|
2017-05-13 12:39:48 +02:00
|
|
|
unsigned dev = atoi(arg);
|
2016-04-08 10:49:34 +02:00
|
|
|
if (dev >= UART_NUMOF) {
|
2016-08-21 16:58:25 +02:00
|
|
|
printf("Error: Invalid UART_DEV device specified (%u).\n", dev);
|
2015-06-14 22:37:19 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2016-04-08 10:49:34 +02:00
|
|
|
else if (UART_DEV(dev) == UART_STDIO_DEV) {
|
2016-08-21 16:58:25 +02:00
|
|
|
printf("Error: The selected UART_DEV(%u) is used for the shell!\n", dev);
|
2016-04-08 10:49:34 +02:00
|
|
|
return -2;
|
|
|
|
}
|
2015-06-14 22:37:19 +02:00
|
|
|
return dev;
|
|
|
|
}
|
|
|
|
|
2016-03-15 10:58:29 +01:00
|
|
|
static void rx_cb(void *arg, uint8_t data)
|
2015-06-14 22:37:19 +02:00
|
|
|
{
|
2015-12-09 09:29:47 +01:00
|
|
|
uart_t dev = (uart_t)arg;
|
2015-06-14 22:37:19 +02:00
|
|
|
|
|
|
|
ringbuffer_add_one(&(ctx[dev].rx_buf), data);
|
2017-01-09 13:17:04 +01:00
|
|
|
if (data == '\n') {
|
2015-06-14 22:37:19 +02:00
|
|
|
msg_t msg;
|
|
|
|
msg.content.value = (uint32_t)dev;
|
|
|
|
msg_send(&msg, printer_pid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *printer(void *arg)
|
|
|
|
{
|
|
|
|
(void)arg;
|
|
|
|
msg_t msg;
|
|
|
|
msg_t msg_queue[8];
|
|
|
|
msg_init_queue(msg_queue, 8);
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
msg_receive(&msg);
|
2015-12-09 09:29:47 +01:00
|
|
|
uart_t dev = (uart_t)msg.content.value;
|
2015-06-14 22:37:19 +02:00
|
|
|
char c;
|
|
|
|
|
2018-07-11 07:25:36 +02:00
|
|
|
printf("Success: UART_DEV(%i) RX: [", dev);
|
2015-06-14 22:37:19 +02:00
|
|
|
do {
|
|
|
|
c = (int)ringbuffer_get_one(&(ctx[dev].rx_buf));
|
2017-01-09 13:17:04 +01:00
|
|
|
if (c == '\n') {
|
2018-07-11 07:25:36 +02:00
|
|
|
puts("]\\n");
|
2015-06-14 22:37:19 +02:00
|
|
|
}
|
|
|
|
else if (c >= ' ' && c <= '~') {
|
|
|
|
printf("%c", c);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("0x%02x", (unsigned char)c);
|
|
|
|
}
|
2017-01-09 13:17:04 +01:00
|
|
|
} while (c != '\n');
|
2015-06-14 22:37:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* this should never be reached */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-01-26 10:13:45 +01:00
|
|
|
static void sleep_test(int num, uart_t uart)
|
|
|
|
{
|
|
|
|
printf("UARD_DEV(%i): test uart_poweron() and uart_poweroff() -> ", num);
|
|
|
|
uart_poweroff(uart);
|
|
|
|
xtimer_usleep(POWEROFF_DELAY);
|
|
|
|
uart_poweron(uart);
|
|
|
|
puts("[OK]");
|
|
|
|
}
|
|
|
|
|
2015-06-14 22:37:19 +02:00
|
|
|
static int cmd_init(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int dev, res;
|
|
|
|
uint32_t baud;
|
|
|
|
|
|
|
|
if (argc < 3) {
|
|
|
|
printf("usage: %s <dev> <baudrate>\n", argv[0]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* parse parameters */
|
|
|
|
dev = parse_dev(argv[1]);
|
|
|
|
if (dev < 0) {
|
|
|
|
return 1;
|
|
|
|
}
|
2017-05-13 12:39:48 +02:00
|
|
|
baud = atoi(argv[2]);
|
2015-06-14 22:37:19 +02:00
|
|
|
|
|
|
|
/* initialize UART */
|
|
|
|
res = uart_init(UART_DEV(dev), baud, rx_cb, (void *)dev);
|
2016-10-28 10:31:38 +02:00
|
|
|
if (res == UART_NOBAUD) {
|
2015-06-14 22:37:19 +02:00
|
|
|
printf("Error: Given baudrate (%u) not possible\n", (unsigned int)baud);
|
|
|
|
return 1;
|
|
|
|
}
|
2016-10-28 10:31:38 +02:00
|
|
|
else if (res != UART_OK) {
|
2015-06-14 22:37:19 +02:00
|
|
|
puts("Error: Unable to initialize UART device\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2018-07-11 07:25:36 +02:00
|
|
|
printf("Success: Successfully initialized UART_DEV(%i)\n", dev);
|
2018-01-26 10:13:45 +01:00
|
|
|
|
|
|
|
/* also test if poweron() and poweroff() work (or at least don't break
|
|
|
|
* anything) */
|
|
|
|
sleep_test(dev, UART_DEV(dev));
|
|
|
|
|
2015-06-14 22:37:19 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_send(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int dev;
|
2017-01-09 13:17:04 +01:00
|
|
|
uint8_t endline = (uint8_t)'\n';
|
2015-06-14 22:37:19 +02:00
|
|
|
|
|
|
|
if (argc < 3) {
|
|
|
|
printf("usage: %s <dev> <data (string)>\n", argv[0]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* parse parameters */
|
|
|
|
dev = parse_dev(argv[1]);
|
|
|
|
if (dev < 0) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("UART_DEV(%i) TX: %s\n", dev, argv[2]);
|
2017-01-09 13:17:04 +01:00
|
|
|
uart_write(UART_DEV(dev), (uint8_t *)argv[2], strlen(argv[2]));
|
|
|
|
uart_write(UART_DEV(dev), &endline, 1);
|
2015-06-14 22:37:19 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const shell_command_t shell_commands[] = {
|
|
|
|
{ "init", "Initialize a UART device with a given baudrate", cmd_init },
|
|
|
|
{ "send", "Send a string through given UART device", cmd_send },
|
|
|
|
{ NULL, NULL, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
puts("\nManual UART driver test application");
|
|
|
|
puts("===================================");
|
|
|
|
puts("This application is intended for testing additional UART\n"
|
|
|
|
"interfaces, that might be defined for a board. The 'primary' UART\n"
|
|
|
|
"interface is tested implicitly, as it is running the shell...\n\n"
|
|
|
|
"When receiving data on one of the additional UART interfaces, this\n"
|
|
|
|
"data will be outputted via STDIO. So the easiest way to test an \n"
|
|
|
|
"UART interface, is to simply connect the RX with the TX pin. Then \n"
|
|
|
|
"you can send data on that interface and you should see the data \n"
|
2017-01-09 13:17:04 +01:00
|
|
|
"being printed to STDOUT\n\n"
|
|
|
|
"NOTE: all strings need to be '\\n' terminated!\n");
|
2015-06-14 22:37:19 +02:00
|
|
|
|
2018-01-26 10:13:45 +01:00
|
|
|
/* do sleep test for UART used as STDIO. There is a possibility that the
|
|
|
|
* value given in UART_STDIO_DEV is not a numeral (depends on the CPU
|
|
|
|
* implementation), so we rather break the output by printing a
|
|
|
|
* non-numerical value instead of breaking the UART device descriptor */
|
|
|
|
sleep_test(UART_STDIO_DEV, UART_STDIO_DEV);
|
|
|
|
|
|
|
|
puts("\nUART INFO:");
|
2015-06-14 22:37:19 +02:00
|
|
|
printf("Available devices: %i\n", UART_NUMOF);
|
2016-03-09 19:39:34 +01:00
|
|
|
printf("UART used for STDIO (the shell): UART_DEV(%i)\n\n", UART_STDIO_DEV);
|
2015-06-14 22:37:19 +02:00
|
|
|
|
|
|
|
/* initialize ringbuffers */
|
2016-04-08 10:49:34 +02:00
|
|
|
for (unsigned i = 0; i < UART_NUMOF; i++) {
|
2015-06-14 22:37:19 +02:00
|
|
|
ringbuffer_init(&(ctx[i].rx_buf), ctx[i].rx_mem, UART_BUFSIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* start the printer thread */
|
|
|
|
printer_pid = thread_create(printer_stack, sizeof(printer_stack),
|
|
|
|
PRINTER_PRIO, 0, printer, NULL, "printer");
|
|
|
|
|
|
|
|
/* run the shell */
|
|
|
|
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
|
|
|
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
|
|
|
return 0;
|
|
|
|
}
|