objc

examples/runtime/gpio/main.c
#include <runtime-hw/hw.h>
#define GPIO_BOOTSEL 30
#define GPIO_A 12 // Button A
#define GPIO_B 13 // Button B
#define GPIO_X 14 // Button X
#define GPIO_Y 15 // Button Y
// RUNLOOP
void runloop(sys_event_queue_t *queue) {
int core = sys_thread_core();
sys_printf("Starting runloop on core %d...\n", core);
// Process events until the queue is empty
while (true) {
if (event == NULL) {
// No more events to process
break;
}
// Simulate processing the event
sys_printf("core %d: Processing event: %s (queue size=%d)\n", core,
(char *)event, sys_event_queue_size(queue));
// Free the allocated string
sys_free(event);
}
sys_printf("core %d: Runloop finished.\n", core);
}
// GPIO CALLBACK
void gpio_callback(uint8_t pin, hw_gpio_event_t event, void *userdata) {
sys_event_queue_t *queue = (sys_event_queue_t *)userdata;
int core = sys_thread_core();
// Shutdown the queue if we have produced enough events
if (pin == GPIO_BOOTSEL) {
return;
}
// Put the event into the queue
// Create a new event string
char *event_data = sys_malloc(50);
if (!event_data) {
return;
} else {
const char *state_str = NULL;
if ((event & HW_GPIO_RISING) && (event & HW_GPIO_FALLING)) {
state_str = "RISING|FALLING";
} else if (event & HW_GPIO_RISING) {
state_str = "RISING";
} else if (event & HW_GPIO_FALLING) {
state_str = "FALLING";
} else {
state_str = "UNKNOWN";
}
sys_sprintf(event_data, 50, "gpio(core=%d pin=%d state=%s)", core, pin,
state_str);
}
// Push the event into the queue
if (!sys_event_queue_try_push(queue, event_data)) {
sys_free(event_data);
}
}
// CORE 1 TASKS
void core1_task(void *arg) {
sys_printf("core %d: Starting task\n", sys_thread_core());
runloop(queue);
sys_printf("core %d: Task completed!\n", sys_thread_core());
}
// CORE 0 TASKS
bool core0_task() {
// Initialize the event queue with a capacity of 20 events
// Check that GPIO is supported
if (hw_gpio_count() == 0) {
sys_printf("main: GPIO is not supported\n");
return false;
}
// Create the task on core 1. If this wasn't an RP2040, we would
// just use sys_thread_create() instead.
sys_printf("main: Starting task on core 1...\n");
if (sys_thread_create_on_core(core1_task, &queue, 1) == false) {
sys_printf("main: Failed to launch task on core 1\n");
return false;
}
// Initialize a GPIO pin for input
sys_printf("Defining pull-up GPIO inputs %d, %d, %d, %d\n", GPIO_A, GPIO_B,
GPIO_X, GPIO_Y);
// The BOOTSEL button is used to signal shutdown
sys_printf("main: Initializing GPIO for BOOTSEL button %d\n", GPIO_BOOTSEL);
hw_gpio_init(GPIO_BOOTSEL, HW_GPIO_INPUT);
// Set the GPIO callback for injecting events into the queue
hw_gpio_set_callback(gpio_callback, &queue);
// Run the event processing loop
runloop(&queue);
sys_printf("core %d: Task completed!\n", sys_thread_core());
return true;
}
// MAIN
int main() {
// Initialize
// Run the task
if (core0_task() == false) {
sys_printf("Main: core 0 task failed\n");
}
// Cleanup and exit
return 0;
}