GPIO pin as interrupt source KEA-64

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

GPIO pin as interrupt source KEA-64

Jump to solution
4,627 Views
kaslewis
Contributor III

I am looking to setup an interrupt on a pin. I am pretty new to Freecale and was therefore wondering where I could get information on how to set the pin accordingly as well as how to handle the interrupt once it occurs.

Any help would be much appreciated.

Kas

0 Kudos
1 Solution
2,020 Views
mjbcswitzerland
Specialist V

Hi Kas

Below is a reference of how the IRQ is used in the uTasker project (the KEA-64 has this as port interrupt possibility but limited to a single pin - PTA5 - see further details at the end).

Here is the user interrupt callback (could do anything so it is just an example)

static void irq_handler(void)

{

    fnInterruptMessage(OWN_TASK, IRQ_FIRED);

}

This is the user interface code to set up an IRQ interrupt (on KE and KEA parts)

INTERRUPT_SETUP interrupt_setup; // interrupt configuration parameters

interrupt_setup.int_type = PORT_INTERRUPT; // identifier to configure port interrupt

interrupt_setup.int_handler = irq_handler; // handling function

interrupt_setup.int_priority = PRIORITY_PORT_IRQ_INT; // interrupt priority level

interrupt_setup.int_port = KE_PORTI; // the port that the interrupt input is on

interrupt_setup.int_port_bits = KE_PORTI_BIT6; // the IRQ input connected

interrupt_setup.int_port_sense = (IRQ_FALLING_EDGE | PULLUP_ON); // interrupt is to be falling edge sensitive

fnConfigureInterrupt((void *)&interrupt_setup); // configure interrupt

fnConfigureInterrupt() does the following in the case of these settings:

static void (*IRQ_handler)(void) = 0; // handler for IRQ

unsigned char ucPortPin = SIM_PINSEL_IRQPS_PTI6;

POWER_UP(0, SIM_SCGC_IRQ); // enable clocks to the external interrupt module

SIM_PINSEL0 = ((SIM_PINSEL0 & ~(SIM_PINSEL_IRQPS_PTI6)) | ucPortPin); // select the IRQ pin to use

IRQ_SC = IRQ_SC_IRQPE; // enable IRQ pin function with pull-up

IRQ_handler = port_interrupt->int_handler; // enter the application handler

fnEnterInterrupt(irq_IRQ_ID, port_interrupt->int_priority, _IRQ_isr); // ensure that the handler is entered

IRQ_SC |= (IRQ_SC_IRQIE | IRQ_SC_IRQACK); // enable interrupt and reset pending interrupt

fnEnterInterrupt() enters the IRQ vector into the vector table (in SRAM in this case but can also be fixed in Flash).

To enable the interrupt source in the NVIC it does (in the case of the IRQ):

IRQ4_7_PRIORITY_REGISTER |= 0xc0000000;

IRQ0_32_SER = 0x00000080;

Of course the main Cortex interrupt must also be enabled.

When the IRQ triggers the IRQ handler is called, which resets the IRQ interrupt flag and calls the user's handler

static __interrupt void _IRQ_isr(void)

{

    IRQ_SC |= (IRQ_SC_IRQACK);                                          // reset the interrupt flag

    if (IRQ_handler != 0) {

        IRQ_handler();                                                  // call the interrupt handler

    }

}

The KEA-64 (as some smaller KE parts) has however only one IRQ input which can only be on PTA5. PTA5 defaults to RESET_b input and to use it the following differences are valid:

- the reset function must be disabled in SIM_SOPT0 [SIM_SOPT0 &= ~(SIM_SOPT_RSTPE);] - this is however a write-once field so it has to be used carefully. It is best to do it immediately after reset (where all such bits are defined together) so that it is guarantied to work.

- The SIM_PINSEL0 operations are redundant since the other sources don't exist

Regards

Mark

http://www.utasker.com/kinetis.html

View solution in original post

0 Kudos
10 Replies
2,020 Views
Rick_Li
NXP Employee
NXP Employee

Hi Kas,

the attached is an pin interrupt example based on K64, the code is similar with that of KEA.

I hope it helps!

0 Kudos
2,020 Views
mjbcswitzerland
Specialist V

Yong

Are you sure that you haven't made a mistake with the part in question?

The K64 supports port interrupts but the KE (and KEA) don't. These have keyboaad or external IRQ support instead.

This means that there are no registers in the KE (or KEA) matching the ones in the K64 pin interrupt example.

The KEA doesn't need to enable clocks to the ports and the interrupt vectors also don't match, as is the interrupt flag clearing incompatible.

Regards

Mark

0 Kudos
2,020 Views
Rick_Li
NXP Employee
NXP Employee

I did not noticed the difference between port interrupt on K64 and KE&KEA.

Thank you so much for your reminder, I will check it!

0 Kudos
2,020 Views
mjbcswitzerland
Specialist V

Hi Kas

I have had the opportunity to work with the KBI as in your device. The first thing to note is that there is a single interrupt for the 8 possible keyboard input interrupts of each of the two KBIs and there is no way to reliably know which one of them interrupted. This means that if any one triggers you know that one of them matched the interrupt requirement and you can read the port inputs (GPIOx_PDIR) to decide what to actually do.

The API looks like this (very similar to the IRQ) but referencing to the pins is performed by their port references and not their KBI references (this makes it more flexible).

It alows multiple pins to be configured for KBI use by referencing their port pins and so automatically allows configuring pins across multiple KBI controllers. The example shows 2 pins, whereby one belongs to KBI0 and KBI1, and both have the same user interrupt handler (although they would fire via differnet interrupt vectors),

INTERRUPT_SETUP interrupt_setup; // interrupt configuration parameters

interrupt_setup.int_type = PORT_INTERRUPT; // identifier to configure port interrupt

interrupt_setup.int_handler = test_kbi; // handling function

// Keyboard

//

interrupt_setup.int_type = KEYBOARD_INTERRUPT; // define keyboard interrupt rather than IRQ

interrupt_setup.int_priority = PRIORITY_KEYBOARD_INT; // interrupt priority level

interrupt_setup.int_port = KE_PORTD; // the port that the interrupt input is on (KE_PORTA, KE_PORTB, KE_PORTC and KE_PORTD are the same)

interrupt_setup.int_port_bits = (KE_PORTD_BIT5 | KE_PORTB_BIT3); // the IRQs input connected

interrupt_setup.int_port_sense = (IRQ_FALLING_EDGE | PULLUP_ON); // interrupt is to be falling edge sensitive

fnConfigureInterrupt((void *)&interrupt_setup); // configure interrupt

There is some assigning between pins and KBI inputs but basically it does (eg. of the input configured on KBI0_P7, which is PTB3):

POWER_UP(0, SIM_SCGC_KBI0); // ensure the module is powered

KBI_handlers[0] = port_interrupt->int_handler; // enter the user handler for the keyboard interrupt controller

fnEnterInterrupt(irq_KBI0_ID, port_interrupt->int_priority, _KBI0_isr);

PORT_PUEL |= port_interrupt->int_port_bits; // enabled pull-ups on the specified KBI inputs

KBI0_SC &= ~KBI_SC_KBIE; // mask main KBI interrupt

KBI0_SC &= ~KBI_SC_KBMOD; // detect only edges

KBI0_ES &= ~0x80; // select falling edge interrupt (this is the bit that was mapped between port and KBI pin)

KBI0_SC |= KBI_SC_KBACK; // clear any false interrupts

KBI0_PE |= 0x80; // enable the pin as KBI interrupt

KBI0_SC |= KBI_SC_KBIE;  // enable main KBI interrupt

The interrupt (KBI0) does:

KBI0_SC |= KBI_SC_KBACK; // clear pending interrupt

if (KBI_handlers[0] != 0) {

    KBI_handlers[0](); // call user handler

}

As you see it is indeed very similar to the IRQ.

Larger devices with more KBI interrupts have a different register set and 32 inputs per KBI controller. The set includes a register informing which of the inputs caused the interrupt and so allows more flexibility to assigning user call-backs to each individual pin interruts if required.

Regards

Mark

http://www.utasker.com/kinetis.html

0 Kudos
2,020 Views
kaslewis
Contributor III

Hello Mark,

Thank you for your endless patience and help. I was reading your previous comment and was wondering, could a keyboard interrupt be used in the same way as a pin interrupt. I'll explain what I'm trying to do and then you could let me know if this may be a valid path to pursue. I am looking to sleep the KEA-64 until a temperature threshold is reached, at this point an interrupt from the sensor should fire and wake the KEA-64 to take action. While one interrupt should work two would be helpful as there is a second interrupt for a critical threshold that may be useful.

Thanks

Kas

0 Kudos
2,020 Views
mjbcswitzerland
Specialist V

Kas

There are more Keyboard interrupts (only one IRQ) and these can wake from sleep modes so this will certainly be more suitable as soon as you need >1 such interrupt.

Unfortunately I can't working KBI code at the moment since I have used it only on the KE04 and KE06, which is a little different to the KE02 (closest to the KEA-64); it is however very similar to the IRQ but with additioanl status flags to indicate which one (or more) if the inputs causes the interrupt.

Regards

Mark

0 Kudos
2,020 Views
kaslewis
Contributor III

