203 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
= Starting a new project
 | 
						||
 | 
						||
Once you’ve successfully xref:#_getting_started[run some example projects], the next step is to make a standalone Embassy project.
 | 
						||
 | 
						||
== Tools for generating Embassy projects
 | 
						||
 | 
						||
=== CLI
 | 
						||
- link:https://github.com/adinack/cargo-embassy[cargo-embassy] (STM32 and NRF)
 | 
						||
 | 
						||
=== cargo-generate
 | 
						||
- link:https://github.com/lulf/embassy-template[embassy-template] (STM32, NRF, and RP)
 | 
						||
- link:https://github.com/bentwire/embassy-rp2040-template[embassy-rp2040-template] (RP)
 | 
						||
 | 
						||
 | 
						||
== Starting a project from scratch
 | 
						||
 | 
						||
As an example, let’s create a new embassy project from scratch for a STM32G474. The same instructions are applicable for any supported chip with some minor changes.
 | 
						||
 | 
						||
Run:
 | 
						||
 | 
						||
[source,bash]
 | 
						||
----
 | 
						||
cargo new stm32g474-example
 | 
						||
cd stm32g474-example
 | 
						||
----
 | 
						||
 | 
						||
to create an empty rust project:
 | 
						||
 | 
						||
[source]
 | 
						||
----
 | 
						||
stm32g474-example
 | 
						||
├── Cargo.toml
 | 
						||
└── src
 | 
						||
    └── main.rs
 | 
						||
----
 | 
						||
 | 
						||
Looking in link:https://github.com/embassy-rs/embassy/tree/main/examples[the Embassy examples], we can see there’s a `stm32g4` folder. Find `src/blinky.rs` and copy its contents into our `src/main.rs`.
 | 
						||
 | 
						||
=== The .cargo/config.toml
 | 
						||
 | 
						||
Currently, we’d need to provide cargo with a target triple every time we run `cargo build` or `cargo run`. Let’s spare ourselves that work by copying `.cargo/config.toml` from `examples/stm32g4` into our project.
 | 
						||
 | 
						||
[source]
 | 
						||
----
 | 
						||
stm32g474-example
 | 
						||
├── .cargo
 | 
						||
│   └── config.toml
 | 
						||
├── Cargo.toml
 | 
						||
└── src
 | 
						||
    └── main.rs
 | 
						||
----
 | 
						||
 | 
						||
In addition to a target triple, `.cargo/config.toml` contains a `runner` key which allows us to conveniently run our project on hardware with `cargo run` via probe-rs. In order for this to work, we need to provide the correct chip ID. We can do this by checking `probe-rs chip list`:
 | 
						||
 | 
						||
[source,bash]
 | 
						||
----
 | 
						||
$ probe-rs chip list | grep -i stm32g474re
 | 
						||
        STM32G474RETx
 | 
						||
----
 | 
						||
 | 
						||
and copying `STM32G474RETx` into `.cargo/config.toml` as so:
 | 
						||
 | 
						||
[source,toml]
 | 
						||
----
 | 
						||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
 | 
						||
# replace STM32G071C8Rx with your chip as listed in `probe-rs chip list`
 | 
						||
runner = "probe-rs run --chip STM32G474RETx"
 | 
						||
----
 | 
						||
 | 
						||
=== Cargo.toml
 | 
						||
 | 
						||
Now that cargo knows what target to compile for (and probe-rs knows what chip to run it on), we’re ready to add some dependencies.
 | 
						||
 | 
						||
Looking in `examples/stm32g4/Cargo.toml`, we can see that the examples require a number of embassy crates. For blinky, we’ll only need three of them: `embassy-stm32`, `embassy-executor` and `embassy-time`.
 | 
						||
 | 
						||
 | 
						||
At the time of writing, embassy is already published to crates.io. Therefore, dependencies can easily added via Cargo.toml.
 | 
						||
 | 
						||
[source,toml]
 | 
						||
----
 | 
						||
[dependencies]
 | 
						||
embassy-stm32 = { version = "0.1.0", features =  ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"] }
 | 
						||
embassy-executor = { version = "0.6.1", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
 | 
						||
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
 | 
						||
----
 | 
						||
 | 
						||
Prior, embassy needed to be installed straight from the git repository. Installing from git is still useful, if you want to checkout a specic revision of an embassy crate which is not yet published.
 | 
						||
The recommended way of doing so is as follows:
 | 
						||
 | 
						||
* Copy the required `embassy-*` lines from the example `Cargo.toml`
 | 
						||
* Make any necessary changes to `features`, e.g. requiring the `stm32g474re` feature of `embassy-stm32`
 | 
						||
* Remove the `path = ""` keys in the `embassy-*` entries
 | 
						||
* Create a `[patch.crates-io]` section, with entries for each embassy crate we need. These should all contain identical values: a link to the git repository, and a reference to the commit we’re checking out. Assuming you want the latest commit, you can find it by running `git ls-remote https://github.com/embassy-rs/embassy.git HEAD`
 | 
						||
 | 
						||
NOTE: When using this method, it’s necessary that the `version` keys in `[dependencies]` match up with the versions defined in each crate’s `Cargo.toml` in the specificed `rev` under `[patch.crates.io]`. This means that when updating, you have to a pick a new revision, change everything in `[patch.crates.io]` to match it, and then correct any versions under `[dependencies]` which have changed.
 | 
						||
 | 
						||
An example Cargo.toml file might look as follows:
 | 
						||
 | 
						||
[source,toml]
 | 
						||
----
 | 
						||
[dependencies]
 | 
						||
embassy-stm32 = {version = "0.1.0", features =  ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"]}
 | 
						||
embassy-executor = { version = "0.3.3", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
 | 
						||
embassy-time = { version = "0.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
 | 
						||
 | 
						||
[patch.crates-io]
 | 
						||
embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }
 | 
						||
embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }
 | 
						||
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }
 | 
						||
----
 | 
						||
 | 
						||
There are a few other dependencies we need to build the project, but fortunately they’re much simpler to install. Copy their lines from the example `Cargo.toml` to the the `[dependencies]` section in the new `Cargo.toml`:
 | 
						||
 | 
						||
[source,toml]
 | 
						||
----
 | 
						||
defmt = "0.3.5"
 | 
						||
defmt-rtt = "0.4.0"
 | 
						||
cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]}
 | 
						||
