Bring Julia code to embedded hardware (ARM)

I am not sure if you have noticed that the latest Julia 1.2 has Linux Binaries for 32bit ARM.

I was interested to try to build and try some simple programs using Julia, and make some examples for others to use as templates (I haven’t seen any really).
I have an ARM Cortex A9 with Linux installed on it, and also an ARM Cortex M3 with FreeRTOS (installing Linux is also possible).

I want to experiment with

  • building executable
  • making lib/dll libraries.
  • Also as you know, a lot of the drivers and libraries are written in C, so we also can try embedding Julia in an already written C code (like writing the main computational function in Julia).
  • building on desktop (Windows, etc) for ARM.

I was wondering if anyone is interested to make a repository and try some examples for embedded programming. Let me know if you want to be involved.

2 Likes

I’m working on something that could help target embedded hardware (while not the main goal). While I could support all CPUs, is it a limitation to only support all 32-bit ones?

1 Like

No that’s not a limitation. But for embedded programming, most of the processors are 32 bit.

1 Like

I’m interested in anything involving standalone compilation and cross compilation. My main immediate interest is WebAssembly (that’s a cross-compiled 32-bit platform, so there are lots of similarities).

3 Likes

I created an organization for this purpose. Feel free to contact me so I give you access.

I have also created a master repository writing the goals and motivation.

First I think we should start with blinking LED :smiley:

For that we need to write a function similar to Arduino pinmode() which we can define pins as input or output (GPIO).

2 Likes

I had actually already created a Julia embedded GitHub group a while ago here: https://github.com/juliaembedded. I was starting with just simulating embedded arithmetic, and was going to be building up a type system to model fixed-point and arbitrary floating-point arithmetic with rounding mode selection (including stochastic rounding). The goal is to allow an algorithm written in Julia to be simulated using the reduced precision that would be in embedded devices so designers could see the effect on performance.

The next project was going to be building an embedded compiler for Julia, that will take a Julia function and transform it to runtime-independent code that can be fed into the LLVM backend for the desired target (then the LLVM to C backend could be used to generate direct C code if desired). My main goal was to create static libraries that would contain the compiled Julia functions, and then those could be linked into existing C applications.

That does have its difficulties though, since you have to extract the memory allocations from the compiler, and ensure that they are either done with the provided embedded functions or all allocatons become static (which is actually the preferred way of handling memory in critical embedded systems). I haven’t had a chance to dig around in the generated code yet, but I think this should be doable in a similar way to how the GPU group accomplished this.

4 Likes

This is awesome. We have the same goals! We should merge and work together. I sent you a PM regarding merging our groups.

I found this Rust embedded book. Rust is also uses LLVM, and so it is useful to inspire from it.
https://rust-embedded.github.io/book/

1 Like

Are you aware of Juliaberry (Julia on Raspberry Pi)?

I played with it a little bit. I could get very fast gpio bit banging speed (about 100 ns per ccall to libpigpio, so it could generate a 5 MHz clock!) but with occasional interruptions by the OS I presume.

I was thinking of doing some embedded systems prototyping in which some control algorithm would be tested and results quickly plotted without having to move data to some other system, but I had trouble with compilation times being really excessive or not finishing at all because of insufficient memory.

I’m not actively messing with it now. If I tried again I would probably divide the problem - let the raspberry pi do the pseudo-real-time stuff in Julia, and let it serve data over Ethernet to a PC doing plotting and analysis, also in Julia.

3 Likes

