STM32F4 SPI中断使用FreeRTOS停止触发

时间:2018-11-23 10:04:31

标签: stm32 spi freertos stm32f4

我正在尝试使用SPI在F410 MCU和RPi之间进行SPI通信。 我在当前有效的代码下面发布(不使用FreeRTOS):

main.c

volatile int tx_done = 0;
volatile int rx_done = 0;

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
    tx_done = 1;
}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
    rx_done = 1;
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_SPI5_Init();
    MX_USART2_UART_Init();

    const uint8_t BUF_SIZE = 16 * sizeof(uint8_t);
    uint8_t buf[16];

    // For UART debug
    uint8_t dbg_buffer[64];
    while (1) {
        memset(buf, 0, BUF_SIZE);
        HAL_StatusTypeDef ret = HAL_SPI_Receive_IT(&hspi5, (uint8_t*)&buf, BUF_SIZE);
        while (rx_done == 0) {};
        rx_done = 0;

        sprintf((char*) dbg_buffer, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d]\r\n",
                                    buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
                                    buf[7], buf[8], buf[9], buf[10], buf[11], buf[12],
                                    buf[13], buf[14], buf[15]);
        HAL_UART_Transmit(&huart2, dbg_buffer, strlen((char const*) dbg_buffer), 50);

        HAL_SPI_Transmit_IT(&hspi5, (uint8_t*) &buf, BUF_SIZE);
        while (tx_done == 0) {};
        tx_done = 0;    
    }
}

stm32f4xx_it.c

/**
* @brief This function handles TIM1 trigger and commutation interrupts and TIM11 global interrupt.
*/
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
  HAL_TIM_IRQHandler(&htim11);
}

/**
* @brief This function handles SPI5 global interrupt.
*/
void SPI5_IRQHandler(void)
{
  HAL_SPI_IRQHandler(&hspi5);
}

spi.c

/* SPI5 init function */
void MX_SPI5_Init(void)
{

  hspi5.Instance = SPI5;
  hspi5.Init.Mode = SPI_MODE_SLAVE;
  hspi5.Init.Direction = SPI_DIRECTION_2LINES;
  hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi5.Init.NSS = SPI_NSS_HARD_INPUT;
  hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi5.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi5.Init.CRCPolynomial = 15;
  if (HAL_SPI_Init(&hspi5) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
    [...]
    HAL_NVIC_SetPriority(SPI5_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(SPI5_IRQn);
}

这与我的另一侧(树莓派)的测试代码配合使用,可以每秒发送一个SPI帧,等待100ms并从F410读取答案。

现在,当我激活FreeRTOS时,我将while(1)循环内容移动到任务中,并使用

创建它
BaseType_t  task1 = xTaskCreate(task_1,  "task_1", 512, NULL, tskIDLE_PRIORITY, &xHandle);

和osKernelStart()。我还使用TIM11作为时基源(根据软件本身的建议,在CubeMX的SYS选项卡下)

然后,我有以下行为:如果我在两个Tx / Rx SPI中断中都放置了断点,我发现其中有两对(3-4?)被触发,然后再也不会触发。如果停止我的代码,我会发现自己陷入了

while (rx_done == 0) {};

循环,确认我不再收到SPI RX中断,而SPI总线上仍有帧。

为了深入研究该理论,我在任务中对此进行了另一项测试:

while(1) {
    memset(buf, 0, 16);

    HAL_StatusTypeDef ret = HAL_SPI_Receive_IT(&hspi5, (uint8_t*)&buf, 16);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
    // Wait for RX interrupt, task is suspended to give processing time to (incoming) others tasks
    vTaskSuspend(NULL);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
}

在我的Rx中断中,我只需调用

xTaskResumeFromISR(task1Handle);

使用此代码,STM32F4可以正确读取发送的第一个数据包,然后任务将其打印在USART2上并再次挂起。从那时起,(再检查内部是否有断点),再也不会调用Rx中断,因此任务都不会在其中继续执行,并且我的代码被冻结...

真的看起来FreeRTOS和STM32 HAL SPI /中断处理之间是一团糟吗?

任何帮助都会很高兴被接受!

1 个答案:

答案 0 :(得分:0)

您是否按照此页面上红色文字所述致电NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );https://www.freertos.org/RTOS-Cortex-M3-M4.html

  

如果将STM32与STM32驱动程序库一起使用,则通过调用NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)确保将所有优先级位分配为可抢占优先级位。在RTOS启动之前。