EmbDev.net

Forum: ARM programming with GCC/GNU tools Interrupts are not acknoledged and don't stop


von Javier R. (fjrg76)


Rate this post
useful
not useful
Hi

After some research I was able to make the external interrupt to work
with the LPC2129 under Crossworks 1.5. However, when asserted the
external signal (low-edge) the code jumps to my ISR, but instead of
exiting it enters again, and after this time the code starts at the init
of the main function, and after some instructions it stops working. I've
followed the procedure to acknoledge the interrupt, and I have no idea
why this is working like that. I guess it's not hard to use the
interrupts, but I've spent some days trying this thing to work properly.
Besides I added an irq_handler() function because if not the code enters
into a infinite loop.

Any idea?? Am I missing something?? This is the code, and if more info
is need please ask. Thanks =)

//====================================================================== 
======
#include <stdio.h>
#include <targets/lpc21xx.h>

static void isrEINT3(void) _attribute_ ((interrupt ("IRQ")));
//static void irq_handler(void) _attribute_ ((interrupt ("IRQ")));

void ledInit(void){
  IO1DIR = 0;
  IO1DIR |= (3 << 22);
  IO1SET = (3 << 22);
}

#define led1On    IO1CLR=(1<<22)
#define led1Off    IO1SET=(1<<22)
#define led2On    IO1CLR=(1<<23)
#define led2Off    IO1SET=(1<<23)


void delay(unsigned d){
  asm volatile("subs r0, r0, #0x00000001");
  asm volatile("bne -1");
}

void isrEINT3(void){
  EXTINT = 8;    /* Clear the interrupt */
  VICVectAddr = 0;  /* Update VIC priorities */
}


void vicInit(void){
  VICIntSelect=0;        /* all vectored IRQ */
  VICIntEnable=(1<<17);            /* enable eint3 */
  VICVectCntl1=(1<<5)|(17);    /* enable eint3 */
  VICVectAddr1=(unsigned long)isrEINT3;  /* eint isr address */
}


void eintInit(void){
  EXTINT=0xff;    /* clear any pending interrupt */
  EXTMODE=(1<<3);    /* edge-sensitive */
  EXTPOLAR=0;    /* low-active */
}

/*                     ATTENTION

HERE IS WHERE THE CORRECT ISR IS ADDRESSED, HOWEVER WHEN THE ISR RETURNS
IT STUCKS AT THE <MARKED> INTRUCTION AND ENTERS AGAIN TO THE ISR

*/
void irq_handler(void){        // <-- Added to handle the IRQ
  void (*interrupt_function)();
  unsigned int vector;

  vector = VICVectAddr;      // Get interrupt vector.
  interrupt_function = (void(*)())vector;
  (*interrupt_function)();    //     <<< MARKED  >>>

  VICVectAddr = 0;      // Clear interrupt in VIC.
}

void boardInit(void){
  IO1DIR = 0;
  IO1DIR |= (3 << 22);      /* leds on board*/
  IO1SET = (3 << 22);
  PINSEL1 |= (0x0F << 6);
  eintInit();              /* initializes eint3 */
  vicInit();         // <----- Initilize the VIC
    __ARMLIB_enableIRQ();

}

int main(void){
  boardInit();

  led1On;    /* board is alive */
  for(;;);

  return 0;
}
//====================================================================== 
======

von Javier R. (fjrg76)


Rate this post
useful
not useful
Hi again

I guess I found how to make this thing to work. The code is the same
except that I changed the attributes to these

//static void isrEINT3(void) _attribute_ ((interrupt ("IRQ")));
static void irq_handler(void) _attribute_ ((interrupt ("IRQ")));

My board now is counting external pulses. According what I'm seeing I
can say that the only function that must be marked with the attribute
"IRQ" is the IRQ handler function, whereas the other isr's should be
treated as normal functions.

