Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1a1a432
Overhaul QSPI module
rnd-ash Jul 16, 2025
3d48888
QSPI - Enable user selection of scramble mode
rnd-ash Jul 16, 2025
bd8f324
Add APB clock to QSPI
rnd-ash Jul 17, 2025
d7702e2
Fix examples and remove QSPI builder in the BSPs
rnd-ash Jul 18, 2025
4de6791
Simplify gclk types
rnd-ash Jul 18, 2025
d579b21
Fix rstfmt
rnd-ash Jul 18, 2025
d6ede4a
Fix doc comment indent
rnd-ash Jul 18, 2025
5c164d1
Remove underscore in QSPI member names
rnd-ash Jul 21, 2025
e881437
samd11/21/51: fix off-by-one Pwm period (#949)
codepainters Nov 13, 2025
39b58a8
changed!: Gate undocumented chip features behind the `undoc-features`…
jbeaurivage Nov 16, 2025
feab341
chore: Remove deprecated warning in aes module (#957)
jbeaurivage Nov 17, 2025
90b9396
feat: Add PB02 and PB03 as undocumented I2C pads for SAMD21 (#958)
wt Nov 18, 2025
a06a4b9
docs: Document newly undoc I2C-capable pins (PB02,PB03) (#960)
jbeaurivage Nov 19, 2025
025e76a
chore: release (#947)
github-actions[bot] Nov 20, 2025
20b17d2
deps(circuit-playground-express): Update dependencies and HAL to 0.23…
wt Nov 20, 2025
48102c1
chore(circuit_playground_express): release v0.12.0 (#961)
github-actions[bot] Nov 20, 2025
c90558c
Overhaul QSPI module
rnd-ash Jul 16, 2025
e165b76
QSPI - Enable user selection of scramble mode
rnd-ash Jul 16, 2025
f7a043d
Add APB clock to QSPI
rnd-ash Jul 17, 2025
1f27473
Fix examples and remove QSPI builder in the BSPs
rnd-ash Jul 18, 2025
76cf1e6
Simplify gclk types
rnd-ash Jul 18, 2025
9df4c2a
Fix rstfmt
rnd-ash Jul 18, 2025
6d348c9
Fix doc comment indent
rnd-ash Jul 18, 2025
622b782
Remove underscore in QSPI member names
rnd-ash Jul 21, 2025
af5fb4f
Merge remote-tracking branch 'refs/remotes/origin/qspi-clockv2' into …
rnd-ash Nov 25, 2025
cecee8b
Correctly specify EnabledGclk0
rnd-ash Nov 25, 2025
e6bca6e
QSPI - Ensure QSPI freq cannot be more than 1/2 of CPU freq
rnd-ash Nov 25, 2025
9495aad
FIx compile warnings of pygamer QSPI example
rnd-ash Nov 25, 2025
8a5f734
QSPI remove unused imports
rnd-ash Nov 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ This repository holds various crates that support/enable working with Microchip

The Hardware Abstraction Layer (HAL - [![Crates.io](https://img.shields.io/crates/v/atsamd_hal.svg)](https://crates.io/crates/atsamd_hal)) crate encodes a type-safe layer over the raw PACs. This crate implements traits specified by the [embedded-hal](https://github.com/rust-embedded/embedded-hal) project, making it compatible with various drivers in the embedded Rust ecosystem. Cargo features are used to enable support for specific hardware variations and features. Online documentation for commonly-used feature sets is provided:

| Chip family | Documented features |
|:------------|:----------------------------------|
| [samd11c] | samd11c dma defmt async |
| [samd11d] | samd11d dma defmt async |
| [samd21g] | samd21g usb dma defmt async |
| [samd21j] | samd21j usb dma defmt async |
| [samd51g] | samd51g usb sdmmc dma defmt async |
| [samd51j] | samd51j usb sdmmc dma defmt async |
| [samd51n] | samd51n usb sdmmc dma defmt async |
| [samd51p] | samd51p usb sdmmc dma defmt async |
| Chip family | Documented features |
|:------------|:-------------------------------------------------|
| [samd11c] | samd11c dma defmt async undoc-features |
| [samd11d] | samd11d dma defmt async undoc-features |
| [samd21g] | samd21g usb dma defmt async undoc-features |
| [samd21j] | samd21j usb dma defmt async undoc-features |
| [samd51g] | samd51g usb sdmmc dma defmt async undoc-features |
| [samd51j] | samd51j usb sdmmc dma defmt async undoc-features |
| [samd51n] | samd51n usb sdmmc dma defmt async undoc-features |
| [samd51p] | samd51p usb sdmmc dma defmt async undoc-features |

[samd11c]: https://atsamd-rs.github.io/atsamd/samd11c/thumbv6m-none-eabi/doc/atsamd_hal/index.html
[samd11d]: https://atsamd-rs.github.io/atsamd/samd11d/thumbv6m-none-eabi/doc/atsamd_hal/index.html
Expand Down Expand Up @@ -153,6 +153,38 @@ If you'd like to build all the same things that the CI would build but on your l
$ ./build-all.py
```

## Undocumented chip features

Some development board manufacturers, such as Adafruit, sell some boards with pin multiplexing configurations that aren't
explicitly allowed by the datasheet. As a convenience, we offer the option to enable these undocumented features by opting
into the `undoc-features` Cargo feature. Note that even though these have shown to work in at least some situations, we do not
provide any guarantees with respect to those.

Currently, we provide these features undocumented features:

### SAMD21:

* Mark `PA00` as I2C-capable according to `circuit_playground_express`.

* Mark `PA01` as I2C-capable according to `circuit_playground_express`.

* Mark `PB02` as I2C-capable according to `circuit_playground_express`.

* Mark `PB03` as I2C-capable according to `circuit_playground_express`.

### SAMx5x devices:
* `UndocIoSet1`: Implement an undocumented `IoSet` for PA16, PA17, PB22 &
PB23 configured for `Sercom1`. The `pygamer` & `feather_m4` use this
combination, but it is not listed as valid in the datasheet.

* `UndocIoSet2`: Implement an undocumented `IoSet` for PA00, PA01, PB22 &
PB23 configured for `Sercom1`. The `itsybitsy_m4` uses this combination,
but it is not listed as valid in the datasheet.

* Mark `PB02` as I2C-capable according to `metro_m4`.

* Mark `PB03` as I2C-capable according to `metro_m4`.

## Running and debugging firmware on target hardware

See our wiki page about [loading code onto the device](https://github.com/atsamd-rs/atsamd/wiki/Loading-code-onto-the-device).
Expand Down
6 changes: 6 additions & 0 deletions boards/atsame54_xpro/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.13.0](https://github.com/atsamd-rs/atsamd/compare/atsame54_xpro-0.12.2...atsame54_xpro-0.13.0) - 2025-11-19

### Other

- updated the following local packages: atsamd-hal

## [0.12.2](https://github.com/atsamd-rs/atsamd/compare/atsame54_xpro-0.12.1...atsame54_xpro-0.12.2) - 2025-06-26

### Other
Expand Down
4 changes: 2 additions & 2 deletions boards/atsame54_xpro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license = "MIT OR Apache-2.0"
name = "atsame54_xpro"
readme = "README.md"
repository = "https://github.com/atsamd-rs/atsamd"
version = "0.12.2"
version = "0.13.0"

[dependencies.cortex-m-rt]
optional = true
Expand All @@ -24,7 +24,7 @@ version = "0.7"
[dependencies.atsamd-hal]
default-features = false
path = "../../hal"
version = "0.22.2"
version = "0.23.0"

[dependencies.usb-device]
optional = true
Expand Down
6 changes: 6 additions & 0 deletions boards/circuit_playground_express/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.12.0](https://github.com/atsamd-rs/atsamd/compare/circuit_playground_express-0.11.1...circuit_playground_express-0.12.0) - 2025-11-20

### Dependencies

- *(circuit-playground-express)* Update dependencies and HAL to 0.23.0 ([#953](https://github.com/atsamd-rs/atsamd/pull/953))

## [0.11.1](https://github.com/atsamd-rs/atsamd/compare/circuit_playground_express-0.11.0...circuit_playground_express-0.11.1) - 2024-10-17

### Added
Expand Down
25 changes: 16 additions & 9 deletions boards/circuit_playground_express/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
[package]
name = "circuit_playground_express"
version = "0.11.1"
categories = ["embedded", "hardware-support", "no-std"]
version = "0.12.0"
authors = ["Paul Sajna <[email protected]>"]
description = "Board Support crate for the Adafruit Circuit Playground Express"
keywords = ["no-std", "arm", "cortex-m", "embedded-hal"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/atsamd-rs/atsamd"
readme = "README.md"
edition = "2018"
edition = "2024"

[dependencies.cortex-m-rt]
version = "0.7"
optional = true

[dependencies.atsamd-hal]
version = "0.14"
version = "0.23.0"
default-features = false

[dependencies.cortex-m]
features = ["critical-section-single-core"]
version = "0.7"

[dependencies.usb-device]
version = "0.2"
version = "0.3.2"
optional = true

[dev-dependencies]
cortex-m = "0.7"
panic-halt = "0.2"
panic-semihosting = "0.5"
usbd-serial = "0.1"
panic-semihosting = "0.6"
usbd-serial = "0.2"
smart-leds = "0.3.0"
heapless = "0.9.2"

[dev-dependencies.ws2812-timer-delay]
features = ["slow"]
version = "0.3.0"

[features]
# ask the HAL to enable atsamd21g support
default = ["rt", "atsamd-hal/samd21g"]
# CPE uses all kinds of undoc'd i2c functionality.
default = ["rt", "atsamd-hal/samd21g", "atsamd-hal/undoc-features"]
dma = ["atsamd-hal/dma"]
rt = ["cortex-m-rt", "atsamd-hal/samd21g-rt"]
unproven = ["atsamd-hal/unproven"]
usb = ["atsamd-hal/usb", "usb-device"]
use_semihosting = []

Expand All @@ -53,3 +59,4 @@ name = "uart"
[[example]]
name = "usb_serial"
required-features = ["usb"]
edition = "2021"
10 changes: 5 additions & 5 deletions boards/circuit_playground_express/examples/blinky_basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_internal_32kosc(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
peripherals.gclk,
&mut peripherals.pm,
&mut peripherals.sysctrl,
&mut peripherals.nvmctrl,
);
let pins = bsp::Pins::new(peripherals.PORT);
let pins = bsp::Pins::new(peripherals.port);
let mut red_led: bsp::RedLed = pins.d13.into();
let mut delay = Delay::new(core.SYST, &mut clocks);
loop {
Expand Down
22 changes: 12 additions & 10 deletions boards/circuit_playground_express/examples/neopixel_rainbow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ use circuit_playground_express as bsp;
use bsp::entry;
use hal::clock::GenericClockController;
use hal::delay::Delay;
use hal::prelude::*;
use hal::fugit::ExtU32;
use hal::timer::TimerCounter;
use hal::timer_traits::InterruptDrivenTimer;
use pac::{CorePeripherals, Peripherals};

use smart_leds::{
hsv::{hsv2rgb, Hsv},
SmartLedsWrite,
hsv::{Hsv, hsv2rgb},
};
use ws2812_timer_delay as ws2812;

Expand All @@ -35,24 +36,25 @@ fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_internal_32kosc(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
peripherals.gclk,
&mut peripherals.pm,
&mut peripherals.sysctrl,
&mut peripherals.nvmctrl,
);
let pins = bsp::Pins::new(peripherals.PORT);
let pins = bsp::Pins::new(peripherals.port);
let mut delay = Delay::new(core.SYST, &mut clocks);

let gclk0 = clocks.gclk0();
let timer_clock = clocks.tcc2_tc3(&gclk0).unwrap();
let mut timer = TimerCounter::tc3_(&timer_clock, peripherals.TC3, &mut peripherals.PM);
timer.start(3.mhz());
let mut timer = TimerCounter::tc3_(&timer_clock, peripherals.tc3, &mut peripherals.pm);
timer.start(1.micros());

let neopixel_pin: bsp::NeoPixel = pins.d8.into();
let mut neopixel = ws2812::Ws2812::new(timer, neopixel_pin);

// Loop through all of the available hue values (colors) to make a
// rainbow effect from the onboard neopixel
use hal::ehal::delay::DelayNs;
loop {
for j in 0..255u8 {
let colors = [hsv2rgb(Hsv {
Expand All @@ -61,7 +63,7 @@ fn main() -> ! {
val: 2,
}); 10];
neopixel.write(colors.iter().cloned()).unwrap();
delay.delay_ms(5u8);
delay.delay_ms(5);
}
}
}
75 changes: 41 additions & 34 deletions boards/circuit_playground_express/examples/uart.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! This example shows how to use the UART to perform transfers using the
//! embedded-hal-nb traits.

#![no_std]
#![no_main]

Expand All @@ -9,58 +12,62 @@ use panic_semihosting as _;
use bsp::hal;
use bsp::pac;
use circuit_playground_express as bsp;
use hal::nb;

use bsp::entry;
use bsp::{entry, periph_alias, pin_alias};
use hal::clock::GenericClockController;
use hal::prelude::*;
use hal::ehal_nb::serial::{Read, Write};
use hal::fugit::RateExtU32;

use pac::{CorePeripherals, Peripherals};
use pac::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.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
peripherals.gclk,
&mut peripherals.pm,
&mut peripherals.sysctrl,
&mut peripherals.nvmctrl,
);

let mut pm = peripherals.PM;
let pins = bsp::Pins::new(peripherals.PORT);
let mut delay = hal::delay::Delay::new(core.SYST, &mut clocks);
let mut pm = peripherals.pm;
let pins = bsp::Pins::new(peripherals.port);

let mut red_led = pins.d13.into_push_pull_output();
// Take peripheral and pins
let uart_sercom = periph_alias!(peripherals.uart_sercom);
let uart_rx = pin_alias!(pins.uart_rx);
let uart_tx = pin_alias!(pins.uart_tx);

// Setup UART peripheral.
let (rx_pin, tx_pin) = (pins.a6, pins.a7);
let mut uart = bsp::uart(
// Setup UART peripheral
let uart = bsp::uart(
&mut clocks,
9600.hz(),
peripherals.SERCOM4,
9600.Hz(),
uart_sercom,
&mut pm,
rx_pin,
tx_pin,
uart_rx,
uart_tx,
);

// Write out a message on start up.
for byte in b"Hello world!\r\n" {
nb::block!(uart.write(*byte)).unwrap();
}
// Split uart in rx + tx halves
let (mut rx, mut tx) = uart.split();

// Make buffers to store data to send/receive
let mut rx_buffer = [0x00; 50];
let tx_buffer = b"Hello, world!";

loop {
match uart.read() {
Ok(byte) => {
// Echo all received characters.
nb::block!(uart.write(byte)).unwrap();
// Send data. We block on each byte, but we could also perform some tasks while
// waiting for the byte to finish sending.
for c in tx_buffer.iter() {
nb::block!(tx.write(*c)).unwrap();
}

// Blink the red led to show that a character has arrived.
red_led.set_high().unwrap();
delay.delay_ms(2u16);
red_led.set_low().unwrap();
}
Err(_) => delay.delay_ms(5u16),
};
// Receive data. We block on each byte, but we could also perform some tasks
// while waiting for the byte to finish sending.
rx.flush_rx_buffer();
for c in rx_buffer.iter_mut() {
*c = nb::block!(rx.read()).unwrap();
}
}
}
Loading