0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RK3576内核485控制引脚修改解析

jf_44130326 来源:Linux1024 2026-02-01 16:53 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、先明确核心目标:修改要解决什么问题?

RS-485是半双工通信,需要1方向控制GPIO”(高电平=发送,低电平=接收)。传统方案中,应用层必须手动:

1.发送前设置GPIO高电平切发送模式;

2.发送完成后等数据发完再设GPIO低电平切接收模式;

若时序错(如没等数据发完就切接收),必然丢包。

修改核心是:让内核在发送数据的关键节点自动控制这个GPIO,应用层只需要调用write()发数据,无需管方向切换。

wKgZO2kancKAJVkmAAAh6iVKS-k162.png

二、逐文件拆解修改:改了什么?为什么这么改?

1.设备树修改(rk3576-evb1.dtsi):给UART绑定485控制GPIO

+&uart5 {

+ status = "okay";

+ pinctrl-names = "default";

+ 485_ctrl_gpio = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>;

+ pinctrl-0 = <&uart5m0_xfer>;

+};

+

+&uart11 {

+ status = "okay";

+ pinctrl-names = "default";

+ 485_ctrl_gpio = <&gpio3 RK_PD7 GPIO_ACTIVE_HIGH>;

+ pinctrl-0 = <&uart11m0_xfer>;

+};

改了什么?

uart5uart11两个串口,各加1485_ctrl_gpio属性:

uart5绑定gpio3PD6引脚uart11绑定gpio3PD7引脚

GPIO_ACTIVE_HIGH表示:GPIO高电平时,485进入发送模式

启用串口(status = "okay")并指定引脚配置(pinctrl-0 = <&uart5m0_xfer>)。

为什么这么改?

设备树是硬件与驱动的桥梁:需要告诉内核哪个UART对应哪个GPIO”,否则驱动不知道该控制哪个引脚;

后续驱动代码(8250_dw.c)会通过of_get_named_gpio读取这个属性,建立UART485控制GPIO的关联。

2.驱动初始化修改(8250_dw.c):读取GPIO配置并初始化

+#include +#include @@ -570,9 +572,11 @@static int dw8250_probe(struct platform_device *pdev)    struct device *dev = &pdev->dev;    struct dw8250_data *data;    struct resource *regs;+    struct device_node *nd = dev->of_node;    int irq;    int err;    u32 val;+    int gpio_ctrl;@@ -610,6 +614,14 @@static int dw8250_probe(struct platform_device *pdev)    data->data.dma.fn = dw8250_fallback_dma_filter;    data->pdata = device_get_match_data(p->dev);    p->private_data = &data->data;+    gpio_ctrl = of_get_named_gpio(nd, "485_ctrl_gpio", 0);+    if (gpio_ctrl > 0)+    {+        data->flags = 0xabcd;+        data->dir_gpio_pin = gpio_ctrl;+        gpio_direction_output(gpio_ctrl, 0);+        gpio_set_value(gpio_ctrl, 0);+    }

改了什么?

1.新增头文件:gpio.hof_gpio.h是内核操作GPIO的必备接口

2.读取设备树GPIO:通过of_get_named_gpio(nd, "485_ctrl_gpio", 0),从设备树读取你定义的485_ctrl_gpio引脚号;

3.初始化GPIO状态:

若读取到有效GPIOgpio_ctrl > 0),给dw8250_data结构体设标记(data->flags = 0xabcd,用于后续识别这是485串口);

存储GPIO引脚号(data->dir_gpio_pin = gpio_ctrl);

