Freedom KL27 external GPIO Interrupt

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Freedom KL27 external GPIO Interrupt

Jump to solution
2,703 Views
killerawft
Contributor I

Hello.

 

I have a FRDM-K27Z board and want to use a external GPIO Interrupt on PTC3. For testing the GPIO Interrupt i use the Switch 3 on the PTC1. I have the problem, that the Interrupt is never called. I used the example of the KSDK 2.0 and made minimal changes but the Interrupt Function is never called.

 

Below you can see the code i used. Maybe you can find some errors in that code or help me otherwise.

 

 

#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 "fsl_device_registers.h"
#include <stdbool.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;
    PRINTF("\r\n Interrupt Occurred\r\n");
    /* 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(); //Changed from BOARD_BootClockHSRUN(); 
    BOARD_InitDebugConsole();

    CLOCK_EnableClock(kCLOCK_PortA);
    CLOCK_EnableClock(kCLOCK_PortB);
    CLOCK_EnableClock(kCLOCK_PortC);

    /* 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;
        }
    }
}

 

 

Killerawft

 

Edit: I also tested the SW3 itself and the switch worked fine without an Interrupt so the error must be in my code.

Edit 2: i tested the same Code as above with the SW1 and the line 

PORT_SetPinMux(BOARD_SW_PORT, BOARD_SW_GPIO_PIN, kPORT_MuxAsGpio);

after line 80 and that worked. So I can call the Interrupt of the Port A with my Code, but i need to Call an Interrupt with the Port C GPIO.

Original Attachment has been moved to: gpio_interrupt.elf.zip

Labels (1)
0 Kudos
1 Solution
2,019 Views
mjbcswitzerland
Specialist V

Hi

I checked your binary and can tell you the problem:

1. The Port and its interrupt (also in NVIC) is set up correctly.
2. The interrupt fires and its vector is taken, however you haven't installed the correct handler since it calls the "un-handled" interrupt which means that it hangs in the interrupt forever (with KDS you should have been able to see this too).

It is easy to see that the vectors are missing (you have VTOR set to 0 - meaning that the vectors are hard-coded - you will probably find them in an assembler file somewhere).

These are the values that you have in Flash starting at address 0x00000000. I have labeled the vectors of interest, including the location of the "port B,C,D,E" interrupt vector (the last one).
Since the vector value is the same as many others it is clear that a un-handled (default) vector is being used rather than one to handle the port interrupt.

pastedImage_1.png

These are the values that you have in Flash starting at address 0x00000000. I have labeled the vectors of interest, including the location of the "port B,C,D,E" interrupt vector (the last one).
Since the vector value is the same as many others it is clear that a un-handled (default) vector is being used rather than one to handle the port interrupt.

If you can work out why and where you need to add it you should be OK. You will however need to ensure that the handler used is suitable for a port interrupt shared by these 4 ports or, in the worst case, one that at least handles the port C case for you.

As noted before, if you would prefer a more power ful and fool-proof solution just down-load the (free) Open Source uTasker project since it handles all such details.

Regards


Mark

View solution in original post

11 Replies
2,019 Views
danieltruong
Contributor IV

Try to do GPIO_PinInit before PORT_SetPinInterruptConfig to see if that helps:

GPIO_PinInit(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN, &sw_config);
PORT_SetPinInterruptConfig(BOARD_SW_PORT, BOARD_SW_GPIO_PIN, kPORT_InterruptFallingEdge);
EnableIRQ(BOARD_SW_IRQ);
    
0 Kudos
2,019 Views
killerawft
Contributor I

Unfortunately that didnt helped either.

0 Kudos
2,019 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi

I am not sure if you have slove this problem.

You can refer the modification shown below:

PTC3 FRDM-KL27Z.png

Be notice that the PTC3 is connect to external signal through J18 by default.

J28 PTC3.png

Best Regards,

Robin

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,019 Views
mjbcswitzerland
Specialist V

Hi

See this video concerning details about the port interrupts on the KL27: https://youtu.be/CubinvMuTwU

Attached is a binary that you can load to your board which prints out a message each time it is pressed (using falling edge interrupt detection) [openSDA VCOM at 115200Baud].
In addition, it includes USB-CDC on USB0 which also prints out the same message when connected.

Notes:
- The KL27 has a single shared interrupt for ports B,C,D and E, which may be the source of your difficulty
- There is a memory debugger on the command line interface (binary attached) which can be used for viewing registers so you can compare content with your setup to find a deviation.
- At http://www.utasker.com/kinetis.html you can use the uTasker open source project as reference to solving such issues - in Visual Studio you can simulate the GPIO interrupt operations and solve any complications with the libraries that you may otherwise be using.

Regards

Mark

KL27 References:
http://www.utasker.com/kinetis/FRDM-KL27Z.html
http://www.utasker.com/kinetis/Capuccino-KL27.html

0 Kudos
2,019 Views
killerawft
Contributor I

I watched the video and added the line PORT_SetPinMux(BOARD_SW_PORT, BOARD_SW_GPIO_PIN, kPORT_MuxAsGpio); after line 80 to set the Port as a GPIO and now the ISFR register of Port C is set. That wasnt the case before.

I also saw that the highest bit of the NVIC_ISER and the NVIC_ICER registers are set. Shouldnt the NVIC_ICER register cleared since that register disables the interrupt? Clearing it by hand with NVIC->ICER[0U] = 0; didnt worked.

And i couldnt test your binary file because i dont know how to flash it to the ARM with the Kinetis Design Studio 3 IDE, so i couldnt test that.

0 Kudos
2,019 Views
mjbcswitzerland
Specialist V

Hi

You don't need KDS to flash binaries to a FRDM board: Just drag and drop it to the hard drive that appears when the board is plugged in.

You can also build the projects yourself with the KDS project on GITHUB. Or do the same in its simulator, in order to improve development efficiency.

Regards

Mark

PS. If you do don't manage to sort it out attach your binary and I'll tell you what is wrong.

0 Kudos
2,019 Views
killerawft
Contributor I

I loaded your binary to the controller and when i pressed SW3 the Interrupt printed a message. In the Question i added the binary of my code so you can check it. 

0 Kudos
2,020 Views
mjbcswitzerland
Specialist V

Hi

I checked your binary and can tell you the problem:

1. The Port and its interrupt (also in NVIC) is set up correctly.
2. The interrupt fires and its vector is taken, however you haven't installed the correct handler since it calls the "un-handled" interrupt which means that it hangs in the interrupt forever (with KDS you should have been able to see this too).

It is easy to see that the vectors are missing (you have VTOR set to 0 - meaning that the vectors are hard-coded - you will probably find them in an assembler file somewhere).

These are the values that you have in Flash starting at address 0x00000000. I have labeled the vectors of interest, including the location of the "port B,C,D,E" interrupt vector (the last one).
Since the vector value is the same as many others it is clear that a un-handled (default) vector is being used rather than one to handle the port interrupt.

pastedImage_1.png

These are the values that you have in Flash starting at address 0x00000000. I have labeled the vectors of interest, including the location of the "port B,C,D,E" interrupt vector (the last one).
Since the vector value is the same as many others it is clear that a un-handled (default) vector is being used rather than one to handle the port interrupt.

If you can work out why and where you need to add it you should be OK. You will however need to ensure that the handler used is suitable for a port interrupt shared by these 4 ports or, in the worst case, one that at least handles the port C case for you.

As noted before, if you would prefer a more power ful and fool-proof solution just down-load the (free) Open Source uTasker project since it handles all such details.

Regards


Mark

2,019 Views
killerawft
Contributor I

That solved the issue. In the board.h file was the IRQ Handler declared as "PORTBCDE_IRQHandler" for the Switch 3 but it should be "PORTB_PORTC_PORTD_PORTE_IRQHandler", like it is defined in the Vector Table in the file "startup_MKL27Z644.S". Now the Interrupt calls my IRQ handler- 

Thank You!

0 Kudos
2,019 Views
egoodii
Senior Contributor III

NVIC_ISER and NVIC_ICER always just READ the contents of what is enabled -- they are not themselves registers, they are access-means to 'set' or 'clear' bits in the ONE physical 'enable' register --- you 'write 1 bits' into these addresses to (individually) enable or disable (Set or Clear each 'enable' bit).  Your write of 'zero' had no effect; you would need to write 1<<31 into ICER to disable a PortC/D interrupt.

0 Kudos
2,019 Views
killerawft
Contributor I

In the mean time i also found that out but thanks for that advice.

0 Kudos