Hi,
There's a problem with using C++ and KDS 3.2.0 and the provided device drivers on an FRDM-KW41Z kit.
If I create a new project using the Kinetis SDK 2.x Project wizard:
Now, if I replace the contents of main.c with those from the gpio_input_interrupt_frdmkw41z example:
/* * Copyright (c) 2015, Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * o Neither the name of Freescale Semiconductor, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "fsl_debug_console.h" #include "fsl_port.h" #include "fsl_gpio.h" #include "fsl_common.h" #include "board.h" #include "pin_mux.h" #include "clock_config.h" /******************************************************************************* * Definitions ******************************************************************************/ #define BOARD_LED_GPIO BOARD_LED_RED_GPIO #define BOARD_LED_GPIO_PIN BOARD_LED_RED_GPIO_PIN #define BOARD_SW_GPIO BOARD_SW3_GPIO #define BOARD_SW_PORT BOARD_SW3_PORT #define BOARD_SW_GPIO_PIN BOARD_SW3_GPIO_PIN #define BOARD_SW_IRQ BOARD_SW3_IRQ #define BOARD_SW_IRQ_HANDLER BOARD_SW3_IRQ_HANDLER #define BOARD_SW_NAME BOARD_SW3_NAME /******************************************************************************* * Prototypes ******************************************************************************/ /******************************************************************************* * Variables ******************************************************************************/ /* Whether the SW button is pressed */ volatile bool g_ButtonPress = false; /******************************************************************************* * Code ******************************************************************************/ /*! * @brief Interrupt service fuction of switch. * * This function toggles the LED */ void BOARD_SW_IRQ_HANDLER(void) { /* Clear external interrupt flag. */ GPIO_ClearPinsInterruptFlags(BOARD_SW_GPIO, 1U << BOARD_SW_GPIO_PIN); /* Change state of button. */ g_ButtonPress = true; /* Toggle LED. */ GPIO_TogglePinsOutput(BOARD_LED_GPIO, 1U << BOARD_LED_GPIO_PIN); } /*! * @brief Main function */ int main(void) { /* Define the init structure for the input switch pin */ gpio_pin_config_t sw_config = { kGPIO_DigitalInput, 0, }; /* Define the init structure for the output LED pin */ gpio_pin_config_t led_config = { kGPIO_DigitalOutput, 0, }; BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); /* Print a note to terminal. */ PRINTF("\r\n GPIO Driver example\r\n"); PRINTF("\r\n Press %s to turn on/off a LED \r\n", BOARD_SW_NAME); /* Init input switch GPIO. */ PORT_SetPinInterruptConfig(BOARD_SW_PORT, BOARD_SW_GPIO_PIN, kPORT_InterruptFallingEdge); EnableIRQ(BOARD_SW_IRQ); GPIO_PinInit(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN, &sw_config); /* Init output LED GPIO. */ GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, &led_config); while (1) { if (g_ButtonPress) { PRINTF(" %s is pressed \r\n", BOARD_SW_NAME); /* Reset state of button. */ g_ButtonPress = false; } } }
And set the pinmux.c settings to those of the gpio_input_interrupt_frdmkw41z example:
void BOARD_InitPins(void) { /* Initialize LPUART0 pins below */ /* Ungate the port clock */ CLOCK_EnableClock(kCLOCK_PortC); /* Affects PORTC_PCR6 register */ PORT_SetPinMux(PORTC, 6U, kPORT_MuxAlt4); /* Affects PORTC_PCR7 register */ PORT_SetPinMux(PORTC, 7U, kPORT_MuxAlt4); /* Affects PORTC_PCR4 register */ port_pin_config_t config; config.pullSelect = kPORT_PullUp; config.mux = kPORT_MuxAsGpio; PORT_SetPinConfig(PORTC, 4U, &config); /* LED PIN_MUX Configuration */ PORT_SetPinMux(PORTC, 1U, kPORT_MuxAsGpio); }
If I then rename main.c to main.cpp and recompile, everything builds fine.
However, when I then debug the program and press SW3 on the FRDM-KW41Z board, it always jumps to the wrong interrupt handler (which is by default an endless loop):
I'm not sure why this is the case, but this isn't something I would have expected.
If I build and run the program as main.c, everything works correctly.
I've attached a ZIP file with the example project. Basically it's gpio_input_interrupt_frdmkw41z but using C++ to build it instead of C.
This problem makes it effectively impossible to use C++ instead of C, since the only difference in builds is the compiler involved!
Thanks,
Max
Original Attachment has been moved to: Test.zip
Solved! Go to Solution.
Hello Max,
Sorry for i haven't this board , so i can not test your project.
I test a simple project include interrupt on other kenitis chip, only change the name main.c to main.cpp,
it can work well.
Could you please test a bare board project , without RTOS .
if still can not work, please add the below code in the interrupt function :
#ifdef __cplusplus
extern "C" {
#endif
" interrupt function "
#ifdef __cplusplus
} /* extern "C" */
#endif
or
extern "C" {
"interrupt function"
} /* extern "C" */
BR
Alice
Hi Alice,
Thanks for the suggestion, it worked.
I guess it would be good for future versions of the Kinetis SDK to make sure that all interrupt handlers are wrapped to use C linkage.
Cheers,
Max
Hello Max,
Sorry for i haven't this board , so i can not test your project.
I test a simple project include interrupt on other kenitis chip, only change the name main.c to main.cpp,
it can work well.
Could you please test a bare board project , without RTOS .
if still can not work, please add the below code in the interrupt function :
#ifdef __cplusplus
extern "C" {
#endif
" interrupt function "
#ifdef __cplusplus
} /* extern "C" */
#endif
or
extern "C" {
"interrupt function"
} /* extern "C" */
BR
Alice