Lo prometido es deuda; éste es el código que utilizo como maestro con el debian (lleva un procesador arm9-> registros utilizados desde la página 145 de éste link, donde pone TWI: https://www.embeddedarm.com/documentation/third-party/ECONA-CNS21XX-HRM-v.1.8.pdf)
void *map_phys(off_t addr,int *fd) {
off_t page;
unsigned char *start;
if (*fd == -1) //si fd no es -1, ya estaba abierto
*fd = open("/dev/mem", O_RDWR|O_SYNC); //apertura en modo escritura y lectura syncrono para que sea efectivo cualquier cambio
if (*fd == -1) {
perror("open(/dev/mem):"); //no se abrio correctamente
return 0;
}
page = addr & 0xfffff000; //las paginas son multiplos de 0x1000 primera pagina= 0x0000; segunda= 0x1000; tercera=0x3000...
//ubica dispositivo en memoria de tamaño una pagina, lectura y escritura, compartido.
start = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, *fd, page);
//start empieza en direccion inicial de la pagina
if (start == MAP_FAILED) {
perror("mmap:"); //no ubico correctamente
return 0;
}
start = start + (addr & 0xfff); //star ahora en direccion de la pagina + offset = direccion del registro proyectado
return start;
}
inline void cavium_enable_TWI() {
setbit(®[0],31); //activa TWI
clrbit(®[0],24); //desactiva TWI data swap: TWI_WR_DAT = PWDATA[31:0] y PRDATA = TWI_RD_DAT[31:0]
}
inline void cavium_disable_TWI(){
clrbit(®[0],31); //desactiva TWI
}
void init_TWI() {
reg = map_phys(0x71000020,&fd); //reg[registrotwi/sizeof(unsigned)] ya puede ser utilizado
cavium_enable_TWI();
TWI_clock_frequency(42724);//280448 default
reg[0x14/sizeof(unsigned)] = 3; //TWI_ACTDONE_FG y TWI_BUSERR_FG puestos a '0'
}
/* void write_TWI_data(unsigned adrs,int len,unsigned data): */
/* Escribe valor de data de len bytes en esclavo adrs mediante I2C */
void write_TWI_data(unsigned adrs,int len,unsigned data) {
int limit=10000; //limitamos tiempo espera transmision
clrbit(®[0],5); //
setbit(®[0],4); //TWI_TRANSFER_CMD=1='01'=Only-Write Operation
reg[0] = (reg[0] & 0xFFFFFFF3) | (((len - 1) & 3)<<2); //TWI_WRDAT_LEN=len
reg[0xC/sizeof(unsigned)] = data; //TWI_WR_DATA=data
reg[0x8/sizeof(unsigned)] = adrs; //TWI_SLAVE_ADDR=adrs
setbit(®[0],6); //comienza escritura TWI_RUN_STAR='1'
printf("Se enviara:%x\n", reg[0xC/sizeof(unsigned)]);
while(!getbit(®[0x14/sizeof(unsigned)],1) && --limit>0); // espera mientras dure la transferencia fin si TWI_ACTDONE_FG='1'
if (limit <=0) { // o si timeout
printf("timeout\n");
}
if (getbit(®[0x14/sizeof(unsigned)],0)) { //si TWI_BUSERR_FG='1' ha ocurrido un error
print_TWI_error();
exit(1);
}
}
/* void read_TWI_data(unsigned adrs,int len): */
/* Lee len bytes de adrs mediante I2C y los devuelve. */
unsigned read_TWI_data(unsigned adrs,int len) {
int limit=10000; //limitamos tiempo espera transmision
clrbit(®[0],5); //
clrbit(®[0],4); //TWI_TRANSFER_CMD=0='00'=Only-Read Operation
reg[0] = (reg[0] & 0xFFFFFFFC) | ((len - 1) & 3); //TWI_RDDAT_LEN=len
setbit(®[0],6); //comienza lectura TWI_RUN_STAR='1'
while(!getbit(®[0x14/sizeof(unsigned)],1) && --limit>0); // espera mientras dure la transferencia fin si TWI_ACTDONE_FG='1'
if (limit <=0) { // o si timeout
printf("timeout\n");
}
if (getbit(®[0x14/sizeof(unsigned)],0)) { //si TWI_BUSERR_FG='1' ha ocurrido un error
print_TWI_error();
exit(1);
}
return reg[0x10/sizeof(unsigned)]; //devuelve TWI_RD_DATA
}
int main(int argc,char *argv[]) {
unsigned lectura;
init_TWI();
write_TWI_data(2,1,9); //debe mandar 0x09 a la direccion esclavo 0x1
//usleep(100000);
lectura=read_TWI_data(2,3); //debe leer 3 bytes del arduino solo consigo que lea uno o dos pero no 3
printf("lectura despues=0x%X\n",lectura);
cavium_disable_TWI();
}
Si a alguien se le ocurre algo que lo diga pleaseeeeee. No da error de nada, simplemente lectura se queda con valores indebidos si intento leer más de 2 bytes del arduino (Wire.write(SensorName,>2));
Un saludo.