【问题标题】:STM32 CMSIS FreeRTOS: configASSERT triggered when releasing BinrarySemaphore from ISRSTM32 CMSIS FreeRTOS:从 ISR 释放 BinrarySemaphore 时触发 configASSERT
【发布时间】:2019-09-22 17:26:04
【问题描述】:

我有一个 UART 空闲中断,它应该通知任务 UART 上的活动已经结束。

为此,我使用的是 BinarySemaphore,在这种情况下它只是一个最大计数为 1 的信号量。

当我调用信号量释放函数osSemaphoreRelease(semaphore_id_uart4_rx);

由于触发了以下断言,应用程序停止。

/* Normally a mutex would not be given from an interrupt, especially if
    there is a mutex holder, as priority inheritance makes no sense for an
    interrupts, only tasks. */
    configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) );

configASSERT 扩展为

if ((!( ( pxQueue->pcHead == ((void *)0) ) && ( pxQueue->pcTail != ((void *)0) ) )) == 0) {vPortRaiseBASEPRI(); for( ;; );}

现在 pxQueue->pcHead 的值为 0,而 pxQueue->pcTail 的值为非 0。所以断言被触发了。

此断言上方的注释表明这是为了从 ISR 中捕获对 MUTEX 的使用。但是,我没有使用 MUTEX,我使用的是 BinarySemaphore ! FreeRTOS FAQ 本身鼓励您使用 Semaphores 或 BinarySemaphores 在 ISR 和 Task 之间进行同步。这就是我正在做的事情。但是二进制信号量仍然被检测为导致此问题的 MUTEX。我什至尝试从 STM32CubeMX RTOS 配置中禁用 MUTEX,但它仍将其检测为 MUTEX 并崩溃。

Binary semaphores for FreeRTOS real time embedded software applications

二进制信号量和互斥量非常相似,但有一些微妙之处 区别:互斥体包括优先级继承机制,二进制 信号量没有。这使得二进制信号量成为更好的选择 实现同步(任务之间或任务与 中断),互斥锁是实现简单的更好选择 相互排斥。

我正在使用带有 STM32F429ZIT6 的 NUCLEO-F429ZI 板, CubeMX 版本:4.27.0, 固件包名称及版本:STM32Cube FW_F4 V1.21.0

代码:

主要功能:

int main(void)
{
  /* USER CODE BEGIN 1 */

    for(int i=0;i<360;i++) {
        sine_wave_array[i]=sin(i/180.0 * 3.1416)*1900 + 1900 + 100;

        if(sine_wave_array[i]<0) {
            sine_wave_array[i]=0;
        } else if(sine_wave_array[i]>=4096){
            sine_wave_array[i]=4095;
        }
    }

    //Initialize HMI struct
    memset(&hmi,0,sizeof(hmi));


  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  MX_UART4_Init();
  MX_UART5_Init();
  MX_DAC_Init();
  MX_TIM6_Init();
  MX_SPI1_Init();
  MX_I2C1_Init();
  MX_ADC3_Init();
  MX_USB_OTG_HS_PCD_Init();
  MX_USART3_UART_Init();
  MX_SPI4_Init();
  MX_I2C2_Init();
  MX_CAN1_Init();
  MX_RTC_Init();
  MX_TIM3_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */




    HAL_ADC_Start_DMA(&hadc3,adcData,ADC_CHANNEL_COUNT);
    __HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);

    // Setting IRQ priority for UART4
    HAL_NVIC_SetPriority(UART4_IRQn, 15, 15);
    HAL_NVIC_SetPriorityGrouping(0);


  /* USER CODE END 2 */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */


  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  semaphore_id_uart4_rx = osSemaphoreCreate(osSemaphore(semaphore_uart4_rx), 1);
  semaphore_id_uart5_rx = osSemaphoreCreate(osSemaphore(semaphore_uart5_rx), 1);
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  osThreadDef(LWIPTask_, LWIPTask, osPriorityNormal, 0, 1024);
  LWIPTaskHandle = osThreadCreate(osThread(LWIPTask_), NULL);

  osThreadDef(USBTask_, USBTask, osPriorityNormal, 0, 512);
  USBTaskHandle = osThreadCreate(osThread(USBTask_), NULL);


  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */


  /* Start scheduler */
  osKernelStart();

  /* We should never get here as control is now taken by the scheduler */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

