tldr: The following procedure should work for any SPI/I2C/... GPIO Expander with an existend linux kernel/gpiod driver that uses a Device Tree configuration.
I'm currently retrofitting a small CNC mill with LinuxCNC on the Raspberry Pi 4.
To get more GPIOs I wanted to use the MCP23017 I2C Port Expander (
www.microchip.com/en-us/product/mcp23017).
For testing I use this board:
www.adafruit.com/product/4132
I don't expect the GPIOs to be realtime, but I want to use them in a HAL file.
While resaerching I found this thread (but there is no real solution, only some hints):
forum.linuxcnc.org/24-hal-components/464...dapt-the-extended-io
I also took a closer look at the hal_gpio driver.
As documented the hal_gpio driver relies on the gpiod package and the names given by gpioinfo. I was lucky because there is a linux kernel driver for the MCP23017:
github.com/torvalds/linux/blob/master/Do...pinctrl-mcp23s08.txt
github.com/torvalds/linux/blob/master/dr...nctrl-mcp23s08_i2c.c
So I added the Device Tree (/boot/broadcom/overlays/mcp23017.dtbo) that was already provided in the firmware folder on the RPi to the config.txt as an overlay and did a reboot.
cnc@raspberrypi:~$ sudo nano /boot/broadcom/config.txt
- add follwing at the end of the file:
- also enable I2C if not alredy enabled:
After running gpioinfo the GPIO extender with the pins was shown, but they didn't have a name ('unnamed').
cnc@raspberrypi:~$ gpioinfo
gpiochip0 - 58 lines:
line 0: "ID_SDA" unused input active-high
...
line 57: "RGMII_TXD3" unused input active-high
gpiochip1 - 8 lines:
line 0: "BT_ON" unused output active-high
...
line 7: "SD_OC_N" unused input active-high
gpiochip2 - 16 lines:
line 0: unnamed unused input active-high
line 1: unnamed unused input active-high
line 2: unnamed unused input active-high
line 3: unnamed unused input active-high
line 4: unnamed unused input active-high
line 5: unnamed unused input active-high
line 6: unnamed unused input active-high
line 7: unnamed unused input active-high
line 8: unnamed unused input active-high
line 9: unnamed unused input active-high
line 10: unnamed unused input active-high
line 11: unnamed unused input active-high
line 12: unnamed unused input active-high
line 13: unnamed unused input active-high
line 14: unnamed unused input active-high
line 15: unnamed unused input active-high
After some resaech and comparison to the Raspberry Pi GPIO device tree I figured out how to set the GPIO names in the device tree:
- Decompile the .dtbo in the .dts format with dtc:
cnc@raspberrypi:~$ dtc /boot/broadcom/overlays/mcp23017.dtbo -o mcp23017.dts
- Edit the .dts file:
cnc@raspberrypi:~$ nano mcp23017.dts
- change the I2C address if necessary (the adafruit board has the address 0x20):
mcp23017_pins@20
mcp@20
reg = <0x20>;
- add the GPIO names in the mcp@20 section (ypu can choose your own names):
gpio-line-names = "MCP20_A0","MCP20_A1","MCP20_A2","MCP20_A3","MCP20_A4","MCP20_A5","MCP20_A6","MCP20_A7","MCP20_B0","MCP20_B1","MCP20_B2","MCP20_B3","MCP20_B4","MCP20_B5","MCP20_B6","MCP20_B7";
- Compile the file back and save it to the firmware folder (keep a backup of the original .dtbo file)
cnc@raspberrypi:~$ dtc mcp23017.dts -o mcp23017.dtbo -O dtb
cnc@raspberrypi:~$ sudo mv /boot/broadcom/overlays/mcp23017.dtbo /boot/broadcom/overlays/mcp23017.dtbo.old
cnc@raspberrypi:~$ sudo mv mcp23017.dtbo /boot/broadcom/overlays/mcp23017.dtbo
- reboot
After applying the patched Device Tree I got names in the gpioionfo output:
cnc@raspberrypi:~$ gpioinfo
gpiochip0 - 58 lines:
line 0: "ID_SDA" unused input active-high
...
line 57: "RGMII_TXD3" unused input active-high
gpiochip1 - 8 lines:
line 0: "BT_ON" unused output active-high
...
line 7: "SD_OC_N" unused input active-high
gpiochip2 - 16 lines:
line 0: "MCP20_A0" unused input active-high
line 1: "MCP20_A1" unused input active-high
line 2: "MCP20_A2" unused input active-high
line 3: "MCP20_A3" unused input active-high
line 4: "MCP20_A4" unused input active-high
line 5: "MCP20_A5" unused input active-high
line 6: "MCP20_A6" unused input active-high
line 7: "MCP20_A7" unused input active-high
line 8: "MCP20_B0" unused input active-high
line 9: "MCP20_B1" unused input active-high
line 10: "MCP20_B2" unused input active-high
line 11: "MCP20_B3" unused input active-high
line 12: "MCP20_B4" unused input active-high
line 13: "MCP20_B5" unused input active-high
line 14: "MCP20_B6" unused input active-high
line 15: "MCP20_B7" unused input active-high
Then it is possible to use the GPIOs with the hal_gpio driver:
cnc@raspberrypi:~$ halrun
halcmd: loadrt hal_gpio inputs=MCP20_A0,MCP20_A1 outputs=MCP20_B0,MCP20_B1
halcmd: show pin
Component Pins:
Owner Type Dir Value Name
4 bit OUT FALSE hal_gpio.MCP20_A0-in
4 bit OUT FALSE hal_gpio.MCP20_A0-in-not
4 bit OUT FALSE hal_gpio.MCP20_A1-in
4 bit OUT FALSE hal_gpio.MCP20_A1-in-not
4 bit IN FALSE hal_gpio.MCP20_B0-out
4 bit IN FALSE hal_gpio.MCP20_B1-out
4 s32 OUT 0 hal_gpio.read.time
4 s32 OUT 0 hal_gpio.write.time