Hi All,
I have a FRDM-KL05Z board. I have made a connection between PB10 as an output (Also Blue LED), and PA11 as input, via a 300 Ohm resistor.
My test program reports that the input is following the output but the ISR is not being called. What am I not doing right please?
Here are some snippets of code:
void PORTA_ISR(void)
{
PORTA_PCR11 |= PORT_PCR_ISF_MASK;
printf("\r\n *** ISR *** \r\n");
}
int main (void)
{
#if(defined(CW))
sysinit();
#endif
gpio_init();
app_init();
printf("\r\nRunning the project.\r\n");
EnableInterrupts;
LED3_OFF;
// configure PA11 as input
PDDR(A) &= ~(1<<11);
// configure port A for falling edge interupts
PORTA_PCR11 |= PORT_PCR_IRQC(0x10);
// Initialise the NVIC to enable the specified IRQ
enable_irq(30); //30 = 46-16
// clear PA11 ISF
PORTA_PCR11 |= PORT_PCR_ISF_MASK;
while(1)
{
printf("\r\nInput: %d", PDIR(A) & (1<<11));
LED3_ON;
delay(500000);
printf("\r\nInput: %d", PDIR(A) & (1<<11));
LED3_OFF;
delay(500000);
}
}
isr.h:
#ifndef __ISR_H
#define __ISR_H 1
#undef VECTOR_046
#define VECTOR_046 PORTA_ISR
extern void PORTA_ISR(void);
#endif //__ISR_H
The output of this program is:
K05
32pin SRAM Size: 4 KB
Silicon rev 15
Flash size: 32 KB program flash, 1 KB protection region
Running the project.
Input: 2048
Input: 0
Input: 2048
Input: 0
Input: 2048
Thanks in advance
Hi Dan,
I did not see the obviously problem on your code either, could you please check NVIC registers to see if they are configed correctly.
please refer to document in below thread:
https://community.freescale.com/docs/DOC-103034
hope it helps!
Hi Yong Li
Thanks. I’ve been away from microcontrollers for over 10 years and am now effectively a novice again. I’m learning uVision 4 but can’t get a debug or download connection to work. I’m currently programming the device by dragging and dropping the .s19 file into the FRDM_KL05Z drive. So, my program has to examine registers and report via the serial port.
I’ve been trying to understand the NVIC register access macros so that I can use them and report contents, but I’m still having trouble understanding them.
Could you please give me examples of how to read and write the relevant NVIC registers?
Thanks
Dan Bovill
Dan
You need to read the Cortex M4 NVIC document to find details of the interrupt registers.
To get your code to enable the interrupt in question the actual operation is:
IRQ28_31_PRIORITY |= 0x00P00000; // where P is the priority that the interrupt should have (KL05 supports 4 levels so P can be 0, 0x4, 0x8 or 0xc) [K has 16] lowest number is highest priority
IRQ0_31_SER = 0x40000000; // enable the PORTA interrupt request - this is a bit set write which sets the bit in the corresponding register IRQ0_31_CER
Check these two registers if you have a debugger. You can use the uTasker KL05 simulator to step the code and examine the registers without the need for a debugger.
If you load the binary that I posted you can examine registers on the UART interface. Eg. to see the IRQ0_31_CER (long word address at 0xe000e180) the command
md e000e180 l 1
gives
Memory Display
0xe000e180 50201001 P ..
[showing that PORTA, LPT, DMA0, and UART0 interrupts are unmasked]
Regards
Mark
Thanks for your advice. I've been reading about NVIC and trying a few things.
I found an error in my original program and fixed that. (I had PORTA_PCR11 |= PORT_PCR_IRQC(0x10); should've been PORTA_PCR11 |= PORT_PCR_IRQC(0xA);)
Now the program switches the BLUE LED on (which should trigger the interrupt) but does not enter the ISR... NOR does it get to "Test Point 1". The blue LED does not switch off (obviously).
So, something is working and something else isn't.
=========
here is main:
=========
int main (void)
{
#if(defined(CW))
sysinit();
#endif
gpio_init();
app_init();
printf("\r\nRunning the PA11 Interrupt project.\r\n");
LED3_OFF;
// The following 2 lines commented out because subsequent lines should do the same job. Shouldn't they?
// EnableInterrupts;
// enable_irq(30); //30 = 46-16
// Initialise the NVIC to enable the specified IRQ
// Report relevant NVIC Regs
printf("\r\nNVIC_ICPR: %x", NVIC_ICPR);
printf("\r\nNVIC_ISER: %x", NVIC_ISER);
printf("\r\nNVIC_IPR7: %x\r\n", NVIC_IPR7);
// Setup relevant NVIC Regs
NVIC_ICPR = 0x40000000; // Clear pending interrupts
NVIC_ISER = 0x40000000; // Enable interrupts from Port A
NVIC_IPR7 = 0x00c00000; // Set interrupt priority to 3
// Report relevant NVIC Regs
printf("\r\nNVIC_ICPR: %x", NVIC_ICPR);
printf("\r\nNVIC_ISER: %x", NVIC_ISER);
printf("\r\nNVIC_IPR7: %x\r\n", NVIC_IPR7);
// Configure PA11
PDDR(A) &= ~(1<<11); // configure PA11 as input
PORTA_PCR11 &= ~(1<<2); // Clear bit 2 for fast slew rate
PORTA_PCR11 |= PORT_PCR_IRQC(0xA); // configure port A for falling edge interrupts
// Report PORT A Regs
printf("\r\nGPIO_PDDR_REG(PTA_BASE_PTR): %x", GPIO_PDDR_REG(PTA_BASE_PTR));
printf("\r\nPORTA_PCR11: %x", PORTA_PCR11);
printf("\r\nPORTA_ISFR: %x\r\n", PORTA_ISFR);
while(1)
{
printf("\r\nInput: %d", PDIR(A) & (1<<11));
LED3_ON;
printf("\r\n *************** Test point 1 **************");
delay(500000);
printf("\r\nInput: %d", PDIR(A) & (1<<11));
LED3_OFF;
delay(500000);
}
}
===========
Here is the ISR:
===========
void PORTA_ISR(void)
{
PORTA_PCR11 |= PORT_PCR_ISF_MASK;
printf("\r\n *** ISR *** \r\n");
}
================
and here is isr.h:
================
#ifndef __ISR_H
#define __ISR_H 1
#undef VECTOR_046
#define VECTOR_046 PORTA_ISR
extern void PORTA_ISR(void);
#endif //__ISR_H
==============
Here is the output:
==============
Running the project.
NVIC_ICPR: 100000
NVIC_ISER: 0
NVIC_IPR7: 0
NVIC_ICPR: 100000
NVIC_ISER: 40000000
NVIC_IPR7: c00000
GPIO_PDDR_REG(PTA_BASE_PTR): 0
PORTA_PCR11: a0107
PORTA_ISFR: 0
Input: 2048
Dan
Did you compare the code that I sent to see whether you could find differences between it and yours?
Not all errors are obvious in code and also problems might be at other locations that are not visible/obvious.
It may be easier if you post the binary that you are loading to the board and then I will be able to tell you "why" it is not working. If you know why, you should be able to then fix it easier.
Regards
Mark
Hi Mark,
Thanks for your help. After much frustration I decided to learn how to use Processor Expert in Code Warrior. This is worth the pain for a novice such as I.
I now have LEDs flashing in timer interupts. I do have a new question about using printf in a Processor Expert project and will ask a new question about that.
Hi Dan
I didn't see anything obviously incorrect but I suspect that you have a problem with the NVIC configuration somewhere (although the vector number is correct).
Therefore I set up the same configuration in the uTasker project - see code below (this is an API so doesn't show the register setup details) but in the PORTA_PCR11 register it sets 0x000a0103 which you could check yours against (this is enabling pull-up too).
INTERRUPT_SETUP interrupt_setup; // interrupt configuration parameters
interrupt_setup.int_type = PORT_INTERRUPT; // identifier to configure port interrupt
interrupt_setup.int_handler = test_irq_A_11; // handling function
interrupt_setup.int_priority = PRIORITY_PORT_A_INT; // interrupt priority level
interrupt_setup.int_port = PORTA; // the port that the interrupt input is on
interrupt_setup.int_port_bits = PORTA_BIT11; // 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
When the interrupt is triggered the UART output (on virtual COM port of the FRDM-KL05Z at 115200Baud) writes "IRQ_A_11" and also the RED LED is toggled so that the interrupt is seen on the LED colour as well.
The blue LED is toggling every 500ms (I think that yours does this).
You can use a debugger to compare all registers to see what is different. There is also a memory debugger on the UART (hit ENTER and then go to the I/O menu).
I also attached a FRDM-KL05Z (also in the ZIP file) simulation (screen shot below) which I used to quickly set up and test the operation. You can run it be simply double clicking the EXE (doesn't need installation) and you can also test the IRQ operation [the Blue LED is toggling and you can change the input state of PTA11 by clicking on it - you will see that the interrupt fires and the RED LED is controlled as on the HW].
Regards
Mark
P.S: If you need to develop efficiently with the FRDM-KL05Z you can simply download the uTasker project and do the same.
http://www.utasker.com/kinetis.html
Dan
There is a single project which configures itself for any supported KE, KL or K parts. There is no binary for the KL05 on the demos page - I attached one here for that reason.
Use the following for the direct download
http://www.utasker.com/forum/index.php?topic=1721.msg6697#msg6697
This version has support for the following boards:
FRDM-KE02Z
FRDM-KL02Z
FRDM-KL05Z
FRDM-KL25Z
FRDM-KL26Z
TWR-KL25Z48MZ
FRDM-KL46Z
TWR-K20N50M
TWR-K20D72M
TWR-K21D50M
TWR-K21F120M
TEENSY 3.1
FRDM-K20D50M
TWR-K40X246
TWR-K40D100M
KWIKSTIK
TWR-K60N512
TWR-K60D100M
TWR-K60F120M
ELZET80 NET-KBED
ELZET80 NET-K60
EMCRAFT K61F150M
FRDM-K64F
EMCRAFT K70F150M
TWR-K70F120M
You can follow this video: https://www.youtube.com/watch?v=uBbiw36Caq4&feature=youtu.be
but essentially you just need to
1: select the part family (in config.h in the uTaskerV1.4 folder)
#define KINETIS_KL00 | // processor type - M0+ basic |
2: Select the board (in the same header)
#define FRDM_KL05Z
3: Build in VisualStudio and simulate the operation (it emulates peripherals, Flash, interrupts and DMA in approx. real-time). If you select the GNU target it will also build a target with the GCC compiler which can be loaded to the board (you may need to set the bat file path to your local copy)
3a. Or open any IDE project and ensure that the processor is set to the correct type (especially Cortex m0+ rather than Cortex m4)
3b. AND ensure that it is using the correct linker script (KL_32_4.ld is correct for the KL05 with 32k Flash and 4k RAM)
If you want to test port interrupts open Port_Interrupts.h and enable IRQ_TEST. In fnInitIRQ() there will be one or more port interrupts configured and assigned to interrupt handlers.
This port interrupt interface allows you to assign an individual interrupt call back to EACH port bit (rather than just one to a port). You can also assign an interrupt to multiple port bits (eg. PTA11, PTA3 and PTA4 could all be assigned to cause a certain interrupt handler to be called when any of them causes a trigger).
You will find that you can test everything in the simulator (if used) and develop, debug, solve problems, experiment and learn. Then you can load to the HW where it will work the same.
Regards
Mark
Dan
No problem - I only need a few minutes to do such things with the uTasker project (on almost any KE, KL or K processor that exists).
You may find that you just need to assign an interrupt priority to your interrupt - I didn't see that this was being explicitly done in your code.
Regards
Mark