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

2024-04-29 05:20

本文主要是介绍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

这篇关于RK3588使能UART串口设备,并生成/dev/ttySx设备节点,GPIO控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/945205

相关文章

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

day-51 合并零之间的节点

思路 直接遍历链表即可,遇到val=0跳过,val非零则加在一起,最后返回即可 解题过程 返回链表可以有头结点,方便插入,返回head.next Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}*

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言