liuzhijun2008 发表于 2024-9-20 16:42:24

ARM LINUX 系统(NUC980 )如何支持更高的波特率 比如1M 2M

NUC980 LINUX 4.4 系统下串口最大的波特率是多少?有坛友知道吗 ? 目前我测试只能支持921600 看规格书上是可以支持3M 的 我想问如何在LINUX 系统上使用 2M工3M这种特殊波特率呢查看内核中的tty_ioctl.c 文件中 可以看到是可以更高的
/*
* Routine which returns the baud rate of the tty
*
* Note that the baud_table needs to be kept in sync with the
* include/asm/termbits.h file.
*/
static const speed_t baud_table[] = {
        0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
        9600, 19200, 38400, 57600, 115200, 230400, 460800,
#ifdef __sparc__
        76800, 153600, 307200, 614400, 921600
#else
        500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
        2500000, 3000000, 3500000, 4000000
#endif
};

#ifndef __sparc__
static const tcflag_t baud_bits[] = {
        B0, B50, B75, B110, B134, B150, B200, B300, B600,
        B1200, B1800, B2400, B4800, B9600, B19200, B38400,
        B57600, B115200, B230400, B460800, B500000, B576000,
        B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
        B3000000, B3500000, B4000000
};
#else
static const tcflag_t baud_bits[] = {
        B0, B50, B75, B110, B134, B150, B200, B300, B600,
        B1200, B1800, B2400, B4800, B9600, B19200, B38400,
        B57600, B115200, B230400, B460800, B76800, B153600,
        B307200, B614400, B921600
};
#endif

static int n_baud_table = ARRAY_SIZE(baud_table);

/**
*        tty_termios_baud_rate
*        @termios: termios structure
*
*        Convert termios baud rate data into a speed. This should be called
*        with the termios lock held if this termios is a terminal termios
*        structure. May change the termios data. Device drivers can call this
*        function but should use ->c_speed directly as they are updated.
*
*        Locking: none
*/

三年模拟 发表于 2024-9-21 16:17:20

980串口这么高波特率,你得开启dma不然接收可能丢包

thepresent 发表于 2024-9-21 21:40:22

设定波特率时,在nuc980的串口驱动中,uart_get_baud_rate判断设定的波特率要小于port->uartclk / 11:
nuc980serial_set_termios
-->baud = uart_get_baud_rate(port, termios, old, port->uartclk / 0xffff, port->uartclk / 11);

而port->uartclk 是在nuc980serial_init_ports中直接写死了:
up->port.uartclk = 12000000;
这样看的话,串口波特率不能超过1090000。
如果要超过这个波特率的话,可以试试更改串口的时钟分频设置,然后配合修改串口驱动程序。

liuzhijun2008 发表于 2024-9-23 18:46:38

thepresent 发表于 2024-9-21 21:40
设定波特率时,在nuc980的串口驱动中,uart_get_baud_rate判断设定的波特率要小于port->uartclk / 11:

而 ...
(引用自3楼)

谢谢回复,问了原厂说是最高公支持 921600 波特率。

liuzhijun2008 发表于 2024-9-23 18:47:43

三年模拟 发表于 2024-9-21 16:17
980串口这么高波特率,你得开启dma不然接收可能丢包
(引用自2楼)

LINUX 系统是内核驱动   DMA 写好的吧

三年模拟 发表于 2024-9-23 20:25:14

980的dma需要开启

yyts 发表于 2024-9-23 20:27:37

刚调了T113,1.5M完全没问题,不过这没什么,另一边5,6块钱的ESP32也完全能应付得过来。

liuzhijun2008 发表于 2024-9-23 23:44:20

yyts 发表于 2024-9-23 20:27
刚调了T113,1.5M完全没问题,不过这没什么,另一边5,6块钱的ESP32也完全能应付得过来。 ...
(引用自7楼)

我的项目是要将udp的socket数据转串口。双向转发。串口太慢了。还有一个问题就是,串口收到数据,串口响应要5毫秒。哪怕是10字节也要五毫秒,现在感觉是无解。准备用SPI代替串口来做。不知道有没有坑。有啥好的方案吗?