By runtime-independent you mean architecture-independent? So removing all arch-specific stuff from the representation? This is exactly the idea behind the approach summarised in this post. Just with the difference that there, the idea was to target some specific platform(s), instead of fully platform-agnostic code (which could then not utilise any of the platform’s features such as SIMD (?).

BTW, like the logo (https://github.com/juliaembedded) and the idea of validating fixed-point versions of Julia code/functions.

2 Likes

That is definitely useful. I think the goal should be to do the simulations and build the program on desktop and only run it on the target processor. A lot of processors don’t have enough space, Ram, etc for running Julia and its compiler.

1 Like

For using drivers for ARM in Julia, I think we can start by writing Julia wrappers for ARM CMSIS Driver which is part of ARM CMSIS, and is supported by many hardware.

It has API for many peripherals as stated in the documentation:

The CMSIS-Driver specification is a software API that describes peripheral driver interfaces for middleware stacks and user applications. The CMSIS-Driver API is designed to be generic and independent of a specific RTOS making it reusable across a wide range of supported microcontroller devices.

The following CMSIS-Driver API groups are defined:

  • CAN: Interface to CAN bus peripheral.
  • Ethernet: Interface to Ethernet MAC and PHY peripheral.
  • I2C: Multi-master Serial Single-Ended Bus interface driver.
  • MCI: Memory Card Interface for SD/MMC memory.
  • NAND: NAND Flash Memory interface driver.
  • Flash: Flash Memory interface driver.
  • SAI: Serial audio interface driver (I2s, PCM, AC’97, TDM, MSB/LSB Justified).
  • SPI: Serial Peripheral Interface Bus driver.
  • Storage: Storage device interface driver.
  • USART: Universal Synchronous and Asynchronous Receiver/Transmitter interface driver.
  • USB: Interface driver for USB Host and USB Device communication.
  • WiFi: Interface driver for wireless communication.

With a quick search that I did it is also possible to use it under Linux.

2 Likes

Hello. I’m new to Julia, but not new to the embedded world. I have worked with many AVR and ARM devices, most of which are too small to run Linux, as most of them had limited RAM and no memory management.

I’m just wondering whether this discussion is still going on, since it appeared to halt in 2019. Are there any new developments from any of the folks who have mentioned potential directions for getting Julia onto small embedded platforms?

2 Likes

I have no idea about this subject, but it came up in the recent AMA. Maybe this helps answer your question:

(Link points to the spot where ARM is discussed briefly.)

2 Likes

Second the request for more info. Also, I didn’t notice in the discussion talk of verification and validation. Do we need to now target a specific standard. Would you trust Julia to fly a plane or drive a car? Would it need to go into C so it could be checked by some of the verification tools? Where does this discussion live?

The following talk might be interesting for you:
https://live.juliacon.org/talk/38UTLX

But I do not think that you can use Julia for any product that needs to be developed according to high security standards (e.g. DO-178C), because for these products you need formal verification not only of the code, but also of the compiler.

An example how to create a verified compiler/ toolchain you can find here for a C/C++ toolkit: https://www.ti.com/lit/wp/spny004/spny004.pdf

This might not be required for small drones. Not so sure about the legal requirements for automated cars.

Thanks!

I’m not as familiar with the verification tools aspect, but in terms of reliability for critical applications, you might be interested in this post from last year by Stefan Karpinski where he advocates for Julia as being safer than some statically typed languages such as C: Julia with respect to reliability, sustainability, critical application, dynamic/static typing, big data, HPC?

1 Like

Julia does support ARM, but not ARM Cortex-M, i.e. those with no MMU (or only the 16-bit Thumb ISA), are not supported. Such assume non-Linux (or Linux variant Julia doesn’t support). In theory Julia could run baremetal, but I think it’s far away.

It might be possible to use an RTOS, like Arm OS (os.mbed.com), one that supports ARM Cortex-R. I’m just guessing here, it would have to be compatible enough with Linux/POSIX (or if not, Julia could support with some changes).

I do not foresee Julia ever supporting AVR or any 8-bit, or a future were using those are useful.

While ARM Cortex-R, does support real-time, and I believe Julia can too (given you’re careful to not trigger allocations, and using appropriate OS and hardware), note what Karpinski says:

Thanks, all for your responses. I was curious about where Julia-on-embedded might be headed (no rhyme intended!) I think its progression will depend on several factors, including, but not limited to, (1) real commercial need, (2) financial support for appropriate research, development, and testing, (3) willingness to restrict language constructs in smaller platforms if necessary, (4) level of effort required to use the desired parts of the language (from a source perspective), or to tie into specific compilation or build points, (5) whether the beauty and flavor of the language would be buried or lost by constraining it.

What do you mean by:

The garbage collector can and needs to be “constrained” for hard-real-time (but not all projects), and can already be done without changing the “language”. Mostly the user needs to be contained, not use all constructs of the language, like eval, that generates code at runtime (something you wouldn’t do in embedded, other languages for, do not have that). You can compile to assembly with PackageCompiler.jl, and even when using eval but then your code needs to have a compiler with it making the binary huge. There are ways to disable code you know will not be used, and PC could probably make smaller code by changing it 8not the Julia language), or some similar project. There are some older (outdated Intel’s Julia2C and I seem to remember another compiling Julia to C):