Files
kernel_drivers_examples/debug/uart/uart_loop_test.c
2018-11-22 15:55:28 +08:00

453 lines
7.6 KiB
C

#include <stdarg.h>
#include <termio.h>
#include <sys/time.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#define DEFAULT_RATE 115200
#define ALPHABET_LEN 26
#define DATA_NR 500
/* uart device handler */
int fd;
/* thrad worker swither */
int trun, rrun;
/* recv and xfer count */
unsigned int tcount, rcount;
/* fp for read file */
FILE *fp_read;
/* totoal data size for test */
int data_size = DATA_NR * ALPHABET_LEN;
/* test data */
static char alphabet_table[ALPHABET_LEN];
static int xfer_only = 0;
static int recv_only = 0;
static speed_t baudrate_map(unsigned long b)
{
speed_t retval;
switch (b)
{
case 110:
retval = B110;
break;
case 300:
retval = B300;
break;
case 1200:
retval = B1200;
break;
case 2400:
retval = B2400;
break;
case 4800:
retval = B4800;
break;
case 9600:
retval = B9600;
break;
case 19200:
retval = B19200;
break;
case 38400:
retval = B38400;
break;
case 57600:
retval = B57600;
break;
case 115200:
retval = B115200;
break;
#ifdef B230400
case 230400:
retval = B230400;
break;
#endif
#ifdef B460800
case 460800:
retval = B460800;
break;
#endif
#ifdef B500000
case 500000:
retval = B500000;
break;
#endif
#ifdef B576000
case 576000:
retval = B576000;
break;
#endif
#ifdef B921600
case 921600:
retval = B921600;
break;
#endif
#ifdef B1000000
case 1000000:
retval = B1000000;
break;
#endif
#ifdef B1152000
case 1152000:
retval = B1152000;
break;
#endif
#ifdef B1500000
case 1500000:
retval = B1500000;
break;
#endif
#ifdef B2000000
case 2000000:
retval = B2000000;
break;
#endif
#ifdef B2500000
case 2500000:
retval = B2500000;
break;
#endif
#ifdef B3000000
case 3000000:
retval = B3000000;
break;
#endif
#ifdef B3500000
case 3500000:
retval = B3500000;
break;
#endif
#ifdef B4000000
case 4000000:
retval = B4000000;
break;
#endif
default:
retval = 0;
break;
}
return(retval);
}
/* xfer DATA_NR number of alphabet data */
void *Uartsend(void * threadParameter)
{
int i;
char *tx_buf;
double speed;
time_t start;
time_t end;
time_t time_consuming;
tcount = 0;
for (i = 0; i < ALPHABET_LEN; i++)
#ifdef XFER_SINE_WAVE
/* show a sine wave on oscilloscope */
alphabet_table[i] = 'U';
#else
alphabet_table[i] = i + 'A';
#endif
tx_buf = malloc(data_size);
for (i = 0; i < DATA_NR; i++)
memcpy(tx_buf + i*ALPHABET_LEN, alphabet_table, ALPHABET_LEN);
while (trun)
{
sleep(1);
start = time(NULL);
write(fd, tx_buf, data_size);
end = time(NULL);
time_consuming = end - start;
speed = data_size * 8 / time_consuming;
tcount += data_size;
printf("sent %d bytes with speed %fbps\n", data_size, speed);
}
free(tx_buf);
return 0;
}
/* recv uart data, and write it into file */
void *Uartread(void * threadParameter)
{
char *rx_buf;
int iores, iocount;
rcount = 0;
while (rrun)
{
iocount = 0;
iores = ioctl(fd, FIONREAD, &iocount);
if(!iocount)
continue;
rx_buf = malloc(iocount);
/* Read in and wrap around the list */
iores = read(fd, rx_buf, iocount);
rcount += iores;
if (recv_only)
{
rx_buf[iores] = '\0';
printf("%s[%d:%d]\n", rx_buf, rcount, iores);
}
else
{
#ifdef DEBUG_MESSAGE
rx_buf[iores] = '\0';
printf("%s[%d:%d]\n", rx_buf, rcount, iores);
#endif
fwrite(rx_buf, 1, iores, fp_read);
free(rx_buf);
}
}
return 0;
}
static void print_usage(const char *name)
{
printf("Usage: %s <tty name> [-S] [-O] [-E] [-HW] [-B baudrate] [-X | -R]"
"\n\t'-S' for 2 stop bit"
"\n\t'-O' for PARODD "
"\n\t'-E' for PARENB"
"\n\t'-HW' for HW flow control enable"
"\n\t'-B' baudrate' for different baudrate"
"\n\t'-X' xfer only, '-R' recv only(default loop mode)\n", name);
}
int main(int argc, char *argv[])
{
int i, ret;
struct termios options;
unsigned long baudrate = DEFAULT_RATE;
char c = 0;
pthread_t p_Uartsend, p_Uartread;
void *thread_res;
char *test_result = "Failed";
if (argc < 2) {
print_usage(argv[0]);
return -1;
}
fd = open(argv[1], O_RDWR | O_NOCTTY);
if (fd == -1)
{
printf("open_port: Unable to open serial port - %s", argv[1]);
return -1;
}
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &options);
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_cflag |= CS8;
options.c_cflag &= ~CRTSCTS;
options.c_lflag &= ~(ICANON | IEXTEN | ISIG | ECHO);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON | BRKINT );
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
options.c_cflag |= (CLOCAL | CREAD);
for (i = 2; i < argc; i++) {
if (!strcmp(argv[i], "-S")) {
options.c_cflag |= CSTOPB;
continue;
}
if (!strcmp(argv[i], "-O")) {
options.c_cflag |= PARODD;
options.c_cflag &= ~PARENB;
continue;
}
if (!strcmp(argv[i], "-E")) {
options.c_cflag &= ~PARODD;
options.c_cflag |= PARENB;
continue;
}
if (!strcmp(argv[i], "-HW")) {
options.c_cflag |= CRTSCTS;
continue;
}
if (!strcmp(argv[i], "-B")) {
i++;
baudrate = atoi(argv[i]);
if(!baudrate_map(baudrate))
baudrate = DEFAULT_RATE;
continue;
}
if (!strcmp(argv[i], "-X")) {
xfer_only = 1;
continue;
}
if (!strcmp(argv[i], "-R")) {
recv_only = 1;
continue;
}
}
if (baudrate) {
cfsetispeed(&options, baudrate_map(baudrate));
cfsetospeed(&options, baudrate_map(baudrate));
}
tcsetattr(fd, TCSANOW, &options);
printf("UART %lu, %dbit, %dstop, %s, HW flow %s\n", baudrate, 8,
(options.c_cflag & CSTOPB) ? 2 : 1,
(options.c_cflag & PARODD) ? "PARODD" : "PARENB",
(options.c_cflag & CRTSCTS) ? "enabled" : "disabled");
/* xfer only mode */
if (xfer_only)
{
trun = 1;
rrun = 0;
}
else if (recv_only) /* recv only mode */
{
rrun = 1;
trun = 0;
}
else /* loop test mode */
{
trun = 1;
rrun = 1;
}
fp_read = fopen("uart_read.txt","wb");
if (trun)
{
/* create and start the xfer thread */
ret = pthread_create(&p_Uartsend, NULL, Uartsend, NULL);
if (ret < 0)
goto error;
}
if (rrun)
{
/*
* create and start the recv thread
* stop the xfer thread if and error happend
*/
ret = pthread_create(&p_Uartread, NULL, Uartread, NULL);
if (ret < 0 && trun) {
ret = pthread_join(p_Uartsend, &thread_res);
goto error;
}
}
/* stop the test */
printf("test begin, press 'c' to exit\n");
while (c != 'c') {
c = getchar();
}
/* xfer only mode */
if (xfer_only)
{
/* stop xfer thread */
trun = 0;
ret = pthread_join(p_Uartsend, &thread_res);
if (ret < 0)
printf("fail to stop Uartsend thread\n");
test_result = "Done";
/* normal exit */
goto error;
}
/* recv only mode */
if (recv_only)
{
/* stop recv thread */
rrun = 0;
ret = pthread_join(p_Uartread, &thread_res);
if (ret < 0)
printf("fail to stop Uartread thread\n");
test_result = "Done";
/* normal exit */
goto error;
}
/* loop test mode */
/* stop xfer thread */
trun = 0;
ret = pthread_join(p_Uartsend, &thread_res);
if (ret < 0)
printf("fail to stop Uartsend thread\n");
printf("tcount=%d Bytes\n", tcount);
/* wait 5 more seconds, when recv thread not yet completed */
i = 5;
while ((tcount > rcount) && i) {
i--;
sleep(1);
}
/* stop the recv thread */
rrun = 0;
ret = pthread_join(p_Uartread, &thread_res);
if (ret < 0)
printf("fail to stop Uartread thread\n");
printf("rcount=%d Bytes\n", rcount);
if (rcount == tcount)
test_result = "Successed";
error:
fclose(fp_read);
close(fd);
printf("Test %s\n", test_result);
return 0;
}