Skip to content

Commit

Permalink
refactoring wrappers and readme info
Browse files Browse the repository at this point in the history
  • Loading branch information
kassane committed Mar 22, 2024
1 parent 6f3617c commit 754cced
Show file tree
Hide file tree
Showing 11 changed files with 624 additions and 246 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI Build

on: [push]

jobs:
build:
strategy:
fail-fast: false
matrix:
runs-on: [ubuntu-latest]
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v4
- uses: korandoru/setup-zig@v1
with:
zig-version: master

- name: prepare-linux
run: |
sudo apt-get update
sudo apt-get install -y cmake
git clone --recursive https://github.com/espressif/esp-idf -b v5.3-dev --depth 1
cd esp-idf && chmod +x ./install.sh && ./install.sh
chmod +x ./export.sh && source ./export.sh
cd ..
- name: Build for esp32-c3
run: |
idf.py set-target esp32c3
idf.py build
idf.py size
idf.py fullclean
- name: Build for esp32-h2
run: |
idf.py set-target esp32h2
idf.py build
idf.py size
idf.py fullclean
- name: Build for esp32-p4
run: |
idf.py --preview set-target esp32p4
idf.py build
idf.py size
idf.py fullclean
49 changes: 38 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
# Using Zig language & toolchain with ESP-IDF
# Using Zig Language & Toolchain with ESP-IDF

| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |

## STATUS: Experimental

## Description

