gpio-button-led
The canonical "first example" for the Alp SDK. It opens one GPIO as an output (LED) and one as an input (button), toggles the LED, and reads the button state. Works on every E1M-conformant SoM.
Source: examples/peripheral-io/gpio-button-led/.
board.yaml
som:
sku: E1M-AEN801 # change to your MPN
preset: e1m-evk # stock preset, or write your board out inline
cores:
m55_hp:
# os: omitted → topology default (m55_hp → zephyr).
# Override with os: baremetal or os: off if needed.
app: ./src
peripherals: [gpio]
diagnostics:
log_level: info
Source
#include <alp/peripheral.h>
#include <alp/e1m_pinout.h>
#include <zephyr/kernel.h>
int main(void) {
// Open LED as output
alp_gpio_t *led = alp_gpio_open(ALP_E1M_GPIO_IO1);
if (led == NULL) {
printk("[gpio] led open failed: err=%d\n", (int)alp_last_error());
return -1;
}
alp_gpio_configure(led, ALP_GPIO_OUTPUT, ALP_GPIO_PULL_NONE);
// Open button as input with pull-up
alp_gpio_t *button = alp_gpio_open(ALP_E1M_GPIO_IO0);
if (button == NULL) {
printk("[gpio] button open failed: err=%d\n", (int)alp_last_error());
alp_gpio_close(led);
return -1;
}
alp_gpio_configure(button, ALP_GPIO_INPUT, ALP_GPIO_PULL_UP);
printk("[gpio] init button=ALP_E1M_GPIO_IO0, led=ALP_E1M_GPIO_IO1\n");
// Toggle the LED four times
for (int i = 0; i < 4; i++) {
int status = alp_gpio_write(led, i & 1);
printk("[gpio] led=%d status=%d\n", i & 1, status);
k_msleep(500);
}
// Read the button state
bool pressed;
int status = alp_gpio_read(button, &pressed);
printk("[gpio] is_pressed -> status=%d pressed=%d\n", status, pressed);
alp_gpio_close(button);
alp_gpio_close(led);
printk("[gpio] done\n");
return 0;
}
Build + run (native_sim)
west build -b native_sim/native/64 alp-sdk/examples/peripheral-io/gpio-button-led
west build -t run
Expected output:
*** Booting Zephyr OS build v4.4.0 ***
[gpio] init button=ALP_E1M_GPIO_IO0, led=ALP_E1M_GPIO_IO1
[gpio] led=0 status=0
[gpio] led=1 status=0
[gpio] led=0 status=0
[gpio] led=1 status=0
[gpio] is_pressed -> status=0 pressed=1
[gpio] done
status=0 means ALP_OK. pressed=1 is gpio_emul's default "input is low" report; on real hardware it depends on the button state.
Build + run (real silicon)
tan --project alp-sdk/examples/peripheral-io/gpio-button-led build
tan --project alp-sdk/examples/peripheral-io/gpio-button-led flash
tan build takes no -b flag — the build target comes from the project's board.yaml (som.sku + preset), and tan finds board.yaml by walking up from the current directory when --project is omitted.
On real silicon the button + LED come from preset: e1m-evk in board.yaml: the EVK routes the user button to the encoder push switch (ALP_E1M_GPIO_IO4) and claims the RGB-red pad (ALP_E1M_GPIO_PWM3) as a plain GPIO. Under native_sim, boards/native_sim_native_64.overlay supplies an emulated alp,pin-array covering the same two indices. A non-EVK board swaps the preset for an inline board definition — the app code is unchanged.
Key teaching points
alp_gpio_openreturns a handle orNULL. Always check.alp_last_error()is the only diagnostic forNULL— it's a thread-local; check it immediately after the open call.- Instance IDs (
ALP_E1M_GPIO_IO0) come from<alp/e1m_pinout.h>and are portable across every conformant SoM. alp_gpio_closeis observable — apps that leak handles will hit a runtime check eventually.
Variants
The same example pattern extends to:
- PWM — open + sweep duty cycle (
pwm-led-fade) - I²C — open + ACK-probe (
i2c-scanner) - UART — echo loop (
uart-echo)