Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 05 of 13

Your first blink

One command builds a pure-Ada GPIO driver, packages a flash image, writes it over the chip's ROM bootloader, resets the board, and streams the console.

Run it

./x list                                       # every example + its profile
./x run esp32s3_gpio0_blink -p /dev/ttyACM0    # build + flash + monitor

The esp32s3_ prefix is optional — ./x run gpio0_blink does the same thing. If ESPPORT is set, drop the -p too.

The first build is slow. It builds the xtensa-dynconfig plugin, generates the Ada runtime for the chosen profile, and compiles the two host tools. Several minutes is normal. Every build after that is incremental and takes seconds.

What you should see

[C] GPIO0 blink (bare Ada driver, no FreeRTOS)
[gpio0] HIGH
[gpio0] low
[gpio0] HIGH
...

That is a library-level Ada task toggling GPIO0 every 250 ms — a 2 Hz square wave on the pad — and printing each transition over the USB-Serial-JTAG console. Wire an LED and a resistor from GPIO0 to GND, or put a scope on the pin, to see it in the physical world.

There is no FreeRTOS underneath this. Its scheduler is not even linked. The timing comes from the Ada runtime's own clock tick, and delay until is served by the board-support layer's alarm — which is why the period is exact rather than drifting.

The verbs, separately

./x run is build + flash + monitor in one. When you want the pieces:

./x build   esp32s3_gpio0_blink            # cross-compile + link + package app.bin
./x flash   esp32s3_gpio0_blink -p /dev/ttyACM0
./x monitor -p /dev/ttyACM0                # just the serial console (115200)
./x clean   esp32s3_gpio0_blink

Each example is also buildable from its own directory with the ./build.sh and ./flash.sh shims, if you prefer working inside one:

cd examples/esp32s3_gpio0_blink
./build.sh
./flash.sh /dev/ttyACM0                    # defaults to /dev/ttyACM0

Other examples worth running next

ExampleWhat it shows
esp32s3_heartbeatSingle-core heartbeat, [ADA] N at 1 Hz
esp32s3_psramA 1 MB static array placed in external PSRAM
esp32s3_smpCross-core mailbox over a protected-object entry
esp32s3_gdma_copyGDMA memory-to-memory with an RAII channel handle
esp32s3_cryptoHardware SHA and AES checked against FIPS vectors
esp32s3_embeddedThe embedded profile: exceptions, finalization, dispatching
esp32s3_full_taskingThe full profile: dynamic tasks, abort, rendezvous

The examples are written to be read. Each opens with a header saying what it demonstrates, what the console should print, and what hardware (if any) it needs; the magic numbers are named and the reasoning is in the code. Once you have one running, the source is the next thing to look at.

Your first blink · Bare-Metal Ada on the ESP32-S3
Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 05 of 13

Your first blink

One command builds a pure-Ada GPIO driver, packages a flash image, writes it over the chip's ROM bootloader, resets the board, and streams the console.

Run it

./x list                                       # every example + its profile
./x run esp32s3_gpio0_blink -p /dev/ttyACM0    # build + flash + monitor

The esp32s3_ prefix is optional — ./x run gpio0_blink does the same thing. If ESPPORT is set, drop the -p too.

The first build is slow. It builds the xtensa-dynconfig plugin, generates the Ada runtime for the chosen profile, and compiles the two host tools. Several minutes is normal. Every build after that is incremental and takes seconds.

What you should see

[C] GPIO0 blink (bare Ada driver, no FreeRTOS)
[gpio0] HIGH
[gpio0] low
[gpio0] HIGH
...

That is a library-level Ada task toggling GPIO0 every 250 ms — a 2 Hz square wave on the pad — and printing each transition over the USB-Serial-JTAG console. Wire an LED and a resistor from GPIO0 to GND, or put a scope on the pin, to see it in the physical world.

There is no FreeRTOS underneath this. Its scheduler is not even linked. The timing comes from the Ada runtime's own clock tick, and delay until is served by the board-support layer's alarm — which is why the period is exact rather than drifting.

The verbs, separately

./x run is build + flash + monitor in one. When you want the pieces:

