Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

LPC2148 FIQ Handler problem

Posted by Carlos Apablaza B on November 8, 2012
Hello,

I'm using FreeRTOS with an LPC2148. I ported the code from the LPC 2106 example. (It works fine)

The FIQ interrupt is working fine too, but I need it to launch a function from the ISR, to toggle a pin of the MCU.

I have 2 tasks: one that blinks an GREEN LED (just to be sure the system is running), and an ISRHandler which is synchronized with a semaphore. In this case, the ISRHandler turns ON an RED LED. The code I'm using is very similar to the one proposed in the documentation.


I'm sure the FIQ interrupt is working fine: With the GREEN LED blinking, if I dont use the ISRHandler, I can turn ON the RED LED in the interrupt when a pin is LOW, and then turn it OFF when the pin returns to HIGH, and the GREEN LED returns to blink. So, the interrupt ends and the blinker task returns to run.


BUT, If I enable the ISRHandler task (with xTaskCreate()), the ISRHandler preempts the blinker task after the FIQ interrupt, and apparently doesnt block when the pin is HIGH again, so the GREEN LED doenst blink anymore.

I hope my explanation isn't too confusing.



This is the code I'm using: (Ill do a brief summary)

----------------------------------------------------------
main.h
----------------------------------------------------------

xSemaphoreHandle xBinarySemaphore;


----------------------------------------------------------
main.c
----------------------------------------------------------

int main( void )
{
// Setup the hardware for use with the Olimex demo board.
prvSetupHardware();

// Create Binary Semaphore
vSemaphoreCreateBinary(xBinarySemaphore);

// SETUP FIQ
PINSEL0 = 0x20000000; // sets p0.14 as EINT1
VICIntSelect |= 0x00008000;
VICIntEnable = 0x00008000;

xTaskCreate( vISRHandlerTask, ( signed char * ) "ISRHandler", 1000, NULL, 3, NULL );
xTaskCreate( vBlinkTask, (signed char * ) "blinker", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

vTaskStartScheduler();

// Should never reach here!
return 0;
}

void FIQ_Handler (void)
{
// Remove FIQ flag
EXTINT = 0x2;

static portBASE_TYPE xHigherPriorityTaskWoken;

xHigherPriorityTaskWoken = pdFALSE;

xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken);

if(xHigherPriorityTaskWoken == pdTRUE)
portYIELD_FROM_ISR();

}

----------------------------------------------------------
ISRHandler.c
----------------------------------------------------------

#include "main.h"

#define LED (1 << 20)

void vISRHandlerTask(void)
{
IO1DIR |= (LED);// Initializes P1.16 as output.

for(;;)
{
// This task will be blocked until the FIQ gives it the semaphore.
xSemaphoreTake(xBinarySemaphore, portMAX_DELAY);

IO1SET |= LED; // turns ON pin 1.16

// When finishing the routine, this task will return to blocked state
// waiting for another semaphore which will be given again by the FIQ.

/// I tried with giving the semaphore, but the MCU starts with the RED LED ON and doesnt do anything.
////xSemaphoreGive(xBinarySemaphore);
}
}

----------------------------------------------------------
Blinker.c
----------------------------------------------------------

#define LED (1 << 19)

void vBlinkTask(void)
{
pwmInit();

pwmFrequency(500);
pwmDutyCycle(90);

IO1DIR |= LED;

for(;;)
{
IO1CLR |= LED; // just blinks an LED every 100 ticks
vTaskDelay(50);
IO1SET |= LED;
vTaskDelay(50);
}
}

----------------------------------------------------------


I'd greatly appreciate any help.

Regards,
Carlos

RE: LPC2148 FIQ Handler problem

Posted by Richard on November 8, 2012
A couple of comments:

1) Do you have a stack setup for FIQ mode? Most of the demos provided don't. The stacks are normally configured in assembly code from the C start up code, before main() is called.

2) If you are using FIQ then you will have to ensure your portDISABLE_INTERRUPTS() and portENABLE_INTERRUPTS() functions disable/enable both IRQ and FIQ.

3) You are likely to get problems using FreeRTOS API functions from an FIQ handler because FIQ can pre-empt IRQ, and the code does not take that into account (none of the demos use FIQ). You might be ok if you disable the FIQ interrupt before using any FreeRTOS functions from an IRQ handler, but then that might defeat the object of using FIQ in the first place.

Regards.

RE: LPC2148 FIQ Handler problem

Posted by Carlos Apablaza B on November 9, 2012
Richard,

Thank you for your fast response.

As you suggested I made a few changes:

I increased the FIQ stack size to 400 bytes in startup.s:

/* Stack Sizes */
.set UND_STACK_SIZE, 0x00000004
.set ABT_STACK_SIZE, 0x00000004
.set FIQ_STACK_SIZE, 0x00000800
.set IRQ_STACK_SIZE, 0X00000400
.set SVC_STACK_SIZE, 0x00000400

--------------------------------------------------------------

in main (just to be sure), i added:

