I have a routine to enable external interrupts and I want to discard any pending ones before enabling them again.
That's the code I use (MCUXpresso IDE v11.5.0 [Build 7232] [2022-01-11], LPC 4330 M4, O3 compilation):
Chip_PININT_ClearIntStatus(LPC_GPIO_PIN_INT, PININTCH(pinint_index));
NVIC_ClearPendingIRQ(nvic_name);
NVIC_EnableIRQ(nvic_name);
The problem is that pending interrupts keep triggering as soon as I enable the irq in the NVIC, even though I've cleared them.
Introducing a delay or a __DSB between Chip_PININT_ClearIntStatus and NVIC_ClearPendingIRQ solves the problem, but I'd like to understand what's going on here.
These are the assemblies produced without and with the DSB
With DSB
00000000 <xxx>:
0: 4b0a ldr r3, [pc, #40] ; (2c <xxx+0x2c>)
2: 2201 movs r2, #1
4: fa02 f000 lsl.w r0, r2, r0
8: 6258 str r0, [r3, #36] ; 0x24
a: f3bf 8f4f dsb sy
e: 094b lsrs r3, r1, #5
10: 009b lsls r3, r3, #2
12: f103 4360 add.w r3, r3, #3758096384 ; 0xe0000000
16: f503 4361 add.w r3, r3, #57600 ; 0xe100
1a: f001 011f and.w r1, r1, #31
1e: fa02 f101 lsl.w r1, r2, r1
22: f8c3 1180 str.w r1, [r3, #384] ; 0x180
26: 6019 str r1, [r3, #0]
28: 4770 bx lr
2a: bf00 nop
2c: 40087000 .word 0x40087000
Without DSB
00000000 <xxx>:
0: 094b lsrs r3, r1, #5
2: 009b lsls r3, r3, #2
4: 2201 movs r2, #1
6: f103 4360 add.w r3, r3, #3758096384 ; 0xe0000000
a: f001 011f and.w r1, r1, #31
e: fa02 f101 lsl.w r1, r2, r1
12: f503 4361 add.w r3, r3, #57600 ; 0xe100
16: fa02 f000 lsl.w r0, r2, r0
1a: 4a03 ldr r2, [pc, #12] ; (28 <xxx+0x28>)
1c: 6250 str r0, [r2, #36] ; 0x24
1e: f8c3 1180 str.w r1, [r3, #384] ; 0x180
22: 6019 str r1, [r3, #0]
24: 4770 bx lr
26: bf00 nop
28: 40087000 .word 0x40087000
As you can see, without __DSB the stores are all delayed until the end. That makes me think if there are some cycles we need to wait for the clearing of the interrupt to be effective. I've searched the user manual and the code examples with the IDE but couldn't find anything.
I understand it can also be some memory reordering in the micro, but I'm not sure. So, what I'm looking for here 1) an explanation for that behaviour and 2) if there's any recommended (or mandatory) way of clearing the interrupt flags to avoid the problem.
Thanks!
It is maybe related to this:
https://community.nxp.com/t5/Kinetis-Microcontrollers/ARM-errata-838869/m-p/1029107
point is that the M4 has a silicon bug, basically requiring a DSB at the end of the ISR.
So this might be what you need to do?