2017-02-20 03:26 AM
Hi, I'm trying to use FreeRTOS with a STM32F401RE Nucleo64 board. I have all the project files in place and the project compiles fine. But I'm trying to use the HAL_Delay() routine from the Cube HAL but I'm running into some problems. I inserted the HAL_IncTick() call before the SysTick handler from FreeRTOS and initialized the MCU with HAL_Init() and configured the clock in a function that I call before starting the scheduler (updating the SystemCoreClock variable). Now, if I call HAL_Delay() before starting the scheduler the program ends up in HardFault handler, while if I make the call after the scheduler has started (in the task) it does not. Now, I think that the variable that is updated bu HAL_IncTick() in the handler is not interfering with the FreeRTOS time base (even if they share the SysTick). Why is it so? Here's my code:
int main(void)
{ HAL_Init(); // calls HAL_MspInit(),sets NVIC priority grouping and enable SysTick (HAL base time) SystemClock_Config(); UART_Init(&uart2_handle,USART2,115200,1024); Nunchuck_Init(); xTaskCreate(&DisplayTask,'display task',500,NULL,1,&displayTaskHandle); xTaskCreate(&NunchuckTask,'nunchuck task',500,NULL,1,&nunchuckTaskHandle); vTaskStartScheduler(); while (1) { }}void SystemClock_Config(void)
{ // configure and enable clock source RCC_OscInitTypeDef osc_config; osc_config.OscillatorType = RCC_OSCILLATORTYPE_HSI; osc_config.HSIState = RCC_HSI_ON; osc_config.PLL.PLLSource = RCC_PLLSOURCE_HSI; osc_config.PLL.PLLState = RCC_PLL_ON; osc_config.PLL.PLLM = 8; osc_config.PLL.PLLN = 84; osc_config.PLL.PLLP = RCC_PLLP_DIV2; osc_config.PLL.PLLQ = 7; HAL_RCC_OscConfig(&osc_config);// select clock source, update SystemCoreClock and set flash wait states
RCC_ClkInitTypeDef clk_config; clk_config.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; clk_config.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; clk_config.AHBCLKDivider = RCC_HCLK_DIV1; clk_config.APB1CLKDivider = RCC_HCLK_DIV2; clk_config.APB2CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&clk_config,FLASH_LATENCY_0); // updates SystemCoreClock}// FreeRTOS tasks
void DisplayTask(void *parameters){ ST7735_Init(); UART_Write(&uart2_handle,'UART ready\r\n'); ST7735_Print('STM32 serial monitor\n\n',ST7735_Color565(0,255,200)); char charbuf[100],*p; while (1) { p = &charbuf[0]; do { *p = UART_Receive(&uart2_handle); } while (*p++ != '\r'); *--p = '\0'; ST7735_Print(&charbuf[0],ST7735_Color565(255,255,255)); }}void NunchuckTask(void *parameters)
{ Nunchuck nunchuck; while (1) { Nunchuck_Update(&nunchuck); }}#freertos #stm32 #tick2017-02-20 05:58 AM
>>I inserted the HAL_IncTick() call before the SysTick handler from FreeRTOS
What does this mean? What does the SysTick_Handler actually look like? Is it calling FreeRTOS functions with structures that may not have been initialized yet? Could you use a flag like FreeRtosUp and put an if (FreeRtosUp) around that other code?
2017-02-20 06:05 AM
Hi
luca
,FreeRTOS may help you :
STM32Cube_FW_F4_V1.0\Projects\STM32469I_EVAL\Applications\FreeRTOS-Nesrine-
2017-02-20 09:49 AM
If your systick handler look like this
void SysTick_Handler(void)
{ HAL_IncTick(); xPortSysTickHandler();}it's because xPortSysTickHandler is called before
vTaskStartScheduler.
If you call HAL_Delay() in task, in main function HAL_Init will initialize Systick interrupt, but CPU can arrive at vTaskStartScheduler function before the first tick interrupt.
If you call HAL_Delay() before
vTaskStartScheduler, CPU will struct at HAL_Delay and then the first tick interrupt will happen.
If you want to use HAL_Delay() before
vTaskStartScheduler, you need to check scheduler state before call xPortSysTickHandler
void SysTick_Handler(void)
{ HAL_IncTick(); if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { xPortSysTickHandler(); }}