/************************************************************************* > File Name: uart.c > Created Time: Fri 23 Oct 2020 11:02:21 AM CST ************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bsp.h" #include "rt.h" #include "uart_user.h" #define UART_MAX_FD 256 //noted by sunxi: 因为传进来的UART_CHANNEL[i]不一定是连续的。 //static int am335x_uarts_fd[CFG_UART_NUM_MAX]; static int am335x_uarts_fd[UART_MAX_FD] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,}; static void am335x_uarts_init(int channel) { am335x_uarts_fd[channel] = -1; } static int set_port(int fd, int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio, oldtio; memset(&oldtio, 0, sizeof(oldtio)); /* save the old serial port configuration */ if(tcgetattr(fd, &oldtio) != 0) { perror("set_port/tcgetattr"); return -1; } memset(&newtio, 0, sizeof(newtio)); /* ignore modem control lines and enable receiver */ newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; /* set character size */ switch (nBits) { case 8: newtio.c_cflag |= CS8; break; case 7: newtio.c_cflag |= CS7; break; case 6: newtio.c_cflag |= CS6; break; case 5: newtio.c_cflag |= CS5; break; default: newtio.c_cflag |= CS8; break; } /* set the parity */ switch (nEvent) { default: case 'N': case 'n': { newtio.c_cflag &= ~PARENB; //清除校验位 newtio.c_iflag &= ~(ICRNL|INPCK|IXON|IXOFF); //关闭奇偶校验 关闭软件流控 break; } case 'o': case 'O': { newtio.c_cflag |= (PARODD | PARENB); //使用奇校验不是用偶校验 newtio.c_iflag |= INPCK; break; } case 'e': case 'E': { newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; //使用偶校验 newtio.c_iflag |= INPCK; break; } case 's': case 'S': { newtio.c_cflag &= ~PARENB; newtio.c_cflag &= ~CSTOPB; break; } } /* set the stop bits */ switch (nStop) { case 1: newtio.c_cflag &= ~CSTOPB; break; case 2: newtio.c_cflag |= CSTOPB; break; default: newtio.c_cflag &= ~CSTOPB; break; } /* set output and input baud rate */ switch (nSpeed) { case 0: cfsetospeed(&newtio, B0); cfsetispeed(&newtio, B0); break; case 50: cfsetospeed(&newtio, B50); cfsetispeed(&newtio, B50); break; case 75: cfsetospeed(&newtio, B75); cfsetispeed(&newtio, B75); break; case 110: cfsetospeed(&newtio, B110); cfsetispeed(&newtio, B110); break; case 134: cfsetospeed(&newtio, B134); cfsetispeed(&newtio, B134); break; case 150: cfsetospeed(&newtio, B150); cfsetispeed(&newtio, B150); break; case 200: cfsetospeed(&newtio, B200); cfsetispeed(&newtio, B200); break; case 300: cfsetospeed(&newtio, B300); cfsetispeed(&newtio, B300); break; case 600: cfsetospeed(&newtio, B600); cfsetispeed(&newtio, B600); break; case 1200: cfsetospeed(&newtio, B1200); cfsetispeed(&newtio, B1200); break; case 1800: cfsetospeed(&newtio, B1800); cfsetispeed(&newtio, B1800); break; case 2400: cfsetospeed(&newtio, B2400); cfsetispeed(&newtio, B2400); break; case 4800: cfsetospeed(&newtio, B4800); cfsetispeed(&newtio, B4800); break; case 9600: cfsetospeed(&newtio, B9600); cfsetispeed(&newtio, B9600); break; case 19200: cfsetospeed(&newtio, B19200); cfsetispeed(&newtio, B19200); break; case 38400: cfsetospeed(&newtio, B38400); cfsetispeed(&newtio, B38400); break; case 57600: cfsetospeed(&newtio, B57600); cfsetispeed(&newtio, B57600); break; case 115200: cfsetospeed(&newtio, B115200); cfsetispeed(&newtio, B115200); break; case 230400: cfsetospeed(&newtio, B230400); cfsetispeed(&newtio, B230400); break; default: cfsetospeed(&newtio, B115200); cfsetispeed(&newtio, B115200); break; } /* set timeout in deciseconds for non-canonical read */ newtio.c_cc[VTIME] = 0; /* set minimum number of characters for non-canonical read */ newtio.c_cc[VMIN] = 0; /* flushes data received but not read */ tcflush(fd, TCIFLUSH); /* set the parameters associated with the terminal from the termios structure and the change occurs immediately */ if((tcsetattr(fd, TCSANOW, &newtio))!=0) { perror("set_port/tcsetattr"); return -1; } return 0; } int uart_open(int channel, uint32_t baudRate, int setting) { /* * Initialize UART for serial communications */ char tty_name[16] = {0x00}; int ret; char parity; if(channel > (UART_MAX_FD - 1) || channel < 0) { return -1; } if (am335x_uarts_fd[channel] < 0) { am335x_uarts_init(channel); memset(tty_name,0,sizeof(tty_name)); sprintf(tty_name, "/dev/ttyAS%d", channel); //sprintf(tty_name, "/dev/ttyO%d", channel); by ygl 2025.6.13 am335x_uarts_fd[channel] = open(tty_name, O_RDWR, 0); if(am335x_uarts_fd[channel] < 0) { printf("inside open %s failed!\n", tty_name); return am335x_uarts_fd[channel]; } } switch(setting) { case PARITY_EVEN://偶校验 parity = 'E'; break; case PARITY_ODD://奇校验 parity = 'O'; break; case PARITY_NONE://无校验 default: parity = 'N'; break; } ret = set_port(am335x_uarts_fd[channel], baudRate, 8, parity, 1); if(ret < 0) { close(am335x_uarts_fd[channel]); perror("set_port failed"); return -2; } return 0; } void uart_close(int channel) { if(channel > (UART_MAX_FD - 1)) { return; } if(am335x_uarts_fd[channel] >= 0) { close(am335x_uarts_fd[channel]); am335x_uarts_fd[channel] = -1; } } int uart_write(int channel, const char *data, int count) { int ret; if((channel > (UART_MAX_FD - 1)) || (data == NULL)) return -1; if(am335x_uarts_fd[channel] < 0) return -2; ret = write(am335x_uarts_fd[channel], data, count); return ret; } void uart_puts (int channel, char *ch) { int write_len; if(ch == NULL) return; write_len = strlen(ch); uart_write(channel, (const char *)ch, write_len); } int uart_read(int channel, char *data, int count) { int ret; if((channel > (UART_MAX_FD - 1)) || (data == NULL)) return -1; if(am335x_uarts_fd[channel] < 0) return -2; ret = read(am335x_uarts_fd[channel], data, count); return ret; } //noted by sunxi: 这个是read的select. int uart_select(int channel) { int ret; struct timeval tv; fd_set rset; tv.tv_sec = 0; tv.tv_usec = 10000; if(channel > (UART_MAX_FD - 1)) return -1; if(am335x_uarts_fd[channel] < 0) return -2; FD_ZERO(&rset); FD_SET(am335x_uarts_fd[channel], &rset); ret = select(am335x_uarts_fd[channel]+1, &rset, NULL, NULL, &tv); return ret; } /********************************************************************/ /* * Wait for a character to be received on the specified UART * * Return Values: * the received character */ char uart_getchar (int channel) { return 0; } int uart_getchar2 (int channel,char *ch) { int ret = uart_read(channel, ch, 1); return ret; } /********************************************************************/ /* * Wait for space in the UART Tx FIFO and then send a character */ void uart_putchar (int channel, char ch) { } void uart_putchar2 (int channel, char ch) { uart_write(channel, (const char *)&ch, 1); } int uart_init(void) { int i, ret; for(i = 0; i < CFG_UART_NUM_MAX; i++) { if((UART_CHANNEL[i]==g_con_uart_index) || (UART_CHANNEL[i]==CFG_UART_HMI)) { continue; } ret = uart_open(i,115200,PARITY_NONE); if (ret < 0) { printf("%s: outside uart %d open failed!\n", __FUNCTION__, i); } else { printf("%s: outside uart %d open success!\n", __FUNCTION__, i); } } return 0; } void uart_exit(void) { int i; printf("uart_exit\n");//sunxi for test for(i = 0; i < CFG_UART_NUM_MAX; i++) { if((UART_CHANNEL[i]==g_con_uart_index) || (UART_CHANNEL[i]==CFG_UART_HMI)) { continue; } uart_close(i); } } int uart_test(void) { char tmp[] = "hello sunxi!"; // u8 c; int ret; static unsigned char buf[256]; static int ret_cnt =0; int i; uart_open(1,9600,PARITY_EVEN); uart_write(1, (const char *)&tmp, strlen(tmp)); for(i = 0; i < 500; i++) { ret = uart_select(1); //有数据可读 if(ret > 0) { printf("\nch_%d have select.",1); //读取数据 memset(buf,0,sizeof(buf)); ret = uart_read(1, buf, sizeof(buf)); if(ret != -1) { //测试代码 printf("\nch_%d RECV num=%d:",1,ret); for(i = 0; i < ret; i++) { printf("%02x ", (unsigned char)buf[i]); } printf("\n"); if(++ret_cnt >= 3) { ret_cnt = 0; uart_write(1, buf, ret); } } } } return 0; }