I've recently come across a few situations where I've seen some "unexpected behaviour" with the Mbed libraries. I'll show one that is probably the easiest to highlight.
Given the code below, the Mbed InterruptIn is used to attach a function to falling edges on P16. However, also defined and the same functionality on P15 but not using an InterruptIn but doing it via one's own method (yes, I know, please don't say "just use an InterruptIn for p15 aswell". This is a demo program to illustrate a point).
#include "mbed.h"
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
InterruptIn p16irq(p16);
Serial pc(USBTX, USBRX);
uint32_t oldVector = NULL;
typedef void (*FN)(void);
extern "C" void p15_IRQHandler (void) __irq {
/* Test for IRQ on Port0. */
if (LPC_GPIOINT->IntStatus & 0x1) {
/* p15 (Port0.23) falling interrupt? */
if (LPC_GPIOINT->IO0IntStatF & (1 << 23)) {
myled2 = !myled2;
LPC_GPIOINT->IO0IntClr = (1 << 23);
}
else {
/* If it's an unexpected IRQ then chain
onto the old interrupt handler and hope
it will deal with it. */
if (oldVector) {
((FN)oldVector)();
}
}
}
}
void p15irq_init(void) {
/* Enable a falling IRQ for p15 */
LPC_GPIOINT->IO0IntEnF |= ( (1UL << 23) );
/* Store the old interrupt vector to chain to. */
oldVector = NVIC_GetVector(EINT3_IRQn);
NVIC_SetVector(EINT3_IRQn, (uint32_t)p15_IRQHandler);
NVIC_EnableIRQ(EINT3_IRQn);
}
void flip1(void) {
myled1 = !myled1;
}
int main() {
int i;
/* Don't call this here, see comments below. */
// p15irq_init();
p16irq.mode(PullUp);
p16irq.fall(&flip1);
/* It's ok to call this AFTER the p16 setup above
because we chain the interrupt. But not BEFORE
because the InterruptIn library doesn't chain
to the previous vector if it cannot handle the
interrupt. */
p15irq_init();
while(1) {
myled4 = 1;
wait(0.2);
myled4 = 0;
wait(0.2);
}
}
It should be fairly obvious what the problem is from the comments but basically the Mbed InterruptIn library takes control of the interrupt vector in a "total fashion". It doesn't respect the previous contents of the vector and use it if it fails to handle the irq. In the above example, dabbing p15 or p16 will flip the leds as shown. However, if you move the call to p15_init() before the p16 setup, then you're in trouble. First, the Mbed interrupt handler isn't expecting p15 to generate an interrupt, quite right to, it's never been told or setup to handle it.
But then it fails in two respects. First, it doesn't call the old irq vector it replaced. But second, in not doing so, it fails to provide a "default" handler that clears the interrupt. So, if you hit p15 then you basically get stuck in an infinite interrupt loop.
Can the libraries ensure they chain interrupts so as to "play nice" with code that may lie outside of what it's expecting but has a;ready been setup to handle it? Otherwise, we'll have a "use the Mbed libraries, or homebrew, but not both" situation arising. Also, people writing libraries that use low level code my well come unstuck also and find their libraries won't be compat with Mbed libraries.
--Andy
I've recently come across a few situations where I've seen some "unexpected behaviour" with the Mbed libraries. I'll show one that is probably the easiest to highlight.
Given the code below, the Mbed InterruptIn is used to attach a function to falling edges on P16. However, also defined and the same functionality on P15 but not using an InterruptIn but doing it via one's own method (yes, I know, please don't say "just use an InterruptIn for p15 aswell". This is a demo program to illustrate a point).
It should be fairly obvious what the problem is from the comments but basically the Mbed InterruptIn library takes control of the interrupt vector in a "total fashion". It doesn't respect the previous contents of the vector and use it if it fails to handle the irq. In the above example, dabbing p15 or p16 will flip the leds as shown. However, if you move the call to p15_init() before the p16 setup, then you're in trouble. First, the Mbed interrupt handler isn't expecting p15 to generate an interrupt, quite right to, it's never been told or setup to handle it.
But then it fails in two respects. First, it doesn't call the old irq vector it replaced. But second, in not doing so, it fails to provide a "default" handler that clears the interrupt. So, if you hit p15 then you basically get stuck in an infinite interrupt loop.
Can the libraries ensure they chain interrupts so as to "play nice" with code that may lie outside of what it's expecting but has a;ready been setup to handle it? Otherwise, we'll have a "use the Mbed libraries, or homebrew, but not both" situation arising. Also, people writing libraries that use low level code my well come unstuck also and find their libraries won't be compat with Mbed libraries.
--Andy