Skip to content

Commit 656979d

Browse files
gkellysajattack
authored andcommitted
boards: Add Seeeduino XIAO support
Add Seeed Studio Seeedunio XIAO support. The `blink` and `usb_serial` examples were tested on hardware.
1 parent 6d0d4c0 commit 656979d

File tree

8 files changed

+411
-0
lines changed

8 files changed

+411
-0
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ env:
2828
- CRATE=boards/pfza_proto1 EXAMPLES="--example=blinky_basic" FEATURES="--features=unproven"
2929
- CRATE=boards/serpente EXAMPLES="--example=blinky_basic --example=pwm" FEATURES="--features=unproven"
3030
- CRATE=boards/edgebadge FEATURES="--features=unproven"
31+
- CRATE=boards/xiao_m0 EXAMPLES="--example=blink --example=usb_serial" FEATURES="--features=usb"
3132

3233
matrix:
3334
allow_failures:

boards/xiao_m0/.cargo/config

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[build]
2+
target = "thumbv6m-none-eabi"
3+
4+
[target.thumbv6m-none-eabi]
5+
runner = 'arm-none-eabi-gdb'
6+
rustflags = [
7+
"-C", "link-arg=-Tlink.x",
8+
]

boards/xiao_m0/Cargo.toml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
[package]
2+
name = "xiao_m0"
3+
version = "0.6.1"
4+
authors = ["Garret Kelly <gdk@google.com>"]
5+
description = "Board support crate for the Seeed Studio Seeeduino XIAO"
6+
keywords = ["no-std", "arm", "cortex-m", "embedded-hal"]
7+
license = "MIT OR Apache-2.0"
8+
repository = "https://github.com/atsamd-rs/atsamd"
9+
readme = "README.md"
10+
documentation = "https://atsamd-rs.github.io/atsamd/atsamd21g18a/xiao_m0/"
11+
edition = "2018"
12+
13+
[dependencies]
14+
cortex-m = "~0.6.2"
15+
embedded-hal = "~0.2.3"
16+
nb = "~0.1"
17+
18+
[dependencies.cortex-m-rt]
19+
version = "~0.6.12"
20+
optional = true
21+
22+
[dependencies.atsamd-hal]
23+
path = "../../hal"
24+
version = "~0.8"
25+
default-features = false
26+
27+
[dependencies.usb-device]
28+
version = "~0.2"
29+
optional = true
30+
31+
[dependencies.usbd-serial]
32+
version = "~0.1"
33+
optional = true
34+
35+
[dev-dependencies]
36+
panic-halt = "~0.2"
37+
38+
[features]
39+
default = ["rt", "atsamd-hal/samd21g18a"]
40+
rt = ["cortex-m-rt", "atsamd-hal/samd21g18a-rt"]
41+
unproven = ["atsamd-hal/unproven"]
42+
usb = ["atsamd-hal/usb", "usb-device", "usbd-serial"]
43+
44+
[[example]]
45+
name = "blink"
46+
47+
[[example]]
48+
name = "usb_serial"
49+
required-features = ["usb"]
50+
51+
[profile.release]
52+
debug = true
53+
lto = true
54+
opt-level = "s"

