From 4b075c7f33bd1e82e521095c06180ae7a152670b Mon Sep 17 00:00:00 2001 From: Javier Alvarez Date: Fri, 19 Sep 2025 00:27:43 +0200 Subject: [PATCH] Update book from edition 2018 to 2024 This change updates the Embedonomicon to the new Rust edition 2024. Up until now, most of the book targeted the Rust edition 2018. Edition 2024 brings a set of new features that remove the need for nightly toolchains. Another advantage is that it introduces the readers to the current language changes, like the unsafe `no_mangle` and `export_name` attributes. This commit bundles the following changes: - Update the CI workflow to work with Rust edition 2024 and remove the need for the nightly toolchain. - Adapt all `Cargo.toml` manifests to use edition 2024. - Update all disassemblies and vector table dumps after compiling with the 1.89 toolchain and edition 2024. This also adds instruction addresses to some of the disassemblies, since the text referred to them but they were not present (see the exceptions chapter and the asm chapter). - Add `unsafe` to the `no_mangle`, `export_name` and `link_section` attributes. - Add `unsafe` to `extern` blocks, marking pure Rust functions as `safe`. - Remove use of `core::intrinsics` and use a single `asm!` instruction to trigger UDF. The reasoning behind this is that `core::intrinsics` requires nightly and is only meant to be used by the compiler. The assembly line achieves the same effect. - Make sure all tests are executed (including the exception tests, which were disabled in the past). - Update the singleton example and tests to use `cortex_m::interrupt::mutex` as suggested by an existing TODO. This removes the need for some unsafe. Also use more recent versions of the `cortex-m` and `cortex-m-semihosting` crates. - `rust_begin_unwind` is in the `__rustc` module now. - Update text in most chapters to describe the new changes in edition 2024. A follow up change will be created to move away from `.data` and `.bss` section initialization using Rust code. Most runtime crates have moved away from this due to certain soundness challenges, so the Embedonomicon should also inform about them. --- .github/workflows/ci.yaml | 19 +- ci/asm/app/Cargo.toml | 2 +- ci/asm/app/release.objdump | 33 +- ci/asm/app/release.vector_table | 8 +- ci/asm/app/src/main.rs | 2 +- ci/asm/app2/Cargo.toml | 2 +- ci/asm/rt/Cargo.toml | 2 +- ci/asm/rt/src/lib.rs | 28 +- ci/asm/rt2/Cargo.toml | 2 +- ci/dma/Cargo.toml | 2 +- ci/exceptions/app/Cargo.toml | 2 +- ci/exceptions/app/app.objdump | 615 +++++++++++++-------- ci/exceptions/app/app.vector_table.objdump | 8 +- ci/exceptions/app/src/main.rs | 6 +- ci/exceptions/app2/src/main.rs | 7 +- ci/exceptions/rt/src/lib.rs | 33 +- ci/logging/app/Cargo.toml | 2 +- ci/logging/app/src/main.rs | 4 +- ci/logging/app2/Cargo.toml | 2 +- ci/logging/app2/src/main.rs | 8 +- ci/logging/app3/Cargo.toml | 2 +- ci/logging/app4/Cargo.toml | 2 +- ci/logging/log/Cargo.toml | 2 +- ci/logging/log/src/lib.rs | 4 +- ci/logging/log2/Cargo.toml | 2 +- ci/logging/log2/src/lib.rs | 8 +- ci/main/app/Cargo.toml | 2 +- ci/main/app/app.objdump | 13 +- ci/main/app/src/main.rs | 2 +- ci/main/app3/src/main.rs | 1 + ci/main/app4/Cargo.toml | 2 +- ci/main/app4/src/main.rs | 3 +- ci/main/rt/Cargo.toml | 2 +- ci/main/rt/src/lib.rs | 14 +- ci/main/rt2/src/lib.rs | 25 +- ci/memory-layout/app.text.objdump | 10 +- ci/memory-layout/src/main.rs | 6 +- ci/script.sh | 69 +-- ci/singleton/app/Cargo.toml | 6 +- ci/singleton/app/src/main.rs | 19 +- ci/singleton/log/Cargo.toml | 2 +- ci/singleton/log/src/lib.rs | 12 +- ci/smallest-no-std/Cargo.toml | 2 +- ci/smallest-no-std/app.o.nm | 2 +- ci/smallest-no-std/src/main.rs | 1 + src/asm.md | 8 +- src/dma.md | 11 +- src/exceptions.md | 23 +- src/logging.md | 11 +- src/main.md | 6 +- src/memory-layout.md | 21 +- src/preface.md | 14 +- src/singleton.md | 18 +- src/smallest-no-std.md | 4 +- 54 files changed, 639 insertions(+), 477 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9335302..6c61945 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,17 +10,6 @@ jobs: build: runs-on: ubuntu-latest - continue-on-error: ${{ matrix.experimental || false }} - - strategy: - matrix: - rust: - - 1.63.0 - - nightly-2022-08-12 #Since Rust 1.63.0 came out Aug 11 2022, we use nightly from the day after. - include: - - rust: nightly-2022-08-12 - experimental: true - steps: - uses: actions/checkout@v2 @@ -30,7 +19,7 @@ jobs: pip3 install --user python-dateutil linkchecker - name: Cache installed binaries - uses: actions/cache@v4 + uses: actions/cache@v4 id: cache-bin with: path: ~/cache-bin @@ -57,9 +46,9 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: ${{ matrix.rust }} + toolchain: 1.89.0 override: true - components: rustfmt, clippy, llvm-tools-preview + components: rustfmt, clippy, llvm-tools target: thumbv7m-none-eabi - name: Install arm-none-eabi-gcc and qemu @@ -85,8 +74,6 @@ jobs: - name: Test run: bash ci/script.sh - env: - RUST_VERSION: ${{ matrix.rust }} deploy: runs-on: ubuntu-latest diff --git a/ci/asm/app/Cargo.toml b/ci/asm/app/Cargo.toml index 46537ab..7d28e50 100644 --- a/ci/asm/app/Cargo.toml +++ b/ci/asm/app/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" diff --git a/ci/asm/app/release.objdump b/ci/asm/app/release.objdump index eb476b9..cdfc03c 100644 --- a/ci/asm/app/release.objdump +++ b/ci/asm/app/release.objdump @@ -3,21 +3,26 @@ app: file format elf32-littlearm Disassembly of section .text: -: - b 0x40 @ imm = #-0x4 +00000040 : + 40: push {r7, lr} + 42: mov r7, sp + 44: b 0x44 @ imm = #-0x4 -
: - b 0x42
@ imm = #-0x4 +00000046
: + 46: push {r7, lr} + 48: mov r7, sp + 4a: b 0x4a @ imm = #-0x4 -: - push {r7, lr} - mov r7, sp - bl 0x42
@ imm = #-0xa - trap +0000004c : + 4c: push {r7, lr} + 4e: mov r7, sp + 50: bl 0x46
@ imm = #-0xe -: - b 0x4e @ imm = #-0x4 +00000054 : + 54: push {r7, lr} + 56: mov r7, sp + 58: b 0x58 @ imm = #-0x4 -: - mrs r0, msp - b 0x40 @ imm = #-0x18 +0000005a : + 5a: mrs r0, msp + 5e: b 0x40 @ imm = #-0x22 diff --git a/ci/asm/app/release.vector_table b/ci/asm/app/release.vector_table index 72868d8..fbd536b 100644 --- a/ci/asm/app/release.vector_table +++ b/ci/asm/app/release.vector_table @@ -1,7 +1,7 @@ app: file format elf32-littlearm Contents of section .vector_table: - 0000 00000120 45000000 4f000000 51000000 ... E...O...Q... - 0010 4f000000 4f000000 4f000000 00000000 O...O...O....... - 0020 00000000 00000000 00000000 4f000000 ............O... - 0030 00000000 00000000 4f000000 4f000000 ........O...O... + 0000 00000120 4d000000 55000000 5b000000 ... M...U...[... + 0010 55000000 55000000 55000000 00000000 U...U...U....... + 0020 00000000 00000000 00000000 55000000 ............U... + 0030 00000000 00000000 55000000 55000000 ........U...U... diff --git a/ci/asm/app/src/main.rs b/ci/asm/app/src/main.rs index 6fbffc1..598535b 100644 --- a/ci/asm/app/src/main.rs +++ b/ci/asm/app/src/main.rs @@ -10,7 +10,7 @@ fn main() -> ! { } #[allow(non_snake_case)] -#[no_mangle] +#[unsafe(no_mangle)] pub fn HardFault(_ef: *const u32) -> ! { loop {} } diff --git a/ci/asm/app2/Cargo.toml b/ci/asm/app2/Cargo.toml index 4f9421a..79b5f8f 100644 --- a/ci/asm/app2/Cargo.toml +++ b/ci/asm/app2/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" diff --git a/ci/asm/rt/Cargo.toml b/ci/asm/rt/Cargo.toml index 57f2fcf..3f74f98 100644 --- a/ci/asm/rt/Cargo.toml +++ b/ci/asm/rt/Cargo.toml @@ -1,5 +1,5 @@ [package] -edition = "2018" +edition = "2024" name = "rt" version = "0.1.0" authors = ["Jorge Aparicio "] diff --git a/ci/asm/rt/src/lib.rs b/ci/asm/rt/src/lib.rs index 4cf1774..6614afe 100644 --- a/ci/asm/rt/src/lib.rs +++ b/ci/asm/rt/src/lib.rs @@ -3,11 +3,11 @@ use core::panic::PanicInfo; // use core::ptr; -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn Reset() -> ! { // Omitted to simplify the `objdump` output // Initialize RAM - extern "C" { + unsafe extern "C" { // static mut _sbss: u8; // static mut _ebss: u8; @@ -23,16 +23,16 @@ pub unsafe extern "C" fn Reset() -> ! { // ptr::copy_nonoverlapping(&_sidata as *const u8, &mut _sdata as *mut u8, count); // Call user entry point - extern "Rust" { - fn main() -> !; + unsafe extern "Rust" { + safe fn main() -> !; } main() } // The reset vector, a pointer into the reset handler -#[link_section = ".vector_table.reset_vector"] -#[no_mangle] +#[unsafe(link_section = ".vector_table.reset_vector")] +#[unsafe(no_mangle)] pub static RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; #[panic_handler] @@ -43,14 +43,14 @@ fn panic(_panic: &PanicInfo<'_>) -> ! { #[macro_export] macro_rules! entry { ($path:path) => { - #[export_name = "main"] + #[unsafe(export_name = "main")] pub unsafe fn __main() -> ! { // type check the given path let f: fn() -> ! = $path; f() } - } + }; } pub union Vector { @@ -58,7 +58,7 @@ pub union Vector { handler: unsafe extern "C" fn(), } -extern "C" { +unsafe extern "C" { fn NMI(); fn HardFaultTrampoline(); // <- CHANGED! fn MemManage(); @@ -69,16 +69,14 @@ extern "C" { fn SysTick(); } -#[link_section = ".vector_table.exceptions"] -#[no_mangle] +#[unsafe(link_section = ".vector_table.exceptions")] +#[unsafe(no_mangle)] pub static EXCEPTIONS: [Vector; 14] = [ Vector { handler: NMI }, Vector { handler: HardFaultTrampoline }, // <- CHANGED! Vector { handler: MemManage }, Vector { handler: BusFault }, - Vector { - handler: UsageFault, - }, + Vector { handler: UsageFault }, Vector { reserved: 0 }, Vector { reserved: 0 }, Vector { reserved: 0 }, @@ -90,7 +88,7 @@ pub static EXCEPTIONS: [Vector; 14] = [ Vector { handler: SysTick }, ]; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn DefaultExceptionHandler() { loop {} } diff --git a/ci/asm/rt2/Cargo.toml b/ci/asm/rt2/Cargo.toml index a2c23f7..055fa76 100644 --- a/ci/asm/rt2/Cargo.toml +++ b/ci/asm/rt2/Cargo.toml @@ -1,5 +1,5 @@ [package] -edition = "2018" +edition = "2024" name = "rt" version = "0.1.0" authors = ["Jorge Aparicio "] diff --git a/ci/dma/Cargo.toml b/ci/dma/Cargo.toml index d661cd0..e29bf3f 100644 --- a/ci/dma/Cargo.toml +++ b/ci/dma/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "shared" version = "0.1.0" diff --git a/ci/exceptions/app/Cargo.toml b/ci/exceptions/app/Cargo.toml index 46537ab..7d28e50 100644 --- a/ci/exceptions/app/Cargo.toml +++ b/ci/exceptions/app/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" diff --git a/ci/exceptions/app/app.objdump b/ci/exceptions/app/app.objdump index 39bcfc6..0c104c2 100644 --- a/ci/exceptions/app/app.objdump +++ b/ci/exceptions/app/app.objdump @@ -3,231 +3,400 @@ app: file format elf32-littlearm Disassembly of section .text: -
: - trap - trap +00000040
: + 40: push {r7, lr} + 42: mov r7, sp + 44: udf #0x0 + 46: trap -: - push {r7, lr} - mov r7, sp - movw r1, #0x0 - movw r0, #0x0 - movt r1, #0x2000 - movt r0, #0x2000 - subs r1, r1, r0 - bl 0x9c <__aeabi_memclr> @ imm = #0x3e - movw r1, #0x0 - movw r0, #0x0 - movt r1, #0x2000 - movt r0, #0x2000 - subs r2, r1, r0 - movw r1, #0x282 - movt r1, #0x0 - bl 0x84 <__aeabi_memcpy> @ imm = #0x8 - bl 0x40
@ imm = #-0x40 - trap +00000048 : + 48: push {r7, lr} + 4a: mov r7, sp + 4c: movw r1, #0x0 + 50: movw r0, #0x0 + 54: movt r1, #0x2000 + 58: movt r0, #0x2000 + 5c: subs r1, r1, r0 + 5e: bl 0x8a <__aeabi_memclr> @ imm = #0x28 + 62: movw r1, #0x0 + 66: movw r0, #0x0 + 6a: movt r1, #0x2000 + 6e: movt r0, #0x2000 + 72: subs r2, r1, r0 + 74: movw r1, #0x44e + 78: movt r1, #0x0 + 7c: bl 0x15a <__aeabi_memcpy> @ imm = #0xda + 80: bl 0x40
@ imm = #-0x44 -: - b 0x82 @ imm = #-0x4 +00000084 : + 84: push {r7, lr} + 86: mov r7, sp + 88: b 0x88 @ imm = #-0x4 -<__aeabi_memcpy>: - b.w 0x88 @ imm = #0x0 +0000008a <__aeabi_memclr>: + 8a: push {r4, r5, r7, lr} + 8c: add r7, sp, #0x8 + 8e: cmp r1, #0x10 + 90: blo 0x112 <__aeabi_memclr+0x88> @ imm = #0x7e + 92: rsbs r2, r0, #0 + 94: and r5, r2, #0x3 + 98: adds r2, r0, r5 + 9a: cmp r0, r2 + 9c: bhs 0xe0 <__aeabi_memclr+0x56> @ imm = #0x40 + 9e: sub.w r12, r5, #0x1 + a2: cbz r5, 0xc8 <__aeabi_memclr+0x3e> @ imm = #0x22 + a4: movs r3, #0x0 + a6: mov lr, r0 + a8: strb r3, [lr], #1 + ac: cmp r5, #0x1 + ae: beq 0xc0 <__aeabi_memclr+0x36> @ imm = #0xe + b0: strb r3, [r0, #0x1] + b2: cmp r5, #0x2 + b4: itte ne + b6: strbne r3, [r0, #0x2] + b8: addne.w lr, r0, #0x3 + bc: addeq.w lr, r0, #0x2 + c0: cmp.w r12, #0x3 + c4: bhs 0xd0 <__aeabi_memclr+0x46> @ imm = #0x8 + c6: b 0xe0 <__aeabi_memclr+0x56> @ imm = #0x16 + c8: mov lr, r0 + ca: cmp.w r12, #0x3 + ce: blo 0xe0 <__aeabi_memclr+0x56> @ imm = #0xe + d0: sub.w r0, lr, #0x4 + d4: movs r3, #0x0 + d6: str r3, [r0, #4]! + da: adds r4, r0, #0x4 + dc: cmp r4, r2 + de: bne 0xd6 <__aeabi_memclr+0x4c> @ imm = #-0xc + e0: subs r1, r1, r5 + e2: bic r0, r1, #0x3 + e6: add r0, r2 + e8: cmp r2, r0 + ea: bhs 0x10e <__aeabi_memclr+0x84> @ imm = #0x20 + ec: movs r3, #0x0 + ee: str r3, [r2], #4 + f2: cmp r2, r0 + f4: bhs 0x10e <__aeabi_memclr+0x84> @ imm = #0x16 + f6: str r3, [r2], #4 + fa: cmp r2, r0 + fc: itt lo + fe: strlo r3, [r2], #4 + 102: cmplo r2, r0 + 104: bhs 0x10e <__aeabi_memclr+0x84> @ imm = #0x6 + 106: str r3, [r2], #4 + 10a: cmp r2, r0 + 10c: blo 0xee <__aeabi_memclr+0x64> @ imm = #-0x22 + 10e: and r1, r1, #0x3 + 112: adds r2, r0, r1 + 114: cmp r0, r2 + 116: bhs 0x158 <__aeabi_memclr+0xce> @ imm = #0x3e + 118: subs r3, r1, #0x1 + 11a: ands r4, r1, #0x3 + 11e: beq 0x13a <__aeabi_memclr+0xb0> @ imm = #0x18 + 120: mov.w r12, #0x0 + 124: mov r1, r0 + 126: strb r12, [r1], #1 + 12a: cmp r4, #0x1 + 12c: beq 0x144 <__aeabi_memclr+0xba> @ imm = #0x14 + 12e: cmp r4, #0x2 + 130: strb.w r12, [r0, #0x1] + 134: bne 0x13e <__aeabi_memclr+0xb4> @ imm = #0x6 + 136: adds r1, r0, #0x2 + 138: b 0x144 <__aeabi_memclr+0xba> @ imm = #0x8 + 13a: mov r1, r0 + 13c: b 0x144 <__aeabi_memclr+0xba> @ imm = #0x4 + 13e: movs r1, #0x0 + 140: strb r1, [r0, #0x2] + 142: adds r1, r0, #0x3 + 144: cmp r3, #0x3 + 146: it lo + 148: poplo {r4, r5, r7, pc} + 14a: subs r0, r1, #0x4 + 14c: movs r1, #0x0 + 14e: str r1, [r0, #4]! + 152: adds r3, r0, #0x4 + 154: cmp r3, r2 + 156: bne 0x14e <__aeabi_memclr+0xc4> @ imm = #-0xc + 158: pop {r4, r5, r7, pc} -: - b.w 0xa0 @ imm = #0x14 +0000015a <__aeabi_memcpy>: + 15a: push {r7, lr} + 15c: mov r7, sp + 15e: pop.w {r7, lr} + 162: b.w 0x166 @ imm = #0x0 -: - mov r3, r1 - mov r1, r2 - mov r2, r3 - b.w 0x1e4 @ imm = #0x14e - -: - movs r2, #0x0 - b.w 0x8c @ imm = #-0x10 - -<__aeabi_memclr>: - b.w 0x96 @ imm = #-0xa - -: - push {r4, r5, r6, r7, lr} - add r7, sp, #0xc - push.w {r8, r9, r10} - cmp r2, #0xf - bls 0x170 @ imm = #0xc2 - rsbs r3, r0, #0 - ands r4, r3, #0x3 - add.w r12, r0, r4 - beq 0xe6 @ imm = #0x2c - mov r3, r0 - mov r6, r1 - ldrb r5, [r6] - strb r5, [r3], #1 - cmp r3, r12 - bhs 0xe6 @ imm = #0x1e - ldrb r5, [r6, #0x1] - strb r5, [r3], #1 - cmp r3, r12 - ittt lo - ldrblo r5, [r6, #0x2] - strblo r5, [r3], #1 - cmplo r3, r12 - bhs 0xe6 @ imm = #0xa - ldrb r5, [r6, #0x3] - adds r6, #0x4 - strb r5, [r3], #1 - cmp r3, r12 - blo 0xbc @ imm = #-0x2c - sub.w lr, r2, r4 - add.w r8, r1, r4 - bic r9, lr, #0x3 - ands r1, r8, #0x3 - add.w r3, r12, r9 - beq 0x176 @ imm = #0x78 - cmp.w r9, #0x1 - blt 0x1a8 @ imm = #0xa4 - bic r6, r8, #0x3 - lsl.w r10, r1, #0x3 - add.w r5, r6, #0x8 - ldr r1, [r6] - rsb.w r6, r10, #0x0 - and r6, r6, #0x18 - lsr.w r2, r1, r10 - ldr r1, [r5, #-4] - lsl.w r4, r1, r6 - orrs r2, r4 - str r2, [r12], #4 - cmp r12, r3 - bhs 0x1a8 @ imm = #0x78 - lsr.w r2, r1, r10 - ldr r1, [r5] - lsl.w r4, r1, r6 - orrs r2, r4 - str r2, [r12], #4 - cmp r12, r3 - itttt lo - lsrlo.w r2, r1, r10 - ldrlo r1, [r5, #0x4] - lsllo.w r4, r1, r6 - orrlo r2, r4 - itt lo - strlo r2, [r12], #4 - cmplo r12, r3 - bhs 0x1a8 @ imm = #0x4e - lsr.w r2, r1, r10 - ldr r1, [r5, #0x8] - adds r5, #0x10 - lsl.w r4, r1, r6 - orrs r2, r4 - str r2, [r12], #4 - cmp r12, r3 - blo 0x118 @ imm = #-0x58 - b 0x1a8 @ imm = #0x36 - mov r3, r0 - cbnz r2, 0x1b2 @ imm = #0x3c - b 0x1de @ imm = #0x66 - cmp.w r9, #0x1 - blt 0x1a8 @ imm = #0x2a - mov r4, r8 - ldr r1, [r4] - str r1, [r12], #4 - cmp r12, r3 - bhs 0x1a8 @ imm = #0x1e - ldr r1, [r4, #0x4] - str r1, [r12], #4 - cmp r12, r3 - ittt lo - ldrlo r1, [r4, #0x8] - strlo r1, [r12], #4 - cmplo r12, r3 - bhs 0x1a8 @ imm = #0xa - ldr r1, [r4, #0xc] - adds r4, #0x10 - str r1, [r12], #4 - cmp r12, r3 - blo 0x17e @ imm = #-0x2c - add.w r1, r8, r9 - and r2, lr, #0x3 - cbz r2, 0x1de @ imm = #0x2a - add r2, r3 - ldrb r6, [r1] - strb r6, [r3], #1 - cmp r3, r2 - bhs 0x1de @ imm = #0x1e - ldrb r6, [r1, #0x1] - strb r6, [r3], #1 - cmp r3, r2 - ittt lo - ldrblo r6, [r1, #0x2] - strblo r6, [r3], #1 - cmplo r3, r2 - bhs 0x1de @ imm = #0xa - ldrb r6, [r1, #0x3] - adds r1, #0x4 - strb r6, [r3], #1 - cmp r3, r2 - blo 0x1b4 @ imm = #-0x2c - pop.w {r8, r9, r10} - pop {r4, r5, r6, r7, pc} - -: - push {r4, r6, r7, lr} - add r7, sp, #0x8 - cmp r2, #0xf - bls 0x25a @ imm = #0x6c - rsbs r3, r0, #0 - ands lr, r3, #0x3 - add.w r12, r0, lr - beq 0x21a @ imm = #0x20 - mov r3, r0 - strb r1, [r3], #1 - cmp r3, r12 - bhs 0x21a @ imm = #0x16 - strb r1, [r3], #1 - cmp r3, r12 - itt lo - strblo r1, [r3], #1 - cmplo r3, r12 - bhs 0x21a @ imm = #0x6 - strb r1, [r3], #1 - cmp r3, r12 - blo 0x1fa @ imm = #-0x22 - sub.w lr, r2, lr - bic r2, lr, #0x3 - add.w r3, r12, r2 - cmp r2, #0x0 - ble 0x252 @ imm = #0x26 - uxtb r2, r1 - mov.w r4, #0x1010101 - muls r2, r4, r2 - str r2, [r12], #4 - cmp r12, r3 - bhs 0x252 @ imm = #0x16 - str r2, [r12], #4 - cmp r12, r3 - itt lo - strlo r2, [r12], #4 - cmplo r12, r3 - bhs 0x252 @ imm = #0x6 - str r2, [r12], #4 - cmp r12, r3 - blo 0x232 @ imm = #-0x22 - and r2, lr, #0x3 - cbnz r2, 0x25e @ imm = #0x4 - b 0x280 @ imm = #0x24 - mov r3, r0 - cbz r2, 0x280 @ imm = #0x20 - add r2, r3 - strb r1, [r3], #1 - cmp r3, r2 - bhs 0x280 @ imm = #0x16 - strb r1, [r3], #1 - cmp r3, r2 - itt lo - strblo r1, [r3], #1 - cmplo r3, r2 - bhs 0x280 @ imm = #0x6 - strb r1, [r3], #1 - cmp r3, r2 - blo 0x260 @ imm = #-0x22 - pop {r4, r6, r7, pc} +00000166 : + 166: push {r4, r5, r6, r7, lr} + 168: add r7, sp, #0xc + 16a: push.w {r8, r9, r10, r11} + 16e: sub sp, #0x2c + 170: cmp r2, #0x10 + 172: blo 0x1b2 @ imm = #0x3c + 174: rsbs r3, r0, #0 + 176: and r8, r3, #0x3 + 17a: add.w r3, r0, r8 + 17e: cmp r0, r3 + 180: bhs 0x1ea @ imm = #0x66 + 182: sub.w r12, r8, #0x1 + 186: cmp.w r8, #0x0 + 18a: mov r6, r0 + 18c: mov r4, r1 + 18e: beq 0x1c6 @ imm = #0x34 + 190: mov r4, r1 + 192: mov r6, r0 + 194: ldrb lr, [r4], #1 + 198: cmp.w r8, #0x1 + 19c: strb lr, [r6], #1 + 1a0: beq 0x1c6 @ imm = #0x22 + 1a2: ldrb r6, [r1, #0x1] + 1a4: cmp.w r8, #0x2 + 1a8: strb r6, [r0, #0x1] + 1aa: bne 0x1be @ imm = #0x10 + 1ac: adds r4, r1, #0x2 + 1ae: adds r6, r0, #0x2 + 1b0: b 0x1c6 @ imm = #0x12 + 1b2: mov r12, r0 + 1b4: add.w r3, r12, r2 + 1b8: cmp r12, r3 + 1ba: blo 0x23e @ imm = #0x80 + 1bc: b 0x298 @ imm = #0xd8 + 1be: ldrb r6, [r1, #0x2] + 1c0: adds r4, r1, #0x3 + 1c2: strb r6, [r0, #0x2] + 1c4: adds r6, r0, #0x3 + 1c6: cmp.w r12, #0x3 + 1ca: blo 0x1ea @ imm = #0x1c + 1cc: subs r4, #0x4 + 1ce: subs r6, #0x4 + 1d0: ldrb r5, [r4, #4]! + 1d4: strb r5, [r6, #4]! + 1d8: ldrb r5, [r4, #0x1] + 1da: strb r5, [r6, #0x1] + 1dc: ldrb r5, [r4, #0x2] + 1de: strb r5, [r6, #0x2] + 1e0: ldrb r5, [r4, #0x3] + 1e2: strb r5, [r6, #0x3] + 1e4: adds r5, r6, #0x4 + 1e6: cmp r5, r3 + 1e8: bne 0x1d0 @ imm = #-0x1c + 1ea: sub.w lr, r2, r8 + 1ee: add.w r4, r1, r8 + 1f2: bic r2, lr, #0x3 + 1f6: ands r6, r4, #0x3 + 1fa: add.w r12, r3, r2 + 1fe: bne 0x2b4 @ imm = #0xb2 + 200: cmp r3, r12 + 202: bhs 0x230 @ imm = #0x2a + 204: mov r1, r4 + 206: ldr r5, [r1] + 208: str r5, [r3], #4 + 20c: cmp r3, r12 + 20e: bhs 0x230 @ imm = #0x1e + 210: ldr r5, [r1, #0x4] + 212: str r5, [r3], #4 + 216: cmp r3, r12 + 218: ittt lo + 21a: ldrlo r5, [r1, #0x8] + 21c: strlo r5, [r3], #4 + 220: cmplo r3, r12 + 222: bhs 0x230 @ imm = #0xa + 224: ldr r5, [r1, #0xc] + 226: adds r1, #0x10 + 228: str r5, [r3], #4 + 22c: cmp r3, r12 + 22e: blo 0x206 @ imm = #-0x2c + 230: adds r1, r4, r2 + 232: and r2, lr, #0x3 + 236: add.w r3, r12, r2 + 23a: cmp r12, r3 + 23c: bhs 0x298 @ imm = #0x58 + 23e: sub.w lr, r2, #0x1 + 242: ands r4, r2, #0x3 + 246: beq 0x270 @ imm = #0x26 + 248: mov r2, r1 + 24a: mov r5, r12 + 24c: ldrb r6, [r2], #1 + 250: cmp r4, #0x1 + 252: strb r6, [r5], #1 + 256: beq 0x274 @ imm = #0x1a + 258: ldrb r2, [r1, #0x1] + 25a: cmp r4, #0x2 + 25c: strb.w r2, [r12, #0x1] + 260: bne 0x2a0 @ imm = #0x3c + 262: adds r2, r1, #0x2 + 264: add.w r5, r12, #0x2 + 268: cmp.w lr, #0x3 + 26c: bhs 0x27a @ imm = #0xa + 26e: b 0x298 @ imm = #0x26 + 270: mov r5, r12 + 272: mov r2, r1 + 274: cmp.w lr, #0x3 + 278: blo 0x298 @ imm = #0x1c + 27a: subs r1, r2, #0x4 + 27c: subs r2, r5, #0x4 + 27e: ldrb r6, [r1, #4]! + 282: strb r6, [r2, #4]! + 286: ldrb r6, [r1, #0x1] + 288: strb r6, [r2, #0x1] + 28a: ldrb r6, [r1, #0x2] + 28c: strb r6, [r2, #0x2] + 28e: ldrb r6, [r1, #0x3] + 290: strb r6, [r2, #0x3] + 292: adds r6, r2, #0x4 + 294: cmp r6, r3 + 296: bne 0x27e @ imm = #-0x1c + 298: add sp, #0x2c + 29a: pop.w {r8, r9, r10, r11} + 29e: pop {r4, r5, r6, r7, pc} + 2a0: ldrb r2, [r1, #0x2] + 2a2: add.w r5, r12, #0x3 + 2a6: strb.w r2, [r12, #0x2] + 2aa: adds r2, r1, #0x3 + 2ac: cmp.w lr, #0x3 + 2b0: bhs 0x27a @ imm = #-0x3a + 2b2: b 0x298 @ imm = #-0x1e + 2b4: mov.w r10, #0x0 + 2b8: rsb.w r11, r6, #0x4 + 2bc: add r5, sp, #0x28 + 2be: str.w r10, [sp, #0x28] + 2c2: add.w r9, r5, r6 + 2c6: lsls.w r5, r11, #0x1f + 2ca: ittt ne + 2cc: ldrbne r5, [r4] + 2ce: strbne.w r5, [r9] + 2d2: movne.w r10, #0x1 + 2d6: subs r5, r4, r6 + 2d8: str r5, [sp, #0x1c] + 2da: lsls r5, r6, #0x3 + 2dc: str r5, [sp, #0x14] + 2de: lsls.w r5, r11, #0x1e + 2e2: itt mi + 2e4: ldrhmi.w r5, [r4, r10] + 2e8: strhmi.w r5, [r9, r10] + 2ec: adds r5, r3, #0x4 + 2ee: ldr.w r10, [sp, #0x28] + 2f2: cmp r5, r12 + 2f4: ldr r5, [sp, #0x14] + 2f6: rsb.w r11, r5, #0x0 + 2fa: bhs 0x3ec @ imm = #0xee + 2fc: rsbs r3, r6, #0 + 2fe: mov r9, r10 + 300: add r1, r3 + 302: and r3, r11, #0x18 + 306: str.w r11, [sp] + 30a: mov r10, r0 + 30c: mov r11, r1 + 30e: str r3, [sp, #0x1c] + 310: add.w r3, r11, r8 + 314: str r3, [sp, #0x18] + 316: lsr.w r9, r9, r5 + 31a: str.w r11, [sp, #0xc] + 31e: ldr r1, [r3, #0x4] + 320: ldr r3, [sp, #0x1c] + 322: str.w r10, [sp, #0x8] + 326: lsl.w r3, r1, r3 + 32a: orr.w r3, r3, r9 + 32e: add.w r9, r10, r8 + 332: mov r11, r9 + 334: str r3, [r11], #8 + 338: cmp r11, r12 + 33a: bhs 0x3c4 @ imm = #0x86 + 33c: lsr.w r3, r1, r5 + 340: str r3, [sp, #0x10] + 342: ldr r3, [sp, #0x18] + 344: ldr.w r10, [sp, #0x10] + 348: ldr r1, [r3, #0x8] + 34a: ldr r3, [sp, #0x1c] + 34c: lsl.w r3, r1, r3 + 350: orr.w r3, r3, r10 + 354: str.w r3, [r9, #0x4] + 358: add.w r3, r9, #0xc + 35c: cmp r3, r12 + 35e: bhs 0x3d0 @ imm = #0x6e + 360: lsrs r1, r5 + 362: ldr r5, [sp, #0x1c] + 364: str r1, [sp, #0x10] + 366: ldr r1, [sp, #0x18] + 368: ldr.w r10, [sp, #0x10] + 36c: ldr r1, [r1, #0xc] + 36e: str r1, [sp, #0x4] + 370: lsl.w r5, r1, r5 + 374: add.w r1, r9, #0x10 + 378: cmp r1, r12 + 37a: orr.w r5, r5, r10 + 37e: str.w r5, [r11] + 382: bhs 0x3e2 @ imm = #0x5c + 384: ldr r1, [sp, #0x14] + 386: ldr r5, [sp, #0x4] + 388: ldr.w r10, [sp, #0x8] + 38c: ldr.w r11, [sp, #0xc] + 390: lsr.w r1, r5, r1 + 394: ldr r5, [sp, #0x18] + 396: add.w r10, r10, #0x10 + 39a: add.w r11, r11, #0x10 + 39e: ldr.w r9, [r5, #0x10] + 3a2: ldr r5, [sp, #0x1c] + 3a4: lsl.w r5, r9, r5 + 3a8: orrs r1, r5 + 3aa: str r1, [r3] + 3ac: add.w r3, r10, r8 + 3b0: ldr r5, [sp, #0x14] + 3b2: adds r1, r3, #0x4 + 3b4: cmp r1, r12 + 3b6: blo 0x310 @ imm = #-0xaa + 3b8: add.w r1, r11, r8 + 3bc: ldr.w r11, [sp] + 3c0: mov r10, r9 + 3c2: b 0x3ea @ imm = #0x24 + 3c4: ldr r3, [sp, #0x18] + 3c6: adds r3, #0x4 + 3c8: str r3, [sp, #0x1c] + 3ca: add.w r3, r9, #0x4 + 3ce: b 0x3da @ imm = #0x8 + 3d0: ldr r3, [sp, #0x18] + 3d2: adds r3, #0x8 + 3d4: str r3, [sp, #0x1c] + 3d6: add.w r3, r9, #0x8 + 3da: ldr.w r11, [sp] + 3de: mov r10, r1 + 3e0: b 0x3ec @ imm = #0x8 + 3e2: ldr r1, [sp, #0x18] + 3e4: ldrd r11, r10, [sp] + 3e8: adds r1, #0xc + 3ea: str r1, [sp, #0x1c] + 3ec: movs r1, #0x0 + 3ee: cmp r6, #0x1 + 3f0: strb.w r1, [sp, #0x24] + 3f4: strb r1, [r7, #-38] + 3f8: bne 0x406 @ imm = #0xa + 3fa: add.w r8, sp, #0x24 + 3fe: mov.w r9, #0x0 + 402: movs r5, #0x0 + 404: b 0x41a @ imm = #0x12 + 406: ldr r5, [sp, #0x1c] + 408: sub.w r8, r7, #0x26 + 40c: ldrb r1, [r5, #0x4] + 40e: ldrb r5, [r5, #0x5] + 410: strb.w r1, [sp, #0x24] + 414: lsl.w r9, r5, #0x8 + 418: movs r5, #0x2 + 41a: lsls r6, r4, #0x1f + 41c: bne 0x422 @ imm = #0x2 + 41e: movs r5, #0x0 + 420: b 0x436 @ imm = #0x12 + 422: ldr r1, [sp, #0x1c] + 424: adds r1, #0x4 + 426: ldrb r1, [r1, r5] + 428: strb.w r1, [r8] + 42c: ldrb r1, [r7, #-38] + 430: lsls r5, r1, #0x10 + 432: ldrb.w r1, [sp, #0x24] + 436: orr.w r5, r5, r9 + 43a: ldr r6, [sp, #0x14] + 43c: orrs r1, r5 + 43e: and r5, r11, #0x18 + 442: lsls r1, r5 + 444: lsr.w r6, r10, r6 + 448: orrs r1, r6 + 44a: str r1, [r3] + 44c: b 0x230 @ imm = #-0x220 diff --git a/ci/exceptions/app/app.vector_table.objdump b/ci/exceptions/app/app.vector_table.objdump index 74b86a1..e890bcb 100644 --- a/ci/exceptions/app/app.vector_table.objdump +++ b/ci/exceptions/app/app.vector_table.objdump @@ -1,7 +1,7 @@ app: file format elf32-littlearm Contents of section .vector_table: - 0000 00000120 45000000 83000000 83000000 ... E........... - 0010 83000000 83000000 83000000 00000000 ................ - 0020 00000000 00000000 00000000 83000000 ................ - 0030 00000000 00000000 83000000 83000000 ................ + 0000 00000120 49000000 85000000 85000000 ... I........... + 0010 85000000 85000000 85000000 00000000 ................ + 0020 00000000 00000000 00000000 85000000 ................ + 0030 00000000 00000000 85000000 85000000 ................ diff --git a/ci/exceptions/app/src/main.rs b/ci/exceptions/app/src/main.rs index c669e44..0913fd5 100644 --- a/ci/exceptions/app/src/main.rs +++ b/ci/exceptions/app/src/main.rs @@ -1,14 +1,12 @@ -#![feature(core_intrinsics)] #![no_main] #![no_std] -use core::intrinsics; - +use core::arch::asm; use rt::entry; entry!(main); fn main() -> ! { // this executes the undefined instruction (UDF) and causes a HardFault exception - intrinsics::abort() + unsafe { asm!("udf #0", options(noreturn)) }; } diff --git a/ci/exceptions/app2/src/main.rs b/ci/exceptions/app2/src/main.rs index 8b10a07..7f3feb7 100644 --- a/ci/exceptions/app2/src/main.rs +++ b/ci/exceptions/app2/src/main.rs @@ -1,18 +1,17 @@ -#![feature(core_intrinsics)] #![no_main] #![no_std] -use core::intrinsics; +use core::arch::asm; use rt::entry; entry!(main); fn main() -> ! { - intrinsics::abort() + unsafe { asm!("udf #0", options(noreturn)) }; } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn HardFault() -> ! { // do something interesting here loop {} diff --git a/ci/exceptions/rt/src/lib.rs b/ci/exceptions/rt/src/lib.rs index 85059a2..5ca4f30 100644 --- a/ci/exceptions/rt/src/lib.rs +++ b/ci/exceptions/rt/src/lib.rs @@ -3,11 +3,12 @@ use core::panic::PanicInfo; use core::ptr; -#[no_mangle] +#[unsafe(no_mangle)] +#[allow(static_mut_refs)] pub unsafe extern "C" fn Reset() -> ! { // NEW! // Initialize RAM - extern "C" { + unsafe extern "C" { static mut _sbss: u8; static mut _ebss: u8; @@ -16,23 +17,23 @@ pub unsafe extern "C" fn Reset() -> ! { static _sidata: u8; } - let count = &_ebss as *const u8 as usize - &_sbss as *const u8 as usize; - ptr::write_bytes(&mut _sbss as *mut u8, 0, count); + let count = unsafe { &_ebss as *const u8 as usize - &_sbss as *const u8 as usize }; + unsafe { ptr::write_bytes(&mut _sbss as *mut u8, 0, count) }; - let count = &_edata as *const u8 as usize - &_sdata as *const u8 as usize; - ptr::copy_nonoverlapping(&_sidata as *const u8, &mut _sdata as *mut u8, count); + let count = unsafe { &_edata as *const u8 as usize - &_sdata as *const u8 as usize }; + unsafe { ptr::copy_nonoverlapping(&_sidata as *const u8, &mut _sdata as *mut u8, count) }; // Call user entry point - extern "Rust" { - fn main() -> !; + unsafe extern "Rust" { + safe fn main() -> !; } main() } // The reset vector, a pointer into the reset handler -#[link_section = ".vector_table.reset_vector"] -#[no_mangle] +#[unsafe(link_section = ".vector_table.reset_vector")] +#[unsafe(no_mangle)] pub static RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; #[panic_handler] @@ -43,14 +44,14 @@ fn panic(_panic: &PanicInfo<'_>) -> ! { #[macro_export] macro_rules! entry { ($path:path) => { - #[export_name = "main"] + #[unsafe(export_name = "main")] pub unsafe fn __main() -> ! { // type check the given path let f: fn() -> ! = $path; f() } - } + }; } pub union Vector { @@ -58,7 +59,7 @@ pub union Vector { handler: unsafe extern "C" fn(), } -extern "C" { +unsafe extern "C" { fn NMI(); fn HardFault(); fn MemManage(); @@ -69,8 +70,8 @@ extern "C" { fn SysTick(); } -#[link_section = ".vector_table.exceptions"] -#[no_mangle] +#[unsafe(link_section = ".vector_table.exceptions")] +#[unsafe(no_mangle)] pub static EXCEPTIONS: [Vector; 14] = [ Vector { handler: NMI }, Vector { handler: HardFault }, @@ -90,7 +91,7 @@ pub static EXCEPTIONS: [Vector; 14] = [ Vector { handler: SysTick }, ]; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn DefaultExceptionHandler() { loop {} } diff --git a/ci/logging/app/Cargo.toml b/ci/logging/app/Cargo.toml index 3519b40..06f118b 100644 --- a/ci/logging/app/Cargo.toml +++ b/ci/logging/app/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" diff --git a/ci/logging/app/src/main.rs b/ci/logging/app/src/main.rs index 2449154..a7f7b25 100644 --- a/ci/logging/app/src/main.rs +++ b/ci/logging/app/src/main.rs @@ -11,12 +11,12 @@ entry!(main); fn main() -> ! { let mut hstdout = hio::hstdout().unwrap(); - #[export_name = "Hello, world!"] + #[unsafe(export_name = "Hello, world!")] static A: u8 = 0; let _ = writeln!(hstdout, "{:#x}", &A as *const u8 as usize); - #[export_name = "Goodbye"] + #[unsafe(export_name = "Goodbye")] static B: u8 = 0; let _ = writeln!(hstdout, "{:#x}", &B as *const u8 as usize); diff --git a/ci/logging/app2/Cargo.toml b/ci/logging/app2/Cargo.toml index 3519b40..06f118b 100644 --- a/ci/logging/app2/Cargo.toml +++ b/ci/logging/app2/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" diff --git a/ci/logging/app2/src/main.rs b/ci/logging/app2/src/main.rs index 3b00eb6..0bc9605 100644 --- a/ci/logging/app2/src/main.rs +++ b/ci/logging/app2/src/main.rs @@ -10,15 +10,15 @@ entry!(main); fn main() -> ! { let mut hstdout = hio::hstdout().unwrap(); - #[export_name = "Hello, world!"] - #[link_section = ".log"] // <- NEW! + #[unsafe(export_name = "Hello, world!")] + #[unsafe(link_section = ".log")] // <- NEW! static A: u8 = 0; let address = &A as *const u8 as usize as u8; hstdout.write_all(&[address]).unwrap(); // <- CHANGED! - #[export_name = "Goodbye"] - #[link_section = ".log"] // <- NEW! + #[unsafe(export_name = "Goodbye")] + #[unsafe(link_section = ".log")] // <- NEW! static B: u8 = 0; let address = &B as *const u8 as usize as u8; diff --git a/ci/logging/app3/Cargo.toml b/ci/logging/app3/Cargo.toml index f23ea58..010ebbb 100644 --- a/ci/logging/app3/Cargo.toml +++ b/ci/logging/app3/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" diff --git a/ci/logging/app4/Cargo.toml b/ci/logging/app4/Cargo.toml index 44b41ca..59f4264 100644 --- a/ci/logging/app4/Cargo.toml +++ b/ci/logging/app4/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" diff --git a/ci/logging/log/Cargo.toml b/ci/logging/log/Cargo.toml index e67d724..a0260fb 100644 --- a/ci/logging/log/Cargo.toml +++ b/ci/logging/log/Cargo.toml @@ -2,6 +2,6 @@ name = "log" version = "0.1.0" authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" [dependencies] diff --git a/ci/logging/log/src/lib.rs b/ci/logging/log/src/lib.rs index 78afdd0..b6202df 100644 --- a/ci/logging/log/src/lib.rs +++ b/ci/logging/log/src/lib.rs @@ -9,8 +9,8 @@ pub trait Log { #[macro_export] macro_rules! log { ($logger:expr, $string:expr) => {{ - #[export_name = $string] - #[link_section = ".log"] + #[unsafe(export_name = $string)] + #[unsafe(link_section = ".log")] static SYMBOL: u8 = 0; $crate::Log::log(&mut $logger, &SYMBOL as *const u8 as usize as u8) diff --git a/ci/logging/log2/Cargo.toml b/ci/logging/log2/Cargo.toml index e67d724..a0260fb 100644 --- a/ci/logging/log2/Cargo.toml +++ b/ci/logging/log2/Cargo.toml @@ -2,6 +2,6 @@ name = "log" version = "0.1.0" authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" [dependencies] diff --git a/ci/logging/log2/src/lib.rs b/ci/logging/log2/src/lib.rs index b67d96b..d5f5e3a 100644 --- a/ci/logging/log2/src/lib.rs +++ b/ci/logging/log2/src/lib.rs @@ -10,8 +10,8 @@ pub trait Log { #[macro_export] macro_rules! error { ($logger:expr, $string:expr) => {{ - #[export_name = $string] - #[link_section = ".log.error"] // <- CHANGED! + #[unsafe(export_name = $string)] + #[unsafe(link_section = ".log.error")] // <- CHANGED! static SYMBOL: u8 = 0; $crate::Log::log(&mut $logger, &SYMBOL as *const u8 as usize as u8) @@ -22,8 +22,8 @@ macro_rules! error { #[macro_export] macro_rules! warn { ($logger:expr, $string:expr) => {{ - #[export_name = $string] - #[link_section = ".log.warning"] // <- CHANGED! + #[unsafe(export_name = $string)] + #[unsafe(link_section = ".log.warning")] // <- CHANGED! static SYMBOL: u8 = 0; $crate::Log::log(&mut $logger, &SYMBOL as *const u8 as usize as u8) diff --git a/ci/main/app/Cargo.toml b/ci/main/app/Cargo.toml index 3e01231..dad0d9b 100644 --- a/ci/main/app/Cargo.toml +++ b/ci/main/app/Cargo.toml @@ -1,5 +1,5 @@ [package] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" authors = ["Jorge Aparicio "] diff --git a/ci/main/app/app.objdump b/ci/main/app/app.objdump index b4c1c79..5e6479e 100644 --- a/ci/main/app/app.objdump +++ b/ci/main/app/app.objdump @@ -4,14 +4,15 @@ app: file format elf32-littlearm Disassembly of section .text:
: - sub sp, #4 - movs r0, #42 + push {r7, lr} + mov r7, sp + sub sp, #0x4 + movs r0, #0x2a str r0, [sp] - b 0x10 @ imm = #-2 - b 0x10 @ imm = #-4 + b 0x14 @ imm = #-0x2 + b 0x14 @ imm = #-0x4 : push {r7, lr} mov r7, sp - bl 0x8
@ imm = #-18 - trap + bl 0x8
@ imm = #-0x16 diff --git a/ci/main/app/src/main.rs b/ci/main/app/src/main.rs index f252abf..f3b5750 100644 --- a/ci/main/app/src/main.rs +++ b/ci/main/app/src/main.rs @@ -3,7 +3,7 @@ extern crate rt; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> ! { let _x = 42; diff --git a/ci/main/app3/src/main.rs b/ci/main/app3/src/main.rs index 622e0f3..1aba5de 100644 --- a/ci/main/app3/src/main.rs +++ b/ci/main/app3/src/main.rs @@ -9,6 +9,7 @@ static RODATA: &[u8] = b"Hello, world!"; static mut BSS: u8 = 0; static mut DATA: u16 = 1; +#[allow(static_mut_refs)] fn main() -> ! { let _x = RODATA; let _y = unsafe { &BSS }; diff --git a/ci/main/app4/Cargo.toml b/ci/main/app4/Cargo.toml index 4f9421a..79b5f8f 100644 --- a/ci/main/app4/Cargo.toml +++ b/ci/main/app4/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" diff --git a/ci/main/app4/src/main.rs b/ci/main/app4/src/main.rs index 537a418..9bfdc54 100644 --- a/ci/main/app4/src/main.rs +++ b/ci/main/app4/src/main.rs @@ -1,7 +1,7 @@ #![no_main] #![no_std] -use core::{ptr, arch::asm}; +use core::{arch::asm, ptr}; use rt::entry; @@ -9,6 +9,7 @@ entry!(main); static mut DATA: i32 = 1; +#[allow(static_mut_refs)] fn main() -> ! { unsafe { // check that DATA is properly initialized diff --git a/ci/main/rt/Cargo.toml b/ci/main/rt/Cargo.toml index 93686fe..3971cf5 100644 --- a/ci/main/rt/Cargo.toml +++ b/ci/main/rt/Cargo.toml @@ -1,5 +1,5 @@ [package] -edition = "2018" +edition = "2024" name = "rt" # <- version = "0.1.0" authors = ["Jorge Aparicio "] diff --git a/ci/main/rt/src/lib.rs b/ci/main/rt/src/lib.rs index f87b01c..e214620 100644 --- a/ci/main/rt/src/lib.rs +++ b/ci/main/rt/src/lib.rs @@ -3,18 +3,18 @@ use core::panic::PanicInfo; // CHANGED! -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn Reset() -> ! { - extern "Rust" { - fn main() -> !; + unsafe extern "Rust" { + safe fn main() -> !; } main() } // The reset vector, a pointer into the reset handler -#[link_section = ".vector_table.reset_vector"] -#[no_mangle] +#[unsafe(link_section = ".vector_table.reset_vector")] +#[unsafe(no_mangle)] pub static RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; #[panic_handler] @@ -25,12 +25,12 @@ fn panic(_panic: &PanicInfo<'_>) -> ! { #[macro_export] macro_rules! entry { ($path:path) => { - #[export_name = "main"] + #[unsafe(export_name = "main")] pub unsafe fn __main() -> ! { // type check the given path let f: fn() -> ! = $path; f() } - } + }; } diff --git a/ci/main/rt2/src/lib.rs b/ci/main/rt2/src/lib.rs index 3a9b750..78f7e70 100644 --- a/ci/main/rt2/src/lib.rs +++ b/ci/main/rt2/src/lib.rs @@ -3,11 +3,12 @@ use core::panic::PanicInfo; use core::ptr; -#[no_mangle] +#[unsafe(no_mangle)] +#[allow(static_mut_refs)] pub unsafe extern "C" fn Reset() -> ! { // NEW! // Initialize RAM - extern "C" { + unsafe extern "C" { static mut _sbss: u8; static mut _ebss: u8; @@ -16,23 +17,23 @@ pub unsafe extern "C" fn Reset() -> ! { static _sidata: u8; } - let count = &_ebss as *const u8 as usize - &_sbss as *const u8 as usize; - ptr::write_bytes(&mut _sbss as *mut u8, 0, count); + let count = unsafe { &_ebss as *const u8 as usize - &_sbss as *const u8 as usize }; + unsafe { ptr::write_bytes(&mut _sbss as *mut u8, 0, count) }; - let count = &_edata as *const u8 as usize - &_sdata as *const u8 as usize; - ptr::copy_nonoverlapping(&_sidata as *const u8, &mut _sdata as *mut u8, count); + let count = unsafe { &_edata as *const u8 as usize - &_sdata as *const u8 as usize }; + unsafe { ptr::copy_nonoverlapping(&_sidata as *const u8, &mut _sdata as *mut u8, count) }; // Call user entry point - extern "Rust" { - fn main() -> !; + unsafe extern "Rust" { + safe fn main() -> !; } main() } // The reset vector, a pointer into the reset handler -#[link_section = ".vector_table.reset_vector"] -#[no_mangle] +#[unsafe(link_section = ".vector_table.reset_vector")] +#[unsafe(no_mangle)] pub static RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; #[panic_handler] @@ -43,12 +44,12 @@ fn panic(_panic: &PanicInfo<'_>) -> ! { #[macro_export] macro_rules! entry { ($path:path) => { - #[export_name = "main"] + #[unsafe(export_name = "main")] pub unsafe fn __main() -> ! { // type check the given path let f: fn() -> ! = $path; f() } - } + }; } diff --git a/ci/memory-layout/app.text.objdump b/ci/memory-layout/app.text.objdump index 72a2fe4..23e5f27 100644 --- a/ci/memory-layout/app.text.objdump +++ b/ci/memory-layout/app.text.objdump @@ -4,8 +4,10 @@ app: file format elf32-littlearm Disassembly of section .text: : - sub sp, #4 - movs r0, #42 + push {r7, lr} + mov r7, sp + sub sp, #0x4 + movs r0, #0x2a str r0, [sp] - b 0x10 @ imm = #-2 - b 0x10 @ imm = #-4 + b 0x14 @ imm = #-0x2 + b 0x14 @ imm = #-0x4 diff --git a/ci/memory-layout/src/main.rs b/ci/memory-layout/src/main.rs index 84a1ead..5c2024d 100644 --- a/ci/memory-layout/src/main.rs +++ b/ci/memory-layout/src/main.rs @@ -4,7 +4,7 @@ use core::panic::PanicInfo; // The reset handler -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn Reset() -> ! { let _x = 42; @@ -13,8 +13,8 @@ pub unsafe extern "C" fn Reset() -> ! { } // The reset vector, a pointer into the reset handler -#[link_section = ".vector_table.reset_vector"] -#[no_mangle] +#[unsafe(link_section = ".vector_table.reset_vector")] +#[unsafe(no_mangle)] pub static RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; #[panic_handler] diff --git a/ci/script.sh b/ci/script.sh index ad4c13e..acd3e55 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -40,7 +40,7 @@ main() { # check presence of the `rust_begin_unwind` symbol diff app.o.nm \ - <(cargo nm -- $(pwd)/target/thumbv7m-none-eabi/debug/deps/app-*.o | grep '[0-9]* [^N] ') + <(cargo nm -- -C $(pwd)/target/thumbv7m-none-eabi/debug/deps/app-*.o | grep '[0-9]* [^N] ') edition_check @@ -86,41 +86,33 @@ main() { edition_check popd - # NOTE(nightly) this will require nightly until core::arch::arm::udf is stabilized - if [ $RUST_VERSION = nightly-2022-08-12 ]; then - pushd app4 - cargo build - qemu_check target/thumbv7m-none-eabi/debug/app - edition_check - popd - fi + pushd app4 + cargo build + qemu_check target/thumbv7m-none-eabi/debug/app + edition_check + popd popd - #FIXME: This fails on nightly-2022-08-12, but we need at least rust 1.63.0 or other things fail. This needs to be fixed manually. - # # exception handling - # NOTE(nightly) this will require nightly until core::arch::arm::udf is stabilized - if [ $RUST_VERSION = FIXME ]; then - pushd exceptions + pushd exceptions - # check that the disassembly matches - pushd app - diff -b app.objdump \ - <(cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex --no-leading-addr) - diff -b app.vector_table.objdump \ - <(cargo objdump --bin app --release -- -s -j .vector_table) - edition_check - popd + # check that the disassembly matches + pushd app + diff -b app.objdump \ + <(cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex) + diff -b app.vector_table.objdump \ + <(cargo objdump --bin app --release -- -s -j .vector_table) + edition_check + popd - # check that it builds - pushd app2 - cargo build - edition_check - popd + # check that it builds + pushd app2 + cargo build + edition_check + popd - popd - fi + popd # # Assembly on stable pushd asm @@ -128,7 +120,7 @@ main() { # check that the disassembly matches pushd app diff -b release.objdump \ - <(cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex --no-leading-addr) + <(cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex) diff release.vector_table \ <(cargo objdump --bin app --release -- -s -j .vector_table) edition_check @@ -145,7 +137,7 @@ main() { # check that the disassembly matches pushd app2 diff -b release.objdump \ - <(cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex --no-leading-addr) + <(cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex) diff release.vector_table \ <(cargo objdump --bin app --release -- -s -j .vector_table) edition_check @@ -232,18 +224,15 @@ main() { popd - # # DMA - # NOTE(nightly) this will require nightly until core::pin is stabilized (1.33) - if [ $RUST_VERSION = nightly-2022-08-12 ]; then - pushd dma - cargo build --examples - popd - fi + # DMA + pushd dma + cargo build --examples + popd } -# checks that 2018 idioms are being used +# checks that 2024 idioms are being used edition_check() { - RUSTFLAGS="-D rust_2018_compatibility -D rust_2018_idioms" cargo check + RUSTFLAGS="-D rust_2024_compatibility" cargo check } # checks that QEMU doesn't crash and that it produces no error messages diff --git a/ci/singleton/app/Cargo.toml b/ci/singleton/app/Cargo.toml index 09ee551..594e4bd 100644 --- a/ci/singleton/app/Cargo.toml +++ b/ci/singleton/app/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" name = "app" version = "0.1.0" @@ -9,7 +9,7 @@ codegen-units = 1 lto = true [dependencies] -cortex-m = "0.5.7" -cortex-m-semihosting = "0.3.1" +cortex-m = "0.7.7" +cortex-m-semihosting = "0.5.0" log = { path = "../log" } rt = { path = "../rt" } diff --git a/ci/singleton/app/src/main.rs b/ci/singleton/app/src/main.rs index 2abfbd3..457b051 100644 --- a/ci/singleton/app/src/main.rs +++ b/ci/singleton/app/src/main.rs @@ -1,13 +1,15 @@ #![no_main] #![no_std] +use core::cell::RefCell; use cortex_m::interrupt; +use cortex_m::interrupt::Mutex; use cortex_m_semihosting::{ debug, - hio::{self, HStdout}, + hio::{self, HostStream}, }; -use log::{global_logger, log, GlobalLog}; +use log::{GlobalLog, global_logger, log}; use rt::entry; struct Logger; @@ -29,16 +31,17 @@ fn main() -> ! { impl GlobalLog for Logger { fn log(&self, address: u8) { // we use a critical section (`interrupt::free`) to make the access to the - // `static mut` variable interrupt-safe which is required for memory safety - interrupt::free(|_| unsafe { - static mut HSTDOUT: Option = None; + // `HSTDOUT` variable interrupt-safe which is required for memory safety + interrupt::free(|cs| { + static HSTDOUT: Mutex>> = Mutex::new(RefCell::new(None)); + let mut hstdout = HSTDOUT.borrow(cs).borrow_mut(); // lazy initialization - if HSTDOUT.is_none() { - HSTDOUT = Some(hio::hstdout()?); + if hstdout.is_none() { + hstdout.replace(hio::hstdout()?); } - let hstdout = HSTDOUT.as_mut().unwrap(); + let hstdout = hstdout.as_mut().unwrap(); hstdout.write_all(&[address]) }) diff --git a/ci/singleton/log/Cargo.toml b/ci/singleton/log/Cargo.toml index e67d724..a0260fb 100644 --- a/ci/singleton/log/Cargo.toml +++ b/ci/singleton/log/Cargo.toml @@ -2,6 +2,6 @@ name = "log" version = "0.1.0" authors = ["Jorge Aparicio "] -edition = "2018" +edition = "2024" [dependencies] diff --git a/ci/singleton/log/src/lib.rs b/ci/singleton/log/src/lib.rs index 51b3cd5..e4f363c 100644 --- a/ci/singleton/log/src/lib.rs +++ b/ci/singleton/log/src/lib.rs @@ -16,12 +16,12 @@ macro_rules! log { // NEW! ($string:expr) => { unsafe { - extern "Rust" { + unsafe extern "Rust" { static LOGGER: &'static dyn $crate::GlobalLog; } - #[export_name = $string] - #[link_section = ".log"] + #[unsafe(export_name = $string)] + #[unsafe(link_section = ".log")] static SYMBOL: u8 = 0; $crate::GlobalLog::log(LOGGER, &SYMBOL as *const u8 as usize as u8) @@ -29,8 +29,8 @@ macro_rules! log { }; ($logger:expr, $string:expr) => {{ - #[export_name = $string] - #[link_section = ".log"] + #[unsafe(export_name = $string)] + #[unsafe(link_section = ".log")] static SYMBOL: u8 = 0; $crate::Log::log(&mut $logger, &SYMBOL as *const u8 as usize as u8) @@ -41,7 +41,7 @@ macro_rules! log { #[macro_export] macro_rules! global_logger { ($logger:expr) => { - #[no_mangle] + #[unsafe(no_mangle)] pub static LOGGER: &dyn $crate::GlobalLog = &$logger; }; } diff --git a/ci/smallest-no-std/Cargo.toml b/ci/smallest-no-std/Cargo.toml index 1df09e1..bf4e356 100644 --- a/ci/smallest-no-std/Cargo.toml +++ b/ci/smallest-no-std/Cargo.toml @@ -1,5 +1,5 @@ [package] -edition = "2018" +edition = "2024" name = "app" authors = ["Jorge Aparicio "] version = "0.1.0" diff --git a/ci/smallest-no-std/app.o.nm b/ci/smallest-no-std/app.o.nm index da40ea6..0ebd506 100644 --- a/ci/smallest-no-std/app.o.nm +++ b/ci/smallest-no-std/app.o.nm @@ -1 +1 @@ -00000000 T rust_begin_unwind +00000000 T __rustc::rust_begin_unwind diff --git a/ci/smallest-no-std/src/main.rs b/ci/smallest-no-std/src/main.rs index 8dc88bb..4b1e4d7 100644 --- a/ci/smallest-no-std/src/main.rs +++ b/ci/smallest-no-std/src/main.rs @@ -4,6 +4,7 @@ use core::panic::PanicInfo; #[panic_handler] +#[inline(never)] fn panic(_panic: &PanicInfo<'_>) -> ! { loop {} } diff --git a/src/asm.md b/src/asm.md index 5c02370..f2eaa86 100644 --- a/src/asm.md +++ b/src/asm.md @@ -11,10 +11,10 @@ line of assembly. That's quite a feat! But depending on the architecture you are targeting you may need some assembly to get to this point. There are also some operations, for example context switching, that require assembly. -The problem is that both *inline* assembly (`asm!`) and *free form* assembly -(`global_asm!`) are unstable, and there's no estimate for when they'll be -stabilized, so you can't use them on stable . This is not a showstopper because -there are some workarounds which we'll document here. +Both *inline* assembly (`asm!`) and *free form* assembly (`global_asm!`) were +unstable before Rust 1.59. Normally, you will want to use `global_asm!` and +`asm!` in your crates. However, this chapter describes an alternative approach +you may also use. To motivate this section we'll tweak the `HardFault` handler to provide information about the stack frame that generated the exception. diff --git a/src/dma.md b/src/dma.md index 8093e77..4908730 100644 --- a/src/dma.md +++ b/src/dma.md @@ -14,8 +14,7 @@ API. Consider the following DMA primitives: ``` rust -{{#include ../ci/dma/src/lib.rs:6:57}} -{{#include ../ci/dma/src/lib.rs:59:60}} +{{#include ../ci/dma/src/lib.rs:6:62}} ``` Assume that the `Dma1Channel1` is statically configured to work with serial port @@ -23,9 +22,7 @@ Assume that the `Dma1Channel1` is statically configured to work with serial port `Serial1` provides the following *blocking* API: ``` rust -{{#include ../ci/dma/src/lib.rs:62:72}} -{{#include ../ci/dma/src/lib.rs:74:80}} -{{#include ../ci/dma/src/lib.rs:82:83}} +{{#include ../ci/dma/src/lib.rs:64:85}} ``` Let's say we want to extend the `Serial1` API to (a) asynchronously send out a @@ -312,10 +309,6 @@ first. [`Pin`]: https://doc.rust-lang.org/nightly/std/pin/index.html -> **NOTE:** To compile all the programs below this point you'll need Rust -> `>=1.33.0`. As of time of writing (2019-01-04) that means using the nightly -> channel. - ``` rust {{#include ../ci/dma/examples/six.rs:16:33}} {{#include ../ci/dma/examples/six.rs:48:59}} diff --git a/src/exceptions.md b/src/exceptions.md index e986827..53b127b 100644 --- a/src/exceptions.md +++ b/src/exceptions.md @@ -109,8 +109,9 @@ application: > hardware a read to an invalid memory address (i.e. outside of the Flash and > RAM regions) would be enough but QEMU happily accepts the operation and > returns zero. A trap instruction works on both QEMU and hardware but -> unfortunately it's not available on stable so you'll have to temporarily -> switch to nightly to run this and the next example. +> unfortunately it's not available as pure Rust code. We will use inline assembly +> to generate the trap instruction. Later chapters describe the use of assembly +> in more detail. ``` rust {{#include ../ci/exceptions/app/src/main.rs}} @@ -149,7 +150,7 @@ $ cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex ``` ``` text -{{#include ../ci/exceptions/app/app.objdump:1:30}} +{{#include ../ci/exceptions/app/app.objdump:1:34}} ``` ``` console @@ -168,21 +169,25 @@ The vector table now resembles the results of all the code snippets in this book stack pointer. - Objdump prints in `little endian` format, so the stack starts at `0x2001_0000`. - - The second entry points to address `0x0000_0045`, the Reset handler. + - The second entry points to address `0x0000_0049`, the Reset handler. - The address of the Reset handler can be seen in the disassembly above, - being `0x44`. + being `0x48`. - The first bit being set to 1 does not alter the address due to alignment requirements. Instead, it causes the function to be executed in _thumb mode_. -- Afterwards, a pattern of addresses alternating between `0x83` and `0x00` is +- Afterwards, a pattern of addresses alternating between `0x85` and `0x00` is visible. - - Looking at the disassembly above, it is clear that `0x83` refers to the - `DefaultExceptionHandler` (`0x84` executed in thumb mode). + - Looking at the disassembly above, it is clear that `0x85` refers to the + `UsageFault` (`0x84` executed in thumb mode). - Cross referencing the pattern to the vector table that was set up earlier in this chapter (see the definition of `pub static EXCEPTIONS`) with [the vector table layout for the Cortex-M], it is clear that the address of the - `DefaultExceptionHandler` is present each time a respective handler entry + `UsageFault` is present each time a respective handler entry is present in the table. + - But we did not explicitly insert `UsageFault` in each entry. Instead, we + aliased each handler to `DefaultExceptionHandler`. Our disassembler found + multiple symbols at the same location, and chose one of them for the + function name. - In turn, it is also visible that the layout of the vector table data structure in the Rust code is aligned with all the reserved slots in the Cortex-M vector table. Hence, all reserved slots are correctly set to a diff --git a/src/logging.md b/src/logging.md index 3f77eac..22a7685 100644 --- a/src/logging.md +++ b/src/logging.md @@ -8,11 +8,14 @@ super cheap logging. Whenever we needed a stable symbol interface between crates we have mainly used the `no_mangle` attribute and sometimes the `export_name` attribute. The `export_name` attribute takes a string which becomes the name of the symbol -whereas `#[no_mangle]` is basically sugar for `#[export_name = ]`. +whereas `#[unsafe(no_mangle)]` is basically sugar for `#[unsafe(export_name = )]`. Turns out we are not limited to single word names; we can use arbitrary strings, e.g. sentences, as the argument of the `export_name` attribute. As least when -the output format is ELF anything that doesn't contain a null byte is fine. +the output format is ELF anything that doesn't contain a null byte is fine. +This is generally true when using the gnu linker. However, there are some [known +limitations](https://github.com/knurling-rs/defmt/issues/979#issuecomment-3133721969) +with the macOS and Windows linkers. Let's check that out: @@ -23,11 +26,11 @@ $ cat foo/src/lib.rs ``` ``` rust -#[export_name = "Hello, world!"] +#[unsafe(export_name = "Hello, world!")] #[used] static A: u8 = 0; -#[export_name = "こんにちは"] +#[unsafe(export_name = "こんにちは")] #[used] static B: u8 = 0; ``` diff --git a/src/main.md b/src/main.md index 2a749d2..744bad3 100644 --- a/src/main.md +++ b/src/main.md @@ -62,7 +62,7 @@ The `rt` will take care of giving the program the right memory layout. ``` console $ cd .. -$ cargo new --edition 2018 --bin app +$ cargo new --edition 2024 --bin app $ cd app @@ -217,11 +217,11 @@ the boundaries of the `.bss` and `.data` sections. The updated reset handler is shown below: ``` console -$ head -n32 ../rt/src/lib.rs +$ head -n33 ../rt/src/lib.rs ``` ``` rust -{{#include ../ci/main/rt2/src/lib.rs:1:31}} +{{#include ../ci/main/rt2/src/lib.rs:1:32}} ``` Now end users can directly and indirectly make use of `static` variables without running into diff --git a/src/memory-layout.md b/src/memory-layout.md index 10855f0..91e74ac 100644 --- a/src/memory-layout.md +++ b/src/memory-layout.md @@ -34,12 +34,21 @@ These compiler generated symbol and section names are not guaranteed to remain c different releases of the Rust compiler. However, the language lets us control symbol names and section placement via these attributes: -- `#[export_name = "foo"]` sets the symbol name to `foo`. -- `#[no_mangle]` means: use the function or variable name (not its full path) as its symbol name. - `#[no_mangle] fn bar()` will produce a symbol named `bar`. -- `#[link_section = ".bar"]` places the symbol in a section named `.bar`. +- `#[unsafe(export_name = "foo")]` sets the symbol name to `foo`. +- `#[unsafe(no_mangle)]` means: use the function or variable name (not its full path) as its symbol name. + `#[unsafe(no_mangle)] fn bar()` will produce a symbol named `bar`. +- `#[unsafe(link_section = ".bar")]` places the symbol in a section named `.bar`. With these attributes, we can expose a stable ABI of the program and use it in the linker script. +Each of these attributes has safety guarantees that must be upheld in your program, namely: +- `#[unsafe(no_mangle)]` fixes the symbol name, regardless of the crate, module, variable or +function name and arguments. Using this attribute, it is possible to create multiple symbols with +the same name, leading to undefined behavior. The user must guarantee that the symbol does not collide +with others. +- `#[unsafe(export_name = "foo")]` also fixes the symbol name. The user must guarantee that +the chosen symbol name (in this case `foo`) does not collide with any other symbol in the program. +- `#[unsafe(link_section = ".bar")]` may place data and code into sections of memory not expecting them, +such as mutable data into read-only areas, or memory regions that do not exist on the target device. ## The Rust side @@ -62,7 +71,7 @@ The hardware expects a certain format here, to which we adhere by using `extern compiler to lower the function using the C ABI, instead of the Rust ABI, which is unstable. To refer to the reset handler and reset vector from the linker script, we need them to have a stable -symbol name so we use `#[no_mangle]`. We need fine control over the location of `RESET_VECTOR`, so we +symbol name so we use `#[unsafe(no_mangle)]`. We need fine control over the location of `RESET_VECTOR`, so we place it in a known section, `.vector_table.reset_vector`. The exact location of the reset handler itself, `Reset`, is not important. We just stick to the default compiler generated section. @@ -270,7 +279,7 @@ $1 = 0x20010000 $2 = 42 (gdb) print &_x -$3 = (i32 *) 0x2000fffc +$3 = (i32 *) 0x2000fff4 (gdb) quit ``` diff --git a/src/preface.md b/src/preface.md index 1050613..0bf477b 100644 --- a/src/preface.md +++ b/src/preface.md @@ -52,10 +52,10 @@ the examples included in this book can be tested in QEMU. You will, however, need to install the following tools to run and inspect the examples in this book: -- All the code in this book uses the 2018 edition. If you are not familiar with - the 2018 features and idioms check the [`edition guide`]. +- All the code in this book uses the 2024 edition. If you are not familiar with + the 2024 features and idioms check the [`edition guide`]. -- Rust 1.31 or a newer toolchain PLUS ARM Cortex-M compilation support. +- Rust 1.89 or a newer toolchain with ARM Cortex-M compilation support. - [`cargo-binutils`](https://github.com/japaric/cargo-binutils). v0.1.4 or newer. @@ -66,7 +66,7 @@ book: - GDB with ARM support. -[`edition guide`]: https://rust-lang-nursery.github.io/edition-guide/ +[`edition guide`]: https://doc.rust-lang.org/edition-guide/ ### Example setup @@ -79,14 +79,14 @@ $ rustup default stable $ # toolchain should be newer than this one $ rustc -V -rustc 1.31.0 (abe02cefd 2018-12-04) +rustc 1.89.0 (29483883e 2025-08-04) $ rustup target add thumbv7m-none-eabi $ # cargo-binutils $ cargo install cargo-binutils -$ rustup component add llvm-tools-preview +$ rustup component add llvm-tools ``` @@ -111,7 +111,7 @@ $ # QEMU $ sudo apt install qemu-system-arm ``` -#### Ubuntu 18.04 or Debian +#### Ubuntu 18.04 (or newer) or Debian ``` console $ # gdb-multiarch -- use `gdb-multiarch` when you wish to invoke gdb diff --git a/src/singleton.md b/src/singleton.md index 10142d3..d632ab8 100644 --- a/src/singleton.md +++ b/src/singleton.md @@ -4,17 +4,13 @@ In this section we'll cover how to implement a global, shared singleton. The embedded Rust book covered local, owned singletons which are pretty much unique to Rust. Global singletons are essentially the singleton pattern you see in C and C++; they are not specific to embedded development but since they involve -symbols they seemed a good fit for the Embedonomicon. - -> **TODO**(resources team) link "the embedded Rust book" to the singletons -> section when it's up +symbols they seemed a good fit for the Embedonomicon. The embedded Rust book +also has a chapter on [singletons]. To illustrate this section we'll extend the logger we developed in the last section to support global logging. The result will be very similar to the -`#[global_allocator]` feature covered in the embedded Rust book. - -> **TODO**(resources team) link `#[global_allocator]` to the collections chapter -> of the book when it's in a more stable location. +`#[global_allocator]` feature covered in the [collections] chapter of the +embedded Rust book. Here's the summary of what we want to do: @@ -126,9 +122,6 @@ $ cat src/main.rs {{#include ../ci/singleton/app/src/main.rs}} ``` -> **TODO**(resources team) use `cortex_m::Mutex` instead of a `static mut` -> variable when `const fn` is stabilized. - We had to add `cortex-m` to the dependencies. ``` console @@ -178,3 +171,6 @@ $ cargo objdump --bin app --release -- -t | grep LOGGER If the `static` is missing that means that there is no vtable and that LLVM was capable of transforming all the `LOGGER.log` calls into `Logger.log` calls. + +[singletons]: https://docs.rust-embedded.org/book/peripherals/singletons.html +[collections]: https://docs.rust-embedded.org/book/collections/index.html#using-alloc diff --git a/src/smallest-no-std.md b/src/smallest-no-std.md index 6076173..a06dd69 100644 --- a/src/smallest-no-std.md +++ b/src/smallest-no-std.md @@ -41,7 +41,7 @@ runs on a system. It can be many things that a standard Rust application can nev With that out of the way, we can move on to the smallest `#![no_std]` program that compiles: ``` console -$ cargo new --edition 2018 --bin app +$ cargo new --edition 2024 --bin app $ cd app ``` @@ -84,7 +84,7 @@ Before linking, the crate contains the panicking symbol. ``` console $ cargo rustc --target thumbv7m-none-eabi -- --emit=obj -$ cargo nm -- target/thumbv7m-none-eabi/debug/deps/app-*.o | grep '[0-9]* [^N] ' +$ cargo nm -- -C $(pwd)/target/thumbv7m-none-eabi/debug/deps/app-*.o | grep '[0-9]* [^N] ' ``` ``` text