Targeting a bare-metal environment

Hi.

Could someone tell me what aspects of the Crystal toolchain and libraries need to be extended or changed to target a bare metal environment for an existing LLVM supported processor architecture ?

I’m interested in targeting a bare metal Arm AArch64 environment. The aim is to incrementally explore the possible use of Crystal for firmware development as a first step.

The underlying assumptions are that so long as Crystal’s run-time requirements can be met for the bare-metal environment (things like memory allocators, GC aspects, signal/exception handling etc perhaps) and the application or use-case isn’t susceptible to the potential time determinism issues around the use of a GC etc, then the expressiveness of Crystal and it’s type-safety et al can be attractive for systems development.

Any thoughts appreciated.

At present I’m studying Lilith which I think would have had to address similar things.

Cheers

Hi again.

Here are some things that I’ve learnt that I’d like to share in case they help someone, along with some additional questions that I have. Would appreciate any insights.

  1. Some of the bare-metal crystal experiments I’ve seen so far are:

  2. The Lilith strategy (which Stakach re-uses) is to use a modified compiler + custom allocator + custom conservative mark and sweep garbage collector + custom prelude. The allocator and the GC are a part of the OS kernel which IIUC links against the compiler library.

    • Some compiler modifications are to do with introducing a Markable class which dynamic types (such as Array and Hash) are made to inherit from. This class introduces scaffolding that helps the custom GC do its marking action.

    • Other compiler modifications are to do with making certain symbols accessible by the OS kernel (such as where the globals reside) which are then used by the custom GC.

    • And then there’s the custom prelude which re-implements most of the language primitives.

    • Question: What I don’t get is why should there be a custom prelude ? Why can’t the compiler’s ‘built-in’ prelude (crystal/src/prelude.cr) be used as-is especially since the allocator and GC are being used from outside the compiler ? Also: Why the need to have explicit Markability ? Doesn’t the built-in Boehm GC have all of that when working with the crystal compiler already ?

  3. At present, my thinking is that a good solution to make Crystal usable for bare-metal targets would be:

    • Look for target “rich” run-time environment specific code or assumptions in the compiler and its supplied libs (Linux/Windows et al). Where applicable, find clean ways of making such code conditionally re-targetable to a bare-metal environment. The GNU target triple would be $ARCH-unknown-none. The code I am alluding to is anything that relies on OS kernel specific facilities (threads, processes, synchronisation primitives, signals, filesystem nuances et al). For such code, a reasonable set of assumptions can be made with regard to the bare-metal environment. Initially one can stub out complex bits in favour of a single threaded non-preemptive environment. Then more complexity can be added incrementally culminating in bridging to an RTOS etc.

    • Look for similar bits in the compiler supplied prelude. Try to define clean interfaces that make it possible to use as much of the prelude as possible by a bare-metal environment.

    • Do the same for any allocator and GC specific code and make it possible to conditionally link to a bare-metal environment specified GC and allocator combination. Basically analyse what Lilith has done and see if interfaces can be implemented that make linkage with a more general bare-metal environment as clean as possible.

    • Use an emulated environment (qemu for Cortex-M class microcontrollers) as the basis for all of this with the ultimate aim of migrating to real silicon (probably Raspberry Pi Pico which is well supported by micropython today).

    • Question: Does the above sound like a reasonable route to enabling crystal use in bare-metal environments ?

I’ll continue studying and experimenting and I hope to share what I learn in the hope that I don’t veer to far off. Any thoughts welcome! Thanks.

Bare metal means no OS?

In this context, yes that’s what it means. Think micropython or mruby.

@fork-bomber Hi, wonder if you got anywhere with this… I’d like to run Crystal on an RP2040.