EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

LPC2148 FreeRTOS FIQ/IRQ external interrupt

Started by capablazabcl November 15, 2012
Hello friends,

I'm working with an LPC2148 with FreeRTOS, and I need to interrupt the MCU with an external interrupt (which could be FIQ or IRQ for instance), and then toggle a pin with a task.

Ive been told FreeRTOS have problems calling its API functions from an FIQ.

Has someone did something similar?

I just need to interrupt the MCU with an external interrupt and then toggle a pin with a periodic task... Maybe theres some workaround I'm not familiar with.

I posted the codes in this link:

https://sourceforge.net/projects/freertos/forums/forum/382005/topic/6137152/index/page/1
I hope you can help me.

Best regards,
Carlos

An Engineer's Guide to the LPC2100 Series

Have you tried using IRQ and wrapping your IRQ handler in a context switch?
// Declare wrapped handler, must be naked
void irq_handler_wrapper( void ) __attribute__((naked));

// Declare actual handler, must not be inlined
void actual_irq_handler(void) __attribute__((noinline));
void actual_irq_handler(void)
{
static signed portBASE_TYPE xHigherPriorityTaskWoken;

xSemaphoreGiveFromISR(sem, &xHigherPriorityTaskWoken);

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

void irq_handler_wrapper( void )
{
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();

/* Call the handler. This must be a separate function unless you can
guarantee that no stack will be used. */
actual_irq_handler();

/* Restore the context of whichever task is going to run next. */
portRESTORE_CONTEXT();
}
--- In l..., "capablazabcl" wrote:
>
> Hello friends,
>
> I'm working with an LPC2148 with FreeRTOS, and I need to interrupt the MCU with an external interrupt (which could be FIQ or IRQ for instance), and then toggle a pin with a task.
>
> Ive been told FreeRTOS have problems calling its API functions from an FIQ.
>
> Has someone did something similar?
>
> I just need to interrupt the MCU with an external interrupt and then toggle a pin with a periodic task... Maybe theres some workaround I'm not familiar with.
>
> I posted the codes in this link:
>
> https://sourceforge.net/projects/freertos/forums/forum/382005/topic/6137152/index/page/1
> I hope you can help me.
>
> Best regards,
> Carlos
>

Mikael,

Thank you for your response.

By playing around a little with your suggested cod, its now working!

I've got to mention it's working with FIQ!

This is what I finally did:

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

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 the 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 response!
Carlos

--- In l..., "mikaeleiman" wrote:
> Have you tried using IRQ and wrapping your IRQ handler in a context switch?
> // Declare wrapped handler, must be naked
> void irq_handler_wrapper( void ) __attribute__((naked));
>
> // Declare actual handler, must not be inlined
> void actual_irq_handler(void) __attribute__((noinline));
> void actual_irq_handler(void)
> {
> static signed portBASE_TYPE xHigherPriorityTaskWoken;
>
> xSemaphoreGiveFromISR(sem, &xHigherPriorityTaskWoken);
>
> if ( xHigherPriorityTaskWoken )
> {
> // switch context to newly awoken task
> portYIELD_FROM_ISR();
> }
> }
>
> void irq_handler_wrapper( void )
> {
> /* Save the context of the interrupted task. */
> portSAVE_CONTEXT();
>
> /* Call the handler. This must be a separate function unless you can
> guarantee that no stack will be used. */
> actual_irq_handler();
>
> /* Restore the context of whichever task is going to run next. */
> portRESTORE_CONTEXT();
> }
> --- In l..., "capablazabcl" wrote:
> >
> > Hello friends,
> >
> > I'm working with an LPC2148 with FreeRTOS, and I need to interrupt the MCU with an external interrupt (which could be FIQ or IRQ for instance), and then toggle a pin with a task.
> >
> > Ive been told FreeRTOS have problems calling its API functions from an FIQ.
> >
> > Has someone did something similar?
> >
> > I just need to interrupt the MCU with an external interrupt and then toggle a pin with a periodic task... Maybe theres some workaround I'm not familiar with.
> >
> > I posted the codes in this link:
> >
> > https://sourceforge.net/projects/freertos/forums/forum/382005/topic/6137152/index/page/1
> >
> >
> > I hope you can help me.
> >
> > Best regards,
> > Carlos
>
I've connected the FIQ interrupt pin to a PWM and the system halts like 15 seconds after the reset.

the PWM is 100 [Hz] with a duty cycle of 10%.

Any suggestions?
Best Regards,
Carlos

--- In l..., "capablazabcl" wrote:
>
> Mikael,
>
> Thank you for your response.
>
> By playing around a little with your suggested cod, its now working!
>
> I've got to mention it's working with FIQ!
>
> This is what I finally did:
>
> ------------------------
>
> 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 the 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 response!
> Carlos
>
> --- In l..., "mikaeleiman" wrote:
> >
> >
> >
> >
> >
> >
> > Have you tried using IRQ and wrapping your IRQ handler in a context switch?
> >
> >
> > // Declare wrapped handler, must be naked
> > void irq_handler_wrapper( void ) __attribute__((naked));
> >
> > // Declare actual handler, must not be inlined
> > void actual_irq_handler(void) __attribute__((noinline));
> >
> >
> > void actual_irq_handler(void)
> > {
> > static signed portBASE_TYPE xHigherPriorityTaskWoken;
> >
> > xSemaphoreGiveFromISR(sem, &xHigherPriorityTaskWoken);
> >
> > if ( xHigherPriorityTaskWoken )
> > {
> > // switch context to newly awoken task
> > portYIELD_FROM_ISR();
> > }
> > }
> >
> > void irq_handler_wrapper( void )
> > {
> > /* Save the context of the interrupted task. */
> > portSAVE_CONTEXT();
> >
> > /* Call the handler. This must be a separate function unless you can
> > guarantee that no stack will be used. */
> > actual_irq_handler();
> >
> > /* Restore the context of whichever task is going to run next. */
> > portRESTORE_CONTEXT();
> > }
> >
> >
> > --- In l..., "capablazabcl" wrote:
> > >
> > > Hello friends,
> > >
> > > I'm working with an LPC2148 with FreeRTOS, and I need to interrupt the MCU with an external interrupt (which could be FIQ or IRQ for instance), and then toggle a pin with a task.
> > >
> > > Ive been told FreeRTOS have problems calling its API functions from an FIQ.
> > >
> > > Has someone did something similar?
> > >
> > > I just need to interrupt the MCU with an external interrupt and then toggle a pin with a periodic task... Maybe theres some workaround I'm not familiar with.
> > >
> > > I posted the codes in this link:
> > >
> > > https://sourceforge.net/projects/freertos/forums/forum/382005/topic/6137152/index/page/1
> > >
> > >
> > > I hope you can help me.
> > >
> > > Best regards,
> > > Carlos
> > >
>

On Sat, Nov 17, 2012 at 12:46 PM, capablazabcl wrote:

> I've connected the FIQ interrupt pin to a PWM and the system halts like 15
> seconds after the reset.
>
> the PWM is 100 [Hz] with a duty cycle of 10%.
>
> Any suggestions?
>

that's typical behaviour for walking off the end of your stack into the
heap. make sure your interrupts aren't nesting and also make sure your code
isn't calling itself recursively.

Also make sure you're checking all your buffers, buffer overflow leads to
smashed stacks if the buffer is allocated on the stack...


Thank you for your response.

I'm not sure where it could be happening. Ill check on that and tell you if
I find something.
Regards,
Carlos



The 2024 Embedded Online Conference