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.3", 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
 | ||
| ----
 |