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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/582086.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人脸识别系统架构

目录 1. 系统架构 1.1 采集子系统 1.2 解析子系统 1.3 存储子系统 1.4 比对子系统 1.5 决策子系统 1.6 管理子系统 1.7 应用开放接口 2. 业务流程 2.1 人脸注册 2.2 人脸验证 2.2.1 作用 2.2.2 特点 2.2.3 应用场景 2.3 人脸辨识 2.3.1 作用 2.3.2 特点 2.3.3…

学习STM32第二十天

低功耗编程 一、修改主频 STM32F4xx系列主频为168MHz&#xff0c;当板载8MHz晶振时&#xff0c;系统时钟HCLK满足公式 H C L K H S E P L L N P L L M P L L P HCLK \frac{HSE \times PLLN}{PLLM \times PLLP} HCLKPLLMPLLPHSEPLLN​&#xff0c;在文件stm32f4xx.h中可修…

HTML 学习笔记

html 超文本标记语言&#xff08;英语&#xff1a;HyperText Markup Language&#xff0c;简称&#xff1a;HTML&#xff09;是一种用于创建网页的标准标记语言。 1.HTML文档的后缀名 (1) .html (2) .htm 这里更推荐使用 ".html "&#xff0c;命名应该遵从含义清…

FPGA 以太网概念简单学习

1 MAC和PHY 从硬件的角度来说&#xff0c;以太网接口电路主要由 MAC &#xff08; Media Access Control &#xff09;控制器和物理层接口 PHY&#xff08;Physical Layer &#xff0c; PHY &#xff09;两大部分构成。 MAC 指媒体访问控制子层协议&#xff0c;它和 PHY 接…

SpringMVC进阶(自定义拦截器以及异常处理)

文章目录 1.自定义拦截器1.基本介绍1.说明2.自定义拦截器的三个方法3.流程图 2.快速入门1.Myinterceptor01.java2.FurnHandler.java3.springDispatcherServlet-servlet.xml配置拦截器4.单元测试 3.拦截特定路径1.拦截指定路径2.通配符配置路径 4.细节说明5.多个拦截器1.执行流程…

刷代码随想录有感(49):找树左下角的值

题干&#xff1a; 用层序遍历方便些&#xff0c;因为只需要把res不断替换成每一层第一个节点值即可&#xff0c;代码如下&#xff1a; class Solution { public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*>que;if(root ! NULL)que.push(root);int res …

逆向案例三十——webpack登录某游戏

网址&#xff1a;aHR0cHM6Ly93d3cuZ205OS5jb20v 步骤&#xff1a; 进行抓包分析&#xff0c;找到登录接口&#xff0c;发现密码有加密 跟栈分析&#xff0c;从第三个栈进入&#xff0c;打上断点&#xff0c;再次点击登录 明显找到password,它由o赋值&#xff0c;o由a.encode(…

【哈希】Leetcode 面试题 01.02. 判定是否互为字符重排

题目讲解 面试题 01.02. 判定是否互为字符重排 算法讲解 直观的想法&#xff1a;我们找到一个字符串的全排列&#xff0c;然后对比当前的排列是否等于另一个字符串。如果两个字符串如果互为排列&#xff0c;所以我们知道两个字符串对应的字符出现的个数相同&#xff0c;那么…

