Reinterpreting The Lua Interpreter

The idea behind Lua is a beautiful one. A simple and concise syntax offers almost all of the niceties of a first-class language. Moreover, a naive implementation of an interpreter with a giant switch case can be implemented in an afternoon. But assembly is your go-to to get decent performance in a JIT-style interpreter. So [Haoran Xu] started to ask himself if he could achieve better performance without hand-rolled assembly, and after a few months of work, he published a work-in-progress called LuaJIT Remake (LJR).

Currently, it supports Lua 5.1, and on a smattering of 34 benchmarks, LJR beats the leading fastest Lua, LuaJIT, by around 28% and the official Lua engine by 3x. [Haoran] offers a great explanation of interpreters that provides excellent background and context for the problem.

But the long and short of it is that switch cases are expensive and hard to optimize for compilers, so using tail calling is a reasonable solution that comes with some significant drawbacks. With tail calls, each case statement becomes a “function” that is jumped to and then jumped out of without mucking with the stack or the registers too much.

However, the calling convention requires any callee-saved registers to be preserved, which means you lose some registers as there is no way to tell the compiler that this function is allowed to break the calling convention. Clang is currently the only compiler that offers a guaranteed tail-call annotation ([[clang::musttail]]). There are other limitations too, for instance requiring the caller and callee to have identical function prototypes to prevent unbounded stack growth.

So [Haoran] went back to the drawing board and wrote two new tools: C++ bytecode semantical description and a special compiler called Deegen. The C++ bytecode looks like this:

void Add(TValue lhs, TValue rhs) {
  if (!lhs.Is<tDouble>() || !rhs.Is<tDouble>()) {
    ThrowError("Can't add!");
  } else {
    double res = lhs.As<tDouble>() + rhs.As<tDouble>();
    Return(TValue::Create<tDouble>(res));
  }
}
DEEGEN_DEFINE_BYTECODE(Add) {
  Operands(
    BytecodeSlotOrConstant("lhs"),
    BytecodeSlotOrConstant("rhs")
  );
  Result(BytecodeValue);
  Implementation(Add);
  Variant(
    Op("lhs").IsBytecodeSlot(),
    Op("rhs").IsBytecodeSlot()
  );
  Variant(
    Op("lhs").IsConstant(),
    Op("rhs").IsBytecodeSlot()
  );
  Variant(
    Op("lhs").IsBytecodeSlot(),
    Op("rhs").IsConstant()
  );
}

Note that this is not the C keyword return. Instead, there is a definition of the bytecode and then an implementation. This bytecode is converted into LLVM IR and then fed into Deegen, which can transform the functions to do tail calls correctly, use the GHC calling conventions, and a few other optimizations like inline caching through a clever C++ lambda mechanism. The blog post is exceptionally well-written and offers a fantastic glimpse into the wild world of interpreters.

The code is on Github. But if you’re interested in a more whimsical interpreter, here’s a Brainf**k interpreter written in Befunge.

Making SVD Files Searchable With Svd2db

Everyone who writes bare-metal code for microcontrollers probably know the joys of looking up the details of specific registers in the reference manual, including their absolute address. Although the search function of the PDF viewer can be helpful, it’d be rather nice if there was a way to search only the registers, and have the offset calculations performed automatically. This is basically what [Terry Porter]’s Svd2db tool enables. As the name suggests, this tool turns the SVD hardware description files that come with ARM-based MCUs into a database file.

This database file is an SQLite database, which allows it to be searched using the provided readdb tool, or any other SQLite tool. This would make the utility useful not just for quick look-ups during development, but presumably also for automated testing scenarios where having an easily searchable database of registers is of use. At this point Svd2db is guaranteed to work with STM32 SVDs, but may work with SVDs for other ARM-based SVD files as well.

 

Pretty Petite Picolibc Powers Processors

Many times when someone tells you that language X is “better” at something they really mean that it has better built-in libraries for that task. Java is a great example. The language isn’t all that different from C++ outside of garbage collection and multiple inheritance, but the standard libraries are super powerful, especially for networking.  Even C relies on a library to provide a lot of functions people think of as part of the language — printf, for example. That’s not really part of the C language, but just part of the standard library. When you are writing for a tiny processor, the choice of library is critical and [Keith Packard] offers you one choice: picolibc.

The library has its genesis from two other diminutive libraries: Newlib and the AVR version of libc. It provides support for ARC, ARM, i386, m68k, MIPS, MSP430, Nios II, PPC, RISC-V, Sparc64, x86_64, and the ESP8266/ESP32.