./x build   esp32s3_gpio0_blink            # cross-compile + link + package app.bin
./x flash   esp32s3_gpio0_blink -p /dev/ttyACM0
./x monitor -p /dev/ttyACM0                # just the serial console (115200)
./x clean   esp32s3_gpio0_blink

Each example is also buildable from its own directory with the ./build.sh and ./flash.sh shims, if you prefer working inside one:

cd examples/esp32s3_gpio0_blink
./build.sh
./flash.sh /dev/ttyACM0                    # defaults to /dev/ttyACM0

Other examples worth running next

ExampleWhat it shows
esp32s3_heartbeatSingle-core heartbeat, [ADA] N at 1 Hz
esp32s3_psramA 1 MB static array placed in external PSRAM
esp32s3_smpCross-core mailbox over a protected-object entry
esp32s3_gdma_copyGDMA memory-to-memory with an RAII channel handle
esp32s3_cryptoHardware SHA and AES checked against FIPS vectors
esp32s3_embeddedThe embedded profile: exceptions, finalization, dispatching
esp32s3_full_taskingThe full profile: dynamic tasks, abort, rendezvous

The examples are written to be read. Each opens with a header saying what it demonstrates, what the console should print, and what hardware (if any) it needs; the magic numbers are named and the reasoning is in the code. Once you have one running, the source is the next thing to look at.

Your first blink · Bare-Metal Ada on the ESP32-S3
Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 05 of 13

Your first blink

One command builds a pure-Ada GPIO driver, packages a flash image, writes it over the chip's ROM bootloader, resets the board, and streams the console.

Run it

./x list                                       # every example + its profile
./x run esp32s3_gpio0_blink -p /dev/ttyACM0    # build + flash + monitor

The esp32s3_ prefix is optional — ./x run gpio0_blink does the same thing. If ESPPORT is set, drop the -p too.

The first build is slow. It builds the xtensa-dynconfig plugin, generates the Ada runtime for the chosen profile, and compiles the two host tools. Several minutes is normal. Every build after that is incremental and takes seconds.

What you should see

[C] GPIO0 blink (bare Ada driver, no FreeRTOS)
[gpio0] HIGH
[gpio0] low
[gpio0] HIGH
...

That is a library-level Ada task toggling GPIO0 every 250 ms — a 2 Hz square wave on the pad — and printing each transition over the USB-Serial-JTAG console. Wire an LED and a resistor from GPIO0 to GND, or put a scope on the pin, to see it in the physical world.

There is no FreeRTOS underneath this. Its scheduler is not even linked. The timing comes from the Ada runtime's own clock tick, and delay until is served by the board-support layer's alarm — which is why the period is exact rather than drifting.

The verbs, separately

./x run is build + flash + monitor in one. When you want the pieces:

./x build   esp32s3_gpio0_blink            # cross-compile + link + package app.bin
./x flash   esp32s3_gpio0_blink -p /dev/ttyACM0
./x monitor -p /dev/ttyACM0                # just the serial console (115200)
./x clean   esp32s3_gpio0_blink

Each example is also buildable from its own directory with the ./build.sh and ./flash.sh shims, if you prefer working inside one:

cd examples/esp32s3_gpio0_blink
./build.sh
./flash.sh /dev/ttyACM0                    # defaults to /dev/ttyACM0

Other examples worth running next

ExampleWhat it shows
esp32s3_heartbeatSingle-core heartbeat, [ADA] N at 1 Hz
esp32s3_psramA 1 MB static array placed in external PSRAM
esp32s3_smpCross-core mailbox over a protected-object entry
esp32s3_gdma_copyGDMA memory-to-memory with an RAII channel handle
esp32s3_cryptoHardware SHA and AES checked against FIPS vectors
esp32s3_embeddedThe embedded profile: exceptions, finalization, dispatching
esp32s3_full_taskingThe full profile: dynamic tasks, abort, rendezvous

The examples are written to be read. Each opens with a header saying what it demonstrates, what the console should print, and what hardware (if any) it needs; the magic numbers are named and the reasoning is in the code. Once you have one running, the source is the next thing to look at.

