New structure test simulatin KED and submodule for gpio Control on rasberry pi without funcotin pointers

linux_test_nopointer
Kynsight 2 months ago
parent 388861864c
commit 01ab78a370

@ -19,18 +19,31 @@
``` sudo apt install libgpiod-dev ```
# To Compile from root of project
## Prepeare for MAKE
```cmake -S ked -B build -DMAIN_FILE=examples/pin_control.c```
this will also create the build diretory for you.
## MAKE
```cd build```
```make```
## RUN
```./ked_executable -pin 21 -dir out -set```
Will set GPIO21 pin (HEADER 40) to High
#Size Difference with Pointers, don't forget tha tin an MCU envoiroment it will also execute faster.
```
With Pointers
text data bss dec hex filename
3812 340 16 4168 1048 ked_executable
Without Pointer
text data bss dec hex filename
3692 332 16 4040 fc8 ked_executable ```

@ -1,6 +1,6 @@
/**
* @file gpio_control.c
* @brief CLI utility to control GPIOs using KED GPIO interface (Linux).
* @brief CLI utility to control GPIO pins using KED GPIO API on Linux.
*/
#include "../ked/peripherals/gpio/gpio.h"
@ -9,63 +9,72 @@
#include <string.h>
/**
* @brief Simple command-line tool to test the GPIO API.
* @brief Print usage message for the CLI tool.
*/
void print_usage(const char* prog_name) {
printf("Usage: %s -pin <number> -set|-reset|-toggle|-read\n", prog_name);
}
/**
* @brief Entry point for GPIO control CLI.
*/
int main(int argc, char* argv[]) {
if (argc < 4) {
printf("Usage: %s -pin <BCM_number> -[set|reset|toggle|read]\n", argv[0]);
print_usage(argv[0]);
return 1;
}
unsigned int pin = 0;
const char* action = NULL;
uint32_t pin = 0;
uint8_t action = 0xFF; // 0=set, 1=reset, 2=toggle, 3=read
for (int i = 1; i < argc; i++) {
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-pin") == 0 && i + 1 < argc) {
pin = (unsigned int)atoi(argv[++i]);
} else if (strncmp(argv[i], "-", 1) == 0) {
action = argv[i] + 1; // skip '-' prefix
pin = atoi(argv[++i]);
} else if (strcmp(argv[i], "-set") == 0) {
action = 0;
} else if (strcmp(argv[i], "-reset") == 0) {
action = 1;
} else if (strcmp(argv[i], "-toggle") == 0) {
action = 2;
} else if (strcmp(argv[i], "-read") == 0) {
action = 3;
}
}
if (pin == 0 || !action) {
fprintf(stderr, "Invalid usage.\n");
return 1;
if (pin == 0 || action == 0xFF) {
print_usage(argv[0]);
return 2;
}
gpio_t gpio;
gpio_config cfg = {
gpio_t gpio = {
.chipname = "/dev/gpiochip0",
.line_offset = pin,
.mode = GPIO_MODE_DEFAULT,
.direction = (strcmp(action, "read") == 0) ? GPIO_DIRECTION_INPUT : GPIO_DIRECTION_OUTPUT,
.bias = GPIO_BIAS_NONE
.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
};
gpio_error_t err = ked_gpio_init(&gpio, &cfg);
if (err != GPIO_OK) {
if (gpio.on_error) gpio.on_error(err);
return 1;
if (ked_gpio_init(&gpio) != T_GPIO_ERR_OK) {
fprintf(stderr, "Failed to initialize GPIO%u\n", pin);
return 3;
}
if (strcmp(action, "set") == 0) {
gpio.set(true);
//printf("GPIO%u set HIGH\n", pin);
} else if (strcmp(action, "reset") == 0) {
gpio.set(false);
//printf("GPIO%u set LOW\n", pin);
} else if (strcmp(action, "toggle") == 0) {
gpio.toggle();
//printf("GPIO%u toggled\n", pin);
} else if (strcmp(action, "read") == 0) {
bool value = gpio.read();
printf("%s\n", value ? "1" : "0");
} else {
fprintf(stderr, "Unknown action: %s\n", action);
if (gpio.on_error) gpio.on_error(GPIO_ERR_UNKNOWN);
return 1;
switch (action) {
case 0:
ked_gpio_set(&gpio, 1);
break;
case 1:
ked_gpio_set(&gpio, 0);
break;
case 2:
ked_gpio_toggle(&gpio);
break;
case 3:
printf("GPIO%u value: %d\n", pin, ked_gpio_read(&gpio));
break;
}
gpio.deinit();
ked_gpio_deinit(&gpio);
return 0;
}

@ -5,7 +5,7 @@
* @date 24.04.2025
* @version 0.0.1
**************************************************************************************************
* @brief Platform-independent GPIO interface for the KED library.
* @brief Platform-independent GPIO interface for the KED library. For more details, see [KED Wiki - GPIO](https://wiki.kynsight.com/bin/view/Kynsight/Projects/KED/Peripherals/GPIO/).
*
* **Detailed Description :**
* This header defines a hardware abstraction layer (HAL) for General Purpose I/O (GPIO)
@ -19,10 +19,12 @@
*
* Usage Example:
* @code
* gpio_t* pin = KED_GPIO.init(&config);
* KED_GPIO.set(pin, true);
* bool state = KED_GPIO.read(pin);
* KED_GPIO.toggle(pin);
* gpio_config cfg = { ... };
* gpio_t pin = ked_gpio_init(&cfg);
* ked_gpio_set(&pin, true);
* bool state = ked_gpio_read(&pin);
* ked_gpio_toggle(&pin);
* ked_gpio_deinit(&pin);
* @endcode
*
* @todo
@ -30,148 +32,146 @@
* - 24.04.2025: Implement Defined States, Errors, Configuration Options
**************************************************************************************************
*/
#ifndef KED_PERIPHERALS_GPIO_GPIO_H_
#define KED_PERIPHERALS_GPIO_GPIO_H_
#ifndef KED_PERIPHERALS_GPIO_H_
#define KED_PERIPHERALS_GPIO_H_
#include <stdbool.h>
#include <stdint.h>
/**
* @brief Enumeration for GPIO functional modes.
*/
/** GPIO Mode Types */
typedef enum {
GPIO_MODE_DEFAULT,
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
GPIO_MODE_ANALOG,
GPIO_MODE_ALTERNATE
} gpio_mode_t;
/**
* @brief Enumeration for GPIO direction settings.
*/
T_GPIO_MODE_DEFAULT,
T_GPIO_MODE_INPUT,
T_GPIO_MODE_OUTPUT,
T_GPIO_MODE_ANALOG,
T_GPIO_MODE_ALTERNATE
} gpio_function_t;
/** GPIO Direction (explicit) */
typedef enum {
GPIO_DIRECTION_INPUT,
GPIO_DIRECTION_OUTPUT
T_GPIO_DIRECTION_INPUT,
T_GPIO_DIRECTION_OUTPUT
} gpio_direction_t;
/**
* @brief Enumeration for GPIO drive configurations.
*/
/** Drive types for output pins */
typedef enum {
GPIO_DRIVE_DEFAULT,
GPIO_DRIVE_PUSH_PULL,
GPIO_DRIVE_OPEN_DRAIN
T_GPIO_DRIVE_DEFAULT,
T_GPIO_DRIVE_PUSH_PULL,
T_GPIO_DRIVE_OPEN_DRAIN
} gpio_drive_t;
/**
* @brief Enumeration for internal bias resistor settings.
*/
/** Pull-up/pull-down configurations */
typedef enum {
GPIO_BIAS_NONE,
GPIO_BIAS_DISABLE,
GPIO_BIAS_PULL_UP,
GPIO_BIAS_PULL_DOWN
T_GPIO_BIAS_DEFAULT,
T_GPIO_BIAS_DISABLE,
T_GPIO_BIAS_PULL_UP,
T_GPIO_BIAS_PULL_DOWN
} gpio_bias_t;
/**
* @brief Enumeration for GPIO speed settings.
*/
/** Optional pin speed enumeration */
typedef enum {
GPIO_SPEED_DEFAULT,
GPIO_SPEED_LOW,
GPIO_SPEED_MEDIUM,
GPIO_SPEED_HIGH,
GPIO_SPEED_VERY_HIGH
T_GPIO_SPEED_DEFAULT,
T_GPIO_SPEED_LOW,
T_GPIO_SPEED_MEDIUM,
T_GPIO_SPEED_HIGH,
T_GPIO_SPEED_VERY_HIGH
} gpio_speed_t;
/**
* @brief Enumeration for enabling or disabling GPIO interrupts.
*/
/** Enable/disable pin interrupt */
typedef enum {
GPIO_IRQ_DISABLED,
GPIO_IRQ_ENABLED
T_GPIO_IRQ_DISABLED,
T_GPIO_IRQ_ENABLED
} gpio_irq_t;
/**
* @brief GPIO error status codes.
*/
/** GPIO Status */
typedef enum {
T_GPIO_STATUS_NOT_INIT, /**< GPIO is not initialized */
T_GPIO_STATUS_READY, /**< GPIO is ready for use */
T_GPIO_STATUS_BUSY, /**< GPIO is currently in use */
T_GPIO_STATUS_ERROR, /**< GPIO encountered an error */
T_GPIO_STATUS_UPDATING /**< GPIO is currently being reconfigured */
} gpio_status_t;
/** GPIO error status codes */
typedef enum {
GPIO_OK,
GPIO_ERR_UNSUPPORTED_MODE,
GPIO_ERR_LINE_BUSY,
GPIO_ERR_NOT_AVAILABLE,
GPIO_ERR_NO_PULL,
GPIO_ERR_NOT_ANALOG,
GPIO_ERR_UNKNOWN
T_GPIO_ERR_OK, /*!< Suscess flag for the Init Function */
T_GPIO_ERR_UNSUPPORTED_MODE, /*!< Mode is either not valid orsupported by **Hardwaware** */
T_GPIO_ERR_UNSUPPORTED_ALTERNATE, /*!< Alternateive mode is unvalid */
T_GPIO_ERR_BUS_BUSY, /*!< The chosen GPIO BUS is already in Use */
T_GPIO_ERR_NOT_AVAILABLE, /*!< Pin does Not aloow GPIO functionalities or does not Exists */
T_GPIO_ERR_NOT_BIASABLE, /*!< No Pull-Up or Pull-Down Option are awailable */
T_GPIO_ERR_NO_INTERRUPT_SUPPORT, /*!< This GPIO Doesn't allow interrupts */
T_GPIO_ERR_UNSUPPORTED_DRIVE, /*!< This gate griving option is Unsupported (Pushpull, open drain etc..) */
T_GPIO_ERR_UNSUPPORTED_SPEED, /*!< The choosen bus speed is not supported */
T_GPIO_ERR_UNKNOWN /*!< Goal Would be To never be Used, but can be helpful during Developpment */
} gpio_error_t;
/**
* @brief Function pointer type for writing a logic level.
*/
typedef void (*gpio_write_fn)(bool value);
/**
* @brief Function pointer type for reading a logic level.
*/
typedef bool (*gpio_read_fn)(void);
/**
* @brief Function pointer type for toggling a GPIO pin.
*/
typedef void (*gpio_toggle_fn)(void);
/** GPIO configuration structure for Linux */
#ifdef KED_USES_LINUX
typedef struct {
const char* chipname;
unsigned int line_offset;
gpio_function_t mode;
gpio_direction_t direction;
gpio_bias_t bias;
gpio_status_t status;
} gpio_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Function pointer type for GPIO deinitialization.
* @brief Initialize a GPIO pin.
* @param gpio Pointer to target gpio_t object
* @param config Pointer to configuration structure
* @return gpio_error_t status
*/
typedef void (*gpio_deinit_fn)(void);
gpio_error_t ked_gpio_init(const gpio_t* gpio);
/**
* @brief Abstract GPIO handle with callback operations.
* @brief Update configuration of an already initialized GPIO.
*
* This function allows changing selected configuration parameters such as direction,
* bias, or other runtime-reconfigurable options without a full re-init.
*
* @param gpio Pointer to initialized gpio object
* @param config Pointer to new configuration structure
* @return gpio_error_t indicating success or failure of update
*/
typedef void (*gpio_error_fn)(gpio_error_t);
gpio_error_t ked_gpio_update(gpio_t* gpio);
/**
* @brief Abstract GPIO handle with callback operations.
* @brief Deinitialize and release GPIO
* @param gpio Pointer to initialized gpio object
*/
typedef struct {
gpio_write_fn set;
gpio_read_fn read;
gpio_toggle_fn toggle;
gpio_deinit_fn deinit; /**< Deinitialization function pointer */
gpio_error_fn on_error; /**< Error handling callback */
} gpio_t;
void ked_gpio_deinit(gpio_t* gpio);
/**
* @brief Function pointer type for platform-specific GPIO initialization.
* @brief Set GPIO output logic level
* @param gpio Pointer to initialized gpio object
* @param value True for HIGH, false for LOW
*/
typedef gpio_error_t (*gpio_init_fn)(gpio_t* gpio, const void* config);
void ked_gpio_set(gpio_t* gpio, uint8_t value);
#ifdef KED_USES_LINUX
/**
* @brief Platform-specific GPIO configuration structure for Linux.
* @brief Read the GPIO logic level
* @param gpio Pointer to initialized gpio object
* @return Logic level (true or false)
*/
typedef struct {
const char* chipname;
unsigned int line_offset;
gpio_mode_t mode;
gpio_direction_t direction;
gpio_bias_t bias;
} gpio_config;
#endif
uint8_t ked_gpio_read(gpio_t* gpio);
/**
* @brief Initialize a GPIO using the specified configuration.
*
* @param gpio Pointer to target gpio_t handle
* @param config Platform-specific GPIO configuration struct
* @return GPIO_OK on success, or an appropriate gpio_error_t
* @brief Toggle GPIO output state
* @param gpio Pointer to initialized gpio object
*/
gpio_error_t ked_gpio_init(gpio_t* gpio, const gpio_config* config);
void ked_gpio_toggle(gpio_t* gpio);
/**
* @brief Deinitialize and release resources associated with a GPIO pin.
*/
void ked_gpio_deinit(gpio_t* gpio);
void ked_gpio_handle_error(gpio_error_t err);
#ifdef __cplusplus
}
#endif
#endif /* KED_PERIPHERALS_GPIO_GPIO_H_ */

@ -1,6 +1,6 @@
/**
* @file gpio_linux.c
* @brief GPIO implementation for Linux using libgpiod and KED callback injection.
* @brief GPIO implementation for Linux using libgpiod and internal context management.
*/
#include "../../ked/peripherals/gpio/gpio.h"
@ -10,48 +10,28 @@
/**
* @brief Internal Linux GPIO context.
*
* Holds pointers to the open GPIO chip and the requested line.
*/
typedef struct {
struct gpiod_chip* chip; /**< File descriptor to the opened GPIO chip */
struct gpiod_line* line; /**< Reference to the requested GPIO line */
struct gpiod_chip* chip;
struct gpiod_line* line;
} gpio_linux_ctx_t;
static gpio_linux_ctx_t gpio_ctx;
/**
* @brief Set the output level of the GPIO line.
*
* @param value Logic level to set (true for HIGH, false for LOW).
*/
static void gpio_linux_set(bool value) {
void ked_gpio_set(gpio_t* gpio, uint8_t value) {
gpiod_line_set_value(gpio_ctx.line, value);
}
/**
* @brief Read the current logic level of the GPIO line.
*
* @return Logic level (true for HIGH, false for LOW).
*/
static bool gpio_linux_read(void) {
return gpiod_line_get_value(gpio_ctx.line);
uint8_t ked_gpio_read(gpio_t* gpio) {
return (uint8_t)gpiod_line_get_value(gpio_ctx.line);
}
/**
* @brief Toggle the current state of the GPIO output.
*/
static void gpio_linux_toggle(void) {
int current = gpiod_line_get_value(gpio_ctx.line);
void ked_gpio_toggle(gpio_t* gpio) {
uint8_t current = (uint8_t)gpiod_line_get_value(gpio_ctx.line);
gpiod_line_set_value(gpio_ctx.line, !current);
}
/**
* @brief Release the GPIO line and chip.
*
* Called during deinitialization to free resources.
*/
static void gpio_linux_deinit(void) {
void gpio_linux_deinit(gpio_t* gpio) {
if (gpio_ctx.line) {
gpiod_line_release(gpio_ctx.line);
gpio_ctx.line = NULL;
@ -62,78 +42,63 @@ static void gpio_linux_deinit(void) {
}
}
/**
* @brief Default error handling function.
*
* @param err The GPIO error code to report.
*/
static void gpio_linux_handle_error(gpio_error_t err) {
void ked_gpio_handle_error(gpio_error_t err) {
fprintf(stderr, "[GPIO ERROR] Code: %d\n", err);
}
/**
* @brief Initialize a GPIO using a Linux-specific gpio_config.
*
* Sets the direction and bias of the line according to the config.
*
* @param gpio Pointer to a gpio_t handle to be configured.
* @param config Pointer to a Linux-specific gpio_config structure.
* @return GPIO_OK on success or an appropriate gpio_error_t on failure.
*/
gpio_error_t ked_gpio_init(gpio_t* gpio, const gpio_config* config) {
gpio_ctx.chip = gpiod_chip_open(config->chipname);
gpio_error_t ked_gpio_init(const gpio_t* gpio) {
gpio_ctx.chip = gpiod_chip_open(gpio->chipname);
if (!gpio_ctx.chip) {
gpio->on_error(GPIO_ERR_NOT_AVAILABLE);
return GPIO_ERR_NOT_AVAILABLE;
ked_gpio_handle_error(T_GPIO_ERR_NOT_AVAILABLE);
return T_GPIO_ERR_NOT_AVAILABLE;
}
gpio_ctx.line = gpiod_chip_get_line(gpio_ctx.chip, config->line_offset);
gpio_ctx.line = gpiod_chip_get_line(gpio_ctx.chip, gpio->line_offset);
if (!gpio_ctx.line) {
gpiod_chip_close(gpio_ctx.chip);
gpio->on_error(GPIO_ERR_NOT_AVAILABLE);
return GPIO_ERR_NOT_AVAILABLE;
ked_gpio_handle_error(T_GPIO_ERR_NOT_AVAILABLE);
return T_GPIO_ERR_NOT_AVAILABLE;
}
struct gpiod_line_request_config req_cfg = {
.consumer = "ked",
.request_type = (config->direction == GPIO_DIRECTION_OUTPUT)
.consumer = "ked_gpio",
.request_type = (gpio->direction == T_GPIO_DIRECTION_OUTPUT)
? GPIOD_LINE_REQUEST_DIRECTION_OUTPUT
: GPIOD_LINE_REQUEST_DIRECTION_INPUT,
.flags = 0
};
if (config->bias == GPIO_BIAS_PULL_UP) {
if (gpio->bias == T_GPIO_BIAS_PULL_UP)
req_cfg.flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP;
} else if (config->bias == GPIO_BIAS_PULL_DOWN) {
else if (gpio->bias == T_GPIO_BIAS_PULL_DOWN)
req_cfg.flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN;
} else if (config->bias == GPIO_BIAS_DISABLE) {
else if (gpio->bias == T_GPIO_BIAS_DISABLE)
req_cfg.flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE;
} else if (config->bias == GPIO_BIAS_NONE) {
else if (gpio->bias == T_GPIO_BIAS_DEFAULT)
req_cfg.request_type = GPIOD_LINE_REQUEST_DIRECTION_AS_IS;
}
if (gpiod_line_request(gpio_ctx.line, &req_cfg, 0) < 0) {
gpiod_chip_close(gpio_ctx.chip);
gpio->on_error(GPIO_ERR_LINE_BUSY);
return GPIO_ERR_LINE_BUSY;
ked_gpio_handle_error(T_GPIO_ERR_BUS_BUSY);
return T_GPIO_ERR_BUS_BUSY;
}
gpio->set = gpio_linux_set;
gpio->read = gpio_linux_read;
gpio->toggle = gpio_linux_toggle;
gpio->deinit = gpio_linux_deinit;
gpio->on_error = gpio_linux_handle_error;
return GPIO_OK;
}
/**
* @brief Generic GPIO deinitialization entry point.
*
* @param gpio Pointer to the gpio_t structure with deinit function populated.
*/
//3812 340 16 4168 1048 ked_executable
//3816 340 16 4172 104c ked_executable
//3692 332 16 4040 fc8 ked_executable
void ked_gpio_deinit(gpio_t* gpio) {
/*
if (gpio && gpio->deinit) {
gpio->deinit();
gpio->status = T_GPIO_STATUS_NOT_INIT;
}*/
}
gpio_error_t ked_gpio_update(gpio_t* gpio) {
ked_gpio_deinit(gpio);
return ked_gpio_init(gpio);
}

Loading…
Cancel
Save