ISR:

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
   uint32_t isrflags   = READ_REG(huart->Instance->SR);
   uint32_t cr1its     = READ_REG(huart->Instance->CR1);
   uint32_t cr3its     = READ_REG(huart->Instance->CR3);
   uint32_t errorflags = 0x00U;
   uint32_t dmarequest = 0x00U;

   if ((isrflags & USART_SR_IDLE) != RESET) {
        HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
        volatile uint32_t tmp; /* Must be volatile to prevent optimizations */
        tmp = huart->Instance->SR; /* Read status register */
        tmp = huart->Instance->DR; /* Read data register */
        HAL_UART_IdleCallback(huart);
    }

  /* If no error occurs */
  errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
  if(errorflags == RESET)
  {
    /* UART in mode Receiver -------------------------------------------------*/
    if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
    {
      UART_Receive_IT(huart);
      return;
    }
  }  

  /* If some errors occur */
  if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
  {
    /* UART parity error interrupt occurred ----------------------------------*/
    if(((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_PE;
    }

    /* UART noise error interrupt occurred -----------------------------------*/
    if(((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_NE;
    }

    /* UART frame error interrupt occurred -----------------------------------*/
    if(((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_FE;
    }

    /* UART Over-Run interrupt occurred --------------------------------------*/
    if(((isrflags & USART_SR_ORE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
    { 
      huart->ErrorCode |= HAL_UART_ERROR_ORE;
    }

    /* Call UART Error Call back function if need be --------------------------*/    
    if(huart->ErrorCode != HAL_UART_ERROR_NONE)
    {
      /* UART in mode Receiver -----------------------------------------------*/
      if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
      {
        UART_Receive_IT(huart);
      }

      /* If Overrun error occurs, or if any error occurs in DMA mode reception,
         consider error as blocking */
      dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
      if(((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
      {
        /* Blocking error : transfer is aborted
           Set the UART state ready to be able to start again the process,
           Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
        UART_EndRxTransfer(huart);

        /* Disable the UART DMA Rx request if enabled */
        if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
        {
          CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);

          /* Abort the UART DMA Rx channel */
          if(huart->hdmarx != NULL)
          {
            /* Set the UART DMA Abort callback : 
               will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
            huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
            if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
            {
              /* Call Directly XferAbortCallback function in case of error */
              huart->hdmarx->XferAbortCallback(huart->hdmarx);
            }
          }
          else
          {
            /* Call user error callback */
            HAL_UART_ErrorCallback(huart);
          }
        }
        else
        {
          /* Call user error callback */
          HAL_UART_ErrorCallback(huart);
        }
      }
      else
      {
        /* Non Blocking error : transfer could go on. 
           Error is notified to user through user error callback */
        HAL_UART_ErrorCallback(huart);
        huart->ErrorCode = HAL_UART_ERROR_NONE;
      }
    }
    return;
  } /* End if some error occurs */

  /* UART in mode Transmitter ------------------------------------------------*/
  if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
  {
    UART_Transmit_IT(huart);
    return;
  }

  /* UART in mode Transmitter end --------------------------------------------*/
  if(((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
  {
    UART_EndTransmit_IT(huart);
    return;
  }
}

从 ISR 调用的函数:

void HAL_UART_IdleCallback(UART_HandleTypeDef *huart) {
    HAL_UART_RxGenericCallback(huart,3);
}

void HAL_UART_RxGenericCallback(UART_HandleTypeDef *huart,int type) {

    if(type ==3) {

        if(UART4 == huart->Instance) {
            end4 = huart->RxXferSize - __HAL_DMA_GET_COUNTER(huart->hdmarx);
            osSemaphoreRelease(semaphore_id_uart4_rx);
        } else if (UART5 == huart->Instance) {
            end5 = huart->RxXferSize - __HAL_DMA_GET_COUNTER(huart->hdmarx);
            osSemaphoreRelease(semaphore_id_uart5_rx);
        }
    }

    return;
}

【问题讨论】:

  • 你能展示一下你是如何创建这个信号量的吗?一般来说,如果您提供最小、完整和可验证的示例会更好。
  • 显示 您的 代码而不是 RTOS 代码。我们知道 RTOS 之一,并且错误不仅仅存在于 您的代码
  • 添加代码 sn-ps

标签: arm stm32 freertos cmsis


【解决方案1】:

在中断中,您需要使用..FromISR 函数或宏,例如

xSemaphoreTakeFromISR()xSemaphoreGiveFromISR() 等等等等

您还需要设置正确的中断优先级,否则您将陷入不断的停顿和 HF。

【讨论】:

  • xSemaphoreTakeFromISR()、xSemaphoreGiveFromISR() 等是 FreeRTOS 函数。我正在使用 CMSIS 包装器,它反过来正确调用这些 FreeRTOS 函数。
  • 对于中断优先级,这是我正在使用的: // 设置 UART4 的 IRQ 优先级 HAL_NVIC_SetPriority(UART4_IRQn, 15, 15); HAL_NVIC_SetPriorityGrouping(0);
  • 在调用堆栈中,我可以看到正在调用 FromISR() 函数。
  • 我会建议 - 不要使用这个 CMSIS“扩展”。坚持使用 freeRTOS API。
猜你喜欢
  • 2021-09-23
  • 2018-08-08
  • 2021-09-21
  • 1970-01-01
  • 2019-02-26
  • 2018-07-14
  • 2017-04-07
  • 2021-09-12
  • 2018-07-24
相关资源
最近更新 更多