-
Notifications
You must be signed in to change notification settings - Fork 905
Getting Started
To begin, you should:
- Have an MCU that embassy supports. We currently support stm32f4, stm32l0, and nrf series MCUs. We aim to support all common stm32 families.
- Know how to compile, load, and debug a rust program on an embedded target.
- Have an embedded probe that your IDE supports.
- Have the nightly rust compiler with the applicable eabi target, for example
thumbv7em-none-eabi
.
If you're not familiar with embedded development, consult the rust embedded development book.
Because embassy uses some unstable features to support async, embassy requires the rust nightly compiler. Even though embassy currently requires the nightly compiler, you can be confident that software written with embassy will continue to be supported into the future as the required compiler features become stabilized.
Embassy has two options for creating a project: the basic and advanced API. The basic API assumes that every task runs at the same priority and that delays will be needed. The advanced API allows multiple-priority tasks and usage with other frameworks such as RTIC, but is more complex to set-up. Here, we will begin with the simple API.
Though embassy does not require a particular HAL, the stm32-rs
HAL is used to configure clocks if the basic API is used. Other HALs may be used
with other peripherals, provided that they also use the standard svd2rust PAC.
To begin, let's create our main
function:
#[embassy::main(use_hse = 48)]
async fn main(spawner: Spawner) {
let (dp, clocks) = embassy_stm32::Peripherals::take().unwrap();
spawner.spawn(run1()).unwrap();
}
First, we the write main function and add an embassy::main
attribute. The embassy::main
attribute sets-up a simple clock and executor
configuration using the specified arguments. In this case we use a high-speed external oscillator running at 48 Mhz. Then, we take our device
peripherals with embassy_stm32::Peripherals::take()
. This replaces the standard pac::Peripherals::take()
call, because embassy takes some of the
peripherals during set-up. If the basic set-up is used, pac::Peripherals::take()
will panic, though cortex_m::Peripherals::take()
can be used
as normal. Finally, we use the spawner to spawn a task.
Every task is declared with the task macro, as such. Every task is a standard async
function defined with the task
attribute. Only functions
defined with the task
attribute can be spawned with the spawner
. Tasks can accept any number of arguments, but they cannot be defined with
generic parameters.
#[task]
async fn run1() {
loop {
info!("tick");
Timer::after(Duration::from_ticks(13000 as u64)).await;
}
}