天天看點

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

1、CUBE 配置

1.1硬體配置

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

晶振配置

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

系統時鐘源配置 Tim1, systick給freertos用

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

獨立看門狗:預分頻 32 喂狗逾時 4095 個 分頻後的周期數

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

低功耗序列槽1 : 1、異步模式 2、開啟全局中斷

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

低功耗序列槽1 : 添加 DMA

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

時鐘源選擇

1.2 freertos 配置

添加序列槽任務

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

建立dma發送和接收的信号量

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

二、使用者代碼

如果使用信号量同步,要把使能空閑中斷放在預設任務開頭。

這樣可以避免一種開機就當機的情況:

開啟中斷後序列槽在信号量初始化之前就收到一幀資料,

而在中斷中釋放的信号量還沒有被建立。

void HalLpUartInit()
{
	if(HAL_OK != HAL_UART_Receive_DMA(&hlpuart1, g_lpUartRx.data, UART_RX_MAX))
		Error_Handler();
	__HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_IDLE);
	__HAL_UART_ENABLE_IT(&hlpuart1, UART_FLAG_TC);
}
           
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  	HalLpUartInit();
	HAL_GPIO_TogglePin(GPIOA, LED_BLUE_Pin);
	osTimerStart(UI_TimerHandle, 500);
	//這裡用printf會産生一個長度是0的空閑接收中斷 後面列印正常
	//printf("Start Default Task!\r\n");
	LpUartTx(strlen("Start Default Task!\r\n"),(uint8_t *)"Start Default Task!\r\n");
	/* Infinite loop */
	for(;;)
	{
		HAL_IWDG_Refresh(&hiwdg);
		osDelay(1000);
	}
  /* USER CODE END StartDefaultTask */
}
           

序列槽任務

void LpUartTask(void *argument)
{
  /* USER CODE BEGIN LpUartTask */
  /* Infinite loop */
  for(;;)
  {
	  if(osOK == osSemaphoreAcquire(lpuartRxBinarySemHandle,osWaitForever))
	  {
		  printf("rx [%d]:",g_lpUartRx.size);
		  LpUartTx(g_lpUartRx.size, g_lpUartRx.data);
		  printf("\r\n");
	  }
  }
  /* USER CODE END LpUartTask */
}
           

dma發送

void LpUartTx(uint16_t len, uint8_t * buff)
{
	if(0 == len) 
		return;
	if(HAL_OK == osSemaphoreAcquire(lpuartTxBinarySemHandle,10))
		HAL_UART_Transmit_DMA(&hlpuart1, buff, len);
}
           

序列槽全局中斷處理:1、空閑中斷 2、DMA傳輸完成中斷

void LPUART1_IRQHandler(void)
{
  /* USER CODE BEGIN LPUART1_IRQn 0 */
	uint32_t temp;
	uint32_t ret = taskENTER_CRITICAL_FROM_ISR();
    if(__HAL_UART_GET_FLAG(&hlpuart1,UART_FLAG_IDLE) != RESET)
    {
		HAL_UART_DMAStop(&hlpuart1);  
		temp = hlpuart1.hdmarx->Instance->CNDTR;  
		g_lpUartRx.size = UART_RX_MAX - temp;
		// starting uart dma rcv again
		HAL_UART_Receive_DMA(&hlpuart1, g_lpUartRx.data, UART_RX_MAX);  
		osSemaphoreRelease(lpuartRxBinarySemHandle);
		__HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
	}else if(__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_TC) != RESET){
		osSemaphoreRelease(lpuartTxBinarySemHandle);
		__HAL_UART_CLEAR_TXFECF(&hlpuart1);
	}
  /* USER CODE END LPUART1_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart1);
  /* USER CODE BEGIN LPUART1_IRQn 1 */
	taskEXIT_CRITICAL_FROM_ISR(ret);
  /* USER CODE END LPUART1_IRQn 1 */
}
           

實驗效果

STM32WB55XX freertos 二值信号量+dma+idle 不定長序列槽接收 + dma傳輸完成中斷

(第一條列印用printf會産生接收長度為0的空閑中斷,未找到原因)