2009-02-02 9 views
10

Estoy tratando de leer/escribir en un chip FM24CL64-GTR FRAM que está conectado a través de un bus I2C en la dirección 0b 1010 011.Lectura/escritura del uso de I2C en Linux

Cuando estoy tratando de escribir 3 bytes de datos (dirección + 2 bytes, los datos de un byte), aparece un mensaje de kernel ([12406.360000] i2c-adapter i2c-0: sendbytes: NAK bailout.), así como los rendimientos de escritura = por debajo de 3. Véase Código:

#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); 

... 

sin embargo, cuando escribo 2 bytes, a continuación, escribir otro byte, me sale ningún error kernel, pero cuando se trata de leer desde el FRAM, siempre vuelva 0. Este es el código para leer desde el 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); 

Ninguna de las funciones devuelve un valor de error, y también lo he intentado 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); 

Lo cual también tiene éxito, pero siempre devuelve 0. ¿Esto indica un problema de hardware, o estoy haciendo algo mal?

¿Hay controladores FRAM para FM24CL64-GTR sobre I2C en Linux, y cuál sería la API? Cualquier enlace sería útil.

+0

Debería estar utilizando exit() (sin el guión bajo inicial), no _exit(). _exit() no cierra adecuadamente libc. –

+0

Gracias, esto es solo el código de prueba de puesta a cero del hardware, pero aún así, gracias por sus comentarios. – TheSeeker

Respuesta

6

El NAK fue una gran pista: el pasador WriteProtect era extraído externamente, y tuvo que ser conducido a tierra, después de eso, una sola escritura de la dirección seguida por bytes de datos es exitosa (primer segmento de código).

Para leer, la dirección se puede escribir primero (usando escritura()), y luego se pueden leer datos secuenciales a partir de esa dirección.

5

No tengo experiencia con ese dispositivo en particular, pero en nuestra experiencia muchos dispositivos I2C tienen "caprichos" que requieren una solución alternativa, típicamente por encima del nivel del controlador.

Usamos linux (CELinux) y un controlador de dispositivo I2C con Linux también. Pero nuestro código de aplicación también tiene un módulo I2C no trivial que contiene toda la inteligencia de trabajo para manejar todos los diversos dispositivos con los que tenemos experiencia.

Además, cuando se trata de cuestiones I2C, a menudo encuentran que necesito para mí volver a familiarizarse con la especificación de fuente:

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

, así como el uso de un osciloscopio decente.

Buena suerte,

Por encima de enlace está muerto, he aquí algunos otros enlaces:

http://www.nxp.com/documents/user_manual/UM10204.pdf y de Wikipedia curso: http://en.wikipedia.org/wiki/I%C2%B2C

+0

Comenzaré con el osciloscopio esta mañana y publicaré mis hallazgos después de que lo haya hecho funcionar, a menos que alguien más tenga un controlador FRAM I2C para Linux, pero no pude encontrar ninguno. – TheSeeker

2

Tenga en cuenta que el método que usa struct i2c_rdwr_ioctl_data y struct i2c_msg (es decir, la última parte de código que ha dado) es más eficiente que los otros, ya que con ese método ejecuta la característica de inicio repetido de I2c.

Esto significa que evita una transición STA-WRITE-STO -> STA-READ-<data>...-STO, porque su comunicación se convertirá en STA-WRITE-RS-READ-<data>...STO (RS = inicio repetido). Por lo tanto, le ahorra un transitorio STO-STA redundante.

No

que difiere mucho en el tiempo, pero si no es necesario, ¿por qué perder en él ...

Sólo mi 2 qt.

mejores rgds,

0

Usted tenían algunos errores!

La dirección de ic es Ax en hexadecimal, x puede ser cualquier cosa, pero los 4 bits superiores debe ser A=1010 !!!

Cuestiones relacionadas