sobota 8. listopadu 2014

Zprovoznění SPI, I2C a 1-wire na OpenWRT

Jak zprovoznit SPI na zařízení s OpenWRT, když nemá volný SPI port? Stačí jen najít několik volných GPIO pinů, nainstalovat pár balíčků a už to funguje.





SPI

Jako první je nutné najít vhodné a volné GPIO piny, pro pokusy jsem použil malou hračku TP-LINK WR703N. Je nutné si dát pozor, které piny procesor používá pro volbu režimů startu (viz. OpenWRT wiki). Já jsem využil piny  0 - CLK, 7 - MOSI a 29 - MISO.

dále je nutné nainstalovat příslušné balíčky:
kmod-spi-bitbang
kmod-spi-dev
kmod-spi-gpio
kmod-spi-gpio-custom

po restartu zařízení by měl být načten jen modul spi_gpio
root@OpenWrt:/# lsmod | grep spi
spi_gpio                4112  0

dalšímu modulu (spi-gpio-custom) je nutné předat čísla GPIO pinů, které se mají používat, plus další parametry
insmod spi-gpio-custom bus0=1,0,7,29,0,1000
parametry se zadávají v následujícím formátu:
bus0=<id>,<sck>,<mosi>,<miso>,<modeX>,<maxfreqX>,<csX>[<modeX>,<maxfreqX>,<csX>]... [bus1=<id>,<sck>,<mosi>,<miso>,<modeX>,<maxfreqX>,<csX>] ...

V našem případě máme dost pinů pouze na jedno SPI, definujeme tedy parametry jen pro bus0.
<id>
<sck> číslo GPIO pinu, který bude přiřazen jako hodiny SPI (SCK)
<mosi> číslo GPIO pinu, který bude přiřazen jako výstup dat SPI (MOSI)
<miso> číslo GPIO pinu, který bude přiřazen jako vstup dat SPI (MISO)
<modeX>
<maxfreqX> hodnota maximální frekvence, kterou bude SPI se slavem komunikovat (v Hz)
<csX> číslo GPIO pinu, který bude přiřazen jako Chip Select (CS)

Volitelně může několikrát následovat <modeX>,<maxfreqX>,<csX> pro další SPI slave zařízení (na stejné SPI sběrnici).

Kompletní příkaz pro zavedení modulu vypadá takto:
insmod spi-gpio-custom bus0=1,0,7,29,0,1000,20,0,2000,21,0,3000,22

Díky předchozímu se nám do /dev přidají následující zařízení. Druhou číslicí v názvu zařízení se adresují jednotlivá zařízení na jedné sběrnici (pro každý je logicky nutné zadat CS).
/dev/spidev1.0
/dev/spidev1.1
/dev/spidev1.2

spidev1.0 je ovládán pomocí CS na GPIO pinu 20, maximální frekvence hodin je 1 kHz
spidev1.0 je ovládán pomocí CS na GPIO pinu 21, maximální frekvence hodin je 2 kHz
spidev1.0 je ovládán pomocí CS na GPIO pinu 22, maximální frekvence hodin je 3 kHz



I2C

Obdobný postup je i pro I2C sběrnici, ta ke své funkci potřebuje jen dva datové piny (zařízení nejsou adresována CS ale adresou na sběrnici).

Pro podporu I2C je nutné nainstalovat balíčky:
kmod-i2c-gpio-custom kmod-i2c-core

Parametry modulů jsou jen dva, číslo GPIO pinu datového vodiče SDA a SCL. U WR703N jsou potřeba pull-up rezistory na oba datové vodiče.
insmod i2c-gpio-custom bus0=0,0,29
insmod i2c-dev

Výpis syslogu:
root@OpenWrt:/# insmod i2c-gpio-custom bus0=0,0,29
[  846.320000] Custom GPIO-based I2C driver version 0.1.1
[  846.330000] i2c-gpio i2c-gpio.0: using pins 0 (SDA) and 29 (SCL)

