halt in the loop in vListInsert

zhuchunxia wrote on Thursday, June 02, 2016:

I were working on porting FreeRTOSv8.2.3 to our CK610 cpu core… the
first task can work now . but it can’t switch task.
I trace it and find it halt in the loop in vListInsert function.

According to those comment , I check my code and exclude some.

  1. stack overflow does not happen by enable vApplicationStackOverflowHook trace function
  2. my code is simple enough and does not use queue ore semaphore
  3. my code is simple enough and does not use queue ore semaphore

But for case 2, I am not sure my design is okay or not . I doesn’t set
interrupt priority for my interrupt instead of disable and enable global interrupt
I disable/enable global interrupt by CPU_SR_Save() and CPU_SR_Restore() functions…
there are only timer and system software trap interrupt source…
my view seems to be good… but it really halt in the loop …
Could you help to explain ?

#define portDISABLE_INTERRUPTS()		ulPortSetIPL( 1 )
#define portENABLE_INTERRUPTS()		ulPortSetIPL( 0 )
portLONG ulPortSetIPL( portLONG x)
{
	static portLONG cpu_sr = 0x80000100;
	
	if (x)
	{
		cpu_sr = CPU_SR_Save();
	}
	else
	{
		CPU_SR_Restore(cpu_sr);
	}
	
	return cpu_sr;
}

rtel wrote on Thursday, June 02, 2016:

I think this needs to be taken one step at a time, particularly as I can’t download the datasheet for the CK610.

The first thing to check is that the task is really starting the way you expect it to be. When you created the initial stack for the task did you give each register a known value, then check that the correct values were in the correct registers when the task started running?

As for the portDISABLE_INTERRUPTS() and portENABLE_INTERRUPTS() macros - those should do nothing more then disable and enable interrupts respectively, however you want to do that (globally or just masking a sub-set of priorities). In your function, if x is non-zero, I assume it is supposed to disable interrupts - does calling CPU_SR_Save() disable interrupts?

zhuchunxia wrote on Thursday, June 02, 2016:

The first thing to check is that the task is really starting the way you expect it to be. When you created the initial stack for the task did you give each register a known value, then check that the correct values were in the correct registers when the task started running?

yes, I did, I dump PC and PSR register which is in initial stack …it is right …
if x is non-zero, I assume it is supposed to disable interrupts - does calling CPU_SR_Save() disable interrupts?

yes, if x is 1, disable global interrupt to mask all interrupt… if x is 0, enable global interrupt and clear all interrupt.

rtel wrote on Thursday, June 02, 2016:

I think with the amount of information available, and without seeing a
lot of your code, and being able to step through the code on the
hardware, it is going to be very difficult to make useful suggestions.

I think from your original post you say the first task is starting, but
then the first time a context switch is attempted it gets stuck in the
loop. Is the context switch coming from an interrupt, or is the task
trying to perform a context switch itself by yielding or calling a
blocking API function? I would recommend starting with the tick
interrupt OFF, so getting the task level context switch working first.

How is the task context switch performed? A software interrupt? Put a
break point in the interrupt and step through it as the assembly level
so you can see exactly what it is doing - somewhere it is corrupting
memory which is why you are ending up in the loop.

zhuchunxia wrote on Thursday, June 02, 2016:

the interrupt controller is comprosed of IRQ_INTEN, IRQ_INTMASK, IRQ_INTCLR, and IRQ_INTSTS to support 32 interrupt…

zhuchunxia wrote on Thursday, June 02, 2016:

to start first task, I use the following code without task switch
OSIntCtxSw:
lrw r4, pxCurrentTCB
ld.w r4, (r4) // the current task stack pointer is the first member
ld.w sp, (r4)

ld.w r1, (sp,0)					// Get the PC for the task
mtcr	r1, EPC

ld.w r1, (sp,4)					// Get the PSR for the task
mtcr	r1, EPSR

addi	sp, 8					// Increment SP past the PC and PSR

ldm	r1-r15,(sp) 				// Load R0-R13 from the stack
addi	sp, 32					// Increment SP past the registers
addi	sp, 28					// Increment SP past the registers

rte							// Return to new task

then the first task run and enter vTaskDelay funciton. then halti in the loop at last

zhuchunxia wrote on Thursday, June 02, 2016:

the real code use soft trap to do context switch, but it has not run it…
I just send all porting file to you by mail

zhuchunxia wrote on Thursday, June 02, 2016:

the question real status is the first task run after call OSIntCtxSw, then halt in loop after call vtaskdelay, no context switch happen !!!

rtel wrote on Thursday, June 02, 2016:

Have you stepped through the code in the debugger, from the vTaskDelay()
function onwards, to see how it gets into the loop?

zhuchunxia wrote on Thursday, June 02, 2016:

yes… i did.
after enter vtaskdelay, it call prvAddCurrentTaskToDelayedList, then call vListInsert, then get stuck in the following loop code,
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. /
{
/
There is nothing to do here, just iterating to the wanted
insertion position. */
}

rtel wrote on Thursday, June 02, 2016:

In which case, as you said before, the problem is occurring before you
attempt the actual context switch. Possibilities, either:

  1. The C start up code has not correctly initialised the variables used
    by FreeRTOS so the data structures were already corrupt before the
    scheduler started, or

  2. Something in your code has corrupted the data structures used by
    FreeRTOS, or

  3. The linker script is wrong, or

  4. You are using heap_3 and the heap is overlapping other data, or

  5. …something else that has caused the data structures to be corrupted.

zhuchunxia wrote on Sunday, June 05, 2016:

The BaseStack prototype should be unsigned long instead of long, now it works well :slight_smile: