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]

Reply via email to