-
Notifications
You must be signed in to change notification settings - Fork 0
CM33 Firmware Guide
Board: imx93-jaguar-eink
Target: CM33 firmware development and deployment
Audience: Embedded developers
The i.MX93 Jaguar E-Ink board supports loading and running firmware on the Cortex-M33 co-processor. This guide covers both U-Boot and Linux kernel methods for CM33 firmware management.
The CM33 core has access to:
- TCM (Tightly Coupled Memory): 0x201E0000 - 0x201FFFFF (128KB)
- System RAM: Shared with A55 cores via reserved memory regions
- Peripherals: Direct access to many i.MX93 peripherals
The device tree configures these memory regions for CM33:
reserved-memory {
rsc_table: rsc-table@1fff8000 {
reg = <0 0x1fff8000 0 0x1000>;
no-map;
};
vdev0vring0: vdev0vring0@aff00000 {
reg = <0 0xaff00000 0 0x8000>;
no-map;
};
vdev0vring1: vdev0vring1@aff08000 {
reg = <0 0xaff08000 0 0x8000>;
no-map;
};
vdevbuffer: vdevbuffer@a8400000 {
compatible = "shared-dma-pool";
reg = <0 0xa8400000 0 0x100000>;
no-map;
};
m33_reserved: m33_noncacheable_section@a8600000 {
no-map;
reg = <0 0xa8600000 0 0x1000000>;
};
};
- CM33 firmware binary (
.bin
or.elf
format) - Firmware stored on SD card, eMMC, or loaded via TFTP
# 1. Load firmware from SD card
=> fatload mmc 1:1 ${loadaddr} cm33_firmware.bin
# 2. Copy firmware to CM33 TCM
=> cp.b ${loadaddr} 0x201e0000 ${filesize}
# 3. Start CM33 core
=> bootaux 0x201e0000 0
# Load ELF format firmware (automatically handles memory layout)
=> fatload mmc 1:1 ${loadaddr} cm33_firmware.elf
=> bootelf ${loadaddr}
Add these to U-Boot environment for automated CM33 startup:
# Set firmware path and load address
=> setenv cm33_firmware cm33_firmware.bin
=> setenv cm33_loadaddr 0x80000000
# Create boot script for CM33
=> setenv boot_cm33 'fatload mmc 1:1 ${cm33_loadaddr} ${cm33_firmware}; cp.b ${cm33_loadaddr} 0x201e0000 ${filesize}; bootaux 0x201e0000 0'
# Auto-start CM33 during boot
=> setenv bootcmd 'run boot_cm33; run distro_bootcmd'
=> saveenv
The following U-Boot features are enabled for CM33 support:
-
CONFIG_IMX_BOOTAUX=y
- Auxiliary core support -
CONFIG_CMD_BOOTAUX=y
- bootaux command -
CONFIG_CMD_ELF=y
- ELF loading support -
CONFIG_CMD_MEMORY=y
- Memory operations - File system support for firmware loading
- CM33 firmware in ELF format
- Firmware placed in
/lib/firmware/
- Remoteproc kernel support enabled
The following kernel features are enabled:
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
CONFIG_IMX_REMOTEPROC=y
CONFIG_RPMSG=y
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_CTRL=y
CONFIG_RPMSG_NS=y
# List available remoteproc devices
ls /sys/class/remoteproc/
# Check current state
cat /sys/class/remoteproc/remoteproc0/state
# Possible states: offline, running, crashed, invalid
# 1. Copy firmware to /lib/firmware/
cp cm33_firmware.elf /lib/firmware/
# 2. Set firmware name
echo "cm33_firmware.elf" > /sys/class/remoteproc/remoteproc0/firmware
# 3. Start CM33 core
echo "start" > /sys/class/remoteproc/remoteproc0/state
# Stop CM33 core
echo "stop" > /sys/class/remoteproc/remoteproc0/state
# Check remoteproc status
cat /sys/class/remoteproc/remoteproc0/state
# View remoteproc information
cat /sys/class/remoteproc/remoteproc0/name
cat /sys/class/remoteproc/remoteproc0/firmware
# Check kernel messages
dmesg | grep remoteproc
dmesg | grep rpmsg
Once CM33 is running with RPMSG support, communication channels appear:
# List RPMSG devices
ls /dev/rpmsg*
# Example devices:
# /dev/rpmsg_ctrl0 - Control channel
# /dev/rpmsg0 - Data channel
# Send data to CM33
echo "Hello CM33" > /dev/rpmsg0
# Read data from CM33
cat /dev/rpmsg0
If CM33 firmware supports TTY console:
# Check for RPMSG TTY devices
ls /dev/ttyRPMSG*
# Connect to CM33 console
minicom -D /dev/ttyRPMSG0
Your CM33 firmware should:
- Link to TCM address: Start at 0x201E0000
- Initialize stack pointer: Set up stack in TCM or SRAM
- Configure vector table: Set VTOR register
- Handle RPMSG: Implement RPMSG protocol for communication
MEMORY
{
TCM (rwx) : ORIGIN = 0x201E0000, LENGTH = 128K
SRAM (rwx) : ORIGIN = 0xA8600000, LENGTH = 16M
}
SECTIONS
{
.text : {
. = ALIGN(4);
*(.vectors)
*(.text*)
. = ALIGN(4);
} > TCM
.data : {
. = ALIGN(4);
*(.data*)
. = ALIGN(4);
} > TCM
.bss : {
. = ALIGN(4);
*(.bss*)
. = ALIGN(4);
} > TCM
}
# Compile CM33 firmware
arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -T cm33.ld -o cm33_firmware.elf main.c
# Convert to binary format for U-Boot
arm-none-eabi-objcopy -O binary cm33_firmware.elf cm33_firmware.bin
# Check if bootaux command is available
=> help bootaux
# Verify firmware loading
=> md.b 0x201e0000 0x100
# Check CM33 core status
=> bootaux 0x201e0000 0
# Should show "## Starting auxiliary core..." message
# Check remoteproc driver loading
lsmod | grep remoteproc
# Check device tree CM33 node
cat /proc/device-tree/cm33/status
# Check mailbox devices
ls /sys/class/mailbox/
# Monitor kernel messages during firmware loading
dmesg -w &
echo "start" > /sys/class/remoteproc/remoteproc0/state
Firmware Not Starting:
- Check firmware load address (must be 0x201E0000 for TCM)
- Verify firmware format (binary for U-Boot, ELF for remoteproc)
- Check memory permissions and reserved regions
RPMSG Communication Fails:
- Verify CM33 firmware implements RPMSG protocol
- Check vring buffer configuration in device tree
- Ensure mailbox devices are working
Remoteproc State "crashed":
- Check CM33 firmware for exceptions
- Verify memory layout and stack configuration
- Check for resource table in ELF firmware
Use CM33 for time-critical tasks while A55 handles Linux applications:
# Start real-time firmware
echo "realtime_processor.elf" > /sys/class/remoteproc/remoteproc0/firmware
echo "start" > /sys/class/remoteproc/remoteproc0/state
# Send sensor data to CM33
echo "sensor_data" > /dev/rpmsg0
Use CM33 for low-power monitoring while A55 cores sleep:
# Load power management firmware
echo "power_manager.elf" > /sys/class/remoteproc/remoteproc0/firmware
echo "start" > /sys/class/remoteproc/remoteproc0/state
Dedicate CM33 to handle specific peripherals:
# Load peripheral controller firmware
echo "peripheral_ctrl.elf" > /sys/class/remoteproc/remoteproc0/firmware
echo "start" > /sys/class/remoteproc/remoteproc0/state
Create a recipe to include CM33 firmware in the root filesystem:
# recipes-bsp/cm33-firmware/cm33-firmware.bb
SUMMARY = "CM33 firmware for imx93-jaguar-eink"
LICENSE = "CLOSED"
SRC_URI = "file://cm33_firmware.elf"
do_install() {
install -d ${D}/lib/firmware
install -m 0644 ${WORKDIR}/cm33_firmware.elf ${D}/lib/firmware/
}
FILES:${PN} = "/lib/firmware/cm33_firmware.elf"
Create a systemd service:
# /etc/systemd/system/cm33-autostart.service
[Unit]
Description=Auto-start CM33 firmware
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo cm33_firmware.elf > /sys/class/remoteproc/remoteproc0/firmware'
ExecStart=/bin/sh -c 'echo start > /sys/class/remoteproc/remoteproc0/state'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
- TCM: Fastest access, limited to 128KB
- SRAM: Good performance, larger capacity
- DDR: Slowest but largest capacity
- RPMSG: Higher-level protocol, easier to use
- Shared Memory: Lower overhead, requires synchronization
- Mailbox: Lowest overhead, interrupt-based
- CM33 can run while A55 cores are in low-power states
- Implement proper clock gating in CM33 firmware
- Use WFI instruction when CM33 is idle
For questions or issues, contact the software team with specific error messages and firmware details.