2009-02-02 23 views
10

Sto provando a leggere/scrivere su un chip FM24CL64-GTR FRAM collegato tramite un bus I2C all'indirizzo 0b 1010 011.Lettura/scrittura dall'uso di I2C su Linux

Quando sto cercando di scrivere 3 byte (indirizzo dati 2 byte, + dati un byte), ottengo un messaggio del kernel ([12406.360000] i2c-adapter i2c-0: sendbytes: NAK bailout.), così come i rendimenti di scrittura = 3. Vedere codice qui sotto:!

#include <linux/i2c-dev.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <stdint.h> 

int file; 
char filename[20]; 
int addr = 0x53; // 0b1010011; /* The I2C address */ 
uint16_t dataAddr = 0x1234; 
uint8_t val = 0x5c; 
uint8_t buf[3]; 

sprintf(filename,"/dev/i2c-%d",0); 
if ((file = open(filename,O_RDWR)) < 0) 
    exit(1); 

if (ioctl(file,I2C_SLAVE,addr) < 0) 
    exit(2); 

buf[0] = dataAddr >> 8; 
buf[1] = dataAddr & 0xff; 
buf[2] = val; 

if (write(file, buf, 3) != 3) 
    exit(3); 

... 

Tuttavia quando scrivo 2 byte, quindi scrivere un altro byte, ottengo nessun errore del kernel, ma quando si cerca di leggere dal FRAM, ho sempre arrivare di nuovo 0. Ecco il codice per leggere dalla FRAM:

uint8_t val; 

if ((file = open(filename,O_RDWR)) < 0) 
    exit(1); 

if (ioctl(file,I2C_SLAVE,addr) < 0) 
    exit(2); 

if (write(file, &dataAddr, 2) != 2) { 
    exit(3); 

if (read(file, &val, 1) != 1) { 
    exit(3); 

Nessuna delle funzioni restituisce un valore di errore, e ho anche provato con:

#include <linux/i2c.h> 

struct i2c_rdwr_ioctl_data work_queue; 
struct i2c_msg msg[2]; 
uint8_t ret; 

work_queue.nmsgs = 2; 
work_queue.msgs = msg; 

work_queue.msgs[0].addr = addr; 
work_queue.msgs[0].len = 2; 
work_queue.msgs[0].flags = 0; 
work_queue.msgs[0].buf = &dataAddr; 

work_queue.msgs[1].addr = addr; 
work_queue.msgs[1].len = 1; 
work_queue.msgs[1].flags = I2C_M_RD; 
work_queue.msgs[1].buf = &ret; 

if (ioctl(file,I2C_RDWR,&work_queue) < 0) 
    exit(3); 

Che ha esito positivo, ma restituisce sempre 0. Questo indica un problema hardware o sto facendo qualcosa di sbagliato?

Esistono driver FRAM per FM24CL64-GTR su I2C su Linux e quale sarebbe l'API? Qualsiasi collegamento sarebbe utile.

+0

Si dovrebbe usare exit() (senza il carattere di sottolineatura principale), non _exit(). _exit() non chiude correttamente libc. –

+0

Grazie, questo è solo il codice di test di richiamo dell'hardware, ma ancora grazie per il vostro feedback. – TheSeeker

risposta

6

Il NAK è stato un grande suggerimento: il perno WriteProtect era esternamente tirato su, e doveva essere guidato a terra, dopo che una singola scrittura dell'indirizzo seguito da data-byte ha successo (primo segmento di codice).

Per la lettura è possibile scrivere prima l'indirizzo (utilizzando write()), quindi i dati sequenziali possono essere letti a partire da tale indirizzo.

5

Non ho esperienza con quel particolare dispositivo, ma nella nostra esperienza molti dispositivi I2C hanno "stranezze" che richiedono un work-around, tipicamente al di sopra del livello del driver.

Utilizziamo Linux (CELinux) e un driver di periferica I2C con Linux. Ma il nostro codice applicativo ha anche un modulo I2C non banale che contiene tutta l'intelligenza operativa per gestire tutti i vari dispositivi con cui abbiamo esperienza.

Inoltre, quando si tratta di questioni di I2C, spesso trovo che ho bisogno di ri-conoscere me stesso con la specifica fonte:

http://www.nxp.com/acrobat_download/literature/9398/39340011.pdf

così come l'utilizzo di un oscilloscopio decente.

Buona fortuna,

link qui sopra è morto, ecco alcuni altri collegamenti:

http://www.nxp.com/documents/user_manual/UM10204.pdf e naturalmente wikipedia: http://en.wikipedia.org/wiki/I%C2%B2C

+0

Stamattina comincerò con l'oscilloscopio e posterò le mie scoperte dopo averlo fatto funzionare, a meno che qualcun altro non abbia un driver I2C FRAM per Linux, ma non ne ho trovato nessuno. – TheSeeker

2

Si noti che il metodo che utilizza struct i2c_rdwr_ioctl_data e struct i2c_msg (ovvero l'ultima parte di codice fornita) è più efficiente degli altri, poiché con tale metodo si esegue la funzione di avvio ripetuto di I2c.

Ciò significa che si evita una transizione STA-WRITE-STO -> STA-READ-<data>...-STO, perché la comunicazione diventerà STA-WRITE-RS-READ-<data>...STO (RS = avvio ripetuto). Quindi, ti risparmia un transitorio ridondante STO-STA.

Non

che si differenzia molto nel tempo, ma se non è necessario, perché perdere su di esso ...

Solo il mio 2 ct.

Best rgds,

0

Hai avuto alcuni errori!

L'indirizzo del ic è Ax in esadecimale, x può essere qualsiasi cosa, ma i bit superiori 4 dovrebbe essere A=1010 !!!