RTOS port crash and restart

markwrichardson wrote on Thursday, June 20, 2013:

I DL’d user port for eZ80 that seems based on 5.0.0.  I added the 7.4.2 modules.

I didn’t spend too much time testing ver 5, it seemed to work so I moved to 7.4.2.  I will go back to 5 and retest soon.

My problem is that sometimes my RTOS + blinking light task demo starts up and runs fine.  Other times, I have to restart it a few times (from 1 to 7 so far) and then it runs fine.   Fine, meaning for days without a restart.

I’m guessing I have a race condition somewhere.  It crashes after running vTaskStartScheduler() and a few tasks.  I’ve been stepping along looking for clues.  I’m out of ideas for targeting my search.  I plan to do a few stepping marathons soon looking for clues.

Do you have any suggestions off the top of your head.

Thanks

edwards3 wrote on Thursday, June 20, 2013:

If the original port does not have the same problem then look through http://www.freertos.org/History.txt for changes between V5.x x and V6.x.x, then between V6.x.x and v7.x.x.

I din’t think there should be anything significant there. The only major compatibility change was between 4.x.x and 5.x.x, but worth looking.

markwrichardson wrote on Wednesday, June 26, 2013:

I finally narrowed down the issue to this simple stub:

void vApplicationIdleHook( void )
{
//    vCoRoutineSchedule();
	
	if (ulIdleCycleCountL == 0L)
	{
		ulIdleCycleCountH++;
		ulIdleCycleCountL++;
	}
	else
	{
		ulIdleCycleCountL++;
	}
}

By commenting out vCoRoutineSchedule(), RTOS will run days with out a restart.  With this line active I can sometimes get the code to run after a few restarts as I mentioned above.

I’ve been looking at the 2 PDF docs and online and haven’t seen any mention of prerequisite initialization.  In this demo app, there are no coroutinesregistered.  The only reference to coroutine is this one.

The demo app is basically the one present in the eZ80 user contributed port except for my own LED port assignments.

edwards3 wrote on Wednesday, June 26, 2013:

If you are not using coroutines then the line should not be there anyway, so just leave it commented out.

markwrichardson wrote on Wednesday, June 26, 2013:

I do plan to use them for my project.  I’m evaluating a non-supported port of RTOS for the Zilog eZ80.  There was a customer contribution file for this port on the website as of version 5.0.0.  I’m starting small evaluating the stability and correctness of the user supplied port code.  I will continue enhancing the demo with simple uses of the features I plan to use and retain it as a baseline.  When I reach my project testing phase, I plan to offer that baseline as a user contribution.

markwrichardson wrote on Thursday, June 27, 2013:

Judging by Example 7 on pg 38 of the Using the FreeRTOS guide it seems that vApplicationIdleHook() won’t be multithreaded.  However, in my spartan sample unless the simple increment is atomic the addition is erratic.  My processor can’t do atomic long addition, only 3-byte int.  So by surrounding my increment code with DI/EI I’m able to get predictable responses.

Does vApplicationHook() have the potential to be called by each distinct occurrence of vTaskDelay() being used in each seperately running task when preemption is enabled ?

davedoors wrote on Friday, June 28, 2013:

vApplicationIdleHook() is only ever called from the Idle task. I think the Z80 is 8 bits, so 32 bit additions will probably be done in four or more steps, with intermediate results held in registers or on the stack (I don’t know how many registers the Z80 has but guess not many). If the addition is sometimes getting the wrong answer then it is likely that the intermediate values are being corrupted. If the values are on the stack then it could be a simple RAM corruption. If the intermediate values are in registers then it seems the context switch is not working properly.

markwrichardson wrote on Friday, June 28, 2013:

I had wondered about the context switch and will check that again next.

The eZ80 is an ‘enhanced’ Z80.  Just some background for you . .  a Z180 was created from the Z80 with 16 bit registers and a paged memory manager.  It was a proper superset of the Z80 and invited binary porting to a 1MB memory space. . .  the eZ80 was another derivative of the Z80 with 24 bit registers and a full 16MB memory space with no paging required.  It was also a superset of the Z80.

My last post was because I had added a single byte increment during entry and decrement at exit.  Both are a single instruction opcode.  The code below, before I added the DI / EI, led me to the conclusion of a multi thread issue. 

unsigned long AIDtotal = 0;
unsigned int ulIdleCycleCountL = 0;
unsigned int ulIdleCycleCountH = 0;
unsigned char AIDcnt = 0;	
void vApplicationIdleHook( void )
{
//	vCoRoutineSchedule();
	
	asm( "DI" );
	
	AIDcnt ++;
	
	if (AIDcnt > 2)
	{
		asm("nop");
		asm("nop");
		asm("nop");
			
		asm("nop");  // breakpoint
			
		asm("nop");
		asm("nop");
		asm("nop");
		
		AIDtotal ++;
	}
	
	if ( ulIdleCycleCountL == (unsigned int)0xFFFFFF )
	{
		asm("nop");
		asm("nop");
		asm("nop");
		ulIdleCycleCountH++;   // original was breakpoint here 
		asm("nop");
		asm("nop");
		asm("nop");
		ulIdleCycleCountL = (unsigned int)0 ;
	}
	else
	{
		ulIdleCycleCountL =  ulIdleCycleCountL + 1;
	}
	AIDcnt --;
	
	asm( "EI" );
}

Thanks for the reminder to double check the context switch.  I’ll do that again. 

My question in response 6 was because I didn’t think that AIDcnt could become more than ‘1’ unless preemption occurs and another instance of thread through this function has occurred.