vendor-ext-composability
One pad, three ways — a proof that the Alp SDK's vendor-extension layer (<alp/ext/<vendor>/...>) is additive, never exclusive.
Claiming a vendor-specific feature on a pad does not lock that pad out of the portable surfaces. The same physical pad stays usable as a plain digital GPIO and as its portable E1M peripheral.
Source: examples/peripheral-io/vendor-ext-composability/.
The three ways
All on the Arduino A1 analog input — EVK_ADC_ARDUINO_A1, which is ALP_E1M_ADC1.
| Way | Surface | Call |
|---|---|---|
| 1 | Plain GPIO | alp_gpio_open(ALP_E1M_GPIO_ADC1) — the pad's universal GPIO secondary |
| 2 | Portable ADC | alp_adc_open(EVK_ADC_ARDUINO_A1) — the cross-vendor <alp/adc.h> surface, identical on every E1M SoM |
| 3 | Vendor extension | alp_alif_adc_set_trigger_source(handle) — an Alif-only knob from <alp/ext/alif/adc.h>, layered on the Way-2 handle |
Way 3 augments the portable handle; it never replaces it. The header is pulled in defensively with __has_include, so the example compiles on every SoM. On non-Alif silicon the ALP_EXT_ALIF_ADC_AVAILABLE guard is false, the example says so, and the portable Way-2 read keeps working unchanged.
Why this matters
A pad is a shared resource. The SDK guarantees that reaching for a vendor knob never strands the pad — an app can still fall back to the portable peripheral or to a bare GPIO. That guarantee is what lets you prototype against the portable surface, opt into a vendor accelerator where it pays off, and stay portable everywhere else — on the same pins, in the same firmware.
board.yaml
som:
sku: E1M-AEN801 # ships the <alp/ext/alif/adc.h> extension Way 3 uses
preset: e1m-evk
pins:
- { e1m: E1M_ADC1, macro: EVK_ADC_ARDUINO_A1, doc: "Arduino A1 analog input; opened as portable ADC + (on Alif) the vendor-ext trigger knob, and digitally via E1M_GPIO_ADC1" }
cores:
m55_hp:
app: ./src
peripherals:
- adc
- gpio
diagnostics:
log_level: info
Only the routed ADC role is named in pins: — the GPIO secondary is the same pad and needs no separate route.
Expected output
Under native_sim the host overlay wires a GPIO-emul controller, so Way 1 actually toggles the pad. It wires no ADC controller, so Ways 2 and 3 take the graceful skip path — alp_adc_open returns NULL with ALP_ERR_NOT_READY, the same NULL-tolerant contract every SDK open() honours:
[flex] vendor-ext composability: one pad (ALP_E1M_ADC1), three ways
[flex] way 1: ALP_E1M_GPIO_ADC1 driven as a digital GPIO output -- ok
[flex] way 2: ADC open skipped (last_err=-2; native_sim has no ADC)
[flex] done
On a real Alif EVK all three ways run for real.
:::note Two emul controllers in the host overlay
Reaching ALP_E1M_GPIO_ADC1 needs two GPIO-emul controllers, because a single emul controller caps at 32 pins. The shipped overlay shows the canonical two-controller split a full 52-slot board file uses.
:::
Status
Runs on native_sim/native/64; the harness latches on [flex] done. Way 1 executes for real there; Ways 2/3 are proven on Alif silicon.
See also
<alp/adc.h>reference<alp/peripheral.h>reference — GPIOadc-voltmeter— the portable ADC surface on its own- Board portability
- Examples overview