Is this thought right??

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Javier Rod wrote:
> Hi again
>
> I guess I found how to make this thing to work. The code is the same
> except that I changed the attributes to these
>
> //static void isrEINT3(void) _attribute_ ((interrupt ("IRQ")));
> static void irq_handler(void) _attribute_ ((interrupt ("IRQ")));
>
> My board now is counting external pulses. According what I'm seeing I
> can say that the only function that must be marked with the attribute
> "IRQ" is the IRQ handler function, whereas the other isr's should be
> treated as normal functions.
>
> Is this thought right??

Depends on you exceptions-settings. I expect you will find something
like this in your startup-code/vectors-settings:

[...]
                LDR     PC, IRQ_Addr
[...]
IRQ_Addr:       .word   irq_handler
[...]

So on an IRQ exception your c-function irq_handler() gets called. The
c-function is a "wrapper" which reads the address of the service-routine
(isrEINT3()) from the VIC and calls it though a C-function-pointer. The
function called by the core must be "prepared" for IRQ which can be done
for example with the attribute like here. Functions called from inside
the wrapper are usual C-Functions.

I guess you have been confused by the different approaches how a
IRQ-hander can be called. Other examples for LPC load the PC directly
from the VIC with something like LDR PC, [PC, #xxxxxx] at the IRQ
address. In this case isrEINT3 would be called directly and preparation
would be needed (i.e. attribute).

von Javier R. (fjrg76)


Rate this post
useful
not useful
>
> Depends on you exceptions-settings. I expect you will find something
> like this in your startup-code/vectors-settings:
>
> [...]
>                 LDR     PC, IRQ_Addr
> [...]
> IRQ_Addr:       .word   irq_handler
> [...]
>
> So on an IRQ exception your c-function irq_handler() gets called. The
> c-function is a "wrapper" which reads the address of the service-routine
> (isrEINT3()) from the VIC and calls it though a C-function-pointer. The
> function called by the core must be "prepared" for IRQ which can be done
> for example with the attribute like here. Functions called from inside
> the wrapper are usual C-Functions.
>
> I guess you have been confused by the different approaches how a
> IRQ-hander can be called. Other examples for LPC load the PC directly
> from the VIC with something like LDR PC, [PC, #xxxxxx] at the IRQ
> address. In this case isrEINT3 would be called directly and preparation
> would be needed (i.e. attribute).

Hi!!

Yes I'm very confused with the several aproaches to make the interrupts
to work. I understood how to set up the interrupts, but there is a lack
of information about what's next (irq_handler is not documented). I read
some examples, and all were different among them, besides the compiler
that will be used adds more complexity to this thing. After my code
worked, I realized that the only function that must have the attributes
is the one that will redirect the interrupt sources. There are examples
where all the interrupt sources that are used have the atrributes, but I
don't still have a clue why. Now I have the EINT3 and CAP1.2 peripherals
working as interrupts in the way I found.

If you may tell me where I can find some information about the
attributes for the interrupts (something for idiots), you're welcome.
Thanks !! =)

von Clifford S. (clifford)


Rate this post
useful
not useful
First you nee to understand that the ARM core only has two interrupt
sources. Most ARM based microcontrollers have a interrupt controller.
This external to the ARM core. The interrupt controller implementation
varies amongst vendors and the compiler has no knowledge of this
whatsoever.

Furthermore interrupt handling is not defined in the C or C++ languages,
so any provision for this by the compiler is proprietary.

Personally in my projects I have never used this compiler extension, but
rather hook a default handler in the start-up code, the handler then
deals with teh interrupt controller, identifies the source, and calls an
interrupt handler as a normal function through a pointer hooked in at
runtime. My projects use an RTOS so this mechanism is a necessary part
of the BSP. I imagine that something like freeRTOS for example will
allow such mecanisms. Any way my point is that it is a good idea to take
responsibility for interrupt handling rather than expect teh compiler to
support it. The code will be more portable as a consequence.

This free PDF book: http://www.hitex.co.uk/arm/lpc2000book/ may help.
Its examples use the Keil compiler, but the discussion of the
architectural aspects should still be useful to you. (and it is free!)

Perhaps of more direct use is
http://www.quantum-leaps.com/resources/papers.htm##GNU-ARM. It is GNU
specific and parts 8 and 9 deal with interrupt handling. The files
include links to many other resources.

Unfortunately the first publication is LPC2xxx specific, but not GNU
specific, while the second is is GNU specific but not LPC2xxx specific.
In fact it uses an Atmel device for the examples. In both cases much of
the principles apply regardless and the ARM core specifics are
identical. You will have to be aware of the differences between the
parts if not the compilers, so you should also have the LPC2xxx user
manual to hand as well.

Clifford

von Javier R. (fjrg76)


Rate this post
useful
not useful
Hi Clifford!!

I'm newbie at ARM architecture, so while I'm developing my application
I'm learning this MCU, although I'm experienced 8 bit developer. Can you
send my your irq_handler (just an example) in order to integrate it into
my code?? Yours seems to be cleaner and more independant than I'm using.
Thanks!! =)

