Skip to content

Hw alloc - #387

Draft
JesseMelon wants to merge 8 commits into
OpenPRoT:mainfrom
JesseMelon:hw-alloc
Draft

Hw alloc#387
JesseMelon wants to merge 8 commits into
OpenPRoT:mainfrom
JesseMelon:hw-alloc

Conversation

@JesseMelon

@JesseMelon JesseMelon commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Pin ownership: compile-time hardware allocation

This is meant to reduce the number of unsafe keywords by implementing a zero overhead linear chain of authority from the one physical unsafe boundary - hardware.

By collecting hardware facts into data tables, we can assume the correctness of these tables to make functions safe. This also reduces implementation effort for new targets who can reuse more behavior.

This PR converts gpio and i2c to use the safer hardware allocation model, mirroring the abstraction boundaries from zephyr whenever possible.


Writing a test against this

There are two sides. Whoever holds the SCU grant muxes the pin; everyone else binds an
already-muxed pin.
In practice: the kernel/board side routes, userspace apps bind.

Kernel / board side — mint, route, use

use ast10x0_peripherals::gpio::{GpioRole, IntoGpio};
use ast10x0_peripherals::scu::{self, create_pins};

// SAFETY: called once per binary, at boot, with exclusive SoC access.
let pins = unsafe { create_pins() };
let a0 = pins.scu410_0.into_gpio();
let a1 = pins.scu410_1.into_gpio();

scu::route(&(&a0, &a1));          // ONE call, all handles in one tuple → minimal RMWs, folded at compile time

a0.apply(GpioRole::Output);
a0.apply(GpioRole::SetHigh);
let latched = a0.read(a0.map().out_level);

Userspace app — mint, bind, use

The kernel already routed the pin at the SCU; userspace has no SCU grant, so it binds instead of
routing (writes no SCU register):

use ast10x0_peripherals::create_pins;
use ast10x0_peripherals::gpio::{bind_gpio, GpioRole};

let pins = unsafe { create_pins() };
let a0 = bind_gpio(pins.scu410_0);   // no SCU write — pin was routed kernel-side
a0.apply(GpioRole::Input);
a0.ack(a0.map().int_status);

I2C server app

let pins = unsafe { create_pins() };
let (scl, sda) = (pins.scu418_0, pins.scu418_1);

let (Some(m), Some(s)) = (non_cached_buf!(4096), non_cached_buf!(256)) else { /* already taken */ };
let driver = i2c_backend::open_bus_dma(scl, sda, &CFG, m, s)?;   // pins name the controller; init + DMA in one step

The four rules (read before you copy-paste)

  1. create_pins() runs exactly once per binary. It's unsafe for that reason. Each app and the
    kernel each call it once at boot; it hands you every pin token.
  2. Pin tokens are move-only. Consuming one into into_gpio() / bind_gpio() / i2c_bus() is
    your proof of exclusive ownership. Using a pin twice — or minting two handles for one pin — does
    not compile.
  3. Only the SCU-grant holder muxes. Kernel/board: into_gpio() then scu::route(...).
    Userspace: bind_gpio() (binds an already-routed pin).
  4. Call scu::route() once, passing every handle as a single tuple: route(&(&a, &b, &c)). All
    mux writes coalesce at compile time. A lone handle is fine too: route(&h).

Adding a new pin or capability

Add a row to the pins! table in target/ast10x0/peripherals/scu/pins.rs. Each row is one physical
pad plus one entry per capability it supports — capability: &[route writes] => datum:

scu414_30 {
    I2cScl: &[set(0x414, 30)]   => I2cData { ctrl: I2C_CTRL[1] },
    Gpio:   &[clear(0x414, 30)] => GpioData { bit: 30, map: &EFGH },
},
  • GPIO register groups (ABCD/EFGH/IJKL offset tables) live in gpio/map.rs; the Gpio datum points
    the pin at its group (&EFGH) and bit.
  • A contradictory route (sets and clears the same bit) or a bad map is a compile error, not a
    runtime panic.

Layout

Eight logical commits, bottom-up: HAL core (resource + field_mux) → HAL GPIO → HAL I2C → SCU pin
universe → GPIO port → I2C port → board wiring → test migration.

@JesseMelon
JesseMelon force-pushed the hw-alloc branch 4 times, most recently from 2c9f65a to 774ca8e Compare August 4, 2026 15:01
@JesseMelon
JesseMelon force-pushed the hw-alloc branch 2 times, most recently from 47593fd to 1e8ff88 Compare August 18, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant