EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

LPC2378 on Olimex board: IRQ understanding problem

Started by stefan_bluhm November 27, 2011
Dear all,

I am struggling quite a bit in getting the IRQs to work. I am being a
bit difficult on setting up the whole IRQ environment. FIQ as well as
IRQ.

I have successfully tested the software interrupt using the SWI
assembler instructions. So I have no problems with that.

Now this is what I am trying to do: setup he watchdog to generate an
interrupt: a) FIQ and b) IRQ. I can't get nothing to work

The watchdog seems to be working ok, as I was able to do a hard reset if
the watchdog times out.

This is what my example application below can already do: on reset, it
flashes the LED 5 times. That's it... If the watchdog settings are
changed to hard reset, the LED flashes 5 times on reset and waits about
15 seconds. Then flashes again 5 seconds, which indicates a successful
reset to me (as the watchdog is not refreshed).

Here my startup file:

/* Stack Sizes */
.set USR_STACK_SIZE, 0x00000004 /* stack for "SVC" supervisor
mode is 4 bytes */
.set FIQ_STACK_SIZE, 0x00000004 /* stack for "FIQ" interrupts
is 4 bytes */
.set IRQ_STACK_SIZE, 0X00000004 /* stack for "IRQ" normal
interrupts is 4 bytes */
.set SVC_STACK_SIZE, 0x00000004 /* stack for "SVC" supervisor
mode is 4 bytes */
.set ABT_STACK_SIZE, 0x00000004 /* stack for "abort" interrupts
is 4 bytes */
.set UND_STACK_SIZE, 0x00000004 /* stack for "undefined
instruction" interrupts is 4 bytes */

/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
(program status registers) */
.set MODE_USR, 0x10 /* Normal User Mode
*/
.set MODE_FIQ, 0x11 /* FIQ Processing Fast
Interrupts Mode */
.set MODE_IRQ, 0x12 /* IRQ Processing Standard
Interrupts Mode */
.set MODE_SVC, 0x13 /* Supervisor Processing
Software Interrupts Mode */
.set MODE_ABT, 0x17 /* Abort Processing memory
Faults Mode */
.set MODE_UND, 0x1B /* Undefined Processing
Undefined Instructions Mode */
.set MODE_SYS, 0x1F /* System Running Priviledged
Operating System Tasks Mode */

.set I_BIT, 0x80 /* when I bit is set, IRQ is
disabled (program status registers) */
.set F_BIT, 0x40 /* when F bit is set, FIQ is
disabled (program status registers) */
.text
.arm

.global Reset_Handler
.global _startup
.func _startup

_startup:

# Exception Vectors

_vectors: ldr PC, Reset_Addr
ldr PC, Undef_Addr
ldr PC, SWI_Addr
ldr PC, PAbt_Addr
ldr PC, DAbt_Addr
nop /* Reserved Vector (holds
Philips ISP checksum) */
ldr PC, [PC,#-0x120] /* see page 71 of "Insiders
Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin */
ldr PC, FIQ_Addr

Reset_Addr: .word Reset_Handler /* defined in this module
below */
Undef_Addr: .word UNDEF_Routine /* defined in main.c */
SWI_Addr: .word SWI_Routine /* defined in main.c */
PAbt_Addr: .word UNDEF_Routine /* defined in main.c */
DAbt_Addr: .word UNDEF_Routine /* defined in main.c */
IRQ_Addr: .word IRQ_Routine /* defined in main.c */
FIQ_Addr: .word FIQ_Routine /* defined in main.c */
.word 0 /* rounds the vectors and
ISR addresses to 64 bytes total */
# Reset Handler

Reset_Handler:

.extern TargetResetInit
ldr SP, =_stack_end @ temporary stack at
Stack_Top
LDR R0, =TargetResetInit
MOV LR, PC
BX R0

/* Setup a stack for each mode - note that this only
sets up a usable stack
for User mode. Also each mode is setup with interrupts
initially disabled. */

ldr r0, =_stack_end
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined
Instruction Mode */
mov sp, r0
sub r0, r0, #UND_STACK_SIZE
msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
mov sp, r0
sub r0, r0, #ABT_STACK_SIZE
msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
mov sp, r0
sub r0, r0, #FIQ_STACK_SIZE
msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
mov sp, r0
sub r0, r0, #IRQ_STACK_SIZE
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor
Mode */
mov sp, r0
sub r0, r0, #SVC_STACK_SIZE
msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */
mov sp, r0

/* copy .data section (Copy from ROM to RAM) */
ldr R1, =_etext
ldr R2, =_data
ldr R3, =_edata
1: cmp R2, R3
ldrlo R0, [R1], #4
strlo R0, [R2], #4
blo 1b

/* Clear .bss section (Zero init) */
mov R0, #0
ldr R1, =_bss_start
ldr R2, =_bss_end
2: cmp R1, R2
strlo R0, [R1], #4
blo 2b

/* Enter the C code */
b main

.endfunc
.end

I am not a startup file god yet and I admit that I don't understand it
that much at all. From what I understand, the stack sizes and the
addresses seem to be configured ok.

Here is my application

/* *********************************************************
Function declarations
********************************************************* */

void IRQ_Routine (void) __attribute__ ((interrupt("IRQ")));
void FIQ_Routine (void) __attribute__ ((interrupt("FIQ")));
void SWI_Routine (void) __attribute__ ((interrupt("SWI")));
void UNDEF_Routine (void) __attribute__ ((interrupt("UNDEF")));

void flashled ( int );

/**********************************************************
Header files
**********************************************************/
#include "LPC23xx.h"

/**********************************************************
MAIN
**********************************************************/

int main (void) {
// WDMOD = 0x3; // Puts WDEN = 1 and WDRESET = 1 (underflow will
reset microcontroller)
WDMOD = 0x1; // Puts WDEN = 1 (interrupt will be generated )
WDTC = 0x00FFFFFF;
WDFEED = 0xAA;
WDFEED = 0x55;

// Configure interrupt controllers
VICVectCntl0 = 0x00000000; //Set Slot 0 to the
highest priority
VICVectAddr0 = (unsigned)FIQ_Routine; //pass the address of the
IRQ into the VIC slot
VICIntSelect = 0x00000001; // Convert the interrupt to
an FIQ interrupt
VICIntEnable = 0xFFFFFFFD; // enable ALL interrupts

flashled(5);

while (1) {
};
return 0;
}
/* Stubs for various interrupts (may be replaced later) */
/* ---------------- */

