Yarg-Lang is a project to experiment with a dynamic language targetting microcontrollers. It has not yet made a release suitable for wide use. Additional documentation in docs/ and on the wiki.
Yarg aims to be a dedicated language for Microcontroller firmware development. It offers:
- An interactive, on-device, REPL
- Direct hardware access
- Interupt based and multi-core multiprocessing
- Modern language conveniences
- Intended for production deployment, as it gets nearer to a 1.0 release.
Download the latest release from releases, and follow the README instructions in the tar file.
Connect your Pico to your favourite serial terminal. Minicom and Putty are popular choices. Connect to the USB serial device, which will have a name specific to your board and host. Connect at 115200, 8N1. Use a VT100 or ANSI compatible terminal emulation.
Building yarg from source is required for some ports of Yarg, and to contribute to the language itself. See BUILD.md for details.
| dir | Description |
|---|---|
cyarg/ |
yarg implementation in C |
hostyarg/ |
host tooling, notably yarg |
docs/ |
Additional documentation |
test/ |
Various Test Suites. See README.md |
tools/ |
Miscellaneous tools |
vscode-yarg/ |
A VS Code Language Extension for Yarg |
yarg/specimen/ |
Samples of Yarg |
yarg/specimen/conway-life-display |
A Yarg implemention of: jhmcaleely:conway-life-display |
external/ |
dependecies hosted as git submodules. Notably includes littlefs-project:littlefs |
These two samples illustrate Yarg:
hello_ledcan be typed at the REPL after boot, and directly manipulates registers as needed.hello_buttonuses Yarg channels (similar to go channels) to signal when an interrupt is generated by a button. The CPU can simply wait indefinately at idle for each button press.
This sample turns on the builtin LED for a Pico, manipulating the registers directly.
yarg/specimen/hello_led.ya:
// the memory locations we need, see rp2040 datasheet:
// https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
const NUM_BANK0_GPIOS = 30;
place struct {
uint32@0x014 gpio_out_set;
uint32@0x024 gpio_oe_set;
} @xd0000000 sio_hw;
place struct {
struct {
uint32 status;
uint32 ctrl;
}[NUM_BANK0_GPIOS] gpio;
} @x40014000 io_bank0;
// the built in LED on a Pico.
const pico_led = uint32(25);
const gpio_field = uint32(0x1) << pico_led;
// minimally configure a GPIO, assuming core was reset first.
const GPIO_FUNC_SIO = 5;
poke io_bank0.gpio[pico_led].ctrl, GPIO_FUNC_SIO;
poke sio_hw.gpio_oe_set, gpio_field;
// turn the LED on.
poke sio_hw.gpio_out_set, gpio_field;
This sample creates a function that checks the events for the specified GPIO, and signals those on a channel the main coroutine can wait on.
Uses the 'gpio' library, which captures the direct register code above in a library of functions.
Assumes a button is wired to GPIO 2, and a LED+Resistor are connected to GPIO 3.
yarg/specimen/hello_button.ya:
import("gpio");
// GPIO pins to use
const led_io = 12;
const button_io = 11;
fun button_routine(gpio, chan) {
const core = coreNum();
fun gpio_events() {
const events8 = peek(io_bank0.proc[core].ints[uint32(gpio) >> uint32(3)]);
const uint32 events = events8 >> (4 * (uint32(gpio) % uint32(8)));
return events;
}
fun gpio_response() {
const events = gpio_events();
gpio_acknowledge_irq(gpio, events);
share(chan, events);
}
return make_routine(gpio_response, true);
}
// intialise a GPIO for an LED.
gpio_init(led_io);
gpio_set_direction(led_io, GPIO_OUT);
// set up the response routine as an address we can install in the IRQ peripheral
var button_channel = make_channel();
var button_handler_routine = button_routine(button_io, button_channel);
var button_handler_address = pin(button_handler_routine);
gpio_init(button_io);
irq_add_shared_handler(io_irq_bank0, button_handler_address, 0);
// enable interrupts for this gpio
gpio_set_irq_enabled(button_io, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true);
irq_set_enabled(io_irq_bank0, true);
while (true) {
bool state;
var events = receive(button_channel);
if (events == GPIO_IRQ_EDGE_FALL) {
state = false;
} else if (events == GPIO_IRQ_EDGE_RISE) {
state = true;
}
gpio_put(led_io, state);
}
Cornish Yarg is a cheese I enjoy.