iMX8X Cortex-M4: CM4__WDOG hardfault on startup?

Hello,

I have been trying to run the hello_world application on a colibri iMX8X from the iMX8X M4 JTAG startup guide and am finding that I get a HardFault after it executes the first few lines of SystemInit().

I’ve successfully hooked up a JLink debug interface and started up the tdx-Reference-Multimedia-Image in the A-core. I am on a Viola board, so I’ve soldered breakout wires to the pins 146/144 to access the M4 UART (please tell me if this is correct, as this was the location according to the pin planner. I’d like to change them to a more convenient location but am unfamiliar with the pin indexing from the… boards.h file?) although I’m obviously not seeing anything there. I’m using all the default code from Toradex without really changing anything and I’ve rebooted and followed the JTAG guide twice.

This seems to be something related to the watchdog, as stepping from the start of the program fails when the SysInit function tries to disable the watchdog

697 ldr r0, =VTOR
698 ldr r1, =__isr_vector
699 str r1, [r0]
700 ldr r2, [r1]
701 msr msp, r2
703 ldr r0, =SystemInit
704 blx r0
System Init () at /home/$USER/cortex-m/devices/MIMX8QX6/system_MIMX8QX6_cm4.c:94
94 SCB->CPACR |= ((3UL << 10 2) | (3UL << 11 * 2)); / set CP10, CP11 Full Access */
98 CM4__WDOG->CNT = WDOG_UPDATE_KEY
99 CM4__WDOG->TOVAL = 0xFFFF
HardFault_Handler () at /home/$USER/cortex-m/devices/MIMXQX6/gcc/startup_MIMX8QX6_cm4.S
899 ldr r0, =HardFault_Handler
900 bx r0
… repeats

I checked the UsageFault Status Register and found that I have an ‘IMPRECISERR’:
print\x *(unit32_t *) 0xE000ED28
$1 = 0x400

I also found the code from that section in the .c file mentioned:
#if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
SCB->CPACR |= ((3UL << 10 2) | (3UL << 11 * 2)); / set CP10, CP11 Full Access */
#endif

#if (DISABLE_WDOG)
CM4__WDOG->CNT = WDOG_UPDATE_KEY;
CM4__WDOG->TOVAL = 0xFFFF;
CM4__WDOG->CS = (uint32_t)((CM4__WDOG->CS) & ~WDOG_CS_EN_MASK) | WDOG_CS_UPDATE_MASK;
#endif

Perhaps it’s failing somewhere in the CM4__WDOG->CS write? I don’t know what would cause that other than maybe the register being incorrect because I chose the wrong hardware (i.e., trying to write to an address pointer CM4__WDOG->CS that doesn’t exist). It also could be something completely different, as after this the init tries to startup a cache.

Any help is much appreciated. Thanks!

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello! Thank you for your detailed description. I can help you work through this issue on your Colibri iMX8X running the hello_world M4 application via JTAG.

1. JTAG Debug Startup Checklist

  • Ensure you’re using the proper device identifier when invoking the JLinkGDBServer:
    JLinkGDBServer -if JTAG -device MIMX8QX6_M4 -vd -xc mekmimx8qx_gdbsrv.cfg
    
    Make sure you have the mekmimx8qx_gdbsrv.cfg file in the correct location, as per the guide:
    Cortex-M JTAG Debugging | Toradex Developer Center

2. Linux Resource Ownership

The most common cause of HardFaults in the early stages of SystemInit for i.MX SoCs is that the A-core (running Linux or TorizonCore) has not relinquished hardware resources, so the M4 is not able to access them. Particularly, the watchdog peripheral may still be under Linux control, and so M4 attempts to access it will generate a fault.

To test this, try:

  • Booting just to U-Boot, without booting into Linux.
  • Performing your JTAG debug session with the Linux system not running, letting only U-Boot initialize the hardware.

If you do not get a HardFault in this scenario, the issue is with Linux’s early resource usage.
Reference: No serial output of hello world

3. Pin Usage and UART Output

You mentioned using pins 146/144 (according to Pin Planner). On the Colibri iMX8X, these correspond to QuadSPI (QSPI) signals by default, not a UART. For M4 UART communication, it’s vital that:

  • You use the correct pins, and
  • The UART you select is properly configured and muxed for the M4 core in your device tree overlay.

Consult the datasheet pinout table and use a UART resource that is free and accessible by the M4. Refer to your device tree to confirm the mapping.

4. JTAG Debug Connection

Double-check all points in the JTAG debug guide to ensure everything is configured as expected:

5. Watchdog Resource & SystemInit

Your diagnosis—failing on a write to the watchdog—is likely correct. Ensure no other system core is holding the WDOG peripheral. Try disabling the watchdog code temporarily to see if you progress farther in SystemInit. If so, this confirms the resource contention.

6. Boards.h and Pin Indexing

Pin references in boards.h often correlate to NXP signal names and module documentation, not directly to SOM-edge connector pins. To remap UART signals to a more convenient pin:

  • Refer to the Colibri iMX8X datasheet and your specific carrier board’s schematics.
  • Update your device tree overlay so desired pins (that are UART-capable) are routed to the M4’s UART instance.
  • Verify with the Linux cat /proc/pinmux (if available) and/or NXP reference manual.

Summary Recommendation

  • Try running the hello_world application with only U-Boot running, not Linux.
  • Double-check device tree overlays and that your UART pins are correctly configured for use with the M4.
  • Use the prescribed JLinkGDBServer command with the right device and config file.
  • Temporarily comment out the watchdog register writes to check if your program gets further in the initialization.

If you make these adjustments and see improvements or encounter new issues, please let me know what happens next!

Best regards,
Toradex AI Assistant

Helpful links:

Yes, Colibri iMX8X pins 144 and 146 can be used as UART for the M4 core. However, these pins are not routed to any connector or header on the Viola board.

As for the hard fault you’re experiencing, please double-check that you have modified the hello_world code as described in the documentation. It is very important to properly configure the A cores (i.e., Linux) to avoid simultaneous access to the same SoC peripheral. In the case of the hello_world example, you need to disable the CM40 UART by applying the corresponding device tree overlay.

Hello,

Thanks for the advice! I took a look at your recommendations and implemented them. I am still having the same issue though even though I have done the following:

  • Recompile after changing pins to the GPIO0_00/GPIO0_01 for the UART on the M4
  • Adding the CM40 disable in the device tree overlay.

Please let me know what further steps may help to troubleshoot this issue. I included some images from the debug to illustrate what’s been done.



Thanks!

Have you tried running the Hello World app without using JTAG and without starting Linux?

Hi @camstillo ,

Any updates for us here?

Best regards,