在config.json文件中配置出来new mars3d.graphic.PolylineCombine({大量线合并渲染类型的geojson图层

在config.json文件中配置出来new mars3d.graphic.PolylineCombine({大量线合并渲染类型的geojson图层 问题场景&#xff1a; 1.浏览官网示例的时候图层看到大量线数据合并渲染的示例 2.矢量数据较大量级的时候&#xff0c;这种时候怎么在config.json文件中尝试配置呢&#x…

高并发内存池: 介绍

一.功能介绍 功能: 用于实现高效的多线程内存管理(替代系统的内存分配相关的函数(malloc, free)) 性能的提升: 池化技术, 锁竞争的减小处理内存碎片: 内碎片, 外碎片 池化技术: 概念:预先向系统申请过量的资源, 自己管理.->提高性能(每次申请资源都有较大的开销, 提前申…

数字文旅重塑旅游发展新生态:以数字化转型为契机,推动旅游产业的创新发展,提升旅游服务的智能化、网络化和个性化水平

目录 一、引言 二、数字化转型推动旅游产业创新发展 1、数字化转型提升旅游产业效率 2、数字化转型拓展旅游产业边界 3、数字化转型促进旅游产业可持续发展 三、提升旅游服务智能化、网络化和个性化水平 1、智能化提升旅游服务体验 2、网络化拓宽旅游服务渠道 3、个性…

OpenHarmony实战开发-多层级手势事件

多层级手势事件指父子组件嵌套时&#xff0c;父子组件均绑定了手势或事件。在该场景下&#xff0c;手势或者事件的响应受到多个因素的影响&#xff0c;相互之间发生传递和竞争&#xff0c;容易出现预期外的响应。 本章主要介绍了多层级手势事件的默认响应顺序&#xff0c;以及…

【大学生电子竞赛题目分析】——2023年H题《信号分离装置》

今年的大赛已临近落幕&#xff0c;笔者打算陆续对几个熟悉领域的题目作一番分析与讨论&#xff0c;今天首先分析H题。 网上有一些关于H题的分析&#xff0c;许多都是针对盲信号分析的。然而本题具有明确的信号频率范围&#xff0c;明确的信号可能频率&#xff0c;明确的信号波…

全栈从0到1 3D旅游地图标记和轨迹生成

功能演示 演示视频 体验地址 Vercel App 开发技术栈&#xff1a; NextJs&#xff08;前端框架&#xff09;React&#xff08;前端框架&#xff09;TailwindCSS &#xff08;CSS样式&#xff09;echart echart gl &#xff08;地图生成&#xff09;shadui&#xff08;UI组件…

HTML5本地存储账号密码

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>HTML5本地存储账号密码</title> </head…

[论文笔记]SEARCHING FOR ACTIVATION FUNCTIONS

引言 今天带来另一篇激活函数论文SEARCHING FOR ACTIVATION FUNCTIONS的笔记。 作者利用自动搜索技术来发现新的激活函数。通过结合详尽的搜索和基于强化学习的搜索&#xff0c;通过实验发现最佳的激活函数 f ( x ) x ⋅ sigmoid ( β x ) f(x) x \cdot \text{sigmoid}(βx…

Android 学习 鸿蒙HarmonyOS 4.0 第二天(项目结构认识)

项目结构认识 和 了解&#xff1a; 工程目录下的结构如下&#xff1a; 首先能看到有两个.开头的文件&#xff0c;分别是.hvigor 和 .idea。这两个文件夹都是与构建有关系的&#xff0c; 如果你开发过安卓app&#xff0c;构建完会生成一个apk安装包&#xff0c;鸿蒙则是生成hap…

android 分区存储(沙盒存储)适配总结

目录 一、分区存储概念 1.外部存储分类 2.分区存储如何影响文件访问 二、分区适配方案 1. 应用分区存储的文件访问规定 (1).应用专属目录--私有目录 (2).共享目录文件--公有目录 2.MediaStore API介绍 3.Storage Access Framework介绍 三、所有文件访问权限 四、总结…

急急急!微信朋友圈删除了怎么恢复?

微信朋友圈是我们与朋友分享生活点滴的重要平台&#xff0c;但有时候微信出现异常&#xff0c;导致我们编辑好的朋友圈被删除了&#xff0c;这时候该怎么办呢&#xff1f; 幸运的是&#xff0c;微信提供了一种简单的方式来恢复已删除的朋友圈内容。微信朋友圈删除了怎么恢复&a…

react 学习笔记二:ref、状态、继承

基础知识 1、ref 创建变量时&#xff0c;需要运用到username React.createRef()&#xff0c;并将其绑定到对应的节点。在使用时需要获取当前的节点&#xff1b; 注意&#xff1a;vue直接使用里面的值&#xff0c;不需要再用this。 2、状态 组件描述某种显示情况的数据&#…
最新文章