STM32F4 SPI interrupts stop firing with FreeRTOS - Page 1
Forum section: electronics / beginners

author: MisterPatate
author_rank: Newbie
timestamp: November 23, 2018, 11:49:58 am
content: Hello everybody !I'm trying to make an SPI communication between a F410 MCU and a RPi using SPI. I post below the code that currently works (without FreeRTOS usage):main.cCode: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;// For UART debuguint8_t dbg_buffer;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, buf, buf, buf, buf, buf, buf,buf, buf, buf, buf, buf, buf,buf, buf, buf);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.cCode:/*** @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.cCode:/* 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);}This is working fine with my test code on the other (raspberry pi) side, sending a SPI frame every second, waiting 100ms and reading the answer from the F410.Now, when I activate FreeRTOS (I used CubeMX), I move the while(1) loop content to a task, and creates it withCode:BaseType_t task1 = xTaskCreate(task1, "task1", 512, NULL, tskIDLE_PRIORITY, &xHandle);and osKernelStart(). I also use the TIM11 as Timebase Source (under SYS tab on CubeMX as advised by the software itself)Then I have the following behavior: If I place breakpoints inside both Tx/Rx SPI interrupt, I found that a couple (3-4 ?) of them are fired, then never again. If I stop my code I see I'm stucked in theCode:while (rx_done == 0) {};loop, confirming that I don't get SPI RX interrupts anymore whereas there is still frame coming on the SPI bus...To dig a little into that theory, I made another test with this in my task:Code: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 tasksvTaskSuspend(NULL);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);}and in my Rx interrupt, I simply callCode:xTaskResumeFromISR(task1Handle);With this code, the first packet sent is read correctly by the STM32F4, and task print it on USART2 and suspend itself again. From then, (checked with a breakpoint inside), the Rx interrupt is never called again, so the task resume inside neither, and my code is frozen...It really looks like there is a messing between FreeRTOS and STM32 HAL SPI/interrupt handling ?Any help will be gladly accepted !

author: MadScientist
author_rank: Frequent Contributor
timestamp: November 23, 2018, 12:02:12 pm
content: Is the smt32 Hal ( cubemx ) compatible with freeRTOS ? , I didn’t think it wasDave

author: MisterPatate
author_rank: Newbie
timestamp: November 23, 2018, 12:05:56 pm
content: It is, I configurated FreeRTOS within the CubeMX app.https://www.freertos.org/FreeRTOS-Plus/BSP_Solutions/ST/STM32Cube.html

author: AndyC_772
author_rank: Super Contributor
timestamp: November 23, 2018, 12:19:28 pm
content: It's always worth looking at the hardware registers for the peripherals involved. See how they're really set up, what's enabled and what isn't, and whether there are any error flags set which will prevent normal operation until they're cleared.For example, if a UART Rx interrupt is never called, this could be because this interrupt is disabled in the NVIC, or the UART receive IE bit isn't set, or interrupts are globally disabled, or reception is disabled due to (say) a framing error.Reading the hardware registers directly and comparing them against the descriptions in the Reference Manual is the only definitive way to tell. From there, you'll have a way to work backward and see exactly where an undesirable register change was made, and why.

author: MisterPatate
author_rank: Newbie
timestamp: November 23, 2018, 01:51:35 pm
content: Does those registers available in hspi struct ? I must use the HAL here, so just asking

author: AndyC_772
author_rank: Super Contributor
timestamp: November 23, 2018, 02:59:58 pm
content: I honestly have no idea, but even if they were, anything you get from the HAL will tell you how the hardwareshouldbe configured, not necessarily how itisconfigured.Eliminate as many sources of error as you can. By going straight to the hardware, you're able to find out definitively what's wrong, and then you can work backwards to figure out why. You'll find that the parameters you have to pass to the HAL are pretty similar to the register map anyway.

author: MisterPatate
author_rank: Newbie
timestamp: November 23, 2018, 03:11:52 pm
content: Do you have any links to the correspondant documentation ? I'm afraid I don't know where to start.

author: AndyC_772
author_rank: Super Contributor
timestamp: November 23, 2018, 03:39:24 pm
content: ST page for the STM32F410 processor:https://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f4-series/stm32f410/stm32f410c8.htmlThe Reference Manual contains all the register settings in detail:https://www.st.com/resource/en/reference_manual/dm00180366.pdfYour IDE should be able to help you here. If, for example, you think there's a problem with peripheral SPI1, you should just be able to set a watch on "SPI1" and it'll show you a structure containing all the register names and their current values. For example, the status register is called SR, and it can be read just by accessing SPI1->SR.All the register names and locations are defined in the HAL headers - which, IMHO, is the one thing they're good for.