@@ -30,7 +30,7 @@ cargo install cargo-generate
3030```
3131Then generate a new project
3232``` console
33- cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
33+ cargo generate --git https://github.com/knurling-rs/app-template
3434```
3535
3636``` text
@@ -135,6 +135,47 @@ bit in the function signature) to ensure at compile time that'll be the case.
135135
136136## Cross compiling
137137
138+ First of all we will need the memory layout for the target microcontroller, the
139+ LM3S6965 in our case. Otherwise the build will fail to link the image. Create a
140+ file named ` memory.x ` at the root of the project and paste the following content:
141+
142+ ```
143+ MEMORY
144+ {
145+ /* NOTE 1 K = 1 KiBi = 1024 bytes */
146+ /* TODO Adjust these memory regions to match your device memory layout */
147+ /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */
148+ FLASH : ORIGIN = 0x00000000, LENGTH = 256K
149+ RAM : ORIGIN = 0x20000000, LENGTH = 64K
150+ }
151+
152+ /* This is where the call stack will be allocated. */
153+ /* The stack is of the full descending type. */
154+ /* You may want to use this variable to locate the call stack and static
155+ variables in different memory regions. Below is shown the default value */
156+ /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */
157+
158+ /* You can use this symbol to customize the location of the .text section */
159+ /* If omitted the .text section will be placed right after the .vector_table
160+ section */
161+ /* This is required only on microcontrollers that store some configuration right
162+ after the vector table */
163+ /* _stext = ORIGIN(FLASH) + 0x400; */
164+
165+ /* Example of putting non-initialized variables into custom RAM locations. */
166+ /* This assumes you have defined a region RAM2 above, and in the Rust
167+ sources added the attribute `#[link_section = ".ram2bss"]` to the data
168+ you want to place there. */
169+ /* Note that the section will not be zero-initialized by the runtime! */
170+ /* SECTIONS {
171+ .ram2bss (NOLOAD) : ALIGN(4) {
172+ *(.ram2bss);
173+ . = ALIGN(4);
174+ } > RAM2
175+ } INSERT AFTER .bss;
176+ */
177+ ```
178+
138179The next step is to * cross* compile the program for the Cortex-M3 architecture.
139180That's as simple as running ` cargo build --target $TRIPLE ` if you know what the
140181compilation target (` $TRIPLE ` ) should be. Luckily, the ` .cargo/config.toml ` in the
@@ -157,9 +198,11 @@ To cross compile for the Cortex-M3 architecture we have to use
157198` thumbv7m-none-eabi ` . That target is not automatically installed when installing
158199the Rust toolchain, it would now be a good time to add that target to the toolchain,
159200if you haven't done it yet:
201+
160202``` console
161203rustup target add thumbv7m-none-eabi
162204```
205+
163206 Since the ` thumbv7m-none-eabi ` compilation target has been set as the default in
164207 your ` .cargo/config.toml ` file, the two commands below do the same:
165208
@@ -311,55 +354,53 @@ HardFault:
311354## Running
312355
313356Next, let's see how to run an embedded program on QEMU! This time we'll use the
314- ` hello ` example which actually does something.
357+ ` hello ` example which actually does something. By default, this example uses [ defmt]
358+ and RTT to print text.
315359
316- For convenience here's the source code of ` examples/hello.rs ` :
360+ [ defmt ] : https://defmt.ferrous-systems.com/
317361
318- ``` rust,ignore
319- //! Prints "Hello, world!" on the host console using semihosting
362+ In order to read and decode the messages produced by defmt in the host, we need to
363+ switch the RTT transport output to semihosting. When using real hardware this requires
364+ a debug session but when using QEMU this Just Works.
320365
321- #![no_main]
322- #![no_std]
366+ Let's switch the dependencies:
323367
324- use panic_halt as _;
325-
326- use cortex_m_rt::entry;
327- use cortex_m_semihosting::{debug, hprintln};
328-
329- #[entry]
330- fn main() -> ! {
331- hprintln!("Hello, world!").unwrap();
332-
333- // exit QEMU
334- // NOTE do not run this on hardware; it can corrupt OpenOCD state
335- debug::exit(debug::EXIT_SUCCESS);
336-
337- loop {}
338- }
368+ ``` console
369+ cargo remove defmt-rtt
370+ cargo add defmt-semihosting
339371```
340372
341- This program uses something called semihosting to print text to the * host*
342- console. When using real hardware this requires a debug session but when using
343- QEMU this Just Works.
373+ Open ` src/lib.rs ` and replace ` use defmt_rtt as _; ` by ` use defmt_semihosting as _; `
344374
345- Let's start by compiling the example:
375+ Now we can build the example:
346376
347377``` console
348- cargo build --example hello
378+ cargo build --bin hello
349379```
350380
351381The output binary will be located at
352- ` target/thumbv7m-none-eabi/debug/examples/ hello ` .
382+ ` target/thumbv7m-none-eabi/debug/hello ` .
353383
354- To run this binary on QEMU run the following command:
384+ To run this binary on QEMU, the following command would be usually enough :
355385
356386``` console
357387qemu-system-arm \
358388 -cpu cortex-m3 \
359389 -machine lm3s6965evb \
360390 -nographic \
361391 -semihosting-config enable=on,target=native \
362- -kernel target/thumbv7m-none-eabi/debug/examples/hello
392+ -kernel target/thumbv7m-none-eabi/debug/hello
393+ ```
394+
395+ In our case, since we use defmt, the host will not be able to decode the output. Instead, we
396+ will need a tool by Ferrous Systems named [ ` qemu-run ` ] :
397+
398+ [ `qemu-run` ] : https://github.com/knurling-rs/defmt/tree/main/qemu-run/
399+
400+ ``` console
401+ git clone git@github.com:knurling-rs/defmt.git
402+ cd defmt/qemu-run/
403+ cargo run -- --machine lm3s6965evb ../qemu-rs/target/thumbv7m-none-eabi/debug/hello
363404```
364405
365406``` text
0 commit comments