uxListRemove results in address exception

blatini wrote on Monday, August 04, 2014:

I’m using FreeRTOS 8.0.1 on PIC32MX.

I’m getting an address exception error which I’ve traced to the RTOS function uxListRemove(). The value of pxItemToRemove->pvContainer is initialized to NULL in vListInitialiseItem() and its value isn’t checked in uxListRemove() before it is dereferenced in these statements:

List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;

...

/* Make sure the index is left pointing to a valid item. */
if( pxList->pxIndex == pxItemToRemove )
{
	pxList->pxIndex = pxItemToRemove->pxPrevious;
}

The address exception occurs on the if statement – because in this instance, element pvContainer is still NULL. I don’t know why is hasn’t been initialized to something other than NULL. I only know that it hasn’t. 0x0000 is an invalid address in PIC32; RAM is referenced by virtual addresses beginning at 0xA0000000.

The value of ListItem_t pxItemToRemove immediately before the exception is:

xItemValue == 4
pxNext == 0xA0004BF8 (a valid RAM address)
pxPrevious == 0xA0004BF8
pvOwner == 0xA0004BE0
pvContainer == 0

I haven’t done anything that I would consider unusual. In fact, I have 2 nearly identical tasks executing in sequence. The first deletes itself before the second task is created. The first task executes fine. The second task will execute fine if I remove the first task (via commenting it out). But if it follows deletion of the first task, I get this address exception. I’ve checked that the idleTask is running to clean up deleted items. And I played with adjusting stack sizes, etc. before I traced this down to uxListRemove(). I appears to me that perhaps the value of this pointer “pvContainer” should be checked before it is dereferenced. I haven’t explored the RTOS kernel to see what’s actually being done here.

rtel wrote on Monday, August 04, 2014:

Are you using interrupts? If so, at which interrupt priority are they running at what is the value of configMAX_SYSCALL_INTERRUPT_PRIORITY in FreeRTOSConfig.h?

Regards.

blatini wrote on Monday, August 04, 2014:

configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 3.

I’m using 1 peripheral interrupt, the priority of which I set to 3. I configured it with the assembly language wrapper, as described in the RTOS documentation. It is running properly.

rtel wrote on Monday, August 04, 2014:

It is running properly.

Well, maybe not, depending on what is causing the problem. The most common cause of the type of corruption you describe is an interrupt running at the wrong priority. The interrupt itself may appear to execute, but if it were at an incorrect priority it could corrupt data while it was running.

How are you setting the interrupts priority?
Do you have stack overflow detection turned on?
Stack overflow detection only checks the task stacks, so have you tried increasing the size of the stack used by interrupts?
Do you have configASSERT() defined?

Let me know if you are not sure about any of the above questions and I can provide links to the relevant documentation.

Regards.

blatini wrote on Monday, August 04, 2014:

configCHECK_FOR_STACK_OVERFLOW is set to 3

I’m setting the IRQ priority by directly setting bits in the associated PIC32 IPC register. I’ve verified with the debugger that the priority is 3 in the correct register bits immediately before the address exception occurs.

My interrupt doesn’t do anything but copy register contents to an RTOS queue via xQueueSendFromISR and clear the interrupt flag. So I can’t imagine that it requires much stack space.

configISR_STACK_SIZE is set to 300. I increased it to 512, and the problem still occurs.

configAssert is defined as in the PIC sample project:

/* Prevent C specific syntax being included in assembly files. */
void vAssertCalled( const char *pcFileName, unsigned long ulLine );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )


void vAssertCalled( const char * pcFile, unsigned long ulLine )
{
    volatile unsigned long ul = 0;

    ( void ) pcFile;
    ( void ) ulLine;

    __asm volatile( "di" );
    {
	/* Set ul to a non-zero value using the debugger to step out of this
	function. */
	    while( ul == 0 )
	    {
	    	portNOP();
	    }
    }
       __asm volatile( "ei" );
}

blatini wrote on Monday, August 04, 2014:

Thanks for your assistance! Your comments about interrupts got me to looking in a different place than I’ve been looking, and I located the problem in my code. I wasn’t clearing the interrupt queue handle to NULL after calling vQueueDelete. And since I’m checking whether it is NULL before creating it again later, it wasn’t created anew for the 2nd task, so the interrupt was using the old queue handle. If that makes sense …

Anyway, thanks for your time. It is much appreciated!