Fishwaldo opened a new pull request, #19878:
URL: https://github.com/apache/nuttx/pull/19878
## Summary
Adds `/proc/gpio`, which lists every pin registered with the GPIO character
driver, with its type, value and counters in one place.
The pins are already visible in `/dev` and each can be read through its own
node with `GPIOC_READ` and `GPIOC_PINTYPE`. Surveying a whole board that way
means an open and two ioctls per pin, and the signal and interrupt counters
the
upper half keeps are not reachable through any ioctl at all. This is a
quality
of life view of the same kind as `/proc/pinctrl` and `/proc/reset`.
```
gpio6 type:INPUT_PU val:1 regs:0 ints:0 pad:SPI2_CS0_N
port:A.6
gpio28 type:INT_FALLING val:0 regs:0 ints:0 pad:GPIO28 port:A.28
gpio128 type:INPUT val:0 regs:0 ints:0
```
Every line carries the same `key:value` tokens in the same order, so the file
can be parsed as well as read. The common fields all come from state the
upper
half already holds — the pin type, the value through `go_read()`, and the
existing `register_count` and `int_count` — so nothing is added to any hot
path.
Lower halves may supply an optional `go_describe()` adding what only they can
say, such as which pad carries the line or how its trigger is armed:
```c
static int mychip_describe(FAR struct gpio_dev_s *dev, FAR char *extra,
size_t len)
{
FAR struct mychip_gpio_s *priv = (FAR struct mychip_gpio_s *)dev;
snprintf(extra, len, "pad:%u port:%c.%u", priv->pad,
'A' + priv->port, priv->pin);
return OK;
}
```
It writes into a caller supplied buffer and the upper half owns the line, so
a
lower half needs no procfs knowledge of its own. A lower half without it is
listed with the common tokens alone — the `gpio128` line above is exactly
that
case, a TCA6416 expander pin.
Two existing hazards in the paths this touches are fixed as well.
`procfs_register()` appends without checking for duplicates, so the entry is
now claimed once for the lifetime of the system rather than whenever the list
is empty — pins genuinely come and go at run time. And the pin type index is
bounded before use, since it comes from the lower half and the name table
cannot cover a type the enumeration does not define.
## Impact
New feature, off by default. `CONFIG_GPIO_PROCFS` depends on
`FS_PROCFS_REGISTER`; with it unset the list, the lock and the procfs entry
are
compiled out entirely.
`struct gpio_operations_s` gains one optional member at the end. Every
existing
lower half initialises that structure by name or by position without reaching
it, so none need updating. One small allocation per registered pin when the
option is on.
Worth knowing: the renderer calls `go_read()` for every pin on every
`read()`,
and procfs re-walks the list each time. For a memory mapped controller that
is
a register read; for an I2C expander it is a bus transaction per pin per
read.
Measured on the board below, with 32 of its 34 pins on TCA6416 expanders, one
`cat` of the file cost **144 I2C reads**. That is inherent to the procfs
pattern rather than new here, and caching would trade staleness for speed in
a
view whose whole purpose is to be current.
## Testing
Host: macOS 26.5.1 (arm64), `riscv-none-elf-gcc` 15.2.0, Sphinx 6.2.1.
**Build**: `sim:nsh` with `DEV_GPIO` alone, and again with `FS_PROCFS`,
`FS_PROCFS_REGISTER` and `GPIO_PROCFS` added, each from a clean tree: both
compile `drivers/ioexpander/gpio.c`. The EIC7700 EVB configuration builds
with
the option on and off. Documentation builds with no new warnings.
**Hardware**: ESWIN EIC7700 EVB (EIC7700X, 4 x RV64GC), 34 pins registered:
two
from the SoC's own GPIO lower half, which implements `go_describe`, and 32
from
two TCA6416 I2C expanders, whose lower half does not.
```
nsh> cat /proc/gpio
gpio6 type:INPUT_PU val:1 regs:0 ints:0 pad:SPI2_CS0_N
port:A.6
gpio28 type:INT_FALLING val:0 regs:0 ints:0 pad:GPIO28 port:A.28
gpio128 type:INPUT val:0 regs:0 ints:0
gpio129 type:INPUT val:1 regs:0 ints:0
gpio130 type:INPUT val:0 regs:0 ints:0
...
gpio158 type:INPUT val:0 regs:0 ints:0
gpio159 type:INPUT val:0 regs:0 ints:0
```
Checked on that output:
* all 34 registered pins listed, each exactly once — no duplicate or dropped
line at any read boundary
* every line carries the same four common tokens; an `awk` pass counting
`type:`, `val:`, `regs:` and `ints:` finds no line that deviates
* both cases covered on real hardware: `gpio6` and `gpio28` carry the SoC
lower
half's `pad:` and `port:` fields, `gpio28` being an interrupt pin, while
the
expander pins from `gpio128` up show the common tokens alone
* `pad:SPI2_CS0_N` on `gpio6` is correct: that pad is muxed to function 2,
GPIO, which `/proc/pinctrl` reports independently
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]