RK3588使能UART串口设备,并生成/dev/ttySx设备节点,GPIO控制

1、如何在rk3588使能uart设备,并生成/dev/ttySx设备节点

1.1 dts中添加对应的节点

1.1.1 在Y:\rk3588_android\kernel-5.10\arch\arm64\boot\dts\rockchip\rk3588s.dtsi找到串口3肯串口9的名称

    uart3: serial@feb60000 {
        compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
        reg = <0x0 0xfeb60000 0x0 0x100>;
        interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
        clock-names = "baudclk", "apb_pclk";
        reg-shift = <2>;
        reg-io-width = <4>;
        dmas = <&dmac0 12>, <&dmac0 13>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart3m1_xfer>;
        status = "disabled";
    };
    uart9: serial@febc0000 {
        compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
        reg = <0x0 0xfebc0000 0x0 0x100>;
        interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&cru SCLK_UART9>, <&cru PCLK_UART9>;
        clock-names = "baudclk", "apb_pclk";
        reg-shift = <2>;
        reg-io-width = <4>;
        dmas = <&dmac2 11>, <&dmac2 12>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart9m1_xfer>;
        status = "disabled";
    };

由此可知名称为uart3、uart9.

1.1.2 在Y:\rk3588_android\kernel-5.10\arch\arm64\boot\dts\rockchip\rk3588s-pinctrl.dtsi查找RK_PA6、RK_PA5对应哪个节点,可知对应uart3m2_xfer,所以下面pinctrl的节点应该写uart3m2_xfer。uart9类似

        /omit-if-no-ref/
        uart3m2_xfer: uart3m2-xfer {
            rockchip,pins =
                /* uart3_rx_m2 */
                <4 RK_PA6 10 &pcfg_pull_up>,
                /* uart3_tx_m2 */
                <4 RK_PA5 10 &pcfg_pull_up>;
        };
        uart9m2_xfer: uart9m2-xfer {
            rockchip,pins =
                /* uart9_rx_m2 */
                <3 RK_PD4 10 &pcfg_pull_up>,
                /* uart9_tx_m2 */
                <3 RK_PD5 10 &pcfg_pull_up>;
        };

1.1.3 在Y:\rk3588_android\kernel-5.10\arch\arm64\boot\dts\rockchip\rk3588-nvr-demo-v10-android.dts重新写uart3、uart9节点,重新定义部分属性:

&uart9 {
    pinctrl-names = "default";
    pinctrl-0 = <&uart9m2_xfer>;
    status = "okay";
};
​
&uart3 {
    pinctrl-names = "default";
    pinctrl-0 = <&uart3m2_xfer>;
    status = "okay";
};

1.2 rk3588 引脚标号怎么计算
//GPIO0_B7 --> 0*32 + (B-A)*8 + 7 = 15
//GPIO0_C6 --> 0*32 + (C-A)*8 + 6 = 22
//GPIO0_C5 --> 0*32 + (C-A)*8 + 5 = 21 
//GPIO0_C4 --> 0*32 + (C-A)*8 + 4 = 20

2 、串口3和串口9以及GPIO控制代码

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <stdlib.h>
​
int gpio_export(int gpioNum)
{
    int fd = -1;
    char buf[4] = {0,};
​
    if(gpioNum == -1) {
        printf("gpio=-1\n");
        return -1;
    }
​
    sprintf(buf, "%d", gpioNum);
    fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd < 0) {
        printf("fail to export gpio[%d]\n", gpioNum);
        return -1;
    }
