Hard Fault When Watchdog Unlock is Written (MK20FX512)

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

Hard Fault When Watchdog Unlock is Written (MK20FX512)

2,717 Views
nicholasf
Contributor III

I have a program which is about 200KB, and I am attempting to run on an MK20FX512, using Codewarrior for the download and debug.  When the standard CW generated __init_hardware() runs, and attempts to write to the watchdog unlock register, a hard fault interrupt is generated (by the strh instruction) and the processor is reset.

          __init_hardware:

21        SCB_VTOR = (uint32_t)__vector_table; /* Set the interrupt vector table position */

00000800:   ldr r1,[pc,#0x34]

00000804:   movw r0,#0xed08

00000808:   movt r0,#0xe000

0000080c:   str r1,[r0,#0]

35       *(volatile unsigned short *)KINETIS_WDOG_UNLOCK_ADDR = KINETIS_WDOG_UNLOCK_SEQ_1;

0000080e:   movw r1,#0xc520

00000812:   movw r0,#0x200e

00000816:   movt r0,#0x4005

0000081a:   strh r1,[r0,#0] // INTERRUPT GENERATED HERE

It is also worth noting that when this same initialization is run in a different project (with smaller code size), no interrupt is generated.

Another interesting fact is that if I refresh the watchdog instead of trying to unlock it, no hard fault is generated, but the processor has another interrupt when it attempts to initialize the stack pointer (after __init_hardware).

  lda r0,__SP_INIT

  // skip stack setup if __SP_INIT is 0

  // assume sp is already setup.

  cmp r0,#0

  beq skip_sp

  mov sp,r0

  sub sp,#4

  mov r0,#0

  mvn r0,r0

  str r0,[sp,#0]

  add sp,#4 // INTERRUPT GENERATED HERE

skip_sp:

Labels (1)
9 Replies

1,527 Views
thomasgrieger
Contributor III

Hi,

could you check which interrupt is really generated?

I know that you already stated that a hardfault is generated but at this early state in the program (before main) it is more likely that it is a "forced" hardfault. It is used if an non-maskable interrupt is generated which cannot be serviced by an ISR because the corresponding interrupt is turned off. The information can be found in the system control block of the ARM cortex core.

Best regards,

Thomas

1,527 Views
nicholasf
Contributor III

Hi Thomas,
Thanks for the great idea, I copied all the system control registers, and here they are:

SCB_ACTLR0x00xe000e008
SCB_CPUID0x410fc2410xe000ed00
SCB_ICSR0x8030xe000ed04
SCB_VTOR0x00xe000ed08
SCB_AIRCR0xfa0500000xe000ed0c
SCB_SCR0x00xe000ed10
SCB_CCR0x2000xe000ed14
SCB_SHPR10x00xe000ed18
SCB_SHPR20x00xe000ed1c
SCB_SHPR30x00xe000ed20
SCB_SHCSR0x00xe000ed24
SCB_CFSR0x1400
0xe000ed28
SCB_HFSR0x400000000xe000ed2c
SCB_DFSR0x90xe000ed30
SCB_MMFAR0xe000edf80xe000ed34
SCB_BFAR0xe000edf80xe000ed38
SCB_AFSR0x00xe000ed3c

From what I understand about the system control registers, SCB_ICSR is the relevant one in this case, and it appears to confirm the idea that there is a hard fault (though I may be completely wrong)

ARM Information Center

I still do not understand what is causing these problems with writing to registers.

0 Kudos

1,527 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

From the SCB_ICSR register, the hard fault exception happens.

And the SCB_CFSR register shows it caused by bus fault.

The SCB_CFSR value 0x1400 means store stack cause error and Imprecise data access error has occurred.

The SCB_HFSR value 0x40000000 also means the hard fault is caused by bus fault.

If in your project the stack start address definition with problem?

Wish it helps.

best regards,

Ma Hui

0 Kudos

1,527 Views
leonardobueno
Contributor I

Dears,

I am having the same problem with the FRDM-K64F board. My code works perfectly fine without the WatchDog, but when I try to use it, a hardfault is generated exactly when the program tries to unlock the hardware. How do I solve this issue?

Bellow is the registers dump. As pointed by Hui_Ma, the IMPRECISERR bit is activated. That means there is some problem with the Data Bus, but I don't know how to fix it.

r0= [0x1FFFFF88]

r1= [0x40052000]

r2= [0x00000001]

r3= [0x0000C520]

r12= [0x40052000]

lr= [0xCF4B6F7F]

pc= [0x00029ABB]

psr= [0x00029A62]

CFSR= [0x00000400]

CFS.DIVBYZERO = no

CFS.UNALIGNED = no

CFS.NOCP = no

CFS.INVPC = no

CFS.INVSTATE = no

CFS.UNDEFINSTR = no

CFS.BFARVALID = no

CFS.LSPERR = no

CFS.STKERR = no

CFS.UNSTKERR = no

CFS.IMPRECISERR = yes

CFS.PRECISERR = no

CFS.IBUSERR = no

CFS.MMARVALID = no

CFS.MLSPERR = no

CFS.MSTKERR = no

CFS.MUNSTKERR = no

CFS.DACCVIOL = no

CFS.IACCVIOL = no

Thank you for the patience

Leonardo Bueno

0 Kudos

1,527 Views
mjbcswitzerland
Specialist V

Leonardo

When you don't use the watchdog you still disable it. Therefore you must already have used the unlock code successfully.

What is the difference between your original

UNLOCK WATCHDOG

DISABLE WATCHDOG

sequence

and you new

UNLOCK WATCHDOG

ENABLE WATCHDOG

sequence?

The only thing to be careful of is that the unlock sequence is performed within 256 bus clock cycles otherwise it will cause a reset.

Regards

Mark

1,527 Views
leonardobueno
Contributor I

Mark,

The watchdog is not set anywhere in the code but the given Freescale Startup code (that Disables the Watchdog by default). So I did not necessarily implemented the unlock sequence anywhere in the code. Anyway, the start up code doesn't result on a hardfault, but if I try to enable the watchdog anywhere on the main loop it results on a Bus Fault. How do I solve it?

Thank you for your patience

Leonardo Bueno

0 Kudos

1,527 Views
mjbcswitzerland
Specialist V

Leonardo

1. Check that the startup code that unlocks the Watchdog and disables it sets the ALLOWUPDATE flag otherwise it will not allow you to change the setting again.

2. When you later enable the watchdog you also need to perform the unlock sequence immediately before the change.

3 The unlock sequence will cause a reset if the written values are incorrect, or if the sequence takes more that 20 bus cycles to be executed - if there is a risk of interrupts at this time disable interrupts to ensure that the sequence cannot be interrupted.

Regards

Mark

0 Kudos

1,527 Views
leonardobueno
Contributor I

Mark,

I changed my watchdog unlock code to behave exactly like the startup on. Now it doesn't give me a hardfault, but it resets before the end of the unlock sequence. I certified that the ALLOWUPDATE flag is set on the startup code, and I disabled interruptions before starting the unlock sequence to avoid missing the 20 bus cycle time, but the processor still resets when I try the first step of the unlock sequence. Any ideias of what might be causing this?

Thank you for your time

Leonardo Bueno

0 Kudos

1,527 Views
mjbcswitzerland
Specialist V

Leonardo

Check the user's manaual for a list of watchdog restrictions. I don't see what the problem is at the moment. I use the following code and have never experienced any difficuties:

// This sequence must be performed within 20 bus cycles and the writes are possible for the WCT period (16 bus clocks for KE and 128 bus clocks for configuration)

WDOG_UNLOCK = WDOG_UNLOCK_SEQUENCE_1;

WDOG_UNLOCK = WDOG_UNLOCK_SEQUENCE_2;

// Watchdog enabled to generate reset on 2s timeout (no further updates allowed)

//

WDOG_TOVALL = (2000/5);

WDOG_TOVALH = 0;

WDOG_STCTRLH = (WDOG_STCTRLH_STNDBYEN | WDOG_STCTRLH_WAITEN | WDOG_STCTRLH_STOPEN | WDOG_STCTRLH_WDOGEN);

Regards

Mark

0 Kudos