瑞萨RZ/G2L串口SCI的使用(下)

描述

RZ/G2L支持的最大波特率

寄存器

RZ/G2L的SCIFA异步通讯模式下支持的最高波特率可以达到12.5Mbps,如果异步基础时钟选择16倍波特率,同时关闭波特率发生器的倍频模式下依然可以达到3.125Mbps。如果异步基础时钟选择8倍波特率或者波特率发生器开启倍频模式,最大波特率可以达到6.25Mbps。

在上集中我们有讲过RZ/G2L在Linux下的使用遵循POSIX标准。只要POSIX支持的波特率,RZ/G2L都可以支持,并且支持各种波特率下的误差修正,需要开启MDDRS寄存器。

Linux下串口的波特率

Linux下termbits.h支持的波特率如下

左右滑动查看完整内容

 

/* c_cflag bit meaning */
#define CBAUD   0000377
#define  B0 0000000     /* hang up */
#define  B50    0000001
#define  B75    0000002
#define  B110   0000003
#define  B134   0000004
#define  B150   0000005
#define  B200   0000006
#define  B300   0000007
#define  B600   0000010
#define  B1200  0000011
#define  B1800  0000012
#define  B2400  0000013
#define  B4800  0000014
#define  B9600  0000015
#define  B19200 0000016
#define  B38400 0000017
#define  EXTA   B19200
#define  EXTB   B38400
#define  CBAUDEX 0000000
#define  B57600   00020
#define  B115200  00021
#define  B230400  00022
#define  B460800  00023
#define  B500000  00024
#define  B576000  00025
#define  B921600  00026
#define B1000000  00027
#define B1152000  00030
#define B1500000  00031
#define B2000000  00032
#define B2500000  00033
#define B3000000  00034
#define B3500000  00035
#define B4000000  00036

 

也就是标准的Linux支持的最大波特率是4Mbps,但并不是4Mbps以下任意一个波特率都可以支持,只有30种选择。

那如果在特殊的应用场景中,需要这30种波特率以外的选择,是否能够实现呢?答案是肯定的,但是比较复杂。

这里我们提供一种Linux下实现非POSIX标准串口波特率的方法给大家参考。

Linux串口非标波特率的实现

涉及两部分他,包括内核和应用层

首先第一步:我们需要修改内核中的串口驱动,确保串口驱动能够支持需要添加的非标波特率。上集我们已经分享过RZ/G2L的串口驱动代码路径是drivers/tty/serial/sh-sci.c,目前通过开启MDDRS,RZ/G2L几乎可以支持12.5Mbps以下的任意串口波特率。

这里我们以前面提到的3.125Mbps/6.25Mbps/12.5Mbps为例,github上下载的sh-sci.c驱动默认并没有开启波特率发生器的倍频模式,异步基础时钟选择的是默认的16倍波特率。所以最大的波特率可以支持到3.125Mbps,如果需要支持6.25Mbps或者更高的12.5Mbps,需要开启波特率发生器的倍频模式,并且允许异步基础时钟选择8倍波特率。

左右滑动查看完整内容

 

+       #if ABCS0_BGDM_EN
+           if(baud > 6250000){
+               //SEMR_BGDM:Baud rate generator double-speed mode Select:
+               //SEMR_ABCS0:Asynchronous Base Clock Select:
+               serial_port_out(port, SEMR,
+                       serial_port_in(port, SEMR) | (SEMR_ABCS0 | SEMR_BGDM));
+               freq *= 2;
+               prediv /= 2;
+           }else if(baud > 3125000){
+               //SEMR_BGDM:Baud rate generator double-speed mode Select:
+               serial_port_out(port, SEMR,
+                   serial_port_in(port, SEMR) | SEMR_BGDM);
+               freq *= 2;
+           }
+       #endif

 

这部分代码与RZ/G2L的平台相关,需要根据RZ/G2L的规格书配置对应的寄存器。

第二步:为了允许应用层配置我们添加的这三种波特率,需要修改drivers/tty/tty_baudrate.c和include/uapi/asm-generic/termbits.h,这两个文件与平台无关。想要在内核中添加系统默认的30种波特率以外的波特率都需要修改这两个文件。这两个文件的修改内容可以参考以下:

