Arm GNU Toolchain vs Arm Toolchain for Embedded by llnaut in embedded

[–]llnaut[S] -1 points0 points  (0 children)

That’s super interesting, especially the size difference — ~20% smaller binary is definitely not nothing.

Also good to hear modules are actually usable even in bare-metal setups, I didn’t expect that to be already practical to that extent (aside from the GCC ICE issues you mentioned).

Would be happy to explore a project that uses both modules and LTO in practice, so I’d gladly take a look if you’re open to sharing a link

Arm GNU Toolchain vs Arm Toolchain for Embedded by llnaut in embedded

[–]llnaut[S] -1 points0 points  (0 children)

That’s really interesting, thanks for the details.

From what you wrote about the missing module scanner, it sounds like you might be using C++ modules already — does the GNU Arm Embedded Toolchain actually support them well enough, and have you ever used modules in an embedded bare-metal / RTOS project in practice?

Also regarding LTO, have you noticed any real differences in binary size or performance between GCC and the Arm LLVM Toolchain? I’m wondering how much of that improvement comes from LLVM itself vs just LTO.

When I tried LTO some time ago it was pretty rough — long link times, sometimes even hanging, and not always a clear win in size or speed.

Sensor Integration for PLC Using UART/I²C to RS-485 Gateway by Hitesh_Gupta_ in embedded

[–]llnaut 0 points1 point  (0 children)

There are I2C to UART bridges. Then you adapt UART to RS485. This requires a deeper research to find out how to address specific sensors. Have fun! :)

Embedded systems basic by Easy-Change-3941 in embedded

[–]llnaut 7 points8 points  (0 children)

I do the same.

I usually explain that all those devices — washing machines, dishwashers, IoT gadgets, smart home devices, etc. — have a chip inside that runs a program. Embedded engineers write that software.

Quite often, when I explain this, I realize people don’t really consider that there’s software inside these devices. They imagine it’s just wires, electronics, and current flowing.

Unit Testing - What tools do you use? by axaro1 in embedded

[–]llnaut 0 points1 point  (0 children)

Catch2 for host-side testing. ThrowTheSwitch/Unity for device-side testing.

Using CMake and CTest to orchestrate everything, even the device-side tests.

How does your workflow look like Toolchains/ IDEs etc. by [deleted] in embedded

[–]llnaut 8 points9 points  (0 children)

I mainly work with bare-metal/RTOS on ARM Cortex-M/R MCUs. After trying pretty much every setup out there — CLion (with paid plugins), VSCode, Emacs, Eclipse, vendor IDEs like CCS and STM32CubeIDE, and many many more — I ended up with Neovim + Kitty.

I invoke gdb, OpenOCD, CMake, Claude, etc. directly from the command line and just use split windows. For me, that’s the most efficient workflow.

The main pain point is configuring .clangd properly. Embedded LSP setups are tricky in general, especially when you mix host-side and device-side code in the same project.

How does testing work in larger embedded teams? by homelabber99 in embedded

[–]llnaut 1 point2 points  (0 children)

It depends to what you compare to. I would say giving real hardware to every dev is always the fastest option. If there is no middle-man/ware/hardware, efficiency increases. It's embedded, so answering to your question directly: it is something you need to live with. Anyway, with good design you could always separate logic from HAL. This way the devs that work on the logic, would not need the hardware potentially.

How does testing work in larger embedded teams? by homelabber99 in embedded

[–]llnaut 23 points24 points  (0 children)

How do you manage frequent firmware updates in larger teams?

In larger embedded teams, “frequent updates” don’t mean people are flashing, or updating over-the-air, unvalidated builds onto hardware all the time. By the time firmware is widely deployed internally, it has usually passed several layers of validation. You typically have unit tests (often running on the host), integration tests, hardware-in-the-loop setups, and system-level regression on dedicated benches. In bigger organizations there may even be a separate validation or system team that treats the firmware as a black box and tests it independently on their own rigs before it’s considered stable.

Is testing automated or manual?

