Skip to content

Commit

Permalink
docs: Update to esp-generate
Browse files Browse the repository at this point in the history
  • Loading branch information
SergioGasquez committed Nov 14, 2024
1 parent d360fa5 commit c9c03f7
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 82 deletions.
2 changes: 1 addition & 1 deletion book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ additional-js = ["assets/mermaid.min.js", "assets/mermaid-init.js"]
"/overview/bare-metal.html" = "https://esp-rs.github.io/book/overview/using-the-core-library.html"
"/tooling/text-editors-and-ides.html" = "https://esp-rs.github.io/book/tooling/visual-studio-code.html"
"/debugging/vscode-debugging.html" = "https://esp-rs.github.io/book/debugging/vscode.html"
"/writing-your-own-application/no-std-applications/understanding-esp-template.html" = "https://esp-rs.github.io/book/writing-your-own-application/generate-project/esp-template.html"
"/writing-your-own-application/no-std-applications/understanding-esp-template.html" = "https://esp-rs.github.io/book/writing-your-own-application/generate-project/esp-generate.html"
"installation/installation.html" = "https://esp-rs.github.io/book/installation/index.html"
"troubleshooting/espflash.html" = "https://esp-rs.github.io/book/troubleshooting/index.html"

Expand Down
2 changes: 1 addition & 1 deletion src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- [Using Containers](./installation/using-containers.md)
- [Writing Your Own Application](./writing-your-own-application/index.md)
- [Generating Projects from Templates](./writing-your-own-application/generate-project/index.md)
- [Understanding `esp-template`](./writing-your-own-application/generate-project/esp-template.md)
- [Understanding `esp-generate`](./writing-your-own-application/generate-project/esp-generate.md)
- [Understanding `esp-idf-template`](./writing-your-own-application/generate-project/esp-idf-template.md)
- [Writing `no_std` Applications](./writing-your-own-application/nostd.md)
- [Writing `std` Applications](./writing-your-own-application/std.md)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Understanding `esp-template`
# Understanding `esp-generate`

Now that we know how to [generate a `no_std` project][generate-no-std], let's inspect what the generated
project contains, try to understand every part of it, and run it.
Expand All @@ -7,48 +7,52 @@ project contains, try to understand every part of it, and run it.

## Inspecting the Generated Project

When creating a project from [`esp-template`][esp-template] with the following answers:
- Which MCU to target? · `esp32c3`
- Configure advanced template options? · `false`

For this explanation, we will use the default values, if you want further modifications, see the [additional prompts][prompts] when not using default values.
When creating a project from [`esp-generate`][esp-generate] with no extra options:
```
esp-generate --chip esp32c3 your-project
```

It should generate a file structure like this:

```text
├── build.rs
├── .cargo
│   └── config.toml
├── src
│   └── main.rs
├── .gitignore
│ └── config.toml
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
└── rust-toolchain.toml
├── .gitignore
├── rust-toolchain.toml
├── src
│ ├── bin
│ │ └── main.rs
│ └── lib.rs
└── .vscode
└── settings.json
```

Before going further, let's see what these files are for.

- [`build.rs`][build.rs]
- Sets the linker script arguments based on the template options.
- [`.cargo/config.toml`][config-toml]
- The Cargo configuration
- This defines a few options to correctly build the project
- Contains `runner = "espflash flash --monitor"` - this means you can just use `cargo run` to flash and monitor your code
- `src/main.rs`
- The main source file of the newly created project
- For details, see the [Understanding `main.rs`][main-rs] section below
- [`.gitignore`][gitignore]
- Tells `git` which folders and files to ignore
- Contains the custom runner command for `espflash` or `probe-rs`. For example, `runner = "espflash flash --monitor"` - this means you can just use `cargo run` to flash and monitor your code
- [`Cargo.toml`][cargo-toml]
- The usual Cargo manifest declares some meta-data and dependencies of the project
- `LICENSE-APACHE`, `LICENSE_MIT`
- Those are the most common licenses used in the Rust ecosystem
- If you want to use a different license, you can delete these files and change the license in `Cargo.toml`
- [`.gitignore`][gitignore]
- Tells `git` which folders and files to ignore
- [`rust-toolchain.toml`][rust-toolchain-toml]
- Defines which Rust toolchain to use
- The toolchain will be `nightly` or `esp` depending on your target
- `src/bin/main.rs`
- The main source file of the newly created project
- For details, see the [Understanding `main.rs`][main-rs] section below
- `src/lib.rs`
- This tells the Rust compiler that this code doesn't use `libstd`
- `.vscode/settings.json`
- Defines a set of settings for Visual Studio Code to make Rust Analyzer work.

