Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
rt_device
rt_device.user_data 分析: 大部分uart驱动都不安全
发布于 2022-01-21 14:17:17 浏览:1258
订阅该版
[tocm] # 背景 最近在N32G457芯片学习使用RT_thread时, 尝试485通讯.于是加载了rs485这个pkg. rt_thread: https://github.com/RT-Thread/rt-thread.git 切换到 4.0.x N32G457驱动: https://github.com/RT-Thread/rt-thread/tree/master/bsp/n32g452xx/Libraries/rt_drivers # 问题 ## 现象 发现串口接收到数据后, 串口中断持续进入. 清除中断标志没有效果. ## 原因排查 一番操作后, 发现串口中断服务函数里取到的uart已经不是注册时给的uart了 ``` int rt_hw_usart_init(void) { struct n32_uart *uart; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; #if defined(BSP_USING_UART1) uart = &uart1; config.baud_rate = BAUD_RATE_115200; serial1.ops = &n32_uart_ops; serial1.config = config; NVIC_Configuration(uart); /* register UART1 device */ rt_hw_serial_register(&serial1, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, uart); #endif /* BSP_USING_UART1 */ ... ------------------------------------------------------------------------ static void uart_isr(struct rt_serial_device *serial) { struct n32_uart *uart = (struct n32_uart *) serial->parent.user_data; RT_ASSERT(uart != RT_NULL); ... ``` rt_hw_serial_register 注册时, 会将serial.parent.user_data赋值为uart. 而 uart_isr 函数里, uart从serial.parent.user_data取出时, 已经变了. ### 为什么会变 原因是 rs485这个包 在rs485.c 的 int rs485_connect(rs485_inst_t * hinst)函数里对serial.parent.user_data重新赋值冲掉了. ``` hinst->serial->user_data = hinst; hinst->serial->rx_indicate = rs485_recv_ind_hook; hinst->status = 1; LOG_D("rs485 connect success."); ``` rs485_connect 函数里把 hinst->serial->user_data = hinst是为了在接收中断回调函数rs485_recv_ind_hook里进行使用. ``` static rt_err_t rs485_recv_ind_hook(rt_device_t dev, rt_size_t size) { rs485_inst_t *hinst = (rs485_inst_t *)(dev->user_data); if (hinst->evt) { rt_event_send(hinst->evt, RS485_EVT_RX_IND); } return(RT_EOK); } ``` ## 问题结论 驱动层与驱动上层都使用了user_data, 导致冲突. ## 解决 ### 1 经过与rs485包的作者沟通 https://github.com/qiyongzhong0/rt-thread-rs485/issues/2 他觉得 user_data是给驱动上层应用预留的,驱动占用是不合理的. ### 2 但是之后查阅了 RT_thead/bsp/下的很多bsp层drivers/drv_uart.c uart注册为seril设备时的情况 int rt_hw_uart_init(void) allwinner_tina, amebaz, amp32, asm9260t, at32, at91sam9g45,...raspberry-pi, 等都是将uart作为user_data的. 而 stm32, 是以NULL传入的. 这样的驱动是少数的. 大部分芯片移植的时候, 都在驱动层使用了user_data.这就导致驱动上传应用会因为user_data问题,导致驱动无法兼容. ### 3 方案探讨 目前的rt_device设计 ``` /** * Device structure */ struct rt_device { struct rt_object parent; /**< inherit from rt_object */ ... void *user_data; /**< device private data */ }; ``` 不加区分的user_data导致了驱动与应用不兼容. #### 方案1: user_data 留给驱动 ``` rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, const char *name, rt_uint32_t flag, void *data) ``` 注册函数里提供了data.入参. 且大部分驱动都把芯片资源作为data传给了驱动. #### 方案2: user_data 留给驱动上层 #### 方案3: rt_device设计两个指针呢, 一个留给驱动, 一个留给驱动上层的应用. ``` /** * Device structure */ struct rt_device { struct rt_object parent; /**< inherit from rt_object */ ... void *user_data; /**< 留给驱动 */ void *device_data; /**< 留给驱动上层 */ }; ``` 论坛里搜索了一下发现有人提出了这个问题. https://club.rt-thread.org/ask/question/428675.html # 最终 应该选择方案2, user_data留给驱动的上层. 驱动实现时, struct stm32_uart, 等这些是在drv_uart.c内部定义的. ``` struct stm32_uart { ... struct rt_serial_device serial; }; ``` ## 1. uart计算: 在uart结构体内部定义serial设备. 当给出serial指针时, 可以通过 uart = rt_container_of(serial, struct stm32_uart, serial); 来计算出uart的位置. ## 2. uart与serial对应 serial定义在uart内部, 实现了serial与uart对应关系. 是不需要user_data来传递的. ## 3. 安全 serial定义在uart内部, struct stm32_uart 结构体只在 drv_uart.c里出现, 驱动外部是无法知道这个结构体的. 即使有了serial指针, 是无法计算出uart指针的. 无法直接对uart进行任意操作. 如果使用user_data来传递, 这样就能在驱动外面, 通过device->user_data就能访问到uart, 就能直接进行任意操作. 这是不安全的.
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
如是我闻
这家伙很懒,什么也没写!
文章
2
回答
0
被采纳
0
关注TA
发私信
相关文章
1
获取心知天气数据失败?
2
使用rt_device_open打开传感器后,发现设备的open_flag没有设置成只读
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
7
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
3
次点赞
Ghost_Girls
1
篇文章
6
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部