Still identical to the one wihtout pointers, but this version is optimised to use a const pointers. So that when we generate more than one pin they all use the same pointer registers without recreating them.

linux_test
Kynsight 2 months ago
parent a8e5cff8e6
commit dbfd008f1d

@ -36,7 +36,7 @@ Will set GPIO21 pin (HEADER 40) to High
```
Size
text data bss dec hex filename
3836 332 16 4184 1058 ked_executable
3696 332 16 4044 fcc ked_executable
```

@ -21,13 +21,15 @@ void print_usage(const char* prog_name) {
* @brief Entry point for GPIO control CLI.
*/
int main(int argc, char* argv[]) {
if (argc < 4) {
uint32_t pin = 0;
uint8_t action = 0xFF; // 0=set, 1=reset, 2=toggle, 3=read
if (argc < 4) {
print_usage(argv[0]);
return 1;
}
uint32_t pin = 0;
uint8_t action = 0xFF; // 0=set, 1=reset, 2=toggle, 3=read
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-pin") == 0 && i + 1 < argc) {
@ -47,37 +49,36 @@ int main(int argc, char* argv[]) {
print_usage(argv[0]);
return 2;
}
gpio_t gpio_conf = {
gpio_t led = {
.chipname = "/dev/gpiochip0",
.line_offset = pin,
.direction = (action == 3) ? T_GPIO_DIRECTION_INPUT : T_GPIO_DIRECTION_OUTPUT,
.bias = T_GPIO_BIAS_DEFAULT,
.mode = T_GPIO_MODE_DEFAULT,
.status = T_GPIO_STATUS_NOT_INIT
.status = T_GPIO_STATUS_NOT_INIT,
.func = NULL
};
gpio_fn_ptr_t led = {0};
gpio_error_t err = ked_gpio_init(&gpio_conf, &led);
gpio_error_t err = ked_gpio_init(&led);
if (err != T_GPIO_ERR_OK) {
if (led.on_error) led.on_error(err);
led.func->on_error(err);
return 1;
}
switch (action) {
case 0:
if (led.set) led.set(1);
led.func->set(1);
break;
case 1:
if (led.set) led.set(0);
led.func->set(0);
break;
case 2:
if (led.toggle) led.toggle();
led.func->toggle();
break;
case 3:
printf("GPIO%u value: %d\n", pin, led.read());
printf("GPIO%u value: %d\n", pin, led.func->read());
break;
}

@ -126,6 +126,7 @@ struct gpio_s {
gpio_direction_t direction;
gpio_bias_t bias;
gpio_status_t status;
const gpio_fn_ptr_t* func;
};
#endif
@ -137,14 +138,14 @@ struct gpio_s {
* @param gpio Pointer to target gpio_t handle
* @return GPIO_OK on success, or an appropriate gpio_error_t
*/
gpio_error_t ked_gpio_init(gpio_t* gpio, const gpio_fn_ptr_t* callbacks);
gpio_error_t ked_gpio_init(gpio_t* gpio);
/**
* @brief Deinitialize and release resources associated with a GPIO pin.
*
* @param gpio Pointer to GPIO object
*/
void ked_gpio_deinit(gpio_t* gpio, const gpio_fn_ptr_t* callbacks);
void ked_gpio_deinit(gpio_t* gpio);
/* === Platform-agnostic GPIO control interface === */

@ -86,6 +86,22 @@ static gpio_error_t gpio_linux_update(void) {
return T_GPIO_ERR_UNSUPPORTED_MODE;
}
/* === Static GPIO Function Table Instance === */
/**
* @brief Shared Linux GPIO function table for all gpio_t instances.
*
* Each GPIO object holds a pointer to this table via its `vtable` field.
* This avoids redundant copies of function pointers per object.
*/
static const gpio_fn_ptr_t gpio_linux_fn = {
.set = gpio_linux_set,
.read = gpio_linux_read,
.toggle = gpio_linux_toggle,
.update = gpio_linux_update,
.on_error = gpio_linux_handle_error
};
/* === Public API Implementation === */
/**
@ -97,7 +113,7 @@ static gpio_error_t gpio_linux_update(void) {
* @param callbacks Optional pointer to gpio_fn_ptr_t to receive platform-specific handlers
* @return T_GPIO_ERR_OK on success, or appropriate error code
*/
gpio_error_t ked_gpio_init(gpio_t* gpio, const gpio_fn_ptr_t* callbacks) {
gpio_error_t ked_gpio_init(gpio_t* gpio) {
gpio_ctx.chip = gpiod_chip_open(gpio->chipname);
if (!gpio_ctx.chip) {
gpio_linux_handle_error(T_GPIO_ERR_NOT_AVAILABLE);
@ -134,13 +150,7 @@ gpio_error_t ked_gpio_init(gpio_t* gpio, const gpio_fn_ptr_t* callbacks) {
return T_GPIO_ERR_BUS_BUSY;
}
if (callbacks) {
((gpio_fn_ptr_t*)callbacks)->set = gpio_linux_set;
((gpio_fn_ptr_t*)callbacks)->read = gpio_linux_read;
((gpio_fn_ptr_t*)callbacks)->toggle = gpio_linux_toggle;
((gpio_fn_ptr_t*)callbacks)->update = gpio_linux_update;
((gpio_fn_ptr_t*)callbacks)->on_error = gpio_linux_handle_error;
}
gpio->func = &gpio_linux_fn;
return T_GPIO_ERR_OK;
}
@ -151,7 +161,7 @@ gpio_error_t ked_gpio_init(gpio_t* gpio, const gpio_fn_ptr_t* callbacks) {
* @param gpio Unused in this implementation
* @param callbacks Pointer to callback table that includes `deinit`
*/
void ked_gpio_deinit(gpio_t* gpio, const gpio_fn_ptr_t* callbacks) {
void ked_gpio_deinit(gpio_t* gpio) {
if (gpio_ctx.line) {
gpiod_line_release(gpio_ctx.line);
gpio_ctx.line = NULL;

Loading…
Cancel
Save