boards/xiao_m0/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Seeeduino XIAO Board Support Crate
2+
3+
This crate provides a type-safe API for working with the [Seeed Studio
4+
Seeeduino XIAO](http://wiki.seeedstudio.com/Seeeduino-XIAO/).
5+
6+
## Prerequisites
7+
* Install the cross compile toolchain `rustup target add thumbv6m-none-eabi`
8+
* Install the [cargo-hf2 tool](https://crates.io/crates/cargo-hf2) however your
9+
platform requires
10+
11+
## Uploading an example
12+
Check out [the
13+
repository](https://github.com/atsamd-rs/atsamd/tree/master/boards/xiao_m0/examples)
14+
for examples.
15+
16+
* Be in this directory `cd boards/xiao_m0`
17+
* Put your device in bootloader mode by bridging the `RST` pads _twice_ in
18+
quick succession. The orange LED will pulse when the device is in bootloader
19+
mode.
20+
* Build and upload in one step: `cargo hf2 --release --example blink`
21+
* Note that if you're using an older `cargo-hf2` that you'll need to specify
22+
the VID/PID when flashing: `cargo hf2 --vid 0x2886 --pid 0x002f --release
23+
--example blink`

boards/xiao_m0/examples/blink.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
extern crate cortex_m;
5+
extern crate panic_halt;
6+
extern crate xiao_m0 as hal;
7+
8+
use hal::clock::GenericClockController;
9+
use hal::delay::Delay;
10+
use hal::entry;
11+
use hal::pac::{CorePeripherals, Peripherals};
12+
use hal::prelude::*;
13+
14+
#[entry]
15+
fn main() -> ! {
16+
let mut peripherals = Peripherals::take().unwrap();
17+
let core = CorePeripherals::take().unwrap();
18+
let mut clocks = GenericClockController::with_external_32kosc(
19+
peripherals.GCLK,
20+
&mut peripherals.PM,
21+
&mut peripherals.SYSCTRL,
22+
&mut peripherals.NVMCTRL,
23+
);
24+
let mut pins = hal::Pins::new(peripherals.PORT);
25+
let mut led0 = pins.led0.into_open_drain_output(&mut pins.port);
26+
let mut led1 = pins.led1.into_open_drain_output(&mut pins.port);
27+
let mut led2 = pins.led2.into_open_drain_output(&mut pins.port);
28+
let mut delay = Delay::new(core.SYST, &mut clocks);
29+
30+
let mut counter = 0u8;
31+
loop {
32+
counter = counter.wrapping_add(1);
33+
delay.delay_ms(100u8);
34+
if counter & (1 << 0) != 0 {
35+
led0.toggle();
36+
}
37+
if counter & (1 << 1) != 0 {
38+
led1.toggle();
39+
}
40+
if counter & (1 << 2) != 0 {
41+
led2.toggle();
42+
}
43+
}
44+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
extern crate cortex_m;
5+
extern crate panic_halt;
6+
extern crate usb_device;
7+
extern crate usbd_serial;
8+
extern crate xiao_m0 as hal;
9+
10+
use hal::clock::GenericClockController;
11+
use hal::entry;
12+
use hal::gpio::{OpenDrain, Output, Pa18};
13+
use hal::pac::{interrupt, CorePeripherals, Peripherals};
14+
15+
use hal::usb::UsbBus;
16+
use usb_device::bus::UsbBusAllocator;
17+
18+
use usb_device::prelude::*;
19+
use usbd_serial::{SerialPort, USB_CLASS_CDC};
20+
21+
use cortex_m::asm::delay as cycle_delay;
22+
use cortex_m::peripheral::NVIC;
23+
24+
#[entry]
25+
fn main() -> ! {
26+
let mut peripherals = Peripherals::take().unwrap();
27+
let mut core = CorePeripherals::take().unwrap();
28+
let mut clocks = GenericClockController::with_internal_32kosc(
29+
peripherals.GCLK,
30+
&mut peripherals.PM,
31+
&mut peripherals.SYSCTRL,
32+
&mut peripherals.NVMCTRL,
33+
);
34+
let mut pins = hal::Pins::new(peripherals.PORT);
35+
let mut led0 = pins.led0.into_open_drain_output(&mut pins.port);
36+
37+
let bus_allocator = unsafe {
38+
USB_ALLOCATOR = Some(hal::usb_allocator(
39+
peripherals.USB,
40+
&mut clocks,
41+
&mut peripherals.PM,
42+
pins.usb_dm,
43+
pins.usb_dp,
44+
&mut pins.port,
45+
));
46+
USB_ALLOCATOR.as_ref().unwrap()
47+
};
48+
49+
unsafe {
50+
USB_SERIAL = Some(SerialPort::new(&bus_allocator));
51+
USB_BUS = Some(
52+
UsbDeviceBuilder::new(&bus_allocator, UsbVidPid(0x16c0, 0x27dd))
53+
.manufacturer("Fake company")
54+
.product("Serial port")
55+
.serial_number("TEST")
56+
.device_class(USB_CLASS_CDC)
57+
.build(),
58+
);
59+
LED = Some(pins.led1.into_open_drain_output(&mut pins.port));
60+
}
61+
62+
unsafe {
63+
core.NVIC.set_priority(interrupt::USB, 1);
64+
NVIC::unmask(interrupt::USB);
65+
}
66+
67+
// Flash the LED in a spin loop to demonstrate that USB is
68+
// entirely interrupt driven.
69+
loop {
70+
cycle_delay(15 * 1024 * 1024);
71+
led0.toggle();
72+
}
73+
}
74+
75+
static mut USB_ALLOCATOR: Option<UsbBusAllocator<UsbBus>> = None;
76+
static mut USB_BUS: Option<UsbDevice<UsbBus>> = None;
77+
static mut USB_SERIAL: Option<SerialPort<UsbBus>> = None;
78+
static mut LED: Option<Pa18<Output<OpenDrain>>> = None;
79+
80+
fn poll_usb() {
81+
unsafe {
82+
USB_BUS.as_mut().map(|usb_dev| {
83+
USB_SERIAL.as_mut().map(|serial| {
84+
usb_dev.poll(&mut [serial]);
85+
let mut buf = [0u8; 64];
86+
87+
if let Ok(count) = serial.read(&mut buf) {
88+
for (i, c) in buf.iter().enumerate() {
89+
if i >= count {
90+
break;
91+
}
92+
serial.write(&[c.clone()]).unwrap();
93+
LED.as_mut().map(|led| led.toggle());
94+
}
95+
};
96+
});
97+
});
98+
};
99+
}
100+
101+
#[interrupt]
102+
fn USB() {
103+
poll_usb();
104+
}

boards/xiao_m0/memory.x

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
MEMORY
2+
{
3+
/* Leave 8k for the default bootloader on the Seeeduino XIAO */
4+
FLASH (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 256K - 8K
5+
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
6+
}
7+
_stack_start = ORIGIN(RAM) + LENGTH(RAM);

0 commit comments

Comments
 (0)