Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
SPI+DMA
rt-thread 互斥信号量BUG
发布于 2021-08-04 08:39:48 浏览:705
订阅该版
[tocm] ## 问题描述 在项目中用到互斥信号量的时候发现:“RT_WAITING_FOREVER 的延时失效”, 这个互斥信号量的使用是用来控制数据的产生的节奏 ```c 1. 线程扫描一次,产生一次 **m包** 数据,之后通过 take 互斥信号量等待 2. 定时器中断发送数据,等 m包 数据发送完成之,通过 release 互斥信号量,启动数据扫描线程 3. 由于定时周期有 32ms ,此段时间完全够扫描数据线程生产数据 ``` 实际测试的时候发现使用**互斥信号量**的时候,这个 rt_mutex_take 根本没有将让此线程停住,但是使用 **信号量 替换 互斥信号量** 的时候发现这个程序能正常运行 此处程序中我还有个LCD的刷新与LCD缓存操作也使用了 **互斥信号量,此互斥信号量是正常工作** 这个同点是这个 **互斥信号量 是在工作队列中释放的,不知道这个是否是问题点?** ## 软件场景 1. 有一个硬件定时器定时发发送数据,定时中断触发时候,触发回调 [**此处使用工作队列实际发送,SPI中有互斥信息量不能再中断中调用**] ```c /******************************************************************************* * Function Name : hw_timer2_callback * Description : 同步时钟超时处理函数 * Input : None * Output : None * Return : None *******************************************************************************/ /* SPI 同步时钟 工作队列处理函数 */ void drv_spi_timer_tx_work(struct rt_work *work, void *work_data) { struct spi_work_data *spi_data = NULL; spi_data = (struct spi_work_data *)work_data; /* s0:提取数据 */ uint8_t *s_pac = app_data_queue_pop(SPI0_S + spi_data->port * 2); /* s1: 发送数据: 此处存在 dma_sem 管理发送完成才会退出函数 */ app_spi_transfer(spi_data->port, &(port_ant[spi_data->port].ant_spi), s_pac, port_ant[spi_data->port].rpac, ANT_SPI_LEN); /* s2: 回收数据 */ app_data_queue_push(IDLE_E, s_pac); /* s3: 数据发送完成继续扫描数据 */ if (app_data_queue_size(SPI0_S + spi_data->port * 2) == 0) { rt_mutex_release(&port_ant[spi_data->port].scan_lock); // rt_sem_release(&(port_ant[spi_data->port].scan_lock)); } } rt_err_t hw_timer2_callback(rt_device_t dev, rt_size_t size) { uint8_t i; /* 不同工作模式翻转节奏不一样 */ if (sys_tcb_val.work_mode == NORMAL_MODE) { for (i = 0; i < SPI_PORT_MAX; i++) { rt_pin_write(port_ant[i].ant_conf->snd_pin, 1 - rt_pin_read(port_ant[i].ant_conf->snd_pin)); /* 添加工作队列 */ if (app_data_queue_size(SPI0_S + i * 2) > 0) { spi_tmp_data[i].port = i; spi_tmp_work[i].work_data = (void *)&(spi_tmp_data[i]); spi_tmp_work[i].work_func = drv_spi_timer_tx_work; rt_workqueue_dowork(spi_wq, &spi_tmp_work[i]); } } } else { for (i = 0; i < SPI_PORT_MAX; i++) { /* 其他模式都是单天线工作 */ if (sys_tcb_val.work_port == i) rt_pin_write(port_ant[i].ant_conf->snd_pin, 1 - rt_pin_read(port_ant[i].ant_conf->snd_pin)); } } return RT_EOK; } ``` 这个发送数据在发送数据完毕时候释放 /* s3: 数据发送完成继续扫描数据 */ ```c rt_mutex_release(&port_ant[spi_data->port].scan_lock); ``` 1. 工作线程扫描数据产生 ```c void fun_spi_m(void *parameter) { ant_tcb_t *c_ant = (ant_tcb_t *)parameter; while (1) { /* 解析指令 */ app_spi_rcmd_decode(c_ant, (spi_pac_t *)(c_ant->rpac)); rt_memset((uint8_t *)&(c_ant->rpac), 0, sizeof(spi_pac_t)); /* 根据处理结进行新的处理 */ switch (c_ant->init_sta) { /* 其他情况 */ case SPI_RUN: /* s1: 程序运行 */ /* s2: 扫描载包数据:次部分数据只有特答题器的数据 */ for (uint8_t upos = 0; upos < sys_tcb_val.port_max; upos++) { ///.扫描数据,送入发送数据队列 对应 app_data_queue_size(SPI0_S + spi_data->port * 2) } /* 计算延时: 保证缓存非空,每路SPI都有数据发送:实测数据能保证在3个下,这样保证数据非空时序沾满,实时性有能保证 [8253]: IDLE:092 USB:[000 000] SPI:[000 002][000 001][000 001][000 001] [8253]: IDLE:091 USB:[000 000] SPI:[000 002][000 001][000 001][000 001] [8256]: IDLE:090 USB:[000 000] SPI:[000 002][000 001][000 001][000 002] [8263]: IDLE:089 USB:[000 000] SPI:[000 001][000 002][000 001][000 002] [8265]: IDLE:090 USB:[000 000] SPI:[000 001][000 001][000 001][000 002] [8266]: IDLE:091 USB:[000 000] SPI:[000 001][000 001][000 001][000 002] */ rt_mutex_take(&(c_ant->scan_lock), RT_WAITING_FOREVER); // rt_sem_take(&(c_ant->scan_lock), RT_WAITING_FOREVER); break; default: rt_thread_mdelay(1000); break; } } } ``` 当前系统版本为: ```c \ | / - RT - Thread Operating System / | \ 3.1.3 build Jul 19 2021 2006 - 2019 Copyright by rt-thread team ```
查看更多
3
个回答
默认排序
按发布时间排序
yukelab
2021-08-04
这家伙很懒,什么也没写!
互斥量和信号量不同的是:拥有互斥量的线程拥有互斥量的所有权,互斥量支持递归访问且能防止线程优先级翻转;并且**互斥量只能由持有线程释放**,而信号量则可以由任何线程释放。 你这里使用的workqueue应该使用了一个线程;而fun_spi_m是另外一个线程;
小住住
认证专家
2021-08-04
这家伙很懒,什么也没写!
调试跟踪一下呢?会一直在释放吗?
出出啊
2021-08-04
恃人不如自恃,人之为己者不如己之自为也
@yukelab 错,互斥量又叫锁,多用于临界区保护,不同于信号量的主要工作是传递一个信号和线程同步。 加锁和释放锁是要成对的。而且当且仅当多线程情况下,多个线程访问临界区需要互斥量保护临界区只能有一个线程访问。所以叫它互斥量。 中断中向线程传递一个同步消息,用信号量。用互斥量肯定是错的。包括中断的回调函数中都不允许使用互斥量加锁。 看你的代码,没发现哪儿的互斥量使用异常了,rt_workqueue_dowork 中使用互斥量了? hw_timer2_callback 是硬件定时器中断的回调函数吧,回调函数中调用的函数以及子孙函数里都不允许使用互斥量。
撰写答案
登录
注册新账号
关注者
0
被浏览
705
关于作者
懒洋洋
这家伙很懒,什么也没写!
提问
9
回答
0
被采纳
0
关注TA
发私信
相关问题
1
正点原子战舰V3+ENC28J60+SPI,开启SPI DMA后,卡死
2
SPI4设置DMA RX 错误
3
spi DMA 发送数据失败
4
spi dma 中断接收的问题
5
关于spi和dma的问题
6
RT Studio中F407芯片SPI的DMA怎么开启?
7
RT Studio中SPI+DMA如何使用?
8
我现在可以使用SPI正常收发数据了,但是怎样使用SPI的DMA模式进行数据的收发
9
SPI DMA 缓冲区
10
spi使用轮询还是中断
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
五分钟玩转RT-Thread新社区
5
国产MCU移植系列教程汇总,欢迎查看!
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
github高阶加速,速度可达带宽峰值,测试到146Mbit/s
2
英飞凌携手RT-Thread举办嵌入式网络应用开发沙龙,带你从0到1搭建智能数据网关
3
BL808 RT-Thread Wi-Fi 驱动适配
4
rt-thread 系统运行期改变网卡配置
5
简单的步进电机驱动调试
热门标签
RT-Thread Studio
串口
LWIP
Env
AT
SPI
Bootloader
FinSH
ART-Pi
CAN总线
Hardfault
USB
文件系统
RT-Thread
DMA
SCons
线程
MQTT
RT-Thread Nano
STM32
RTC
ESP8266
rt-smart
flash
ota在线升级
WIZnet_W5500
FAL
I2C
packages_软件包
UART
cubemx
freemodbus
潘多拉开发板_Pandora
定时器
BSP
PWM
ADC
socket
中断
rt_mq_消息队列_msg_queue
keil_MDK
SDIO
Debug
AB32VG1
MicroPython
C++_cpp
编译报错
msh
QEMU
ulog
本月问答贡献
出出啊
1500
个答案
338
次被采纳
小小李sunny
1389
个答案
276
次被采纳
张世争
714
个答案
157
次被采纳
crystal266
522
个答案
153
次被采纳
whj467467222
1216
个答案
146
次被采纳
本月文章贡献
出出啊
1
篇文章
12
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
2
篇文章
1
次点赞
crystal266
2
篇文章
5
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部