cancel
Showing results for 
Search instead for 
Did you mean: 

FreeRTOS STM32 tick

Luca Davidian
Associate
Posted on February 20, 2017 at 12:26

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 #tick
3 REPLIES 3
Posted on February 20, 2017 at 14:58

>>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?

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Nesrine M_O
Lead II
Posted on February 20, 2017 at 15:05

Hi

luca

,

  1. A set of application under the STM32F4 firmware package using

    FreeRTOS may help you :

    STM32Cube_FW_F4_V1.0\Projects\STM32469I_EVAL\Applications\FreeRTOS
  2. Have a look alos to

    http://www.st.com/content/ccc/resource/technical/document/user_manual/2d/60/ff/15/8c/c9/43/77/DM00105pdf/files/DM00105pdf/jcr:content/translations/en.DM00105pdf

    user manual about Developing Applications on STM32Cube with RTOS

-Nesrine-

dechawat
Associate II
Posted on February 20, 2017 at 18:49

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();

  }

}