aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan McIntyre <me@mciantyre.dev>2025-07-05 16:24:52 -0400
committerIan McIntyre <me@mciantyre.dev>2025-07-05 16:24:52 -0400
commit6f313f98fc8162c8dc7bac330fde927901cb9ba8 (patch)
treeb565427482d9fd16d0eae3791fb901882f9884da
First commit
-rw-r--r--.cargo/config.toml2
-rw-r--r--.gitignore2
-rw-r--r--.gitmodules15
-rw-r--r--Cargo.toml.chiptool12
-rw-r--r--Cargo.toml.svd2rust13
-rw-r--r--Makefile102
-rw-r--r--README.md74
m---------chiptool0
m---------form0
m---------imxrt-ral0
m---------svd2rust0
m---------svdtools0
-rw-r--r--transform.yaml245
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