i.MX RT1060 Device Configuration Data (DCD) Generator

Crates.io docs.rs

The i.MX RT1050/1060 series of MCUs feature a ROM bootloader. As a part of the boot process, it interprets the Device Configuration Data (DCD) section in the firmware image to perform limited initialization and validation of peripheral registers, e.g. to set up external memory controllers, before any ARM instructions from the firmware image are run.

This crate defines: - Semantic descriptors of DCD commands. - Serialization from a list of commands to the DCD binary (byte array).

A common use case / workflow: - In the build.rs script of a firmware crate, define DCD commands and serialize them into a file (e.g. $OUT_DIR/dcd.bin). - In the firmware itself, define a static byte array initialized with the contents of the DCD binary, which can be linked into the firmware image. (Shameless plug: static-include-bytes helps with this step.)

What does the DCD do exactly?

The DCD section in the firmware image is a serialized byte array of one or more commands:

Reference: i.MX RT1060 Reference Manual (rev. 3), ยง9.7.2 .

See below for important details and caveats that affect the interpretation of DCD.

Usage

```rust use imxrtdcd as dcd; use imxrtral as ral; // feature = "imxrt1062"

// RECOMMENDED: using imxrt-ral and convenience macros let commandsmacro = vec![ dcd::writereg!(ral::ccmanalog, CCMANALOG, PLLARM, @BYPASS, BYPASSCLKSRC: CLK1), dcd::checkallclear!(ral::ccm, CCM, CDHIPR, @PERIPHCLKSELBUSY, @PERIPH2CLKSEL_BUSY), ];

// equivalent direct construction let commandsdirect = vec![ dcd::Command::Write(dcd::Write { width: dcd::Width::B4, op: dcd::WriteOp::Write, address: 0x400D8000, value: 0x00014000, }), dcd::Command::Check(dcd::Check { width: dcd::Width::B4, cond: dcd::CheckCond::AllClear, address: 0x400FC048, mask: (1 << 3) | (1 << 5), count: None, }), ];

asserteq!(commandsmacro, commands_direct);

// serialize into an std::io::Write let mut dcdbytes = vec![]; let numbyteswritten = dcd::serialize(&mut dcdbytes, &commandsmacro).expect("IO error"); asserteq!(numbyteswritten, 28); asserteq!( &dcdbytes, &[ // DCD header 0xD2, 0, 28, 0x41, // write 0xCC, 0, 12, 0x04, 0x40, 0x0D, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, // check 0xCF, 0, 12, 0x04, 0x40, 0x0F, 0xC0, 0x48, 0x00, 0x00, 0x00, 0x28, ] ); ```

Convenience Macros

To simplify the construction of commands, the feature "ral" (on by default) provides convenience macros designed to work with register definitions in imxrt-ral.

These macros share a common syntax as follows: ignore macro!(ral::path::to::peripheral, INSTANCE, REGISTER, ...args)

Where:

All args are then bitwise-OR'd together as the final value / mask of the command.

This syntax is inspired by (and is a superset of) write_reg! and friends in imxrt-ral (re-exporting ral-registers), adapted for the limitations of DCD.

DCD Details and Caveats

DCD size limit

The DCD serialization format is 4-byte aligned with a 2-byte length field in its header. This allows the entire DCD block to be at most 65532 bytes long (all headers included). However, the boot ROM of a specific chip family may enforce a (much) shorter size limit. For RT1060 this is 1768 bytes.

This crate only enforces the 64 KiB length limit to keep the binary format valid, but does return the size of the serialized DCD so that the user may add a tighter check.

Write command compression

Multiple consecutive Write commands with the same bit width and operation (i.e. write/clear/set) can be merged (sharing the same command header) to save 4 bytes per extra command.

This crate automatically performs this compression during serialization. This may help meet the DCD size limit.

Valid Write command address ranges

The boot ROM of a specific chip family may only allow Write commands to a limited number of address ranges.

For example, the following are the valid address ranges for RT1060 (again from the reference manual):

| Begin | End (inclusive) | Description | |---------------|-----------------|------------------------| | 0x400A_4000 | 0x400A_7FFF | IOMUX Control SNVS GPR | | 0x400A_8000 | 0x400A_BFFF | IOMUX Control SNVS | | 0x400A_C000 | 0x400A_FFFF | IOMUX Control GPR | | 0x401F_8000 | 0x401F_BFFF | IOMUX Control | | 0x400D_8000 | 0x400D_BFFF | CCM Analog | | 0x400F_C000 | 0x400F_FFFF | CCM | | 0x402F_0000 | 0x402F_3FFF | SEMC |

Writing to anywhere outside these ranges will cause the boot ROM to immediately abandon interpreting the rest of your DCD.

This crate does not enforce any address range limitations. The user is expected to provide valid write addresses for the target chip family.

Check command polling count

The Check command may specify one of the following:

Note that (through my limited experimentation) the boot ROM does not seem to limit the address range of Check commands.

Tips

Command Combos