Weird Interaction With VIC on ARM/LPC2103

rost_stargen wrote on Monday, April 23, 2007:

My environment:

Olimex LPC-P2103 board (ARM7)
Eclipse 3.2.2
GCC 4.0.2
Free RTOS 4.1.1

I have some problems with interrupts hanging queues and task delays.

I have interrupts enabled for TIMER2 in the LPC2103 processor. When the interrupt fires, my ISR (based on the serialISR demo) disables the interrupt, executes a QueueSendFromISR and then writes the VICVectAddr register to force the processor to readjust the interrupt priority. However the QueueReceive call in the task that is waiting on the queue hangs and a vTaskDelay call in another unrelated task hangs. If I do NOT write the VICVectAddr register things work OK.

I have a second interrupt for EINT2 (triggered by a momentary button on the board) and this interrupt seems to be serviced correctly regardless of whether or not I write the VICVectAddr register after servicing the TIMER2 interrupt which doesn’t make sense to me.

I have been unable to see how writing the VICVectAddr register should have any effect on the queue or task delay.

Any ideas what I should look at?

Brian

embeddedc wrote on Monday, April 23, 2007:

> writes the VICVectAddr register to force the processor to readjust the interrupt priority

Is this a valid thing to do while an interrupt is being processed.  Does it work when not using FreeRTOS?

Maybe it is screwing up the timer interrupt hence the delay function does not work?

What do you mean by "readjust"?

rost_stargen wrote on Monday, April 23, 2007:

embeddedc,

From the LPC2100 manual (not the best grammar!!!):

"Vector Address register (VICVectAddr - 0xFFFF F030)
This is a read/write accessible register. When an IRQ interrupt occurs, the IRQ service routine can read this register and jump to the value read. If any of the interrupt requests or software interrupts that are assigned to a vectored IRQ slot is (are) enabled, classified as IRQ, and asserted, reading from this register returns the address in the Vector Address Register for the highest-priority such slot (lowest-numbered) such slot. Otherwise it returns the address in the Default Vector Address Register. Writing to this register does not set the value for future reads from it. Rather, this register should be written near the end of an ISR, to update the priority hardware."

I don’t think the above is very clear (ha ha), we understand it to mean the register can be read but written values are ignored, writes simply trigger the CPU to update it’s view of the pending interrupts.

From serialISR.c (FreeRTOS demo for ARM7_LPC2106_GCC):

void vUART_ISR( void )
{
    /* This ISR can cause a context switch, so the first statement must be a
    call to the portENTER_SWITCHING_ISR() macro.  This must be BEFORE any
    variable declarations. */
    portENTER_SWITCHING_ISR();

    /* Clear the ISR in the VIC. */
    VICVectAddr = serCLEAR_VIC_INTERRUPT;  <---- this is defined to be ZERO

    /* Exit the ISR.  If a task was woken by either a character being received
    or transmitted then a context switch will occur. */
    portEXIT_SWITCHING_ISR( ( xTaskWokenByTx || xTaskWokenByRx ) );
}

From my code:

void vEUI_ISR( void )
{

  /* This ISR can cause a context switch, so the first statement must be a
     call to the portENTER_SWITCHING_ISR() macro.  This must be BEFORE any
     variable declarations. */
  portENTER_SWITCHING_ISR();

  /* Clear the ISR in the VIC. */
  WRITE(VICVectAddr, euiCLEAR_VIC_INTERRUPT);  <— "write" is our own routine for reg access, the param here is defined as ZERO…in other words, this should be the same as the demo example (I did try the EXACT syntax from the demo, same result)

  /* Exit the ISR.  No context switch will occur. */
  portEXIT_SWITCHING_ISR(bQueueReturnValue);

}

Bothe the demo and my code call xQueueSendFromISR.

Brian

embeddedc wrote on Monday, April 23, 2007:

It is curious that it works without the call to WRITE(VICVectAddr, euiCLEAR_VIC_INTERRUPT), as without this the interrupt is never complete as far as the VIC is concerned.

Are you using startup code that is based on code from another FreeRTOS.org demo?  Specifically, are you vectoring directly to the ISR, or is there some code that executes prior to the ISR?  To know look at what is loaded in the IRQ vector.  If it is something like this:

ldr   pc, [pc,#-0xFF0]

then you are vectoring directly to the ISR.

rost_stargen wrote on Monday, April 23, 2007:

embeddedc,

I found the problem finally. I wasn’t properly clearing the interrupt in the ISR, I was only disabling it. As a result the code kept re-entering the ISR and starving out all other non-interrupt tasks. I’m confused why when I did not trigger the CPU to update the interrupt priorities the ISR was not being re-entered, but that’s something I’ll worry about after I wrap up work on this ISR.

Thanks for your replies.