Lisp for microcontrollers

News!

uLisp now supports the popular Maple Mini and Blue Pill STM32-based boards

A new STM32 version of uLisp now supports the Maple Mini and Blue Pill STM32 ARM Cortex-M3 boards, which are widely available at low cost on sites such as eBay, AliExpress, and Banggood.

The STM32 version supports 32-bit floating-point and integer arithmetic, and it allows the Lisp workspace to be saved to the STM32's non-volatile flash memory. For more information see STM32 boards.

uLisp® is a version of the Lisp programming language specifically designed to run on microcontrollers with a limited amount of RAM. It currently supports the Arduino ATmega-based boards, Arduino ARM SAM/SAMD-based boards, Adafruit ARM SAMD51-based boards, BBC Micro Bit, ESP8266/ESP32-based boards, and MSP430-based LaunchPad boards. You can use exactly the same uLisp program, irrespective of the platform.

Because uLisp is an interpreter you can type commands in, and see the effect immediately, without having to compile and upload your program. This makes it an ideal environment for learning to program, or for setting up simple electronic devices.

Lisp is a flexible language, with many advanced features that make it easier to program in than C or C++, so it's ideal for learning about fundamental programming concepts. It's also an ideal language for expressing complex ideas, such as teaching a robot to solve mazes or finding the shortest route on a map. As well as supporting a core set of Lisp functions uLisp includes Arduino extensions, making it ideal as a control language for the Arduino.

You can download the current version of uLisp free from the Download uLisp page.

ATmega1284. Although there isn't an official Arduino board based on it, the ATmega1284 is easy to wire up on a prototyping board, and provides a generous 16 Kbytes RAM.

MSP430 version

The MSP430 version of uLisp supports the following boards:

MSP430 F5529 LaunchPad. This uses the flash memory for saving images, and provides enough memory for a fairly complex application.

MSP430 FR5969 LaunchPad. This version uses the FRAM for the workspace, and for saving images, giving a generous amount of memory.

MSP430 FR5994 LaunchPad. This version uses the FRAM for the workspace, and for saving images, giving a generous amount of memory.

32-bit platforms

The versions of uLisp for 32-bit platforms support integers between 2147483647 and -2147483648, and 32-bit floating-point numbers.

ARM version

The ARM version of uLisp supports the following boards:

Arduino Due. This board is based on the AT91SAM3X8E ARM Cortex-M3 core and provides 512 Kbytes of flash, 96 Kbytes of RAM, and an 84 MHz clock. It's currently the fastest uLisp platform.

Arduino Zero. This board is based on the SAMD21 ARM Cortex-M0+ core and provides 256 Kbytes of flash and 32 Kbytes of RAM.

Arduino MKRZero. This is similar to the Arduino Zero, based on the SAMD21 ARM Cortex-M0+ core and with 256 Kbytes of flash and 32 Kbytes of RAM. It incorporates an SD-card socket, allowing you to use an SD card for saving and loading uLisp images.

Adafruit M4 boards. The Adafruit Metro M4, Adafruit ItsyBitsy M4, and Adafruit Feather M4 are each based on the ATSAMD51 120MHz ARM Cortex M4 microcontroller. They have similar features and performance; the main difference is the form-factor of each board.

BBC Micro Bit. This is based on a Nordic Semiconductor nRF51822 ARM Cortex-M0 microcontroller. It runs at 16 MHz and provides 256 Kbytes of flash program memory and 16 Kbytes of RAM. It doesn't support saving and loading uLisp images.

STM32 version

STM32 boards. These boards are based on the STM32F103 ARM Cortex-M3 processor running at 72 MHz, with 128 Kbytes of flash and 20 Kbytes of RAM.

ESP8266/ESP32 version

The ESP8266/ESP32 version of uLisp supports the following boards:

ESP8266 boards. These boards are based on the 32-bit Tensilica Xtensa L106 microprocessor running at 80 MHz, with 4 Mbytes of flash and 80 Kbytes of RAM. They include integrated Wi-Fi.