Continue reading “Pretty Petite Picolibc Powers Processors”

Creating Your Alarm On The Fly

We suspect that most of us who use an alarm clock have our particular sound memorized. Common choices are annoying beeping, energetic marimbas, or what used to be your favorite song (which you have now come to despise). [Adam Kumpf] wanted a more pleasant alarm clock and came up with WakeSlow, an alarm clock audio stream, which is a spiritual successor to an earlier project he did called Warmly.

Some might say, “an audio stream? You could create an acceptable alarm tone generator with a 555 and a 2N2222”. The idea behind WakeSlow is to use your existing internet-connected alarm clock that can play an audio stream. You generate a URL using WakeSlow, and it plays the alarm. A custom URL is helpful since it incorporates weather data, letting you know if it’s going to rain, blowing wind, or be sunny that day. It mixes CC0 audio to form the stream, and includes a 5-minute fade to wake you up gradually. After five minutes, it’s jazz time, and it plays a sample of some CC0 jazz.

The code is super simple, and he makes it available on his website under a public domain/CC0 license. The simplicity offers something powerful, making it exactly how you like it. You could incorporate holiday information, a text-to-speech news announcer reading the news of what’s on your calendar that day, or anything you can dream of.

Hackers are generally particular about clocks, and alarm clocks fall under the same umbrella. WakeSlow allows you to skip the hardware part of making your customized alarm, but if you prefer to have the whole thing be custom, we have a few suggestions for alarms to look at.

PySpectrometer version 2, showing mini spectroscope, 4 inch display and hand for scale

Pi-based Spectrometer Gets An Upgrade

Here at Hackaday, we love to see projects re-visited and updated after we’ve covered them on the site. It’s always exciting to see what the creators come up with next, and this Pi-Based Spectrometer project is a great example of that.

[LesWright] found himself with a problem when the new version of Raspberry Pi operating system was released (Bullseye), and it broke some functionality on his original software. Rather than just fix the issues, [Les] chose to rewrite the software more dramatically and has ended up with a much more capable spectrometer that is able to match professional devices costing many times more.

Screenshot of Waterfall Display for PySpectrometer 2
Screenshot of Waterfall Display for PySpectrometer 2

By using multi-wavelength calibration and polynomial regression data, the new version is much more accurate and can now resolve wavelengths down to +/- 1nm.

The whole project is now written in OpenCV, and there’s a nifty new waterfall spectrum display, that will show changes in measured spectra over time.

A low-cost benchtop spectroscope is coupled to a RaspberryPi Camera via a CCTV zoom lens and the whole setup is mounted to a small block of aluminium for thermal and mechanical stability. The spectroscope is pointed at a fluorescent lamp and the user is guided through a calibration routine to tune the software to the hardware.

We’re impressed with the precision [Les] has achieved with his builds, and the write-up is sufficiently detailed to allow others to follow in his footsteps. We’d love to see if readers build one themselves, and what they use them for!

If you want to read up on the original build, you can find our article here. We’ve covered several spectrometry projects in the past, including this Gamma-Ray Spectrometer and this one based around an STM32 Nucleo board. Continue reading “Pi-based Spectrometer Gets An Upgrade”

Bare-Metal STM32: Setting Up And Using SPI

The Serial Peripheral Interface (SPI) interface was initially standardized by Motorola in 1979 for short-distance communication in embedded systems. In its most common four-wire configuration, full-duplex data transfer is possible on the two data (MOSI, MISO) lines with data rates well exceeding 10 Mb/s. This makes SPI suitable for high-bandwidth, full-duplex applications like SD storage cards and large resolution, high-refresh displays.

STM32 devices come with a variable number of SPI peripherals, two in the F042 at 18 Mb/s and five in the F411. Across the STM32 families, the SPI peripheral is relatively similar, with fairly minor differences in the register layout. In this article we’ll look at configuring an SPI peripheral in master mode.

Continue reading “Bare-Metal STM32: Setting Up And Using SPI”

Arduino IDE v2.0 screen with callout tags to identify features

Arduino IDE 2.0 Is Here

Arduino have released the latest version of their Integrated Development Environment (IDE), Version 2.0 and it is a big step up from the previous release, boasting plenty of new features to help you to develop your code more easily.

As the de-facto way for beginners to get into programming hardware, more experienced users have sometimes complained about what they see as the over-simplistic IDE — even lacking relatively basic features such as autocomplete. The new version provides this, and much more besides. Continue reading “Arduino IDE 2.0 Is Here”