EmbeddedRelated.com
Forums

lpc2148 demo code hangs on ISR

Started by CeDeROM August 9, 2008
Hello!

I have used new FreeRTOS 5.0.0 gcc demo as base for my application. I
have tried to use portion of J.C.Wren UART code to send and receive
data. What is wrong - I can only send two bytes of data, then program
hangs. When I use gcc demo routines to send via uart everything works
fine. What can be wrong? Also my device does not want to enumerate
when using usb and usbserial from lpc2148 demo.
Is it code faoult, ISR, or FreeRTOS? I dont have much time, so if its
necessary I will switch back to OS 4 release.

Regards,
Tomek

--
CeDeROM, http://www.tomek.cedro.info

An Engineer's Guide to the LPC2100 Series

> Hello!
>
> I have used new FreeRTOS 5.0.0 gcc demo as base for my
> application. I have tried to use portion of J.C.Wren UART
> code to send and receive data. What is wrong - I can only
> send two bytes of data, then program hangs. When I use gcc
> demo routines to send via uart everything works fine. What
> can be wrong? Also my device does not want to enumerate when
> using usb and usbserial from lpc2148 demo.
> Is it code faoult, ISR, or FreeRTOS? I dont have much time,
> so if its necessary I will switch back to OS 4 release.
>

Did you take note of the following changes to the QueueSendFromISR()
function, which is most likely used by Mr Wren:
http://www.freertos.org/upgrading.html

Regards,
Richard.

+ http://www.FreeRTOS.org
17 official architecture ports, more than 6000 downloads per month.

+ http://www.SafeRTOS.com
Certified by T as meeting the requirements for safety related systems.

Hello Richard!

--- In l..., "FreeRTOS.org Info"
wrote:
> Did you take note of the following changes to the QueueSendFromISR()
> function, which is most likely used by Mr Wren:
> http://www.freertos.org/upgrading.html

Thanks to Your comment, I have made it working, thank You! :-)

Inside of the ISR handler routine I have:
1. Replaced:
portENTER_SWITCHING_ISR();
with
portSAVE_CONTEXT();

2. Replaced:
portEXIT_SWITCHING_ISR ((xTaskWokenByTx || xTaskWokenByRx));
with
portRESTORE_CONTEXT();
if (xTaskWokenByTx==pdTRUE || xTaskWokenByRx==pdTRUE)
portYIELD_FROM_ISR();

3. Replaced:
if (xQueueSendFromISR (xRX0Queue, &cChar, (portBASE_TYPE) pdFALSE))
xTaskWokenByRx = pdTRUE;
with
xQueueSendFromISR (xRX0Queue, &cChar, &xTaskWokenByRx);
So the whole routine looks like this:

void uartISR0 (void)
{
portSAVE_CONTEXT();

signed portCHAR cChar;
portBASE_TYPE xTaskWokenByTx = pdFALSE;
portBASE_TYPE xTaskWokenByRx = pdFALSE;

switch (UART0_IIR & serINTERRUPT_SOURCE_MASK)
{
//
// Not handling this, but clear the interrupt
//
case serSOURCE_ERROR :
{
cChar = UART0_LSR;
}
break;

//
// The THRE is empty. If there is another character in the Tx
queue, send it now,
// otherwise, no more characters, so indicate THRE is available
//
case serSOURCE_THRE :
{
if (xQueueReceiveFromISR (xTX0Queue, &cChar, &xTaskWokenByTx)
== pdTRUE)
UART0_THR = cChar;
else
lTHREEmpty0 = pdTRUE;
}
break;

//
// A character was received. Place it in the queue of received
characters
//
case serSOURCE_RX_TIMEOUT :
case serSOURCE_RX :
{
cChar = UART0_RBR;
xQueueSendFromISR (xRX0Queue, &cChar, &xTaskWokenByRx);
}
break;

default :
break;
}

VIC_VectAddr = (unsigned portLONG) 0;

portRESTORE_CONTEXT();
if (xTaskWokenByTx==pdTRUE || xTaskWokenByRx==pdTRUE)
portYIELD_FROM_ISR();
}

