Skip to main content

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_open returns a handle or NULL. Always check.
  • alp_last_error() is the only diagnostic for NULL — 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_close is observable — apps that leak handles will hit a runtime check eventually.

Variants

The same example pattern extends to:

See also

Questions about this page? Discuss in Community Forum