int main( void )
{
portENABLE_INTERRUPTS();
...

--------------------------------------------------------------

Also, in portmacro.h the codes seems to be correctly handling the activation/deactivation of FIQ and IRQ:

#define portDISABLE_INTERRUPTS()\
__asm volatile (\
"STMDBSP!, {R0}\n\t"/* Push R0.*/\
"MRSR0, CPSR\n\t"/* Get CPSR.*/\
"ORRR0, R0, #0xC0\n\t"/* Disable IRQ, FIQ.*/\
"MSRCPSR, R0\n\t"/* Write back modified value.*/\
"LDMIASP!, {R0}" )/* Pop R0.*/

#define portENABLE_INTERRUPTS()\
__asm volatile (\
"STMDBSP!, {R0}\n\t"/* Push R0.*/\
"MRSR0, CPSR\n\t"/* Get CPSR.*/\
"BICR0, R0, #0xC0\n\t"/* Enable IRQ, FIQ.*/\
"MSRCPSR, R0\n\t"/* Write back modified value.*/\
"LDMIASP!, {R0}

--------------------------------------------------------------

Also I added to the ISRHandler:

void vISRHandlerTask(void)
{
IO1DIR |= (LED);// Initializes P1.16 as output.

for(;;)
{
// This task will be blocked until the FIQ gives it the semaphore.
xSemaphoreTake(xBinarySemaphore, portMAX_DELAY);

portDISABLE_INTERRUPTS();

IO1SET |= LED;

// When finishing the routine, this task will return to blocked state
// waiting for another semaphore which will be given again by the FIQ.
//xSemaphoreGive(xBinarySemaphore);

portENABLE_INTERRUPTS();
}
}

As you said on number 3:
You are likely to get problems using FreeRTOS API functions from an FIQ handler because FIQ can pre-empt IRQ, and the code does not take that into account (none of the demos use FIQ).

If I understand, you mean, the FIQ can preempt the IRQ? But I only have a FIQ. there are not other interrupts.


You might be ok if you disable the FIQ interrupt before using any FreeRTOS functions from an IRQ handler, but then that might defeat the object of using FIQ in the first place.

I think this too is applicable when having FIQ and IRQ interrupts? Or am I wrong?


I can add now, that, with this code if I remove the call to xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken); in the FIQ routine, the LED returns to blink, so that seems to be the trouble.


I'm using the FIQ because its the fastest one only, but if you tell me that the IRQ will work, then I could give it a try. (Or any other workaround :D)


Thank you for your support!!
Carlos

RE: LPC2148 FIQ Handler problem

Posted by Carlos Apablaza B on November 9, 2012
Sorry,

This doesnt work either.

void vISRHandlerTask(void)
{
IO1DIR |= (LED);// Initializes P1.16 as output.

for(;;)
{
portDISABLE_INTERRUPTS();

// This task will be blocked until the FIQ gives it the semaphore.
xSemaphoreTake(xBinarySemaphore, portMAX_DELAY);

IO1SET |= LED;

// When finishing the routine, this task will return to blocked state
// waiting for another semaphore which will be given again by the FIQ.
//xSemaphoreGive(xBinarySemaphore);

portENABLE_INTERRUPTS();
}
}

Carlos

RE: LPC2148 FIQ Handler problem

Posted by https://www.google.com/accounts on November 16, 2012
No one?

Any help please?

I just need to interrupt the MCU with an external interrupt, and then do some processing with a task, periodically...

RE: LPC2148 FIQ Handler problem

Posted by Richard on November 16, 2012
Hi Carlos,

I don't know anything about this specific MCU so I did a quick read of the user manual. From your code above, I do not see where you are configuring the EXT interrupt mode and polarity. These registers apparently default to 0 which means level sensitive active low.

I suspect when you change the state of the external pin to low, the interrupt fires as expected. You clear the interrupt flag but at this point the input is still low so as soon as the interrupt exits, it will fire again. You end up doing nothing more than servicing the interrupt. I've done this sort of thing.

You could make the input edge triggered (falling or rising).

Hope this helps
travfrog

RE: LPC2148 FIQ Handler problem

Posted by https://www.google.com/accounts on November 17, 2012
Dear all,

The problem is solved!

travfrog thank you too for your help: The EXT is set to level sensitive by default as you said, so I was triggering the interrupt by moving a wire from VCC/GND. Now I've set it to edge sensitive so I can trigger it with a PWM.

Here's what I dit to make the FIQ[/b work (thanks to mikaeleiman from lpc2000 yahoo group)


------------------------

main.c:

void FIQ_Handler (void) __attribute__ ((interrupt("FIQ"))) __attribute((naked));

void FIQ_Handler (void)
{
portSAVE_CONTEXT();

actualFIQHandler();

EXTINT = 0x2;

portRESTORE_CONTEXT();
}

-----------------------------

actualFIQHandler.c

void actualFIQHandler(void) __attribute__((noinline));
void actualFIQHandler(void)
{
static signed portBASE_TYPE xHigherPriorityTaskWoken;

xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken);

if ( xHigherPriorityTaskWoken )
{
// switch context to newly awoken task
portYIELD_FROM_ISR();
}
}

----------------------------------------

and finally ISRHandler.c

void vISRHandlerTask(void)
{
IO1DIR |= (LED);// Initializes P1.16 as output.

int flag=0;

for(;;)
{
portDISABLE_INTERRUPTS();

// This task will be blocked until the FIQ gives it the semaphore.
xSemaphoreTake(xBinarySemaphore, portMAX_DELAY);

if(flag==1)
{
IO1SET |= LED;
flag=0;
}
else
{
IO1CLR |= LED;
flag=1;
}

// When finishing the routine, this task will return to blocked state
// waiting for another semaphore which will be given again by the FIQ.

portENABLE_INTERRUPTS();
}
}


I defined the interrupt as edge sensitive, and its working okay now.


Thank you for your support!
Carlos


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS