Hi, I have the LPC2104 kit. I've used the IAR-System for developing so far but I would like to try the GNU ARM. I've rebuilt several existing applications that use interrupts but they don't work with GNU ARM. How can I use interrupts with GNU ARM? Attached I send an example of a code that works with IAR and doesn't work with GNU ARM. Is the crt0.s or led.c a problem? Help is appreciated. __________________________________ |
|
[gnu arm] interrupts don't work :/
Started by ●August 29, 2004
Reply by ●August 29, 20042004-08-29
The attachment: http://149.156.124.14/~pluto/tmp/led.zip __________________________________ |
Reply by ●August 30, 20042004-08-30
interrupt keyword does not work in GCC 3.3.1 http://gcc.gnu.org/bugzilla/show_bug.cgi?id637 try a new version or refer to http://groups.yahoo.com/group/lpc2000/message/223 --- In , Pawel Sikora <rzulfik@y...> wrote: > Hi, > > I have the LPC2104 kit. > I've used the IAR-System for developing so far > but I would like to try the GNU ARM. > I've rebuilt several existing applications > that use interrupts but they don't work with GNU ARM. > > How can I use interrupts with GNU ARM? > Attached I send an example of a code that works > with IAR and doesn't work with GNU ARM. > > Is the crt0.s or led.c a problem? > > Help is appreciated. |
|
Reply by ●September 3, 20042004-09-03
--- lpc2100 <> wrote: > interrupt keyword does not work in GCC 3.3.1 > http://gcc.gnu.org/bugzilla/show_bug.cgi?id637 > > try a new version or refer to I am using a GNUARM-3.4.1. [fragment of app.s] irq_handler: @ Interrupt Service Routine. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 1, uses_anonymous_args = 0 str ip, [sp, #-4]! mov ip, sp stmfd sp!, {r0, r1, r2, r3, r4, fp, ip, lr, pc} sub fp, ip, #4 mvn r4, #4032 sub r4, r4, #15 ldr r3, [r4, #0] mov lr, pc mov pc, r3 mov r3, #0 str r3, [r4, #0] ldmfd sp, {r0, r1, r2, r3, r4, fp, sp, lr} ldmfd sp!, {ip} subs pc, lr, #4 Everything (except VIC) works fine. I don't known what is wrong :( [app.c] #include "iolpc210x_gcc.h" #define bit(n) (1U << (n)) static void delay(int d) { while (d > 0) d--; } typedef enum { YELLOW, GREEN, RED } LEDS; static void ledOn(LEDS led) { switch (led) { case YELLOW: IOCLR.bit.P0_12 = 1; break; case GREEN: IOCLR.bit.P0_25 = 1; break; case RED: IOCLR.bit.P0_26 = 1; break; } } static void ledOff(LEDS led) { switch (led) { case YELLOW: IOSET.bit.P0_12 = 1; break; case GREEN: IOSET.bit.P0_25 = 1; break; case RED: IOSET.bit.P0_26 = 1; break; } } static volatile int ledStatus = 0; void timer0_isr() { ledStatus = !ledStatus; if (ledStatus) ledOff(RED); else ledOn(RED); T0IR.reg = 0xFF; } void init_timer() { VICIntSelect.reg &= ~bit(VIC_TIMER0); VICVectAddr2 = (unsigned)&timer0_isr; VICVectCntl2.reg = 0x20 | VIC_TIMER0; VICIntEnable.reg = bit(VIC_TIMER0); T0TCR.bit.CE = 0; T0TCR.bit.CR = 1; T0MR0 = (14745600/4)/2; // 2Hz T0PC = 0; T0MCR.bit.MR0INT = 1; T0MCR.bit.MR0RES = 1; T0CCR.reg = 0; T0EMR.reg = 0; T0TCR.bit.CE = 1; } void __irq irq_handler() { ((void (*)())VICVectAddr)(); VICVectAddr = 0; } int main() { PINSEL0.bit.P0_12 = 0; PINSEL1.bit.P0_25 = 0; PINSEL1.bit.P0_26 = 0; IODIR.bit.P0_12 = 1; IODIR.bit.P0_25 = 1; IODIR.bit.P0_26 = 1; ledOff(RED); ledOff(YELLOW); ledOff(GREEN); init_timer(); while (1) { ledOn(YELLOW); delay(50000); ledOff(YELLOW); delay(50000); } } [startup.s] .set SYSTEM_MODE, 0x1F .set UNDEFINED_MODE, 0x1B .set ABORT_MODE, 0x17 .set SUPERVISOR_MODE, 0x13 .set IRQ_MODE, 0x12 .set FIQ_MODE, 0x11 .set USER_MODE, 0x10 .text .arm .align 0 # exception vectors ldr pc, reset_handler_addr ldr pc, undefined_instruction_handler_addr ldr pc, software_interrupt_handler_addr ldr pc, prefetch_abort_handler_addr ldr pc, data_abort_handler_addr ldr pc, endless_loop ldr pc, irq_handler_addr ldr pc, fiq_handler_addr reset_handler_addr: .long reset_handler undefined_instruction_handler_addr: .long undefined_instruction_handler software_interrupt_handler_addr: .long software_interrupt_handler prefetch_abort_handler_addr: .long prefetch_abort_handler data_abort_handler_addr: .long data_abort_handler .long 0 /* ARM-reserved vector */ irq_handler_addr: .long irq_handler fiq_handler_addr: .long fiq_handler .global reset_handler reset_handler: msr cpsr_c, #UNDEFINED_MODE ldr sp, =__UNDEFINED_SP__ msr cpsr_c, #ABORT_MODE ldr sp, =__ABORT_SP__ msr cpsr_c, #SUPERVISOR_MODE ldr sp, =__SUPERVISOR_SP__ msr cpsr_c, #IRQ_MODE ldr sp, =__IRQ_SP__ msr cpsr_c, #FIQ_MODE ldr sp, =__FIQ_SP__ msr cpsr_c, #USER_MODE ldr sp, =__USER_SP__ # setup a default stack limit (when compiled with "-mapcs-stack-check"). sub sl, sp, #__USER_STACK_SIZE__ # relocate .data(rw) section (copy from FLASH to RAM). ldr r1, =__text_end__ ldr r2, =__data_start__ ldr r3, =__data_end__ reset_handler_L01: cmp r2, r3 ldrlo r0, [r1], #4 strlo r0, [r2], #4 blo reset_handler_L01 # clear .bss(rw) section. mov r0, #0 ldr r1, =__bss_start__ ldr r2, =__bss_end__ reset_handler_L02: cmp r1, r2 strlo r0, [r1], #4 blo reset_handler_L02 # set up arguments to main and call. mov r0, #0 mov r1, #0 bl main .global endless_loop endless_loop: b endless_loop .end [lpc2104.ld] MEMORY { FLASH(rx) : ORIGIN = 0x00000000, LENGTH = 128K RAM(rw) : ORIGIN = 0x40000000, LENGTH = 16K } __STACK_START__ = 0x40000000 + 16K; __UNDEFINED_STACK_SIZE__ = 0x0004; __ABORT_STACK_SIZE__ = 0x0004; __SUPERVISOR_STACK_SIZE__ = 0x0004; __FIQ_STACK_SIZE__ = 0x0004; __IRQ_STACK_SIZE__ = 0x0080; __USER_STACK_SIZE__ = 0x0200; __UNDEFINED_SP__ = __STACK_START__ - 4; __ABORT_SP__ = __UNDEFINED_SP__ - __UNDEFINED_STACK_SIZE__; __SUPERVISOR_SP__ = __ABORT_SP__ - __ABORT_STACK_SIZE__; __FIQ_SP__ = __SUPERVISOR_SP__ - __SUPERVISOR_STACK_SIZE__; __IRQ_SP__ = __FIQ_SP__ - __FIQ_STACK_SIZE__; __USER_SP__ = __IRQ_SP__ - __IRQ_STACK_SIZE__; SECTIONS { . = 0; .text : { __text_start__ = .; startup.o(.text) *(.text) *(.glue_7) *(.glue_7t) } >FLASH =0 . = ALIGN(4); .rodata : { *(.rodata) *(.rodata*) } >FLASH . = ALIGN(4); __text_end__ = .; .data : AT(__text_end__) { __data_start__ = .; *(.data) } >RAM . = ALIGN(4); __data_end__ = .; .bss : { __bss_start__ = .; *(.bss) *(COMMON) } >RAM . = ALIGN(4); __bss_end__ = .; } PROVIDE(undefined_instruction_handler = endless_loop); PROVIDE(software_interrupt_handler = endless_loop); PROVIDE(prefetch_abort_handler = endless_loop); PROVIDE(data_abort_handler = endless_loop); PROVIDE(irq_handler = endless_loop); PROVIDE(fiq_handler = endless_loop); __________________________________________________ |
|
Reply by ●September 6, 20042004-09-06
You are running in user mode...try system mode. (see startup.s) --- In , Pawel Sikora <rzulfik@y...> wrote: > > --- lpc2100 <lpc2100@y...> wrote: > > > interrupt keyword does not work in GCC 3.3.1 > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id637 > > > > try a new version or refer to > > I am using a GNUARM-3.4.1. > > [fragment of app.s] > > irq_handler: > @ Interrupt Service Routine. > @ args = 0, pretend = 0, frame = 0 > @ frame_needed = 1, uses_anonymous_args = 0 > str ip, [sp, #-4]! > mov ip, sp > stmfd sp!, {r0, r1, r2, r3, r4, fp, ip, lr, pc} > sub fp, ip, #4 > mvn r4, #4032 > sub r4, r4, #15 > ldr r3, [r4, #0] > mov lr, pc > mov pc, r3 > mov r3, #0 > str r3, [r4, #0] > ldmfd sp, {r0, r1, r2, r3, r4, fp, sp, lr} > ldmfd sp!, {ip} > subs pc, lr, #4 > > Everything (except VIC) works fine. > I don't known what is wrong :( > > [app.c] > > #include "iolpc210x_gcc.h" > #define bit(n) (1U << (n)) > > static void delay(int d) > { > while (d > 0) > d--; > } > > typedef enum { YELLOW, GREEN, RED } LEDS; > > static void ledOn(LEDS led) > { > switch (led) > { > case YELLOW: IOCLR.bit.P0_12 = 1; break; > case GREEN: IOCLR.bit.P0_25 = 1; break; > case RED: IOCLR.bit.P0_26 = 1; break; > } > } > > static void ledOff(LEDS led) > { > switch (led) > { > case YELLOW: IOSET.bit.P0_12 = 1; break; > case GREEN: IOSET.bit.P0_25 = 1; break; > case RED: IOSET.bit.P0_26 = 1; break; > } > } > > static volatile int ledStatus = 0; > > void timer0_isr() > { > ledStatus = !ledStatus; > if (ledStatus) > ledOff(RED); > else > ledOn(RED); > T0IR.reg = 0xFF; > } > > void init_timer() > { > VICIntSelect.reg &= ~bit(VIC_TIMER0); > VICVectAddr2 = (unsigned)&timer0_isr; > VICVectCntl2.reg = 0x20 | VIC_TIMER0; > VICIntEnable.reg = bit(VIC_TIMER0); > > T0TCR.bit.CE = 0; > T0TCR.bit.CR = 1; > T0MR0 = (14745600/4)/2; // 2Hz > T0PC = 0; > T0MCR.bit.MR0INT = 1; > T0MCR.bit.MR0RES = 1; > T0CCR.reg = 0; > T0EMR.reg = 0; > T0TCR.bit.CE = 1; > } > > void __irq irq_handler() > { > ((void (*)())VICVectAddr)(); > VICVectAddr = 0; > } > > int main() > { > PINSEL0.bit.P0_12 = 0; > PINSEL1.bit.P0_25 = 0; > PINSEL1.bit.P0_26 = 0; > IODIR.bit.P0_12 = 1; > IODIR.bit.P0_25 = 1; > IODIR.bit.P0_26 = 1; > ledOff(RED); > ledOff(YELLOW); > ledOff(GREEN); > init_timer(); > while (1) > { > ledOn(YELLOW); delay(50000); > ledOff(YELLOW); delay(50000); > } > } > > [startup.s] > > .set SYSTEM_MODE, 0x1F > .set UNDEFINED_MODE, 0x1B > .set ABORT_MODE, 0x17 > .set SUPERVISOR_MODE, 0x13 > .set IRQ_MODE, 0x12 > .set FIQ_MODE, 0x11 > .set USER_MODE, 0x10 > > .text > .arm > .align 0 > > # exception vectors > ldr pc, reset_handler_addr > ldr pc, undefined_instruction_handler_addr > ldr pc, software_interrupt_handler_addr > ldr pc, prefetch_abort_handler_addr > ldr pc, data_abort_handler_addr > ldr pc, endless_loop > ldr pc, irq_handler_addr > ldr pc, fiq_handler_addr > > reset_handler_addr: .long reset_handler > undefined_instruction_handler_addr: .long > undefined_instruction_handler > software_interrupt_handler_addr: .long > software_interrupt_handler > prefetch_abort_handler_addr: .long > prefetch_abort_handler > data_abort_handler_addr: .long data_abort_handler > .long 0 /* ARM-reserved vector */ > irq_handler_addr: .long irq_handler > fiq_handler_addr: .long fiq_handler > > .global reset_handler > reset_handler: > msr cpsr_c, #UNDEFINED_MODE > ldr sp, =__UNDEFINED_SP__ > msr cpsr_c, #ABORT_MODE > ldr sp, =__ABORT_SP__ > msr cpsr_c, #SUPERVISOR_MODE > ldr sp, =__SUPERVISOR_SP__ > msr cpsr_c, #IRQ_MODE > ldr sp, =__IRQ_SP__ > msr cpsr_c, #FIQ_MODE > ldr sp, =__FIQ_SP__ > msr cpsr_c, #USER_MODE > ldr sp, =__USER_SP__ > # setup a default stack limit (when compiled with > "-mapcs-stack-check"). > sub sl, sp, #__USER_STACK_SIZE__ > # relocate .data(rw) section (copy from FLASH to RAM). > ldr r1, =__text_end__ > ldr r2, =__data_start__ > ldr r3, =__data_end__ > reset_handler_L01: > cmp r2, r3 > ldrlo r0, [r1], #4 > strlo r0, [r2], #4 > blo reset_handler_L01 > # clear .bss(rw) section. > mov r0, #0 > ldr r1, =__bss_start__ > ldr r2, =__bss_end__ > reset_handler_L02: > cmp r1, r2 > strlo r0, [r1], #4 > blo reset_handler_L02 > # set up arguments to main and call. > mov r0, #0 > mov r1, #0 > bl main > > .global endless_loop > endless_loop: > b endless_loop > > .end > > [lpc2104.ld] > > MEMORY > { > FLASH(rx) : ORIGIN = 0x00000000, LENGTH = 128K > RAM(rw) : ORIGIN = 0x40000000, LENGTH = 16K > } > > __STACK_START__ = 0x40000000 + 16K; > > __UNDEFINED_STACK_SIZE__ = 0x0004; > __ABORT_STACK_SIZE__ = 0x0004; > __SUPERVISOR_STACK_SIZE__ = 0x0004; > __FIQ_STACK_SIZE__ = 0x0004; > __IRQ_STACK_SIZE__ = 0x0080; > __USER_STACK_SIZE__ = 0x0200; > > __UNDEFINED_SP__ = __STACK_START__ - 4; > __ABORT_SP__ = __UNDEFINED_SP__ - > __UNDEFINED_STACK_SIZE__; > __SUPERVISOR_SP__ = __ABORT_SP__ - > __ABORT_STACK_SIZE__; > __FIQ_SP__ = __SUPERVISOR_SP__ - > __SUPERVISOR_STACK_SIZE__; > __IRQ_SP__ = __FIQ_SP__ - __FIQ_STACK_SIZE__; > __USER_SP__ = __IRQ_SP__ - __IRQ_STACK_SIZE__; > > SECTIONS > { > . = 0; > .text : > { > __text_start__ = .; > startup.o(.text) > *(.text) > *(.glue_7) > *(.glue_7t) > } > >FLASH =0 > . = ALIGN(4); > .rodata : > { > *(.rodata) > *(.rodata*) > } > >FLASH > . = ALIGN(4); > __text_end__ = .; > > .data : AT(__text_end__) > { > __data_start__ = .; > *(.data) > } > >RAM > . = ALIGN(4); > __data_end__ = .; > > .bss : > { > __bss_start__ = .; > *(.bss) > *(COMMON) > } > >RAM > . = ALIGN(4); > __bss_end__ = .; > } > > PROVIDE(undefined_instruction_handler = endless_loop); > PROVIDE(software_interrupt_handler = endless_loop); > PROVIDE(prefetch_abort_handler = endless_loop); > PROVIDE(data_abort_handler = endless_loop); > PROVIDE(irq_handler = endless_loop); > PROVIDE(fiq_handler = endless_loop); > __________________________________________________ > |
Reply by ●September 24, 20042004-09-24
As far as I know, attribute interrupt in GCC works incorrect. It's better to use an assembler container, for example: .extern My_C_ISR_Func .global ISR_Func .text .code 32 ISR_Func: stmfd sp!, {r0-r12, lr} bl My_C_ISR_Func ldmfd sp!, {r0-r12, lr} subs pc, lr, #4 .ltorg -- aka cd_racer |
|
Reply by ●September 24, 20042004-09-24
On 24 Sep 2004 at 19:49, Konstantin V. Novick wrote: > > As far as I know, attribute interrupt in GCC works incorrect. [Stuff snipped] I believe this has been fixed in the newer versions of GCC. Regards Anton Erasmus > > > ------------------------ Yahoo! Groups Sponsor > --------------------~--> $9.95 domain names from Yahoo!. Register > anything. http://us.click.yahoo.com/J8kdrA/y20IAA/yQLSAA/dN_tlB/TM > --------------------------------~- > > Yahoo! Groups Links > > -- A J Erasmus |
Reply by ●September 26, 20042004-09-26
You can do the following: MEMMAP = MEMMAP_USERRAMMODE; *(volatile INT32U *)(0x00000018L) = 0xE51FFFF0L; (MEMMAP - see page 33 of UM_LPC2106_2105_2104 - user manual, also you see page 70 of UM_LPC2106_2105_2104). I haven't use GCC's interrupt attribute because of the old GCC version (3.2.0). But from this thread I think that GCC use a single entry-point for IRQ and at this point you are to do a proper jump (using VICVectAddr register, for example). Thus you can use different ARM-based microcontrollers in single way (in fact, the addresses of interrupt registers are different on Atmel's AT91RM9200 and Philips LPC2106). But in this case you are to write your IRQ entry-point function in a proper way. But another way is to place at IRQ vector exception's address (0x00000018) an instruction, that loads an address from VICVectAddr register to PC-register. Thus, there's no need to think about entry-point function. But in this case you are to proper init the exception vector (according to microcontroller's user manual) and write a proper container for your's IRQ function. |
|
Reply by ●September 27, 20042004-09-27