I've read all the threads on this that I can find, and still can't see what I'm doing wrong

Edit: OK, I found my mistake which, of course, had nothing to do with anything interrupty. I'm posting this anyway as a how-to for anyone else interested in this. Most code available seems to be in C.
What I think I'm doing is:
1. Setting pins GPIO30 and 31 as INPUT with PULLUP resistors.
2. Setting GPAFEN0 to detect a falling edge on GPIO30
3. Setting the GPU (in IRQ2_EN) to generate interrupts for gpio_int[1] <<<< EDIT2: curious bug?
4. I have a branch to my interrupt service routine, irq, at 0x0018 in the jump table. (I have my kernel loaded at 0x0000)
5. I enable interrupts in the CPSR
6. The ISR checks if the interrupt was due to gpio_int[0] <<<< EDIT2: curious bug? and branches to the handler gpio_0_irq if it was.
7. gpio_0_irq writes a 1<<30 to GPIO_EDS0 to clear the interrupt on GPIO30 ...
8. ... and reads the level on the GPIO31 pin
Things to note (this is intended as documentation for anyone else trying to get interrupts working):
The BCM2835 has 54 GPIO pins. These are organised in two banks, ie bank 0 [31:0] for GPIO31-0 and bank 1 [22:0] for GPIO54-32. These are the 0 and 1 used for the GPIO registers like GPSET1, GPCLR0, GPCLR1, GPLEV0, GPLEV1, GPEDS0, GPEDS1, GPREN0, GPREN1... (There's only one GPPUD, because only GPIO0-31 have pullup/down resistors).
Note that none of the GPIO pins in the second bank (GPIO32-54) is available on any headers, which is a shame, because it makes getting two different interrupts from the GPIO pins difficult. In fact, only GPIO40/45 are used at all and are connected to PWM0/1_OUT. Well, GPIO46-53 are used for HDMI and the SD card, but I don't want to mess with those...)
The GPU interrupts are "not very well documented." (*) However, there are 64 of them, also organised in two banks (which have nothing to do with the two banks of GPIO pins. TWO BANKS simply means there are more than 32 (but <= 64) of whatever it is). To show that these are different things (**), the designers have chosen to call these two banks 1 and 2 (instead of 0 and 1). These are the 1 and 2 used for the IRQ registers like IRQ1_PDG, IRQ2_PDG, IRQ1_EN, IRQ2_EN (my names for the registers).
(*) understatement
(**) sarcasm
The first bank of GPIO pins is said to generate one GPU interrupt the second another with a third being generated (as well) by both. It is guessed that the first bank generates gpio_irq[0] and the second bank gpio_irq[1]. These are the GPU IRQs 49 and 50 (ie. bits 17 and 18 in the second IRQ bank). <<<< EDIT2: Apparently this guess is incorrect.
>>>>
This is odd.
Code: Select all
ldr r1, =IRQ_base
mov r0, #0x1<<18 // enable gpio_int[0] (17 = GPU intrpt 49 - 32)
str r0, [r1, #IRQ_IRQ2_EN] // (- 32, to get 2nd bank of 32 intrpts)
pop {pc}
//***********************************************
.globl irq
irq:
push {r0,r1,lr}
ldr r1, =IRQ_base
ldr r0, [r1, #IRQ_IRQ2_PDG]
tst r0, #1<<17
bleq gpio_0_irq
<<<<
Here's my feeble attempt...
Code: Select all
.section .text
// header-pin RPi board signal BCM2835 pin
// P1-1,17 3.3 V
// P1-2,4 5 V
// P1-3,5 SDA1,SCL1 GPIO2,3
// P1-6,9,14,20,25 GND
// P1-8,10 TXD0, RXD0 GPIO14,15
// P1-7 GPIO_GCLK GPIO4 TDI
// P1-11:13,15,16,18,22 GPIO_GEN0:6 GPIO17,18,27,22:25 2TMS 3TRST 5TDO 6TCK
// P1-19,21,23 SPI_MOSI:MISO:SCLK GPIO10,9,11
// P1-24,26 SPI_CE0_N:CE_1_N GPIO8,7
// P5-1 5 V
// P5-2 3.3 V
// P5-3:4 GPIO_GEN7:8 GPIO28:29
// P5-5:6 GPIO_GEN9:10 GPIO30:31
// P5-7:8 GND
.globl init_gpio
init_gpio:
push {lr}
ldr r1, =GPIO_base
ldr r0, [r1, #GPIO_GPFSEL3]
bic r0, #0x7<<0 // CLEAR bits 0000.0111 << (n * 3) set GPIO30 and 31 as INPUT
bic r0, #0x7<<3
str r0, [r1, #GPIO_GPFSEL3]
mov r0, #0b10
str r0, [r1, #GPIO_GPPUD] // enable PULL_UP resistors...
mov r0, #150
bl delay
mov r0, #1<<30 // GPIO pins 30 and 31 = GPIO_GEN9 and 10 (on header P5)
orr r0, #1<<31
str r0, [r1, #GPIO_GPPUDCLK0] // ... on GPIO30, 31
mov r0, #150
bl delay
mov r0, #0
str r0, [r1, #GPIO_GPPUD] // "remove control signal"
str r0, [r1, #GPIO_GPPUDCLK0] // "remove the clock"
mov r0, #1<<30
str r0, [r1, #GPIO_GPAFEN0] // detect asynchronous FALLING EDGE on GPIO30
ldr r1, =IRQ_base
mov r0, #1<<18 // enable gpio_int[0] (17 = GPU intrpt 49 - 32) >>>> odd bug? <<<<
str r0, [r1, #IRQ_IRQ2_EN] // (- 32, to get 2nd bank of 32 intrpts)
pop {pc}
//***********************************************
.globl irq
irq:
push {r0,r1,lr}
ldr r1, =IRQ_base
ldr r0, [r1, #IRQ_IRQ2_PDG]
tst r0, #1<<17
bleq gpio_0_irq
pop {r0,r1,lr}
subs r15, lr, #4 // exit, reinstalling CPSR
//***********************************************
.globl gpio_0_irq
gpio_0_irq:
push {r0,r1}
ldr r1, =GPIO_base
mov r0, #1<<30
str r0, [r1, #GPIO_EDS0] // clear interrupt by writing a 1
ldr r0, [r1, #GPIO_LEV0]
and r0, #1<<31 // read level of GPIO31 pin
pop {r0,r1}
mov pc, lr
//***********************************************
main:
...
mrs r0,cpsr // enable normal interrupts
bic r0,#0x80 // 1000.0000
msr cpsr_c,r0
...
//***********************************************