1
0

refactor(MP/daemon): use stack instead of heap for gpio

This commit is contained in:
2026-06-07 15:13:12 +02:00
parent 0f6502bf9b
commit 16e60f46e8
5 changed files with 86 additions and 51 deletions

View File

@@ -29,9 +29,9 @@ void BTN_add_epoll_event(BTN* btn, int tail);
void epoll_init();
static void* epoll_thread(void* arg);
BTN* BTN_init(BTN_type type) {
BTN* btn = malloc(sizeof(BTN));
if (btn == NULL) return NULL;
int BTN_init(BTN* btn, BTN_type type) {
if (btn == NULL) return -1;
pthread_mutex_init(&btn->mutex, NULL);
btn->callback = NULL;
@@ -48,15 +48,18 @@ BTN* BTN_init(BTN_type type) {
break;
default:
printf("Invalid button type\n");
return NULL;
return -1;
}
strcat(gpio_path, btn->pin);
int f = open(GPIO_UNEXPORT, O_WRONLY);
write(f, btn->pin, strlen(btn->pin));
close(f);
if (f != -1) {
write(f, btn->pin, strlen(btn->pin));
close(f);
}
f = open(GPIO_EXPORT, O_WRONLY);
if (f == -1) return -1;
write(f, btn->pin, strlen(btn->pin));
close(f);
@@ -65,6 +68,7 @@ BTN* BTN_init(BTN_type type) {
strcat(direction_path, "/direction");
f = open(direction_path, O_WRONLY);
if (f == -1) return -1;
write(f, "in", 2);
close(f);
@@ -73,7 +77,8 @@ BTN* BTN_init(BTN_type type) {
strcat(edge_path, "/edge");
f = open(edge_path, O_WRONLY);
write(f, "both", 4); // "both" means it triggers on press AND release
if (f == -1) return -1;
write(f, "both", 4);
close(f);
char value_path[100];
@@ -83,7 +88,7 @@ BTN* BTN_init(BTN_type type) {
f = open(value_path, O_RDONLY);
if (f == -1) {
printf("Failed to setup button on pin %s\n", btn->pin);
return NULL;
return -1;
}
btn->fd = f;
@@ -96,7 +101,8 @@ BTN* BTN_init(BTN_type type) {
if (tail >= MAX_BTN) {
pthread_mutex_unlock(&btn_list_mutex);
perror("Failed to add epoll event");
exit(EXIT_FAILURE);
close(btn->fd);
return -1;
}
btn_list[tail] = btn;
@@ -106,7 +112,18 @@ BTN* BTN_init(BTN_type type) {
BTN_add_epoll_event(btn, tail);
pthread_mutex_unlock(&btn_list_mutex);
return btn;
return 0;
}
void BTN_deinit(BTN* btn) {
if (btn == NULL) return;
pthread_mutex_lock(&btn->mutex);
if (btn->fd != -1) {
close(btn->fd);
btn->fd = -1;
}
pthread_mutex_unlock(&btn->mutex);
pthread_mutex_destroy(&btn->mutex);
}
void BTN_set_callback(BTN* btn, BTN_callback callback) {
@@ -121,7 +138,7 @@ void BTN_add_epoll_event(BTN* btn, int tail) {
// EPOLLERR is used to detect if there is an error
// EPOLLET is for edge triggered mode (non-blocking)
ev[tail].events = EPOLLIN | EPOLLERR | EPOLLET;
ev[tail].data.fd = btn->fd;
ev[tail].data.ptr = btn;
int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, btn->fd, &ev[tail]);
if (ret < 0) {
@@ -154,28 +171,19 @@ static void* epoll_thread(void* arg) {
}
for (int i = 0; i < n; i++) {
char buf[2];
int fd = events[i].data.fd;
int tail = -1;
BTN* btn = NULL;
for (int j = 0; j < MAX_BTN; j++) {
if (btn_list[j] == NULL) continue;
if (btn_list[j]->fd == fd) {
tail = j;
btn = btn_list[j];
break;
}
}
if (tail == -1) {
printf("No button found for fd %d\n", fd);
continue;
}
pread(btn->fd, buf, sizeof(buf), 0);
if (buf[0] == '1') {
// printf("Button %s pressed\n", btn->pin);
if (btn->callback != NULL) {
btn->callback();
BTN* btn = (BTN*)events[i].data.ptr;
if (btn == NULL) continue;
pthread_mutex_lock(&btn->mutex);
if (btn->fd != -1) {
pread(btn->fd, buf, sizeof(buf), 0);
if (buf[0] == '1') {
if (btn->callback != NULL) {
btn->callback();
}
}
}
pthread_mutex_unlock(&btn->mutex);
}
}
return NULL;

View File

@@ -22,7 +22,8 @@ typedef struct {
pthread_mutex_t mutex;
} BTN;
BTN* BTN_init(BTN_type type);
int BTN_init(BTN* btn, BTN_type type);
void BTN_deinit(BTN* btn);
void BTN_set_callback(BTN* btn, BTN_callback callback);
#endif

View File

@@ -16,9 +16,8 @@
#include <stdlib.h>
LED* LED_init(LED_type type) {
LED* led = malloc(sizeof(LED));
if (led == NULL) return NULL;
int LED_init(LED* led, LED_type type) {
if (led == NULL) return -1;
// Concatenate GPIO LED path based on type
char gpio_path[32] = GPIO_LED_BASE;
@@ -32,7 +31,7 @@ LED* LED_init(LED_type type) {
break;
default:
printf("Invalid LED type\n");
return NULL;
return -1;
}
strcat(gpio_path, pin);
@@ -63,15 +62,15 @@ LED* LED_init(LED_type type) {
f = open(value_path, O_RDWR);
if (f == -1) {
printf("Failed to setup led on pin %s\n", pin);
return NULL;
return -1;
}
led->gpio = f;
if (pthread_mutex_init(&led->mutex, NULL) != 0) {
close(f);
return NULL;
return -1;
}
return led;
return 0;
}
void LED_on(LED* led) {
@@ -100,8 +99,17 @@ void LED_toggle(LED* led) {
char value[2];
pread(led->gpio, value, sizeof(value), 0);
if (value[0] == '0') {
LED_on(led);
pwrite(led->gpio, "1", sizeof("1"), 0);
} else {
LED_off(led);
pwrite(led->gpio, "0", sizeof("0"), 0);
}
pthread_mutex_unlock(&led->mutex);
}
void LED_deinit(LED* led) {
if (led == NULL) {
return;
}
pthread_mutex_destroy(&led->mutex);
close(led->gpio);
}

View File

@@ -16,9 +16,10 @@ typedef struct {
pthread_mutex_t mutex;
} LED;
LED* LED_init(LED_type type);
int LED_init(LED* led, LED_type type);
void LED_on(LED* led);
void LED_off(LED* led);
void LED_toggle(LED* led);
void LED_deinit(LED* led);
#endif //LED_H

View File

@@ -21,17 +21,30 @@
int main(void) {
BTN btn_inc, btn_dec, btn_mode;
if (BTN_init(&btn_inc, BTN_INCREASE) != 0) {
fprintf(stderr, "Failed to initialize increase button\n");
return 1;
}
if (BTN_init(&btn_dec, BTN_DECREASE) != 0) {
fprintf(stderr, "Failed to initialize decrease button\n");
return 1;
}
if (BTN_init(&btn_mode, BTN_MODE) != 0) {
fprintf(stderr, "Failed to initialize mode button\n");
return 1;
}
BTN* btn_inc = BTN_init(BTN_INCREASE);
BTN* btn_dec = BTN_init(BTN_DECREASE);
BTN* btn_mode = BTN_init(BTN_MODE);
LED led_power;
if (LED_init(&led_power, LED_POWER) != 0) {
fprintf(stderr, "Failed to initialize power LED\n");
return 1;
}
LED* led_power = LED_init(LED_POWER);
BTN_set_callback(btn_inc, btn_increase_period);
BTN_set_callback(btn_dec, btn_decrease_period);
BTN_set_callback(btn_mode, mode_toggle);
BTN_set_callback(&btn_inc, btn_increase_period);
BTN_set_callback(&btn_dec, btn_decrease_period);
BTN_set_callback(&btn_mode, mode_toggle);
struct ipc_callbacks_t ipc_cbs = {
.on_dec_period = decrease_period,
@@ -54,7 +67,7 @@ int main(void) {
init_oled(&oled_cbs);
btn_set_led(led_power);
btn_set_led(&led_power);
init_animations();
while (1) {
@@ -62,5 +75,9 @@ int main(void) {
}
stop_ipc_server();
LED_deinit(&led_power);
BTN_deinit(&btn_inc);
BTN_deinit(&btn_dec);
BTN_deinit(&btn_mode);
return 0;
}