= 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)

=== esp-generate
- link:https://github.com/esp-rs/esp-generate[esp-generate] (ESP32 using esp-hal)

== 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"] }
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"] }
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 `[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 = "1.85"
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
----