​
    write(fd, buf, sizeof(buf));
    close(fd);
    printf("export gpio[%d] ok\n", gpioNum);
    return 0;
}
​
int gpio_unexport(int gpioNum)
{
    int fd = -1;
    char buf[4] = {0,};
​
    if(gpioNum == -1)
        return -1;
​
    sprintf(buf, "%d", gpioNum);
    fd = open("/sys/class/gpio/unexport", O_WRONLY);
    if (fd < 0) {
        printf("no export gpio[%d]\n", gpioNum);
        return -1;
    }
​
    write(fd, buf, sizeof(buf));
    close(fd);
    return 0;
}
​
int gpio_set_direction(int gpioNum, const char* direct)  //direct: "in", "out"
{
    int fd = -1;
    char path[48] = {0,};
​
    if(gpioNum == -1)
        return -1;
​
    sprintf(path, "/sys/class/gpio/gpio%d/direction", gpioNum);
    fd = open(path, O_WRONLY);
    if (fd < 0) {
        printf("fail direction[%s] gpio[%d]\n", direct, gpioNum);
        return -1;
    }
​
    write(fd, direct, sizeof(direct));
    close(fd);
    return 0;
}
​
int gpio_get_value(int gpioNum)
{
    int gpio_fd = -1;
    char path[48] = {0,};
    char gpio_value = 0;
    
    if(gpioNum == -1)
        return -1;
    
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", gpioNum);
    
    gpio_fd = open(path, O_RDONLY);
    if (gpio_fd < 0) {
        perror("Failed to open GPIO sysfs file");
        return -1;
    }
​
    if (read(gpio_fd, &gpio_value, sizeof(gpio_value)) < 0) {
        perror("Failed to read GPIO value");
        close(gpio_fd);
        return -1;
    }
    
    close(gpio_fd);
​
    return atoi(&gpio_value);
}
​
int gpio_set_value(int gpioNum, int value)
{
    int fd = -1;
    char buf[4] = {0,};
    char path[48] = {0,};
​
    if(gpioNum == -1)
        return -1;
    
    sprintf(buf, "%d", value);
    sprintf(path, "/sys/class/gpio/gpio%d/value", gpioNum);
​
    fd = open(path, O_WRONLY);
    if (fd < 0) {
        printf( "fail to open gpio[%d]\n", gpioNum);
        return -1;
    }
​
    write(fd, buf, 4);
    close(fd);
    return 0;
}
​
int uart_open_dev(const char *dev_name)
{
    int fd = -1;
    if (!strcmp(dev_name, "RS232")) {
        fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY);
        if (fd == -1) {
            perror("Failed to open the serial port");
            return -1;
        }
    } else if (!strcmp(dev_name, "RS485")) {
        fd = open("/dev/ttyS9", O_RDWR | O_NOCTTY);
        if (fd == -1) {
            perror("Failed to open the serial port");
            return -1;
        }
    }
    return fd;
}
​
int uart_send_data(int fd, char *data)
{
   ssize_t bytesWritten = write(fd, data, strlen(data));
   if (bytesWritten == -1) {
       perror("Failed to write to serial port");
       return -1;
   }
   return 0;
}
​
int uart_read_data(int fd, char *data)
{
    ssize_t bytesRead = 0;
    bytesRead = read(fd, data, sizeof(data));
    return bytesRead;
}
​
int uart_set_baudrate(int fd, int baudrate)
{
    struct termios options;
    tcgetattr(fd, &options);
    
    // 设置串口波特率
    cfsetispeed(&options, baudrate);
    cfsetospeed(&options, baudrate);
    
    // 8个数据位,无奇偶校验,一个停止位
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    
    // 使能接收和本地模式
    options.c_cflag |= (CLOCAL | CREAD);
    
    // 设置为原始模式
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_iflag &= ~(IXON | IXOFF | IXANY);
    options.c_oflag &= ~OPOST;
    
    tcsetattr(fd, TCSANOW, &options);
    
    return 0;
}
​
void uart_close_dev(int fd)
{
    close(fd);
}
​
​
#if 1
//GPIO0_B7 --> 0*32 + (B-A)*8 + 7 = 15
//GPIO0_C6 --> 0*32 + (C-A)*8 + 6 = 22
//GPIO0_C5 --> 0*32 + (C-A)*8 + 5 = 21 
//GPIO0_C4 --> 0*32 + (C-A)*8 + 4 = 20
​
#define GPIO0_C6    22
#define GPIO0_C5    21
#define GPIO0_C4    20  
void gpio_init(void)
{
    gpio_export(GPIO0_C6);
    gpio_export(GPIO0_C5);
    gpio_export(GPIO0_C4);
    
    gpio_set_direction(GPIO0_C6, "out");  //设置为输出
    gpio_set_direction(GPIO0_C5, "out");  //设置为输出
    gpio_set_direction(GPIO0_C4, "in");   //设置为输入
    
    gpio_set_value(GPIO0_C6, 1);//输出高电平
    gpio_set_value(GPIO0_C5, 0);//输出低电平
}
​
void gpio_exit(void)
{
    gpio_unexport(GPIO0_C6);
    gpio_unexport(GPIO0_C5);
    gpio_unexport(GPIO0_C4);
}
​
int main(int argc, char *argv[]) 
{
    printf("argc = %d, argv[1] = %s\n", argc, argv[1]);
    if (!strcmp(argv[1], "RS485") || !strcmp(argv[1], "RS232")) {
        int fd = uart_open_dev(argv[1]);
        uart_set_baudrate(fd, B115200);
        
        char buffer[256];
        char sendData[256] = "Hello, serial port!\n";
        ssize_t bytesRead;
        
        while (1) {
            bytesRead = uart_read_data(fd, buffer);
            
            if (bytesRead > 0) {
                printf("Received %zd bytes: %.*s\n", bytesRead, (int)bytesRead, buffer);
                uart_send_data(fd, sendData);
            }
        }
        
        uart_close_dev(fd);
    } else {
        gpio_init();
        while (1) {
            if (gpio_get_value(GPIO0_C4)) {
                printf("GPIO0_C4 is high level\n");
                gpio_set_value(GPIO0_C6, 1);//输出高电平
                gpio_set_value(GPIO0_C5, 1);//输出高电平
            } else {
                printf("GPIO0_C4 is low level\n");
                gpio_set_value(GPIO0_C6, 0);//输出低电平
                gpio_set_value(GPIO0_C5, 0);//输出低电平
            }
            usleep(200 * 1000);
        }
        gpio_exit();
    }
    return 0;
}
#endif

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值