owned this note
owned this note
Published
Linked with GitHub
RustNL Unconf Embedded Track May 9 2024
===============
Attendees:
-
* Daniel Egger (@therealprof)
* Adam Greig (@adamgreig)
* Adam Hott (@greengenie)
* James Munns (@jamesmunns)
* Richard Meadows (@richardeoin)
* Henk Oordt (@hdoordt)
* Dario Nieuwenhuis (@dirbaio)
* Noah Hüsser (@Yatekii)
* Dominik Böhi (@Tiwalun)
* Christian Meusel (@sirhcel)
* Sergio Gasquez (@sergiogasquez)
Governance Topics
-------
1. What do we want to happen to the WG going forward – should it remain part of the Rust project or become a separate organisation?
a) (and discuss leadership council representative)
**5 people**
2. What’s our direction and roadmap for the next couple of years? What areas do we focus on?
**4 people**
4. Do we want to update our leadership model or core team members?
**3 people**
Technical Topics
-----
1. What do we recommend instead of`static mut`? Can we write down best practices?
**11 people**
3. What should we do about volatile-cell, dereferenceablegate, PAC singletons? Have we reached a consensus that we can document and start to implement?
**9 people**
5. What should we do about the PAC/RT/arch crate interactions, especially in Cortex-M? Should it follow the new RISC-V model? Can both architectures be harmonised?
**10 people**
Project Topics
----
More of these and they’re quite mixed
1. Should we have a golden HAL example for new authors to reference? What should it look like? Do we make specific recommendations for best practices around things like generics, pin ownership, ...?
**11 people**
3. What should we do about our documentation, in particular the book and the discovery book? Should they be reworked? Combined? Rewritten or majorly updated? Related is embedded-hal documentation: what common questions can we pre-empt, such as async sharing or SPI for weird peripherals
**12 people**
5. Can we push for std/core to have configurable size/speed selections to help reduce bloat on embedded? And related topic about high code size for async.
**9 people**
7. Probe-rs: more topics than fit on the slides! Refer to HackMD 5. Bluetooth in Rust and binary data structures discussion topics
8. Bluetooth in Rust
**9 people**
10. binary data structures discussion topics
**7 people**
-----
# Embedded Documentation and Learning Rejuvenation Plan
1. Complete the PR merge and issue triage for the STM and MB
Embedded Discovery Book.
2. Split the MB Book into separate MB1 and MB2 Books.
3. Mark the MB1 Book and STM Book as deprecated; refer folks to the
MB2 Book.
4. There is no step 4.
5. At this point we should have three repos. Turn off PRs
and Issues for the older repos.
6. Ensure the Book content is up-to-date. Fix as necessary.
7. Set up CI for the Book.
8. Port the fundamental "missing content" from the STM Book
to the MB2 Book: interrupts, DMA.
9. Add async chapter to Book.
9. Add RTIC and/or Tock chapter to Book? Patches welcome.
----
* Important question: Use `microbit`/`nrf52833-hal` or
`microbit-bsp`/`embassy-hal` for sync part of Book? How
many Embassy abstractions can "leak through"? Live vs
"dead" ecosystem?
* Finish rewrite of "display" in `microbit-bsp` regardless.
* Next book: "Embedded HAL Developer Book" teaching Embedded
HAL provider and client best practices.
* Another book: "Embassy Developer Book".
* Producing docs at scale:
* Book sprints. Online or offline. Will folks participate?
* Paying students to doc. Needs a mentor.
* Leveraging Rustdoc better?
* FAQ for chat!
* Office hours
Minutes from the sessions
===
Thursday AM2 session:
---
* Short introduction to leadership council by jp
* 2 volunteers to join the launchpad team (council) on site: @Noah and @jamesmunns
* Discussion around the place of the embedded WG
* Does the REWG qualify as a *user* of the project to be part of the project?
* In the early days we were quite vocal about getting some essential features in, we advocated for embedded as a usecase for Rust and despite not being that active we still have some ties to the Rust project and will probably require some support from the compiler.
* "Keeping the foot in the door" is important
* Would leaving the project undermine the authority of our work?
* Should we join forces with the Rust Linux people since their use case is similar and they also don't have representation? Would our organisation be a fit for them?
* "Rust Application Organisation" (working title) is in formation to further the use of Rust in the field. Might be a better fit for the REWG than the Rust project due to being application focused. Their plan is till to cooperate with the Rust project so we might have a voice there.
* It still might be interesting to have a closer and more direct connection to the Rust project. Also there a lot more touching points like the use of libcore and cargo, not just the compiler.
* We could also try to become more active to maintain target docs and support actual hidden benefitiaries (e.g. TockOS) of the work more.
* Roadmapping ideas:
* Ensuring that we can compile for upcoming targets (RISC-V)
* Improving on embedded-hal and other foundational crates
* Providing the materials to get larger groups of people onboarded and educated efficiently and at scale
* Documentation
* Tutorials/Guides
* Examples
* Libraries
* Decide on where to go with sync/async approaches as they're quite different and have different applications
* How far to go with documentation and showcases for non-WG projects (embassy, FreeRTOS, TockOS, RTIC, etc.)?
* Can we coordinate with other organisations and projects (e.g. MISRA) to make sure that Rust projects can still comply with those essential rules in some industries?
* Can we coordinate/cooperate/liase with more vendors to improve the (out of the box) experience?
* Can we onboard/establish better communiation channels to vendors to allow them to be considered in our work
* Can we have more regular meetings to foster collaboration?
* Ensure better visibility of our work
* Multiple levels of materials for audiences at different experience stages
* Better graphics/diagrams
* Define the "target markets"
* ![Screenshot 2024-05-09 at 12.22.14](https://hackmd.io/_uploads/ry39VQqG0.jpg)
* Can we define an ownership to make it clearer which work is maintained by the community and which work is handled by the vendor
* Improving the CI experience for embedded project
* Set up a collaborative environment for embedded testing?
* How do we ensure the ongoing maintenance? Are volunteers enough or should we find funding/companies to take care of that?
* Provide more details and structure about which contributions we're looking for to encourage more volunteer work
* Interoperability/migration stuff for existing projects/product to move to Rust
* Produce hardware/example/documentation/tools for hobbyists to lure them in from Arduino
* Create a UI only installation experience for Windows users
Thursday PM1 Volatile/Singletons Session:
---
Singletons, volatile, dereferenceable
* Should we still be using `vcell`, `volatilecell` or similar crates?
* We (svd2rust) currently generates memory-mapped structs which we take references to,
but this isn't necessarily sound
* Would it be possible to have a type in the compiler which provides us the required semantics?
* Looked at chiptool
* Less code generated so faster to build
* Easier docs to navigate
* Can't support RO/WO/different read/write semantics though
* No owned singletons
* Safe construction and access to all the registers including DMA
* There are also some other forks of chiptool (raltool, unnamed silicon vendor, infineon)
* Cortex-M crate is also involved: it should probably be a PAC and a HAL, with the former using svd2rust etc and the latter providing the singletons
* Discussed Dirbaio's document about no-owned-singletons: don't model peripherals that split into parts (and so HALs hvae to bypass ownership); don't model multi-core ownership; don't support multiple PAC versions in one application
* Removing singletons from the PAC (and moving it into the HAL) seems good, but how do we do it?
* It will be a breaking change for HALs and for applications
* Any sort of guide or automated fix-up?
* How do we communicate that?
* Need to talk to HAL teams to discuss the changes and how disruptive they will be
* Tools team to open RFC (@adamgreig volunteered)
* Tangent: Should we provide a checklist for PAC/HAL crate publishers to guide them to avoid confusion/conflicts?
Thursday PM1 Bluetooth Session:
---
https://github.com/embassy-rs/trouble
BLE session reference:
* Quick overveiw of BLE spec splitting stack in Host, HCI (Host Controller Interface) and Controller.
* Controller implementations are often vendor-specific
* Bt-hci provides HCI types and traits.
* TrouBLE implements Host
* Qualification:
* Considered to be in the far future
* Focus on implementing missing features, testing and integration with qualification tests (auto-pts)
* TrouBLE TODOs and "assigned tasks" (no commitment):
* Stm32WB example
* Multicore / Ipc example: Dominik
* Rp Pico W example: Tiago
* Gatt client: Christian
* HIL testing: Ulf
* API cleanup (less generics) and documentation: Ulf
* Security manager: espressif
* Esp32 example: espressif
* All tasks created as GH issues.
### Unrelated Amanieu Mentions:
* We want to move away from volatile because it's a cloudy area with a lot of baggage
* There is desire to formalize SPECIFICALLY the "mmio" use case, practically:
* mmio_write -> like volatile write, but MUST NOT be used for data w/in the Rust Abstract Machine
* in the short term, we could wrap volatile anyway, OR we could impl with inline asm
* inline asm would allow us to avoid cases like volatile write of `[u8;512]` "larger than addressable width" operation
* mmio_read -> like volatile read, but ""
* Same notes as above
* There is an expectation that each PLATFORM provides a mmio_fence/mmio_compiler_fence method
* This should be implemented with inline asm
* compiler fence can be empty asm block as all asm blocks imply by default a fence (unless you opt out with nomem, etc.)
* fence should use the appropriate instruction (dsb xx/dmb/isb, etc), and should also take an ordering to declare which kind of
instruction we generate
* In the future, mmio_read and mmio_write COULD be provided by core::sync... or core::intrisic or core::ptr but the intent is
likely that fence should always be provided per-platform
* Also provide guidance in docs to "deprecated" volatile operation
* This might live in `cortex-m-asm`
### Related projects
- HCI implementation for STM32WB: https://github.com/eupn/stm32wb55
Thursday PM2: PAC/Cortex-M/Cortex-M-RT crates session
---
* Shoult we split the cortex-M crate into two?
* Introduce a new trait representing an interrupt which has to be implemented by the PAC
* Should we upstream some of the inline ASM code as intrinsics?
* Yes, upstream says this is OK
* Risc-V
* ESP need(ed) a -rt fork for specific chips
* risc-v/-rt split into
* risc-v-pac
* this is the PAC interface: interruptnumber, prioritynumber, ... traits
* risc-v-peripheral
* this is the PAC and the HAL, including some E-H implementations
* Platform-level interrupt controller driver
* risc-v
* CSRs, inline assembly
* risc-v-rt
* init code, macros, interrupt handling
* CPU doesn't do register stacking/spilling so our crates need to handle the interrupt ABI
* risc-v-rt crate does this today
* Interrupt macro
* Remove static mut transform
* New syntax... `#[interupt(instance of enum that impls the shared trait)] fn bla()`
* We discussed several possible syntaxes and various problems wiht all of them`
* ![IMG_1897](https://hackmd.io/_uploads/BkSXWv5zR.jpg)
* Tendency towards number 4
```rust
// vv--- This is cortex_m_rt::interrupt
#[interrupt(rp2040_pac::Interrupt::UART0)] // <<--- this is from your selected PAC
fn handle_uart_rx() { // <<--- we will make an unmangled *additional* symbol for this function called `UART0`
// Do stuff
}
```
* @diarbaio volunteered to write an RFC
## Thursday PM2: Binary data structures, fancy registers
### data structures
We often need fixed data structures provided by chip vendors that sit on top of the binaries we want to run, aka "headers". Those are needed in both storage parts (SD card, SPI flash, ...) and for loading binaries over e.g. UART or USB for development.
**NOTE**: This code is running on the _host_, not on the target, so performance is usually no concern.
#### Examples
- "new" vs "old" implementation in https://github.com/orangecms/vf2-header
- `Header` + `Param1` in https://github.com/orangecms/sg_boot/blob/main/src/protocol.rs
#### Approaches
1. define data structure with semantics
- have partial default implementation
- fill up additional fields, e.g. sizes, checksums
2. write out a vec step by step
- useful where data structure is mostly padding / fixed
1. let the linker add a blob
- define a section for it; e.g., oreboot sunxi/nezha (Allwinner D1)
- have intermediate binary file and inject values in build step
2. include with build framework directly
- less "linker magic"
- let it be one of the concatenations that you do anyway
3. standalone tool
- take an arbitrary binary and push it to a target device
- also useful for non-Rust use-cases, e.g. U-Boot SPL, little asm test
### fancy register interactions
To interpret CPU information, talk to non-generic register blocks (e.g., efuses, vendor-specific peripherals, etc) or just single registers, we would like to have something like embedded HAL/PAC, but more ad-hoc.
For projects like oreboot, we would like to have some guidance of what options there are in which scenario.
**NOTE**: This is code to run on the _target_, so we are concerned about binary size. Runtime performance is often not an issue, because the code runs at most once in some cases (verbose debug output) or a few times only (initialization phase).
#### Examples
- CPU information on T-Header cores, https://github.com/platform-system-interface/thead_cpuinfo/
#### Approaches
There are many ways to handle register access. We have noted down a list of options to look into.
- manual definitions (current example)
- lean macros / choose any out of many such crates?
- https://docs.rs/bilge/latest/bilge/
- https://docs.rs/bitflags/latest/bitflags/
- https://docs.rs/bit_field/latest/bit_field/
- https://docs.rs/bitfield/latest/bitfield/
- https://docs.rs/tock-registers/latest/tock_registers/
- `deku` crate
- `device-driver` crate
- `bitvec` crate
- FAQ with some minor opinions
- guidelines with suggestions/examples per use-case
- why we avoid XYZ in case of ABC
Writing to / modifying registers could be simplified.
Not really all Rust here, to get the idea:
```rs
reg.write(|w| w.field1().set_to_foo().field2().set_xx());
reg.write(|w| {
w.field1().set_to_foo();
w.field2().set_xx();
w
});
// extend initial value
reg.write(|w| { ...w, foo: Foo.Bar } );
// change current value
reg.modify(|w| { ...w, foo: Foo.Bar } );
modify!(reg, { ...w, foo: Foo.Bar } );
```
Polling a status register _and_ yielding the result (not discussed further)
```rs
fn poll_smth() -> u32 {
// prepare ...
let res = loop {
let r = unsafe { read_volatile(reg as *const u32) };
if r & (1 << 2) != 0 {
// NOTE: this returns/yields!
break r;
}
};
// finalize ...
res
}
```
Alignment is sometimes an issue, often enough easily done at build time.
For RISC-V, the exception handler needs to be 4-byte aligned. LLVM does 2-byte alignment by default. Simple enough:
`#![feature(fn_align)]` / `#[repr(align(4))]`
Possibly use the `riscv` crate for this. In oreboot, we define our trap handler manually. The SBI we provide is _optional_, so having something in a link step feels too complicated in the build process.
At runtime, code you are hosting may cause unaligned access exceptions (not discussed further).
Friday AM1: Docs
---
* Bart Massey presented and walked us through a plan (find it at the top of this document)
* Which concepts ("old" HALs, embassy, ...) do we want to teach in our books? Multiple, one? At which level? PAC, HAL, BSP?
* "Discovery" book:
* Using an external BSP might create the false perception that you have to use a BSP to use Rust on MCUs which often don't exist. Maybe include a basic "BSP" (potentially without naming it as such) in the books to ease a reader into the concepts and then explain how to do your own.
* Could introduce BSP as "design pattern" to abstract over different boards
* Add more books ("workshops") to have guide through different user stories
* Whatever we decide to use in the books should be "usable in production", probably settle on embassy on nRF. Requires some work to make sure that there's a "stable" version of embassy published
* Borrow from Ferrous materials: https://github.com/ferrous-systems/rust-exercises/blob/main/exercise-book/src/SUMMARY.md#embedded-rust-on-the-nrf52
* Have more regular work meetings to get work done
* There is money, maybe we should find some students (also need mentors) to do some paid work
* Documentated examples and tooling need CI
* Need to have a living FAQ addressing the most pressing questions
* Be more active on the discourse? https://users.rust-lang.org/c/embedded/10
Friday AM1: probe-rs
---
- Discussion about roadmap
- Users / use cases
- Dion
- `cargo run` for flashing
- Custom CLI tools
- teleprobe for CI
- Dominik / tiwalun
- Use as a library
- Expose more of the low-level API
- Add features to select supported probes
- Francois
- No debug interface on chip
- Emulator use case using JTAG
- Leon
- Not used probe-rs so far
- integrated into tock-os build tool in 5 min
- Python script which uses j-link / openOCD
- jannic
- easy to use, for hobby purposes
- debian packaging?
- Noah
- Debug sequences, should all be built in or user extendable
- Ulf
- CLI for hobby purposes, with environment variables
- Would like to use DAP more
- Factory flashing
- Scott
- HIL testing at Espressif, using embedded-test
- CLI use case, get backtrace when interrupting
- Ideas / Feature requests
- Client / Server setup
- Support for heterogeneous chips (ARM + RISCV / Xtensa + RISCV)
- Stability guarantees for command line / Bindings to other languages (python)
- Python bindings in a separate crate
- separate binary?
- would help with documentation (changing flags)
- Stabilize both lib and CLI?
- Packaging
- Add to debian
- Split out debugging
- Connect to emulator for testing
- Debug host programs
- Support bootloaders
- Not in probe-rs (lib)
- In cargo-flash
- probe-rs roadmap (existing)
- error handling / recovering
- multi-core support
- unlocking a single core
- starting / selecting multiple cores
- supporting multiple architectures on the same chip
- Support for new archs
- AVR
- TI MSP?
- Have a tier level? / Require support
- Triaging / PR handling
- Close old PRs / issues
- Improve the issue template
- Add a bug-report command
- Just create an issue
- Create a zip file with more data
- 64-bit systems
- Should we support it?
- Also related to new arch support / tier level
- WASM
- Support using probe-rs in the browser
- probe-rs is sync, which blocks everything
- Debug sequences
- manual match to select sequence currently
- support specifying debug sequence from external Rust code
- support for sequence in scripting language not a priority
- auto-discovery
- add manual support for every chip
- stm information could be read from cube-mx data?
- read information from cmsis-dap?
- reset support
- What kind of resets are there?
- Which function triggers a reset?
- flash algorithm
- improve template
- host source code
- rtt-on-probe
- j-link does it
- rp2040 based probe implements it
- Documentation
- Documentation for tools / end users
- on website
- Architecture documentation (internal)
- Target database on website
- Ref manual
- SVD
- etc
- more general rust-embedded?
- CI
- how to make secure?
- collaborate with embassy / tockOS
- Hardware (debug probe)
- What price point?
- Should we have a custom protocol / extension
- Why do we want to produce it?
- Multicore
- How to handle multiple cores
- Add parameters to session to specify which cores to connect to?
- Only connect to a core when the user requests to connect to it
- Gracefully handle cores which are not accessible,
- Requirements
- Do not automatically enable cores
- Offer a method to manually enable core (e.g. for flashing)
- Problems
- More flexible erase
- Lower level access than session is not possible
- Next steps
- Design a lower level interface
-
Friday AM2: HAL Examples
---
> Should we have a golden HAL example for new authors to reference?
Option 1: Embedded WG "blesses" some implementation
Option 2: Status quo: Awesome-embedded-rust remains the place to find available HALs with a variety of approaches.
There is a "guidelines for HALs" in the Embedded Rust Book https://docs.rust-embedded.org/book/design-patterns/hal/index.html. This might have slowed down innovation because people have blindly followed. This document misses some of the progress and new ideas from recent years.
We need a space for writing down ideas and the results. Without this, the disadvantages of previous/rejected ideas are lost as well as the trade-offs for adopting the current approach.
The embedded-hal traits deliberately do not standardise the construction of peripheral types. This is where HALs differ from each other and where more alignment between HALs would be most benifical for users.
> What
should it look like? Do we make specific recommendations for best practices
around things like generics, pin ownership, …?
General consensus that the Embedded WG should not bless/maintain a golden HAL, **but**:
The guidelines currently in the Embedded Rust Book could be complemented by:
* Describing multiple design patterns and the trade-offs between them
* Link to HALs which implement different design patterns (even though these links might eventually rot)
This could be in the Embedded Rust Book or in the Embedonomicon.
Similar work going on in esp-hal [API-GUIDELINES.md](https://github.com/esp-rs/esp-hal/pull/1543)
Friday AM2: Discussion with Rust Project
---
https://hackmd.io/GbZ7BWyzS9qD-8DaHJwfSg
# Project / domain sync
https://hackmd.io/Hy2dWIoMC
## Embedded pain points
* Panic-handling / formatting
* Size,
* but also speed
* Static mut
* People use it a lot
* Lacking TLS/allocator, have interrupts, need a way to grab state; some folks use static mut, lots of room for UB
* Better data structure crates (e.g., `OnceCell`) are an option
* Lots of embedded projects were broken by a recent lint-change
* If you have targets that lack atomics etc portably handling in a sound way is challenging; have mutex types and things that will switch off interupts, etc etc
* Regular statics are more stringent trait bounds
* Useful to specialize on send/sync if platform has only one?
* Not that much: interrupts but also
* multithreaded cores are coming
* But some places (e.g., TockOS) basically want a way to do thread-local data that is embedded friendly
* Feature flags
* sometimes they are not strictly additive (e.g., one per CPU variant)
* lots of embedded stuff needs build-time configuration
* can have 100 features for 100 memory sizes
* RFP available on this
* Target CPU features - atomics, etc.
* these are unstable and not always available
* targets are very "broad brush" (e.g., ThumbV8 etc covers 4 different processors each of which is orderable from ARM with between 3-5 distinct hardware configurations)
* and all the options to tell LLVM what's going on are unstable; you have to use negative target features
* either need a ton of target mechanisms OR a way to tune them
* don't want to do runtime detection of what features you have; sometimes you can't, sometimes you don't want the codesize
* Build std is not stable
* Really want to be able to build core, defaults are not good
* In std things tend to be optimized for speed, not codesize (e.g., they use a lookup table)
* If you could build std, you could change those choices (supply alternative impl)
* Amanieu suggested we add a flag, but stabilization is blocked on build-std
* Cargo: nobody is advocating or tracked it. Team is not opposed but needs an owner. And an owner that is deep expect willing to work with team to understand the space.
* Opportunities for narrowing the problem?
* Embedded has common needs, do we need the full generality, or should we specialize particular choices.
* Related needs "feature evolution"...
* "negative features"
* improved "no default features"
* deprecated features
* unstable features
* ...some of them have RFCs, of varying quality
* Build-std RFC ...
* ...how does libs commit to feature space? are we worried about that?
* ...do we combinatorily test all 30 options?
* mara: depends
* Code size folks often wind up depending on nightly especially
* e.g., panic-immediately-abort
* would be good to have an end-game to stabilize a subset in next few years
* Amanieu: build-std is the hard part, figuring out the set of stable/unstable features seems relatively straight-forward
* DMA
* you need to setup a transfer
* but then you get a callback for when it's done
* can have a drop guard that disables DMA
* but because we are leaking a ref o the stack
* Amanieu: why not scope threads?
* async makes it harder
* Unsafe code guidelines are pretty unclear, esp when you have DMA or hardware that could change things under the hood
* Should that be safe? unsafe? how does it interact with rust memory model? leads to long discussions that don't go anywhere
* niko: I would like to know the specific things for which we need rules to give prioritization to "which questions need an answer"
* hours and hours talking to Ralf =)
* grounded has been coming out of that
* happy to compile concrete examples :)
* UCG: used to be illegal to have references to memory mapped structures, we conded defeat and went back to "automatically calculating things"
* C-ism is you declare a struct and get a reference to it in memory
* issue is the derefernceable attribute that lets reads trigger it; but in mmio reads can have side-effects
* it was technically illegal but never observed miscompilation
* went back to codegen of a lot of pointer offsets
* have wrappers that call volatile/read/write
* ideas for how to make that better going forward
* "even more sound" -- not a thing!
* "code is so good it's used as a compiler and doc generation benchmark"
* "only takes a few minutes to build..."
* `cursed` keyword
---
* Leak auto trait
* Niko to Dirabio: basically you want to be able to guarantee dtors run ? i.e., the async case that I'm already aware of? (DMA, io-uring, etc) Can you list out the use cases to be sure we're aware of them all?
* Yes, make sure drop runs. MustMove is "too strong", we do want to allow dropping things, we just want to ensure Drop runs.
* must move can be too strong for two reasons
* it's annoying to call drop explicitly
* we expect a lot of type system pain, e.g., value will have to be put into data structures and things in a way that could be bad
* which do you mean? sounds like the former primarily.
* both, I think? for example MustMove would mean a combinator like `with_timeout(dur, fut)` wouldn't work, because it'd have to drop the fut on timeout. And it's very "infectious", any future that awaits a MustMove future also becomes MustMove.
* Use cases are
* Futures that await DMA to finish
* https://github.com/embassy-rs/embassy/blob/9cbbedef793d619c659c6a81080675282690a8af/embassy-nrf/src/uarte.rs#L652
* https://github.com/embassy-rs/embassy/blob/9cbbedef793d619c659c6a81080675282690a8af/embassy-stm32/src/dma/dma_bdma.rs#L698-L699
* https://github.com/embassy-rs/embassy/blob/9cbbedef793d619c659c6a81080675282690a8af/embassy-rp/src/dma.rs#L184-L187
* Structs (not futures!) that keep DMA running in the background all the time (to a buffer ,.read() and .write() just pop/push data to the buffer.)
* this means async-specific fixes like "completion futures" are not enough.
* https://github.com/embassy-rs/embassy/blob/9cbbedef793d619c659c6a81080675282690a8af/embassy-nrf/src/buffered_uarte.rs#L508-L509
* io-uring (essentially same as DMA, except done by the kernel instead of the hardware)
* Things that borrow buffers, and register themselves in some "global list", and must deregister themselves on drop to avoid use-after-free on the buffers.
* https://github.com/embassy-rs/embassy/blob/9cbbedef793d619c659c6a81080675282690a8af/embassy-net/src/tcp.rs#L361
## Non-technical pain points
* Infrequent conversation
* Why is it so hard to get everyone in the same room together?
* Doesn't help that embedded WG is in Matrix
* when stuff comes up in other domains, easier to ping
* Always been "on the side" and "self organizing"
* part of the project but not part
* Can we get on the team charts? e.g. embedded
* async is kind of different, mostly people working on async in compiler/lang, not a group covering all usage of async in the same way
* Mara: I think it'd be nice to have more organized things covering domains
* same solution for embedded, game-dev
* Might be a good idea to extract out a "core" group that is doing compiler/lang and close things
* Right now everybody in the WG is in theory a maintainer of people who maintain crates
* Don't have a way for folks to join who don't want to do that but do want to be involved
* Why *not* have an embedded team?
* maybe it's a question of *what* the team should do?
* Why does it make sense to have a team?
* Tightly interconnected
* Where did lack of team cause issues?
* When async first launched it needed work
* Jonas, X were able to address it
* Code size is not being prioritized
* Mara has started that, which is good
* Going faster, smoother
* Lacking "backchannel ties" feel like concerns aren't being heard
* Haven't known where to show up for help, or haven't had a place to go for advocacy
* Seeing the difference in outcomes of when we had someone in the project, they become show-stoppers
* Ed Page: just being a team may not help, usually you need an owner within the cargo team that ensures this doesn't get dropped on the table
* We've been doing office hours to help get access
* But didn't know about office hours, we've been trying to reach out
* Maintaining the shared crate: yes a team.
* A team that doesn't have ownership, not decision maker, is not going to make any difference
* Don't have preferred channels between teams, it's more just people who are active
* How much of the issues are because embedded's not a team, vs project, thinking about why the communication breaks down is important?
* Typically channels (teams repo, shared infra, calendar repo, zulip), all@ -- biggest issue for embedded WG is that we don't have a reliable way to communicate for embedded WG
* Is the easiest first step just getting people on Zulip actively communicating?
* Clearly there is a communication problem, e.g. idea for how to drive code-size has not reached
* "how to reach and interact with the teams is more effective"
* How Tock ultimately dealt with this is that a contributor was pushing on code-size
* do-ocratic means folks h
* Weekly meetings .. hold them on Zulip?
* easier to tag
---
* Problems
* Advancing priorities (major new development)
* there *has been* no roadmap, not a secret one, so that was the challenge
* code size: would need owners, work within teams
* Ensuring embedded needs are considered during regular maintenance
* Inclusion in CI - make sure we don't break them
* Providing guidance to new users so they have "official" references to find
* "on the shelf"
* Maintaining that content
* PoC for vendors to contact and raise questions
* Visibility:
* checking every single PR to be sure nothing impacts embedded size, a lot of work, I shouldn't have to do it
*
---
Jack's Proposed Clear wins and steps
* Embedded WG to be active on Zulip
* Regular meetings is very helpful, can ping folks
* Embedded people should interact with the teams in the spaces they inhabit
* This will go a long way
* Create project goals
* New lead for the binary size WG?
* Thinking about concrete answer to are the libraries for the different architectures, target features, etc, the things that they maintain: important for the Rust project
* Ultimately: Council question
* If answer is yes, we need to find a place for them
* From there we can figure out how things are going
* Mara wants to talk to people 1:1 every few weeks!
---
Proposed taxonomy (Niko+Jack, didn't discuss)
* taxonomy (proposed)
* teams
* maintenance, long-term vision of *something*
* project
* owner
* tracking issue
* ping group
* no structure
---
But:
* took a long time to get people to approve PRs that modify embedded WG homepage, roster, etc
* we exist but people are not aware of us
*
---
Options
* Multiple groups
* Small team in Rust-land for maintaining a particular library
* Advocacy, language, etc (~5)
* Maintaining core crates (~10 more)
* External "interest group"
* space for users to congregate
* representation from chip vendors
---
* What we want and need (Niko's take for now)
* Rust users who want to do embedded development have a clear "getting started point"
* books, tutorials
* crates that meet common needs
* Standard set of useful core interop libraries and books that are well-maintained
* *And* always possible to not use them
* Rust language, compiler, and toolchain are aware of the needs of embedded development and are prioritizing those needs
* This should include the full range of embedded developers
Friday PM2: Static mut
---
* Static muts are being deprecated and now generates a warning
* But we like to use it in Embedded
* It can be very hard to use safely
* For example doesn't check if contents are send/sync
* Very easy for even experienced users to trigger UB
* Can be hard to motivate the problems because often the UB doesn't trigger a miscompilation
* @jamesmunns has been working on the grounded crate to provide abstractions for safely using mutable statics
* Uses UnsafeCell which you may hold aliasing pointers to
* Some types will be completely safe to use, like StaticCell and ConstInitCell
* Some unsafe types, for example to preserve data/flags between reboots
* There are some examples in the book but there are snags around custom section initialisation etc, so the examples very easily lead to UB
* There are some uses of static mut that are OK, like the singleton macro in cortex-m
* Do we officially recommend grounded? Do we teach the underlying step?
* Question about higher level APIs and what they could look like
* Should we put out a public announcement about this transition away from static muts? With what alternatives?
* When do these new types get important enough to be owned by the WG, or even by libcore?
* There are discussions about the requirements users have for static muts and what the workarounds and alternatives are
* One motivation for removing static muts is that there are viable workarounds
* We feel like embedded is most impacted
* Could raise this on Zulip
* There may be different specific constructs that make sense in different environments, which may be a good reason to not upstream a specific solution (RacyUnsafeCell?)
* Use cases for static mut
* Sharing things with IRQs (also mut), moving things into IRQs
* Tock have experimented with high-level APIs similar to grounded, including some tweaks that are a better fit for their needs
* Including a safe thread-local storage that uses a platform-speciifc API to check which thread/priority/etc you're operating on
* Grounded may be useful for TockOS. Especially if it has an extensive and useful test suite.
* Different requirements between inter-application and intra-application use cases, for example bootloaders, operating system kernels
* Could we have miri analysis? Possibly on libraries but hard on applications as we can't run them under miri. Grounded's tests do run under miri.
* It's a very foundational data type, so should it be in a crate or in core? Perhaps split based on needing critical-section?
* At least having lots of clear safety-related docs leads others in the right directon too
* Could cortex-m-rt provide a better interrupt macro that helps with sharing things with an interrupt?
* We want these things to be composable and easily swappable in the future if need be
* StaticCell is very similar, could have been implemented in grounded if it didn't already exist
* Having good defaults that are built in to our WG crates make sense, especially for beginners. More important and urgent is having documentation of the history and requirements, enumerating the legitimate use-cases for some kind of mutable statics, and the common core of how to do that soundly. The rust project can use this too. We want to know what semantics we can rely on.
* Perhaps a single crate that contains every related struct would be helpful, and its documentation could clearly set out when and why to use each type (maybe as a decision tree)
* Adam suggestions:
* Update docs as discussed above
* Tidy up crate to make it as easy as possible to start using (currently starts off as a few modules etc)
* RFC to move to libs team
* Begin discussions with project once we have this list of what we need it for, what we use instead, what the new types look like, and whether we can move any of our new types into core
* and also whether new types in core (UnsafeRacyCell etc) could be used in grounded instead
* Noted it will be removed in 2024 edition so we have ~5 months to do something
* Technically can keep static mut and use addr_of but it's not simple to do this soundly at all
* Will follow plan above.
Friday PM2: Code size
---
* Two areas to look at
* Code size in general from rustc
* We spoke a little about this in the project chat
* The std lib could have flags to swap between fast and small algorithms
* though this will require build_std as well to become stable
* this can solve problems like std count() on a string...
* demo shows saving 150 bytes by mapping chars to units, up to 1kb
* std isn't usually affected by opt-level (though LTO can interact with this),
but we want specialisation of algorithms here so opt-level isn't really relevant
* core fmt vs microformat, for example formatting runtime integers
pulls in a 200b LUT in std
* slice has a rotate function that is also very optimised for speed,
probably from lowering to memcpy
* could this be fixed per-target? no, should always be a flag, although
we might well default the flag choice depending on the target
* the Write trait use is also different in std/microformat: in std it's a trait object
which means vtables are always along for the ride, while in microformat the input is
a generic so the optimiser can usually see into the format and do a good job
* can't easily fix this as it's part of the public API in std
* project people seem keen on adding a size opt flag to the compiler, @dion is happy to investigate that
* saw an example for cm55 with vector unit where opt-level z emits a long loop but opt-level 3 emits the tiny vectored addition
* Perhaps we can do better at tracking bloat in rust-lang PRs by extending our examples that rust CI run, perhaps also compiling at all opt-levels to compare too
* Noted that perf.rust-lang does track binary size of some embedded projects, but it reports ELF size and not binary code size
* Currently we test a PAC as a lib, but we could add a <30s binary application
* Rust size benchmarking
* Benchmark project would be fine to add some reasonable sized OSS (<30s compile time for the project itself) application to the bench suite. Possibly Stabilizer (~350kb)
* The triage team might also incorporate binary sizes into their process
* Async code size
* Hard to debug where size is coming from
* Needed to look into debug info where full names finally appear
* Can we improve debuggability? Or make the compiler better at async code size?
* Send commit diff with before/after code size to compiler team?