KL02Z External Interrupt ISR not called

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

KL02Z External Interrupt ISR not called

1,595 Views
richardgagliard
Contributor I

Hi all,

I'm working on a project using a KL02Z controller and am trying to configure the Port B pin 5 as an interrupt. I'm using the MCUXpresso IDE.

I've configured the pin as an input and set the interrupt to trigger on a falling edge:

PORT_SetPinInterruptConfig(PORTB, PIN5_IDX, kPORT_InterruptFallingEdge); /* Set PORTB5 (pin 13) to interrupt on falling edge */

Note: Pin5_IDX is defined as 5U.

This actually calls a macro:

static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(config);
}

Next the interrupt is enabled:

NVIC_EnableIRQ(PORTB_IRQn);

This calls another inline macro:

__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}

When I run the code and toggle the input to pin 13 on the CPU, I see that the PORTB->PCR[5] has the value of 0x010a0105. That indicates that the ISF flag has been set, so the interrupt has triggered. 

Additionally, the PORTB->ISFR indicates a value of 0x20, which also indicates that the interrupt has triggered.

Looking at the NVIC->ISER, the value is 0x80020400. The fact that Bit 31 is set indicates that the PortB interrupts should be enabled.

The NVIC->ISPR is similar: the value is 0x80000400, indicating that the PortB interrupt is pending.

Looking in memory at address 0x000000BC I see that the 32 bits there are 0x00001150, which is not the default handler but my ISR, so I think I've got that setup OK.

 

Finally, at the end of the processor init routine I have the statement:

__ASM volatile ("cpsie i" : : : "memory"); // Enable IRQ

which enables the maskable interrupts, so I'm assuming that isn't an issue.

What I don't see is the tool stop at my first statement in the ISR, which is where I increment a global variable. That variable is still at zero, indicating that the ISR hasn't been called.

Oh, one final thing - when I halted the execution to look at the variables the processing was in a while look in my main code (just spinning for now), so I don't think it's a matter of the ISR being starved for attention.

Any suggestions?

Thanks so much in advance.

Rich

Labels (1)
Tags (2)
0 Kudos
5 Replies

1,072 Views
mjbcswitzerland
Specialist V

Rich

It sounds as though you haven't enabled interrupts globally.

Regards

Mark

P.S: I have attached a binary file that can be loaded to the FRDM-KL02Z that has a falling edge interrupt configured on PTB5. On the OpenSDA VCOM there is a command line menu at 115200Baud where a message is sent on each interrupt. There is also a memory viewer in the I/O menu so that you can check register settings - or you can do it with the debugger.
These are the register settings that may help:
- port B interrup vector priority set in NVIC IRQ28_31_PRIORITY_REGISTER = 0x40000000
- interrupt enabled in NVIC IRQ0_31_SER with 0x80000000
- PORTB_PCR5 set to 0x000a0103
- Port B clocked by 0x00000400 in SIM_SCGC5
- when the interrupts triggered PORTB_PCR5 shows 0x010a0103 and PORTB_ISFR is 0x00000020 - PORTB_ISFR is written with this value to clear the interrupt.

I test this in the uTasker KL02 simulator for simplicity and run it on the target once it is seen to be fully operational (where it then works)

pastedImage_2.png


Kinetis: http://www.utasker.com/kinetis.html
Kinetis KL02/3/5:
- http://www.utasker.com/kinetis/FRDM-KL02Z.html
- http://www.utasker.com/kinetis/FRDM-KL03Z.html
- http://www.utasker.com/kinetis/FRDM-KL05Z.html
Videos:
GPIO Interrupt: https://youtu.be/CubinvMuTwU
- https://youtu.be/qRzbwW4-QQg
- https://youtu.be/iZEMRiDmHzw


Free Open Source solution: https://github.com/uTasker/uTasker-Kinetis
Working project in 15 minutes video: https://youtu.be/K8ScSgpgQ6M

Professional Kinetis support, one-on-one training and complete fast-track project solutions: http://www.utasker.com/support.html

0 Kudos

1,072 Views
richardgagliard
Contributor I

Thanks so much for the response, Mark!

I felt the same way - that it was a general global interrupt issue - and upon further examination it looks like my SPI interrupt is not working either. I thought the 'cspie' statement enabled the interrupts in general, and the NVIC_EnableIRQ() call enabled the maskable interrupts. Correct?

Comparing the settings with yours (NVIC->IP[7] = 0x40000000  (priority), NVIC->ISER, PORTB->PCR[5], and PORTB->ISFR) they look the same where it matters, so I think that's not the issue. Thanks so much for helping me check that!

When I look at the NVIC->ISPR I see the upper-most bit clear before I change the pin and it is set when I check it afterwards, so I think that is OK as well.

I'm feeling rather stupid at this point but I'm not sure how to check if interrupts in general are enabled. I know I had them working before this, but I can't figure out what I've changed to kill that. Yet another example to remind me to back up my work from time to time.

I'll try to pull together your example when I have some time to see if I can figure it out with that.

Thanks again for the help!

Rich

0 Kudos

1,072 Views
mjbcswitzerland
Specialist V

Rich

Verify the state of global interrupt masking in the debugger by looking at the PRIMASK core register. If it is 1 it is masked and if 0 it is not.

Regards

Mark

0 Kudos

1,072 Views
richardgagliard
Contributor I

The PRIMASK register is 0, so it looks like it isn't masked.

Next I decided to drop back to an SDK example and chose the TPM Timer example - mainly because that uses interrupts and doesn't use IO. My situation is that I'm bringing up a board of my own using a KL02Z16 rather than the Z32 that is on the eval board. So using the TPM sidesteps the IO issue. As I just have a processor (and some caps) on the board right now I only have an internal clock so I had to change the clock_config.c file so that it uses the internal clock. Long story short I was able to get the code working correctly on the eval board and while it runs on my board I still have an issue of the interrupts being logged (in this case it was a Timer Overflow) but the ISR doesn't get called. 

After hours of reducing the already dwindling set of hair on my head I grabbed another of my boards with just the CPU and tried it and it worked. Hmmmm. The voltage is a solid 3.304V, so that's not the issue. I'm assuming something went wrong with the part...particularly since there's nothing left on the board to blame.

Has anyone experienced that?

I guess I'm back up and running and I've learned a bit, but I'm wondering how to prevent that. Don't think that was an ESD issue, but you never know. 

Anyway, Thanks so much for your help!!

Rich

0 Kudos

1,072 Views
richardgagliard
Contributor I

Well, I thought I was back up and running anyway. Turns out the problem wasn't with the particular part (very rarely is) but with my design....

Mistakes seem so blindingly obvious once you figure them out, and this one is no exception. As there may be others that fall into the same trap I've just extricated myself from, I thought I'd swallow my pride and publish my mistake. From the "gee you should have known" department, the mistake turns out that I used PortB Pin 5 as an input. This pin happens to be the NMI pin and when the CPU boots up with this pin held low, funny things happen. When my board was not connected to the my programmer the CPU was just dormant (not surprisingly). When it was connected, it ran, but did so without enabling any ISRs.

Long story short: make sure you pay attention to the default pin configurations on the chip - you'll wind up with less forehead sized dents in your wall.

Rich

0 Kudos