Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
SPI+DMA
rt-thread 互斥信号量BUG
发布于 2021-08-04 08:39:48 浏览:1120
订阅该版
[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
被浏览
1.1k
关于作者
懒洋洋
这家伙很懒,什么也没写!
提问
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
国产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
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
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
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部