von Clifford S. (clifford)


Rate this post
useful
not useful
Javier Rod wrote:
> I'm learning this MCU, although I'm experienced 8 bit developer. Can you
> send my your irq_handler (just an example) in order to integrate it into
> my code?? Yours seems to be cleaner and more independent than I'm using.

Unfortunately it is not strictly my code but rather that of my
employer (even if I did write it). It also includes code that is the
copyright of the RTOS vendor, so unfortunately not. Moreover it is for
an ARM9 (Samsung S3C2410X) so may differ from what you need. I think the
Quantum Leap code implements more or less teh architecture I suggested.
You simply need to be aware of teh interrupt controller differences
between the Atmel AM91 and the NXP LCP21xx.


Clifford

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> Javier Rod wrote:
>> I'm learning this MCU, although I'm experienced 8 bit developer. Can you
>> send my your irq_handler (just an example) in order to integrate it into
>> my code?? Yours seems to be cleaner and more independent than I'm using.
>
> Unfortunately it is not strictly my code but rather that of my
> employer (even if I did write it). It also includes code that is the
> copyright of the RTOS vendor, so unfortunately not. Moreover it is for
> an ARM9 (Samsung S3C2410X) so may differ from what you need. I think the
> Quantum Leap code implements more or less teh architecture I suggested.
> You simply need to be aware of teh interrupt controller differences
> between the Atmel AM91 and the NXP LCP21xx.

The function __IRQ_Wrapper in file startup.S in the zip-package
available from
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/lpc2k_bundle_port/index.html
should demonstrate an implementation of the approach described by
Clifford for LPC21xx.

von Javier R. (fjrg76)


Rate this post
useful
not useful
Martin Thomas wrote:
> Clifford Slocombe wrote:
>> Javier Rod wrote:
>>> I'm learning this MCU, although I'm experienced 8 bit developer. Can you
>>> send my your irq_handler (just an example) in order to integrate it into
>>> my code?? Yours seems to be cleaner and more independent than I'm using.
>>
>> Unfortunately it is not strictly my code but rather that of my
>> employer (even if I did write it). It also includes code that is the
>> copyright of the RTOS vendor, so unfortunately not. Moreover it is for
>> an ARM9 (Samsung S3C2410X) so may differ from what you need. I think the
>> Quantum Leap code implements more or less teh architecture I suggested.
>> You simply need to be aware of teh interrupt controller differences
>> between the Atmel AM91 and the NXP LCP21xx.
>
> The function __IRQ_Wrapper in file startup.S in the zip-package
> available from
> 
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/lpc2k_bundle_port/index.html
> should demonstrate an implementation of the approach described by
> Clifford for LPC21xx.

Thanks!!

My system is now working in the way I explained before, however I'll
take a look in order to do the things right (as the pros do).

Let me ask you something related. When I reset the MCU through the RST
pin it doesn't run (it does nothing). I need to cycle the power in order
the MCU to work. Is this related with the reset interrupt??

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.