From ceca9d4a4befe43c67231808b3d2df9b5ad0b5b6 Mon Sep 17 00:00:00 2001 From: Elman Steve Laguna <32938596+salsasteve@users.noreply.github.com> Date: Tue, 9 Jan 2024 06:57:13 -0600 Subject: [PATCH] Add adafruit matrix portal m4 (#713) * Adding Matrix Portal M4 with blinky example * Fixing tier * Fixing rust formatting * Fixing toml, README and crates.json * Adding cortex-m feature * Adding to top level README --- README.md | 3 +- boards/matrix_portal_m4/.cargo/config | 15 + boards/matrix_portal_m4/CHANGELOG.md | 12 + boards/matrix_portal_m4/Cargo.toml | 45 ++ boards/matrix_portal_m4/README.md | 26 + boards/matrix_portal_m4/build.rs | 16 + .../matrix_portal_m4/examples/blinky_basic.rs | 36 ++ boards/matrix_portal_m4/memory.x | 8 + boards/matrix_portal_m4/src/lib.rs | 11 + boards/matrix_portal_m4/src/pins.rs | 479 ++++++++++++++++++ crates.json | 5 + 11 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 boards/matrix_portal_m4/.cargo/config create mode 100644 boards/matrix_portal_m4/CHANGELOG.md create mode 100644 boards/matrix_portal_m4/Cargo.toml create mode 100644 boards/matrix_portal_m4/README.md create mode 100644 boards/matrix_portal_m4/build.rs create mode 100644 boards/matrix_portal_m4/examples/blinky_basic.rs create mode 100644 boards/matrix_portal_m4/memory.x create mode 100644 boards/matrix_portal_m4/src/lib.rs create mode 100644 boards/matrix_portal_m4/src/pins.rs diff --git a/README.md b/README.md index 31b1a0897f4f..db0ed7c57f9e 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The Peripheral Access Crates (PACs) are automatically generated from Microchip S | [atsamd21g](https://docs.rs/atsamd21g/) | [![Crates.io](https://img.shields.io/crates/v/atsamd21g.svg)](https://crates.io/crates/atsamd21g) | [Arduino Nano 33 IOT][arduino_nano33_iot], [Circuit Playground Express][circuit_playground_express], [Feather M0][feather_m0]\*, [ItsyBitsy M0][itsybitsy_m0], [Metro M0][metro_m0]\*, [MKR1000][arduino_mkr1000], [MKR Vidor 4000][arduino_mkr_vidor_4000], [MKR ZERO][arduino_mkrzero], [P1AM-100][p1am_100], [SAMD21 Mini][samd21_mini], [SODAQ ONE][sodaq_one], [Wio Lite MG126][wio_lite_mg126], [Wio Lite W600][wio_lite_w600], [Xiao M0][xiao_m0] | | [atsamd21j](https://docs.rs/atsamd21j/) | [![Crates.io](https://img.shields.io/crates/v/atsamd21j.svg)](https://crates.io/crates/atsamd21j) | [SODAQ SARA AFF][sodaq_sara_aff] | | [atsamd51g](https://docs.rs/atsamd51g/) | [![Crates.io](https://img.shields.io/crates/v/atsamd51g.svg)](https://crates.io/crates/atsamd51g) | [ItsyBitsy M4][itsybitsy_m4], [Trellis M4][trellis_m4] | -| [atsamd51j](https://docs.rs/atsamd51j/) | [![Crates.io](https://img.shields.io/crates/v/atsamd51j.svg)](https://crates.io/crates/atsamd51j) | [EdgeBadge][edgebadge], [Feather M4][feather_m4]\*, [Metro M4][metro_m4]\*, [PyPortal][pyportal] | +| [atsamd51j](https://docs.rs/atsamd51j/) | [![Crates.io](https://img.shields.io/crates/v/atsamd51j.svg)](https://crates.io/crates/atsamd51j) | [EdgeBadge][edgebadge], [Feather M4][feather_m4]\*, [Metro M4][metro_m4]\*, [PyPortal][pyportal], [Matrix Portal M4][matrix_portal_m4] | | [atsame51n](https://docs.rs/atsame51n/) | [![Crates.io](https://img.shields.io/crates/v/atsame51n.svg)](https://crates.io/crates/atsame51n) | | | [atsamd51p](https://docs.rs/atsamd51p/) | [![Crates.io](https://img.shields.io/crates/v/atsamd51p.svg)](https://crates.io/crates/atsamd51p) | [Grand Central M4 Express][grand_central_m4], [Wio Terminal][wio_terminal] | | [atsame51g](https://docs.rs/atsame51g/) | [![Crates.io](https://img.shields.io/crates/v/atsame51g.svg)](https://crates.io/crates/atsame51g) | | @@ -69,6 +69,7 @@ The Peripheral Access Crates (PACs) are automatically generated from Microchip S [grand_central_m4]: https://github.com/atsamd-rs/atsamd/tree/master/boards/grand_central_m4/ [itsybitsy_m0]: https://github.com/atsamd-rs/atsamd/tree/master/boards/itsybitsy_m0/ [itsybitsy_m4]: https://github.com/atsamd-rs/atsamd/tree/master/boards/itsybitsy_m4/ +[matrix_portal_m4]: https://github.com/atsamd-rs/atsamd/tree/master/boards/matrix_portal_m4/ [metro_m0]: https://github.com/atsamd-rs/atsamd/tree/master/boards/metro_m0/ [metro_m4]: https://github.com/atsamd-rs/atsamd/tree/master/boards/metro_m4/ [neo_trinkey]: https://github.com/atsamd-rs/atsamd/tree/master/boards/neo_trinkey diff --git a/boards/matrix_portal_m4/.cargo/config b/boards/matrix_portal_m4/.cargo/config new file mode 100644 index 000000000000..f0975800a654 --- /dev/null +++ b/boards/matrix_portal_m4/.cargo/config @@ -0,0 +1,15 @@ +# vim:ft=toml: +[target.thumbv7em-none-eabihf] +#runner = 'arm-none-eabi-gdb' +runner = 'probe-run --chip ATSAMD51J19A' + +[build] +target = "thumbv7em-none-eabihf" +rustflags = [ + + # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x + # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 + "-C", "link-arg=--nmagic", + + "-C", "link-arg=-Tlink.x", +] diff --git a/boards/matrix_portal_m4/CHANGELOG.md b/boards/matrix_portal_m4/CHANGELOG.md new file mode 100644 index 000000000000..7a6c21934a04 --- /dev/null +++ b/boards/matrix_portal_m4/CHANGELOG.md @@ -0,0 +1,12 @@ +# Unreleased + +- + +# v0.1.0 + +- Added blinky_basic.rs example +- Added pin mapping to pin.rs + +--- + +Changelog tracking started at v0.1.0 diff --git a/boards/matrix_portal_m4/Cargo.toml b/boards/matrix_portal_m4/Cargo.toml new file mode 100644 index 000000000000..27731af88e3f --- /dev/null +++ b/boards/matrix_portal_m4/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "matrix_portal_m4" +version = "0.1.0" +authors = ["Salsa Steve "] +description = "Board Support crate for the Matrix Portal M4" +keywords = ["no-std", "arm", "cortex-m", "embedded-hal"] +categories = ["embedded", "hardware-support", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/atsamd-rs/atsamd" +readme = "README.md" +edition = "2021" + +# for cargo flash +[package.metadata] +chip = "ATSAMD51J19A" + +[dependencies.cortex-m-rt] +version = "0.7" +optional = true + +[dependencies.atsamd-hal] +version = "0.16.0" +default-features = false + +[dependencies.usb-device] +version = "0.3.1" +optional = true + +[dependencies.cortex-m] +version = "0.7" +features = ["critical-section-single-core"] + +[dev-dependencies] +panic-halt = "0.2" + +[features] +# ask the HAL to enable atsamd51j support +default = ["rt", "atsamd-hal/samd51j", "atsamd-hal/samd51"] +rt = ["cortex-m-rt", "atsamd-hal/samd51j-rt"] +unproven = ["atsamd-hal/unproven"] +usb = ["atsamd-hal/usb", "usb-device"] + + +[[example]] +name = "blinky_basic" diff --git a/boards/matrix_portal_m4/README.md b/boards/matrix_portal_m4/README.md new file mode 100644 index 000000000000..d3713264a54a --- /dev/null +++ b/boards/matrix_portal_m4/README.md @@ -0,0 +1,26 @@ +# Adafruit Matrix Portal M4 Board Support Crate + +This crate provides a type-safe API for working with the [Adafruit Matrix Portal M4 +board](https://www.adafruit.com/product/4745). + +## Prerequisites +* Install the cross compile toolchain `rustup target add thumbv7em-none-eabihf` +* Install [cargo-hf2 the hf2 bootloader flasher tool](https://crates.io/crates/cargo-hf2) however your platform requires + +## Uploading an example +Check out the repository for examples: + +https://github.com/atsamd-rs/atsamd/tree/master/boards/matrix_portal_m4/examples + +* Be in this directory `cd boards/matrix_portal_m4` +* Put your device in bootloader mode usually by hitting the reset button twice. +* Build and upload in one step +``` + +$ cargo hf2 --release --example blinky_basic --vid 0x239a --pid 0x00c9 + Finished release [optimized] target(s) in 0.74s + Trying Ok(Some("Adafruit Industries")) Ok(Some("Matrix Portal M4")) + Flashing "/Users/User/atsamd/boards/matrix_portal_m4/target/thumbv7em-none-eabihf/release/examples/blinky_basic" + Finished in 0.051s +$ +``` \ No newline at end of file diff --git a/boards/matrix_portal_m4/build.rs b/boards/matrix_portal_m4/build.rs new file mode 100644 index 000000000000..4bed4688f2c0 --- /dev/null +++ b/boards/matrix_portal_m4/build.rs @@ -0,0 +1,16 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; +fn main() { + if env::var_os("CARGO_FEATURE_RT").is_some() { + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + println!("cargo:rerun-if-changed=memory.x"); + } + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/boards/matrix_portal_m4/examples/blinky_basic.rs b/boards/matrix_portal_m4/examples/blinky_basic.rs new file mode 100644 index 000000000000..098c26fd6bad --- /dev/null +++ b/boards/matrix_portal_m4/examples/blinky_basic.rs @@ -0,0 +1,36 @@ +#![no_std] +#![no_main] + +use matrix_portal_m4::{entry, hal, pac, Pins}; +#[cfg(not(feature = "panic_led"))] +use panic_halt as _; + +use hal::clock::GenericClockController; +use hal::delay::Delay; +use hal::prelude::*; +use pac::{CorePeripherals, Peripherals}; + +#[entry] +fn main() -> ! { + let mut peripherals = Peripherals::take().unwrap(); + let core = CorePeripherals::take().unwrap(); + let mut clocks = GenericClockController::with_internal_32kosc( + peripherals.GCLK, + &mut peripherals.MCLK, + &mut peripherals.OSC32KCTRL, + &mut peripherals.OSCCTRL, + &mut peripherals.NVMCTRL, + ); + let mut delay = Delay::new(core.SYST, &mut clocks); + delay.delay_ms(400u16); + + let pins = Pins::new(peripherals.PORT); + let mut red_led = pins.led.into_push_pull_output(); + + loop { + delay.delay_ms(200u8); + red_led.set_high().unwrap(); + delay.delay_ms(200u8); + red_led.set_low().unwrap(); + } +} diff --git a/boards/matrix_portal_m4/memory.x b/boards/matrix_portal_m4/memory.x new file mode 100644 index 000000000000..e473c115bc53 --- /dev/null +++ b/boards/matrix_portal_m4/memory.x @@ -0,0 +1,8 @@ +MEMORY +{ + /* Leave 16k for the default bootloader on the Matrix Portal M4 */ + FLASH (rx) : ORIGIN = 0x00000000 + 16K, LENGTH = 512K - 16K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K +} +_stack_start = ORIGIN(RAM) + LENGTH(RAM); + diff --git a/boards/matrix_portal_m4/src/lib.rs b/boards/matrix_portal_m4/src/lib.rs new file mode 100644 index 000000000000..fde796c50453 --- /dev/null +++ b/boards/matrix_portal_m4/src/lib.rs @@ -0,0 +1,11 @@ +#![no_std] + +pub use atsamd_hal as hal; +pub use hal::ehal; +pub use hal::pac; + +pub mod pins; +pub use pins::*; + +#[cfg(feature = "rt")] +pub use cortex_m_rt::entry; diff --git a/boards/matrix_portal_m4/src/pins.rs b/boards/matrix_portal_m4/src/pins.rs new file mode 100644 index 000000000000..5455b4e3bd83 --- /dev/null +++ b/boards/matrix_portal_m4/src/pins.rs @@ -0,0 +1,479 @@ +// //! matrix_portal_m4 pins + +// reference URL https://github.com/tinygo-org/tinygo/blob/release/src/machine/board_matrixportal-m4.go +use super::hal; + +hal::bsp_pins!( + PA02 { + // STEMMA connectors + // ADC (A0) + name: a0, + aliases: { + Reset: A0Reset, + } + } + PA27 { + /// Accelerometer Interrupt + /// LIS3DH IRQ + name: accelerometer_interrupt, + aliases: { + Reset: AccelerometerInterruptReset, + } + } + PA07 { + // ADC (A4) + name: a4, + aliases: { + Reset: A4Reset, + } + } + PA04 { + // ADC (A2) + // SPI SDO + name: a2, + aliases: { + AlternateC: Sdo, + Reset: A2Reset, + } + } + PA05 { + // ADC (A1) + // SPI SCK + name: a1, + aliases: { + AlternateC: Sck, + Reset: A1Reset, + } + } + PB23 { + // Button "Down" + name: button_down, + aliases: { + PushPullOutput: Button, + Reset: ButtonDownReset, + } + } + PB22 { + // Button "Up" + name: button_up, + aliases: { + PushPullOutput: ButtonUp, + Reset: ButtonUpReset, + } + } + + PA00 { + // UART TX + name: uart_tx, + aliases: { + AlternateC: UartTx, + Reset: UartTxReset, + } + } + PB04 { + // MTX G2 + // HUB75 G2 + name: mtx_g2, + aliases: { + Reset: MtxG2Reset, + } + } + PB05 { + // MTX B2 + // HUB75 B2 + name: mtx_b2, + aliases: { + Reset: MtxB2Reset, + } + } + PB06 { + // MTX CLK + // HUB75 CLK + name: mtx_clk, + aliases: { + Reset: MtxClkReset, + } + } + PB07 { + // MTX ADDRA + // HUB75 ADDR A + name: mtx_addra, + aliases: { + Reset: MtxAddraReset, + } + } + PB09 { + // MTX ADDRC + // HUB75 ADDR C + name: mtx_addrc, + aliases: { + Reset: MtxAddrcReset, + } + } + PB31 { + // Accelerometer I2C SDA + // I2C SDA + name: sda, + aliases: { + AlternateD: Sda, + Reset: SdaReset, + } + } + PA16 { + // SCK + // ESP32 SPI SCK + name: esp_sck, + aliases: { + PushPullOutput: EspSck, + Reset: EspSckReset, + } + } + PA17 { + // MIS0 + // ESP32 SPI SDI + name: miso, + aliases: { + PushPullOutput: Miso, + Reset: MisoReset, + } + } + PA18 { + // ESP RTS + // ESP32 RTS + name: esp_rts, + aliases: { + Reset: EspRtsReset, + } + } + PA19 { + // MOSI + // ESP32 SPI SDO + name: mosi, + aliases: { + PushPullOutput: Mosi, + Reset: MosiReset, + } + } + PA20 { + // ESP GPIO0 + // ESP32 GPIO0 + name: esp_gpio0, + aliases: { + Reset: EspGpio0Reset + } + } + PA21 { + // ESP RESET + // ESP32 Reset + name: esp_reset, + aliases: { + Reset: EspResetReset, + } + } + PA22 { + // ESP BUSY + // ESP32 Busy + name: esp_busy, + aliases: { + Reset: EspBusyReset, + } + } + PA23 { + /// Neopixel status LED + name: neopixel, + aliases: { + Reset: NeopixelReset, + PushPullOutput: Neopixel, + } + } + + PB00 { + // MTX R1 + // HUB75 R1 + name: mtx_r1, + aliases: { + AlternateB: MtxR1, + Reset: MtxR1Reset, + } + } + PB01 { + // MTX G1 + // HUB75 G1 + name: mtx_g1, + aliases: { + AlternateB: MtxG1, + Reset: MtxG1Reset, + } + } + PA06 { + // ADC (A3) + name: a3, + aliases: { + AlternateB: A3, + Reset: A3Reset, + } + } + PB08 { + // MTX ADDRB + // HUB75 ADDR B + name: mtx_addrb, + aliases: { + AlternateB: MtxAddrb, + Reset: MtxAddrbReset, + } + } + + PB14 { + // MTX LAT + // HUB75 LAT + name: mtx_lat, + aliases: { + AlternateB: MtxLat, + Reset: MtxLatReset, + } + } + PB15 { + // MTX ADDRD + // HUB75 ADDR D + name: mtx_addrd, + aliases: { + Reset: MtxAddrdReset, + } + } + PB17 { + // ESP CS + // ESP32 SPI CS + name: esp_cs, + aliases: { + Reset: EspCsReset, + } + } + + PB12 { + // MTX OE + // HUB75 OE + name: mtx_oe, + aliases: { + AlternateC: MtxOe, + Reset: MtxOeReset, + } + } + PB13 { + // MTX ADDRE + // HUB75 ADDR E + name: mtx_addre, + aliases: { + AlternateC: MtxAddre, + Reset: MtxAddreReset, + } + } + + PA12 { + // ESP RX + // ESP32 UART RX + name: esp_rx, + aliases: { + AlternateC: EspUartRx, + Reset: EspUartRxReset, + } + } + PA13 { + // ESP TX + // ESP32 UART TX + name: esp_tx, + aliases: { + AlternateC: EspUartTx, + Reset: EspUartTxReset, + } + } + PA14 { + // D13 LED + name: led, + aliases: { + PushPullOutput: RedLed, + Reset: RedLedReset, + } + } + + PB02 { + // MTX B1 + // HUB75 B1 + name: mtx_b1, + aliases: { + AlternateD: MtxB1, + Reset: MtxB1Reset, + } + } + PB03 { + // MTX R2 + // HUB75 R2 + name: mtx_r2, + aliases: { + AlternateD: MtxR2, + Reset: MtxR2Reset, + } + } + + PB30 { + // Accelerometer I2C SCL + // I2C SCL + name: scl, + aliases: { + AlternateD: Scl, + Reset: SclReset, + } + } + PA01 { + // RX + // UART RX + name: uart_rx, + aliases: { + AlternateC: UartRx, + Reset: UartRxReset, + } + } + + PA24 { + /// The USB D- pad + name: usb_dm + aliases: { + AlternateH: UsbDm, + Reset: UsbDmReset, + } + } + PA25 { + /// The USB D+ pad + name: usb_dp + aliases: { + AlternateH: UsbDp, + Reset: UsbDpReset, + } + } +); + +impl Pins { + /// Split the device pins into subsets + pub fn split(self) -> Sets { + let stemma = Stemma { a0: self.a0 }; + + let mtx = Matrix { + r1: self.mtx_r1, + g1: self.mtx_g1, + b1: self.mtx_b1, + r2: self.mtx_r2, + g2: self.mtx_g2, + b2: self.mtx_b2, + clk: self.mtx_clk, + lat: self.mtx_lat, + oe: self.mtx_oe, + addra: self.mtx_addra, + addrb: self.mtx_addrb, + addrc: self.mtx_addrc, + addrd: self.mtx_addrd, + addre: self.mtx_addre, + }; + + let esp = Esp { + cs: self.esp_cs, + gpio0: self.esp_gpio0, + busy: self.esp_busy, + reset: self.esp_reset, + rts: self.esp_rts, + }; + + let esp_uart = EspUart { + tx: self.esp_tx, + rx: self.esp_rx, + }; + + let spi = Spi { + mosi: self.mosi, + sck: self.esp_sck, + miso: self.miso, + }; + + let i2c = I2C { + sda: self.sda, + scl: self.scl, + }; + + let usb = Usb { + usb_dm: self.usb_dm, + usb_dp: self.usb_dp, + }; + + Sets { + led: self.led, + neopixel: self.neopixel, + esp, + i2c, + spi, + stemma, + esp_uart, + usb, + mtx, + } + } +} + +pub struct Sets { + pub led: RedLedReset, + pub neopixel: NeopixelReset, + pub esp: Esp, + pub i2c: I2C, + pub spi: Spi, + pub stemma: Stemma, + pub esp_uart: EspUart, + pub usb: Usb, + pub mtx: Matrix, +} + +pub struct Esp { + pub cs: EspCsReset, + pub gpio0: EspGpio0Reset, + pub busy: EspBusyReset, + pub reset: EspResetReset, + pub rts: EspRtsReset, +} + +pub struct I2C { + pub sda: SdaReset, + pub scl: SclReset, +} + +pub struct Spi { + pub mosi: MosiReset, + pub sck: EspSckReset, + pub miso: MisoReset, +} + +pub struct Stemma { + pub a0: A0Reset, +} + +pub struct EspUart { + pub tx: EspUartTxReset, + pub rx: EspUartRxReset, +} + +pub struct Usb { + pub usb_dm: UsbDmReset, + pub usb_dp: UsbDpReset, +} + +pub struct Matrix { + pub r1: MtxR1Reset, + pub g1: MtxG1Reset, + pub b1: MtxB1Reset, + pub r2: MtxR2Reset, + pub g2: MtxG2Reset, + pub b2: MtxB2Reset, + pub clk: MtxClkReset, + pub lat: MtxLatReset, + pub oe: MtxOeReset, + pub addra: MtxAddraReset, + pub addrb: MtxAddrbReset, + pub addrc: MtxAddrcReset, + pub addrd: MtxAddrdReset, + pub addre: MtxAddreReset, +} diff --git a/crates.json b/crates.json index dbca408a0478..cae374805a1d 100644 --- a/crates.json +++ b/crates.json @@ -65,6 +65,11 @@ "build": "cargo build --examples --all-features", "target": "thumbv7em-none-eabihf" }, + "matrix_portal_m4": { + "tier": 2, + "build": "cargo build --examples --all-features", + "target": "thumbv7em-none-eabihf" + }, "metro_m0": { "tier": 1, "build": "cargo build --examples --all-features",