GPIO为输出模式(gpio_direction_output),并初始化为低电平(gpio_set_value(gpio_ctrl, 0)初始是接收模式,避免上电就误发。

为什么这么改?

这是驱动层与硬件建立连接的关键:设备树只是声明,驱动需要通过probe函数读取声明并初始化硬件

初始设为低电平(接收模式)是安全设计:防止设备上电时GPIO随机电平导致485总线被占用,干扰其他设备。

3.数据结构扩展(8250_dwlib.h):存储485控制状态

@@ -50,6 +50,8 @@struct dw8250_data {#endif    unsigned int        skip_autocfg:1;    unsigned int        uart_16550_compatible:1;+    int flags;+    int dir_gpio_pin;};

改了什么?

dw8250_data结构体(RK平台UART驱动的核心数据结构)中,新增两个字段:

flags:标记是否为485串口(用0xabcd作为识别值);

dir_gpio_pin:存储485方向控制GPIO的引脚号。

为什么这么改?

内核驱动的数据结构是状态的载体dw8250_data原本只存UART基础配置,现在要控制485,必须新增字段存储是否是485”控制哪个GPIO”

后续发送数据时(8250_port.c),需要通过这个结构体获取GPIO信息,才能控制方向。

4.发送逻辑修改(8250_port.c):自动切换收发方向

+// #include "8250.h"+#include "8250_dwlib.h"+#include +#include @@ -1833,6 +1835,7 @@void serial8250_tx_chars(struct uart_8250_port *up)    struct uart_port *port = &up->port;    struct circ_buf *xmit = &port->state->xmit;    int count;+    struct dw8250_data* p_data = (struct dw8250_data*)(port->private_data);@@ -1848,6 +1851,14 @@void serial8250_tx_chars(struct uart_8250_port *up)    }    count = up->tx_loadsz;+    if(0xabcd == p_data->flags)+    {+        if (gpio_get_value(p_data->dir_gpio_pin) != 1)+        {+            gpio_set_value(p_data->dir_gpio_pin, 1);+            printk("this uart is 485, set rts gpio %d value 1n", p_data->dir_gpio_pin);+        }    +    }@@ -1884,7 +1895,30 @@void serial8250_tx_chars(struct uart_8250_port *up)    if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))-        __stop_tx(up);+    {+         __stop_tx(up);+        if(0xabcd == p_data->flags)+        {+            unsigned int lsr;+            int loop_count = 200;+            while(loop_count)+            {+                loop_count--;+                lsr=serial_port_in(port,UART_LSR);+                if(((lsr & UART_LSR_TEMT) == UART_LSR_TEMT))+                    break;+                mdelay(1);+            }+            if(loop_count<0)+            {+                printk("timeout wait 485 send %dn",p_data->dir_gpio_pin);+            }+            +            gpio_set_value(p_data->dir_gpio_pin, 0);+            printk("this uart is 485, set rts gpio %d value 0n", p_data->dir_gpio_pin);+                +        }+    }    

改了什么?

这是最核心的自动控制逻辑,分两个阶段:

1.发送前:切到发送模式

先通过port->private_data拿到dw8250_data结构体(之前在probe函数中绑定);

检查flags == 0xabcd(确认是485串口),且GPIO当前不是高电平GPIO为高电平(gpio_set_value(1));

打印日志,提示“485串口已切发送模式

1.发送后:切回接收模式

当发送缓冲区为空(uart_circ_empty(xmit)),先调用__stop_tx停止发送;

然后循环检查UARTLSR寄存器serial_port_in(port,UART_LSR)):

等待UART_LSR_TEMT位(发送移位寄存器空)确保硬件已把最后1个字节发完(避免数据残留);

最多等200msloop_count=200),超时打印错误日志;

最后设GPIO为低电平(gpio_set_value(0)),切回接收模式,打印日志。

为什么这么改?

解决传统应用层控制的时序痛点:应用层无法精确判断硬件是否真的发完数据,而内核能直接读UART寄存器(LSR),确保数据发完再切接收;

200ms超时是容错设计:防止硬件异常时GPIO一直处于发送模式,阻塞总线。

三、修改带来的3个核心优势(纯代码层面总结)

1.应用层彻底解放:无需再写GPIO控制代码(如ioctlGPIO电平、猜延时等),调用write()发数据即可,内核自动搞定方向切换;

2.时序绝对精准:通过读取UART硬件寄存器(LSR_TEMT)判断发送完成,比应用层usleep(靠经验猜延时)可靠100%,不会丢包;

3.硬件适配灵活:若换485控制引脚,只需改设备树(dtsi)的485_ctrl_gpio,驱动和应用层无需动符合硬件与软件解耦的内核设计思想。

四、开发者需注意的2个细节

1.GPIO引脚唯一性uart5GPIO3_PD6uart11GPIO3_PD7,需确保这两个GPIO没被其他硬件(如SPII2C)占用,否则会导致引脚冲突;

2.超时参数调整loop_count=200200ms)是通用值,若485波特率极低(如2400),1个字节发送时间长,可适当增大loop_count,避免超时误判。

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

    关注

    4

    文章

    1474

    浏览量

    43088
  • RS-485
    +关注

    关注

    11

    文章

    751

    浏览量

    86987
  • rk3576
    +关注

    关注

    1

    文章

    292

    浏览量

    1668
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    基于RK3576开发板的PWN使用说明

    RK3576开发板使用PWN教程及Demo
    的头像 发表于 05-07 14:07 2477次阅读
    基于<b class='flag-5'>RK3576</b>开发板的PWN使用说明

    基于RK3576开发板的人脸识别算法

    RK3576开发板展示人脸识别算法例程和API说明
    的头像 发表于 05-07 16:48 2904次阅读
    基于<b class='flag-5'>RK3576</b>开发板的人脸识别算法

    如何移植EtherCAT Igh--基于米尔RK3576开发板

    本文将介绍基于米尔电子MYD-LR3576开发板(米尔基于瑞芯微RK3576开发板)的板端移植EtherCATIgh方案的开发测试。摘自优秀创作者-EPTmachine米尔基于瑞芯微RK3576
    的头像 发表于 09-26 08:04 1w次阅读
    如何移植EtherCAT Igh--基于米尔<b class='flag-5'>RK3576</b>开发板

    米尔RK3576RK3588怎么选?-看这篇就够了

    在中国半导体产业的版图中,瑞芯微作为国内SoC芯片领跑者,凭借其在处理器芯片设计领域的深厚积累和持续创新,推出很多智能应用处理器芯片,在嵌入式系统领域得到大规模的应用。RK3588和RK3576系列
    发表于 12-27 11:44

    【米尔RK3576开发板评测】+项目名称值得购买的米尔RK3576开发板

    米尔依然是核心板加扩展板的模式,我拿到手的开发板,核心板已经通过LGA贴片,焊好了。 开发板做工很好,布线细致工整。 RK3576开发板 采用Rockchip RK3576第二代8nm高性能
    发表于 01-08 22:59

    RK3576 vs RK3588:为何越来越多的开发者转向RK3576

    瑞芯微(Rockchip)最新发布的 RK3576 一经推出,就吸引了大量原本关注 RK3588 的开发者。RK3588 作为旗舰级芯片,性能固然强大,但 RK3576 凭借其超高的能
    发表于 05-30 08:46

    Mpp支持RK3576

    想问下,https://github.com/rockchip-linux/mpp这里面支持RK3576么,看介绍没有提到说支持RK3576 目前是买了个rk3576的机顶盒,搭载了安卓14,想做安卓视频硬解。
    发表于 06-13 15:35

    RK这2款旗舰芯片RK3588 PK RK3576,谁是最优选

    ,了解两者的区别十分重要,以下将从多个方面进行详细对比。一、处理器性能解析(一)CPU 性能1. 核心架构◦ RK3576:采用四核 Cortex - A72 和四核 Cortex - A53 架构
    发表于 07-10 18:24

    【作品合集】米尔RK3576开发板测评

    测试 作者:鲁治驿【米尔RK3576开发板免费体验】测评综合解析 【米尔RK3576开发板免费体验】集成MQ-2烟雾传感器和ADS1263模块实现气体监测 【米尔RK3576开发板免费
    发表于 09-11 10:19

    【作品合集】灵眸科技EASY EAI Orin Nano(RK3576)开发板测评

    【EASY EAI Orin Nano(RK3576)开发板试用体验】01-开箱报告及开发环境准备 【EASY EAI Orin Nano(RK3576)开发板试用体验】02-拓展空间及内核分析
    发表于 09-09 09:59

    新品体验 | RK3576开发板

    前言:RK3576作为瑞芯微第二代8nm高性能AIOT平台,一经推出便获得了极大的关注。广州眺望电子科技有限公司是一家专注于嵌入式处理器模组研发与应用的国家高新技术企业,目前公司已推出的相关型号有
    的头像 发表于 11-01 08:08 3375次阅读
    新品体验 | <b class='flag-5'>RK3576</b>开发板

    RK3576单板发布倒计时:RK3399与RK3576对比

    好多人说RK3576RK3399的升级版,某种程度上也可以这么说,RK3576在强大的多媒体功能的基础上,性能和接口都进行了升级 一、工艺 性能 rk3576采用 Rockchip
    的头像 发表于 12-03 16:59 2746次阅读
    <b class='flag-5'>RK3576</b>单板发布倒计时:<b class='flag-5'>RK</b>3399与<b class='flag-5'>RK3576</b>对比

    RK3588与RK3576区别解析

    以下是RK3576RK3588对比: 电鱼电子SBC-RK3576单板 核心性能:RK3576为四核A72@2.2GHz + 四核A53@1.8GHz + M0协处理器,算力 58K
    的头像 发表于 12-17 14:03 4349次阅读
    <b class='flag-5'>RK</b>3588与<b class='flag-5'>RK3576</b>区别<b class='flag-5'>解析</b>

    瑞芯微RK3576RK3576S有什么区别,性能参数配置与型号差异解析

    瑞芯微第二代8nm高性能AIOT平台RK3576家族再添新成员-RK3576S,先说结论:相较主型号的RK3576/RK3576J,性能略有缩减,而功耗有所降低。主要应用于商显终端、智
    的头像 发表于 08-14 23:57 2672次阅读
    瑞芯微<b class='flag-5'>RK3576</b>与<b class='flag-5'>RK3576</b>S有什么区别,性能参数配置与型号差异<b class='flag-5'>解析</b>

    迅为如何在RK3576上部署YOLOv5;基于RK3576构建智能门禁系统

    迅为如何在RK3576开发板上部署YOLOv5;基于RK3576构建智能门禁系统
    的头像 发表于 11-25 14:06 1950次阅读
    迅为如何在<b class='flag-5'>RK3576</b>上部署YOLOv5;基于<b class='flag-5'>RK3576</b>构建智能门禁系统