From 938fe31b2ec985149e701b7718926813e02cd9e4 Mon Sep 17 00:00:00 2001 From: John Gemmell Date: Wed, 11 Feb 2026 22:48:42 -0500 Subject: [PATCH] support for nxp mimxrt1064 --- embassy-nxp/Cargo.toml | 2 + embassy-nxp/build.rs | 2 +- embassy-nxp/src/chips/mimxrt1064.rs | 13 ++++ embassy-nxp/src/gpio/rt1xxx.rs | 36 ++++++++--- embassy-nxp/src/lib.rs | 1 + examples/mimxrt1064-evk/.cargo/config.toml | 8 +++ examples/mimxrt1064-evk/Cargo.toml | 35 +++++++++++ examples/mimxrt1064-evk/build.rs | 12 ++++ examples/mimxrt1064-evk/src/bin/blinky.rs | 26 ++++++++ examples/mimxrt1064-evk/src/bin/button.rs | 30 ++++++++++ examples/mimxrt1064-evk/src/lib.rs | 70 ++++++++++++++++++++++ 11 files changed, 225 insertions(+), 10 deletions(-) create mode 100644 embassy-nxp/src/chips/mimxrt1064.rs create mode 100644 examples/mimxrt1064-evk/.cargo/config.toml create mode 100644 examples/mimxrt1064-evk/Cargo.toml create mode 100644 examples/mimxrt1064-evk/build.rs create mode 100644 examples/mimxrt1064-evk/src/bin/blinky.rs create mode 100644 examples/mimxrt1064-evk/src/bin/button.rs create mode 100644 examples/mimxrt1064-evk/src/lib.rs diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index c81e683a26..2f7fa68452 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -12,6 +12,7 @@ build = [ {target = "thumbv8m.main-none-eabihf", features = ["defmt", "lpc55s16"]}, {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1011", "rt", "time-driver-pit"]}, {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1062", "rt", "time-driver-pit"]}, + {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1064", "rt", "time-driver-pit"]}, ] [package.metadata.embassy_docs] @@ -87,3 +88,4 @@ lpc55-core0 = ["nxp-pac/lpc55s69_cm33_core0"] lpc55s16 = ["nxp-pac/lpc55s16", "_lpc55"] mimxrt1011 = ["nxp-pac/mimxrt1011", "_rt1xxx", "dep:imxrt-rt"] mimxrt1062 = ["nxp-pac/mimxrt1062", "_rt1xxx", "dep:imxrt-rt"] +mimxrt1064 = ["nxp-pac/mimxrt1064", "_rt1xxx", "dep:imxrt-rt"] diff --git a/embassy-nxp/build.rs b/embassy-nxp/build.rs index 87974be9a2..3c124dadcf 100644 --- a/embassy-nxp/build.rs +++ b/embassy-nxp/build.rs @@ -36,7 +36,7 @@ fn main() { let singletons = singletons(&mut cfgs); cfg_aliases! { - rt1xxx: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, + rt1xxx: { any(feature = "mimxrt1011", feature = "mimxrt1062", feature = "mimxrt1064") }, } cfg_aliases! { diff --git a/embassy-nxp/src/chips/mimxrt1064.rs b/embassy-nxp/src/chips/mimxrt1064.rs new file mode 100644 index 0000000000..d5969a24b9 --- /dev/null +++ b/embassy-nxp/src/chips/mimxrt1064.rs @@ -0,0 +1,13 @@ +// This must be imported so that __preinit is defined. +use imxrt_rt as _; + +pub(crate) mod _generated { + #![allow(dead_code)] + #![allow(unused_imports)] + #![allow(non_snake_case)] + #![allow(missing_docs)] + + include!(concat!(env!("OUT_DIR"), "/_generated.rs")); +} + +pub use _generated::*; diff --git a/embassy-nxp/src/gpio/rt1xxx.rs b/embassy-nxp/src/gpio/rt1xxx.rs index 8a560310c2..a436320b2d 100644 --- a/embassy-nxp/src/gpio/rt1xxx.rs +++ b/embassy-nxp/src/gpio/rt1xxx.rs @@ -866,56 +866,74 @@ fn irq_handler(block: Gpio, wakers: &[AtomicWaker; 32], high_bits: bool) { } } -#[cfg(all(any(feature = "mimxrt1011", feature = "mimxrt1062"), feature = "rt"))] +#[cfg(all( + any(feature = "mimxrt1011", feature = "mimxrt1062", feature = "mimxrt1064"), + feature = "rt" +))] #[interrupt] fn GPIO1_COMBINED_0_15() { irq_handler(pac::GPIO1, &GPIO1_WAKERS, false); } -#[cfg(all(any(feature = "mimxrt1011", feature = "mimxrt1062"), feature = "rt"))] +#[cfg(all( + any(feature = "mimxrt1011", feature = "mimxrt1062", feature = "mimxrt1064"), + feature = "rt" +))] #[interrupt] fn GPIO1_COMBINED_16_31() { irq_handler(pac::GPIO1, &GPIO1_WAKERS, true); } -#[cfg(all(any(feature = "mimxrt1011", feature = "mimxrt1062"), feature = "rt"))] +#[cfg(all( + any(feature = "mimxrt1011", feature = "mimxrt1062", feature = "mimxrt1064"), + feature = "rt" +))] #[interrupt] fn GPIO2_COMBINED_0_15() { irq_handler(pac::GPIO2, &GPIO2_WAKERS, false); } -#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[cfg(all(any(feature = "mimxrt1062", feature = "mimxrt1064"), feature = "rt"))] #[interrupt] fn GPIO2_COMBINED_16_31() { irq_handler(pac::GPIO2, &GPIO2_WAKERS, true); } -#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[cfg(all(any(feature = "mimxrt1062", feature = "mimxrt1064"), feature = "rt"))] #[interrupt] fn GPIO3_COMBINED_0_15() { irq_handler(pac::GPIO3, &GPIO3_WAKERS, false); } -#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[cfg(all(any(feature = "mimxrt1062", feature = "mimxrt1064"), feature = "rt"))] #[interrupt] fn GPIO3_COMBINED_16_31() { irq_handler(pac::GPIO3, &GPIO3_WAKERS, true); } -#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[cfg(all(any(feature = "mimxrt1062", feature = "mimxrt1064"), feature = "rt"))] #[interrupt] fn GPIO4_COMBINED_0_15() { irq_handler(pac::GPIO4, &GPIO4_WAKERS, false); } -#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[cfg(all(any(feature = "mimxrt1062", feature = "mimxrt1064"), feature = "rt"))] #[interrupt] fn GPIO4_COMBINED_16_31() { irq_handler(pac::GPIO4, &GPIO4_WAKERS, true); } -#[cfg(all(any(feature = "mimxrt1011", feature = "mimxrt1062"), feature = "rt"))] +#[cfg(all( + any(feature = "mimxrt1011", feature = "mimxrt1062", feature = "mimxrt1064"), + feature = "rt" +))] #[interrupt] fn GPIO5_COMBINED_0_15() { irq_handler(pac::GPIO5, &GPIO5_WAKERS, false); } + +#[cfg(all(any(feature = "mimxrt1062", feature = "mimxrt1064"), feature = "rt"))] +#[interrupt] +fn GPIO5_COMBINED_16_31() { + irq_handler(pac::GPIO5, &GPIO5_WAKERS, false); +} diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 21c6375c4e..c0185aa9a5 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -28,6 +28,7 @@ mod time_driver; #[cfg_attr(lpc55, path = "chips/lpc55.rs")] #[cfg_attr(feature = "mimxrt1011", path = "chips/mimxrt1011.rs")] #[cfg_attr(feature = "mimxrt1062", path = "chips/mimxrt1062.rs")] +#[cfg_attr(feature = "mimxrt1064", path = "chips/mimxrt1064.rs")] mod chip; pub use chip::{Peripherals, interrupt, peripherals}; diff --git a/examples/mimxrt1064-evk/.cargo/config.toml b/examples/mimxrt1064-evk/.cargo/config.toml new file mode 100644 index 0000000000..a88452be91 --- /dev/null +++ b/examples/mimxrt1064-evk/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.thumbv7em-none-eabihf] +runner = 'probe-rs run --chip MIMXRT1064' + +[build] +target = "thumbv7em-none-eabihf" # Cortex-M7 + +[env] +DEFMT_LOG = "trace" diff --git a/examples/mimxrt1064-evk/Cargo.toml b/examples/mimxrt1064-evk/Cargo.toml new file mode 100644 index 0000000000..9e73c40f75 --- /dev/null +++ b/examples/mimxrt1064-evk/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "embassy-imxrt1064-evk-examples" +version = "0.1.0" +edition = "2024" +license = "MIT OR Apache-2.0" +publish = false + +[dependencies] +cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.3" +defmt = "1.0.1" +defmt-rtt = "1.0.0" + +embassy-executor = { version = "0.10.0", path = "../../embassy-executor", features = ["platform-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1064", "unstable-pac", "time-driver-pit"] } +embassy-time = { version = "0.5.1", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" +embassy-sync = { version = "0.8.0", path = "../../embassy-sync", features = ["defmt"] } +embedded-hal-1 = { package = "embedded-hal", version = "1.0" } +embedded-hal-async = "1.0.0" + +imxrt-boot-gen = { version = "0.3.4", features = ["imxrt1064"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } +panic-semihosting = "0.6.0" + +[build-dependencies] +imxrt-rt = { version = "0.1.7", features = ["device"] } + +[profile.release] +debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabihf", artifact-dir = "out/examples/mimxrt1064-evk" } +] diff --git a/examples/mimxrt1064-evk/build.rs b/examples/mimxrt1064-evk/build.rs new file mode 100644 index 0000000000..ff3909ecad --- /dev/null +++ b/examples/mimxrt1064-evk/build.rs @@ -0,0 +1,12 @@ +use imxrt_rt::{Family, RuntimeBuilder}; + +fn main() { + RuntimeBuilder::from_flexspi(Family::Imxrt1064, 4 * 1024 * 1024) + .build() + .unwrap(); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // Not link.x, as imxrt-rt needs to do some special things + println!("cargo:rustc-link-arg-bins=-Timxrt-link.x"); +} diff --git a/examples/mimxrt1064-evk/src/bin/blinky.rs b/examples/mimxrt1064-evk/src/bin/blinky.rs new file mode 100644 index 0000000000..1761df40f9 --- /dev/null +++ b/examples/mimxrt1064-evk/src/bin/blinky.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nxp::gpio::{Level, Output}; +use embassy_time::Timer; +// Must include `embassy_imxrt1064_evk_examples` to ensure the FCB gets linked. +use {defmt_rtt as _, embassy_imxrt1064_evk_examples as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_nxp::init(Default::default()); + info!("Hello world!"); + + // User LED (D18) + let led = p.GPIO_AD_B0_09; + let mut led = Output::new(led, Level::High); + + loop { + Timer::after_millis(500).await; + + info!("Toggle"); + led.toggle(); + } +} diff --git a/examples/mimxrt1064-evk/src/bin/button.rs b/examples/mimxrt1064-evk/src/bin/button.rs new file mode 100644 index 0000000000..586d8bb615 --- /dev/null +++ b/examples/mimxrt1064-evk/src/bin/button.rs @@ -0,0 +1,30 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nxp::gpio::{Input, Level, Output, Pull}; +// Must include `embassy_imxrt1064_evk_examples` to ensure the FCB gets linked. +use {defmt_rtt as _, embassy_imxrt1064_evk_examples as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_nxp::init(Default::default()); + info!("Hello world!"); + + // User LED (D18) + let led = p.GPIO_AD_B0_09; + // User button (SW8) + let button = p.WAKEUP; + let button = Input::new(button, Pull::Up100K); + let mut led = Output::new(led, Level::Low); + led.set_high(); + + loop { + if button.is_high() { + led.set_high(); + } else { + led.set_low(); + } + } +} diff --git a/examples/mimxrt1064-evk/src/lib.rs b/examples/mimxrt1064-evk/src/lib.rs new file mode 100644 index 0000000000..64b4416cc4 --- /dev/null +++ b/examples/mimxrt1064-evk/src/lib.rs @@ -0,0 +1,70 @@ +//! FlexSPI configuration block (FCB) for the iMXRT1064-EVK + +#![no_std] + +use imxrt_boot_gen::flexspi::opcodes::sdr::*; +use imxrt_boot_gen::flexspi::{self, FlashPadType, ReadSampleClockSource, SerialClockFrequency, SerialFlashRegion, *}; +use imxrt_boot_gen::serial_flash::*; +pub use nor::ConfigurationBlock; + +const SEQ_READ: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0xEB)) + .instr(Instr::new(RADDR, Pads::Four, 0x18)) + .instr(Instr::new(DUMMY, Pads::Four, 0x06)) + .instr(Instr::new(READ, Pads::Four, 0x04)) + .build(); + +const SEQ_READ_STATUS: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x05)) + .instr(Instr::new(READ, Pads::One, 0x04)) + .build(); + +const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x06)) + .instr(STOP) + .build(); + +const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x20)) + .instr(Instr::new(RADDR, Pads::One, 0x18)) + .build(); + +const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x02)) + .instr(Instr::new(RADDR, Pads::One, 0x18)) + .instr(Instr::new(WRITE, Pads::One, 0x04)) + .instr(STOP) + .build(); + +const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x60)) + .instr(STOP) + .build(); + +const LUT: LookupTable = LookupTable::new() + .command(Command::Read, SEQ_READ) + .command(Command::ReadStatus, SEQ_READ_STATUS) + .command(Command::WriteEnable, SEQ_WRITE_ENABLE) + .command(Command::EraseSector, SEQ_ERASE_SECTOR) + .command(Command::PageProgram, SEQ_PAGE_PROGRAM) + .command(Command::ChipErase, SEQ_CHIP_ERASE); + +const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock = flexspi::ConfigurationBlock::new(LUT) + .version(Version::new(1, 4, 0)) + .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad) + .cs_hold_time(3) + .cs_setup_time(3) + .controller_misc_options(0x10) + .serial_flash_pad_type(FlashPadType::Quad) + .serial_clk_freq(SerialClockFrequency::MHz120) + .flash_size(SerialFlashRegion::A1, 4 * 1024 * 1024); + +pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock = + nor::ConfigurationBlock::new(COMMON_CONFIGURATION_BLOCK) + .page_size(256) + .sector_size(4 * 1024) + .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); + +#[unsafe(no_mangle)] +#[cfg_attr(all(target_arch = "arm", target_os = "none"), unsafe(link_section = ".fcb"))] +pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK;