How to use an interrupt on Cortex – M3

armassembly

I am trying to set up the chip so it will detect a rising edge on a pin then start outputting a square wave on the next pin over after that.

I have the interrupt turned on but I don't know how to say "if interrupt is triggered, run the wave generator". I've scoured the data sheet but I can't seem to understand it.

; New asm data section
    AREA square_func, CODE, READONLY
; Export back to C
    EXPORT square_wave
    ALIGN
square_wave
    LDR     R1,=0x2009c000      ; Pointer to base of port 0 
    LDR     R2,=0x00000001      ; To control pin 0
    LDR     R3,=0x00000001      ; For XOR to invert pin 0
    STR     R2,[R1,#0x00]       ; Set pin 0 to output (base+0x00)
    STR     R2,[R1,#0x14]       ; Turn on pin 0
    LDR     R4,=749             ; Set up timer
    LDR     R6,=0x40028090      ; Interupt pointer for port 0
    LDR     R7,=0x00000002      ; For pin 1
    STR     R7,[R6]             ; Set pin 1 to rising edge interrupt
loop
    SUB     R4, 1               ; Decrement timer
    CMP     R4, 0               ; Compare to 0
    BNE     loop                ; If !0, keep looping
    LDR     R4,=749             ; Reset timer
    EOR     R2,R3               ; Invert bits
    STR     R2,[R1,#0x14]       ; Invert pin
    MUL     R3,R3,R3            ; To waste cycles, ignore (1*1=1)
    B       loop                ; Restart loop
    ALIGN

Best Answer

The interrupt mechanism is described in the ARM Architectural Reference Manual and/or the Technical Reference Manual, both are available at infocenter.arm.com. Then there is some info that you need from the chip vendors datasheet (arm does not make chips they make processor cores that chip vendors buy and use). so unlike the traditional arm with an irq and fiq input the cortex-m3 has a bunch of interrupt inputs and you have to figure out where the vendor wired your interrupt.

The way the cortex-m's work you have an interrupt vector table which includes addresses for the routines for each of the interrupts/exceptions. (described in the ARM ARM and/or ARM TRM) reset happens to be one of those so you already have that implemented, the first four bytes are loaded into the stack pointer then the next four are the address for reset then it goes into exceptions and interrupts which are core specific (the cortex-m3 and cortex-m4 and cortex-m0 dont necessarily have the exact same list and certainly each vendor or model may have different things wired up).

Then of course you have to enable interrupts on the vendor side, the peripheral, perhaps an interrupt controller then on the arm side.

The nice thing about the cortex-m design is that the hardware conforms to the arm calling convention (it preserves registers for you on the stack, etc), you can place the address to a C function right in the vector table, there is no longer a need to wrap your C interrupt handler with assembly or use compiler specific directives to get the compiler to wrap your code for handling interrupts.

I generally recommend that you start by polling your way toward the core, if possible poll the peripheral interrupt status to see if it fired, then enable that status to go on to the next level, poll that, then enable that eventually to the edge of the core where you can usually poll it without enabling it into the core. YMMV, some folks like to just Christmas Tree light it all up at once and see what happens (write the finished code first then debug a bunch of code not knowing where to start looking).