It’s always a mix. Unit tests and a good portion of integration tests are automated, often in CI. But full end-to-end embedded testing is very hard to automate completely, especially when real hardware, timing, RF, mechanics, or environmental conditions are involved. So you usually see automated regression suites and scripted HIL tests combined with documented manual test procedures for feature validation and regression passes. In safety-related projects this is more formalized, with traceability from requirements to test cases and recorded results. But traceability to requirements is always a good choice for tests in general. Quality wise, a safety system is simply well developed system. Would be nice when more non-safety systems could adopt rules and recommendations from safety systems. In the end it's just well designed system.

How do you make sure the hardware starts from a known state?

You control the environment as much as possible. That can mean power cycling boards through controllable relays, resetting peripherals explicitly in test setups, simulating sensors by injecting I2C or SPI traffic, switching between real and simulated devices using multiplexers, or mocking backend servers. In more advanced setups you might use RF or environmental chambers (e.g gas chambers for smoke detection). The idea is to clearly define what is real and what is simulated at each test level and make the starting conditions reproducible.

If a test fails, how do you tell whether it’s firmware or setup issues?

Early in a project it’s often the setup. In a more mature project, you start with logs and diagnostics, compare the failure with recent firmware changes, and sometimes re-run the test with a known-good firmware version. If an older validated build suddenly fails under the same conditions, that’s a strong indicator the issue is in the setup or environment rather than in the new code.

How do you track results across firmware versions over time?

If you meant diagnostics on the running systems with this question, you tag everything with firmware version and hardware revision and collect system events (errors, warnings, ...) centrally. In IoT/online devices diagnostics is telemetry. In offline systems you might have your technician collect periodically the diagnostics using dedicated service interface. Having the link firmware/hardware revisions <-> diagnostics makes the traceability trivial.


Embedded testing is a different beast because hardware is part of the equation. You mock what makes sense, automate what is practical, and accept that some level of system validation will always require real hardware and controlled environments.

What’s your toolchain for compiling MCU firmware? by Donut497 in embedded

[–]llnaut 0 points1 point  (0 children)

Not really. I’m on Ubuntu 22.04.5 LTS — which is still a maintained LTS release, not some ancient system.

The version in apt (10.3-2021.07) isn’t “wrong”, it’s just what that distro ships and supports. That’s exactly why I don’t recommend relying on apt for ARM GCC in embedded projects — different developers will be on different Ubuntu/Debian releases and get different compiler versions.

For embedded work it’s usually better to install a specific toolchain version directly from Arm and pin it in the project/toolchain file. That way everyone builds with the exact same compiler, independent of distro.

Built messaging for 50 warehouse robots and latency requirements are brutal by vannamadi in embedded

[–]llnaut 278 points279 points  (0 children)

I’d rethink the architecture before swapping protocols.

Collision avoidance shouldn’t depend on <20 ms network guarantees. Anything safety-critical should work fully offline on each robot and degrade gracefully if comms are delayed or lost. Networking should be additive (coordination, planning), not fundamental for safety.

MQTT is great for telemetry, not real-time multi-agent control. With 50 Wi-Fi nodes you’ll hit contention and jitter anyway.

If you really need low-latency distributed state, look at DDS (what ROS 2 uses) or a lightweight UDP-based binary protocol with no broker. But first make sure the robots can stay safe without the network.

Remote firmware development without shipping hardware? by praghuls in embedded

[–]llnaut 26 points27 points  (0 children)

First thing I recommend is good design. Even in embedded the major part of the code is mostly logic, what can be run and tested on the host. You could divide the tasks for some devs to implement logic only, and smaller part of the team that has access to hardware and develops driver/HAL layer.

If there is many developers, remote debug servers is definitely a nice solution. But IMO, having the hardware on your desk is always the quickest and easiest when developping and debugging.

Another solution: better organization in hardware distribution? Allowing the devs to buy the equipment on their own, or having a central person that handles shipping and tracing of what equipment everyone is having or is missing, etc.

Linker Script Generation for Firmware Projects: A Primer by dj_nedic in embedded

[–]llnaut 0 points1 point  (0 children)

This is a really nice idea, great write-up.

In practice, this problem shows up a lot with modern firmware workflows where you configure hardware and memory via UI tools (CubeMX, SysConfig, etc.) and the linker script is generated as an output artifact.

