Sam Price created a merge request:
https://gitlab.rtems.org/rtems/rtos/rtems/-/merge_requests/1499
Project:Branches: TheSamPrice/rtems:gpio-api-ioctl to rtems/rtos/rtems:main
Author: Sam Price
RTEMS has GPIO support in two BSPs and no general interface. This proposes
one. It is the API and its test only -- drivers and documentation follow as
separate MRs once the shape is agreed, so this is opened as a Draft for
review rather than for merge.
## Said up front
**This was written with AI assistance, and it is the first API of that origin
the project will have to review.** I would rather that be stated than
discovered. I have tried to make it reviewable on evidence rather than on
trust, and what is *not* verified is listed below rather than left for a
reviewer to find. Review it as hard as any other contribution.
## Where it came from
The design brief is not mine. After surveying every GPIO implementation in
the tree, Chris Johns set out what the interface should be: the BSP
exclusively controls pin allocation and modes at the SoC level; the API
controls settings only for configured pins; a standard RTEMS driver with a
node in the IMFS and an ioctl handler; unsupported features return not
supported; continuous logical pin numbering that the BSP maps to hardware,
with pins possibly banked and sparse; physical and virtual pin
characteristics, so a BSP driver can implement virtual IO; and a call
returning a pin's configuration in terms of the published options.
This implements that brief, virtual IO included.
## The shape
A controller is a BSP driver registered as a device node, publishing
`pin_count` logical pins numbered 0..pin_count-1 with no holes. Banks and
sparse hardware are the driver's problem, not the caller's. Thirteen
directives, each one `ioctl()`:
```c
fd = open("/dev/gpio0", O_RDWR);
rtems_gpio_pin_by_name(fd, "LED0", &pin); /* name the pad, not the number
*/
memset(&config, 0, sizeof(config));
config.direction = RTEMS_GPIO_DIRECTION_OUTPUT;
config.flags = RTEMS_GPIO_FLAG_ACTIVE_LOW; /* no hardware inverter needed */
config.drive_strength = 12000; /* microamps; reads back 20000 */
rtems_gpio_pin_configure(fd, pin, &config);
rtems_gpio_pin_set(fd, pin, 1); /* logical 1; the pad goes low */
```
The generic layer does the locking, the pin range checks and the capability
checks, so no driver writes them. A handler left NULL answers `ENOTSUP`, so a
controller that can only read and write pins is a legal driver.
The commit message records the decisions and why the alternatives were not
taken. In short: polarity is applied in the generic layer so a controller
with no inversion register still supports active-low pins; bulk operations
are caller-sized `uint32_t` bitmaps with no maximum anywhere; `can_block` is
a property rather than something inferred; drive strength and debounce are in
microamps and microseconds rather than hardware enum indexes; and capability,
board reservation and current owner are three separate questions.
## This ground has been covered before
None of the choices are new.
- **Linux, December 2012.** Alexandre Courbot's RFC "gpiolib: introduce
descriptor-based GPIO interface" replaced integer pin IDs with opaque
descriptors, because the integer namespace was fixed at build time, needed
a statically allocated array, and required the `ARCH_NR_GPIOS` maximum.
- **RTEMS, 2014-2015.** This is not the project's first generic GPIO API.
Andre Marques's `bsps/include/bsp/gpio.h` and
`bsps/shared/dev/gpio/gpio-support.c` already answer "pins or ports?" with
both. The one thing it does that this does not is fix its size at compile
time: it `#error`s unless the BSP defines `BSP_GPIO_PIN_COUNT` and
`BSP_GPIO_PINS_PER_BANK`, and rejects `BSP_GPIO_PINS_PER_BANK > 32`. That
is the same build-time-maximum problem Courbot's RFC set out to remove, and
it is why `pin_count` here is a runtime property of a controller instance.
- **Zephyr, April 2026.** RFC: Fast GPIO API Extension -- one descriptor is
one port plus a pin mask, and cross-port atomicity is explicitly not
promised. Note Zephyr's `gpio_port_pins_t` is a `uint32_t`, so a port *is*
at most 32 pins and a wider controller becomes several port devices. That
is a fair answer, but it hands the bank sums back to the caller, which the
brief above rules out.
## What is verified
- `cpukit/dev/gpio/gpio.c` -- **306/306 coverable lines**, measured with
tcgcov (a QEMU TCG plugin) over an unmodified image on
`qemu-system-arm -M xilinx-zynq-a9`.
- `gpio01` passes on this branch, rebased onto `62598e8db1` and rebuilt. The
test controller has 40 pins on purpose -- at 32 or fewer the suite could
not tell a bulk operation that spans bitmap words from one that does not.
- No new compiler warnings in the GPIO sources.
## What is not verified
**No hardware.** The three hardware drivers that use this API are not in this
MR, but none of them has run on silicon, so the API has only ever been
exercised against a software test controller and a virtual driver. QEMU does
not model the Zynq PS GPIO registers at all.
## Open questions
1. **The existing API.** `bsps/include/bsp/gpio.h` and
`bsps/shared/dev/gpio/gpio-support.c` are used by beagle and raspberrypi.
There is no symbol collision -- that one is `rtems_gpio_bsp_*` and this is
`rtems_gpio_pin_*` / `rtems_gpio_drv_*` -- so they can coexist, but two
GPIO APIs is not a good end state. Deprecate, port the two BSPs, or leave
it?
2. **Level-triggered re-entrancy.** A handler that does not remove its cause
is re-entered. Linux masks the line and unmasks on ack. Worth settling
once in the API rather than per driver.
3. **Documentation form.** The `c-user` chapter is written by hand, following
`regulator` and `iodev`. If rtems-central spec items are wanted instead, I
would rather know now.
Happy to reshape any of it. The API is the part worth arguing about.
--
View it on GitLab:
https://gitlab.rtems.org/rtems/rtos/rtems/-/merge_requests/1499
You're receiving this email because of your account on gitlab.rtems.org.
Unsubscribe from this thread:
https://gitlab.rtems.org/-/namespace/49/sent_notifications/5-djhm02bl9m53tv84ilxjp87eo-1d/unsubscribe
| Manage all notifications: https://gitlab.rtems.org/-/profile/notifications |
Help: https://gitlab.rtems.org/help
_______________________________________________
bugs mailing list
[email protected]
http://lists.rtems.org/mailman/listinfo/bugs