1171|7

326

帖子

1

TA的资源

纯净的硅(初级)

楼主
 

FreeRTOS中的互斥锁在中断中Give [复制链接]

 

新手第一次使用FreeRTOS的互斥锁,本想用它来指示串口发送DMA的占用情况,在DMA传输完成中断中Give串口发送DMA互斥量(xSemaphoreGiveFromISR)。结果系统始终无法正常运行起来。由于一次修改了多处代码一时定位不到问题点。只知道调试串口打印出“FreeRTOS assert "!( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMute...”的消息。网上找了一圈,发现大家都说FreeRTOS的互斥锁功能不完整,本来互斥量应该遵循谁上锁谁解锁的原则,结果FreeRTOS却没能实现这个功能,他的互斥锁上锁后所有人都可以解锁。于是我便坚定了中断中也可以解锁互斥量。但是一通折腾下来始终不能成功运行,最后无意中看到宏“xSemaphoreGiveFromISR”的使用前注释才发现了问题所在:

 

Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) must not be used with this macro.

原来虽然FreeRTOS不能实现谁上锁谁开锁这个功能,但是他还是稍微做了下弥补,那就是中断函数中不允许Give互斥量。

最新回复

同意版主大大,升级试试看   详情 回复 发表于 2023-12-26 08:30
点赞 关注
个人签名模电临时工
 

回复
举报

7020

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

FreeRTOS不能实现谁上锁谁开锁这个功能,但是他还是稍微做了下弥补,那就是中断函数中不允许Give互斥量

非常感谢分享

 
 
 

回复

753

帖子

0

TA的资源

纯净的硅(高级)

板凳
 

我对FreeRTOS中的互斥锁的理解也不深。

看来未来也需要加强一下

 
 
 

回复

7193

帖子

11

TA的资源

版主

4
 
现在最新版的好象说修复了这个问题,楼主可以去试试。

点评

不知道我用的是不是最新版,总之用了互斥量就一堆的问题,各种报Assert错误,我也不知道是不是因为谁上锁谁解锁的原因导致的。总之如果遵循谁上锁谁解锁的原则使用互斥量就可以运行。否则就会报各种ASSERT错误。如果  详情 回复 发表于 2023-12-23 17:09
 
 
 

回复

326

帖子

1

TA的资源

纯净的硅(初级)

5
 
本帖最后由 shipeng 于 2023-12-23 17:14 编辑
lugl4313820 发表于 2023-12-23 10:15 现在最新版的好象说修复了这个问题,楼主可以去试试。

不知道我用的是不是最新版,总之用了互斥量就一堆的问题,各种报Assert错误,我也不知道是不是因为谁上锁谁解锁的原因导致的。总之如果遵循谁上锁谁解锁的原则使用互斥量就可以运行。否则就会报各种ASSERT错误。如果把互斥量换成二值信号量就没有这个问题。