Pro vlastní zápis a čtení je možné použít balíček i2c-tools.
Nejprve detekujeme, zda máme na sběrnici něco připojeno:
root@OpenWrt:/# i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Ano máme, konkrétně na adrese 0x50, jdeme tedy zapisovat a následně číst.
root@OpenWrt:/# i2cget -y 0 0x50 0 b
0x00
root@OpenWrt:/# i2cget -y 0 0x50 1 b
0x01
root@OpenWrt:/# i2cget -y 0 0x50 2 b
0x02
root@OpenWrt:/# i2cget -y 0 0x50 3 b
0x03
root@OpenWrt:/# i2cget -y 0 0x50 4 b
0x11
root@OpenWrt:/# i2cset -y 0 0x50 4 0x04 b
root@OpenWrt:/# i2cget -y 0 0x50 4 b
0x04

1-Wire

A nyní k 1-Wire

potřebné balíčky jsou tyto:
kmod-w1-master-gpio kmod-w1-gpio-custom kmod-w1-slave-therm

Po restartu máme zavedeny všechny potřebné moduly až na w1-gpio-custom.
root@OpenWrt:/# lsmod | grep w1
w1_gpio                 1344  0
w1_therm                1840  0
wire                   14721  2 w1_therm

Obvyklým postupem předáme parametry, druhý definuje číslo GPIO portu, pin také potřebuje 4,4 kOhm pull-up. Třetí, zda je pin open drain (jinak ale vůbec netuším k čemu tato volba slouží).
root@OpenWrt:/# insmod w1-gpio-custom bus0=0,7,0
[  890.230000] Custom GPIO-based W1 driver version 0.1.1

Po zavedení modulu už máme načtená čidla na sběrnici, v našem případě jedno čidlo DS1822 s adresou 22-0000001abd7d a 1-wire spínač 28-000000eefb97.
root@OpenWrt:/# ls /sys/devices/w1_bus_master1/
22-0000001abd7d      28-000000eefb97      w1_master_attempts         w1_master_remove
driver                     w1_master_max_slave_count  w1_master_search
subsystem                  w1_master_name             w1_master_slave_count
uevent                     w1_master_pointer          w1_master_slaves
w1_master_add              w1_master_pullup           w1_master_timeout

Nyní stačí načíst hodnotu, v tomto případě se vše zdařilo (CRC souhlasí) a teplota je 26,187 ºC.
root@OpenWrt:/# cat /sys/devices/w1_bus_master1/22-0000001abd7d/w1_slave
a3 01 4b 46 7f ff 0d 10 ce : crc=ce YES
a3 01 4b 46 7f ff 0d 10 ce t=26187


GPIO


Další možností je piny používat jako GPIO piny, pomocí příkazu ho nastavíme jako GPIO.
echo "29" > /sys/class/gpio/export

Dále je nutné nastavit směr, out či in.
echo "out" > /sys/class/gpio/gpio29/direction

A nyní již zapisujeme hodnotu (0 nebo 1).
echo "1" > /sys/class/gpio/gpio29/value

Hodnotu value je možné i číst, v režimu vstupu čteme skutečný stav pinu.
Víc dokumentace k modulu GPIO je na https://www.kernel.org/doc/Documentation/gpio/sysfs.txt

Ještě jedno informace na závěr, pro uvolnění USARTU je vhodné deaktivovat výstup hlášek jádra pomocí příkazu: dmesg -n 1

Zdroje:
http://randomcoderdude.wordpress.com/2013/08/15/spi-over-gpio-in-openwrt/
http://wiki.openwrt.org/toh/tp-link/tl-wr703n
https://dev.openwrt.org/browser/trunk/package/kernel/spi-gpio-custom/src/spi-gpio-custom.c
http://cs.wikipedia.org/wiki/Serial_Peripheral_Interface - obrázek
https://dev.openwrt.org/browser/trunk/package/w1-gpio-custom/src/w1-gpio-custom.c?rev=10982
http://mujweb.cz/mrazik/router/index.html
http://cs.wikipedia.org/wiki/I%C2%B2C - obrázek
http://wiki.openwrt.org/doc/hardware/port.gpio

Žádné komentáře:

Okomentovat