Is it proper way to exit ISR routine? 1. clear irq routine address,
2. restore context, 3. exit or yield to other task.

Here if the full code of UART handling:
http://files.tomek.cedro.info/electronics/FreeRTOS/lpc2148/uart-
FreeRTOS5.tar.gz

Best regards,
Tomek
> portRESTORE_CONTEXT();
> if (xTaskWokenByTx==pdTRUE || xTaskWokenByRx==pdTRUE)
> portYIELD_FROM_ISR(); }
>
> Is it proper way to exit ISR routine? 1. clear irq routine
> address, 2. restore context, 3. exit or yield to other task.
>

Without having gone through it in too much detail I would say that the if()
statement following the call to portRESTORE_CONTEXT() as definitely wrong.

Please read the docs - starting with the "interrupt service routines"
section of this page: http://www.freertos.org/portlpc2106.html. It tells
you what to do and gives examples.

Regards,
Richard.

+ http://www.FreeRTOS.org
17 official architecture ports, more than 6000 downloads per month.

+ http://www.SafeRTOS.com
Certified by T as meeting the requirements for safety related systems.

Hello Richard!

--- In l..., "FreeRTOS.org Info"
wrote:
> > portRESTORE_CONTEXT();
> > if (xTaskWokenByTx==pdTRUE || xTaskWokenByRx==pdTRUE)
> > portYIELD_FROM_ISR(); }
> >
> > Is it proper way to exit ISR routine? 1. clear irq routine
> > address, 2. restore context, 3. exit or yield to other task.
> > Without having gone through it in too much detail I would say that
the if()
> statement following the call to portRESTORE_CONTEXT() as definitely
wrong.

Ok, as I can see in the source tree there is always scheme:
portSAVE_CONTEXT
portYIELD_FROM_ISR (that is vTaskSwitchContext)
portRESTORE_CONTEXT

and it works like:
-save context not to crash interrupted task registry/stack
-perform operations
-if some task was blocked waiting for queue and got some data, then
it wants to run
-we give a hint to kernel by portYIELD_FROM_ISR that there is a task
waiting for execution
-restore context and go back from isr routine to interrupted task (by
finish isr function)
-now kernel decides which task to run: interrupted task or queue
receiver

Please verify if I am correct :-)

Before, I thought that portYIELD_FROM_ISR is like JUMP or CALL to the
queue receiver task.

I think this would be nice idea to use storing/restoring context with
yielding in queue example.

Best Regards,
Tomek

ps/2: I am using this arm7 lpc2106 gcc example on unix environment
and it works fine with little modification *.bat into *.sh.
> and it works like:
> -save context not to crash interrupted task registry/stack
> -perform operations
> -if some task was blocked waiting for queue and got some data, then
> it wants to run
> -we give a hint to kernel by portYIELD_FROM_ISR that there is a task
> waiting for execution
> -restore context and go back from isr routine to interrupted task (by
> finish isr function)
> -now kernel decides which task to run: interrupted task or queue
> receiver
>
> Please verify if I am correct :-)

Thats about sums it up. Each port works slightly differently but all
follow a similar scheme. A demo is provided for each so there is always
something to copy.

Regards,
Richard.

+ http://www.FreeRTOS.org
17 official architecture ports, more than 6000 downloads per month.

+ http://www.SafeRTOS.com
Certified by T as meeting the requirements for safety related systems.

--- In l..., "FreeRTOS.org Info"
wrote:
> > Please verify if I am correct :-)
>
> That's about sums it up. Each port works slightly differently but
all
> follow a similar scheme. A demo is provided for each so there is
always
> something to copy.

Thank You Richard for support and patience :-)

Best Regards,
Tomek