I've been writing a small program for my KE04Z which runs in RAM in order to program the flash of the device. I've been using SWD to place the program in RAM and run it. All was going well (blinking LEDs as a test, etc) until I tried to start the PIT in order to confirm the speed of the microcontroller by flashing an LED with some specific timing (the flash controller manual says that if the speed is wrong then it could destroy the flash). I don't have an oscilloscope available at the moment, otherwise I would just ditch the PIT, write the GPIO_PTOR over and over again, and measure the period of the resulting square wave.
I have in my startup section the following assembly which moves the VTOR to my interrupt vector table:
ldr r0, =0xE000ED08
ldr r1, =__interrupt_vector_table
str r1,[r0]
__interrupt_vector_table points to the beginning of the RAM section where I have placed my interrupt vector table (0x1fffff00 for the record) (link to code here: swd-kinetis/startup.S at master · kcuzner/swd-kinetis · GitHub ).
In my main method I have the following:
SIM->SCGC |= SIM_SCGC_PIT_MASK;
PIT->MCR = 0;
PIT->CHANNEL[0].LDVAL = 1.2e6;
PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK;
PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TIE_MASK;
NVIC->ISER[0] = 1 << 22;
__enable_irq();
It was at this point where I started to run into problems. Once the PIT would go off, a lockup would occur according to the SIM_SRSID register when I read it via SWD. I have a couple thoughts on why this could happen:
I'm pretty sure it has to do with my ISR or the interrupt in general because once I comment out the line of code that sets PIT_TCTRL0.TIE the program works fine and doesn't lock up.
My ISR is really simple right now:
void PIT_CH0_IRQHandler(void)
{
PIT->CHANNEL[0].TFLG = 0x1;
}
Whch compiles to:
2000001c <PIT_CH0_IRQHandler>:
2000001c: 2201 movs r2, #1
2000001e: 4b01 ldr r3, [pc, #4] ; (20000024 <PIT_CH0_IRQHandler+0x8>)
20000020: 611a str r2, [r3, #16]
20000022: 4770 bx lr
20000024: 400370fc strdmi r7, [r3], -ip
I honestly don't know if this is right. There is no context saving going on or anything else that I've seen in other ISRs, but I've never looked in detail at ARM Cortext M0+ ISRs so for all I know the NVIC takes care of context saving.
My question is: Is my ISR code, NVIC code, or VTOR relocating code the problem here? Or perhaps is locating the VTOR in RAM a bad thing and won't work properly?
This is my first time writing a program that runs in RAM and also my first time relocating the VTOR, so I don't have a lot of experience in these matters. I've done lots of interrupt code for a K20 before, but the VTOR was always at 0x0. If I've left anything out or need to supply additional information, just let me know.
解決済! 解決策の投稿を見る。
The full source can be found here: https://github.com/kcuzner/swd-kinetis/tree/master/firmware/KE04
However, I managed to fix the problem!
I was thinking about how exactly the NVIC stores the context since that seems to be the moment that causes things to go nuts and I realized that it likely uses the stack.
I execute the following sequence in SWD when loading my program (its likely not the best way to do it, but its a work in progress):
The processor would then run until the first interrupt. My realization was that since I had neglected to set the stack pointer during step 6 it was probably pointing to the reset value, which would be 0xffffffff. The NVIC likely had nowhere to save the context when the interrupt occurred and probably caused a fault. This would eventually let the WDT go off since it just loops endlessly in those routines which would cause the VTOR to reset back to 0x0, then attempting to execute 0xffffffff (since that's what is at address 0x4 in the unprogrammed state of the device) which would result in a LOCKUP.
By simply setting the stack pointer (register 14) to the top of my stack during step 6 above I fixed my problem.
Hi, Kevin,
Can you attach your project so that we can review even test your code on our FRDM board?
BR
Xiangjun Rong
The full source can be found here: https://github.com/kcuzner/swd-kinetis/tree/master/firmware/KE04
However, I managed to fix the problem!
I was thinking about how exactly the NVIC stores the context since that seems to be the moment that causes things to go nuts and I realized that it likely uses the stack.
I execute the following sequence in SWD when loading my program (its likely not the best way to do it, but its a work in progress):
The processor would then run until the first interrupt. My realization was that since I had neglected to set the stack pointer during step 6 it was probably pointing to the reset value, which would be 0xffffffff. The NVIC likely had nowhere to save the context when the interrupt occurred and probably caused a fault. This would eventually let the WDT go off since it just loops endlessly in those routines which would cause the VTOR to reset back to 0x0, then attempting to execute 0xffffffff (since that's what is at address 0x4 in the unprogrammed state of the device) which would result in a LOCKUP.
By simply setting the stack pointer (register 14) to the top of my stack during step 6 above I fixed my problem.