cortex-m-rt = "0.7.3"
 | 
						||
panic-probe = "0.3.1"
 | 
						||
----
 | 
						||
 | 
						||
These are the bare minimum dependencies required to run `blinky.rs`, but it’s worth taking a look at the other dependencies specified in the example `Cargo.toml`, and noting what features are required for use with embassy – for example `futures = { version = "0.3.17", default-features = false, features = ["async-await"] }`.
 | 
						||
 | 
						||
Finally, copy the `[profile.release]` section from the example `Cargo.toml` into ours.
 | 
						||
 | 
						||
[source,toml]
 | 
						||
----
 | 
						||
[profile.release]
 | 
						||
debug = 2
 | 
						||
----
 | 
						||
 | 
						||
=== rust-toolchain.toml
 | 
						||
 | 
						||
Before we can build our project, we need to add an additional file to tell cargo to use the nightly toolchain. Copy the `rust-toolchain.toml` from the embassy repo to ours, and trim the list of targets down to only the target triple relevent for our project — in this case, `thumbv7em-none-eabi`:
 | 
						||
 | 
						||
[source]
 | 
						||
----
 | 
						||
stm32g474-example
 | 
						||
├── .cargo
 | 
						||
│   └── config.toml
 | 
						||
├── Cargo.toml
 | 
						||
├── rust-toolchain.toml
 | 
						||
└── src
 | 
						||
    └── main.rs
 | 
						||
----
 | 
						||
 | 
						||
[source,toml]
 | 
						||
----
 | 
						||
# Before upgrading check that everything is available on all tier1 targets here:
 | 
						||
# https://rust-lang.github.io/rustup-components-history
 | 
						||
[toolchain]
 | 
						||
channel = "nightly-2023-11-01"
 | 
						||
components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ]
 | 
						||
targets = ["thumbv7em-none-eabi"]
 | 
						||
----
 | 
						||
 | 
						||
=== build.rs
 | 
						||
 | 
						||
In order to produce a working binary for our target, cargo requires a custom build script. Copy `build.rs` from the example to our project:
 | 
						||
 | 
						||
[source]
 | 
						||
----
 | 
						||
stm32g474-example
 | 
						||
├── build.rs
 | 
						||
├── .cargo
 | 
						||
│   └── config.toml
 | 
						||
├── Cargo.toml
 | 
						||
├── rust-toolchain.toml
 | 
						||
└── src
 | 
						||
    └── main.rs
 | 
						||
----
 | 
						||
 | 
						||
=== Building and running
 | 
						||
 | 
						||
At this point, we‘re finally ready to build and run our project! Connect your board via a debug probe and run:
 | 
						||
 | 
						||
[source,bash]
 | 
						||
----
 | 
						||
cargo run --release
 | 
						||
----
 | 
						||
 | 
						||
should result in a blinking LED (if there’s one attached to the pin in `src/main.rs` – change it if not!) and the following output:
 | 
						||
 | 
						||
[source]
 | 
						||
----
 | 
						||
   Compiling stm32g474-example v0.1.0 (/home/you/stm32g474-example)
 | 
						||
    Finished release [optimized + debuginfo] target(s) in 0.22s
 | 
						||
     Running `probe-rs run --chip STM32G474RETx target/thumbv7em-none-eabi/release/stm32g474-example`
 | 
						||
     Erasing sectors ✔ [00:00:00] [#########################################################] 18.00 KiB/18.00 KiB @ 54.09 KiB/s (eta 0s )
 | 
						||
 Programming pages   ✔ [00:00:00] [#########################################################] 17.00 KiB/17.00 KiB @ 35.91 KiB/s (eta 0s )    Finished in 0.817s
 | 
						||
0.000000 TRACE BDCR configured: 00008200
 | 
						||
└─ embassy_stm32::rcc::bd::{impl#3}::init::{closure#4} @ /home/you/.cargo/git/checkouts/embassy-9312dcb0ed774b29/7703f47/embassy-stm32/src/fmt.rs:117
 | 
						||
0.000000 DEBUG rcc: Clocks { sys: Hertz(16000000), pclk1: Hertz(16000000), pclk1_tim: Hertz(16000000), pclk2: Hertz(16000000), pclk2_tim: Hertz(16000000), hclk1: Hertz(16000000), hclk2: Hertz(16000000), pll1_p: None, adc: None, adc34: None, rtc: Some(Hertz(32000)) }
 | 
						||
└─ embassy_stm32::rcc::set_freqs @ /home/you/.cargo/git/checkouts/embassy-9312dcb0ed774b29/7703f47/embassy-stm32/src/fmt.rs:130
 | 
						||
0.000000 INFO  Hello World!
 | 
						||
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:14
 | 
						||
0.000091 INFO  high
 | 
						||
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:19
 | 
						||
0.300201 INFO  low
 | 
						||
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:23
 | 
						||
----
 |