Memfault's engineering blog publishes in-depth embedded firmware articles on Cortex-M, bootloaders, linker scripts, Rust, and tooling.
Commenters call it one of the best resources for Cortex-M embedded work, praising consistently good posts, the fault debugging article, and the monthly roundup.
Here are some that I've been following why working on my newsletter (https://weeklyrobotics.com/). These will be mostly robotics oriented, and some of them might be inactive:
* [Robots&Chisel](http://www.robotandchisel.com/blog/) - a blog by Michael Ferguson, he did a very nice series of posts on restoring a UBR-1 robot and implementing ROS-2 on it
* [Mike Isted](https://mikeisted.wordpress.com/) - at one point Mike was writing quite many blog posts on making drones, including some offboard control and autonomy
* [The Interrupt](https://interrupt.memfault.com/) - in-depth blog about embedded programming. Really like their monthly "What we've been reading..." series
* [Electron Dust](https://www.electrondust.com/) - inactive, but a really cool series of blog post on making a ball bouncing robot
* [Casey Handmer blog](https://caseyhandmer.wordpress.com/) - some very in-depth articles related to space
* [Modicum of Fun](https://jpieper.com/) - a blog post of Josh Pieper, who makes mjbots open-source motor controller
Other:
* [Julia's Drawings](https://drawings.jvns.ca/) - neat presentation of various technical concepts in programming. Unfortunately it's not active anymore.
> Async Rust (by default) can allocate memory
For bare-metal Rust firmware, you would always use no-std, which excludes a default allocator.
I understand from what you're saying that the principal difference between embassy-rs and what you'd expect from an RTOS is the choice of scheduling; as far as I can see, embassy-rs'es cooperative scheduler is even defended as highly intended.
The advantage of cooperative scheduling is that you don't need threads and context switching, since every yield gives control to the next task. And, as you say, the downside is that you can't reason about when yielding happens, so you can only hope that tasks yield often.
> interrupt executor [...] essentially ties each task to a dedicated interrupt, and AFAICT requires that all high-priority work must happen in interrupt context.
Hmm, that seems bad.
And how so is RTIC disqualified? It seems not classically preemptive.
https://rtic.rs/2/book/en/#rtic---the-past-current-and-future
https://interrupt.memfault.com/blog/embedded-async-rust#cooperative-vs-preemptive-scheduling
https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown
Working with / compiling from source code (portable/non-portable): cosmopolitan libc[0]
Each language kinda has own tricks,java[3], rust[4]
From [1] : " A comparison of dietlibc, uclibc, musl, and glibc, by the author of musl: http://www.etalabs.net/compare_libcs.html "
How to make smaller C and C++ binaries[7]
Removing unused code[5] / Exploiting function similarity for code size reduction[6]
-------
[0] : a) https://justine.lol/cosmopolitan/
b) size tricks : https://justine.lol/sizetricks/ [1] : Dietlibc - a libc optimized for small size : https://news.ycombinator.com/item?id=21291893
[2] : https://interrupt.memfault.com/blog/dealing-with-large-symbol-files
[3] : java : https://www.graalvm.org/latest/reference-manual/native-image/guides/optimize-native-executable-with-pgo/
[4] minimizing rust : https://github.com/johnthagen/min-sized-rust
[5] : https://tetzank.github.io/posts/removing-unused-code/
[6] : https://dl.acm.org/doi/10.1145/2666357.2597811
[7] : how to make smaller c and c++ binaries : https://news.ycombinator.com/item?id=35853625
GDB is happy to deal with separate debug info files from the executable code - and has been approximately "always", as far as I'm aware. But it's not particularly common / well-understood how to actually achieve it.
Some info here on how to configure GDB to use it: https://sourceware.org/gdb/current/onlinedocs/gdb.html/Separate-Debug-Files.html
The old-school way appears to be to extract the debug information from the binaries after compilation, then strip the binaries. As described here: https://stackoverflow.com/questions/866721/how-to-generate-gcc-debug-symbol-outside-the-build-target
The new way is to use gcc's ability to generate split DWARF directly: https://interrupt.memfault.com/blog/dealing-with-large-symbol-files#splitting-debug-info-at-build-time
This will work with debuginfod but you don't have to have that running to use these - you can just supply the symbol directory when you want to debug.
Direct link: https://interrupt.memfault.com/blog/eoss-recap#engineering-secure-ssh-access-for-engineers
> Colin (Garmin) goes through the challenges for enabling SSH access to devices in production. Passwords and secret keys are not great solutions: if you share one across all your devices then a leak would be catastrophic. And a leak is hard to protect against because the engineers need the keys with them when doing maintenance work. So instead, he recommends using certificates to create keys that are only valid for one hour or one day. The device SSH daemon validates that the engineer key has been signed by the proper certificate, and that we are still within the correct validity period. This way, the only real secret (the private key used to sign the keys) can be stored in a very safe storage, engineers are only granted access for a few hours (so an ex-employee will not have access anymore).
> If I understand correctly, when an initializer is provided the padding bits are set to 0.
https://interrupt.memfault.com/blog/c-struct-padding-initialization looks at this (albeit a bit outdated; clang 13 and GCC 11) and claims to see undefined values even when initializers are given, at higher optimization levels
> Additionally, setting the whole chunk of memory to 0 w/ memset would work.
This seems to be the only thing that can be relied on to work (… sadly)
An alternate answer is: don't treat structs as chunks of bytes when the chunk crosses padding (i.e. create functions to hash specific structs)
Another alternate answer: remove the padding and add "_pad12[34]" members instead. But then you need to figure out where you actually have padding, which is architecture dependent…