ESP32 boards. These boards are based on the 32-bit Tensilica Xtensa LX6 microprocessor running at 160 or 240 MHz, with 4 Mbytes of flash and 520 Kbytes of RAM. They include integrated Wi-Fi and dual-mode Bluetooth.

Performance

The following table gives a summary of the performance of the different versions:

8/16-bit platforms

Platform

Processor

Clock

Objects

Image

GC time

Tak

Arduino Uno, Arduino Nano

ATmega328

16 MHz

315

256

0.5 ms

59 secs

Arduino Mega 2560

ATmega2560

16 MHz

1216

1024

2.1 ms

49 secs

Tiny Lisp Computer

ATmega1284

16 MHz

2816

1024

4.8 ms

48 secs

MSP430 F5529 LaunchPad

MSP430F5529

25 MHz

1280

1280

1.3 ms

20 secs

MSP430 FR5969 LaunchPad

MSP430FR5969

16 MHz

3072

1536

10.2 ms

60 secs

MSP430 FR5994 LaunchPad

MSP430FR5994

16 MHz

3072

1536

6.7 ms

41 secs

32-bit platforms

Platform

Processor

Clock

Objects

Image

GC time

Tak

FFT

Arduino Due

ATSAM3X8E

84 MHz

10240

*

4.5 ms

7 secs

213 ms

Arduino Zero

ATSAMD21

48 MHz

3072

*

1.2 ms

10 secs

348 ms

Arduino MKRZero

ATSAMD21

48 MHz

3072

*

1.2 ms

13 secs

438 ms

Adafruit Metro M4

ATSAMD51

120 MHz

20480

8192

3.4 ms

4.2 secs

122 ms

Adafruit ItsyBitsy M4

ATSAMD51

120 MHz

20480

8192

3.4 ms

4.1 secs

Adafruit Feather M4

ATSAMD51

120 MHz

20480

8192

3.4 ms

4.2 secs

BBC Micro Bit

nRF51822

16 MHz

1024

*

1.7 ms

33 secs

Maple Mini

STM32F103

72 MHz

1152

1280

0.7 ms

9 secs

355 ms

Blue Pill

STM32F103

72 MHz

1472

1280

0.7 ms

9 secs

ESP8266 boards

ESP8266

80 MHz

3072

512

0.6 ms

12 secs

ESP32 boards

ESP32

240 MHz

4096

512

0.3 ms

7 secs

242 ms

Objects gives the number of Lisp objects of storage available, each equivalent to 4 bytes on the 8/16-bit platforms and 8 bytes on the 32-bit platforms.

Image gives the number of cells that can be saved to non-volatile storage using save-image.On the Adafruit M4 boards you can save an image to the on-board DataFlash chip.* On the Arduino Due, Zero, and MKRZero you can save images to an SD card. The BBC Micro Bit doesn't support saving images.

Specification

An integer is a sequence of digits, optionally prefixed with "+" or "-". Integers can be between -32768 and 32767 (or between 2147483647 to -2147483648 on the 32-bit platforms). You can enter integers in hexadecimal, octal, or binary with the notations #x2A, #o52, or #b101010, all of which represent 42.

The 32-bit platforms also support 32-bit floating-point numbers, and provide a full set of floating-point functions.

On platforms with more than 2 Kbytes of RAM arbitrary user-defined symbol names are supported. Any sequence that isn't an integer can be used as a symbol; so, for example, 12a is a valid symbol. On platforms with only 2 Kbytes symbol names can have up to three characters consisting of a-z and 0-9.

There is one namespace for functions and variables; in other words, you cannot use the same name for a function and a variable. uLisp provides tail-call optimization, so applications written using recursive functions can be as efficient as using iteration.

Strings can consist of an arbitrary sequence of ASCII characters. Strings can be unlimited length, and are automatically garbage-collected.

uLisp includes a mark and sweep garbage collector. Garbage collection takes under 1 msec on an Arduino Uno or under 3 msec on an Arduino Mega 2560 (see above table).