[esp-template]: https://github.com/esp-rs/esp-template
[prompts]: https://github.com/esp-rs/esp-template#esp-template
[esp-generate]: https://github.com/esp-rs/esp-generate
[build.rs]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
[main-rs]: #understanding-mainrs
[cargo-toml]: https://doc.rust-lang.org/cargo/reference/manifest.html
[gitignore]: https://git-scm.com/docs/gitignore
Expand All @@ -68,44 +72,43 @@ Before going further, let's see what these files are for.
- The `no_main` attribute says that this program won't use the standard main interface, which is usually used when a full operating system is available. Instead of the standard main, we'll use the entry attribute from the `esp-riscv-rt` crate to define a custom entry point. In this program, we have named the entry point `main`, but any other name could have been used. The entry point function must be a [diverging function][diverging-function]. I.e. it has the signature `fn foo() -> !`; this type indicates that the function never returns – which means that the program never terminates.

```rust,ignore
4 use esp_backtrace as _;
5 use esp_println::println;
6 use esp_hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, timer::TimerGroup, Rtc};
4 use esp_backtrace as _;
5 use esp_hal::delay::Delay;
6 use esp_hal::prelude::*;
7 use log::info;
```
- `use esp_backtrace as _;`
- Since we are in a bare-metal environment, we need a panic handler that runs if a panic occurs in code
- There are a few different crates you can use (e.g `panic-halt`) but `esp-backtrace` provides an implementation that prints the address of a backtrace - together with `espflash` these addresses can get decoded into source code locations
- `use esp_println::println;`
- Provides `println!` implementation
- `use esp_hal::{...}`
- We need to bring in some types we are going to use
- `use esp_hal::delay::Delay;`
- Provides `Delay` driver implementation.
- `use esp_hal::prelude::*;`
- Imports the `esp-hal` [prelude][prelude].

```rust,ignore
8 #[entry]
9 fn main() -> ! {
10 let peripherals = Peripherals::take();
11 let system = peripherals.SYSTEM.split();
12 let clocks = ClockControl::max(system.clock_control).freeze();
13
14 println!("Hello world!");
15
16 loop {}
10 esp_println::logger::init_logger_from_env();
11
12 let delay = Delay::new();
13 loop {
14 info!("Hello world!");
15 delay.delay(500.millis());
16 }
17 }
```

Inside the `main` function we can find:
- `let peripherals = Peripherals::take()`
- HAL drivers usually take ownership of peripherals accessed via the PAC
- Here we take all the peripherals from the PAC to pass them to the HAL drivers later
- `let mut system = peripherals.SYSTEM.split();`
- Sometimes a peripheral (here the System peripheral) is coarse-grained and doesn't exactly fit the HAL drivers - so here we split the System peripheral into smaller pieces which get passed to the drivers
- `let clocks = ClockControl::max(system.clock_control).freeze();`
- Here we configure the system clocks - in this case, boost to the maxiumum for the chip
- We freeze the clocks, which means we can't change them later
- Some drivers need a reference to the clocks to know how to calculate rates and durations
- `println!("Hello world!");`
- Prints "Hello world!"
- `esp_println::logger::init_logger_from_env();`
- Initializes the logger, if `ESP_LOG` environment variable is defined, it will use that log level.
- `let delay = Delay::new();`
- Creates a delay instance.
- `loop {}`
- Since our function is supposed to never return, we just "do nothing" in a loop
- Since our function is supposed to never return, we use a loop
- `info!("Hello world!");`
- Creates a log message with `info` level that prints "Hello world!".
- `delay.delay(500.millis());`
- Waits for 500 milliseconds.

[diverging-function]: https://doc.rust-lang.org/beta/rust-by-example/fn/diverging.html

Expand All @@ -114,7 +117,7 @@ Inside the `main` function we can find:
Building and running the code is as easy as

```shell
cargo run
cargo run --release
```

This builds the code according to the configuration and executes [`espflash`][espflash] to flash the code to the board.
Expand All @@ -127,26 +130,26 @@ Make sure that you have [`espflash`][espflash] installed, otherwise this step wi
You should see something similar to this:

```text
[2023-04-17T14:17:08Z INFO ] Serial port: '/dev/ttyACM0'
[2023-04-17T14:17:08Z INFO ] Connecting...
[2023-04-17T14:17:09Z INFO ] Using flash stub
[2023-04-17T14:17:09Z WARN ] Setting baud rate higher than 115,200 can cause issues
...
[2024-11-14T09:29:32Z INFO ] Serial port: '/dev/ttyUSB0'
[2024-11-14T09:29:32Z INFO ] Connecting...
[2024-11-14T09:29:32Z INFO ] Using flash stub
[2024-11-14T09:29:33Z WARN ] Setting baud rate higher than 115,200 can cause issues
Chip type: esp32c3 (revision v0.3)
Crystal frequency: 40MHz
Crystal frequency: 40 MHz
Flash size: 4MB
Features: WiFi, BLE
MAC address: 60:55:f9:c0:39:7c
App/part. size: 203,920/4,128,768 bytes, 4.94%
MAC address: a0:76:4e:5a:d2:c8
App/part. size: 76,064/4,128,768 bytes, 1.84%
[00:00:00] [========================================] 13/13 0x0
[00:00:00] [========================================] 1/1 0x8000
[00:00:01] [========================================] 64/64 0x10000
[2023-04-17T14:17:11Z INFO ] Flashing has completed!
[00:00:00] [========================================] 11/11 0x10000
[2024-11-14T09:29:35Z INFO ] Flashing has completed!
Commands:
CTRL+R Reset chip
CTRL+C Exit
...
Hello world!
INFO - Hello world!
```

