Reset asserting multiple times on POR, and fast execution

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

Reset asserting multiple times on POR, and fast execution

918 Views
dereksnell
NXP Employee
NXP Employee

We were asked to drive an output pin as quickly as possible on a KV11 Kinetis MCU.  And in the process we found some interesting behavior with the reset pin, that was causing additional delays.  Here are the details, and solution.  

We wanted to use the FRDM-KV11Z board, and simple SDK example to demonstrate fast execution from POR.  The SDK demo led_blinky is a simple example for this, so we wanted to drive the Red LED pin low on PTD6 as fast as possible after reset is released.  

The first step is optimizing the application code to drive the GPIO quickly.  Placing code in main() will not execute immediately after reset, because there is startup code that executes first.  In particular, the variable initialization done by the runtime library can take some time, especially in larger applications.  The SDK already has a hook in place for code like this that needs to execute quickly after reset, and before the runtime library initialization.  This hook is SystemInitHook().  Keep in mind, when using code in this hook, since variables have not been initialized, you cannot count on any to have a known value.  We used this code to drive PTD6 low:

void SystemInitHook (void) {
 /* Port D Clock Gate Control: Clock enabled */
 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;

 /* PORTD6 (pin 63) is configured as PTD6 */
 PORTD->PCR[BOARD_LED_RED_GPIO_PIN] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;

 /* Init output LED GPIO. */
 BOARD_LED_GPIO->PDDR |= (1 << BOARD_LED_RED_GPIO_PIN);
}‍‍‍‍‍‍‍‍

 

This succeeded in driving the LED pin low very quickly after reset was released, only 5us.  But when watching reset during POR, we found this unexpected behavior shown below.  The top signal is reset, and we can see it toggles high 5 times before it finally stays high and executes the code.  We also monitor VDD as it rises.  On power up, the KV11 datasheet says the Low Voltage Detect (LVD) Low threshold is 1.6V, and the reset sequence should start once VDD exceeds that level.  After the reset sequence completes and flash has initialized, reset goes high and execution should start.  But here we see reset asserted again 5 more times after that initial release of reset.  After the 6th and final rising edge of Reset, the LED pin is driven low after only 5us.  But the total time from VDD=1.6V to LED pin going low is 686us.  Something else to notice is the high reset pulses are 25us, and the MCU is executing code during that pulse.  So why does the MCU execute for 25us before another reset is triggered, and yet it doesn't execute the code to drive the LED pin low, which only needs 5us?  It seems it is not executing our application code.

Reset_Toggling.jpg

The cause of this behavior is the Non-Maskable Interrupt (NMI) pin on the MCU.  When NMI is asserted low, it forces an interrupt, and jumps to the NMI ISR.  Take a look at the NMI signal on PTA4 pin of this FRDM-KV11Z board:

NMI_cap.jpg

The cap on this pin keeps NMI low initially during POR, and with the weak pull-up it takes some time to get pulled high.  So reset releases, code starts executing, and it immediately jumps to the NMI ISR and gets stuck there.  This also means code doesn't disable or service the watchdog, so reset gets asserted again.  This continues to happen until NMI is pulled high, and then our application code finally executes.

The Kinetis MCUs do have an option stored in flash to disable NMI on boot, to prevent something like this from happening.  In the KV11, the NMI_DIS bit is bit2 in the FOPT flash location at address 0x40D.  By clearing the NMI_DIS bit in flash, NMI will be disabled.  The SDK projects configure the Flash_Config area using the structure below in the startup file, like startup_mkv11z7.c.  The linker places this Flash_Config section at address 0x400, so the last word contains the FOPT byte for address 0x40D.  The FOPT byte was the default 0xFF, and was changed to 0xFB to clear the NMI_DIS bit2.  BTW, the 0xFE byte in the same word is the FSEC byte at 0x40C, and is set to 0xFE to leave the MCU unsecured.

__attribute__ ((used,section(".FlashConfig"))) const struct {
 unsigned int word1;
 unsigned int word2;
 unsigned int word3;
 unsigned int word4;
} Flash_Config = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFBFE}; // NMI_DIS cleared in FOPT
‍‍‍‍‍‍

Now with NMI disabled, the capture below shows the final results.  Reset no longer toggles, and only goes high once.  The LED pin is driven low so quickly, the logic analyzer on the digital signal does not even recognize it goes high.  The bottom channel is analog voltage of the LED pin.  It starts to rise with VDD until the code executes and drives it low.  This is 5us after reset is released like we saw before, but is only 98us after VDD=1.6V.  Much better!

NMI_DIS.jpg

The modified project with source code, and the binary image are attached.

1 Reply

779 Views
mjbcswitzerland
Specialist V

HI

void SystemInitHook (void) {
 /* Port D Clock Gate Control: Clock enabled */
 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;

 /* PORTD6 (pin 63) is configured as PTD6 */
 PORTD->PCR[BOARD_LED_RED_GPIO_PIN] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;

 /* Init output LED GPIO. */
 BOARD_LED_GPIO->PDDR |= (1 << BOARD_LED_RED_GPIO_PIN);
}

can be made a bit more efficient with

void SystemInitHook (void) {
 /* Port D Clock Gate Control: Clock enabled */
 SIM->SCGC5 = SIM_SCGC5_PORTD_MASK;

 /* PORTD6 (pin 63) is configured as PTD6 */
 PORTD->PCR[BOARD_LED_RED_GPIO_PIN] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;

 /* Init output LED GPIO. */
 BOARD_LED_GPIO->PDDR = (1 << BOARD_LED_RED_GPIO_PIN);
}

The ORs are redundant since the register content is known after a reset.

Regards

Mark

0 Kudos