Fuart & UART流控使用参考


1. Fuart流控流程


1.1. HW连接


1.2. 参数说明

  • RTS

    Require To Send,发送请求为输出信号,用于指示本设备准备好可接收数据,低电平有效,低电平说明本设备可以接收数据。

  • CTS

    Clear To Send,允许发送输入信号,用于判断是否可以向对方发送数据,低电平有效,低电平说明本设备可以向对方发送数据。


1.3. 流控制方式

如果本端处理数据流(接收对方数据),将RTS置为低电平; 对方设备CTS脚是低电平,则可以发送数据。

如果本端不处理数据流(不接收对方数据),将RTS置为高电平; 对方设备CTS脚是高电平,则停止发送数据, 等待CTS的脚位变化。


1.4. FUART 测试方式

1.4.1. kernel验证RTS CTS 流程

  • modify infinity6e.dtsi

  • modify infinity6e-padmux.dtsi add

1.4.2. 编译kernel

将kernel烧写到flash

重启

进入shell后(请先验证该组的四个pin是否可以单独控制拉高/低电平)

  1. / #    ls /dev/ttyS2

  2. / #    stty -F /dev/ttyS2 ispeed 115200 ospeed 115200 cs8

  3. / #    cd mnt/

  4. /mnt #   ./enable_rtscts (应用程序,用来开启流控,请自行拷贝代码编译)

  5. / #     /customer/riu_r 103c 6e(查看是否设置为mode1)

    BANK:0x103C 16bit-offset 0x6E

    0x0010

  6. / #    /customer/riu_r 1102 8(查看rts cts enable)

    BANK:0x1102 16bit-offset 0x08

    0x0022

  7. 此时已经enable RTS CTS,使用LA测PAD_FUART_CTS,PAD_FUART_RTS

    PAD_FUART_CTS = 1

    PAD_FUART_RTS = 0(正确值)

  8. 将PAD_FUART_RX,PAD_FUART_TX连接到PC

    / #  echo aaaaaaaa > /dev/ttyS2

    此时PC上的串口工具没有接收到任何数据

    将PAD_FUART_CTS接地,PC串口工具log如下:

    CTS验证通过

  9. / #     cat dev/ttyS2 &

  10. / #     /customer/riu_r 1102 2

    BANK:0x1102 16bit-offset 0x02

    0x0005

  11. / #    /customer/riu_w 1102 2 0(关闭fuart接收中断,tx接收到数据后不会将数据读出,fifo full后,RTS被置1

    BANK:0x1102 16bit-offset 0x02

    0x0000

  12. 使用串口工具send 30byte data to fuart

  13. 使用LA测PAD_FUART_RTS

    PAD_FUART_RTS = 1(正确值)

  14. / #      /customer/riu_w 1102 2 5(打开fuart接收中断,fifo的数据被读出后,RTS被置0

    BANK:0x1102 16bit-offset 0x02

    0x0005

  15. 使用LA测PAD_FUART_RTS

    PAD_FUART_RTS = 0(正确值)

    PC串口工具log如下:

    RTS验证通过

1.4.3. 代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
int enable_rtscts(int fd)
{
    struct termios options;
    if ( tcgetattr( fd,&options) != 0)
    {
        perror("SetupSerial 1");
        return -1;
    }
    options.c_cflag |= CRTSCTS;
    tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
    if (tcsetattr(fd,TCSANOW,&options) != 0)
    {
        perror("SetupSerial 3");
        return -1;
    }
    return 0;
}

int main(int argc, char **argv)
{
    int fd;
    fd = open("/dev/ttyS2",O_RDWR|O_NOCTTY|O_NDELAY);
    if (fd <= 0){
        printf("Can't Open Serial Port!\n");
        return -1;
        }
    if(enable_rtscts(fd)== -1)
    {
        printf("Set Parity Error\n");
        exit(1);
    }
    printf("enable rts cts\n");
    close(fd);
    return 0;
}

1.5. 注意事项

  1. 确认pin脚配置Fuart

  2. kernel\arch\arm\boot\dts\infinity2m-ssc011a-s01a-padmux-display.dtsi :

    <PAD_FUART_RX PINMUX_FOR_FUART_MODE_1 MDRV_PUSE_FUART_RX>,  
    <PAD_FUART_TX PINMUX_FOR_FUART_MODE_1 MDRV_PUSE_FUART_TX>,  
    <PAD_FUART_CTS PINMUX_FOR_FUART_MODE_1 MDRV_PUSE_FUART_CTS>,  
    <PAD_FUART_RTS PINMUX_FOR_FUART_MODE_1 MDRV_PUSE_FUART_RTS>,
    
  3. kernel\arch\arm\boot\dts\infinity2m-ssc011a-s01a-padmux-display.dtsi :

    fuart: uart2@1F220400 {
        compatible = "sstar,uart";
        reg = <0x1F220400 0x100>, <0x1F220600 0x100>;
        interrupts = <GIC_SPI INT_IRQ_FUART IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI INT_IRQ_URDMA IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&CLK_fuart>;
        dma = <0>;
        sctp_enable = <1>;//rts cts enable is 1
        //pad = <PAD_FUART_RX>;//fuart mode2
        pad = <PAD_FUART_CTS>;//fuart mode 1
        tolerance = <2>;
        status = "ok";
    };
    
  4. 确认软件使能cts/rts,如果没有使能cts/rts功能 ,他们默认值为高电平状态。

  5. 如果要保证ssd20x处于可接受状态,使用命令:cat /dev/ttyS2 &  ,如果没有一直开启ttyS2的设备,那么Fuart的中断状态会自动清除。获取register[101e 2]==0x0000;正常为0x0005。


2. 接RS芯片,半双工通信流程

  1. 连接方法

    RS485属于master-salver模式,同时mater作为发起端,salver应答端。网络中同时只有一台在发送数据,其他设备属于监听状态。

    主要流程如下, 所有行为需要等待master端的通知。

    Host/Master给RS485芯片发送数据时,先把R/D拉高, 发送完毕后,将R/D 拉低,Host/Master进入监听状态,等待slaver应答。

  2. app层使用方法

    struct serial_rs485 rs485conf;
    
    memset(&rs485conf,0,sizeof(rs485conf));
    
    rs485conf.padding[0] = 17;   //用来控制slaver收发的gpio index
    rs485conf.delay_rts_after_send = 2000;  //发送完最后一个字节需要的delay,单位:us
    rs485conf.flags |= SER_RS485_RTS_ON_SEND; //发送前拉高gpio,打开SER_RS485_RTS_AFTER_SEND指的是发送后拉高
    rs485conf.flags |= SER_RS485_ENABLED; // 使能本串口485模式,默认禁用
    ioctl(iHandle, TIOCSRS485, &rs485conf);