一、在外设产生中断时 需要用到二值信号量与任务同步,在程序开始创建二值信号量如果没有用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");
}