SysTick_Handler() not called after entering the first task

For some reason SysTick_Handler() doesn’t get called after prvPortStartFirstTask(). More specifically, it stops being called somewhere after the first call to xPortPendSVHandler() and actually switching to the first task.

This doesn’t happen if I don’t include one of the main tasks, but I can’t narrow it down any further.

Here’s how it’s initialized:

...

const size_t task_stack_depth_bytes = 5000;
const uint32_t task_stack_depth_words = task_stack_depth_bytes / 4;
StackType_t task_stack_buffer[task_stack_depth_words] = { 0 };
StaticTask_t task_tcb;
TaskHandle_t task_handle;
static void task_task(void* arg);

void setup() {
  task_handle = xTaskCreateStatic(task_task, NULL, task_stack_depth_ints, NULL, 1, task_stack_buffer, &task_tcb);

...

PREFETCH_ENABLE is set to 0, so it shouldn’t be anything related to a HW bug that’s present in my MCU.

Going through the FAQ:

SysTick_Handler() gets called initially, and FreeRTOSConfig_Default.h has the right lines:

#define vPortSVCHandler    SVC_Handler
#define xPortPendSVHandler PendSV_Handler

so its not point #1.

It’s not a stack overflow since I’ve set configCHECK_FOR_STACK_OVERFLOW and the tasks have more than enough memory. So its not point #2.

I am allocating the tasks statically and the buffers are in global space. So it’s not point #3.

When entering the first task, uxCriticalNesting is equal 0, and NVIC_INT_CTRL_REG has the same value as before calling the scheduler, so I’m pretty sure, but not certain, that it’s not point #4.

I’m not using any dynamical memory at all (and _sbrk() never gets called), so it’s not point #5.

None of my interrupts are called before the first task, so not #6.

CONTROL->nPRIV == 0 when the scheduler gets called, so not #7.

Board: STM32F407VG (Rev A) Disco (MBB997 B-00)
IDE: PlatformIO, Arduino as a Framework

I believe the Arduino framework has a Systick_handler() on the STM32. Do you think the Framework and the FreeRTOS are conflicting and shutting down the interrupt?

Don’t think so.

The arduino framework has SysTick_Handler() in clock.c and here’s how the calls cascade:

SysTick_Handler() in clock.c
	HAL_IncTick() callback in main.cpp
	HAL_SYSTICK_IRQHandler()
		HAL_SYSTICK_Callback() (empty)
	osSystickHandler() in cmsis_os.c
		xPortSysTickHandler() in port.c
			xTaskIncrementTick() in tasks.c

What are you doing in this task?

It is not recommended to use the SysTick to drive ST Hal Tick when you are using FreeRTOS. Is it possible to use any other Timer to drive HAL Tick?

Also, what is the priority of SysTick? Is it at or below configMAX_SYSCALL_PRIORITY?

Thanks.

I’ve switched to driving HAL_Tick with Timer 1, didn’t help.

But I think the problem really is within the main task. The issue I have is that I have two sensors, one with it’s own task. Here’s how they look.

void measure_task(void) {
  
  //taskENTER_CRITICAL();

  // Initialization
  sensor.begin();
  sensor.off();

  sensor.InitSensor(SENSOR_ADDRESS);  // Communicate over I2C
  sensor.SetTuningParameter(1000);
  sensor.SetTimingBudget(30000);
  sensor.SetDistanceMode(DISTANCEMODE_SHORT);
  
  sensor.StartMeasurement();  // Communicate over I2C

  //taskEXIT_CRITICAL();

  while (1) {
    vTaskSuspend(NULL); // Wait for the interrupt

    // Receive measurements

    ...
}

I need to have the initialization part of the function protected, because the sensors are sharing the I2C peripheral, and the order of operations is important.

It seems like my first attempt at doing that with taskENTER_CRITICAL() / taskEXIT_CRITICAL() was heavy handed and is what caused this problem. It probably need interrupts enabled to finish the sensor.InitSensor(SENSOR_ADDRESS) call and something like a mutex would be a better solution here.

I am glad to hear things are working better.