What you see here are messages from the first and second stage bootloader, and then, our "Hello world" message!
Expand All @@ -157,6 +160,8 @@ You can reboot with `CTRL+R` or exit with `CTRL+C`.

If you encounter any issues while building the project, please, see the [Troubleshooting][troubleshooting] chapter.


[prelude]: https://doc.rust-lang.org/reference/names/preludes.html
[espflash]: https://github.com/esp-rs/espflash/tree/main/espflash
[runner-config]: https://doc.rust-lang.org/cargo/reference/config.html#targettriplerunner
[troubleshooting]: ../../troubleshooting/index.md
51 changes: 34 additions & 17 deletions src/writing-your-own-application/generate-project/index.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,46 @@
# Generating Projects from Templates

We currently maintain two template repositories:
- [`esp-template`][esp-template] - `no_std` template.
- [`esp-generate`][esp-generate] - `no_std` template.
- [`esp-idf-template`][esp-idf-template] - `std` template.

Both templates are based on [`cargo-generate`][cargo-generate], a tool that allows you to create a new project based on some existing template. In our case, [`esp-idf-template`][esp-idf-template] or [`esp-template`][esp-template] can be used to generate an application with all the required configurations and dependencies.

## `esp-generate`

`esp-generate` is project generation tool that can be used to generate an application with all the required configurations and dependencies

1. Install `esp-generate`:
```shell
cargo install esp-generate
```
2. Generate a project based on the template, selecting the chip and the name of the project:
```shell
esp-generate --chip=esp32c6 your-project
```
See [Understanding `esp-generate`][understanding-esp-generate] for more details on the template project.

When the `esp-generate` subcommand is invoked, you will be prompted with a TUI where you can select the configuration of your application. Upon completion of this process, you will have a buildable project with all the correct configurations.

3. Build/Run the generated project:
- Use `cargo build` to compile the project using the appropriate toolchain and target.
- Use `cargo run` to compile the project, flash it, and open a serial monitor with our target device.

[esp-generate]: https://github.com/esp-rs/esp-generate
[understanding-esp-generate]: ./esp-generate.md

## `esp-idf-template`

`esp-idf-tempalte` is based on [`cargo-generate`][cargo-generate], a tool that allows you to create a new project based on some existing template. In our case, [`esp-idf-template`][esp-idf-template] can be used to generate an application with all the required configurations and dependencies.

1. Install `cargo generate`:
```shell
cargo install cargo-generate
```
2. Generate a project based on one of the templates:
- `esp-template`:
```shell
cargo generate esp-rs/esp-template
```
See [Understanding `esp-template`][understanding-esp-template] for more details on the template project.
- `esp-idf-template`:
```shell
cargo generate esp-rs/esp-idf-template cargo
```
See [Understanding `esp-idf-template`][understanding-esp-idf-template] for more details on the template project.
2. Generate a project based on the template:
```shell
cargo generate esp-rs/esp-idf-template cargo
```
See [Understanding `esp-idf-template`][understanding-esp-idf-template] for more details on the template project.

When the `cargo generate` subcommand is invoked, you will be prompted to answer several questions regarding the target of your application. Upon completion of this process, you will have a buildable project with all the correct configurations.

Expand All @@ -30,17 +50,14 @@ Both templates are based on [`cargo-generate`][cargo-generate], a tool that allo

[cargo-generate]: https://github.com/cargo-generate/cargo-generate
[esp-idf-template]: https://github.com/esp-rs/esp-idf-template
[esp-template]: https://github.com/esp-rs/esp-template
[understanding-esp-template]: ./esp-template.md
[understanding-esp-idf-template]: ./esp-idf-template.md

## Using Dev Containers in the Templates

Both template repositories have a prompt for Dev Containers support, see details in [Dev Containers][dev-container] section of the template README.
Both template repositories have a prompt for Dev Containers support.

Dev Containers use the [`idf-rust`][idf-rust] container image, which was explained in the [Using Container][using-container] section of the [Setting up a Development Environment][setting-env] chapter. This image provides an environment ready to develop Rust applications for Espressif chips with no installation required. Dev Containers also have integration with [Wokwi simulator][wokwi], to simulate the project, and allow flashing from the container using [`web-flash`][web-flash].

[dev-container]: https://github.com/esp-rs/esp-template/tree/main/docs#dev-containers
[idf-rust]: https://hub.docker.com/r/espressif/idf-rust/tags
[using-container]: ../../installation/using-containers.md
[wokwi]: https://wokwi.com/
Expand Down

0 comments on commit c9c03f7

Please sign in to comment.