Your first blink · Bare-Metal Ada on the ESP32-S3
Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 05 of 13

Your first blink

One command builds a pure-Ada GPIO driver, packages a flash image, writes it over the chip's ROM bootloader, resets the board, and streams the console.

Run it

./x list                                       # every example + its profile
./x run esp32s3_gpio0_blink -p /dev/ttyACM0    # build + flash + monitor

The esp32s3_ prefix is optional — ./x run gpio0_blink does the same thing. If ESPPORT is set, drop the -p too.

The first build is slow. It builds the xtensa-dynconfig plugin, generates the Ada runtime for the chosen profile, and compiles the two host tools. Several minutes is normal. Every build after that is incremental and takes seconds.

What you should see

[C] GPIO0 blink (bare Ada driver, no FreeRTOS)
[gpio0] HIGH
[gpio0] low
[gpio0] HIGH
...

That is a library-level Ada task toggling GPIO0 every 250 ms — a 2 Hz square wave on the pad — and printing each transition over the USB-Serial-JTAG console. Wire an LED and a resistor from GPIO0 to GND, or put a scope on the pin, to see it in the physical world.

There is no FreeRTOS underneath this. Its scheduler is not even linked. The timing comes from the Ada runtime's own clock tick, and delay until is served by the board-support layer's alarm — which is why the period is exact rather than drifting.

The verbs, separately

./x run is build + flash + monitor in one. When you want the pieces:

./x build   esp32s3_gpio0_blink            # cross-compile + link + package app.bin
./x flash   esp32s3_gpio0_blink -p /dev/ttyACM0
./x monitor -p /dev/ttyACM0                # just the serial console (115200)
./x clean   esp32s3_gpio0_blink

Each example is also buildable from its own directory with the ./build.sh and ./flash.sh shims, if you prefer working inside one:

cd examples/esp32s3_gpio0_blink
./build.sh
./flash.sh /dev/ttyACM0                    # defaults to /dev/ttyACM0

Other examples worth running next

ExampleWhat it shows
esp32s3_heartbeatSingle-core heartbeat, [ADA] N at 1 Hz
esp32s3_psramA 1 MB static array placed in external PSRAM
esp32s3_smpCross-core mailbox over a protected-object entry
esp32s3_gdma_copyGDMA memory-to-memory with an RAII channel handle
esp32s3_cryptoHardware SHA and AES checked against FIPS vectors
esp32s3_embeddedThe embedded profile: exceptions, finalization, dispatching
esp32s3_full_taskingThe full profile: dynamic tasks, abort, rendezvous

The examples are written to be read. Each opens with a header saying what it demonstrates, what the console should print, and what hardware (if any) it needs; the magic numbers are named and the reasoning is in the code. Once you have one running, the source is the next thing to look at.

Your first blink · Bare-Metal Ada on the ESP32-S3
Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 05 of 13

Your first blink

One command builds a pure-Ada GPIO driver, packages a flash image, writes it over the chip's ROM bootloader, resets the board, and streams the console.

Run it

./x list                                       # every example + its profile
./x run esp32s3_gpio0_blink -p /dev/ttyACM0    # build + flash + monitor

The esp32s3_ prefix is optional — ./x run gpio0_blink does the same thing. If ESPPORT is set, drop the -p too.

The first build is slow. It builds the xtensa-dynconfig plugin, generates the Ada runtime for the chosen profile, and compiles the two host tools. Several minutes is normal. Every build after that is incremental and takes seconds.

What you should see

[C] GPIO0 blink (bare Ada driver, no FreeRTOS)
[gpio0] HIGH
[gpio0] low
[gpio0] HIGH
...

That is a library-level Ada task toggling GPIO0 every 250 ms — a 2 Hz square wave on the pad — and printing each transition over the USB-Serial-JTAG console. Wire an LED and a resistor from GPIO0 to GND, or put a scope on the pin, to see it in the physical world.

There is no FreeRTOS underneath this. Its scheduler is not even linked. The timing comes from the Ada runtime's own clock tick, and delay until is served by the board-support layer's alarm — which is why the period is exact rather than drifting.

The verbs, separately

./x run is build + flash + monitor in one. When you want the pieces:

