[riot-notifications] [RIOT-OS/RIOT] drivers: add PCF857X I2C I/O expander driver (#10430)

Gunar Schorcht notifications at github.com
Mon Nov 19 16:33:32 CET 2018

### Contribution description

This PR adds a driver module for the widespread PCF857X serial I/O expander modules which extend the number of GPIOs over the I2C bus. The following expander modules are supported by the driver:

- PCF8574 and PCF857A 8-bit I2C I/O expander with 1 port with 8 input/output pins
- PCF8575 16-bit I2C I/O expander with 2 ports with 8 input/output pins each

The driver defines the driver variants by a pseudomodule for each of supported expander module:

- `pcf8574 ` for PCF8574
- `pcf8574a` for PCF8574A
- `pcf8575 ` for PCF8575

The driver interface is kept as compatible as possible with the peripheral GPIO interface. The only difference is that the functions have the prefix `pcf857x_` and require an additional parameter, the pointer to the expansion device of type `pcf857x_t`

Since PCF857X expander pins are only quasi-bidirectional without having a separate direction control signal, they only support active LOW driven outputs and inputs that are pulled up to HIGH. HIGH outputs are nothing else than pulled-up inputs. The driver maps this behavior to the `GPIO_IN_PU` and `GPIO_OD` and additionally to the `GPIO_IN`, `GPIO_OUT` and `GPIO_OD_PU` modes.

Optionally, the driver can use the low-active open-drain INT signal of PCF857x expander modules

- to provide external interrupt capabilities for all expander pins which are compatible to module `periph_gpio_irq`
- to keep internal up-to-state of expander inputs to avoid reading expander input pins via I2C each time a single input value read with `pcf857x_gpio_read`, see the benchmarks.

The driver support direct GPIO mapping to SAUL with is compatible to the peripheral GPIO SAUL interface. Thus PCF857X I/O expander pins can be used with SAUL in the same was as peripheral GPIOS.

## Benchmarks

The performance of the driver strongly depends on using interrupt capabilities or not:

- PCF857X driver run-time performance benchmark without interrupt capabilities @ 400 kHz I2C bus speed:
                 nop loop:       639us  ---   0.063us per call  ---   15649452 calls per sec
                 gpio_set:    842995us  ---  84.299us per call  ---      11862 calls per sec
               gpio_clear:    840009us  ---  84.000us per call  ---      11904 calls per sec
              gpio_toggle:    842000us  ---  84.200us per call  ---      11876 calls per sec
                gpio_read:    877514us  ---  87.751us per call  ---      11395 calls per sec
               gpio_write:    841430us  ---  84.143us per call  ---      11884 calls per sec
- PCF857X driver run-time performance benchmark with interrupt capabilities (module `periph_gpio_irq`)  @ 400 kHz I2C bus speed:
                 nop loop:       626us  ---   0.062us per call  ---   15974440 calls per sec
                 gpio_set:   1751632us  ---  175.163us per call  ---       5708 calls per sec
               gpio_clear:   1755016us  ---  175.501us per call  ---       5697 calls per sec
              gpio_toggle:   1755082us  ---  175.508us per call  ---       5697 calls per sec
                gpio_read:      4751us  ---   0.475us per call  ---    2104820 calls per sec
               gpio_write:   1759999us  ---  175.999us per call  ---       5681 calls per sec
Reference board was an `esp8266-esp-12x` in IC2 fast mode.

### Testing procedure

The test application `tests/driver_pcf857x` can be used to test each PCF857X expander I/O pin with shell commands. It bases on the test application for GPIO peripheral drivers.

To use the test application, just compile it with one of the pseudomodules
`pcf8574`, `pcf8574a` or `pcf8575, e.g.

     USEMODULE=pcf8575 make flash -C tests/driver_pcf857x BOARD=...

Add module `periph_gpio_irq` and define the MCU interrupt pin by parameter  PCF857X_PARAM_INT_PIN` to use the PCF857X interrupt signal, e.g.,

     CFLAGS="-DPCF857X_PARAM_INT_PIN=\(GPIO\(0,6\)\)" \
     USEMODULE="pcf8575 periph_gpio_irq" make 

### Issues/PRs references

Beside the PCF857X expanders, there are many more expansion modules. An attempt has already been made to add a driver for the MCP23017 16-bit I2C I/O expander with PR #7652. With the 16-bit MCP23S17 SPI I/O expander there is a GPIO expander that allows faster access with up to 10 MHz.

Perhaps there should be a general management architecture for modules that provide access to GPIOs, for example a registry for GPIO providers with a common access interface. Every GPIO provider would need to register with its meta information. If the MCU were also considered as a GPIO provider, all GPIOs could be used over the same interface, regardless of whether it is provided by the MCU or an GPIO expander.
You can view, comment on, or merge this pull request online at:


-- Commit Summary --

  * doc: add I/O expanders to drivers_periph group
  * drivers: add PCF857X I/O expander driver
  * sys/auto_init: add PCF857X SAUL initialization
  * makefiles: add PCF957X driver pseudomodules
  * tests: add PCF957X driver test application

-- File Changes --

    M drivers/Makefile.dep (24)
    M drivers/Makefile.include (4)
    A drivers/include/pcf857x.h (418)
    M drivers/include/periph/doc.txt (10)
    A drivers/pcf857x/Makefile (1)
    A drivers/pcf857x/include/pcf857x_params.h (109)
    A drivers/pcf857x/pcf857x.c (416)
    A drivers/pcf857x/pcf857x_saul.c (57)
    M makefiles/pseudomodules.inc.mk (6)
    M sys/auto_init/auto_init.c (4)
    A sys/auto_init/saul/auto_init_pcf857x.c (107)
    A tests/driver_pcf857x/Makefile (11)
    A tests/driver_pcf857x/README.md (25)
    A tests/driver_pcf857x/main.c (324)

-- Patch Links --


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.riot-os.org/pipermail/notifications/attachments/20181119/85cd802b/attachment-0001.html>

More information about the notifications mailing list