int i2c_master_wr(unsigned int addr, const void * buf, int len) { struct stm32f_i2c * i2c = STM32F_I2C1; int ret; xfer.ptr = (uint8_t *)buf; xfer.rem = len; xfer.cnt = len; /* – To enter Transmitter mode, a master sends the slave address with LSB reset. */ xfer.addr = addr << 1; xfer.ret = -2; DCC_LOG2(LOG_INFO, "addr=0x%02x len=%d", addr, len); // tracef("addr=0x%02x len=%d", addr, len); __thinkos_flag_clr(xfer.flag); i2c->cr1 = I2C_START | I2C_ACK | I2C_PE; /* generate a Start condition */ if (thinkos_flag_timedwait(xfer.flag, 100) == THINKOS_ETIMEDOUT) { // tracef("thinkos_flag_timedwait() tmo %d %d ", xfer.cnt, xfer.flag); DCC_LOG(LOG_TRACE, "Timeout..."); i2c_master_reset(); ret = -1; } else ret = xfer.ret; DCC_LOG1(LOG_INFO, "ret=%d", ret); return ret; }
void i2c_reset(void) { thinkos_mutex_lock(i2c_mutex); i2c_master_reset(); thinkos_mutex_unlock(i2c_mutex); }
int i2c_cb(int i2c_id, unsigned char ** data, void * user, bool nack) { switch(i2c_status) { case I2C_IDLE: i2c_data = RF_ADDRESS << 1; *data = &i2c_data; i2c_status++; return I2C_MASTER_WRITE; case I2C_ADDRESS: if(nack) { i2c_status = I2C_STOP2; return I2C_MASTER_STOP; } i2c_status = I2C_REG_L; i2c_data = REG_FIFO_LEN; *data = &i2c_data; return I2C_MASTER_WRITE; case I2C_REG_L: if(nack) { i2c_status = I2C_STOP2; return I2C_MASTER_STOP; } i2c_status = I2C_RESTART; return I2C_MASTER_RESTART; case I2C_RESTART: i2c_data = RF_ADDRESS << 1 | 0x1; *data = &i2c_data; i2c_status = I2C_ADDRESS2; return I2C_MASTER_WRITE; case I2C_ADDRESS2: if(nack){ i2c_status = I2C_STOP2; return I2C_MASTER_STOP; } i2c_status = I2C_READ_L1; *data = &i2c_data; return I2C_MASTER_READ; case I2C_READ_L1: i2c_status = I2C_READ_L1_ACK; fifo_read_len = i2c_data; return I2C_MASTER_ACK; case I2C_READ_L2: fifo_read_len |= i2c_data << 8; if(fifo_read_len && !AsebaFifoRxFull()) { i2c_status = I2C_READ_L2_ACK; return I2C_MASTER_ACK; } else { i2c_status = I2C_READ_FIFO_NACK; return I2C_MASTER_NACK; } case I2C_READ_L1_ACK: i2c_status = I2C_READ_L2; *data = &i2c_data; return I2C_MASTER_READ; case I2C_READ_FIFO_ACK: case I2C_READ_L2_ACK: i2c_status = I2C_READ_FIFO; *data = &i2c_data; return I2C_MASTER_READ; case I2C_READ_FIFO: AsebaFifoPushToRx(i2c_data); status |= RF_DATA_RX; fifo_read_len--; if(fifo_read_len && !AsebaFifoRxFull()) { i2c_status = I2C_READ_FIFO_ACK; return I2C_MASTER_ACK; } else { i2c_status = I2C_READ_FIFO_NACK; return I2C_MASTER_NACK; } case I2C_READ_FIFO_NACK: // Check if we should write something. if(!AsebaFifoTxEmpty()) { i2c_status = I2C_RESTART2; return I2C_MASTER_RESTART; } else { // Nothing to send. End of communication. i2c_status = I2C_STOP2; return I2C_MASTER_STOP; } case I2C_RESTART2: i2c_data = RF_ADDRESS << 1; *data = &i2c_data; i2c_status = I2C_ADDRESS3; return I2C_MASTER_WRITE; case I2C_ADDRESS3: if(nack) { i2c_status = I2C_STOP2; return I2C_MASTER_STOP; } *data = &i2c_data; i2c_data = REG_FIFO; i2c_status = I2C_REG_F; return I2C_MASTER_WRITE; case I2C_REG_F: if(nack || AsebaFifoTxEmpty()) { i2c_status = I2C_STOP2; return I2C_MASTER_STOP; } i2c_status = I2C_WRITE_FIFO; i2c_data = AsebaFifoTxPeek(); *data = &i2c_data; return I2C_MASTER_WRITE; case I2C_WRITE_FIFO: if(!nack) // The device accepted our write. AsebaFifoTxPop(); if(nack || AsebaFifoTxEmpty()) { // RF fifo full ... or our fifo is empty. // In both case we have to stop writing. i2c_status = I2C_STOP2; return I2C_MASTER_STOP; } // try a next write i2c_status = I2C_WRITE_FIFO; i2c_data = AsebaFifoTxPeek(); *data = &i2c_data; return I2C_MASTER_WRITE; case I2C_STOP2: i2c_status = I2C_IDLE; if(read_acc) { read_acc = 0; // Read async will immediatly start a transfert. // We must reset the state machine first. i2c_master_reset(i2c_id); mma7660_read_async(); return I2C_MASTER_QUIT; } else return I2C_MASTER_DONE; } // Never reached return I2C_MASTER_QUIT; }