I'm trying to port ISR code for a pushbutton on the LPC804 (OM40001) from C to C++14. It works fine in C. Unfortunately, in C++, my ISR isn't engaging when I push the pushbutton on the board. Instead, the chip hangs in the while loop found in the IntDefaultHandler() generated by the SDK.
On the LPC804 board I'm using the User pushbutton on the main board and one of the LEDs on the add-on capacitive touch board.
I'm not sure why this is happening and am looking for some advice as to how to figure it out.
James
#include "LPC804.h"
#define LED_USER2 (20) // One of the LED on the capacitive touch board. (PIO0_20)
#define BUTTON_USER1 (13) // GPIO 13 (PIO0_13) is connected to the button.
int main(void) {
// disable interrupts
__disable_irq(); // turn off globally
NVIC_DisableIRQ(PIN_INT0_IRQn); // turn off the PIN INT0 interrupt.
// ----------------------- Begin GPIO setup ------------------------------------
// Set up a general GPIO for use within the Interrupt Service Routine for MRT
// Only the ISR needs the GPIO. (PB8 & PB9)
SYSCON->SYSAHBCLKCTRL0 |= ( SYSCON_SYSAHBCLKCTRL0_GPIO0_MASK | // GPIO is on
SYSCON_SYSAHBCLKCTRL0_GPIO_INT_MASK); // GPIO Interrupt is on
// Put 0 in the GPIO and GPIO Interrupt reset bit to reset it.
// Then put a 1 in the GPIO and GPIO Interrupt reset bit to allow both to operate.
// manual: Section 6.6.10
SYSCON->PRESETCTRL0 &= ~(SYSCON_PRESETCTRL0_GPIO0_RST_N_MASK |
SYSCON_PRESETCTRL0_GPIOINT_RST_N_MASK); // reset GPIO and GPIO Interrupt (bit=0)
SYSCON->PRESETCTRL0 |= (SYSCON_PRESETCTRL0_GPIO0_RST_N_MASK |
SYSCON_PRESETCTRL0_GPIOINT_RST_N_MASK); // clear reset (bit=1)
// Config the Pushbutton for input and LED for output
// Remember: only bits set to 1 have an effect on DIRCLR and DIRSET registers.
// bits cleared to 0 are ignored.
// Therefore, use DIRCLR to select input and DIRSET to select output
GPIO->DIRCLR[0] = (1UL<<BUTTON_USER1); // input on (BUTTON_USER1)
GPIO->CLR[0] = (1UL<<LED_USER2); // LED is on( turn off )
GPIO->DIRSET[0] = (1UL<<LED_USER2); // output on (LED_USER2)
// ----------------------- end of GPIO setup -----------------------------------
// Set up GPIO IRQ: interrupt channel 0 (PINTSEL0) to GPIO
SYSCON->PINTSEL[0] = BUTTON_USER1; // PINTSEL0 is BUTTON_USER1
// Configure the Pin interrupt mode register (a.k.a ISEL) for edge-sensitive
// on PINTSEL0. 0 is edge sensitive. 1 is level sensitive.
PINT->ISEL = 0x00; // channel 0 bit is 0: is edge sensitive (so are the other channels)
// Use IENR or IENF (or S/CIENF or S/CIENR) to set edge type
// Configure Chan 0 for only falling edge detection (no rising edge detection)
PINT->CIENR = 0b00000001; // bit 0 is 1: disable channel 0 IRQ for rising edge
PINT->SIENF = 0b00000001; // bit 0 is 1: enable channel 0 IRQ for falling edge
// Remove any pending or left-over interrupt flags
PINT->IST = 0xFF; // each bit set to 1 removes any pending flag.
// enable global interrupts & GPIO INT channel 0
NVIC_EnableIRQ(PIN_INT0_IRQn); // GPIO interrupt
__enable_irq(); // global
/* Enter an infinite loop, check the pushbutton on GPIO8.*/
while(1)
{
asm("NOP");
}
return 0 ;
}
// ---------------------------------------
// ISR for the GPIO Interrupt
//
// A GPIO interrupt has been detected. Enable the MRT oneshot interrupt
// so that you can check on the GPIO state in a specific amount of time.
// after it has settled out (debounced).
//
// Could check GPIO directly with
// if(GPIO->B[0][8] & 1) // Is GPIO0_8 a 1? GPIO0_8 is the pushbutton
//
// ---------------------------------------
void PIN_INT0_IRQHandler(void)
{
// was an IRQ requested for Channel 0 of GPIO INT?
if (PINT->IST & (1<<0))
{
// remove the any IRQ flag for Channel 0 of GPIO INT
PINT->IST = (1<<0);
// TOggle the LED
GPIO->NOT[0] = (1UL<<LED_USER2); //
}
else
{
asm("NOP"); // Place a breakpt here if debugging.
}
return;
}
Solved! Go to Solution.
yup! it works!
// ---------------------------------------
// ISR for the GPIO Interrupt
//
// A GPIO interrupt has been detected. Enable the MRT oneshot interrupt
// so that you can check on the GPIO state in a specific amount of time.
// after it has settled out (debounced).
//
// Could check GPIO directly with
// if(GPIO->B[0][8] & 1) // Is GPIO0_8 a 1? GPIO0_8 is the pushbutton
//
// for C++ https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Linking_C_and_C.2B.2B_code
// ---------------------------------------
extern "C" {
void PIN_INT0_IRQHandler(void)
{
// was an IRQ requested for Channel 0 of GPIO INT?
if (PINT->IST & (1<<0))
{
// remove the any IRQ flag for Channel 0 of GPIO INT
PINT->IST = (1<<0);
// TOggle the LED
GPIO->NOT[0] = (1UL<<LED_USER2); //
}
else
{
asm("NOP"); // Place a breakpt here if debugging.
}
return;
}
}
thanks! Will try it out.