Running zig std allocator (as static-lib) on [esp-idf FreeRTOS](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/freertos.html).
This project aims to integrate Zig language and toolchain with the [Espressif IoT Development Framework](https://github.com/espressif/esp-idf) for enhanced development capabilities on ESP32 and its variants.

## Required
## Prerequisites

- [Zig](https://ziglang.org/download) toolchain - v0.12.0 or master
- [ESP-IDF](https://github.com/espressif/esp-idf) - v4.4 or v5.2
- [ESP-IDF](https://github.com/espressif/esp-idf) - v4.4 or v5.2 or master

### Targets Allowed

| target | commands |
| ------ | -------- |
| esp32 | `-Dtarget=xtensa-freestanding-none -Dcpu=esp32` |
| esp32-s2 | `-Dtarget=xtensa-freestanding-none -Dcpu=esp32s2` |
| esp32-s3 | `-Dtarget=xtensa-freestanding-none -Dcpu=esp32s3` |
| esp32-c2/c3 | `-Dtarget=riscv32-freestanding-none -Dcpu=generic_rv32+c+m` |
| esp32-h2/c5/c6 | `-Dtarget=riscv32-freestanding-none -Dcpu=generic_rv32+a+c+m` |
| esp32-p4 | `-Dtarget=riscv32-freestanding-eabihf -Dcpu=generic_rv32+a+c+f+m` |

<br>
<sub>
Expand All @@ -22,20 +34,35 @@ Running zig std allocator (as static-lib) on [esp-idf FreeRTOS](https://docs.es
</sub>
</br>


### Key Features:

- **Zig Language Integration**: Utilize the Zig programming language to write firmware code, offering modern language features such as comptime, meta-programming, and error handling.

- **Zig Toolchain Integration**: Zig toolchain uses `build.zig`, can be used to build Zig libraries and executables, and can be integrated with the ESP-IDF build system. Also,
replace clang and clang++ with Zig compiler and linker.
- **Note:** For C++ support, zig toolchain uses `llvm-libc++` ABI by default.

- **ESP-IDF Compatibility**: Seamlessly integrate Zig with the ESP-IDF framework, allowing developers to leverage the rich set of APIs and functionalities provided by ESP-IDF for IoT development.

- **Build System Configuration**: Employ CMake to build Zig libraries, enabling easy integration with existing ESP-IDF projects while ensuring efficient dependency management and build configuration.

- **Cross-Platform Development**: Facilitate development across various ESP32 variants including ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-H2, ESP32-P4, ESP32-S2, and ESP32-S3, ensuring broad compatibility and versatility.


### About Allocators

> [!NOTE]
>
> Asserts allocations are within `@alignOf(std.c.max_align_t)` and directly calls
> `malloc`/`free`. Does not attempt to utilize `malloc_usable_size`.
>
> - `std.heap.raw_c_allocator` allocator is safe to use as the backing allocator with
> `std.heap.ArenaAllocator` for example and is more optimal in such a case
> than `std.heap.c_allocator`. - ref.: [std-doc](https://ziglang.org/documentation/master/std/#std.heap.raw_c_allocator)
> - `std.heap.raw_c_allocator` allocator is safe to use as the backing allocator with `std.heap.ArenaAllocator` for example and is more optimal in such a case than `std.heap.c_allocator`. - ref.: [std-doc](https://ziglang.org/documentation/master/std/#std.heap.raw_c_allocator)
>
> Custom Allocators (based on `std.heap.raw_c_allocator`)
> - `std.heap.ArenaAllocator` takes an existing allocator, wraps it, and provides an interface where you can allocate without freeing, and then free it all together. - ref.: [std-doc](https://ziglang.org/documentation/master/std/#std.heap.ArenaAllocator)
>
> - `esp_idf.HeapCapsAllocator.init(caps: u32)`
> - `esp_idf.MultiHeapAllocator.init()` - ref.: [espressif-doc](https://docs.espressif.com/projects/esp-idf/en/v5.2.1/esp32c3/api-reference/system/mem_alloc.html)
> **Custom Allocators** (based on `std.heap.raw_c_allocator`)
>
> - `std.heap.ArenaAllocator` takes an existing allocator, wraps it, and provides an interface where you can allocate without freeing, and then free it all together. - ref.: [std-doc](https://ziglang.org/documentation/master/std/#std.heap.ArenaAllocator)
> - `idf.heap.HeapCapsAllocator` - ref.: [espressif-doc](https://docs.espressif.com/projects/esp-idf/en/v5.2.1/esp32c3/api-reference/system/mem_alloc.html)
> - `idf.heap.MultiHeapAllocator` - ref.: [espressif-doc](https://docs.espressif.com/projects/esp-idf/en/v5.2.1/esp32c3/api-reference/system/mem_alloc.html)
> - `idf.heap.vPortAllocator` - ref.: [FreeRTOS-doc](https://www.freertos.org/a00111.html)
151 changes: 92 additions & 59 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,28 @@ pub fn idf_wrapped_modules(b: *std.Build) *std.Build.Module {
.path = "imports/idf-sys.zig",
},
});
const rtos = b.addModule("rtos", .{
.root_source_file = .{
.path = "imports/rtos.zig",
},
.imports = &.{
.{
.name = "sys",
.module = sys,
},
},
});
const version = b.addModule("ver", .{
.root_source_file = .{
.path = "imports/version.zig",
},
.imports = &.{
.{
.name = "sys",
.module = sys,
},
},
});
const log = b.addModule("log", .{
.root_source_file = .{
.path = "imports/logger.zig",
Expand Down Expand Up @@ -199,9 +221,9 @@ pub fn idf_wrapped_modules(b: *std.Build) *std.Build.Module {
},
},
});
const gpio = b.addModule("gpio", .{
const heap = b.addModule("heap", .{
.root_source_file = .{
.path = "imports/gpio.zig",
.path = "imports/heap.zig",
},
.imports = &.{
.{
Expand All @@ -210,9 +232,9 @@ pub fn idf_wrapped_modules(b: *std.Build) *std.Build.Module {
},
},
});
const heap = b.addModule("heap", .{
const bt = b.addModule("bluetooth", .{
.root_source_file = .{
.path = "imports/heap.zig",
.path = "imports/bluetooth.zig",
},
.imports = &.{
.{
Expand All @@ -221,9 +243,9 @@ pub fn idf_wrapped_modules(b: *std.Build) *std.Build.Module {
},
},
});
const bt = b.addModule("bluetooth", .{
const wifi = b.addModule("wifi", .{
.root_source_file = .{
.path = "imports/bluetooth.zig",
.path = "imports/wifi.zig",
},
.imports = &.{
.{
Expand All @@ -232,9 +254,9 @@ pub fn idf_wrapped_modules(b: *std.Build) *std.Build.Module {
},
},
});
const wifi = b.addModule("wifi", .{
const errors = b.addModule("error", .{
.root_source_file = .{
.path = "imports/wifi.zig",
.path = "imports/error.zig",
},
.imports = &.{
.{
Expand All @@ -243,15 +265,19 @@ pub fn idf_wrapped_modules(b: *std.Build) *std.Build.Module {
},
},
});
const errors = b.addModule("error", .{
const gpio = b.addModule("gpio", .{
.root_source_file = .{
.path = "imports/error.zig",
.path = "imports/gpio.zig",
},
.imports = &.{
.{
.name = "sys",
.module = sys,
},
.{
.name = "error",
.module = errors,
},
},
});
return b.addModule("esp_idf", .{
Expand All @@ -268,8 +294,12 @@ pub fn idf_wrapped_modules(b: *std.Build) *std.Build.Module {
.module = bootloader,
},
.{
.name = "sys",
.module = sys,
.name = "rtos",
.module = rtos,
},
.{
.name = "ver",
.module = version,
},
.{
.name = "lwip",
Expand Down Expand Up @@ -313,54 +343,57 @@ pub fn idf_wrapped_modules(b: *std.Build) *std.Build.Module {

// Targets config
const espressif_targets: []const std.Target.Query = if (isEspXtensa())
&[_]std.Target.Query{
// need zig-fork (using espressif-llvm backend) to support this
.{
.cpu_arch = .xtensa,
.cpu_model = .{ .explicit = &std.Target.xtensa.cpu.esp32 },
.os_tag = .freestanding,
.abi = .none,
},
.{
.cpu_arch = .xtensa,
.cpu_model = .{ .explicit = &std.Target.xtensa.cpu.esp32s2 },
.os_tag = .freestanding,
.abi = .none,
},
.{
.cpu_arch = .xtensa,
.cpu_model = .{ .explicit = &std.Target.xtensa.cpu.esp32s3 },
.os_tag = .freestanding,
.abi = .none,
},
}
xtensa_targets ++ riscv_targets
else
&.{
// esp32-c3/c2
.{
.cpu_arch = .riscv32,
.cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 },
.os_tag = .freestanding,
.abi = .none,
.cpu_features_add = std.Target.riscv.featureSet(&.{ .m, .c }),
},
// esp32-c6/61/h2
.{
.cpu_arch = .riscv32,
.cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 },
.os_tag = .freestanding,
.abi = .none,
.cpu_features_add = std.Target.riscv.featureSet(&.{ .m, .a, .c }),
},
// esp32-p4
.{
.cpu_arch = .riscv32,
.cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 },
.os_tag = .freestanding,
.abi = .none,
.cpu_features_add = std.Target.riscv.featureSet(&.{ .m, .a, .c, .f }),
},
};
riscv_targets;

const riscv_targets = &[_]std.Target.Query{
// esp32-c3/c2
.{
.cpu_arch = .riscv32,
.cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 },
.os_tag = .freestanding,
.abi = .none,
.cpu_features_add = std.Target.riscv.featureSet(&.{ .m, .c }),
},
// esp32-c6/61/h2
.{
.cpu_arch = .riscv32,
.cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 },
.os_tag = .freestanding,
.abi = .none,
.cpu_features_add = std.Target.riscv.featureSet(&.{ .m, .a, .c }),
},
// esp32-p4
.{
.cpu_arch = .riscv32,
.cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 },
.os_tag = .freestanding,
.abi = .eabihf,
.cpu_features_add = std.Target.riscv.featureSet(&.{ .m, .a, .c, .f }),
},
};
const xtensa_targets = &[_]std.Target.Query{
// need zig-fork (using espressif-llvm backend) to support this
.{
.cpu_arch = .xtensa,
.cpu_model = .{ .explicit = &std.Target.xtensa.cpu.esp32 },
.os_tag = .freestanding,
.abi = .none,
},
.{
.cpu_arch = .xtensa,
.cpu_model = .{ .explicit = &std.Target.xtensa.cpu.esp32s2 },
.os_tag = .freestanding,
.abi = .none,
},
.{
.cpu_arch = .xtensa,
.cpu_model = .{ .explicit = &std.Target.xtensa.cpu.esp32s3 },
.os_tag = .freestanding,
.abi = .none,
},
};

fn isEspXtensa() bool {
var result = false;
Expand Down
Loading

0 comments on commit 754cced

Please sign in to comment.