diff --git a/Cargo.toml b/Cargo.toml index dad28be48b..ddaecaf339 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,14 +22,14 @@ members = [ "boards/redboard_artemis_nano", "boards/stm32f3discovery", "boards/stm32f412gdiscovery", + "boards/teensy40", "boards/nano33ble", "capsules", "chips/apollo3", "chips/arty_e21_chip", "chips/e310x", - "chips/imxrt1050", "chips/earlgrey", - "chips/imxrt1050", + "chips/imxrt10xx", "chips/lowrisc", "chips/msp432", "chips/nrf52", diff --git a/arch/cortex-m7/src/lib.rs b/arch/cortex-m7/src/lib.rs index 885b7ffe8b..8f97605021 100644 --- a/arch/cortex-m7/src/lib.rs +++ b/arch/cortex-m7/src/lib.rs @@ -20,6 +20,7 @@ pub use cortexm::svc_handler; pub use cortexm::syscall; pub use cortexm::systick; pub use cortexm::systick_handler; +pub use cortexm::unhandled_interrupt; /// Provide a `switch_to_user` function with exactly that name for syscall.rs. #[cfg(all(target_arch = "arm", target_os = "none"))] diff --git a/boards/README.md b/boards/README.md index 4fdd861d12..c39a5bf70f 100644 --- a/boards/README.md +++ b/boards/README.md @@ -19,6 +19,7 @@ that Tock supports. | [STM32F412G Discovery kit](stm32f412gdiscovery/README.md) | ARM Cortex-M4 | STM32F412G | openocd | custom | #1827 | | [SparkFun RedBoard Artemis Nano](redboard_artemis_nano/README.md) | ARM Cortex-M4 | Apollo3 | custom | custom | No | | [i.MX RT 1052 Evaluation Kit](imxrt1050-evkb/README.md) | ARM Cortex-M7 | i.MX RT 1052 | custom | custom | No | +| [Teensy 4.0](teensy40/README.md) | ARM Cortex-M7 | i.MX RT 1062 | custom | custom | No | | [SiFive HiFive1](hifive1/README.md) | RISC-V | FE310-G000 | openocd | tockloader | [Yes (5.1)][qemu] | | [Digilent Arty A-7 100T](arty_e21/README.md) | RISC-V RV32IMAC | SiFive E21 | openocd | tockloader | No | | [Earlgrey on Nexys Video](earlgrey_nexysvideo/README.md) | RISC-V RV32IMC | EarlGrey | custom | custom | [Yes (5.1)][qemu] | diff --git a/boards/imxrt1050-evkb/Cargo.toml b/boards/imxrt1050-evkb/Cargo.toml index a5b4478836..f3dcaf7416 100644 --- a/boards/imxrt1050-evkb/Cargo.toml +++ b/boards/imxrt1050-evkb/Cargo.toml @@ -10,4 +10,4 @@ components = { path = "../components" } cortexm7 = { path = "../../arch/cortex-m7" } capsules = { path = "../../capsules" } kernel = { path = "../../kernel" } -imxrt1050 = { path = "../../chips/imxrt1050" } \ No newline at end of file +imxrt10xx = { path = "../../chips/imxrt10xx" } \ No newline at end of file diff --git a/boards/imxrt1050-evkb/src/io.rs b/boards/imxrt1050-evkb/src/io.rs index adb7b51cfa..2a42e03785 100644 --- a/boards/imxrt1050-evkb/src/io.rs +++ b/boards/imxrt1050-evkb/src/io.rs @@ -7,7 +7,7 @@ use kernel::hil::led; use kernel::hil::uart; use kernel::hil::uart::Configure; -use imxrt1050; +use crate::imxrt1050; use imxrt1050::gpio::PinId; use crate::CHIP; diff --git a/boards/imxrt1050-evkb/src/main.rs b/boards/imxrt1050-evkb/src/main.rs index bb6e89faa3..1441b33b55 100644 --- a/boards/imxrt1050-evkb/src/main.rs +++ b/boards/imxrt1050-evkb/src/main.rs @@ -19,7 +19,6 @@ use kernel::{create_capability, static_init}; // use components::fxos8700::Fxos8700Component; // use components::ninedof::NineDofComponent; - use imxrt1050::iomuxc::DriveStrength; use imxrt1050::iomuxc::MuxMode; use imxrt1050::iomuxc::OpenDrainEn; @@ -28,6 +27,7 @@ use imxrt1050::iomuxc::PullKeepEn; use imxrt1050::iomuxc::PullUpDown; use imxrt1050::iomuxc::Sion; use imxrt1050::iomuxc::Speed; +use imxrt10xx as imxrt1050; // Unit Tests for drivers. // #[allow(dead_code)] @@ -45,7 +45,7 @@ const NUM_PROCS: usize = 1; // Actual memory for holding the active process structures. static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] = [None]; -static mut CHIP: Option<&'static imxrt1050::chip::Imxrt1050> = None; +static mut CHIP: Option<&'static imxrt1050::chip::Imxrt10xx> = None; // How should the kernel respond when a process faults. const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic; @@ -67,7 +67,7 @@ pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000]; struct Imxrt1050EVKB { alarm: &'static capsules::alarm::AlarmDriver< 'static, - VirtualMuxAlarm<'static, imxrt1050::gpt1::Gpt1<'static>>, + VirtualMuxAlarm<'static, imxrt1050::gpt::Gpt1<'static>>, >, button: &'static capsules::button::Button<'static, imxrt1050::gpio::Pin<'static>>, console: &'static capsules::console::Console<'static>, @@ -163,14 +163,15 @@ unsafe fn set_pin_primary_functions() { /// Helper function for miscellaneous peripheral functions unsafe fn setup_peripherals() { - use imxrt1050::gpt1::GPT1; + use imxrt1050::ccm::CCM; + use imxrt1050::gpt::GPT1; // LPUART1 IRQn is 20 cortexm7::nvic::Nvic::new(imxrt1050::nvic::LPUART1).enable(); // TIM2 IRQn is 28 GPT1.enable_clock(); - GPT1.start(); + GPT1.start(CCM.perclk_sel(), CCM.perclk_divider()); cortexm7::nvic::Nvic::new(imxrt1050::nvic::GPT1).enable(); } @@ -201,8 +202,8 @@ pub unsafe fn reset_handler() { DynamicDeferredCall::set_global_instance(dynamic_deferred_caller); let chip = static_init!( - imxrt1050::chip::Imxrt1050, - imxrt1050::chip::Imxrt1050::new() + imxrt1050::chip::Imxrt10xx, + imxrt1050::chip::Imxrt10xx::new() ); CHIP = Some(chip); @@ -298,13 +299,13 @@ pub unsafe fn reset_handler() { .finalize(components::button_component_buf!(imxrt1050::gpio::Pin)); // ALARM - let gpt1 = &imxrt1050::gpt1::GPT1; + let gpt1 = &imxrt1050::gpt::GPT1; let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize( - components::alarm_mux_component_helper!(imxrt1050::gpt1::Gpt1), + components::alarm_mux_component_helper!(imxrt1050::gpt::Gpt1), ); let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm) - .finalize(components::alarm_component_helper!(imxrt1050::gpt1::Gpt1)); + .finalize(components::alarm_component_helper!(imxrt1050::gpt::Gpt1)); // GPIO // For now we expose only two pins diff --git a/boards/teensy40/Cargo.toml b/boards/teensy40/Cargo.toml new file mode 100644 index 0000000000..4adb802897 --- /dev/null +++ b/boards/teensy40/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "teensy40" +version = "0.1.0" +authors = ["Tock Project Developers "] +build = "build.rs" +edition = "2018" + +[dependencies] +components = { path = "../components" } +cortexm7 = { path = "../../arch/cortex-m7" } +capsules = { path = "../../capsules" } +kernel = { path = "../../kernel" } +imxrt10xx = { path = "../../chips/imxrt10xx" } diff --git a/boards/teensy40/Makefile b/boards/teensy40/Makefile new file mode 100644 index 0000000000..1e04f9b1ef --- /dev/null +++ b/boards/teensy40/Makefile @@ -0,0 +1,31 @@ +# Makefile for building the tock kernel for the Teensy 4 + +TARGET=thumbv7em-none-eabi +PLATFORM=teensy40 + +include ../Makefile.common + +%.hex: %.elf + $(Q)$(OBJCOPY) -O ihex $< $@ + +kernel: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).elf + +.PHONY: program +program: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).hex + $(Q)teensy_loader_cli --mcu=TEENSY40 -w -v $< + +# Unsupported; there's no easily-accessible JTAG interface +.PHONY: flash +flash: + echo "Use 'make program' to program the Teensy 4" + exit 1 + +# For testing with a blinky LED +BLINK=../../../libtock-c/examples/blink/build/cortex-m7/cortex-m7.tbf +app.elf: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).elf + $(Q)arm-none-eabi-objcopy --update-section .apps=$(BLINK) $< $@ + +app: app.elf + $(Q)$(OBJCOPY) -O ihex $< $@ + teensy_loader_cli --mcu=TEENSY40 -w -v $@ + $(Q)rm $@ $< diff --git a/boards/teensy40/README.md b/boards/teensy40/README.md new file mode 100644 index 0000000000..b681342308 --- /dev/null +++ b/boards/teensy40/README.md @@ -0,0 +1,80 @@ +Teensy 4.0 Development Board +============================ + +The `teensy40` board supports the Teensy **4.0** development board. +For more information, visit the +[Teensy 4.0 Development Board](https://www.pjrc.com/store/teensy40.html) +product page. + +The board may suffice for the [Teensy **4.1** development board](t41), which +shares common pins and a larger amount of flash memory. However, the board +will not contain features that are only available on the Teensy 4.1 development +board, such as extended flash memory and RAM, an on-board SD card, or ethernet. + +[t41]: https://www.pjrc.com/store/teensy41.html + +Programming Dependencies +------------------------ + +Before attempting to program your Teensy 4.0 with Tock and Tock apps, make sure +that you have either + +- a build of [`teensy_loader_cli`](https://github.com/PaulStoffregen/teensy_loader_cli), or +- the [Teensy Loader Application](https://www.pjrc.com/teensy/loader.html) + +If you're already familiar with programming the Teensy with Arduino tools, +the Teensy Loader Application is already bundled with the Teensyduino add-ons +that you may already be using. + +Programming +----------- + +From this directory, build the Tock kernel for the Teensy 4: + +```bash +$ make +``` + +Build Tock apps out of tree. Once you've built an app, use +`arm-none-eabi-objcopy` with `--update-section` to create an ELF image that +includes your app(s). The example below combines a prebuilt `blink` example +with the Teensy 4 Tock kernel. + +```bash +$ arm-none-eabi-objcopy \ + --update-section .apps=../../../libtock-c/examples/blink/build/cortex-m7/cortex-m7.tbf \ + ../../target/thumbv7em-none-eabi/release/teensy40.elf \ + ../../target/thumbv7em-none-eabi/release/teensy40-app.elf +``` + +Once you've created a single ELF image, use `arm-none-eabi-objcopy` to turn +that into HEX: + +```bash +$ arm-none-eabi-objcopy -O ihex \ + ../../target/thumbv7em-none-eabi/release/teensy40-app.elf \ + ../../target/thumbv7em-none-eabi/release/teensy40-app.hex +``` + +Finally, use a Teensy programmer to flash `teensy40-app.hex` to your board! + +```bash +$ teensy_loader_cli -w -v --mcu=TEENSY40 target/thumbv7em-none-eabi/release/teensy40-app.hex +``` + +Use the example `Makefile` below to create a build and flash workflow: + +```Makefile +APP=../../../libtock-c/examples/blink/build/cortex-m7/cortex-m7.tbf +KERNEL=$(TOCK_ROOT_DIRECTORY)/target/teensy40/release/teensy40.elf +KERNEL_WITH_APP=$(TOCK_ROOT_DIRECTORY)/target/teensy40/release/teensy40-app.elf +KERNEL_WITH_APP_HEX=$(TOCK_ROOT_DIRECTORY)/target/teensy40/release/teensy40-app.hex + +.PHONY: program +program: target/thumbv7em-none-eabi/release/teensy40.elf + arm-none-eabi-objcopy --update-section .apps=$(APP) $(KERNEL) $(KERNEL_WITH_APP) + arm-none-eabi-objcopy -O ihex $(KENERL_WITH_APP) $(KERNEL_WITH_APP_HEX) + teensy_loader_cli -w -v --mcu=TEENSY40 $(KERNEL_WITH_APP_HEX) +``` + +For another example, see [`Makefile`](./Makefile). diff --git a/boards/teensy40/build.rs b/boards/teensy40/build.rs new file mode 100644 index 0000000000..3051054fc6 --- /dev/null +++ b/boards/teensy40/build.rs @@ -0,0 +1,4 @@ +fn main() { + println!("cargo:rerun-if-changed=layout.ld"); + println!("cargo:rerun-if-changed=../kernel_layout.ld"); +} diff --git a/boards/teensy40/layout.ld b/boards/teensy40/layout.ld new file mode 100644 index 0000000000..681dda017d --- /dev/null +++ b/boards/teensy40/layout.ld @@ -0,0 +1,72 @@ +/* + * Teensy 4 Linker Script + * + * We do not utilize any of the tightly-coupled memory (TCM) + * regions. There's another 512KB region that could be + * used for RAM, or for instruction execution (ITCM), or for + * quickly-accessible data (DTCM). + * + * NXP's iMXRT processors require a special boot section, which + * we call '.boot' below. It contains the FlexSPI Configuration + * Block (FCB) for serial NOR flash, and the image vector table + * (IVT). The FCB is available in src/fcb.rs. + */ + +MEMORY +{ + rom (rx) : ORIGIN = 0x60000000, LENGTH = 512K + prog (rx) : ORIGIN = 0x60080000, LENGTH = 512K + ram (rwx) : ORIGIN = 0x20200000, LENGTH = 512K +} + +MPU_MIN_ALIGN = 8K; + +SECTIONS +{ + .boot : + { + /* FlexSPI Configuration Block (defined in source) */ + KEEP(*(.fcb)); + KEEP(*(.fcb_buffer)); + /* ------------------ + * Image Vector Table + * ------------------ + * + * See section 9.7.1.1 "Image vector table structure" + * of the IMXRT1060 reference manual. + */ + _ivt = .; + LONG(0x402000D1); /* Header, magic number */ + /* Address to the vector table + * + * Relies on the fact that the vector table is the + * first thing in ROM. + */ + LONG(_stext); + LONG(0x00000000); /* RESERVED */ + LONG(0x00000000); /* Device Configuration Data (unused) */ + LONG(_boot_data); /* Address of boot data */ + LONG(_ivt); /* Address to the IVT (self) */ + LONG(0x00000000); /* Command Sequence File (unused) */ + LONG(0x00000000); /* RESERVED */ + /* --------- + * Boot Data + * --------- + * + * See section 9.7.1.2 "Boot data structure" of the + * IMXRT1060 reference manual. + */ + _boot_data = .; + LONG(ORIGIN(rom)); /* Start of image */ + /* Size of the program image (assuming that we also need the boot section) */ + LONG((_etext-_stext) + (_erelocate-_srelocate) + SIZEOF(.boot)); + LONG(0x00000000); /* Plugin flag (unused) */ + /* End of iMXRT10xx magic + * + * Need to align vector table on a 1024-byte boundary given the size of the table + */ + . = ALIGN(1024); + } > rom +} + +INCLUDE ../kernel_layout.ld diff --git a/boards/teensy40/src/fcb.rs b/boards/teensy40/src/fcb.rs new file mode 100644 index 0000000000..401f06f1ae --- /dev/null +++ b/boards/teensy40/src/fcb.rs @@ -0,0 +1,530 @@ +//! FlexSPI Configuration Block (FCB) +//! +//! The FCB holds command sequences and configurations necessary to boot +//! an iMXRT10xx processor from FLASH over SPI. +//! +//! The array was auto-generated using the [`imxrt-boot-gen` crate](https://github.com/imxrt-rs/imxrt-boot-gen). +//! We copied the array of magic numbers here, rather than incorporating +//! that build-time dependency in tock. +//! +//! The array is only referenced in the linker script. + +pub type FCB = [u8; 512]; + +#[link_section = ".fcb"] +#[no_mangle] +#[used] +static FLEXSPI_CONFIGURATION_BLOCK: FCB = [ + 0x46, // 0x000 Tag 'FCFB' + 0x43, // 0x001 + 0x46, // 0x002 + 0x42, // 0x003 + 0x00, // 0x004 Version 'bugfix' + 0x00, // 0x005 Version 'minor' + 0x01, // 0x006 Version 'major + 0x56, // 0x007 Version 'V' + 0x00, // 0x008 RESERVED + 0x00, // 0x009 RESERVED + 0x00, // 0x00A RESERVED + 0x00, // 0x00B RESERVED + 0x01, // 0x00C readSampleClkSrc + 0x01, // 0x00D csHoldTime + 0x02, // 0x00E csSetupTime + 0x00, // 0x00F columnAddressWidth + 0x00, // 0x010 deviceModeCfgEnable + 0x00, // 0x011 RESERVED + 0x00, // 0x012 + 0x00, // 0x013 waitTimeCfgCommands + 0x00, // 0x014 + 0x00, // 0x015 + 0x00, // 0x016 + 0x00, // 0x017 + 0x00, // 0x018 + 0x00, // 0x019 + 0x00, // 0x01A + 0x00, // 0x01B + 0x00, // 0x01C + 0x00, // 0x01D RESERVED + 0x00, // 0x01E RESERVED + 0x00, // 0x01F RESERVED + 0x00, // 0x020 + 0x00, // 0x021 + 0x00, // 0x022 + 0x00, // 0x023 + 0x00, // 0x024 + 0x00, // 0x025 + 0x00, // 0x026 + 0x00, // 0x027 + 0x00, // 0x028 + 0x00, // 0x029 + 0x00, // 0x02A + 0x00, // 0x02B + 0x00, // 0x02C RESERVED + 0x00, // 0x02D RESERVED + 0x00, // 0x02E RESERVED + 0x00, // 0x02F RESERVED + 0x00, // 0x030 + 0x00, // 0x031 + 0x00, // 0x032 + 0x00, // 0x033 + 0x00, // 0x034 + 0x00, // 0x035 + 0x00, // 0x036 + 0x00, // 0x037 + 0x00, // 0x038 + 0x00, // 0x039 + 0x00, // 0x03A + 0x00, // 0x03B + 0x00, // 0x03C RESERVED + 0x00, // 0x03D RESERVED + 0x00, // 0x03E RESERVED + 0x00, // 0x03F RESERVED + 0x00, // 0x040 + 0x00, // 0x041 + 0x00, // 0x042 + 0x00, // 0x043 + 0x01, // 0x044 deviceType + 0x04, // 0x045 sflashPadType + 0x03, // 0x046 serialClkFreq + 0x00, // 0x047 + 0x00, // 0x048 RESERVED + 0x00, // 0x049 RESERVED + 0x00, // 0x04A RESERVED + 0x00, // 0x04B RESERVED + 0x00, // 0x04C RESERVED + 0x00, // 0x04D RESERVED + 0x00, // 0x04E RESERVED + 0x00, // 0x04F RESERVED + 0x00, // 0x050 sflashA1Size + 0x00, // 0x051 + 0x20, // 0x052 + 0x00, // 0x053 + 0x00, // 0x054 sflashA2Size + 0x00, // 0x055 + 0x00, // 0x056 + 0x00, // 0x057 + 0x00, // 0x058 sflashB1Size + 0x00, // 0x059 + 0x00, // 0x05A + 0x00, // 0x05B + 0x00, // 0x05C sflashB2Size + 0x00, // 0x05D + 0x00, // 0x05E + 0x00, // 0x05F + 0x00, // 0x060 + 0x00, // 0x061 + 0x00, // 0x062 + 0x00, // 0x063 + 0x00, // 0x064 + 0x00, // 0x065 + 0x00, // 0x066 + 0x00, // 0x067 + 0x00, // 0x068 + 0x00, // 0x069 + 0x00, // 0x06A + 0x00, // 0x06B + 0x00, // 0x06C + 0x00, // 0x06D + 0x00, // 0x06E + 0x00, // 0x06F + 0x00, // 0x070 + 0x00, // 0x071 + 0x00, // 0x072 + 0x00, // 0x073 + 0x00, // 0x074 + 0x00, // 0x075 + 0x00, // 0x076 + 0x00, // 0x077 + 0x00, // 0x078 + 0x00, // 0x079 + 0x00, // 0x07A + 0x00, // 0x07B + 0x00, // 0x07C + 0x00, // 0x07D + 0x00, // 0x07E + 0x00, // 0x07F + 0xEB, // 0x080 (LUT[0]) READ: OPCODE=CMD_SDR, PADS=SINGLE, OPERAND=0xEB + 0x04, // 0x081 + 0x18, // 0x082 (LUT[0]) READ: OPCODE=RADDR_SDR, PADS=QUAD, OPERAND=0x18 + 0x0A, // 0x083 + 0x06, // 0x084 (LUT[0]) READ: OPCODE=DUMMY_SDR, PADS=QUAD, OPERAND=0x6 + 0x32, // 0x085 + 0x04, // 0x086 (LUT[0]) READ: OPCODE=READ_SDR, PADS=QUAD, OPERAND=0x4 + 0x26, // 0x087 + 0x00, // 0x088 (LUT[0]) READ: STOP + 0x00, // 0x089 + 0x00, // 0x08A (LUT[0]) READ: STOP + 0x00, // 0x08B + 0x00, // 0x08C (LUT[0]) READ: STOP + 0x00, // 0x08D + 0x00, // 0x08E (LUT[0]) READ: STOP + 0x00, // 0x08F + 0x05, // 0x090 (LUT[1]) READ_STATUS: OPCODE=CMD_SDR, PADS=SINGLE, OPERAND=0x5 + 0x04, // 0x091 + 0x04, // 0x092 (LUT[1]) READ_STATUS: OPCODE=READ_SDR, PADS=SINGLE, OPERAND=0x4 + 0x24, // 0x093 + 0x00, // 0x094 (LUT[1]) READ_STATUS: STOP + 0x00, // 0x095 + 0x00, // 0x096 (LUT[1]) READ_STATUS: STOP + 0x00, // 0x097 + 0x00, // 0x098 (LUT[1]) READ_STATUS: STOP + 0x00, // 0x099 + 0x00, // 0x09A (LUT[1]) READ_STATUS: STOP + 0x00, // 0x09B + 0x00, // 0x09C (LUT[1]) READ_STATUS: STOP + 0x00, // 0x09D + 0x00, // 0x09E (LUT[1]) READ_STATUS: STOP + 0x00, // 0x09F + 0x00, // 0x0A0 (LUT[2]) + 0x00, // 0x0A1 + 0x00, // 0x0A2 (LUT[2]) + 0x00, // 0x0A3 + 0x00, // 0x0A4 (LUT[2]) + 0x00, // 0x0A5 + 0x00, // 0x0A6 (LUT[2]) + 0x00, // 0x0A7 + 0x00, // 0x0A8 (LUT[2]) + 0x00, // 0x0A9 + 0x00, // 0x0AA (LUT[2]) + 0x00, // 0x0AB + 0x00, // 0x0AC (LUT[2]) + 0x00, // 0x0AD + 0x00, // 0x0AE (LUT[2]) + 0x00, // 0x0AF + 0x06, // 0x0B0 (LUT[3]) WRITE_ENABLE: OPCODE=CMD_SDR, PADS=SINGLE, OPERAND=0x6 + 0x04, // 0x0B1 + 0x00, // 0x0B2 (LUT[3]) WRITE_ENABLE: STOP + 0x00, // 0x0B3 + 0x00, // 0x0B4 (LUT[3]) WRITE_ENABLE: STOP + 0x00, // 0x0B5 + 0x00, // 0x0B6 (LUT[3]) WRITE_ENABLE: STOP + 0x00, // 0x0B7 + 0x00, // 0x0B8 (LUT[3]) WRITE_ENABLE: STOP + 0x00, // 0x0B9 + 0x00, // 0x0BA (LUT[3]) WRITE_ENABLE: STOP + 0x00, // 0x0BB + 0x00, // 0x0BC (LUT[3]) WRITE_ENABLE: STOP + 0x00, // 0x0BD + 0x00, // 0x0BE (LUT[3]) WRITE_ENABLE: STOP + 0x00, // 0x0BF + 0x00, // 0x0C0 (LUT[4]) + 0x00, // 0x0C1 + 0x00, // 0x0C2 (LUT[4]) + 0x00, // 0x0C3 + 0x00, // 0x0C4 (LUT[4]) + 0x00, // 0x0C5 + 0x00, // 0x0C6 (LUT[4]) + 0x00, // 0x0C7 + 0x00, // 0x0C8 (LUT[4]) + 0x00, // 0x0C9 + 0x00, // 0x0CA (LUT[4]) + 0x00, // 0x0CB + 0x00, // 0x0CC (LUT[4]) + 0x00, // 0x0CD + 0x00, // 0x0CE (LUT[4]) + 0x00, // 0x0CF + 0x20, // 0x0D0 (LUT[5]) ERASE_SECTOR: OPCODE=CMD_SDR, PADS=SINGLE, OPERAND=0x20 + 0x04, // 0x0D1 + 0x18, // 0x0D2 (LUT[5]) ERASE_SECTOR: OPCODE=RADDR_SDR, PADS=SINGLE, OPERAND=0x18 + 0x08, // 0x0D3 + 0x00, // 0x0D4 (LUT[5]) ERASE_SECTOR: STOP + 0x00, // 0x0D5 + 0x00, // 0x0D6 (LUT[5]) ERASE_SECTOR: STOP + 0x00, // 0x0D7 + 0x00, // 0x0D8 (LUT[5]) ERASE_SECTOR: STOP + 0x00, // 0x0D9 + 0x00, // 0x0DA (LUT[5]) ERASE_SECTOR: STOP + 0x00, // 0x0DB + 0x00, // 0x0DC (LUT[5]) ERASE_SECTOR: STOP + 0x00, // 0x0DD + 0x00, // 0x0DE (LUT[5]) ERASE_SECTOR: STOP + 0x00, // 0x0DF + 0x00, // 0x0E0 (LUT[6]) + 0x00, // 0x0E1 + 0x00, // 0x0E2 (LUT[6]) + 0x00, // 0x0E3 + 0x00, // 0x0E4 (LUT[6]) + 0x00, // 0x0E5 + 0x00, // 0x0E6 (LUT[6]) + 0x00, // 0x0E7 + 0x00, // 0x0E8 (LUT[6]) + 0x00, // 0x0E9 + 0x00, // 0x0EA (LUT[6]) + 0x00, // 0x0EB + 0x00, // 0x0EC (LUT[6]) + 0x00, // 0x0ED + 0x00, // 0x0EE (LUT[6]) + 0x00, // 0x0EF + 0x00, // 0x0F0 (LUT[7]) + 0x00, // 0x0F1 + 0x00, // 0x0F2 (LUT[7]) + 0x00, // 0x0F3 + 0x00, // 0x0F4 (LUT[7]) + 0x00, // 0x0F5 + 0x00, // 0x0F6 (LUT[7]) + 0x00, // 0x0F7 + 0x00, // 0x0F8 (LUT[7]) + 0x00, // 0x0F9 + 0x00, // 0x0FA (LUT[7]) + 0x00, // 0x0FB + 0x00, // 0x0FC (LUT[7]) + 0x00, // 0x0FD + 0x00, // 0x0FE (LUT[7]) + 0x00, // 0x0FF + 0x00, // 0x100 (LUT[8]) + 0x00, // 0x101 + 0x00, // 0x102 (LUT[8]) + 0x00, // 0x103 + 0x00, // 0x104 (LUT[8]) + 0x00, // 0x105 + 0x00, // 0x106 (LUT[8]) + 0x00, // 0x107 + 0x00, // 0x108 (LUT[8]) + 0x00, // 0x109 + 0x00, // 0x10A (LUT[8]) + 0x00, // 0x10B + 0x00, // 0x10C (LUT[8]) + 0x00, // 0x10D + 0x00, // 0x10E (LUT[8]) + 0x00, // 0x10F + 0x02, // 0x110 (LUT[9]) PAGE_PROGRAM: OPCODE=CMD_SDR, PADS=SINGLE, OPERAND=0x2 + 0x04, // 0x111 + 0x18, // 0x112 (LUT[9]) PAGE_PROGRAM: OPCODE=RADDR_SDR, PADS=SINGLE, OPERAND=0x18 + 0x08, // 0x113 + 0x04, // 0x114 (LUT[9]) PAGE_PROGRAM: OPCODE=WRITE_SDR, PADS=SINGLE, OPERAND=0x4 + 0x20, // 0x115 + 0x00, // 0x116 (LUT[9]) PAGE_PROGRAM: STOP + 0x00, // 0x117 + 0x00, // 0x118 (LUT[9]) PAGE_PROGRAM: STOP + 0x00, // 0x119 + 0x00, // 0x11A (LUT[9]) PAGE_PROGRAM: STOP + 0x00, // 0x11B + 0x00, // 0x11C (LUT[9]) PAGE_PROGRAM: STOP + 0x00, // 0x11D + 0x00, // 0x11E (LUT[9]) PAGE_PROGRAM: STOP + 0x00, // 0x11F + 0x00, // 0x120 (LUT[10]) + 0x00, // 0x121 + 0x00, // 0x122 (LUT[10]) + 0x00, // 0x123 + 0x00, // 0x124 (LUT[10]) + 0x00, // 0x125 + 0x00, // 0x126 (LUT[10]) + 0x00, // 0x127 + 0x00, // 0x128 (LUT[10]) + 0x00, // 0x129 + 0x00, // 0x12A (LUT[10]) + 0x00, // 0x12B + 0x00, // 0x12C (LUT[10]) + 0x00, // 0x12D + 0x00, // 0x12E (LUT[10]) + 0x00, // 0x12F + 0x60, // 0x130 (LUT[11]) CHIP_ERASE: OPCODE=CMD_SDR, PADS=SINGLE, OPERAND=0x60 + 0x04, // 0x131 + 0x00, // 0x132 (LUT[11]) CHIP_ERASE: STOP + 0x00, // 0x133 + 0x00, // 0x134 (LUT[11]) CHIP_ERASE: STOP + 0x00, // 0x135 + 0x00, // 0x136 (LUT[11]) CHIP_ERASE: STOP + 0x00, // 0x137 + 0x00, // 0x138 (LUT[11]) CHIP_ERASE: STOP + 0x00, // 0x139 + 0x00, // 0x13A (LUT[11]) CHIP_ERASE: STOP + 0x00, // 0x13B + 0x00, // 0x13C (LUT[11]) CHIP_ERASE: STOP + 0x00, // 0x13D + 0x00, // 0x13E (LUT[11]) CHIP_ERASE: STOP + 0x00, // 0x13F + 0x00, // 0x140 (LUT[12]) + 0x00, // 0x141 + 0x00, // 0x142 (LUT[12]) + 0x00, // 0x143 + 0x00, // 0x144 (LUT[12]) + 0x00, // 0x145 + 0x00, // 0x146 (LUT[12]) + 0x00, // 0x147 + 0x00, // 0x148 (LUT[12]) + 0x00, // 0x149 + 0x00, // 0x14A (LUT[12]) + 0x00, // 0x14B + 0x00, // 0x14C (LUT[12]) + 0x00, // 0x14D + 0x00, // 0x14E (LUT[12]) + 0x00, // 0x14F + 0x00, // 0x150 (LUT[13]) + 0x00, // 0x151 + 0x00, // 0x152 (LUT[13]) + 0x00, // 0x153 + 0x00, // 0x154 (LUT[13]) + 0x00, // 0x155 + 0x00, // 0x156 (LUT[13]) + 0x00, // 0x157 + 0x00, // 0x158 (LUT[13]) + 0x00, // 0x159 + 0x00, // 0x15A (LUT[13]) + 0x00, // 0x15B + 0x00, // 0x15C (LUT[13]) + 0x00, // 0x15D + 0x00, // 0x15E (LUT[13]) + 0x00, // 0x15F + 0x00, // 0x160 (LUT[14]) + 0x00, // 0x161 + 0x00, // 0x162 (LUT[14]) + 0x00, // 0x163 + 0x00, // 0x164 (LUT[14]) + 0x00, // 0x165 + 0x00, // 0x166 (LUT[14]) + 0x00, // 0x167 + 0x00, // 0x168 (LUT[14]) + 0x00, // 0x169 + 0x00, // 0x16A (LUT[14]) + 0x00, // 0x16B + 0x00, // 0x16C (LUT[14]) + 0x00, // 0x16D + 0x00, // 0x16E (LUT[14]) + 0x00, // 0x16F + 0x00, // 0x170 (LUT[15]) DUMMY: STOP + 0x00, // 0x171 + 0x00, // 0x172 (LUT[15]) DUMMY: STOP + 0x00, // 0x173 + 0x00, // 0x174 (LUT[15]) DUMMY: STOP + 0x00, // 0x175 + 0x00, // 0x176 (LUT[15]) DUMMY: STOP + 0x00, // 0x177 + 0x00, // 0x178 (LUT[15]) DUMMY: STOP + 0x00, // 0x179 + 0x00, // 0x17A (LUT[15]) DUMMY: STOP + 0x00, // 0x17B + 0x00, // 0x17C (LUT[15]) DUMMY: STOP + 0x00, // 0x17D + 0x00, // 0x17E (LUT[15]) DUMMY: STOP + 0x00, // 0x17F + 0x00, // 0x180 + 0x00, // 0x181 + 0x00, // 0x182 + 0x00, // 0x183 + 0x00, // 0x184 + 0x00, // 0x185 + 0x00, // 0x186 + 0x00, // 0x187 + 0x00, // 0x188 + 0x00, // 0x189 + 0x00, // 0x18A + 0x00, // 0x18B + 0x00, // 0x18C + 0x00, // 0x18D + 0x00, // 0x18E + 0x00, // 0x18F + 0x00, // 0x190 + 0x00, // 0x191 + 0x00, // 0x192 + 0x00, // 0x193 + 0x00, // 0x194 + 0x00, // 0x195 + 0x00, // 0x196 + 0x00, // 0x197 + 0x00, // 0x198 + 0x00, // 0x199 + 0x00, // 0x19A + 0x00, // 0x19B + 0x00, // 0x19C + 0x00, // 0x19D + 0x00, // 0x19E + 0x00, // 0x19F + 0x00, // 0x1A0 + 0x00, // 0x1A1 + 0x00, // 0x1A2 + 0x00, // 0x1A3 + 0x00, // 0x1A4 + 0x00, // 0x1A5 + 0x00, // 0x1A6 + 0x00, // 0x1A7 + 0x00, // 0x1A8 + 0x00, // 0x1A9 + 0x00, // 0x1AA + 0x00, // 0x1AB + 0x00, // 0x1AC + 0x00, // 0x1AD + 0x00, // 0x1AE + 0x00, // 0x1AF + 0x00, // 0x1B0 RESERVED + 0x00, // 0x1B1 RESERVED + 0x00, // 0x1B2 RESERVED + 0x00, // 0x1B3 RESERVED + 0x00, // 0x1B4 RESERVED + 0x00, // 0x1B5 RESERVED + 0x00, // 0x1B6 RESERVED + 0x00, // 0x1B7 RESERVED + 0x00, // 0x1B8 RESERVED + 0x00, // 0x1B9 RESERVED + 0x00, // 0x1BA RESERVED + 0x00, // 0x1BB RESERVED + 0x00, // 0x1BC RESERVED + 0x00, // 0x1BD RESERVED + 0x00, // 0x1BE RESERVED + 0x00, // 0x1BF RESERVED + 0x00, // 0x1C0 pageSize + 0x01, // 0x1C1 + 0x00, // 0x1C2 + 0x00, // 0x1C3 + 0x00, // 0x1C4 sectorSize + 0x10, // 0x1C5 + 0x00, // 0x1C6 + 0x00, // 0x1C7 + 0x01, // 0x1C8 ipCmdSerialClkFreq + 0x00, // 0x1C9 + 0x00, // 0x1CA + 0x00, // 0x1CB + 0x00, // 0x1CC RESERVED + 0x00, // 0x1CD RESERVED + 0x00, // 0x1CE RESERVED + 0x00, // 0x1CF RESERVED + 0x00, // 0x1D0 RESERVED + 0x00, // 0x1D1 RESERVED + 0x00, // 0x1D2 RESERVED + 0x00, // 0x1D3 RESERVED + 0x00, // 0x1D4 RESERVED + 0x00, // 0x1D5 RESERVED + 0x00, // 0x1D6 RESERVED + 0x00, // 0x1D7 RESERVED + 0x00, // 0x1D8 RESERVED + 0x00, // 0x1D9 RESERVED + 0x00, // 0x1DA RESERVED + 0x00, // 0x1DB RESERVED + 0x00, // 0x1DC RESERVED + 0x00, // 0x1DD RESERVED + 0x00, // 0x1DE RESERVED + 0x00, // 0x1DF RESERVED + 0x00, // 0x1E0 RESERVED + 0x00, // 0x1E1 RESERVED + 0x00, // 0x1E2 RESERVED + 0x00, // 0x1E3 RESERVED + 0x00, // 0x1E4 RESERVED + 0x00, // 0x1E5 RESERVED + 0x00, // 0x1E6 RESERVED + 0x00, // 0x1E7 RESERVED + 0x00, // 0x1E8 RESERVED + 0x00, // 0x1E9 RESERVED + 0x00, // 0x1EA RESERVED + 0x00, // 0x1EB RESERVED + 0x00, // 0x1EC RESERVED + 0x00, // 0x1ED RESERVED + 0x00, // 0x1EE RESERVED + 0x00, // 0x1EF RESERVED + 0x00, // 0x1F0 RESERVED + 0x00, // 0x1F1 RESERVED + 0x00, // 0x1F2 RESERVED + 0x00, // 0x1F3 RESERVED + 0x00, // 0x1F4 RESERVED + 0x00, // 0x1F5 RESERVED + 0x00, // 0x1F6 RESERVED + 0x00, // 0x1F7 RESERVED + 0x00, // 0x1F8 RESERVED + 0x00, // 0x1F9 RESERVED + 0x00, // 0x1FA RESERVED + 0x00, // 0x1FB RESERVED + 0x00, // 0x1FC RESERVED + 0x00, // 0x1FD RESERVED + 0x00, // 0x1FE RESERVED + 0x00, // 0x1FF RESERVED +]; diff --git a/boards/teensy40/src/io.rs b/boards/teensy40/src/io.rs new file mode 100644 index 0000000000..a734d1fa55 --- /dev/null +++ b/boards/teensy40/src/io.rs @@ -0,0 +1,60 @@ +use core::fmt::{self, Write}; + +use kernel::debug::{self, IoWrite}; +use kernel::hil::{ + led, + uart::{self, Configure}, +}; + +use crate::imxrt1060::gpio; +use crate::imxrt1060::lpuart; + +struct Writer { + output: &'static mut lpuart::Lpuart<'static>, +} + +const BAUD_RATE: u32 = 115_200; + +impl Writer { + pub unsafe fn new(output: &'static mut lpuart::Lpuart) -> Self { + output.configure(uart::Parameters { + baud_rate: BAUD_RATE, + stop_bits: uart::StopBits::One, + parity: uart::Parity::None, + hw_flow_control: false, + width: uart::Width::Eight, + }); + + Writer { output } + } +} + +impl IoWrite for Writer { + fn write(&mut self, bytes: &[u8]) { + for byte in bytes { + self.output.send_byte(*byte); + } + } +} + +impl Write for Writer { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.write(s.as_bytes()); + Ok(()) + } +} + +#[no_mangle] +#[panic_handler] +unsafe fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! { + let led = &mut led::LedHigh::new(gpio::PinId::B0_03.get_pin_mut().as_mut().unwrap()); + let mut writer = Writer::new(&mut lpuart::LPUART2); + debug::panic( + &mut [led], + &mut writer, + panic_info, + &cortexm7::support::nop, + &crate::PROCESSES, + &crate::CHIP, + ) +} diff --git a/boards/teensy40/src/main.rs b/boards/teensy40/src/main.rs new file mode 100644 index 0000000000..6627a99f8c --- /dev/null +++ b/boards/teensy40/src/main.rs @@ -0,0 +1,226 @@ +//! System configuration +//! +//! - LED on pin 13 +//! - UART2 allocated for a debug console on pins 14 and 15 +//! - GPT1 is the alarm source + +#![no_std] +#![no_main] +#![feature(const_in_array_repeat_expressions)] + +mod fcb; +mod io; + +use imxrt1060::iomuxc::{MuxMode, PadId, Sion, IOMUXC}; +use imxrt10xx as imxrt1060; +use kernel::capabilities; +use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState}; +use kernel::component::Component; +use kernel::hil::led::LedHigh; +use kernel::{create_capability, static_init}; + +/// Number of concurrent processes this platform supports +const NUM_PROCS: usize = 4; + +/// Actual process memory +static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] = + [None; NUM_PROCS]; + +/// What should we do if a process faults? +const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic; + +/// Teensy 4 platform +struct Teensy40 { + led: + &'static capsules::led::LedDriver<'static, LedHigh<'static, imxrt1060::gpio::Pin<'static>>>, + console: &'static capsules::console::Console<'static>, + ipc: kernel::ipc::IPC, + alarm: &'static capsules::alarm::AlarmDriver< + 'static, + capsules::virtual_alarm::VirtualMuxAlarm<'static, imxrt1060::gpt::Gpt1<'static>>, + >, +} + +impl kernel::Platform for Teensy40 { + fn with_driver(&self, driver_num: usize, f: F) -> R + where + F: FnOnce(Option<&dyn kernel::Driver>) -> R, + { + match driver_num { + capsules::led::DRIVER_NUM => f(Some(self.led)), + capsules::console::DRIVER_NUM => f(Some(self.console)), + kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), + capsules::alarm::DRIVER_NUM => f(Some(self.alarm)), + _ => f(None), + } + } +} + +type Chip = imxrt1060::chip::Imxrt10xx; +static mut CHIP: Option<&'static Chip> = None; + +#[no_mangle] +pub unsafe fn reset_handler() { + imxrt1060::init(); + imxrt1060::ccm::CCM.enable_iomuxc_clock(); + imxrt1060::ccm::CCM.enable_iomuxc_snvs_clock(); + + imxrt1060::ccm::CCM.set_perclk_sel(imxrt1060::ccm::PerclkClockSel::Oscillator); + imxrt1060::ccm::CCM.set_perclk_divider(8); + + imxrt1060::gpio::PinId::B0_03.get_pin().as_ref().map(|pin| { + use kernel::hil::gpio::Configure; + pin.make_output(); + }); + + // Pin 13 is an LED + IOMUXC.enable_sw_mux_ctl_pad_gpio(PadId::B0, MuxMode::ALT5, Sion::Disabled, 3); + + // Pins 14 and 15 are UART TX and RX + IOMUXC.enable_sw_mux_ctl_pad_gpio(PadId::AdB1, MuxMode::ALT2, Sion::Disabled, 2); + IOMUXC.enable_sw_mux_ctl_pad_gpio(PadId::AdB1, MuxMode::ALT2, Sion::Disabled, 3); + + IOMUXC.enable_lpuart2_tx_select_input(); + IOMUXC.enable_lpuart2_rx_select_input(); + + imxrt1060::lpuart::LPUART2.enable_clock(); + imxrt1060::lpuart::LPUART2.set_baud(); + + imxrt1060::gpt::GPT1.enable_clock(); + imxrt1060::gpt::GPT1.start( + imxrt1060::ccm::CCM.perclk_sel(), + imxrt1060::ccm::CCM.perclk_divider(), + ); + + cortexm7::nvic::Nvic::new(imxrt1060::nvic::GPT1).enable(); + cortexm7::nvic::Nvic::new(imxrt1060::nvic::LPUART2).enable(); + + let chip = static_init!(Chip, Chip::new()); + CHIP = Some(chip); + + // Start loading the kernel + let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES)); + // TODO how many of these should there be...? + let dynamic_deferred_call_clients = + static_init!([DynamicDeferredCallClientState; 2], Default::default()); + let dynamic_deferred_caller = static_init!( + DynamicDeferredCall, + DynamicDeferredCall::new(dynamic_deferred_call_clients) + ); + DynamicDeferredCall::set_global_instance(dynamic_deferred_caller); + + let uart_mux = components::console::UartMuxComponent::new( + &imxrt1060::lpuart::LPUART2, + 115_200, + dynamic_deferred_caller, + ) + .finalize(()); + // Create the debugger object that handles calls to `debug!()` + components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(()); + + // Setup the console + let console = components::console::ConsoleComponent::new(board_kernel, uart_mux).finalize(()); + + // LED + let led = components::led::LedsComponent::new(components::led_component_helper!( + LedHigh, + LedHigh::new(imxrt1060::gpio::PinId::B0_03.get_pin().as_ref().unwrap()) + )) + .finalize(components::led_component_buf!( + LedHigh<'static, imxrt1060::gpio::Pin> + )); + + // Alarm + let mux_alarm = components::alarm::AlarmMuxComponent::new(&imxrt1060::gpt::GPT1).finalize( + components::alarm_mux_component_helper!(imxrt1060::gpt::Gpt1), + ); + let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm) + .finalize(components::alarm_component_helper!(imxrt1060::gpt::Gpt1)); + + // + // Capabilities + // + let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability); + let main_loop_capability = create_capability!(capabilities::MainLoopCapability); + let process_management_capability = + create_capability!(capabilities::ProcessManagementCapability); + + let ipc = kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability); + + // + // Platform + // + let teensy40 = Teensy40 { + led, + console, + ipc, + alarm, + }; + + // + // Kernel startup + // + extern "C" { + /// Beginning of the ROM region containing app images. + /// + /// This symbol is defined in the linker script. + static _sapps: u8; + /// End of the ROM region containing app images. + /// + /// This symbol is defined in the linker script. + static _eapps: u8; + /// Beginning of the RAM region for app memory. + static mut _sappmem: u8; + /// End of the RAM region for app memory. + static _eappmem: u8; + } + + kernel::procs::load_processes( + board_kernel, + chip, + core::slice::from_raw_parts( + &_sapps as *const u8, + &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + ), + core::slice::from_raw_parts_mut( + &mut _sappmem as *mut u8, + &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + ), + &mut PROCESSES, + FAULT_RESPONSE, + &process_management_capability, + ) + .unwrap(); + + let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES) + .finalize(components::rr_component_helper!(NUM_PROCS)); + board_kernel.kernel_loop( + &teensy40, + chip, + Some(&teensy40.ipc), + scheduler, + &main_loop_capability, + ); +} + +/// Space for the stack buffer +/// +/// Justified in tock's `kernel_layout.ld`. +#[no_mangle] +#[link_section = ".stack_buffer"] +#[used] +static mut STACK_BUFFER: [u8; 0x1000] = [0; 0x1000]; + +const FCB_SIZE: usize = core::mem::size_of::(); + +/// Buffer between FCB and IVT +/// +/// The FCB is put at the start of flash. We then need to add a 4K buffer in between +/// the start of flash to the IVT. This buffer provides that padding. +/// +/// See justification for the `".stack_buffer"` section to understand why we need +/// explicit padding for the FCB. +#[no_mangle] +#[link_section = ".fcb_buffer"] +#[used] +static mut FCB_BUFFER: [u8; 0x1000 - FCB_SIZE] = [0xFF; 0x1000 - FCB_SIZE]; diff --git a/chips/imxrt1050/README.md b/chips/imxrt1050/README.md deleted file mode 100644 index 2ff251d2b7..0000000000 --- a/chips/imxrt1050/README.md +++ /dev/null @@ -1,10 +0,0 @@ -Imxrt1050 Series MCU -================ - - -## Links -### IMXRT 1050 EVKB - -* [General information](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/i-mx-rt-crossover-mcus/i-mx-rt1050-crossover-mcu-with-arm-cortex-m7-core:i.MX-RT1050) -* [Datasheet](https://www.nxp.com/docs/en/data-sheet/IMXRT1050CEC.pdf) -* [Reference Manual](https://www.nxp.com/webapp/Download?colCode=IMXRT1050RM) diff --git a/chips/imxrt1050/Cargo.toml b/chips/imxrt10xx/Cargo.toml similarity index 84% rename from chips/imxrt1050/Cargo.toml rename to chips/imxrt10xx/Cargo.toml index ff98bbf488..23a5ce7e76 100644 --- a/chips/imxrt1050/Cargo.toml +++ b/chips/imxrt10xx/Cargo.toml @@ -1,12 +1,11 @@ [package] -name = "imxrt1050" +name = "imxrt10xx" version = "0.1.0" authors = ["Tock Project Developers "] edition = "2018" [dependencies] cortexm7 = { path = "../../arch/cortex-m7" } -cortexm = { path = "../../arch/cortex-m" } enum_primitive = { path = "../../libraries/enum_primitive" } kernel = { path = "../../kernel" } tock-rt0 = { path = "../../libraries/tock-rt0" } diff --git a/chips/imxrt10xx/README.md b/chips/imxrt10xx/README.md new file mode 100644 index 0000000000..c164fab99f --- /dev/null +++ b/chips/imxrt10xx/README.md @@ -0,0 +1,19 @@ +i.MX RT 10xx Series MCU +======================= + +Tock supports the i.MX RT 1050 and 1060 MCU variants. These MCU variants are +so similar, they share a single `imxrt10xx` chip crate. + +## Links + +### IMXRT 1050 + +* [General information](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/i-mx-rt-crossover-mcus/i-mx-rt1050-crossover-mcu-with-arm-cortex-m7-core:i.MX-RT1050) +* [Datasheet](https://www.nxp.com/docs/en/data-sheet/IMXRT1050CEC.pdf) +* [Reference Manual](https://www.nxp.com/webapp/Download?colCode=IMXRT1050RM) (Requires a free NXP account) + +### IMXRT 1060 + +* [General information](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/i-mx-rt-crossover-mcus/i-mx-rt1060-crossover-mcu-with-arm-cortex-m7-core:i.MX-RT1060) +* [Datasheet](https://www.nxp.com/docs/en/nxp/data-sheets/IMXRT1060CEC.pdf) +* [Reference Manual](https://www.nxp.com/webapp/Download?colCode=IMXRT1060RM) (Requires a free NXP account) diff --git a/chips/imxrt1050/src/ccm.rs b/chips/imxrt10xx/src/ccm.rs similarity index 86% rename from chips/imxrt1050/src/ccm.rs rename to chips/imxrt10xx/src/ccm.rs index 636e2356f1..4e442f966c 100644 --- a/chips/imxrt1050/src/ccm.rs +++ b/chips/imxrt10xx/src/ccm.rs @@ -12,8 +12,16 @@ struct CcmRegisters { csr: ReadOnly, // CCM Clock Switcher Register ccsr: ReadWrite, - // unimplemented - _reserved2: [u8; 20], + // ARM clock root + cacrr: ReadWrite, + // Bus clock divider + cbcdr: ReadWrite, + // Bus clock multiplexer + cbcmr: ReadWrite, + // Serial clock multiplexer 1 + cscmr1: ReadWrite, + // Serial clock multiplexer 2 + cscmr2: ReadWrite, cscdr1: ReadWrite, _reserved3: [u8; 44], clpcr: ReadWrite, @@ -39,9 +47,9 @@ register_bitfields![u32, RBC_EN OFFSET(27) NUMBITS(1) [], /// Counter for analog_reg_bypass REG_BYPASS_COUNT OFFSET(21) NUMBITS(6) [], - /// On chip oscilator enable bit + /// On chip oscillator enable bit COSC_EN OFFSET(12) NUMBITS(1) [], - /// Oscilator ready counter value + /// Oscillator ready counter value OSCNT OFFSET(0) NUMBITS(8) [] ], @@ -58,6 +66,24 @@ register_bitfields![u32, PLL3_SW_CLK_SEL OFFSET(0) NUMBITS(1) [] ], + CSCMR1 [ + // Selector for the PERCLK clock multiplexer + PERCLK_CLK_SEL OFFSET(6) NUMBITS(1) [ + // Derive clock from IPG CLK root + IpgClockRoot = 0, + // Derive clock from OSCILLATOR + Oscillator = 1 + ], + // Divider for PERCLK PODF + // + // 0 = divide by 1 + // 1 = divide by 2 + // 2 = divide by 3 + // ... + // 63 = divide by 64 + PERCLK_PODF OFFSET(0) NUMBITS(6) [] + ], + CSCDR1 [ // Divider for trace clock TRACE_PODF OFFSET(25) NUMBITS(2) [], @@ -443,6 +469,19 @@ impl Ccm { self.registers.ccgr5.modify(CCGR5::CG12::CLEAR); } + // LPUART2 clock + pub fn is_enabled_lpuart2_clock(&self) -> bool { + self.registers.ccgr0.is_set(CCGR0::CG14) + } + + pub fn enable_lpuart2_clock(&self) { + self.registers.ccgr0.modify(CCGR0::CG14.val(0b11 as u32)); + } + + pub fn disable_lpuart2_clock(&self) { + self.registers.ccgr0.modify(CCGR0::CG14::CLEAR); + } + // UART clock multiplexor pub fn is_enabled_uart_clock_mux(&self) -> bool { self.registers.cscdr1.is_set(CSCDR1::UART_CLK_SEL) @@ -470,6 +509,46 @@ impl Ccm { pub fn disable_uart_clock_podf(&self) { self.registers.cscdr1.modify(CSCDR1::UART_CLK_PODF::CLEAR); } + + // + // PERCLK + // + + /// Returns the selection for the periodic clock + pub fn perclk_sel(&self) -> PerclkClockSel { + use CSCMR1::PERCLK_CLK_SEL::Value; + match self.registers.cscmr1.read_as_enum(CSCMR1::PERCLK_CLK_SEL) { + Some(Value::Oscillator) => PerclkClockSel::Oscillator, + Some(Value::IpgClockRoot) => PerclkClockSel::IPG, + _ => unreachable!("Implemented all periodic clock selections"), + } + } + + /// Set the periodic clock selection + pub fn set_perclk_sel(&self, sel: PerclkClockSel) { + let sel = match sel { + PerclkClockSel::IPG => CSCMR1::PERCLK_CLK_SEL::IpgClockRoot, + PerclkClockSel::Oscillator => CSCMR1::PERCLK_CLK_SEL::Oscillator, + }; + self.registers.cscmr1.modify(sel); + } + + /// Set the periodic clock selection and divider + /// + /// This should only be called when all associated clock gates are disabled. + /// + /// `divider` will be clamped between 1 and 64. + pub fn set_perclk_divider(&self, divider: u8) { + let divider: u32 = divider.min(64).max(1).into(); + self.registers + .cscmr1 + .modify(CSCMR1::PERCLK_PODF.val(divider - 1)); + } + + /// Returns the periodic clock divider, guaranteed to be non-zero + pub fn perclk_divider(&self) -> u8 { + (self.registers.cscmr1.read(CSCMR1::PERCLK_PODF) as u8) + 1 + } } pub enum PeripheralClock { @@ -483,6 +562,7 @@ pub enum PeripheralClock { pub enum HCLK0 { GPIO2, + LPUART2, } pub enum HCLK1 { @@ -511,11 +591,21 @@ pub enum HCLK5 { // and others ... } +/// Periodic clock selection for GPTs and PITs +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PerclkClockSel { + /// IPG clock selection (default) + IPG, + /// Crystal oscillator + Oscillator, +} + impl ClockInterface for PeripheralClock { fn is_enabled(&self) -> bool { match self { &PeripheralClock::CCGR0(ref v) => match v { HCLK0::GPIO2 => unsafe { CCM.is_enabled_gpio2_clock() }, + HCLK0::LPUART2 => unsafe { CCM.is_enabled_lpuart2_clock() }, }, &PeripheralClock::CCGR1(ref v) => match v { HCLK1::GPIO1 => unsafe { CCM.is_enabled_gpio1_clock() }, @@ -545,6 +635,9 @@ impl ClockInterface for PeripheralClock { HCLK0::GPIO2 => unsafe { CCM.enable_gpio2_clock(); }, + HCLK0::LPUART2 => unsafe { + CCM.enable_lpuart2_clock(); + }, }, &PeripheralClock::CCGR1(ref v) => match v { HCLK1::GPIO1 => unsafe { @@ -592,6 +685,9 @@ impl ClockInterface for PeripheralClock { HCLK0::GPIO2 => unsafe { CCM.disable_gpio2_clock(); }, + HCLK0::LPUART2 => unsafe { + CCM.disable_lpuart2_clock(); + }, }, &PeripheralClock::CCGR1(ref v) => match v { HCLK1::GPIO1 => unsafe { diff --git a/chips/imxrt1050/src/chip.rs b/chips/imxrt10xx/src/chip.rs similarity index 90% rename from chips/imxrt1050/src/chip.rs rename to chips/imxrt10xx/src/chip.rs index d05fb1caee..2890c278dc 100644 --- a/chips/imxrt1050/src/chip.rs +++ b/chips/imxrt10xx/src/chip.rs @@ -6,20 +6,20 @@ use kernel::debug; use kernel::Chip; use crate::gpio; -use crate::gpt1; +use crate::gpt; use crate::lpi2c; use crate::lpuart; use crate::nvic; -pub struct Imxrt1050 { +pub struct Imxrt10xx { mpu: cortexm7::mpu::MPU, userspace_kernel_boundary: cortexm7::syscall::SysCall, scheduler_timer: cortexm7::systick::SysTick, } -impl Imxrt1050 { - pub unsafe fn new() -> Imxrt1050 { - Imxrt1050 { +impl Imxrt10xx { + pub unsafe fn new() -> Imxrt10xx { + Imxrt10xx { mpu: cortexm7::mpu::MPU::new(), userspace_kernel_boundary: cortexm7::syscall::SysCall::new(), scheduler_timer: cortexm7::systick::SysTick::new_with_calibration(792_000_000), @@ -27,7 +27,7 @@ impl Imxrt1050 { } } -impl Chip for Imxrt1050 { +impl Chip for Imxrt10xx { type MPU = cortexm7::mpu::MPU; type UserspaceKernelBoundary = cortexm7::syscall::SysCall; type SchedulerTimer = cortexm7::systick::SysTick; @@ -39,8 +39,10 @@ impl Chip for Imxrt1050 { if let Some(interrupt) = cortexm7::nvic::next_pending() { match interrupt { nvic::LPUART1 => lpuart::LPUART1.handle_interrupt(), + nvic::LPUART2 => lpuart::LPUART2.handle_interrupt(), nvic::LPI2C1 => lpi2c::LPI2C1.handle_event(), - nvic::GPT1 => gpt1::GPT1.handle_interrupt(), + nvic::GPT1 => gpt::GPT1.handle_interrupt(), + nvic::GPT2 => gpt::GPT2.handle_interrupt(), nvic::GPIO1_1 => gpio::PORT[0].handle_interrupt(gpio::GpioPort::GPIO1), nvic::GPIO1_2 => gpio::PORT[0].handle_interrupt(gpio::GpioPort::GPIO1), nvic::GPIO2_1 => gpio::PORT[1].handle_interrupt(gpio::GpioPort::GPIO2), diff --git a/chips/imxrt1050/src/gpio.rs b/chips/imxrt10xx/src/gpio.rs similarity index 100% rename from chips/imxrt1050/src/gpio.rs rename to chips/imxrt10xx/src/gpio.rs diff --git a/chips/imxrt1050/src/gpt1.rs b/chips/imxrt10xx/src/gpt.rs similarity index 63% rename from chips/imxrt1050/src/gpt1.rs rename to chips/imxrt10xx/src/gpt.rs index e4cdb4c730..d60b724478 100644 --- a/chips/imxrt1050/src/gpt1.rs +++ b/chips/imxrt10xx/src/gpt.rs @@ -1,10 +1,11 @@ +use core::sync::atomic::{AtomicU32, Ordering}; use cortexm7; use cortexm7::support::atomic; use kernel::common::cells::OptionalCell; use kernel::common::registers::{register_bitfields, ReadOnly, ReadWrite}; use kernel::common::StaticRef; use kernel::hil; -use kernel::hil::time::{Freq2475MHz, Ticks, Ticks32, Time}; +use kernel::hil::time::{Ticks, Ticks32, Time}; use kernel::ClockInterface; use kernel::ReturnCode; @@ -13,7 +14,7 @@ use crate::nvic; /// General purpose timers #[repr(C)] -struct Gpt1Registers { +struct GptRegisters { /// GPT Control Register cr: ReadWrite, /// GPT Prescaler Register @@ -61,7 +62,20 @@ register_bitfields![u32, /// Free run or Restart mode FRR OFFSET(9) NUMBITS(1) [], /// Clock source select - CLKSRC OFFSET(6) NUMBITS(3) [], + CLKSRC OFFSET(6) NUMBITS(3) [ + /// No clock + NoClock = 0, + /// Peripheral Clock (ipg_clk) + PeripheralClock = 1, + /// High Frequency Reference Clock (ipg_clk_highfreq) + HighFrequencyReferenceClock = 2, + /// External Clock + ExternalClock = 3, + /// Low Frequency Reference Clock (ipg_clk_32k) + LowFrequencyReferenceClock = 4, + /// Crystal oscillator as Reference Clock (ipg_clk_24M) + CrystalOscillator = 5 + ], /// GPT Stop Mode enable STOPEN OFFSET(5) NUMBITS(1) [], /// GPT Doze Mode Enable @@ -138,25 +152,33 @@ register_bitfields![u32, ] ]; -const GPT1_BASE: StaticRef = - unsafe { StaticRef::new(0x401EC000 as *const Gpt1Registers) }; +const GPT1_BASE: StaticRef = + unsafe { StaticRef::new(0x401EC000 as *const GptRegisters) }; +const GPT2_BASE: StaticRef = + unsafe { StaticRef::new(0x401F0000 as *const GptRegisters) }; -pub struct Gpt1<'a> { - registers: StaticRef, +pub struct Gpt<'a, S> { + registers: StaticRef, clock: Gpt1Clock, client: OptionalCell<&'a dyn hil::time::AlarmClient>, irqn: u32, + _selection: core::marker::PhantomData, } -pub static mut GPT1: Gpt1<'static> = Gpt1::new(); +pub type Gpt1<'a> = Gpt<'static, _1>; +pub type Gpt2<'a> = Gpt<'static, _2>; -impl<'a> Gpt1<'a> { - const fn new() -> Gpt1<'a> { - Gpt1 { - registers: GPT1_BASE, +pub static mut GPT1: Gpt1<'static> = Gpt::new(GPT1_BASE, nvic::GPT1); +pub static mut GPT2: Gpt2<'static> = Gpt::new(GPT2_BASE, nvic::GPT2); + +impl<'a, S> Gpt<'a, S> { + const fn new(registers: StaticRef, irqn: u32) -> Self { + Gpt { + registers, clock: Gpt1Clock(ccm::PeripheralClock::CCGR1(ccm::HCLK1::GPT1)), client: OptionalCell::empty(), - irqn: nvic::GPT1, + irqn, + _selection: core::marker::PhantomData, } } @@ -179,7 +201,13 @@ impl<'a> Gpt1<'a> { self.client.map(|client| client.alarm()); } - pub fn start(&self) { + /// Start the GPT, specifying the peripheral clock selection and the peripheral clock divider + /// + /// If you select the crystal oscillator as the periodic clock root, the GPT will divide the + /// input clock by 3. + /// + /// `divider` must be non-zero. + pub fn start(&self, selection: ccm::PerclkClockSel, divider: u8) { // Disable GPT and the GPT interrupt register first self.registers.cr.modify(CR::EN::CLEAR); @@ -224,17 +252,42 @@ impl<'a> Gpt1<'a> { // Set the value of the Output Compare Register self.registers.ocr1.set(0xFFFF_FFFF - 1); - // Disable 24Mhz clock input from crystal - self.registers.cr.modify(CR::EN_24M::CLEAR); - - // We will use the ipg_clk_highfreq provided by perclk_clk_root, - // which runs at 24.75 MHz. Before calling set_alarm, we assume clock - // to GPT1 has been enabled. - self.registers.cr.modify(CR::CLKSRC.val(0x2 as u32)); - - // We do not prescale the value for the moment. We will do so - // after we will set the ARM_PLL1 CLK accordingly. - self.registers.pr.modify(PR::PRESCALER.val(0 as u32)); + match selection { + ccm::PerclkClockSel::IPG => { + // Disable 24Mhz clock input from crystal + self.registers.cr.modify(CR::EN_24M::CLEAR); + + // We will use the ipg_clk_highfreq provided by perclk_clk_root, + // which runs at 24.75 MHz. Before calling set_alarm, we assume clock + // to GPT1 has been enabled. + self.registers.cr.modify(CR::CLKSRC.val(0x2 as u32)); + + // We do not prescale the value for the moment. We will do so + // after we will set the ARM_PLL1 CLK accordingly. + self.registers.pr.modify(PR::PRESCALER.val(0 as u32)); + + self.set_frequency(IMXRT1050_IPG_CLOCK_HZ / divider as u32); + } + ccm::PerclkClockSel::Oscillator => { + // Enable 24MHz clock input + self.registers + .cr + .modify(CR::EN_24M::SET + CR::CLKSRC::CrystalOscillator); + + // Funknown reasons, the 24HMz prescaler must be non-zero, even + // though zero is a valid value according to the reference manual. + // If it's not set, the counter doesn't count! Thanks to the se4L + // project for adding a comment to their code. + // + // I'm also finding that it can't be too large; a prescaler of 8 + // for the 24MHz clock doesn't work! + const DEFAULT_PRESCALER: u32 = 3; + self.registers + .pr + .write(PR::PRESCALER24M.val(DEFAULT_PRESCALER - 1)); + self.set_frequency(OSCILLATOR_HZ / DEFAULT_PRESCALER / divider as u32); + } + } // Enable the GPT self.registers.cr.modify(CR::EN::SET); @@ -242,14 +295,45 @@ impl<'a> Gpt1<'a> { // Enable the Output Compare 1 Interrupt Enable self.registers.ir.modify(IR::OF1IE::SET); } + + fn set_frequency(&self, hz: u32) { + let idx = match self.irqn { + nvic::GPT1 => 0, + nvic::GPT2 => 1, + _ => unreachable!(), + }; + GPT_FREQUENCIES[idx].store(hz, Ordering::Release); + } +} + +/// Assumed IPG clock frequency for the iMXRT1050 processor family. +/// +/// TODO this is not a constant value; it changes when setting the ARM clock +/// frequency. Change this after correctly configuring ARM frequency. +const IMXRT1050_IPG_CLOCK_HZ: u32 = 24_750_000; +/// Crystal oscillator frequency +const OSCILLATOR_HZ: u32 = 24_000_000; + +/// GPT selection tags +pub enum _1 {} +pub enum _2 {} + +static GPT_FREQUENCIES: [AtomicU32; 2] = [AtomicU32::new(0), AtomicU32::new(0)]; + +impl hil::time::Frequency for _1 { + fn frequency() -> u32 { + GPT_FREQUENCIES[0].load(Ordering::Acquire) + } +} + +impl hil::time::Frequency for _2 { + fn frequency() -> u32 { + GPT_FREQUENCIES[1].load(Ordering::Acquire) + } } -/// The frequency is dependent on the ARM_PLL1 frequency. -/// In our case, we get a 24.75 MHz frequency for the timer. -/// The frequency will be fixed when the ARM_PLL1 CLK will -/// be correctly configured. -impl hil::time::Time for Gpt1<'_> { - type Frequency = Freq2475MHz; +impl hil::time::Time for Gpt<'_, F> { + type Frequency = F; type Ticks = Ticks32; fn now(&self) -> Ticks32 { @@ -257,7 +341,7 @@ impl hil::time::Time for Gpt1<'_> { } } -impl<'a> hil::time::Alarm<'a> for Gpt1<'a> { +impl<'a, F: hil::time::Frequency> hil::time::Alarm<'a> for Gpt<'a, F> { fn set_alarm_client(&self, client: &'a dyn hil::time::AlarmClient) { self.client.set(client); } diff --git a/chips/imxrt1050/src/iomuxc.rs b/chips/imxrt10xx/src/iomuxc.rs similarity index 95% rename from chips/imxrt1050/src/iomuxc.rs rename to chips/imxrt10xx/src/iomuxc.rs index d9984f7f52..acf9b0d388 100644 --- a/chips/imxrt1050/src/iomuxc.rs +++ b/chips/imxrt10xx/src/iomuxc.rs @@ -592,4 +592,40 @@ impl Iomuxc { .lpi2c1_sda_select_input .modify(DAISY_SELECT_INPUT::DAISY::CLEAR); } + + // LPUART2_RX_SELECT_INPUT + pub fn is_enabled_lpuart2_rx_select_input(&self) -> bool { + self.registers + .lpuart2_rx_select_input + .is_set(DAISY_SELECT_INPUT::DAISY) + } + pub fn enable_lpuart2_rx_select_input(&self) { + self.registers + .lpuart2_rx_select_input + .modify(DAISY_SELECT_INPUT::DAISY::SET); + } + + pub fn disable_lpuart2_rx_select_input(&self) { + self.registers + .lpuart2_rx_select_input + .modify(DAISY_SELECT_INPUT::DAISY::CLEAR); + } + + // LPUART2_TX_SELECT_INPUT + pub fn is_enabled_lpuart2_tx_select_input(&self) -> bool { + self.registers + .lpuart2_tx_select_input + .is_set(DAISY_SELECT_INPUT::DAISY) + } + pub fn enable_lpuart2_tx_select_input(&self) { + self.registers + .lpuart2_tx_select_input + .modify(DAISY_SELECT_INPUT::DAISY::SET); + } + + pub fn disable_lpuart2_tx_select_input(&self) { + self.registers + .lpuart2_tx_select_input + .modify(DAISY_SELECT_INPUT::DAISY::CLEAR); + } } diff --git a/chips/imxrt1050/src/iomuxc_snvs.rs b/chips/imxrt10xx/src/iomuxc_snvs.rs similarity index 100% rename from chips/imxrt1050/src/iomuxc_snvs.rs rename to chips/imxrt10xx/src/iomuxc_snvs.rs diff --git a/chips/imxrt1050/src/lib.rs b/chips/imxrt10xx/src/lib.rs similarity index 89% rename from chips/imxrt1050/src/lib.rs rename to chips/imxrt10xx/src/lib.rs index 40002ae050..3a6686b03b 100644 --- a/chips/imxrt1050/src/lib.rs +++ b/chips/imxrt10xx/src/lib.rs @@ -1,10 +1,10 @@ -//! Peripheral implementations for the IMXRT1050 MCU. +//! Peripheral implementations for the IMXRT1050 and IMXRT1060 MCUs. //! //! imxrt1050 chip: -#![crate_name = "imxrt1050"] +#![crate_name = "imxrt10xx"] #![crate_type = "rlib"] -#![feature(llvm_asm, const_fn)] +#![feature(const_fn)] #![no_std] pub mod chip; @@ -13,37 +13,15 @@ pub mod nvic; // Peripherals pub mod ccm; pub mod gpio; -pub mod gpt1; +pub mod gpt; pub mod iomuxc; pub mod iomuxc_snvs; pub mod lpi2c; pub mod lpuart; -use cortexm7::{generic_isr, hard_fault_handler, svc_handler, systick_handler}; -// use cortexm::scb::{set_vector_table_offset}; - -#[cfg(not(any(target_arch = "arm", target_os = "none")))] -unsafe extern "C" fn unhandled_interrupt() { - unimplemented!() -} - -#[cfg(all(target_arch = "arm", target_os = "none"))] -unsafe extern "C" fn unhandled_interrupt() { - let mut interrupt_number: u32; - - // IPSR[8:0] holds the currently active interrupt - llvm_asm!( - "mrs r0, ipsr " - : "={r0}"(interrupt_number) - : - : "r0" - : - ); - - interrupt_number = interrupt_number & 0x1ff; - - panic!("Unhandled Interrupt. ISR {} is active.", interrupt_number); -} +use cortexm7::{ + generic_isr, hard_fault_handler, svc_handler, systick_handler, unhandled_interrupt, +}; extern "C" { // _estack is not really a function, but it makes the types work @@ -261,7 +239,7 @@ pub unsafe fn init() { tock_rt0::init_data(&mut _etext, &mut _srelocate, &mut _erelocate); tock_rt0::zero_bss(&mut _szero, &mut _ezero); - cortexm::scb::set_vector_table_offset( + cortexm7::scb::set_vector_table_offset( &BASE_VECTORS as *const [unsafe extern "C" fn(); 16] as *const (), ); diff --git a/chips/imxrt1050/src/lpi2c.rs b/chips/imxrt10xx/src/lpi2c.rs similarity index 100% rename from chips/imxrt1050/src/lpi2c.rs rename to chips/imxrt10xx/src/lpi2c.rs diff --git a/chips/imxrt1050/src/lpuart.rs b/chips/imxrt10xx/src/lpuart.rs similarity index 98% rename from chips/imxrt1050/src/lpuart.rs rename to chips/imxrt10xx/src/lpuart.rs index 383a5915f9..a7338775b2 100644 --- a/chips/imxrt1050/src/lpuart.rs +++ b/chips/imxrt10xx/src/lpuart.rs @@ -297,6 +297,8 @@ register_bitfields![u32, const LPUART1_BASE: StaticRef = unsafe { StaticRef::new(0x40184000 as *const LpuartRegisters) }; +const LPUART2_BASE: StaticRef = + unsafe { StaticRef::new(0x4018_8000 as *const LpuartRegisters) }; #[derive(Copy, Clone, PartialEq)] enum LPUARTStateTX { @@ -335,6 +337,11 @@ pub static mut LPUART1: Lpuart = Lpuart::new( LpuartClock(ccm::PeripheralClock::CCGR5(ccm::HCLK5::LPUART1)), ); +pub static mut LPUART2: Lpuart = Lpuart::new( + LPUART2_BASE, + LpuartClock(ccm::PeripheralClock::CCGR0(ccm::HCLK0::LPUART2)), +); + impl<'a> Lpuart<'a> { const fn new(base_addr: StaticRef, clock: LpuartClock) -> Lpuart<'a> { Lpuart { diff --git a/chips/imxrt1050/src/nvic.rs b/chips/imxrt10xx/src/nvic.rs similarity index 98% rename from chips/imxrt1050/src/nvic.rs rename to chips/imxrt10xx/src/nvic.rs index f4ed327dc4..6b9323e3c5 100644 --- a/chips/imxrt1050/src/nvic.rs +++ b/chips/imxrt10xx/src/nvic.rs @@ -23,7 +23,7 @@ // pub const CM7: u32 = 18; // pub const CM7: u32 = 19; pub const LPUART1: u32 = 20; -// pub const LPUART2: u32 = 21; +pub const LPUART2: u32 = 21; // pub const LPUART3: u32 = 22; // pub const LPUART4: u32 = 23; // pub const LPUART5: u32 = 24; @@ -98,7 +98,7 @@ pub const GPIO5_2: u32 = 89; // pub const GPC: u32 = 97; // pub const SRC: u32 = 98; pub const GPT1: u32 = 100; -// pub const GPT2: u32 = 101; +pub const GPT2: u32 = 101; // pub const FLEXPWM1: u32 = 102; // pub const FLEXPWM1: u32 = 103; // pub const FLEXPWM1: u32 = 104; diff --git a/kernel/src/hil/time.rs b/kernel/src/hil/time.rs index aefe956361..f5bfc9b432 100644 --- a/kernel/src/hil/time.rs +++ b/kernel/src/hil/time.rs @@ -282,15 +282,6 @@ impl Frequency for Freq16MHz { } } -/// 24.75MHz `Frequency` -#[derive(Debug)] -pub struct Freq2475MHz; -impl Frequency for Freq2475MHz { - fn frequency() -> u32 { - 24750000 - } -} - /// 1MHz `Frequency` #[derive(Debug)] pub struct Freq1MHz;