FreeRTOS and interrupts

I have a function that reads data from CANBus that works ok without RTOS but as soon as it is activated the interrupt routine is never entered again. I have a general timer interrupt that works ok. Any ideas?
I have RX0 interrupt enabeled. Here is the callback for CAN Rx:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
	//GPIOC->ODR ^= (1<<13);
 	HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxHeader, RxMailbox); //Receive CAN bus message to RxMailbox buffer
 	CANFlag = 1;

Here is the CAN wait loop that will never be exited, it is called from a task:


  uint32_t tickstart =  HAL_GetTick();		// Setup timeout for waiting reply
  uint32_t wait =  100;
  uint8_t flag = 0;

  while((HAL_GetTick() - tickstart) < wait){


	 __disable_irq();			// Read receive flag
	  flag = CANFlag;

	  if (flag ==1 && RxMailbox[0] == Tx[0] && RxMailbox[1] == Tx[1] ){ // We got reply, check if the reply is for the same command

              // DATA HANDLING///

		return  flag;
	  } else {
		  flag = 0;
		  {}	//nop
  return flag;	// Timeout, no reply

How are the variables tickStart and wait used? Could it be that the while loop never rubs after first invocation?

I updated the code to include the definitions. Indeed it also seems this loop never exits like it is supposed to when 100ms is up.

well, now you have the problem, it should be easy to nail down… may be an optimization issue. Or a problem with the HAL timer not incrementing, eg due to disabled interrupts. Do not use the HAL, it does nothing but cause headaches.

Why do you use both osdelay and HAL_Delay in the same function, btw?

CANFlag is volatile, right ? Otherwise the code is broken and may or may not work.
Why not starting with a working FreeRTOS based demo and migrate your code into it ?
Could be a more successful approach getting more familiar with FreeRTOS applications.

Hey @tarmogr, sorry to hear that you’re having some issues with not exiting your interrupt callback.
I’ve got some questions about the code that you’ve shared
Is the HAL_CAN_RxFifio0MsgPendingCallback() being correctly called from the IRQ itself? Or do you have an IRQ handler that is calling it? And have you verified if you’re correctly returning back to your task after entering that callback?

I know that the STM32F412 Discovery kit integrates a Cortex-M4, where is your project using the FreeRTOS port for that chip? If it is a first thought looking at this would be that the HAL_GetTick() might not be compatible with the FreeRTOS Tick Handler? If you are you probably should be using vTaskDelay() instead of osDelay(). And should also be using either taskENTER/EXIT_Critical() to enable and disable IRQs instead of the raw calls.

As @hs2 pointed out you may need to set CANFlag, and flag to volatile to ensure that they get updated correctly on use.

Additionally, how large is the PACKETMARGIN delay value? Could you potentially be delaying for too long in there? And what is the difference between HAL_Delay() and osDelay()? Lastly, is osDelay() supposed to only be delaying for a single system tick? Or is it a longer operation?

Thr HAL_CAN_RxFifio0MsgPendingCallback() is supposed to be called by the code that is generated by STMCubeMX. And indeed it is called without using OS. I have verified that this function is actually never called when using OS.

I will do that but it seems the code never gets to set the flag in the first place.

Packetmargin is about 20ms. HAL_Delay() seems to be working fine inside task. Bear in mind this code is migrated from non OS project so regarding HAL_Delay() yes I need to replace them all eventually. The reason I used osDelay() is that to my understanding this function notifies OS so that it can exit the task if needed to do other things, including servicing the interrupt(?). osDelay(1) is 1 millisecond delay.

One sidenote. Initially the HAL_GetTick did not increment at all, whenever HAL_Dealy was called the code got stuck. I increased the system tick priority from 15 to 0 and it started incrementing. But the problems stated above still exist.

There is a fundamental tension between FreeRTOS’s tick and the HAL tick. FreeRTOS wants its tic to be low priority (high value), Ike 15, while HAL wants a high priority tic, as some of their ISR routine wait for it to happen. If you must use both, you need to move one of them off of the systick, and make them use different interrupts.

Prioritu 0 is a BAD priority to use, as it has special meaning, use priority 1 at most.

Change the HAL tick to some other timer than SysTick. You can do that in the GUI by going to “System Core → Sys → Timeabase Source”:

Hey @tarmogr, wanted to ask if you’re still seeing issues with this or if you’ve found a solution to your problem?