Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
SPI+DMA
rt-thread 互斥信号量BUG
发布于 2021-08-04 08:39:48 浏览:1280
订阅该版
[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.3k
关于作者
懒洋洋
这家伙很懒,什么也没写!
提问
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
【RT-Thread】【ci】【scons】将ci.attachconfig.yml和scons结合使用
2
Rt-thread中OTA下载后,bootloader不搬程序
3
ulog 日志 LOG_HEX 输出时间改为本地日期时间
4
在RT-Thread Studio中构建前执行python命令
5
研究一了一段时间RTT,直接标准版上手太难,想用nano,但又舍不得组件
热门标签
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在线升级
cubemx
PWM
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位
9
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
4
次点赞
Ghost_Girls
1
篇文章
7
次点赞
xiaorui
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部