diff options
| author | Ian McIntyre <me@mciantyre.dev> | 2025-07-05 16:24:52 -0400 |
|---|---|---|
| committer | Ian McIntyre <me@mciantyre.dev> | 2025-07-05 16:24:52 -0400 |
| commit | 6f313f98fc8162c8dc7bac330fde927901cb9ba8 (patch) | |
| tree | b565427482d9fd16d0eae3791fb901882f9884da | |
First commit
| -rw-r--r-- | .cargo/config.toml | 2 | ||||
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | .gitmodules | 15 | ||||
| -rw-r--r-- | Cargo.toml.chiptool | 12 | ||||
| -rw-r--r-- | Cargo.toml.svd2rust | 13 | ||||
| -rw-r--r-- | Makefile | 102 | ||||
| -rw-r--r-- | README.md | 74 | ||||
| m--------- | chiptool | 0 | ||||
| m--------- | form | 0 | ||||
| m--------- | imxrt-ral | 0 | ||||
| m--------- | svd2rust | 0 | ||||
| m--------- | svdtools | 0 | ||||
| -rw-r--r-- | transform.yaml | 245 |
13 files changed, 465 insertions, 0 deletions
diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..c9b00e8 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +dep-info-basedir = "." diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e9f777 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +imxrt-svd2rust/ +imxrt-chiptool/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..aa3e766 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,15 @@ +[submodule "imxrt-ral"] + path = imxrt-ral + url = git@github.com:imxrt-rs/imxrt-ral.git +[submodule "svd2rust"] + path = svd2rust + url = git@github.com:rust-embedded/svd2rust.git +[submodule "chiptool"] + path = chiptool + url = git@github.com:embassy-rs/chiptool.git +[submodule "form"] + path = form + url = git@github.com:djmcgill/form.git +[submodule "svdtools"] + path = svdtools + url = git@github.com:rust-embedded/svdtools.git diff --git a/Cargo.toml.chiptool b/Cargo.toml.chiptool new file mode 100644 index 0000000..4397cf5 --- /dev/null +++ b/Cargo.toml.chiptool @@ -0,0 +1,12 @@ +[package] +name = "imxrt-chiptool" +version = "0.1.0" +edition = "2024" + +[dependencies] +cortex-m = { version = "0.7" } +cortex-m-rt = { version = "0.7", optional = true } +defmt = { version = "1", optional = true } + +[features] +rt = ["cortex-m-rt/device"] diff --git a/Cargo.toml.svd2rust b/Cargo.toml.svd2rust new file mode 100644 index 0000000..1d707c8 --- /dev/null +++ b/Cargo.toml.svd2rust @@ -0,0 +1,13 @@ +[package] +name = "imxrt-svd2rust" +version = "0.1.0" +edition = "2021" + +[dependencies] +critical-section = { version = "1.0", optional = true } +cortex-m = "0.7" +cortex-m-rt = { version = "0.7", optional = true } +vcell = "0.1.2" + +[features] +rt = ["cortex-m-rt/device"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1811907 --- /dev/null +++ b/Makefile @@ -0,0 +1,102 @@ +CODEGEN_TOOL_PROFILE := release +PAC_PROFILE := release +TIMINGS ?= --timings + +-include chiptool/target/$(CODEGEN_TOOL_PROFILE)/chiptool.d +-include svd2rust/target/$(CODEGEN_TOOL_PROFILE)/svd2rust.d +-include form/target/$(CODEGEN_TOOL_PROFILE)/form.d +-include svdtools/target/$(CODEGEN_TOOL_PROFILE)/svdtools.d + +CHIPTOOL = chiptool/target/$(CODEGEN_TOOL_PROFILE)/chiptool +SVD2RUST = svd2rust/target/$(CODEGEN_TOOL_PROFILE)/svd2rust +FORM = form/target/$(CODEGEN_TOOL_PROFILE)/form +SVDTOOLS = svdtools/target/$(CODEGEN_TOOL_PROFILE)/svdtools + +$(CHIPTOOL): + cargo build --manifest-path=chiptool/Cargo.toml --profile=$(CODEGEN_TOOL_PROFILE) + +$(SVD2RUST): + cargo build --manifest-path=svd2rust/Cargo.toml --profile=$(CODEGEN_TOOL_PROFILE) + +$(FORM): + cargo build --manifest-path=form/Cargo.toml --profile $(CODEGEN_TOOL_PROFILE) + +$(SVDTOOLS): + cargo build --manifest-path=svdtools/Cargo.toml --profile $(CODEGEN_TOOL_PROFILE) + +.PHONY: codegen_tools +codegen_tools: $(CHIPTOOL) $(RALTOOL) $(SVD2RUST) $(FORM) $(SVDTOOLS) + +.PHONY: test_codegen_tools +test_codegen_tools: codegen_tools + $(CHIPTOOL) --help + $(SVD2RUST) --help + $(FORM) --help + $(SVDTOOLS) --help + +.PHONY: imxrt-ral.shootout +imxrt-ral.shootout: + @cargo update --manifest-path=imxrt-ral/Cargo.toml + + @cargo clean --manifest-path=imxrt-ral/Cargo.toml --profile=$(PAC_PROFILE) + cargo build --manifest-path=imxrt-ral/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv7em-none-eabihf --package=imxrt-ral --features=imxrt1011,rt $(TIMINGS) + + @cargo clean --manifest-path=imxrt-ral/Cargo.toml --profile=$(PAC_PROFILE) + cargo build --manifest-path=imxrt-ral/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv7em-none-eabihf --package=imxrt-ral --features=imxrt1062,rt $(TIMINGS) + + @cargo clean --manifest-path=imxrt-ral/Cargo.toml --profile=$(PAC_PROFILE) + cargo build --manifest-path=imxrt-ral/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv7em-none-eabihf --package=imxrt-ral --features=imxrt1176_cm7,rt $(TIMINGS) + + @cargo clean --manifest-path=imxrt-ral/Cargo.toml --profile=$(PAC_PROFILE) + cargo build --manifest-path=imxrt-ral/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv8m.main-none-eabihf --package=imxrt-ral --features=imxrt1189_cm33,rt $(TIMINGS) + +imxrt-svd2rust: + @mkdir -p $@ + +imxrt-ral/svd/%.svd.patched: $(SVDTOOLS) + SVDTOOLS=../$(SVDTOOLS) $(MAKE) -C imxrt-ral svd/$*.svd.patched + +imxrt-svd2rust/%: imxrt-ral/svd/%.svd.patched imxrt-svd2rust $(SVD2RUST) $(FORM) + @mkdir -p $@ + @cp Cargo.toml.svd2rust $@/Cargo.toml + @$(SVD2RUST) -i $< --output-dir $@ + @$(FORM) --input $@/lib.rs --outdir $@/src/ + @rm -f @/lib.rs + @cargo fmt --manifest-path=$@/Cargo.toml + +.PHONY: imxrt-svd2rust.shootout +imxrt-svd2rust.shootout: imxrt-svd2rust/imxrt1011 imxrt-svd2rust/imxrt1062 + @cargo update --manifest-path=imxrt-svd2rust/imxrt1011/Cargo.toml + @cargo clean --manifest-path=imxrt-svd2rust/imxrt1011/Cargo.toml + cargo build --manifest-path=imxrt-svd2rust/imxrt1011/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv7em-none-eabihf --features=rt $(TIMINGS) + + @cargo update --manifest-path=imxrt-svd2rust/imxrt1062/Cargo.toml + @cargo clean --manifest-path=imxrt-svd2rust/imxrt1062/Cargo.toml + cargo build --manifest-path=imxrt-svd2rust/imxrt1062/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv7em-none-eabihf --features=rt $(TIMINGS) + +imxrt-chiptool: + @mkdir -p $@ + +imxrt-chiptool/%: imxrt-ral/svd/%.svd.patched imxrt-chiptool $(CHIPTOOL) $(FORM) + @mkdir -p $@ + @cp Cargo.toml.chiptool $@/Cargo.toml + @cd $@ && ../../$(CHIPTOOL) generate --svd ../../$< --transform ../../transform.yaml && ../../$(FORM) --input lib.rs --outdir src/ && rm lib.rs + @cargo fmt --manifest-path=$@/Cargo.toml + +.PHONY: imxrt-chiptool.shootout +imxrt-chiptool.shootout: imxrt-chiptool/imxrt1011 imxrt-chiptool/imxrt1062 imxrt-chiptool/imxrt1176_cm7 imxrt-chiptool/imxrt1189_cm33 + @cargo update --manifest-path=imxrt-chiptool/imxrt1011/Cargo.toml + @cargo clean --manifest-path=imxrt-chiptool/imxrt1011/Cargo.toml + cargo build --manifest-path=imxrt-chiptool/imxrt1011/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv7em-none-eabihf --features=rt $(TIMINGS) + + @cargo update --manifest-path=imxrt-chiptool/imxrt1062/Cargo.toml + @cargo clean --manifest-path=imxrt-chiptool/imxrt1062/Cargo.toml + cargo build --manifest-path=imxrt-chiptool/imxrt1062/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv7em-none-eabihf --features=rt $(TIMINGS) + + @cargo update --manifest-path=imxrt-chiptool/imxrt1176_cm7/Cargo.toml + @cargo clean --manifest-path=imxrt-chiptool/imxrt1176_cm7/Cargo.toml + cargo build --manifest-path=imxrt-chiptool/imxrt1176_cm7/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv7em-none-eabihf --features=rt $(TIMINGS) + + @cargo update --manifest-path=imxrt-chiptool/imxrt1189_cm33/Cargo.toml + @cargo clean --manifest-path=imxrt-chiptool/imxrt1189_cm33/Cargo.toml + cargo build --manifest-path=imxrt-chiptool/imxrt1189_cm33/Cargo.toml --profile=$(PAC_PROFILE) --target=thumbv8m.main-none-eabihf --features=rt $(TIMINGS) diff --git a/README.md b/README.md new file mode 100644 index 0000000..3fceeed --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +How long does it take to build a peripheral access crate (PAC) for different i.MX RT MCUs? +Let's find out! +[Here](https://www.mciantyre.dev/2025/06/30/imxrt-pac-shootout.html) are my measurements. + +We'll use three different PAC representations: + +1. the classic [svd2rust] PAC. +2. the [chiptool] PAC, preferred by [embassy]. +3. the register access layer (RAL) design, first pioneered by [stm32ral] and + later adopted by [imxrt-ral]. + +[svd2rust]: https://github.com/rust-embedded/svd2rust +[stm32ral]: https://github.com/adamgreig/stm32ral +[imxrt-ral]: https://github.com/imxrt-rs/imxrt-ral +[embassy]: https://github.com/embassy-rs +[chiptool]: https://github.com/embassy-rs/chiptool + +With each of these, we'll build PACs for four different i.MX RT MCUs: + +1. iMXRT1011 +2. iMXRT1062 +3. iMXRT1176 (Cortex-M7 only) +4. iMXRT1189 (Cortex-M33 only) + +We'll clean-build all PACs in release mode, targeting the best architecture profile for each MCU. +Note that this also includes the time to build PAC dependencies. +We'll trust Cargo's reporting of how long it takes. + +## Try it out + +Clone this repository along with all of its submodules. + +``` +git clone --recurse-submodules https://git.mciantyre.dev/imxrt-pac-shootout +``` + +Install the Rust targets we're using to build PACs: + +``` +rustup target add thumbv7em-none-eabihf thumbv8m.main-none-eabihf +``` + +The rest of these commands should automatically build the tools and intermediates +needed for codegen. + +### imxrt-ral + +This one is the simplest: clean-build the package for each MCU. + +``` +make -j imxrt-ral.shootout +``` + +### imxrt-svd2rust + +Generate four PACs using `svd2rust`, supplying the same patched SVDs used by imxrt-ral. +Separate each PAC's modules with `form`, and format them with `rustfmt`. +Then, build all four PACs. + +``` +make -j imxrt-svd2rust.shootout +``` + +### imxrt-chiptool + +Generate four PACs using `chiptool`, supplying the same patched SVDs used by imxrt-ral. +Use a transform file that's equivalent to what imxrt-ral uses. + +Separate each PAC's modules with `form`, and format them with `rustfmt`. +Then, build all four PACs. + +``` +make -j imxrt-chiptool.shootout +``` diff --git a/chiptool b/chiptool new file mode 160000 +Subproject 6651cd0877390fdd3c76af037244e795bb867da diff --git a/form b/form new file mode 160000 +Subproject 42afa0b7b8fd70458401c6bfb66979c9d78a8f9 diff --git a/imxrt-ral b/imxrt-ral new file mode 160000 +Subproject 9b21c91b8bc9c937e8d2ea52b0e46359928122f diff --git a/svd2rust b/svd2rust new file mode 160000 +Subproject 23464b37d2bd90e7dc19be853b4337c0e5797c4 diff --git a/svdtools b/svdtools new file mode 160000 +Subproject ce6ff6663b752d6ed8732432c36008b4386eb7d diff --git a/transform.yaml b/transform.yaml new file mode 100644 index 0000000..c599601 --- /dev/null +++ b/transform.yaml @@ -0,0 +1,245 @@ +# A port of the raltool-cfg.yaml from imxrt-ral. This is how raltool +# transforms its peripherals, so it's only fair that chiptool does +# the same. + +transforms: + # Transform device names, keeping the RAL convention. + - !Rename + from: Mimxrt1011 + to: imxrt1011 + type: Device + - !Rename + from: Mimxrt1015 + to: imxrt1015 + type: Device + - !Rename + from: Mimxrt1021 + to: imxrt1021 + type: Device + - !Rename + from: Mimxrt1051 + to: imxrt1051 + type: Device + - !Rename + from: Mimxrt1052 + to: imxrt1052 + type: Device + - !Rename + from: Mimxrt1061 + to: imxrt1061 + type: Device + - !Rename + from: Mimxrt1062 + to: imxrt1062 + type: Device + - !Rename + from: Mimxrt1064 + to: imxrt1064 + type: Device + - !Rename + from: Mimxrt1176Cm7 + to: imxrt1176_cm7 + type: Device + - !Rename + from: Mimxrt1176Cm4 + to: imxrt1176_cm4 + type: Device + - !Rename + from: Mimxrt1189Cm33 + to: imxrt1189_cm33 + type: Device + - !Rename + from: Mimxrt1189Cm7 + to: imxrt1189_cm7 + type: Device + - !Rename + from: pit::Pit1 + to: pit::Pit + type: Block + - !Rename + from: usb::Usb1 + to: usb::Usb + type: Block + - !DeleteEnums + from: usb::vals::Fs2 + # Combine GPT OCR and ICR registrers for 10xx MCUs. + # This allows it to match the 11xx MCUs, and reduce + # code bloat. + - !MakeRegisterArray + blocks: gpt::Gpt(\d) + from: OCR(\d) + to: OCR + - !MakeRegisterArray + blocks: gpt::Gpt(\d) + from: ICR(\d) + to: ICR + # Drop select enums from GPT fields. These extra enums + # are present in 11xx SVDs and prevent the tool from + # combining with the 10xx GPT definition. + - !DeleteEnums + from: gpt::vals::Im(\d) + - !DeleteEnums + from: gpt::vals::Om(\d) + - !DeleteEnums + from: gpt::vals::Fo(\d) + - !DeleteEnums + from: gpt::vals::Sr(\d) + - !DeleteEnums + from: gpt::vals::Of(\d) + - !DeleteEnums + from: gpt::vals::If(\d) + - !DeleteEnums + from: gpt::vals::Of(\d)ie + - !DeleteEnums + from: gpt::vals::If(\d)ie + # Move the CAN wrapper instance number to the far right + # so it's properly parsed. + - !Rename + from: CAN(\d)_WRAPPER + to: CAN_WRAPPER$1 + type: Block + # This resembles a XECC_FLEXSPI peripheral. + # It consolidates when there's a number at the end. + - !Rename + from: XECC_SEMC + to: XECC_SEMC0 + type: Block + # This peripheral is tricky to support. + # + # - It has clusters in clusters. While we can generate code for this, + # we can't easily add macro support for this. + # - It has clusters that alias each other. This is trickier to support + # in today's codegen tool, so we're punting. + - !Delete + from: caam::Caam + # 1176 CM7 has GPIO blocks under a "cm7_gpio" module. Change this + # so that they're under a "gpio" module. Also, rename the block so + # that it matches the 10xx GPIO block name, and can be combined. + - !Rename + from: cm7_gpio::Cm7Gpio2 + to: gpio::Gpio1 + type: Block + # Same goes for the 1176 CM4: rename for combining. + - !Rename + from: gpio::Gpio2 + to: gpio::Gpio1 + type: Block + # Change the fast GPIO numbers on the 1176 CM7 so that they have a + # unique instance number. Add 10 to make it distinct. This is faily hacky, + # so TODO make this better. + - !Rename + from: CM7_GPIO2 + to: FAST_GPIO20 + type: Block + - !Rename + from: CM7_GPIO3 + to: FAST_GPIO30 + type: Block + # Similar number suffixes result in duplicate instance types. Define unique + # numbers (that are a bit less hacky, maybe). + - !Rename + from: PGMC_CPC0_MIF0 + to: PGMC_CPC_MIF00 + type: Block + - !Rename + from: PGMC_CPC0_MIF1 + to: PGMC_CPC_MIF01 + type: Block + - !Rename + from: PGMC_CPC1_MIF0 + to: PGMC_CPC_MIF10 + type: Block + - !Rename + from: PGMC_CPC1_MIF1 + to: PGMC_CPC_MIF11 + type: Block + # 1176 LPSPI has fewer enums which prevent combining. Remove them from + # the 10xx variants. They're simple, intuitive bool fields, so it's no + # bit deal to remove. + - !DeleteEnums + from: lpspi::vals::Hren + - !DeleteEnums + from: lpspi::vals::Hrpol + - !DeleteEnums + from: lpspi::vals::Hrsel + - !DeleteEnums + from: lpspi::vals::Pcspol + # The 1189 has two DMA peripherals. Avoid collision when unifying with 10xx + # names. + - !Delete + from: dma3::Dma3 + # DMA and DMAMUX are suffixed with numbers on the 1176, since each core + # has its own instance. They're also suffixed on 10xx chips, even though + # there's just one instnace. Rename them so that the names are the same across + # all chips. + - !Rename + from: dma(\d)::Dma(\d) + to: dma::Dma + type: All + - !Rename + from: DMA(\d) + to: DMA + type: All + - !Rename + from: dmamux(\d)::Dmamux(\d) + to: dmamux::Dmamux + type: All + - !Rename + from: DMAMUX(\d) + to: DMAMUX + type: All + - !RenameRegisters + block: ocotp::Ocotp + from: HW_OCOTP_(.*) + to: $1 + # Field is needlessly named 'AM1F' on the 1176. + # All 1000-series use AM1IE. The field meaning + # is the same regardless, and this lets us combine + # the LPI2C blocks. + - !RenameFields + fieldset: lpi2c::regs::Sier + from: AM1F + to: AM1IE + - !RenameFields + fieldset: src::regs::Srsr + from: LOCKUP + to: LOCKUP_SYSRESETREQ + # Groups of 1189 peripherals that use derivedFrom but with meaningful names + # instead of plain numbering. raltool only handles the numbered case, so + # delete them until someone needs them. + - !Delete + from: aon_mif_ln28fdsoi_spllram::AonMifLn28fdsoiSpllram + - !Delete + from: aon_mif_s28spregh::AonMifS28spregh + - !Delete + from: aon_mix_slice::AonMixSlice + - !Delete + from: enetc0_revmii_mac::Enetc0RevmiiMac + - !Delete + from: enetc0_revmii_phy::Enetc0RevmiiPhy + - !Delete + from: ethernet_pll::EthernetPll + - !Delete + from: mu2_mua::Mu2Mua + - !Delete + from: sw0_global::Sw0Global + - !Delete + from: tstmr2_tstmra::Tstmr2Tstmra + - !Delete + from: xcache_pc::XcachePc + - !Delete + from: m33_pcf::M33Pcf1 + # Aliased cluster arrays are not supported by raltool at the time of writing. + - !Delete + from: ecat::RxErrorCntr + - !Delete + from: ecat::ForwardedRxErrorCntr + - !Delete + from: ecat::LostLinkCntr + - !Delete + from: ecat::Fmmu + - !Delete + from: ecat::Syncmanager + # This one probably just needs some renaming to work. + - !Delete + from: mu2_mub::Mu2Mub |
