Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arduino Zero support #305

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions boards/arduino_zero/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# samd21 is a Cortex-M0 and thus thumbv6m

[build]
target = "thumbv6m-none-eabi"

[target.thumbv6m-none-eabi]
runner = 'arm-none-eabi-gdb'
rustflags = [
"-C", "link-arg=-Tlink.x",
]
56 changes: 56 additions & 0 deletions boards/arduino_zero/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[package]
name = "arduino_zero"
version = "0.8.1"
authors = ["Karsten Große <[email protected]>"]
description = "Board Support crate for the Arduino ZERO"
keywords = ["no-std", "arm", "cortex-m", "embedded-hal", "arduino"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/atsamd-rs/atsamd"
readme = "README.md"
edition = "2018"

[dependencies]
cortex-m = "0.6"
embedded-hal = "0.2.3"
nb = "0.1"

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

[dependencies.panic-halt]
version = "0.2"
optional = true

[dependencies.atsamd-hal]
path = "../../hal"
version = "0.10"
default-features = false

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

[dependencies.usbd-serial]
version = "0.1"
optional = true

[features]
# ask the HAL to enable atsamd21g support
default = ["rt", "panic_halt", "atsamd-hal/samd21g", "usb"]
rt = ["cortex-m-rt", "atsamd-hal/samd21g-rt"]
usb = ["atsamd-hal/usb", "usb-device", "usbd-serial"]
panic_halt = ["panic-halt"]
unproven = ["atsamd-hal/unproven"]
use_semihosting = []

[[example]]
name = "blinky_basic"

[[example]]
name = "usb_logging"
required-features = ["usb"]

[[example]]
name = "pwm"
required-features = ["unproven"]
22 changes: 22 additions & 0 deletions boards/arduino_zero/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Arduino Mkrzero Board Support Crate

This crate provides a type-safe API for working with the [Arduino mkrzero board](https://store.arduino.cc/arduino-mkrzero).

## Examples
### Blinky Basic
#### Requirements
- Arduino IDE installed
- samd package installed
- Now the arduino distribution contains bossac.exe in `ArduinoData/packages/arduino/tools/bossac/1.7.0/` add it to your path
- `ArduinoData` is likely something like `~/.arduino15/`
- Probably best to install an example sketch via the IDE just to make sure everything is working
- Note that the [arduino cli](https://github.com/arduino/arduino-cli) (or just regular bossac) may soon replace this section
- arm-none-eabi tools installed, you need gcc and objcopy.
- thumbv6m-none-eabi rust target installed via `rustup target add thumbv6m-none-eabi`

#### Steps
```bash
cargo build --release --example blinky_basic
arm-none-eabi-objcopy -O binary target/thumbv6m-none-eabi/release/examples/blinky_basic target/blinky_basic.bin
bossac -i -d -U true -i -e -w -v target/blinky_basic.bin -R
```
16 changes: 16 additions & 0 deletions boards/arduino_zero/build.rs
Original file line number Diff line number Diff line change
@@ -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");
}
32 changes: 32 additions & 0 deletions boards/arduino_zero/examples/blinky_basic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#![no_std]
#![no_main]

extern crate arduino_zero as hal;

use hal::clock::GenericClockController;
use hal::delay::Delay;
use hal::entry;
use hal::pac::{CorePeripherals, Peripherals};
use hal::prelude::*;

#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_external_32kosc(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
);
let mut pins = hal::Pins::new(peripherals.PORT);
let mut led = pins.led_sck.into_open_drain_output(&mut pins.port);
let mut delay = Delay::new(core.SYST, &mut clocks);

loop {
delay.delay_ms(200u8);
led.set_high().unwrap();
delay.delay_ms(200u8);
led.set_low().unwrap();
}
}
48 changes: 48 additions & 0 deletions boards/arduino_zero/examples/pwm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#![no_std]
#![no_main]

extern crate arduino_zero as hal;
extern crate atsamd_hal;

use hal::clock::{GenericClockController, Tcc0Tcc1Clock};
use hal::delay::Delay;
use hal::entry;
use hal::pac::{CorePeripherals, Peripherals};
use hal::prelude::*;
use hal::pwm::{Channel, Pwm0};

