From 3a23c59c29cc7a205b1d622b92058f3d1d89aeda Mon Sep 17 00:00:00 2001 From: JasonJiaJie Date: Thu, 7 Dec 2017 11:06:10 +0800 Subject: [PATCH 1/3] [Termios]1. Add termios test. 2.Add termios.h 1. Add termios test. 2.Add termios.h --- components/libc/compilers/armlibc/termios.h | 7 + components/libc/termios/posix_termios.c | 14 +- examples/libc/termios_test.c | 360 ++++++++++++++++++++ 3 files changed, 373 insertions(+), 8 deletions(-) create mode 100644 components/libc/compilers/armlibc/termios.h create mode 100644 examples/libc/termios_test.c diff --git a/components/libc/compilers/armlibc/termios.h b/components/libc/compilers/armlibc/termios.h new file mode 100644 index 0000000000..0b54066a76 --- /dev/null +++ b/components/libc/compilers/armlibc/termios.h @@ -0,0 +1,7 @@ +#ifndef _TERMIOS_H__ +#define _TERMIOS_H__ + +#include +#include + +#endif diff --git a/components/libc/termios/posix_termios.c b/components/libc/termios/posix_termios.c index 4ec513ef1d..4f7417cb27 100644 --- a/components/libc/termios/posix_termios.c +++ b/components/libc/termios/posix_termios.c @@ -28,8 +28,6 @@ #include -#include "posix_termios.h" - int tcgetattr(int fd, struct termios *tio) { /* Get the current serial port settings. */ @@ -41,20 +39,20 @@ int tcgetattr(int fd, struct termios *tio) int tcsetattr(int fd, int act, const struct termios *tio) { - switch (act) + switch (act) { case TCSANOW: /* make the change immediately */ return (ioctl(fd, TCSETA, (void*)tio)); case TCSADRAIN: /* - * Don't make the change until all currently written data + * Don't make the change until all currently written data * has been transmitted. */ return (ioctl(fd, TCSETAW, (void*)tio)); case TCSAFLUSH: - /* Don't make the change until all currently written data - * has been transmitted, at which point any received but + /* Don't make the change until all currently written data + * has been transmitted, at which point any received but * unread data is also discarded. */ return (ioctl(fd, TCSETAF, (void*)tio)); @@ -65,7 +63,7 @@ int tcsetattr(int fd, int act, const struct termios *tio) } /** - * this function gets process group ID for session leader for controlling + * this function gets process group ID for session leader for controlling * terminal * * @return always 0 @@ -87,7 +85,7 @@ speed_t cfgetispeed(const struct termios *tio) int cfsetospeed(struct termios *tio, speed_t speed) { - if (speed & ~CBAUD) + if (speed & ~CBAUD) { errno = EINVAL; return -1; diff --git a/examples/libc/termios_test.c b/examples/libc/termios_test.c new file mode 100644 index 0000000000..192021b9ab --- /dev/null +++ b/examples/libc/termios_test.c @@ -0,0 +1,360 @@ +/* + * termios_test.c + * + * Created on: 2017-12-06 + * Author: JasonJia + */ + +#include +#include +#include +#include +#include + +#if defined (RT_USING_POSIX) + #include + #include + #if defined (RT_USING_POSIX_TERMIOS) + #include + #else + #error "TERMIOS need RT_USING_POSIX_TERMIOS" + #endif +#else + #error "POSIX poll/select need RT_USING_POSIX" +#endif + +#define JOINT(x,y) x##y +#define B(x) JOINT(B,x) +#define Default_baud_rate 115200 +#define Default_parity 'n' +#define BUFFER_SIZE 64 + +struct termios_test_s +{ + int baud_rate; + const char *dev; +}; + +static struct termios_test_s term_param; + +static int _check_baud_rate(int baud_rate) +{ + #define BAUD_RATE(x) \ + {\ + if(x==baud_rate) \ + {\ + rt_kprintf("%d baud rate\n",baud_rate);\ + return JOINT(B,x);\ + }\ + } + BAUD_RATE(110); + BAUD_RATE(200); + BAUD_RATE(300); + BAUD_RATE(600); + BAUD_RATE(1200); + BAUD_RATE(1800); + BAUD_RATE(2400); + BAUD_RATE(4800); + BAUD_RATE(9600); + BAUD_RATE(19200); + BAUD_RATE(38400); + BAUD_RATE(57600); + BAUD_RATE(115200); + BAUD_RATE(230400); + BAUD_RATE(460800); + BAUD_RATE(921600); + + rt_kprintf("%d is not support,use default %d value.\n",baud_rate,Default_baud_rate); + return B(Default_baud_rate); +} + +int open_comm(const char *name) +{ + int fd; + fd = open(name, O_RDWR | O_NOCTTY | O_NONBLOCK, 0); + if(fd == -1) + { + rt_kprintf("Open %s fail.\n",name); + return -1; + } + else + { + rt_kprintf("Open %s success,fd:%d\n",name,fd); + } + + return fd; +} + +void close_comm(int fd) +{ + if(fd != -1) + { + close(fd); + } +} + +void config_comm(int fd, int speed_baud_rate, char parity, int data_bits, int stop_bits) +{ + int valid_baud_rate = 0; + struct termios new_tc; + + memset(&new_tc, 0x00, sizeof(struct termios)); + + valid_baud_rate = _check_baud_rate(speed_baud_rate); + + new_tc.c_cflag |= (CLOCAL | CREAD);//Enable in default. + + /* + *Set baud rate. e.g B115200 is 115200 bauds. + */ + cfsetispeed(&new_tc, valid_baud_rate);//input speed + cfsetospeed(&new_tc, valid_baud_rate);//output speed + + /* + *Set parity. + */ + switch(parity) + { + case 'n': + case 'N': + new_tc.c_cflag &= ~PARENB; //Disable parity. + break; + case 'o': + case 'O': + new_tc.c_cflag |= PARENB; //Enable parity. + new_tc.c_cflag |= PARODD; //Odd parity. + break; + case 'e': + case 'E': + new_tc.c_cflag |= PARENB; //Enable parity. + new_tc.c_cflag &= ~PARODD; //even parity. + break; + } + + /* + *Set data bits. + */ + new_tc.c_cflag &= ~CSIZE; + switch(data_bits) + { + case 5: + break; + case 6: + break; + case 7: + new_tc.c_cflag |= CS7; + break; + case 8: + new_tc.c_cflag |= CS8; + break; + } + + /* + *Set stop bits. + */ + (stop_bits == 2)?(new_tc.c_cflag |= CSTOPB):(new_tc.c_cflag &= ~ CSTOPB); + + tcflush(fd,TCIFLUSH); + //new_tc.c_cc[VTIME] = 0; + //new_tc.c_cc[VMIN] = 1; + + if( tcsetattr(fd, TCSANOW, &new_tc) != 0) + { + rt_kprintf("Set port config fail!\n"); + } +} + +int recv_comm(int fd, unsigned char *buffer, rt_size_t size, struct timeval *timeout) +{ + struct timeval t; + int ret = 0; + rt_size_t drv_recved = 0; + int recved = 0, need = size; + int timeout_cnt = 0; + unsigned char *c = RT_NULL; + fd_set readSet; + + RT_ASSERT(RT_NULL != buffer); + + if(fd == -1) + { + return -1; + } + + t.tv_sec = 0; + t.tv_usec = 100000; + + if(RT_NULL == timeout) + { + /* Wait forever approximate, it's a large time. */ + timeout_cnt = 0xffffffff; + } + else + { + timeout_cnt = (timeout->tv_sec * 1000 * 1000 + timeout->tv_usec)/(t.tv_sec * 1000 * 1000 + t.tv_usec); + } + + while(1) + { + FD_ZERO(&readSet); + FD_SET(fd, &readSet); + + ret = select(fd+1,&readSet,RT_NULL,RT_NULL,&t); + if(ret < 0) + { + rt_kprintf("select error %d\n",ret); + break; + } + else if(ret == 0) + { + /* timeout */ + timeout_cnt--; + + if(timeout_cnt == 0) + { + rt_kprintf("need %d data in timeout %d ms,but only %d recved.\n", + size, + timeout->tv_sec * 1000 + timeout->tv_usec / 1000, + recved); + + recved = 0; + + break; + } + } + else + { + if(FD_ISSET(fd, &readSet)) + { + c = &buffer[size - need]; + ioctl(fd, FIONREAD, &drv_recved); + + /* check poll and ioctl */ + RT_ASSERT(drv_recved != 0); + + drv_recved = (drv_recved > need ? need : drv_recved); + recved = read(fd, c, drv_recved); + if(recved != drv_recved) + { + rt_kprintf("fatal error %s(%d).\n",__FUNCTION__,__LINE__); + RT_ASSERT(0); + recved = 0; + break; + } + + need -= recved; + + if(need) + { + continue; + } + else if (need == 0) + { + recved = size; + break; + } + else + { + rt_kprintf("fatal error %s(%d).\n",__FUNCTION__,__LINE__); + RT_ASSERT(0); + } + + } + } + } + + return recved; +} + +int send_comm(int fd, const unsigned char *buffer, rt_size_t size) +{ + RT_ASSERT(RT_NULL != buffer); + + if(fd == -1) + { + return -1; + } + + //serial framework does not support poll out now + write(fd, buffer, size); + + return 0; +} + +int flush_comm(int fd) +{ + if(fd == -1) + { + return -1; + } + tcflush(fd,TCIFLUSH); + return 0; +} + +void termios_test_entry(void *p) +{ + int len = 0; + int fd = -1; + unsigned char *pBuf = RT_NULL; + struct termios_test_s *pTerm = (struct termios_test_s *)p; + + if((fd = open_comm(pTerm->dev)) == -1) + { + rt_kprintf("Check the device name...\n"); + return; + } + + pBuf = (unsigned char *)rt_malloc(BUFFER_SIZE); + RT_ASSERT(pBuf != RT_NULL); + + memset(pBuf, 0x00, BUFFER_SIZE); + + config_comm(fd, pTerm->baud_rate, Default_parity, 8, 1); + + flush_comm(fd); + + rt_kprintf("Block recv 10 bytes.\n"); + /* Block recv 10 bytes */ + len = recv_comm(fd, pBuf, 10, RT_NULL); + + rt_kprintf("Recv:%s\n", pBuf); + + send_comm(fd, pBuf, len); + rt_kprintf("Termios test exit.\n"); + + close_comm(fd); + + rt_free(pBuf); + pBuf = RT_NULL; +} + +int termios_test(int argc, char **argv) +{ + rt_thread_t tid; + + if(argc < 2) + { + rt_kprintf("Please input device name...\n"); + return -1; + } + + term_param.dev = argv[1]; + term_param.baud_rate = ((argc >= 3) ? atoi(argv[2]) : Default_baud_rate); + + tid = rt_thread_create("termtest", + termios_test_entry, (void *)&term_param, + 512, RT_THREAD_PRIORITY_MAX/3, 20); + + if (tid != RT_NULL) + rt_thread_startup(tid); + + return 0; +} + +#ifdef RT_USING_FINSH + #include + #ifdef FINSH_USING_MSH + MSH_CMD_EXPORT_ALIAS(termios_test, termtest, e.g: termtest /dev/uart4 115200); + #endif /* FINSH_USING_MSH */ +#endif /* RT_USING_FINSH */ + From bd4c90f61948810278b774a4ba1ad3440c7d1460 Mon Sep 17 00:00:00 2001 From: JasonJiaJie Date: Thu, 7 Dec 2017 17:52:20 +0800 Subject: [PATCH 2/3] [Termios]Fix compile error for gcc and iar. Fix compile error for gcc and iar.Add termios.h to newlib and dlib --- components/libc/compilers/dlib/termios.h | 7 +++++++ components/libc/compilers/newlib/termios.h | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 components/libc/compilers/dlib/termios.h create mode 100644 components/libc/compilers/newlib/termios.h diff --git a/components/libc/compilers/dlib/termios.h b/components/libc/compilers/dlib/termios.h new file mode 100644 index 0000000000..0b54066a76 --- /dev/null +++ b/components/libc/compilers/dlib/termios.h @@ -0,0 +1,7 @@ +#ifndef _TERMIOS_H__ +#define _TERMIOS_H__ + +#include +#include + +#endif diff --git a/components/libc/compilers/newlib/termios.h b/components/libc/compilers/newlib/termios.h new file mode 100644 index 0000000000..0b54066a76 --- /dev/null +++ b/components/libc/compilers/newlib/termios.h @@ -0,0 +1,7 @@ +#ifndef _TERMIOS_H__ +#define _TERMIOS_H__ + +#include +#include + +#endif From e9b846d1197e01c29d0d212570c05fa2adbb265d Mon Sep 17 00:00:00 2001 From: JasonJiaJie Date: Thu, 14 Dec 2017 09:28:10 +0800 Subject: [PATCH 3/3] [list]1.Modify rt_slist_foreach to rt_slist_for_each_entry. 2.Add rt_sllist_isempty. 3.Make code cleanup 1.Modify rt_slist_foreach to rt_slist_for_each_entry. 2.Add rt_sllist_isempty. 3.Make code cleanup --- include/rtservice.h | 82 ++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/include/rtservice.h b/include/rtservice.h index 2bf1fbe1d6..7c7982da00 100644 --- a/include/rtservice.h +++ b/include/rtservice.h @@ -23,6 +23,8 @@ * 2006-09-07 Bernard move the kservice APIs to rtthread.h * 2007-06-27 Bernard fix the rt_list_remove bug * 2012-03-22 Bernard rename kservice.h to rtservice.h + * 2017-11-15 JasonJia Modify rt_slist_foreach to rt_slist_for_each_entry. + * Make code cleanup. */ #ifndef __RT_SERVICE_H__ @@ -38,6 +40,14 @@ extern "C" { /*@{*/ +/** + * rt_container_of - return the member address of ptr, if the type of ptr is the + * struct type. + */ +#define rt_container_of(ptr, type, member) \ + ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member))) + + /** * @brief initialize a list object */ @@ -128,7 +138,7 @@ rt_inline unsigned int rt_list_len(const rt_list_t *l) * @param member the name of list in structure */ #define rt_list_entry(node, type, member) \ - ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member))) + rt_container_of(node, type, member) /** * rt_list_for_each_entry - iterate over list of given type @@ -136,9 +146,9 @@ rt_inline unsigned int rt_list_len(const rt_list_t *l) * @head: the head for your list. * @member: the name of the list_struct within the struct. */ -#define rt_list_for_each_entry(pos, head, member) \ - for (pos = rt_list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ +#define rt_list_for_each_entry(pos, head, member) \ + for (pos = rt_list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ pos = rt_list_entry(pos->member.next, typeof(*pos), member)) /** @@ -148,10 +158,10 @@ rt_inline unsigned int rt_list_len(const rt_list_t *l) * @head: the head for your list. * @member: the name of the list_struct within the struct. */ -#define rt_list_for_each_entry_safe(pos, n, head, member) \ - for (pos = rt_list_entry((head)->next, typeof(*pos), member), \ - n = rt_list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ +#define rt_list_for_each_entry_safe(pos, n, head, member) \ + for (pos = rt_list_entry((head)->next, typeof(*pos), member), \ + n = rt_list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ pos = n, n = rt_list_entry(n->member.next, typeof(*n), member)) /** @@ -195,18 +205,6 @@ rt_inline void rt_slist_insert(rt_slist_t *l, rt_slist_t *n) l->next = n; } -rt_inline rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n) -{ - /* remove slist head */ - struct rt_slist_node *node = l; - while (node->next && node->next != n) node = node->next; - - /* remove node */ - if (node->next != (rt_slist_t *)0) node->next = node->next->next; - - return l; -} - rt_inline unsigned int rt_slist_len(const rt_slist_t *l) { unsigned int len = 0; @@ -220,29 +218,53 @@ rt_inline unsigned int rt_slist_len(const rt_slist_t *l) return len; } +rt_inline rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n) +{ + /* remove slist head */ + struct rt_slist_node *node = l; + while (node->next && node->next != n) node = node->next; + + /* remove node */ + if (node->next != (rt_slist_t *)0) node->next = node->next->next; + + return l; +} + +rt_inline int rt_slist_isempty(rt_slist_t *l) +{ + return l->next == RT_NULL; +} + /** * @brief get the struct for this single list node * @param node the entry point * @param type the type of structure * @param member the name of list in structure */ -#define rt_slist_entry(node, type, member) \ - ((type *)((char*)(node)-(unsigned long)(&((type *)0)->member))) +#define rt_slist_entry(node, type, member) \ + rt_container_of(node, type, member) /** * rt_slist_for_each_entry - iterate over single list of given type - * @node: the type * to use as a loop cursor. - * @list: the head for your single list. + * @pos: the type * to use as a loop cursor. + * @head: the head for your single list. + * @member: the name of the list_struct within the struct. */ -#define rt_slist_foreach(node, list) \ - for ((node) = (list)->next; (node) != RT_NULL; (node) = (node)->next) +#define rt_slist_fore_each_entry(pos, head, member) \ + for (pos = rt_slist_entry((head)->next, typeof(*pos), member); \ + &pos->member != (RT_NULL); \ + pos = rt_slist_entry(pos->member.next, typeof(*pos), member)) /** - * rt_container_of - return the member address of ptr, if the type of ptr is the - * struct type. + * rt_slist_first_entry - get the first element from a slist + * @ptr: the slist head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the slist_struct within the struct. + * + * Note, that slist is expected to be not empty. */ -#define rt_container_of(ptr, type, member) \ - ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member))) +#define rt_slist_first_entry(ptr, type, member) \ + rt_slist_entry((ptr)->next, type, member) /*@}*/