Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
DMA
串口
10
串口接收释放信号量的问题
发布于 2021-10-22 16:00:26 浏览:1541
订阅该版
[tocm] 在看别人代码,和迪文屏通信时发现的问题。 先用dma_rx的方式接收数据 ```c rt_device_open(ScreenDev.dev, RT_DEVICE_FLAG_DMA_RX) ``` 设置了回调函数 ```c rt_device_set_rx_indicate(ScreenDev.dev, Screen_rx_ind); ``` 回调函数为,每调用一次,释放一次信号量 ```c static rt_err_t Screen_rx_ind(rt_device_t dev, rt_size_t size) { /* release semaphore to let finsh thread rx data */ rt_sem_release(&ScreenDev.r_tx); return RT_EOK; } ``` ## 问题一 请问这里是接收一个字节就调用这个回调函数,还是通过DMA接收完一帧数据才调用一次回调函数? 这是对接收到的数据进行处理,看到,接收到一个信号量,才会读取一个字节ch,对ch进行解析。 ```c void Screen_process(void *s) { RT_ASSERT(ScreenDev.dev); u8 ch = 0; rt_kprintf ("scree process thread running...\r\n"); ScreenDev.r_sta = LCDPSTATUS_FINDHEAD1; ScreenDev.buff_len = 0; memset(ScreenDev.buff, 0, Screen_BUFF_SIZE); while (1) { if ((rt_sem_take(&ScreenDev.r_tx, 5000)) != RT_EOK) { continue; } /* read one character from device */ while (rt_device_read(ScreenDev.dev, 0, &ch, 1) == 1) { lcd_cmd_analyse(ch); } rt_thread_delay(50); } } ``` ## 问题二 如果问题一中,接收完一帧数据5个字节,才释放一个信号量,那么在这个函数中,只能take一个信号量,处理一个字节。如果想处理剩下的4个字节,需要take4个信号量,可是前面只释放了一个。为什么代码能正常工作呢。 ## 问题三 函数最后有`rt_thread_delay(50);`这里是挂起50ms,执行其他线程,如果50ms过后本来应该执行这个线程,但是如果有优先级更高的线程正在执行,就没办法继续执行这个线程了吧,需要等待高优先级的线程执行完。
查看更多
2
个回答
默认排序
按发布时间排序
梅江松子
2021-10-22
这家伙很懒,什么也没写!
## 问题一 是DMA接收完成一帧 调用一次回调函数 ```c static void uart_isr(struct rt_serial_device *serial) { #ifdef RT_SERIAL_USING_DMA else if ((uart->uart_dma_flag) && (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_IDLE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_IDLE) != RESET)) { level = rt_hw_interrupt_disable(); recv_total_index = serial->config.bufsz - __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle)); recv_len = recv_total_index - uart->dma_rx.last_index; uart->dma_rx.last_index = recv_total_index; rt_hw_interrupt_enable(level); if (recv_len) { rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); } __HAL_UART_CLEAR_IDLEFLAG(&uart->handle); } } ``` 在上诉代码在 rtt stm32的 drv_uart.c 中,采用DMA方式接收,会触发串口空闲中断,进入 ```c rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); ``` 随后进入 dma接收处理 ```c case RT_SERIAL_EVENT_RX_DMADONE: { int length; rt_base_t level; /* get DMA rx length */ length = (event & (~0xff)) >> 8; if (serial->config.bufsz == 0) { struct rt_serial_rx_dma* rx_dma; rx_dma = (struct rt_serial_rx_dma*) serial->serial_rx; RT_ASSERT(rx_dma != RT_NULL); RT_ASSERT(serial->parent.rx_indicate != RT_NULL); serial->parent.rx_indicate(&(serial->parent), length); rx_dma->activated = RT_FALSE; } else { /* disable interrupt */ level = rt_hw_interrupt_disable(); /* update fifo put index */ rt_dma_recv_update_put_index(serial, length); /* calculate received total length */ length = rt_dma_calc_recved_len(serial); /* enable interrupt */ rt_hw_interrupt_enable(level); /* invoke callback */ if (serial->parent.rx_indicate != RT_NULL) { serial->parent.rx_indicate(&(serial->parent), length); } } ``` 最后的调用 serial->parent.rx_indicate(&(serial->parent), length); 传入的参数 length 就是此次接收的帧长度; 所以回调函数中,应该想办法把这个长度告诉应用程序,而不是单纯的释放一次信号量。 可以参考rtt官方文档 如下图部分 ![6971777b08806a5ac3a291960beba71b.jpg.webp](https://oss-club.rt-thread.org/uploads/20211022/6971777b08806a5ac3a291960beba71b.jpg.webp)
李肯陪你玩赚嵌入式
认证专家
2021-10-22
2022年度和2023年度RT-Thread社区优秀开源布道师,COC深圳城市开发者社区主理人,专注于嵌入式物联网的架构设计
#### **谈谈我的理解** **问题一** 我理解的是,接收到一帧数据就会触发这个回调函数,而不是接收到一个字节就触发 **问题二** 基于问题一的回答,我们来看触发了信号量take之后的处理流程,你的分析逻辑有些不对, 重点在于对这段代码的理解不对: ```c /* read one character from device */ while (rt_device_read(ScreenDev.dev, 0, &ch, 1) == 1) { lcd_cmd_analyse(ch); } ``` 注意这里是一个while循环,不是一次性的运行,是有可能运行多次的; 比如你提到的接收到一帧数据5个字节就release信号量,然后处理线程take到了信号量, 那么有这个while流程,就可以5次去读取串口数据,也就是rt_device_read前5次都可以返回1; 之后就返回非1,这样就退出了while循环; 接着去等待下一次信号量触发。 **问题三** 你的理解是正确的,确实存在50ms后,被高优先级的任务抢去执行,但这不是正常的抢占式运行策略嘛?如果想把保证本线程的高实时性,那么需要提升它的优先级。 以上理解,仅供参考。
撰写答案
登录
注册新账号
关注者
1
被浏览
1.5k
关于作者
伊森亨特
这家伙很懒,什么也没写!
提问
77
回答
31
被采纳
0
关注TA
发私信
相关问题
1
串口DMA发送数据时,数据被覆盖
2
关于串口DMA模式下rt_device_close问题
3
利用stm32f427实现usb转串口,电脑端什么也没有识别到
4
finsh 控制台 适配 RS 485请大神指点????
5
uart_sample.c 中,读串口设备时偏移量pos要设置为-1而不是0?
6
【结贴】at_device软件包中对串口接收数据缺少判断导致数据接收异常
7
串口无法接受数据,但可以发送
8
串口如何有效的清除掉接收缓冲,而不必一个一个的去读取
9
串口接收使用方式问题
10
雅特力FINSH问题
推荐文章
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组件
最新文章
1
STM32H7R7运行CherryUSB
2
RT-Smart首次线下培训,锁定2024 RT-Thread开发者大会!
3
使用RC522软件包驱动FM1722
4
常量数据类型和表达式陷阱分享
5
进行i2c驱动移植的经验总结
热门标签
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
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部