#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_external_32kosc(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
);
let mut delay = Delay::new(core.SYST, &mut clocks);
let mut pins = hal::Pins::new(peripherals.PORT);

// PWM0_CH1 is A4 on the board - pin 19 or PA05
// see: https://github.com/arduino/ArduinoCore-samd/blob/master/variants/mkrzero/variant.cpp
let _a4 = pins.a4.into_function_e(&mut pins.port);
let gclk0 = clocks.gclk0();

let tcc0_tcc1_clock: &Tcc0Tcc1Clock = &clocks.tcc0_tcc1(&gclk0).unwrap();

let mut pwm0 = Pwm0::new(
&tcc0_tcc1_clock,
1.khz(),
peripherals.TCC0,
&mut peripherals.PM,
);
let max_duty = pwm0.get_max_duty();
pwm0.enable(Channel::_1);
loop {
pwm0.set_duty(Channel::_1, max_duty);
delay.delay_ms(500u16);
pwm0.set_duty(Channel::_1, max_duty / 4);
delay.delay_ms(500u16);
}
}
105 changes: 105 additions & 0 deletions boards/arduino_zero/examples/usb_logging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#![no_std]
#![no_main]

extern crate arduino_zero as hal;
extern crate cortex_m;
extern crate panic_halt;
extern crate usb_device;
extern crate usbd_serial;

use hal::clock::GenericClockController;
use hal::delay::Delay;
use hal::entry;
use hal::pac::{interrupt, CorePeripherals, Peripherals};
use hal::prelude::*;

use hal::usb::UsbBus;
use usb_device::bus::UsbBusAllocator;
use usb_device::prelude::*;
use usbd_serial::{SerialPort, USB_CLASS_CDC};

use cortex_m::peripheral::NVIC;

static mut USB_ALLOCATOR: Option<UsbBusAllocator<UsbBus>> = None;
static mut USB_BUS: Option<UsbDevice<UsbBus>> = None;
static mut USB_SERIAL: Option<SerialPort<UsbBus>> = None;

#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let mut core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_external_32kosc(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
);
let mut pins = hal::Pins::new(peripherals.PORT);
let mut led = pins.led_sck.into_open_drain_output(&mut pins.port);
let mut delay = Delay::new(core.SYST, &mut clocks);

let bus_allocator = unsafe {
USB_ALLOCATOR = Some(hal::usb_allocator(
peripherals.USB,
&mut clocks,
&mut peripherals.PM,
pins.usb_n, // PA24, also usb_dm
pins.usb_p, // PA24 also usb_dp
&mut pins.port,
));
USB_ALLOCATOR.as_ref().unwrap()
};

unsafe {
USB_SERIAL = Some(SerialPort::new(&bus_allocator));
USB_BUS = Some(
UsbDeviceBuilder::new(&bus_allocator, UsbVidPid(0x2222, 0x3333))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(USB_CLASS_CDC)
.build(),
);
}

unsafe {
core.NVIC.set_priority(interrupt::USB, 1);
NVIC::unmask(interrupt::USB);
}

loop {
delay.delay_ms(200u8);
led.set_high().unwrap();
delay.delay_ms(200u8);
led.set_low().unwrap();

// Turn off interrupts so we don't fight with the interrupt
cortex_m::interrupt::free(|_| unsafe {
USB_BUS.as_mut().map(|_| {
USB_SERIAL.as_mut().map(|serial| {
// Skip errors so we can continue the program
let _ = serial.write("log line\r\n".as_bytes());
});
})
});
}
}

fn poll_usb() {
unsafe {
USB_BUS.as_mut().map(|usb_dev| {
USB_SERIAL.as_mut().map(|serial| {
usb_dev.poll(&mut [serial]);

// Make the other side happy
let mut buf = [0u8; 16];
let _ = serial.read(&mut buf);
});
});
};
}

#[interrupt]
fn USB() {
poll_usb();
}
5 changes: 5 additions & 0 deletions boards/arduino_zero/memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* bootloader 8kb */
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
Loading