# Circle: bare metal C++ for the Raspberry Pi, with a disclaimer that tells you what it is

> A bare metal programming environment where the README is a running release log. The useful details are in the toolchain changes and the fixes for a USB MIDI problem that took several attempts.

**rsta2/circle** — A C++ bare metal environment for Raspberry Pi with USB (32 and 64 bit)

- Repository: https://github.com/rsta2/circle
- Website: https://circle-rpi.readthedocs.io
- Stars: 2,333 · Forks: 315
- Language: C
- License: GPL-3.0
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/rsta2-circle

## A C++ environment that GitHub files under C

Circle is a bare metal programming environment for the Raspberry Pi. It gives you C++ classes for hardware features, add-on libraries for specific purposes, and sample programs that demonstrate how those classes are used. Applications can be built as 32-bit or 64-bit.

GitHub labels the repository as a C project, and the README explains why in a paragraph worth quoting in full, because it is unusual to see a project reconcile its own language classification so plainly. The bundled third-party C libraries under addon/ are larger than the core, and since GitHub classifies by volume, the C wins. The main libraries are written in C++ with classes, which is why it calls itself a C++ environment.

That distinction matters for anyone searching. A query for a Raspberry Pi bare metal framework returns plenty of assembly, Makefile-driven and C projects, and Circle sits among them looking like the wrong language if you only read the badge.

The repository describes itself as a free open-source project created by makers for makers. The topics are bare-metal, c-plus-plus, raspberry-pi, tcp-ip and usb, which is an accurate five-word summary of the scope. The homepage is circle-rpi.readthedocs.io, and the license is GPL-3.0, which is a meaningful constraint for embedded work since it carries over into anything you link statically.

## The disclaimer is the most useful section of the README

The README opens its second section with a disclaimer, and it is more specific than most. Five points are stated.

There is no warranty, and the text names the three excluded warranties directly: merchantability, fitness for a particular purpose, and noninfringement. Testing is limited, because contributors test to the best of their ability but there is no dedicated testing department and nobody can validate every device, bootloader version or model revision. User responsibility is assigned to you, with a parenthetical that is worth noting because it is unusual: integrating Circle into a project, especially a commercial product, which the text describes as not recommended, means you are responsible for testing in your target environment and for the consequences.

Distribution is source only. No official binary releases are provided. And the closing point is a risk acknowledgement, where using Circle means accepting the residual risks of bare metal development.

For an embedded framework this is the correct level of candour, and it is more informative than a generic open source disclaimer because it names the specific failure mode: untested hardware combinations. A project that ships prebuilt SD card images invites the assumption that some organisation has verified them. This one refuses to make that claim, which is arguably why there are no binaries to ship.

Read the disclaimer before the feature list. It tells you that Circle is a well-maintained personal project rather than a vendor-supported product, and every other section of the README is consistent with that.

## A README that is really a running release log

Most of the README is release notes, and the naming convention explains the project's age. The current release is 51.1.1, which is described as the 51st Step. That is a numbering scheme, not a year, and it has been running for a long time.

Release 51.1.1 is a hotfix that reverts a commit. The specific problem: the commit did not allow lld to be used as the linker with Clang, and Clang is planned for use with circle-stdlib, the separate standard library project. The hotfix also adds a sanity check for the 8BitDo gamepad drivers.

A revert as a release strategy tells you something. It means a change shipped, broke a specific toolchain combination, and was pulled back within days rather than patched forward. That is reassuring about responsiveness and slightly less reassuring about pre-release testing, which is worth knowing given the no-dedicated-testing-department disclaimer.

Release 51.1 is the substantive one, and its structure is instructive. The headline is support for the official 5-inch and 7-inch DSI touchscreens, versions 1 and 2, on the Raspberry Pi 5, implemented in addon/rp1dsi and testable with sample/28-touchscreen and the LVGL sample in addon/lvgl. Using them requires setting the DSI_DISPLAY variable in the relevant Makefile, so it is a compile-time selection rather than a runtime one.

The second item is a bug that has defeated the maintainer more than once. Dropped USB MIDI events on the Raspberry Pi 1 through 3 and Zero were attacked again, with the cmdline.txt option usbboost= extended to take a bit-masked decimal parameter where each of bits 0 through 3 enables a different mitigation. Setting usbboost=15 turns everything on, and the README is candid that this only works when the MIDI controller is plugged into the USB root port with no hub in between.

If you use FIQ mode for USB on those older models, the release adds USB_MIDI_FIQ_COMPLETION to push event delivery latency to the minimum. The cost is that your MIDI event packet handler then has to run at FIQ_LEVEL instead of the usual IRQ_LEVEL, which is a real constraint on what that handler may do. There is also an optional USB_MIDI_CHECK_INCOMING to validate incoming packets before they reach the handler.

The smaller additions in the same release are the kind of detail that only a real user files. A new log severity called LogTrace exists for frequent trace messages, generated with the LOGTRACE macro and visible only when loglevel=5 is set in cmdline.txt. A number of 8BitDo Xbox360 gamepads and keyboards are now supported. USB mice using the generic HID interface at 3-0-0 were added. FatFs moved to R0.16 with patch 2.

The fix list is more revealing than the feature list. An invalid handling of TCP ACK for fragmented modem sessions was corrected, which also solved scrambled TCP data over low-speed or poor-quality links. A race condition in CSynchronizationEvent::Wait() could lose wake events when called from an IRQ handler. A spurious hang caused by unexpected USB disconnect events on cold boot was fixed. Hidden WLAN SSIDs work with scan_ssid=1 in wpa_supplicant.conf. The USB mass-storage gadget gained speed auto-negotiation and better host reset handling. And WLAN could not connect to eero7 routers, which is now fixed.

## The 51st Step rebuilt TCP/IP around congestion control

The 51st Step release is mostly about the network stack, and the changes are the kind that only matter once your application is doing real throughput.

The headline is TCP congestion control per RFC 5681, with Fast Retransmit and Fast Recovery. Until now the stack evidently sent without backing off, which works until it does not. Alongside it, unnecessary copying of frames and data inside the stack is largely prevented, and the README makes a specific claim about the result: throughput improves considerably, especially when a Raspberry Pi with 100 MBps Ethernet is attached to a Gigabit network.

That scenario is the reason to care. A Pi with Fast Ethernet on a gigabit network was previously limited by the stack's copying overhead rather than the wire, and removing the copies changes the practical ceiling.

The socket API is described as nearly unchanged, which is the right way to handle a performance rewrite. Two additions matter. The MSG_MORE flag on CSocket::Send() tells the receiving side not to deliver data immediately because more is coming, which removes a round of small packets when you are streaming a larger payload. And CSocket::Bind() accepts port 0 to bind an ephemeral port, retrieved with CSocket::GetOwnPort(). A related convenience is that CSocket::SendTo() no longer requires a preceding Bind() or Connect(), assigning an ephemeral port automatically.

If you are porting code from a POSIX stack, the mapping is close to conventional Linux semantics, which reduces the surprise factor considerably.

## Toolchain changes that will break an existing project

The recommended toolchain for building Circle applications is now based on GCC 15.2.Rel1. The recommended firmware in boot/ was updated to match.

The more consequential change is the language default. Circle is now built with -std=c++17 by default, with C++14 available as the previous default and C++20 also selectable. For an existing project this is the kind of change that either helps or breaks, depending on how your code was written.

The configure tool gained three options alongside the language selection: --kernel-max-size, --clang, and --kasan. The last two are notable. A --clang option paired with the 51.1.1 hotfix for lld suggests active work on the Clang toolchain for circle-stdlib. A --kasan option enables the address and undefined behaviour sanitizers in a bare metal environment, which is unusual and genuinely useful for a project that cannot easily attach a debugger.

The relevant configuration surface in cmdline.txt has also grown, and these are the settings a project is most likely to depend on:

```
usbboost=15
loglevel=5
scan_ssid=1
USE_USB_FIQ
USB_MIDI_FIQ_COMPLETION
USB_MIDI_CHECK_INCOMING
```

The option names are stable enough to be worth writing down. USE_GPIO_MANAGER_FIQ was added for applications needing several FIQ-triggered GPIO interrupt pins, because CGPIOPinFIQ cannot be used in that situation.

## What the samples and tree say about the scope

The sample directory is the fastest way to understand what the environment covers, because the numbering runs from trivial to genuinely capable.

The first samples are GPIO output, drawing a pixel and then text to the screen, a timer, and simple USB. From there it moves into Ethernet, USB mass storage, a USB keyboard, soft serial, a USB mouse, a GPIO clock, PWM sound, PWM output, a USB printer, files, I2C ping, a fractal, NTP time, tasks, a simple TCP client, a web server, SPI, hardware random numbers, SPI with DMA, and a CPU stress test.

Several of those are doing double duty as documentation. A web server sample is the shortest complete demonstration of the TCP/IP stack, and the CPU stress sample is presumably how you benchmark the performance claims in the 51st Step release.

The repository tree confirms the structure implied by the README. Include and lib hold the core, addon/ holds the third-party libraries, app/ holds applications, sample/ holds the demonstrations, boot/ holds the firmware, doc/ holds the class list and cmdline.txt documentation, test/ is present for tests, and tools/ is there. There are also a configure script at the root, a Rules.mk makefile fragment, a circle.ld linker script, a makeall convenience script, and a makedoc for generating documentation. Doxyfile indicates the docs are Doxygen-generated.

