Derek Snell

Reset asserting multiple times on POR, and fast execution

Discussion created by Derek Snell Employee on Sep 25, 2019
Latest reply on Sep 26, 2019 by Mark Butcher

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.

 

 

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:

 

 

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!

 

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

Outcomes