Requesting inputs about amount of execution time per task and preventing Task Priority inversion

Hello,

I am porting a legacy code to FreeRTOS (version 10.2.1 with CMSIS-RTOS version 2.0). I am using STM32H753BIT6 revision V microcontroller.

Concern 1:

I need help with finding FreeRTOS equivalents for RTXC (RTOS) APIs KS_defslice() and KS_defres().

As per RTXC document:

  1. The KS_defslice kernel service defines the amount of time the specified task is permitted to run before it is forced to yield in a time-sliced scheduling situation.

  2. The KS_defres kernel service defines the priority inversion attribute of the specified resource. This attribute determines if an attempt to lock a resource can result in a priority inversion and if RTXC is to handle the inversion. When enabled by ON as the condition, the attribute will cause RTXC to check for a priority inversion if an attempt to lock the resource fails. When the attribute is disabled, no such checking.

Concern 2:

After I ported three tasks and some timers from RTXC (RTOS) to FreeRTOS (with Fixed Priority Preemptive scheduling), I am observing that the lower priority task starts to execute even when the higher priority task was not blocked. I am not sure of the reason for this.
I had expected /wanted that task T_TaskEventHandler() (being the highest priority task which being *osPriorityNormal2 out of the three tasks) would have executed until the below line gets executed:

Event = xEventGroupWaitBits(H_EvtGrp_Event, dWaitForAnyBit, pdTRUE, pdFALSE, portMAX_DELAY);

I have added my test code to project present in folder FreeRTOS\Demo\Win32-MSVC . Once the project starts to execute as expected I will merge the working code to my STM32H753 project.

Below is the variable declaration that I use:

osThreadId TaskEventHandler_ThreadId, CAN_ThreadId, GatewayMain_ThreadId;

Below is the initialization that I use inside main()

	osThreadAttr_t EventTaskAttributes = {
		.name = "EVENTHANDLERTASK",
		.priority = (osPriority_t)osPriorityNormal2,
		.stack_size = configMINIMAL_STACK_SIZE * sizeof(StackType_t)	// The osThreadNew() assumes the base unit as byte, where as xTaskCreate() uses sizeof(StackType_t) as the base unit.
	};
	TaskEventHandler_ThreadId = osThreadNew(T_TaskEventHandler, NULL, &EventTaskAttributes);

	osThreadAttr_t CAN_Attributes = {
		.name = "CANTASK",
		.priority = (osPriority_t)osPriorityNormal1,
		.stack_size = configMINIMAL_STACK_SIZE * sizeof(StackType_t)	// The osThreadNew() assumes the base unit as byte, where as xTaskCreate() uses sizeof(StackType_t) as the base unit.
	};
	CAN_ThreadId = osThreadNew(T_CAN, NULL, &CAN_Attributes);

	osThreadAttr_t GatewayAttributes = {
		.name = "GATEWAYMAINTASK",
		.priority = (osPriority_t)osPriorityNormal,
		.stack_size = configMINIMAL_STACK_SIZE * sizeof(StackType_t)	// The osThreadNew() assumes the base unit as byte, where as xTaskCreate() uses sizeof(StackType_t) as the base unit.
	};
	GatewayMain_ThreadId= osThreadNew(T_GatewayMain, NULL, &GatewayAttributes);

	vTaskStartScheduler();
	for (;;);

I assume using code similar to below in all three task functions will be an overkill:

EventBits_t uxReturn = xEventGroupSync(H_EvtGrp_Sync_3_Tasks, dSyncEventHandleTask, dAllThreeTasksSync, portMAX_DELAY);

The CAN Task and Gateway Main task have timer related implementation as shown below (followed by a while(1) { ...<code here>... }):

	TimerHandle_t H_RC_LED_OneShot = xTimerCreate("RC_LEDONESHOTEVENT", pdMS_TO_TICKS(dRC_LED_OnPeriod), pdFALSE, (void*)RC_LEDONESHOTEVENT, rvRC_LED_OneShotHandler_Signal);
	xTimerStart(H_RC_LED_OneShot, 0);

which is replacement for:

`L_RC_LED_OneShot = KS_start_timer(NULL, dRC_LED_OnPeriod, 0, RC_LEDONESHOTEVENT);`

and

	EventBits_t uxBits = xEventGroupClearBits(H_EvtGrp_Event, 1 << UPDATEDANV);
	if (uxBits & (1 << UPDATEDANV))
	{
		assert_failed((uint8_t *)__FILE__, __LINE__);
	}

which is replacement for:

KS_pend(UPDATEDANV);

Please help.

Thanks and regards,
Rajeev

I forgot to share below information:

void rvRC_LED_OneShotHandler_Signal(TimerHandle_t xTimer)
{
	xTimer = xTimer;
	xEventGroupSetBits(H_EvtGrp_Event, 1UL << RC_LEDONESHOTEVENT);
}

The RTXC does not need this implementation as it uses KS_start_timer() which uses semaphore RC_LEDONESHOTEVENT and triggers execution of function dRC_LED_OnPeriod() when the time period expires.

For priority inversion concerns, FreeRTOS handles this with the Mutex.

FreeRTOS also support round-robin time-slicing between tasks of the same priority, using a 1 tick period.

FreeRTOS, if set to be preemptive, will always be running one of the highest priority ready tasks. (and highest priority is after any priority adjustment from mutexes detecting an inversion).

I find the code a bit hard to understand, as you are using a third-party wrapper that changes some of the concepts.

Note, that moving from one OS to another always has some issues, as they have different feature sets, and you designed the original application for the feature set of the OS you started with. For example, if this timer is to wake up one single task, then I would NOT use an EventGroup, but a direct-to-task notification (which might not be in the OS Wrapper, but then it is the WRAPPERS limitation, not FreeRTOS). If you had originally written the app with CMSIS for RTXC (if that exists), then the port to FreeRTOS would likely be easier, as that is what CMSIS was designed to do, but it also says that you are limiting yourself to the lowest common denominator features.

Hello @richard-damon ,

Please suggest whether I must post my second Query / Concern to “Partners & Sponsors ST” forum (as the CMSIS rappers were provided as a part of the code that was generated with help of STM32CubeMX)?

Is there a way to change the category of this thread?

Please suggest.

Regards,
Rajeev

How are you observing that?

Just making sure you know: In FreeRTOS priority 1 is higher than priority 0.

Dear @rtel ,

I was using the CMSIS_OS.C and other files copied from CMSIS (version 1) folder.

I am aware that higher the priority number used, greater will be the Task’s priority (when compared to other task). Thus, task with priority = osPriorityNormal2 will have higher priority over task that has priority = osPriorityNormal.

After I started to use the CMSIS version 2 I do not observe this issue.

Regards,
@rxa1031