下面是我的源码,说一下我的软件逻辑:每次DMA传输完成后启动一个10毫秒定时器,在定时器回调函数中Give互斥量。从而保证帧最小间隔为10毫秒,以防止发送帧粘连。

  • SemaphoreHandle_t DMA2C5MuxSem_Handle = NULL;
  • TimerHandle_t xHandleTimerU4Tx = NULL;
  • TaskHandle_t xHandleTaskU4TX = NULL;
  • static void U4TxTimerCallback(void);
  • static void CreateU4TxFrameDelay(TickType_t xTimerPeriodInTicks );
  • static void vTaskU4TX_Handler(void *pvParameters);
  • void UART4_DMA_Init(void);
  • void BSP_UART4_Init(void);
  • void BSP_USART_Config(void)
  • {
  • BSP_UART4_Init();
  • UART4_DMA_Init();
  • NVIC_EnableIRQRequest(UART4_IRQn, 2, 0);
  • USART_EnableInterrupt(UART4, USART_INT_IDLE);
  • /* Enable UART4 RX and UART4 TX DMA */
  • USART_EnableDMA(UART4, USART_DMA_TX_RX);
  • U4RxQueue = xQueueCreate(U4RX_QUE_DEPTH, U4RX_QUE_SIZE);//msgs , length of msg(byte)
  • if (NULL==U4RxQueue)printf("U4RxQueue Creating Failed!\r\n");
  • U4TxQueue = xQueueCreate(4, 4);
  • if (NULL==U4TxQueue)printf("U4TxQueue Creating Failed!\r\n");
  • #ifndef USE_DMA_WITH_MUTEX
  • DMA2C5MuxSem_Handle = xSemaphoreCreateBinary();
  • #else
  • DMA2C5MuxSem_Handle = xSemaphoreCreateMutex();
  • #endif
  • if (NULL==DMA2C5MuxSem_Handle)printf("DMA2C5MuxSem Creating Failed!\r\n");
  • #ifndef USE_DMA_WITH_MUTEX
  • else if (0==uxSemaphoreGetCount(DMA2C5MuxSem_Handle) && pdPASS!=xSemaphoreGive(DMA2C5MuxSem_Handle))printf("DMA2C5MuxSem Giving Failed!\r\n");
  • #endif
  • CreateU4TxFrameDelay(10);
  • xTaskCreate((TaskFunction_t )vTaskU4TX_Handler,
  • (const char* )"UART4 TX Task",
  • (uint16_t )256,
  • (void* )NULL,
  • (UBaseType_t )5,
  • (TaskHandle_t* )&xHandleTaskU4TX);
  • }
  • static void U4TxTimerCallback(void)
  • {
  • #ifndef USE_DMA_WITH_MUTEX
  • if (0==uxSemaphoreGetCount(DMA2C5MuxSem_Handle) && pdPASS != xSemaphoreGive( DMA2C5MuxSem_Handle))printf("DMA2C5MuxSem Giving failed!");
  • #else
  • if (NULL!=xSemaphoreGetMutexHolder(DMA2C5MuxSem_Handle) && pdPASS != xSemaphoreGive( DMA2C5MuxSem_Handle))printf("DMA2C5MuxSem Giving failed!");
  • #endif
  • else if (0!=uxQueueMessagesWaiting(U4TxQueue))portYIELD();//if the queue is not empty,then request a context switch
  • }
  • static void CreateU4TxFrameDelay(TickType_t xTimerPeriodInTicks )
  • {
  • xHandleTimerU4Tx = xTimerCreate("U4TxTimer",xTimerPeriodInTicks,pdFALSE,(void*)3,(TimerCallbackFunction_t)U4TxTimerCallback);
  • if (NULL==xHandleTimerU4Tx)printf("U4TxTimer Creating failed!");
  • }
  • static void vTaskU4TX_Handler(void *pvParameters)
  • {
  • UsartTxRxBuffer_t *tx_buffer;
  • while(1)
  • {
  • if (pdPASS==xQueueReceive(U4TxQueue, (uint8_t*)&tx_buffer, portMAX_DELAY))
  • {
  • xSemaphoreTake(DMA2C5MuxSem_Handle, 5689U);//5689ms Is The MAX TIME of DMA-UART-Tx,65536bytes*1000ms/11520(byte rate)=5688.888...
  • if (0!=tx_buffer->length)
  • {
  • /* Disable TX DMA */
  • DMA_Disable(DMA2_Channel5);
  • memcpy(DMA_UART4_TxBuf,tx_buffer->DatArea,tx_buffer->length);
  • DMA2_Channel5->CHNDATA_B.NDATA = tx_buffer->length;
  • /* Enable TX DMA */
  • DMA_Enable(DMA2_Channel5);
  • }
  • if (NULL!=tx_buffer)vPortFree((uint8_t*)tx_buffer);
  • }
  • }
  • }
  • void DMA2_Channel5_IRQHandler(void)
  • {
  • if (RESET != DMA_ReadIntFlag(DMA2_INT_FLAG_TC5))
  • {
  • BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  • DMA_ClearIntFlag(DMA2_INT_FLAG_TC5);
  • if (NULL!=xHandleTimerU4Tx)
  • {
  • xTimerResetFromISR(xHandleTimerU4Tx,&xHigherPriorityTaskWoken);
  • }
  • }
  • }
  • void UART4_DMA_Init(void)
  • {
  • DMA_Config_T dmaConfig;
  • /* Enable DMA Clock */
  • RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA2);
  • /* TX DMA config */
  • dmaConfig.peripheralBaseAddr = UART4_DR_ADDRESS;
  • dmaConfig.memoryBaseAddr = (uint32_t)DMA_UART4_TxBuf;
  • dmaConfig.dir = DMA_DIR_PERIPHERAL_DST;
  • dmaConfig.bufferSize = 0;
  • dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
  • dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
  • dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_BYTE;
  • dmaConfig.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE;
  • dmaConfig.loopMode = DMA_MODE_NORMAL;
  • dmaConfig.priority = DMA_PRIORITY_HIGH;
  • dmaConfig.M2M = DMA_M2MEN_DISABLE;
  • /* Enable DMA channel */
  • DMA_Config(DMA2_Channel5, &dmaConfig);
  • /* Enable TX DMA */
  • DMA_Enable(DMA2_Channel5);
  • NVIC_EnableIRQRequest(DMA2_Channel5_IRQn, 3, 0);
  • DMA_EnableInterrupt(DMA2_Channel5, DMA_INT_TC);
  • /* RX DMA Configure */
  • dmaConfig.dir = DMA_DIR_PERIPHERAL_SRC;
  • dmaConfig.loopMode = DMA_MODE_CIRCULAR;
  • dmaConfig.bufferSize = sizeof(DMA_UART4_RxBuf);
  • dmaConfig.memoryBaseAddr = (uint32_t)DMA_UART4_RxBuf;
  • /* Enable DMA channel */
  • DMA_Config(DMA2_Channel3, &dmaConfig);
  • /* Enable RX DMA */
  • DMA_Enable(DMA2_Channel3);
  • // NVIC_EnableIRQRequest(DMA2_Channel3_IRQn, 1, 0);
  • // DMA_EnableInterrupt(DMA2_Channel3, DMA_INT_TC);
  • }
  • void BSP_UART4_Init(void)
  • {
  • GPIO_Config_T GPIO_ConfigStructure;
  • USART_Config_T USART_ConfigStruct;
  • RCM_EnableAPB2PeriphClock((RCM_APB2_PERIPH_T)(RCM_APB2_PERIPH_GPIOC));
  • RCM_EnableAPB1PeriphClock((RCM_APB1_PERIPH_T)(RCM_APB1_PERIPH_UART4));
  • /*Uart4 TX*/
  • GPIO_ConfigStructure.pin = GPIO_PIN_10;
  • GPIO_ConfigStructure.speed = GPIO_SPEED_50MHz;
  • GPIO_ConfigStructure.mode = GPIO_MODE_AF_PP;
  • GPIO_Config(GPIOC, &GPIO_ConfigStructure);
  • /*Uart4 RX*/
  • GPIO_ConfigStructure.pin = GPIO_PIN_11;
  • GPIO_ConfigStructure.mode = GPIO_MODE_IN_FLOATING;
  • GPIO_Config(GPIOC, &GPIO_ConfigStructure);
  • USART_ConfigStruct.baudRate = 115200;
  • USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
  • USART_ConfigStruct.mode = USART_MODE_TX_RX;
  • USART_ConfigStruct.parity = USART_PARITY_NONE;
  • USART_ConfigStruct.stopBits = USART_STOP_BIT_1;
  • USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;
  • USART_Config(UART4, &USART_ConfigStruct);
  • USART_Enable(UART4);
  • }

 

 
个人签名模电临时工
 
 

回复

7193

帖子

11

TA的资源

版主

6
 

前段时间管管发了一个帖子,说freertos升级到了最新版了的,你可以去看看。

 
 
 

回复

7783

帖子

2

TA的资源

五彩晶圆(高级)

7
 

我记得是可以的呀,应该是10版本以上。

 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

8
 

同意版主大大,升级试试看

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
有奖探索 | 和村田一起,深挖 GNSS 开发!
活动时间:即日起-5月11日
活动奖励:智能手环、螺丝刀套装、双肩包

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 6

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表