A note on the class documentation: the README links to doc/classes.txt for the ready-tested classes and addon/README for the add-on libraries, so the detailed API reference lives in the repository rather than on a hosted site.

## Project state, and who should look at this

The repository has 2,313 stars and 310 forks, with 13 open issues. The last push was 2026-09-28, so it is actively maintained. The GitHub releases list is empty, which is consistent with the source-only distribution policy rather than a sign of neglect: versions are announced in the README and built from source.

The fork-to-star ratio is worth a second look. Roughly one fork for every seven stars is high for an application framework, and it is what you would expect from a community that builds hardware on it. The open issue count is low for a project of this age, though the disclaimer explains why that number should be read carefully: with no dedicated testing department, issues are what users report, not what testing finds.

Circle makes sense for a specific set of projects. If you need a Raspberry Pi to boot without an operating system, control GPIO, drive a display or touchscreen, and speak USB or TCP/IP without a Linux kernel underneath, Circle gives you tested classes for all of that and a sample for nearly every feature. The standard library lives in a separate project, circle-stdlib, which supports an LLVM libc++ port, so the standard library coverage is Circle's dependency rather than its own.

It is a poor fit if you need a supported product, a vendor commitment, or prebuilt images you can hand to someone who will not compile from source. The GPL-3.0 license also needs thought if you intend to ship anything, and the README's own parenthetical about commercial products being not recommended suggests the author agrees.

What makes the project worth reading regardless is the README's honesty about its limits. Bare metal frameworks are usually presented through their feature lists. Circle presents its warranty exclusions, its testing gaps and its failed USB MIDI attempts, and the result is a much clearer picture of the project than a feature list would give you.

## Conclusion

Circle is worth reading even if you never boot it, because the README is an unusually honest description of what a hobby-scale bare metal framework is. The project is a single long line of releases numbered like years, the fixes are specific enough to be useful, and the maintainer documents his own failures rather than hiding them. Two features make that possible: the USB MIDI workaround has needed repeated attempts, and the toolchain moved from GCC 14 to GCC 15 with C++17 as the new default, so an old project that still builds against the previous default will stop building without a clear error. The disclaimer at the top of the README deserves to be quoted to anyone considering Circle in a product, since it states plainly that there is no warranty, no dedicated testing department, and no official binaries. If your requirement is a Raspberry Pi that boots without an operating system and talks USB and TCP/IP, Circle is a realistic choice for a prototype and a considered risk for anything shipped.

## FAQ

### What is Circle used for on the Raspberry Pi?

Circle is a C++ bare metal programming environment for the Raspberry Pi. It provides tested classes and add-on libraries for hardware features such as GPIO, screens, USB devices, SPI, I2C, timers and TCP/IP networking, so a program can run on the Pi without an operating system underneath.

### Why is the Circle repository listed as a C project when it is C++?

GitHub classifies a repository by the volume of code in each language, and the bundled third-party C libraries under addon/ outnumber the core. The README states this directly and explains that the main Circle libraries are written in C++ using classes, which is why it calls itself a C++ programming environment.

### Does Circle provide prebuilt images or binaries?

No. The README states that Circle is published only as source code with no official binary releases, as one of the five points in its disclaimer. You build applications yourself using the configure tool and the recommended toolchain, currently GCC 15.2.Rel1.

### Which C++ standard does Circle build with?

Since the 51st Step release, Circle builds with -std=c++17 by default. The configure tool can also select C++14, which was the previous default, or C++20. If you are updating an older Circle project, this default change is the most likely reason it stops building.

### Which Raspberry Pi models and screens does Circle support?

The README says Circle should be usable on most existing models, with a Support Status section listing details. Release 51.1 added support for the official 5-inch and 7-inch DSI touchscreens, versions 1 and 2, on the Raspberry Pi 5 through addon/rp1dsi, tested with sample/28-touchscreen. Enabling it requires setting the DSI_DISPLAY variable in the relevant Makefile.

### Is Circle suitable for a commercial or safety-critical product?

The README does not say so. Its disclaimer states there is no warranty of any kind, that there is no dedicated testing department and contributors cannot validate every device or model revision, and that integrating Circle into a commercial product is not recommended. Using it means you are responsible for testing in your target environment and for the consequences.

## Sources

- [Issues](https://github.com/rsta2/circle/issues)
- [License: GPL-3.0](https://github.com/rsta2/circle/blob/master/LICENSE)
- [Project website](https://circle-rpi.readthedocs.io)
- [README](https://github.com/rsta2/circle/blob/master/README.md)
- [rsta2/circle on GitHub](https://github.com/rsta2/circle)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/rsta2-circle
