M0AGX / LB9MG

Amateur radio and embedded systems

  • Triggering DMA from timers (or GPIO) on the SAM E70

    The SAM E70 is still a powerful MCU despite being released around 2015. It has a 300 MHz Cortex-M7, 150 MHz bus system and high-speed USB. High-speed USB (not the same thing as USB 2.0) is pretty rare in Cortex-M devices. It is usually the domain of much more powerful Cortex-A chips. When developing a data acquisition system on the SAM E70 I was surprised that there is no obvious way to trigger a DMA transfer from a timer!

    Read more...

  • Interrupt remapping on Cortex-M0 (and other small chips)

    Interrupt remapping is the ability to change the interrupt handlers at runtime. Why would you need to change handlers on the fly? During "normal" operation this is indeed unlikely. A simple branch like if (something){ handle1(); } else { handle2(); } in the handler is enough. Remapping is useful when there are totally different applications running. For example a manufacturing test application and a regular application, or a bootloader and the application.

    Read more...

  • Lifehack: detecting debugger connection for Cortex-M0 & Ozone

    I find it useful to be able to detect from firmware if a debugger is attached. For example when an assertion fails I can use a simple __BKPT(123); to stop the code and immediately inspect everything manually in the debugger. In the field I would rather prepare debugging breadcrumbs and reset. Of course having two different firmware behaviours comes with its own risks. For example enabling debug output can affect timings and make some bugs (dis)appear. However, when hunting bugs this is also an important information on its own.

    Read more...

  • Reducing Home Assistant RAM usage

    I tried running Home Assistant with zigbee2mqtt on an A20 OLinuXino board that has only 1 GB of RAM. Startup and initial operation was okay but after a random while (days) the system locked up and become unreachable over the network. Without Home Assistant the board was running okay for weeks so I guessed that it must have been RAM usage.

    Read more...

  • Very simple stack overflow detection for Cortex-M and RISC-V

    There are many ways of detecting and dealing with stack overflow in embedded systems. Here is a very, very easy stack canary with minimal overhead that can be used on Cortex-M and RISC-V with GNU and LLVM toolchains.

    Read more...

  • Yet another autossh tutorial

    SSH remote port forwarding is very useful to access machines behind firewalls and NATs. The ssh client connects to the server (the server must be publicly reachable). The server then starts listening on ports requested by the client and passes the traffic to the client. To the outside world this looks like the public machine has extra services running.

    I find this scheme especially handy to access devices connected using 5G. Mobile networks almost never provide public IP addresses and use CGNAT unless you are a big business customer.

    Read more...

  • Abusing reserved interrupt vectors on Cortex-M for metadata

    Bootloaders in embedded systems need a way to tell if there is a valid application available in memory. Executables on devices with an operating system use elaborate file formats like elf and exe but small bare-metal bootloaders need something simpler to keep both the bootloader size and the application size small. In this post I present the simplest possible scheme - a single CRC32 checksum appended to a raw binary file and how to do it.

    Read more...

  • Wiznet W7500 flash programming

    W7500 is a nice little MCU from Wiznet with a built-in hardware TCP/IP stack and Ethernet MAC. You can get quite far with your IoT application on a Cortex-M0 running at 48 MHz when the networking is offloaded in hardware. The device begins to show its age in 2023 (it was released around 2016). There is no crypto acceleration whatsoever, no AES. Only an RNG is available. I think that modern TLS is practically impossible but some lighter cryptography should be possible. Nevertheless, if you can put the device on an isolated VLAN the chip can still be useful today.

    Read more...

  • Listing stuck Python threads

    More than once I have been in the situation where a multithreaded Python application (eventually 😁) runs fine, all the threads cooperate nicely, but do not shut down cleanly. This for example happens after closing GUI windows where the GUI goes away but some worker threads do not. A Ctrl+C might help to shut down the stuck application only if the main thread is stuck. Still, every application should shut down cleanly so that it can be correctly monitored and restarted by init / systemd / wrapper script etc.

    Read more...

  • Recovering a bricked Wiznet W7500 using the bootloader

    I "bricked" a Wiznet W7500 MCU during development. After flashing yet another build of the firmware the J-Link disconnected suddenly and I was not able to connect to the chip again (even under reset). What's funny is that the LEDs blinked as usual and I was able to ping my application so the chip was far from being dead. I quickly found the suspected piece of code: pin muxing. When changing PORTA muxing options I must have un-muxed the SWD pins. 🙁

    Read more...