void IRQ_Routine (void) {
flashled(5);
}

void FIQ_Routine (void) {
flashled(2);
}

void SWI_Routine (void) {
flashled(15);
}

void UNDEF_Routine (void) {
flashled(10);
}

// This flashes the LED STAT i times
void flashled( int i ) {
IODIR1 |= 0x00080000; // pin P1.19 is an
output, everything else is input after reset
int counter, j = 0; // initialise
counter and j
for( counter = 0; counter < i; counter++ ) // Run the loop i
times
{
j = 0;
IOCLR1 = 0x00080000; // Enable LED
while( j < 2000000 ) { // wait for this
number of cycles before quitting
if( j == 1000000 ) { // Disable LED on
this condition
IOSET1 = 0x00080000; // Disable LED
}
j++; // Increase cycle
counter
}
}
}

Now can anyone please tell me what I am doing wrong?
How do I trigger the FIQ? As far as I understand, I only need to set
VICIntSelect
VICIntEnable
to the right settings (for watchdog, this is bit 0 ) so both should be
set = 1.

How would I trigger the normal IRQ. My understanding is to only set
VICIntEnable
VICVectCntlX (Priority)
VICVectAddrX
In the last two cases, my understanding goes a bit dumm on how to use
them. Which priority register would I use?. My assumption is to use the
same VICVectAddr register as the required interrupt (so as the watchdog
is on bit 0, i would also use ViCVectAddr0 ?? )

Thank you all for your help and support to improve my understanding (and
getting the code to work :) )

Best wishes,

Stefan



An Engineer's Guide to the LPC2100 Series

On 27.11.2011 15:08, stefan_bluhm wrote:
> I am struggling quite a bit in getting the IRQs to work. I am being a
> bit difficult on setting up the whole IRQ environment. FIQ as well as
> IRQ...

I took a quick glance over your code and didn't find anything clearly
wrong. Anything other than I didn't find your code enabling interrupts
globally. You have to enable interrupts also in program status register.
Did you do that? I can't give you an example right here but, now that
you know what to look for, you probably find one easily.

--

Timo
Dear Timo,

thank you for pointing this out. I didn't realise I have to enable
interrupts globally and couldnt find any indicators anywhere. I will
check all my documentations again on how to do it. Would be great if
anyone else know and lets me know where to find this info.

Thanks a lot,

Stefan
--- In l..., Timo wrote:

> I took a quick glance over your code and didn't find anything clearly
> wrong. Anything other than I didn't find your code enabling interrupts
> globally. You have to enable interrupts also in program status
register.
> Did you do that? I can't give you an example right here but, now that
> you know what to look for, you probably find one easily.
>
> --
>
> Timo
>

On 27.11.2011 17:32, stefan_bluhm wrote:
> ... where to find this info.

Here is one example:

asm volatile("mrs r12, cpsr\n"
"bic r12, r12, #0xC0\n"
"msr cpsr_c, r12" ::: "r12", "cc");

from this page:

http://www.ethernut.de/en/documents/arm-inline-asm.html

--

Timo

The 2024 Embedded Online Conference