From 1079445a07920deed7cd92c1dbdaf89fd8ce4de9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 May 2024 19:43:54 +0200 Subject: [PATCH] introduce mem pool and heap --- .../stm32h7-rtic/.cargo/def_config.toml | 4 +- embedded-examples/stm32h7-rtic/.gitignore | 1 + embedded-examples/stm32h7-rtic/Cargo.lock | 93 +++++++++++++++++-- embedded-examples/stm32h7-rtic/Cargo.toml | 5 +- embedded-examples/stm32h7-rtic/src/main.rs | 81 +++++++++++++++- .../stm32h7-rtic/vscode/launch.json | 2 +- satrs/src/pool.rs | 8 ++ 7 files changed, 178 insertions(+), 16 deletions(-) diff --git a/embedded-examples/stm32h7-rtic/.cargo/def_config.toml b/embedded-examples/stm32h7-rtic/.cargo/def_config.toml index b229e7f..1788b96 100644 --- a/embedded-examples/stm32h7-rtic/.cargo/def_config.toml +++ b/embedded-examples/stm32h7-rtic/.cargo/def_config.toml @@ -9,6 +9,8 @@ rustflags = [ # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 "-C", "link-arg=--nmagic", + # Can be useful for debugging. + # "-Clink-args=-Map=app.map" ] [build] @@ -24,4 +26,4 @@ rb = "run --bin" rrb = "run --release --bin" [env] -DEFMT_LOG = "info" \ No newline at end of file +DEFMT_LOG = "info" diff --git a/embedded-examples/stm32h7-rtic/.gitignore b/embedded-examples/stm32h7-rtic/.gitignore index 7eedae7..c2bb1e7 100644 --- a/embedded-examples/stm32h7-rtic/.gitignore +++ b/embedded-examples/stm32h7-rtic/.gitignore @@ -1,3 +1,4 @@ /target /.cargo/config* /.vscode +/app.map diff --git a/embedded-examples/stm32h7-rtic/Cargo.lock b/embedded-examples/stm32h7-rtic/Cargo.lock index 3436bc9..dd919c1 100644 --- a/embedded-examples/stm32h7-rtic/Cargo.lock +++ b/embedded-examples/stm32h7-rtic/Cargo.lock @@ -23,7 +23,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" dependencies = [ - "rustc_version", + "rustc_version 0.2.3", ] [[package]] @@ -65,8 +65,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cobs" version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +source = "git+https://github.com/robamu/cobs.rs.git?branch=all_features#c70a7f30fd00a7cbdb7666dec12b437977385d40" [[package]] name = "cortex-m" @@ -218,6 +217,16 @@ dependencies = [ "syn 2.0.64", ] +[[package]] +name = "embedded-alloc" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddae17915accbac2cfbc64ea0ae6e3b330e6ea124ba108dada63646fd3c6f815" +dependencies = [ + "critical-section", + "linked_list_allocator", +] + [[package]] name = "embedded-dma" version = "0.2.0" @@ -294,6 +303,15 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hash32" version = "0.3.1" @@ -309,6 +327,19 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.0", + "spin", + "stable_deref_trait", +] + [[package]] name = "heapless" version = "0.8.0" @@ -316,7 +347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ "defmt", - "hash32", + "hash32 0.3.1", "stable_deref_trait", ] @@ -330,6 +361,22 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "managed" version = "0.8.0" @@ -523,20 +570,28 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.23", ] [[package]] name = "satrs" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866fcae3b683ccc37b5ad77982483a0ee01d5dc408dea5aad2117ad404b60fe1" dependencies = [ "cobs", "crc", "defmt", "delegate", "derive-new", + "heapless 0.7.17", "num-traits", "num_enum", "paste", @@ -564,6 +619,7 @@ dependencies = [ "defmt", "defmt-brtt", "defmt-test", + "embedded-alloc", "panic-probe", "rtic", "rtic-monotonics", @@ -572,6 +628,12 @@ dependencies = [ "stm32h7xx-hal", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "semver" version = "0.9.0" @@ -581,6 +643,12 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "semver-parser" version = "0.7.0" @@ -603,7 +671,7 @@ dependencies = [ "byteorder", "cfg-if", "defmt", - "heapless", + "heapless 0.8.0", "managed", ] @@ -621,6 +689,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/embedded-examples/stm32h7-rtic/Cargo.toml b/embedded-examples/stm32h7-rtic/Cargo.toml index c09b999..f5dfbeb 100644 --- a/embedded-examples/stm32h7-rtic/Cargo.toml +++ b/embedded-examples/stm32h7-rtic/Cargo.toml @@ -21,6 +21,7 @@ defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] } panic-probe = { version = "0.3", features = ["print-defmt"] } cortex-m-semihosting = "0.5.0" stm32h7xx-hal = { version="0.16", features= ["stm32h743v", "ethernet"] } +embedded-alloc = "0.5" [dependencies.smoltcp] version = "0.11.0" @@ -36,10 +37,10 @@ version = "1" features = ["cortex-m-systick"] [dependencies.satrs] -# path = "satrs" +path = "../../satrs" version = "0.2" default-features = false -features = ["defmt"] +features = ["defmt", "heapless"] [dev-dependencies] defmt-test = "0.3" diff --git a/embedded-examples/stm32h7-rtic/src/main.rs b/embedded-examples/stm32h7-rtic/src/main.rs index 7bad1f7..9c78c81 100644 --- a/embedded-examples/stm32h7-rtic/src/main.rs +++ b/embedded-examples/stm32h7-rtic/src/main.rs @@ -1,13 +1,18 @@ #![no_main] #![no_std] +extern crate alloc; use rtic::app; use rtic_monotonics::systick::Systick; use rtic_monotonics::Monotonic; +use satrs::pool::StaticHeaplessMemoryPool; +use satrs::static_subpool; +// global logger + panicking-behavior + memory layout use satrs_stm32h7_nucleo_rtic as _; -use smoltcp::socket::{dhcpv4, udp}; // global logger + panicking-behavior + memory layout +use smoltcp::socket::{dhcpv4, udp}; use core::mem::MaybeUninit; +use embedded_alloc::Heap; use smoltcp::iface::{Config, Interface, SocketHandle, SocketSet, SocketStorage}; use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr}; use stm32h7xx_hal::ethernet; @@ -15,9 +20,18 @@ use stm32h7xx_hal::ethernet; const DEFAULT_BLINK_FREQ_MS: u32 = 1000; const PORT: u16 = 7301; -/// Ethernet descriptor rings are a global singleton -#[link_section = ".sram3.eth"] -static mut DES_RING: MaybeUninit> = MaybeUninit::uninit(); +const HEAP_SIZE: usize = 131_072; + +#[global_allocator] +static HEAP: Heap = Heap::empty(); + +// We place the memory pool buffers inside the larger AXISRAM. +pub const SUBPOOL_SMALL_NUM_BLOCKS: u16 = 32; +pub const SUBPOOL_SMALL_BLOCK_SIZE: usize = 32; +pub const SUBPOOL_MEDIUM_NUM_BLOCKS: u16 = 16; +pub const SUBPOOL_MEDIUM_BLOCK_SIZE: usize = 128; +pub const SUBPOOL_LARGE_NUM_BLOCKS: u16 = 8; +pub const SUBPOOL_LARGE_BLOCK_SIZE: usize = 2048; // This data will be held by Net through a mutable reference pub struct NetStorageStatic<'a> { @@ -55,6 +69,7 @@ impl<'a> Net<'a> { &mut ethdev, smoltcp::time::Instant::from_millis((Systick::now() - Systick::ZERO).to_millis()), ); + // SAFETY: The RX and TX buffers are passed here and not used anywhere else. let udp_rx_buffer = smoltcp::socket::udp::PacketBuffer::new(unsafe { &mut UDP_RX_META[..] }, unsafe { &mut UDP_RX[..] @@ -251,6 +266,11 @@ mod app { let rmii_txd1 = gpiob.pb13.into_alternate::<11>(); let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS); + + /// Ethernet descriptor rings are a global singleton + #[link_section = ".sram3.eth"] + static mut DES_RING: MaybeUninit> = MaybeUninit::uninit(); + let (eth_dma, eth_mac) = ethernet::new( cx.device.ETHERNET_MAC, cx.device.ETHERNET_MTL, @@ -300,6 +320,59 @@ mod app { let net = Net::new(store, eth_dma, mac_addr.into()); + let mut heapless_pool: StaticHeaplessMemoryPool<3> = StaticHeaplessMemoryPool::new(true); + static_subpool!( + SUBPOOL_SMALL, + SUBPOOL_SMALL_SIZES, + SUBPOOL_SMALL_NUM_BLOCKS as usize, + SUBPOOL_SMALL_BLOCK_SIZE, + link_section = ".axisram" + ); + static_subpool!( + SUBPOOL_MEDIUM, + SUBPOOL_MEDIUM_SIZES, + SUBPOOL_MEDIUM_NUM_BLOCKS as usize, + SUBPOOL_MEDIUM_BLOCK_SIZE, + link_section = ".axisram" + ); + static_subpool!( + SUBPOOL_LARGE, + SUBPOOL_LARGE_SIZES, + SUBPOOL_LARGE_NUM_BLOCKS as usize, + SUBPOOL_LARGE_BLOCK_SIZE, + link_section = ".axisram" + ); + + heapless_pool + .grow( + unsafe { SUBPOOL_SMALL.assume_init_mut() }, + unsafe { SUBPOOL_SMALL_SIZES.assume_init_mut() }, + SUBPOOL_SMALL_NUM_BLOCKS, + false, + ) + .expect("growing heapless memory pool failed"); + heapless_pool + .grow( + unsafe { SUBPOOL_MEDIUM.assume_init_mut() }, + unsafe { SUBPOOL_MEDIUM_SIZES.assume_init_mut() }, + SUBPOOL_MEDIUM_NUM_BLOCKS, + false, + ) + .expect("growing heapless memory pool failed"); + heapless_pool + .grow( + unsafe { SUBPOOL_LARGE.assume_init_mut() }, + unsafe { SUBPOOL_LARGE_SIZES.assume_init_mut() }, + SUBPOOL_LARGE_NUM_BLOCKS, + false, + ) + .expect("growing heapless memory pool failed"); + + // Set up global allocator. Use AXISRAM for the heap. + #[link_section = ".axisram"] + static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; + unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) } + eth_link_check::spawn().expect("eth link check failed"); blink::spawn().expect("spawning blink task failed"); ( diff --git a/embedded-examples/stm32h7-rtic/vscode/launch.json b/embedded-examples/stm32h7-rtic/vscode/launch.json index 2e4eb58..0ee6e8c 100644 --- a/embedded-examples/stm32h7-rtic/vscode/launch.json +++ b/embedded-examples/stm32h7-rtic/vscode/launch.json @@ -12,7 +12,7 @@ "chip": "STM32H743ZITx", "coreConfigs": [ { - "programBinary": "${workspaceFolder}/target/thumbv7em-none-eabihf/debug/satrs-stm32h7-rtic", + "programBinary": "${workspaceFolder}/target/thumbv7em-none-eabihf/debug/satrs-stm32h7-nucleo-rtic", "rttEnabled": true, "svdFile": "STM32H743.svd" } diff --git a/satrs/src/pool.rs b/satrs/src/pool.rs index c655643..825ca8b 100644 --- a/satrs/src/pool.rs +++ b/satrs/src/pool.rs @@ -390,6 +390,14 @@ pub mod heapless_mod { static mut $sizes_list_name: core::mem::MaybeUninit<[usize; $num_blocks]> = core::mem::MaybeUninit::new([satrs::pool::STORE_FREE; $num_blocks]); }; + ($pool_name: ident, $sizes_list_name: ident, $num_blocks: expr, $block_size: expr, $meta_data: meta) => { + #[$meta_data] + static mut $pool_name: core::mem::MaybeUninit<[u8; $num_blocks * $block_size]> = + core::mem::MaybeUninit::new([0; $num_blocks * $block_size]); + #[$meta_data] + static mut $sizes_list_name: core::mem::MaybeUninit<[usize; $num_blocks]> = + core::mem::MaybeUninit::new([satrs::pool::STORE_FREE; $num_blocks]); + }; } /// A static memory pool similar to [super::StaticMemoryPool] which does not reply on