Hello Mark,

I have been looking around but I can not seem to find what the difference is between a KBI and a IRQ. They appear to behave very similarly if not the same, any clarification here would be much appreciated.

Kas

0 Kudos
2,020 Views
mjbcswitzerland
Specialist V

Kas

Yes, they are very similar. However when the IRQ triggers you know that the single IRQ pin state has changed to cause the interrupt. In the case of the KBI your know that one of the possible ones triggered the interrupt and then you need to work out which one it was by reading the staus register and resetting it.

Since further changes can take place when doing the handling it can be a little tricky to ensure than no changes are ever missed.

If you just need to wake up then it makes it a lot simpler because you can enable multiple KBI inputs/interrupts and you will be woken when any one of them fires.

Regards

Mark

0 Kudos
2,021 Views
mjbcswitzerland
Specialist V

Hi Kas

Below is a reference of how the IRQ is used in the uTasker project (the KEA-64 has this as port interrupt possibility but limited to a single pin - PTA5 - see further details at the end).

Here is the user interrupt callback (could do anything so it is just an example)

static void irq_handler(void)

{

    fnInterruptMessage(OWN_TASK, IRQ_FIRED);

}

This is the user interface code to set up an IRQ interrupt (on KE and KEA parts)

INTERRUPT_SETUP interrupt_setup; // interrupt configuration parameters

interrupt_setup.int_type = PORT_INTERRUPT; // identifier to configure port interrupt

interrupt_setup.int_handler = irq_handler; // handling function

interrupt_setup.int_priority = PRIORITY_PORT_IRQ_INT; // interrupt priority level

interrupt_setup.int_port = KE_PORTI; // the port that the interrupt input is on

interrupt_setup.int_port_bits = KE_PORTI_BIT6; // the IRQ input connected

interrupt_setup.int_port_sense = (IRQ_FALLING_EDGE | PULLUP_ON); // interrupt is to be falling edge sensitive

fnConfigureInterrupt((void *)&interrupt_setup); // configure interrupt

fnConfigureInterrupt() does the following in the case of these settings:

static void (*IRQ_handler)(void) = 0; // handler for IRQ

unsigned char ucPortPin = SIM_PINSEL_IRQPS_PTI6;

POWER_UP(0, SIM_SCGC_IRQ); // enable clocks to the external interrupt module

SIM_PINSEL0 = ((SIM_PINSEL0 & ~(SIM_PINSEL_IRQPS_PTI6)) | ucPortPin); // select the IRQ pin to use

IRQ_SC = IRQ_SC_IRQPE; // enable IRQ pin function with pull-up

IRQ_handler = port_interrupt->int_handler; // enter the application handler

fnEnterInterrupt(irq_IRQ_ID, port_interrupt->int_priority, _IRQ_isr); // ensure that the handler is entered

IRQ_SC |= (IRQ_SC_IRQIE | IRQ_SC_IRQACK); // enable interrupt and reset pending interrupt

fnEnterInterrupt() enters the IRQ vector into the vector table (in SRAM in this case but can also be fixed in Flash).

To enable the interrupt source in the NVIC it does (in the case of the IRQ):

IRQ4_7_PRIORITY_REGISTER |= 0xc0000000;

IRQ0_32_SER = 0x00000080;

Of course the main Cortex interrupt must also be enabled.

When the IRQ triggers the IRQ handler is called, which resets the IRQ interrupt flag and calls the user's handler

static __interrupt void _IRQ_isr(void)

{

    IRQ_SC |= (IRQ_SC_IRQACK);                                          // reset the interrupt flag

    if (IRQ_handler != 0) {

        IRQ_handler();                                                  // call the interrupt handler

    }

}

The KEA-64 (as some smaller KE parts) has however only one IRQ input which can only be on PTA5. PTA5 defaults to RESET_b input and to use it the following differences are valid:

- the reset function must be disabled in SIM_SOPT0 [SIM_SOPT0 &= ~(SIM_SOPT_RSTPE);] - this is however a write-once field so it has to be used carefully. It is best to do it immediately after reset (where all such bits are defined together) so that it is guarantied to work.

- The SIM_PINSEL0 operations are redundant since the other sources don't exist

Regards

Mark

http://www.utasker.com/kinetis.html

0 Kudos
2,020 Views
yasuhikokoumoto
Senior Contributor I

Hi Kas,

Isn't the following KEA64 Reference Manual enough?


http://cache.freescale.com/files/microcontrollers/doc/ref_manual/KEA64RM.pdf?WT_TYPE=Reference Manuals&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation&fileExt=.pdf

Best regards,
Yasuhiko Koumoto.

0 Kudos