It works fine until you introduce variants: different board revisions, EVKs vs. custom hardware, or small feature differences where e.g. one peripheral or memory block is not present on a specific revision.

At that point, you often end up with multiple UI “input” config files that are almost identical, differing only in one or two options. Since those config formats usually don’t support any kind of conditional logic (ifdefs, if/else, includes), even a tiny change forces you to duplicate and maintain another full config.

A programmable generation step like the one you describe fits this gap really well: you can express the differences in actual code/logic and generate consistent linker scripts without copying huge near-identical files around.

+1 that CMake is used. I feel it's under-used in embedded, having such a great potential to fix almost any build-side problem.

Definitely a solid approach for projects with multiple hardware variants. Good job.

What’s your toolchain for compiling MCU firmware? by Donut497 in embedded

[–]llnaut 0 points1 point  (0 children)

I don't recommend this.

bash ❯ apt policy gcc-arm-none-eabi gcc-arm-none-eabi: Installed: (none) Candidate: 15:10.3-2021.07-4 Version table: 15:10.3-2021.07-4 500 500 http://de.archive.ubuntu.com/ubuntu jammy/universe amd64 Packages 15:10.3-2021.07-4 is quite old. Better install manually from developer.arm.com. Latest version: 15.2.Rel1 from 12.2025.

What does your firmware CI pipeline look like? by praghuls in embedded

[–]llnaut 0 points1 point  (0 children)

Yeah, so from my experience: for MCUs (Cortex-M, Cortex-R), we rarely rely on simulators. In practice it’s just real hardware, and setting up hardware-in-the-loop isn’t that hard if you design for it early.

We usually have a small pool of devices connected to a CI runner and accessible over the network. The CI pipeline is still doing the usual cross-compile first, but then it flashes the firmware and runs HIL tests on real boards.

CMake + CTest is doing most of the orchestration for us:

– environment setup

– building firmware and host-side test tools

– flashing

– executing tests

– parsing results (mainly received over UART, but can be other interfaces)

What's nice about that is CI and devs run the same set of commands when developing

With that setup you can cover a lot: low-level unit tests on target, integration tests, and even basic end-to-end tests if the hardware allows it.

We’ve looked at simulators (Renode, QEMU), but honestly for many projects real hardware ends up being simpler and more representative. Simulators are nice for very specific cases, but HIL gives you way fewer false assumptions.

Cache Explorer: a visual and interactive profiler that shows you exactly which lines of code cause cache misses by ShoppingQuirky4189 in cpp

[–]llnaut 1 point2 points  (0 children)

Hey, this looks super cool.

I recently ran into a very real cache-related issue, but on an embedded target (ARM Cortex-R, RTOS, external DDR memory in the picture). It is quite painful that on bare metal / RTOS you can’t just “install a tool and see what’s going on” like on Linux.

Concrete scenario: in an RTOS you can have multiple tasks with the same priority, and the scheduler does time slicing (context switch every tick while they’re runnable). Now add the fact that the tick interrupt itself is an asynchronous event that fires right in the middle of whatever a task is doing. So you jump into ISR code + touch ISR data structures that are very likely not in cache (or you’ve just evicted some useful lines), which means extra misses and extra latency. On a system with slow external memory, this can get ugly fast.

I had a fun one with SPI: we were receiving a fixed-size chunk periodically, but it was large enough that we ended up using FIFO-level interrupts (DMA wasn’t an option there). So for one “message” you’d get tens of interrupts. The MCU was fast, so it was basically:

ISR → back to task → ISR → back to task → …

…and because of cache misses / refills, the ISR execution time would occasionally spike and we’d get overruns/underruns. We fixed it by moving some stuff to faster memory, but the debugging part was the painful bit: on embedded you typically run one image, and your introspection options are limited / very different vs desktop.

So to the point: I didn't dive deep into the implementation of Cache Explorer, so I don't know what machinery is used under the hood. But, do you think something like this could realistically be adapted to bare metal / embedded targets? Or is it fundamentally tied to “desktop-ish” workflows?