I2C

1. I2C im buildroot aktivieren:

Damit der I²C-Bus auf dem NGW100 verwendet werde kann, muss man diesen erst im Kernel des buildroots aktivieren.

cd
make linux26-menuconfig

Device Drivers -> I2C support -> I2C device Interface
make

Anschließend kann das neu kompilierte rootfs auf eine SD-Karte kopiert oder direkt auf das Board geflashed werden. Es empfiehlt sich aber das Linux erst auf eine SD-Karte zu kopieren, um zu sehen ob es einwandfrei funktioniert. Nachdem booten sollte nun im /dev Ordner das Device i2c-0 zu sehen sein.

2. I2C Scanner cross-kompilieren:

Für den I²C Scanner werden die Sources vom lm-sensor Projekt verwendet. Bevor man kompilieren kann muss man den cross-compilier erstmal allgemein im System bekannt machen. Dieser ist im builroot unter /home/de4d9b/buildroot-avr32-v2.3.0/build_avr32/staging_dir/bin/avr32-linux-gcc zu finden.

Anlegen eines symbolischen Links für das Cross-Compilieren des I2C Scanners.
cd /bin
sudo ln -s /home/de4d9b/buildroot-avr32-v2.3.0/build_avr32/staging_dir/bin/avr32-linux-gcc avr32-linux-gcc

Nun können die Sources des lm-sensor Projekts herrunter geladen, entpackt und cross-compiliert werden.
wget http://dl.lm-sensors.org/i2c-tools/releases/i2c-tools-3.0.2.tar.bz2
tar -xvjf i2c-tools-3.0.2.tar.bz2
cd i2c-tools-3.0.2
ARCH=avr32 CROSS_COMPILE=avr32-linux make CC=avr32-linux-gcc prefix=/tmp/i2ctools
ARCH=avr32 CROSS_COMPILE=avr32-linux make CC=avr32-linux-gcc prefix=/tmp/i2ctools install

Die cross-compilierten Dateien wurden im Verzeichniss /tmp/i2ctools abgelegt. Diese müssen jetzt nur noch auf das NGW100 per FTP/SMB kopieren werden (im binär Modus).
Sind die files erstmal auf dem Board, müssen diese erst noch ausführbar gemacht werden.
cd /home/root/i2tools/sbin
chmod a+x *

Nun kann auf dem I²C Bus nach angeschlossenen Geräten gesucht werden. 🙂
Die „0“ nach dem i2cdetect bedeutet, dass auf dem Device i2c-0 gesucht wird.
./i2cdetect 0

WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] Y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — — 0b — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — — —
40: — — — — — — — — — — — — — — — —
50: — — — — — — — — — — — — — — — —
60: — — — — — — — — — — — — — — — —
70: — — — — — — — —

An der Position 0x0b befindet sich ein weiter Mikrocontroller der über I²C an den AP7000 angeschlossen ist. Es ist bekannt, dass sich die firmware des ATTiny24 sehr buggy verhält (siehe Quellen). Diese Erfahrung kann ich nur bestätigen, bei dem Versuch die Temperatur auszulesen. Dies macht sich da durch bemerkbar, wenn man den I²C scanner auf den Chip anwendet, verschwinden die Temperaturwerte und können logischerweise nicht mehr ausgelesen werden. Erst ein Neustart setzt diesen Fehler zurück.

Die Werte eines Addr-Blocks lassen sich mit dem Programm „i2cdump“ anzeigen. Die „0“ steht, wie beim „2cdetect“, für das Device /dev/i2c-0 und 0x0b ist die Adresse vom dem Gerät auf dem I²C-Bus.
./i2cdump 0 0x0b

/home/root/i2ctools/sbin # ./i2cdump 0 0x0b
No size specified (using byte-data access)
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0, address 0xb, mode byte
Continue? [Y/n] Y
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 01 02 29 01 02 2a 01 02 2a 01 00 00 00 00 00 00 ??)??*??*?……
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 2b …………..?+
90: 01 00 00 00 00 00 00 00 00 00 08 61 74 6d 65 6c ?………?atmel
a0: 2e 6e 6f 06 4e 47 57 31 30 30 01 12 0f fd fe ff .no?NGW100?????.
b0: 8f 9f 8d 8d 00 00 00 00 00 00 00 00 00 00 00 00 ????…………
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
d0: 00 02 52 03 02 48 03 00 00 00 00 00 00 00 00 00 .?R??H?………
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….

Beispiel: C-Code zum Auslesen der Temperatur aus dem ATTiny24:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define LEN 4

int main()
{
   int fd, i;
   struct i2c_rdwr_ioctl_data msgset;
   struct i2c_msg msg[2];

   unsigned char write[] = {0x8D}; 	//Indexaddr ab der gelesen werden soll
   unsigned char read[LEN];			//Array in dem die ausgelesenen Daten gespeichert werden
   long addr = 0x0b;
   
   //MSG-Block schreiben der addr, ab der lesen werden soll
   msg[0].addr = addr;
   msg[0].flags = 0;
   msg[0].len = 1;
   msg[0].buf = &write[0];
   
   //MSG-Block zum auslesen der Werte
   msg[1].addr = addr;
   msg[1].flags = I2C_M_RD;
   msg[1].len = LEN;
   msg[1].buf = read;
   
   msgset.msgs = msg;
   msgset.nmsgs = 2;

   if((fd = open("/dev/i2c-0",O_RDWR)) < 0) {
      perror("could not open device");
      return fd;
   } else {
      printf("opened device i2c-0n");
   }

   if(ioctl(fd,I2C_RDWR,&msgset) < 0) {
      perror("ioctl");
      return -1;
   }
   
   //Ausgeben von vier Felder, da der Temperaturwert im Speicher des ATTiny24, aufgrund der buggy firmware, immer hin und her springt.
   printf("DEC | HEXn");
   printf("----------------n");
   for (i = 0; i < LEN; i++) printf("%03d | 0x%08xn", read[i],read[i]);
 
   return 0;
} 

Quellen:
http://www.lm-sensors.org/
http://www.avrfreaks.net/wiki/index.php/Documentation:NGW/NGW100_Board_controller
http://www.hs-augsburg.de/~phuewe/E-Linux/Studienarbeit.html
http://www.atmel.com/dyn/resources/prod_documents/doc32083.pdf
http://www.avrfreaks.net/wiki/index.php/Documentation:NGW/NGW100_Board_controller
http://de.wikipedia.org/wiki/I%C2%B2C