I am currently working on my university Supervised Professional Practice project, which involves implementing an Asymmetric Multiprocessing (AMP) architecture on a Colibri i.MX7 module. I am running a Bare-Metal application on the Cortex-M4 and TorizonOS on the Cortex-A7.
I am facing a critical issue where the Cortex-M4 freezes (suffers a Hard Fault) at the exact moment TorizonOS finishes booting and reaches the login: prompt. I suspect this is related to the Linux kernel power management / Common Clock Framework disabling shared clocks.
Here are the full details of my setup, the issue, and everything I have tried so far.
1. Hardware & Software Setup
-
SoM: Toradex Colibri i.MX7D 1GB eMMC V1.1A
-
Carrier Board: Iris V1.1 Carrier Board
-
Cortex-A7 OS: Torizon OS Upstream 7.6.1+build.38 (Kernel 6.6.138-7.6.1)
-
Cortex-M4 OS: Bare-Metal (compiled using NXP
FreeRTOS-Colibri-iMX7SDK, specifically thegpio_imxdriver example). -
Boot Method: Early boot via U-Boot (
setenv m4boot 'load mmc 0:1 ${loadaddr} /boot/gpio_imx.elf && bootaux ${loadaddr}').
2. The Problem
My Bare-Metal code simply blinks an LED on GPIO5 and continuously prints a message over UART2. When I power on the board, U-Boot successfully loads the .elf file and the Cortex-M4 starts executing perfectly (LED blinks and UART prints are visible). However, when TorizonOS finishes its boot process and prints the login option, prompt on the A7 console, the M4 LED stops blinking and the UART2 stops printing simultaneously. This indicates a Hard Fault / External Abort on the M4, presumably because Linux disabled the clock for a peripheral the M4 was actively using.
3. What I have tried so far (without success)
-
RDC Isolation (M4 Side): I modified
hardware_init.cto assign the M4 to Domain 1 and explicitly lock the RDC for GPIO5 and UART2 (RDC_SetPdapAccess(RDC, rdcPdapGpio5, 3 << (BOARD_DOMAIN_ID * 2), false, false);). -
CCM Clock Gates (M4 Side): Forced
CCM_ControlGate(CCM, ccmCcgrGateGpio5, ccmClockNeededAll);. -
Device Tree Overlays (Linux Side):
-
Attempt 1: Disabled the peripherals in the A7 device tree (
status = "disabled";for&gpio5and&uart2). -
Attempt 2: Tried to trick the power management by setting them to
status = "okay";but with a fake driver (compatible = "pps-bare-metal-reserved";). -
Attempt 3: Added a
reserved-memorynode for the M4 atm4@80000000.
-
-
RPMsg / RemoteProc approach: Since early boot is being aggressively clock-gated by Kernel 6.6, I tried compiling the
pingpong_bmandstr_echo_bmexamples from the NXP SDK to let Linux handle the clocks via RPMsg. However, the modulesimx_rpmsg_ttyandimx_rprocseem to be missing or built-in without exposing the TTY port in this specific TorizonOS 7 kernel, so/dev/ttyRPMSGnever appears, even when adding&rpmsg { status = "okay"; };to the DT.
4. Cortex-M4 Main Code (main.c)
Here is the simplified Bare-Metal code I am running:
C
#include <stdint.h>
#include <stdbool.h>
#include "board.h"
#include "debug_console_imx.h"
#include "gpio_imx.h"
void delay(void) {
for (volatile uint32_t i = 0; i < 5000000; ++i) {
__asm("NOP");
}
}
int main(void) {
hardware_init(); /* RDC and CCM isolation applied here */
configure_gpio_pin(BOARD_GPIO_LED_CONFIG);
gpio_init_config_t ledInitConfig = {
.pin = BOARD_GPIO_LED_CONFIG->pin,
.direction = gpioDigitalOutput,
.interruptMode = gpioNoIntmode
};
GPIO_Init(BOARD_GPIO_LED_CONFIG->base, &ledInitConfig);
while (1) {
GPIO_WritePinOutput(BOARD_GPIO_LED_CONFIG->base, BOARD_GPIO_LED_CONFIG->pin, 1);
PRINTF("hola, desde M\n\r");
for (volatile uint32_t i = 0; i < 5000000; i++) {}
GPIO_WritePinOutput(BOARD_GPIO_LED_CONFIG->base, BOARD_GPIO_LED_CONFIG->pin, 0);
for (volatile uint32_t i = 0; i < 5000000; i++) {}
}
}
Questions:
-
Is there a known workaround or specific Device Tree configuration in TorizonOS 7 (Kernel 6.6) to completely prevent the Common Clock Framework from touching the M4 domain clocks during late boot?
-
Is RemoteProc/RPMsg the only officially supported way to keep the M4 alive in TorizonOS 7? If so, how can I properly enable the RPMsg TTY interface in this kernel version?
Any guidance, documentation, or tips would be greatly appreciated. Thank you in advance!