-
-
Notifications
You must be signed in to change notification settings - Fork 40k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC, PoC, etc.] GPIO abstractions #20258
Comments
I'd like to help with this. Couple things:
Is that correct?
|
typedef struct pin_impl_t {
pintype_t type;
union {
uint16_t mcu_pin; This would probably end up being something like Note that With Also with some casts we could use separate structs for pin types instead of a single union for all types, and save some bytes (because the structs won't be padded to the maximum possible size). |
Currently the ChibiOS analog driver code would just silently return 0 if you call Making this code work with the new GPIO abstraction would require either rewriting parts of it (things like |
Yeah, was thinking of |
So the casting would result in something like: typedef struct pin_base_t {
pin_type_t type;
} pin_base_t; typedef struct pin_chibios_t {
pin_base_t base;
ioline_t line;
} pin_chibios_t; typedef struct pin_avr_t {
pin_base_t base;
uint8_t pin;
} pin_avr_t; // #define GP29 29U
const pin_chibios_t pin_gp29 = {.base = {.type = MCU_PIN}, .line = 29U};
#define GP29 ((const pin_base_t*)&pin_gp29) Though as mentioned, at that point we may as well just embed the vtable directly, as if it were C++: typedef struct pin_chibios_t {
gpio_pin_vtable_t vtable;
ioline_t line;
} pin_chibios_t; typedef struct pin_avr_t {
gpio_pin_vtable_t vtable;
uint8_t pin;
} pin_avr_t; // #define GP29 29U
const pin_chibios_t pin_gp29 = {.vtable = &gpio_pin_vtable_mcu_chibios, .line = 29U};
#define GP29 ((const gpio_pin_vtable_t*)&pin_gp29) |
I wonder whether we would need to make this extra abstraction layer optional (especially on AVR the overhead may be significant; also the code using those abstractions would probably require at least LTO to be fully optimized, because otherwise the compiler won't see the constant values stored in pin objects and vtables). #if GPIO_EXPANDER_ENABLE
/* Using GPIO abstractions */
typedef struct pin_vtable_t {
bool (*read_pin)(pin_t pin);
void (*write_pin)(pin_t pin, bool value);
} pin_vtable_t;
typedef struct pin_base_t {
const pin_vtable_t *vtable;
} pin_base_t;
typedef const pin_base_t *pin_t;
typedef struct pin_platform_t {
pin_base_t base;
pin_platform_raw_t raw_pin;
};
extern const pin_vtable_t pin_vtable_platform;
# define DECLARE_PLATFORM_PIN(name) extern const pin_platform_t pin_##name
# define DEFINE_PLATFORM_PIN(name, value) \
const pin_platform_t pin_##name = { \
.base = {.vtable = &pin_vtable_platform}, \
.raw_pin = (value), \
}
# define PLATFORM_PIN_VALUE(name, value) (&pin_##name.base)
# define PIN_GET_OP(pin, op) ((pin)->vtable->op)
#else
/* Using only raw MCU pins */
typedef pin_platform_raw_t pin_t;
# define DECLARE_PLATFORM_PIN(name) struct pin_base_t
# define DEFINE_PLATFORM_PIN(name, value) struct pin_base_t
# define PLATFORM_PIN_VALUE(name, value) value
# define PIN_GET_OP(pin, op) platform_raw_##op
#endif
inline bool readPin(pin_t pin) {
return PIN_GET_OP(pin, read_pin)(pin);
}
inline void writePin(pin_t pin, bool value) {
PIN_GET_OP(pin, write_pin)(pin, value);
} Here A DECLARE_PLATFORM_PIN(B0);
#define B0 PLATFORM_PIN_VALUE(B0, PAL_LINE(GPIOB, 0U)) and would also need a corresponding DEFINE_PLATFORM_PIN(B0, PAL_LINE(GPIOB, 0U)) (not sure what to do with the duplication there, except maybe generating those files — a macro can't output a |
BTW im making some experiments over here(still minimal, it compiles but havent flashed anything yet). Sharing in case someone wants to provide some feedback, help with it, and trying to avoid other people duplicating work |
Made some progress, would love some feedback 🤓 https://github.com/elpekenin/qmk_firmware/tree/pin-playground |
This issue has been automatically marked as stale because it has not had activity in the last 90 days. It will be closed in the next 30 days unless it is tagged properly or other activity occurs. |
This issue has been automatically closed because it has not had activity in the last 30 days. If this issue is still valid, re-open the issue and let us know. |
Early proposal
Do not assume any PoC will be merged as-is, this is intended to explore future designs.
This issue is to track potential rework or redesign of the GPIO definitions within QMK.
Part of the complexity in dealing with a lot of alternative pin definitions is the fact that there's no cohesive way to integrate "mismatching" types of GPIOs in matrix definitions or peripheral connections.
Current definitions of
pin_t
are purely limited to MCU-hosted pins.Initial proposal is to redefine
pin_t
as a struct, with an enum to determine which underlying system services the request -- an example:readPin
as an example is purely that -- would need error checking and the like, and the vtables themselves would just assignNULL
to items they don't have the ability to do.The text was updated successfully, but these errors were encountered: