随笔:外设中断FreeRTOS——使用信号量注意事项1

一、在外设产生中断时 需要用到二值信号量与任务同步,在程序开始创建二值信号量如果没有用xSemaphoreGive(),进行释放信号量会出现外设中断来后,在中断程序中使用xSemaphoreGiveFromISR();会出现任务中用xSemaphoreTake()接收不到中断发的二至信号量值。所以在创建二值信号量后,就需xSemaphoreGive()释放一次。

BaseType_t xReturn = pdFAIL;

 uartDMATCSemaphore = xSemaphoreCreateBinary();
    if(NULL != uartDMATCSemaphore)
    printf("uartDMATCSemaphore二值信号量创建成功!\n");

//其他代码

 xSemaphoreGive(USART3_DMAtx_Handle);
  xSemaphoreGive(uartDMATCSemaphore); 
 

  vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务  
  taskEXIT_CRITICAL();            //退出临界区

、在使用DMA接收中断和DMA发送中断也尽量使用二值信号量,若采用全局变量会出现运行一段时间涉及到该DMA的任务会假死。

例如:在DMA发送中断中使用

//=======================================
//DMA发送完成中断服务程序
//=======================================void DMA1_Stream6_IRQHandler(void)
{
  BaseType_t xHP_TaskWoken= pdFALSE;
  if(DMA_GetITStatus(SERIAL2_USART_TX_DMA_STREAM,SERIAL2_USART_TX_IT_TC) != RESET)
  {   DMA_ClearITPendingBit(SERIAL2_USART_TX_DMA_STREAM,SERIAL2_USART_TX_IT_TC);
    DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_TCIF6 | DMA_FLAG_FEIF6 | 
                      DMA_FLAG_DMEIF6 | DMA_FLAG_TEIF6 | DMA_FLAG_HTIF6);     //清除标志位 
    while(0==(SERIAL2_USART->SR & USART_FLAG_TC))//等待全部发送完成 “transmission complete”(发送完成)这个地方不等待,会出现一包数据最后两字节发送不出去
    {;}
    DMA_Cmd(SERIAL2_USART_TX_DMA_STREAM, DISABLE);//禁止传输
    USART2_RS485(ON);//RS485使能接收        
    if(USART2_DMAtx_Handle!=NULL)
    {
    //释放二值信号量
    xSemaphoreGiveFromISR(USART2_DMAtx_Handle,&xHP_TaskWoken); // (通知消费者,现在状态)
    }    
    if(xHP_TaskWoken == pdTRUE)//注意这个地方要判断
    portYIELD_FROM_ISR(xHP_TaskWoken);//如果需要的话进行一次任务切换
  }    
}

注意:是生产者释放信号量,消费者获取信号量//=======================================
//串口DMA发送函数
//======================================= 
void USART2_DMA_TranData(uint8_t *str,uint32_t dataLen)
{  
  while(xSemaphoreTake(USART2_DMAtx_Handle,2) != pdTRUE)//获取信号量,等待DMA发送可用,
(消费者获取信号量)
  {;}  DMA_ClearFlag(SERIAL2_USART_TX_DMA_STREAM,SERIAL2_USART_TX_Flag_TCIF); //清DMA发送完成标志
  DMA_Cmd(SERIAL2_USART_TX_DMA_STREAM, DISABLE);//关闭DMA设备(需要在DMA关闭的状态下才能进行配置)  
  while(DMA_GetCmdStatus(SERIAL2_USART_TX_DMA_STREAM) != DISABLE);//等待关闭完成
  USART_ClearFlag(SERIAL2_USART, USART_FLAG_TC);     //清除“transmission complete”(发送完成)
  USART_GetFlagStatus(SERIAL2_USART, USART_FLAG_TXE);//Transmit data register empty flag
    
  SERIAL2_USART_TX_DMA_STREAM->M0AR = (uint32_t)str;//需要发送的数据地址
  SERIAL2_USART_TX_DMA_STREAM->NDTR = dataLen;//需要发送的数据长度
  DMA_SetCurrDataCounter(SERIAL2_USART_TX_DMA_STREAM,dataLen);          //数据传输量     
  DMA_Cmd(SERIAL2_USART_TX_DMA_STREAM, ENABLE);                      //开启DMA传输 
//    printf("\n USART1_2_2 \n");  
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值