M0AGX / LB9MG

Amateur radio and embedded systems

  • Thread-safe event passing in wxPython

    wxWidgets are my favourite widget toolkit for making quick and dirty utilitarian interfaces in Python. The bindings are called wxPython. Why I like wxPython? I find Tkinter too basic, Qt needing too much boilerplate code, and GTK (PyGobject) too fiddly to set up on Windows (maybe it has since improved). While getting wxPython is as easy as pip install wxPython on all platforms.

    Most applications run some kind of background tasks. If the whole application was single threaded the GUI would freeze until the background tasks complete so a common technique is to have separate threads for the GUI and the "backend". Multithreading naturally leads to the issue of synchronization. For example you should not destroy a button from one thread when it is being repainted by another thread.

    Read more...

  • Multiprocessing - Python's best kept secret

    I use Python for most of my offline data processing needs. Recently I had to analyze a big set of data from an experiment. The unit task was not that difficult, open a file, run a couple of algorithms, and calculate several metrics from the signal. It took around ten seconds. All done in Scipy and NumPy. The "only" problem that I had thousands of files with a total volume around 20 GB. It should be trivial to parallelize - or so I thought.

    Read more...

  • Best practices in firmware

    Across the years spent writing firmware I have come across techniques that have helped me with reliability, meeting delivery deadlines, and overall "debug quality of life". In this article I want to focus on developments practices and lifehacks that apply uniquely to firmware and avoid the ones that apply to "big" desktop or server software.

    This article will be updated as more ideas become crystallized so please add my blog to your RSS reader. 🙂

    Updated on 19.08.2024 : added section about stack usage (at the end of the article). Thanks Alan! 🙂

    Read more...

  • Connecting a high speed parallel ADC to SAM E70

    ADCs come in all shapes and sizes. Converters built into MCUs made great progress across the years but sometimes you need a dedicated discrete ADC. At the extremes of the "speed spectrum" there are "slow but precise" ADCs (that tend to use SPI or I2C), and absolute monsters with SerDes outputs that can only be consumed by an FPGA.

    My application needed an ADC from the middle ground but with multiple channels and simultaneous sampling. Interfacing a medium-speed multichannel ADC to an SAM E70 MCU turned out more interesting than I wished for. 😊

    Read more...

  • 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...