./x build   esp32s3_gpio0_blink            # cross-compile + link + package app.bin
./x flash   esp32s3_gpio0_blink -p /dev/ttyACM0
./x monitor -p /dev/ttyACM0                # just the serial console (115200)
./x clean   esp32s3_gpio0_blink

Each example is also buildable from its own directory with the ./build.sh and ./flash.sh shims, if you prefer working inside one:

cd examples/esp32s3_gpio0_blink
./build.sh
./flash.sh /dev/ttyACM0                    # defaults to /dev/ttyACM0

Other examples worth running next

ExampleWhat it shows
esp32s3_heartbeatSingle-core heartbeat, [ADA] N at 1 Hz
esp32s3_psramA 1 MB static array placed in external PSRAM
esp32s3_smpCross-core mailbox over a protected-object entry
esp32s3_gdma_copyGDMA memory-to-memory with an RAII channel handle
esp32s3_cryptoHardware SHA and AES checked against FIPS vectors
esp32s3_embeddedThe embedded profile: exceptions, finalization, dispatching
esp32s3_full_taskingThe full profile: dynamic tasks, abort, rendezvous

The examples are written to be read. Each opens with a header saying what it demonstrates, what the console should print, and what hardware (if any) it needs; the magic numbers are named and the reasoning is in the code. Once you have one running, the source is the next thing to look at.

Your first blink · Bare-Metal Ada on the ESP32-S3
Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 05 of 13

Your first blink

One command builds a pure-Ada GPIO driver, packages a flash image, writes it over the chip's ROM bootloader, resets the board, and streams the console.

Run it

./x list                                       # every example + its profile
./x run esp32s3_gpio0_blink -p /dev/ttyACM0    # build + flash + monitor

The esp32s3_ prefix is optional — ./x run gpio0_blink does the same thing. If ESPPORT is set, drop the -p too.

The first build is slow. It builds the xtensa-dynconfig plugin, generates the Ada runtime for the chosen profile, and compiles the two host tools. Several minutes is normal. Every build after that is incremental and takes seconds.

What you should see

[C] GPIO0 blink (bare Ada driver, no FreeRTOS)
[gpio0] HIGH
[gpio0] low
[gpio0] HIGH
...

That is a library-level Ada task toggling GPIO0 every 250 ms — a 2 Hz square wave on the pad — and printing each transition over the USB-Serial-JTAG console. Wire an LED and a resistor from GPIO0 to GND, or put a scope on the pin, to see it in the physical world.

There is no FreeRTOS underneath this. Its scheduler is not even linked. The timing comes from the Ada runtime's own clock tick, and delay until is served by the board-support layer's alarm — which is why the period is exact rather than drifting.

The verbs, separately

./x run is build + flash + monitor in one. When you want the pieces:

./x build   esp32s3_gpio0_blink            # cross-compile + link + package app.bin
./x flash   esp32s3_gpio0_blink -p /dev/ttyACM0
./x monitor -p /dev/ttyACM0                # just the serial console (115200)
./x clean   esp32s3_gpio0_blink

Each example is also buildable from its own directory with the ./build.sh and ./flash.sh shims, if you prefer working inside one:

cd examples/esp32s3_gpio0_blink
./build.sh
./flash.sh /dev/ttyACM0                    # defaults to /dev/ttyACM0

Other examples worth running next

ExampleWhat it shows
esp32s3_heartbeatSingle-core heartbeat, [ADA] N at 1 Hz
esp32s3_psramA 1 MB static array placed in external PSRAM
esp32s3_smpCross-core mailbox over a protected-object entry
esp32s3_gdma_copyGDMA memory-to-memory with an RAII channel handle
esp32s3_cryptoHardware SHA and AES checked against FIPS vectors
esp32s3_embeddedThe embedded profile: exceptions, finalization, dispatching
esp32s3_full_taskingThe full profile: dynamic tasks, abort, rendezvous

The examples are written to be read. Each opens with a header saying what it demonstrates, what the console should print, and what hardware (if any) it needs; the magic numbers are named and the reasoning is in the code. Once you have one running, the source is the next thing to look at.