liuzhijun2008 发表于 2024-9-23 23:45:52

三年模拟 发表于 2024-9-23 20:25
980的dma需要开启
(引用自6楼)

有这方面的资料吗?我第一次用nuc 980之前都没跑Linux系统。之前用裸奔的方式还可以。没遇到什么问题。现在做linux的应用编程的用户态编程效率太低了。

liuzhijun2008 发表于 2024-9-24 13:28:53

// 主处理函数
void *io_thread(void *args)
{
    thread_args* ptr =(thread_args*)args;
    int udp_sockfd = ptr->sockfd;
    int serial_fd = ptr->serfd;
    int i=0;
    int len=0;

    struct timeval timeout;
        timeout.tv_sec = 0;// 设置为0秒
        timeout.tv_usec = 100;//100; // 设置为100微秒

    fcntl(udp_sockfd, F_SETFL, O_NONBLOCK);
        fcntl(serial_fd, F_SETFL, O_NONBLOCK);
   
       
               
        printf("sockaddr_in005 \n");

    fd_set read_fds;
    char udpbuffer;
        char buffer;
       
    struct sockaddr_in client_addr;
    socklen_t addr_len = sizeof(client_addr);
       
        printf("run while006 \n");

    while (1)
        {
      FD_ZERO(&read_fds);
      FD_SET(udp_sockfd, &read_fds);
      FD_SET(serial_fd, &read_fds);
      int max_fd = (udp_sockfd > serial_fd) ? udp_sockfd : serial_fd;


      // 监控文件描述符
      if (select(max_fd + 1, &read_fds, NULL, NULL, &timeout) < 0)
       //if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) < 0)
                {
            perror("select error");
            break;
      }

      // 处理 UDP 数据
      if (FD_ISSET(udp_sockfd, &read_fds))
                {
            ssize_t len = recvfrom(udp_sockfd, udpbuffer, sizeof(udpbuffer), 0, (struct sockaddr *)&client_addr, &addr_len);
            if (len > 0)
                        {
                write(serial_fd, udpbuffer, len);
            }
      }

      // 处理串口数据
       else if (FD_ISSET(serial_fd, &read_fds))
                {
         // ssize_t len = read(serial_fd, buffer, sizeof(buffer));
            ssize_t len = read(serial_fd, buffer, 128);
            if (len > 0)
                        {       
                                sendto(udp_sockfd, buffer, len, 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
            }
      }


    }

    close(serial_fd);
    close(udp_sockfd);
    return NULL;
}

liuzhijun2008 发表于 2024-9-24 13:29:08

三年模拟 发表于 2024-9-23 20:25
980的dma需要开启
(引用自6楼)

现在是串口收到的数据 产生IO 更新到用户空间会延时 3-5MS   如何加快这个速度呢   有偿请教。

yyts 发表于 2024-9-24 13:39:34

liuzhijun2008 发表于 2024-9-23 23:44
我的项目是要将udp的socket数据转串口。双向转发。串口太慢了。还有一个问题就是,串口收到数据,串口响 ...
(引用自8楼)

我的数据包,延时要求没那么高,有个队列缓存起来后面再按顺序收完都可以。

liuzhijun2008 发表于 2024-9-24 14:01:43

yyts 发表于 2024-9-24 13:39
我的数据包,延时要求没那么高,有个队列缓存起来后面再按顺序收完都可以。 ...
(引用自12楼)

我这个要求很高 对响应要求 高不能通过 环形缓冲这样会更慢, 现在主要是网口将数据通过NUC980主机串口发出去之后从机设备在 600US 内就将数据返回给NUC980 LINUX 串口了,但LINUX用户空间收到这一帧数据是 5MS 之后。 希望将这个数据做到 1MS 以内5MS 就太慢了,如果是 5MS不如直接用 115200
页: [1]
查看完整版本: ARM LINUX 系统(NUC980 )如何支持更高的波特率 比如1M 2M