Kernel thinks I exited a task

static void prvTaskExitError(void) is called.

I am running v10.0.0 on an ARM cortex m4+ in Atmel studio.
I have no interrupts.
Polling RTC Mode 2 calendar in one task and polling key presses in another.
The condition causing it is outlined below, but there is no condition that would cause the task to exit.

In a certain condition (working a clock set key) I set a global and that global prevents the other task from acting on the calendar time update, but it clears the flag. All it was doing was updating the LCD. The assert looks like it could come from unbalanced enter/exit critical sections but (a) they are all balanced and (b) they are not being called because I deactivated the few code blocks that needed anything.

The tick hook is my only interrupt. The only action it is taking is to strobe the common and segment lines on a 4 char, 7 segment LCD. As noted below, there is a single read of a shared value:
uint8_t AtomicCachedSegments = LCD_Segment_Data[idxChar]; // caching the character allows us not to use a Mutex

I have disabled the other actions on calendar to isolate my issue.

if adjust key is presses, the system enters time set mode and sets the global. If they key is held, the field is changed. If it released and pressed again the next field is selected. If the key is held long enough in any field, the call to SetCharacter() is causing a problem.

						switch (TimeSetState)
						{
							case TS_MONTH_CHARS:
							tsLocalNow.bit.MONTH++;
							if (tsLocalNow.bit.MONTH > 12) // 1-12
							tsLocalNow.bit.MONTH = 1;
							SetCharacter(0, '0'+tsLocalNow.bit.MONTH/10, false);
							SetCharacter(1, '0'+tsLocalNow.bit.MONTH%10, true);
							break;
							
							case TS_DAY_CHARS:
							tsLocalNow.bit.DAY++;
							if (tsLocalNow.bit.DAY > Days[tsLocalNow.bit.MONTH]) 
							tsLocalNow.bit.DAY = 1;
							SetCharacter(2, '0'+tsLocalNow.bit.DAY/10, false);
							SetCharacter(3, '0'+tsLocalNow.bit.DAY%10, true);
							break;
							
							case TS_HOUR_CHARS:
							tsLocalNow.bit.HOUR++;
							tsLocalNow.bit.HOUR=tsLocalNow.bit.HOUR % 24;
							SetCharacter(0, '0'+tsLocalNow.bit.HOUR/10, false);
							SetCharacter(1, '0'+tsLocalNow.bit.HOUR%10, false);
							break;
							
							case TS_MIN_CHARS:
							tsLocalNow.bit.MINUTE++;
							tsLocalNow.bit.MINUTE = tsLocalNow.bit.MINUTE % 60;
							SetCharacter(2, '0'+tsLocalNow.bit.MINUTE/10, false);
							SetCharacter(3, '0'+tsLocalNow.bit.MINUTE%10, true);
							break;
							
							default:
							break;
						}

prvTaskExitError(void) is on the configAssert.
Stack says that SetCharacter() ‘called’ it.

void SetCharacter(uint8_t idx, uint8_t char1, bool dpt)
{
	if (idx >= NUMBER_CHARS) return;
	
	uint8_t segments = SegmentFromCharacter (char1); <<<<<

it is just a long case statement converting ascii to 7 segment

uint8_t SegmentFromCharacter (uint8_t char1)
{
	switch (char1)
	{
		case '0': return 0b11111100;  // msb is a...lsb is dpt   coms are 3 2 1 0 1 2 3 0 and lines are 1 1 1 0 0 0 0 1
		case '1': return 0b01100000;  // abcdefgp
		case '2': return 0b11011010;
	

Ultimately the character’s segments are put into LCD_Segment_Data[]. The only place this is used is in the tick hook timer, which atomically grabs the value and then stobes the segments on the display LCD.

Sounds like you already have configASSERT() defined. You may want to update to the latest FreeRTOS version, which should be a drop in replacement, as it contains more configASSERTS()s that check for misconfigurations. Are you also doing the other things on this page https://www.freertos.org/FAQHelp.html such as checking for stack overflows?

You already got me past the hard faults and I have no user defined IRQ/ISR.

I doubled stack and heap sizes to no avail and i do have a stack overflow hook, but I am not actively testing the high water mark. The only thing left to deactivate is the calendar task, but at this point all it does is clear the status flags for the alarms (minute and hour, none enabled for interrupts). Likely it is a task swap fault though.

I will try updating later (ie tomorrow).

Tasks are created as:

void FREERTOS_V1000_0_example(void)
{
BaseType_t success = xTaskCreate(Switches_task, “Switches”, TASK_EXAMPLE_STACK_SIZE, NULL, TASK_EXAMPLE_STACK_PRIORITY, xCreatedExampleTask);

success &= xTaskCreate(CALENDAR_task, "Calendar", TASK_EXAMPLE_STACK_SIZE, NULL, TASK_EXAMPLE_STACK_PRIORITY, xCreatedExampleTask);

if (success == pdTRUE)
{
	LCD_MODE (GPIO_DIRECTION_OUT);
	vTaskStartScheduler();
}

LCD_MODE (GPIO_DIRECTION_IN);
return;

}

After a night’s sleep I found a condition where the calendar task was returning (meant to skip the rest of loop)… Sometimes the best debugging is to walk away and refresh.

Thanks for taking the time to report back.

It’s the least anyone could do given how well you support everyone!