左右滑动查看完整内容

 

diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c
index bdfaee2c1331..75d287893d11 100644
--- a/drivers/tty/tty_baudrate.c
+++ b/drivers/tty/tty_baudrate.c
@@ -24,7 +24,7 @@ static const speed_t baud_table[] = {
    1000000, 1152000, 1500000, 2000000
 #else
    500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
-   2500000, 3000000, 3500000, 4000000
+   2500000, 3000000, 3500000, 4000000, 3125000, 6250000, 12500000
 #endif
 };
 
@@ -36,7 +36,7 @@ static const tcflag_t baud_bits[] = {
    B1000000, B1152000, B1500000, B2000000
 #else
    B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000,
-   B2500000, B3000000, B3500000, B4000000
+   B2500000, B3000000, B3500000, B4000000, B3125000, B6250000, B12500000
 #endif
 };


 @@ -73,6 +73,14 @@ speed_t tty_termios_baud_rate(struct ktermios *termios)
        else
            cbaud += 15;
    }
+   if (cbaud & CBAUDEX2) {
+       cbaud &= ~CBAUDEX2;
+
+       if (cbaud < 1 || cbaud + 30 > n_baud_table)
+           termios->c_cflag &= ~CBAUDEX2;
+       else
+           cbaud += 30;
+   }
    return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
 }
 EXPORT_SYMBOL(tty_termios_baud_rate);
diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h
index 7db62a33ee52..1353300b6934 100644
--- a/include/uapi/asm-generic/termbits.h
+++ b/include/uapi/asm-generic/termbits.h
@@ -110,7 +110,7 @@ struct ktermios {
 #define   FF1  0100000
 
 /* c_cflag bit meaning */
-#define CBAUD  0010017
+#define CBAUD  0030017
 #define  B0    0000000     /* hang up */
 #define  B50   0000001
 #define  B75   0000002


@@ -158,7 +158,9 @@ struct ktermios {
 #define  B3500000 0010016
 #define  B4000000 0010017
+#define CBAUDEX2 0020000
+#define  B3125000  0020001
+#define  B6250000  0020002
+#define  B12500000 0020003
 #define CIBAUD   002003600000  /* input baud rate */
 #define CMSPAR   010000000000  /* mark or space (stick) parity */
 #define CRTSCTS      020000000000  /* flow control */

 

经过上面两步修改,内核已支持我们需要添加的3种非POSIX标准的串口波特率。

接下来演示应用层如何使用我们添加的这三种串口波特率。

左右滑动查看完整内容

 

#define B3125000  0020001
#define B6250000  0020002
#define B12500000 0020003
**
** 串口配置
** 参数 cfg 指向一个 uart_cfg_t 结构体对象
**/
static int uart_cfg(const uart_cfg_t *cfg)
{
    struct termios new_cfg = {0}; //将 new_cfg 对象清零
    speed_t speed;
    
    /* 设置为原始模式 */
    cfmakeraw(&new_cfg);
    
    /* 使能接收 */
    new_cfg.c_cflag |= CREAD| CLOCAL;
    
    /* 设置波特率 */
  speed = B3125000; // B3125000  B6250000  B12500000
new_cfg.c_cflag |= speed;


    /* 串口的其他属性配置参考标准的POSIX */


    /* 写入配置、使配置生效 */
    if (0 > tcsetattr(fd, TCSANOW, &new_cfg)) {
        fprintf(stderr, "tcsetattr error: %s
", strerror(errno));
        return -1;
    }

 

经过以上修改,我们就可以在linux下使用文章开头提到的RZ/G2L的最大波特率12.5Mbps进行串口通讯。

需要注意的是,我们给RZ/G2L添加的这三个波特率尤其是6.25Mbps或者12.5Mbps远超标准linux下支持的最大波特率4Mbps,所以,通过PC端的Ubuntu是无法使用这三种波特率与RZ/G2L的SMARC EVK板进行通讯测试的,如果要使用我们上面添加的这三种波特率,只能在两个SMARC EVK板上进行。

所以,除以上添加的这三种波特率外,如果要添加POSIX标准支持的30种以外的其他波特率,都可以参考这个方法来实现。

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分