int i2c_read(int device, unsigned char *buf, int count) { int cnt = count; int timeout = 5; device &= 0xFF; i2c_open(); L_try_again: if (timeout < 0) goto L_timeout; __i2c_send_nack(); /* Master does not send ACK, slave sends it */ __i2c_send_start(); if (i2c_put_data( (device << 1) | I2C_READ ) < 0) goto device_err; __i2c_send_ack(); /* Master sends ACK for continue reading */ while (cnt) { if (cnt == 1) { if (i2c_get_data(buf, 0) < 0) break; } else { if (i2c_get_data(buf, 1) < 0) break; } cnt--; buf++; } __i2c_send_stop(); i2c_close(); return count - cnt; device_err: timeout--; __i2c_send_stop(); goto L_try_again; L_timeout: __i2c_send_stop(); logf("Read I2C device 0x%2x failed.", device); i2c_close(); return -1; }
int i2c_read(unsigned char device, unsigned char *buf, unsigned char address, int count) { int cnt = count; int timeout = 5; L_try_again: if (timeout < 0) goto L_timeout; __i2c_send_nack(); /* Master does not send ACK, slave sends it */ __i2c_send_start(); if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) goto device_werr; #ifndef CONFIG_TOUCHSCREEN_AK4183 if (i2c_put_data(address) < 0) goto address_err; #endif __i2c_send_start(); if (i2c_put_data( (device << 1) | I2C_READ ) < 0) goto device_rerr; __i2c_send_ack(); /* Master sends ACK for continue reading */ while (cnt) { if (cnt == 1) { if (i2c_get_data(buf, 0) < 0) break; } else { if (i2c_get_data(buf, 1) < 0) break; } cnt--; buf++; } #ifdef CONFIG_TOUCHSCREEN_AK4183 __i2c_send_nack(); #endif __i2c_send_stop(); return count - cnt; device_rerr: device_werr: address_err: timeout --; __i2c_send_stop(); goto L_try_again; L_timeout: __i2c_send_stop(); printk("Read I2C device 0x%2x failed.\n", device); return -ENODEV; }
static inline void stmi2c_clear_pending_interrupts(uint32_t i2c) { uint16_t SR1 = I2C_SR1(i2c); // Certainly do not wait for buffer interrupts: // ------------------------------------------- i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN); // Disable TXE, RXNE // Error interrupts are handled separately: // --------------------------------------- // Clear Event interrupt conditions: // -------------------------------- // Start Condition Was Generated if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) ) { // SB: cleared by software when reading SR1 and writing to DR i2c_send_data(i2c, 0x00); } // Address Was Sent if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) ) { // ADDR: Cleared by software when reading SR1 and then SR2 uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c); } // Byte Transfer Finished if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) ) { // SB: cleared by software when reading SR1 and reading/writing to DR uint8_t dummy __attribute__ ((unused)) = i2c_get_data(i2c); i2c_send_data(i2c, 0x00); } }
uchar i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data, int len) { uchar status = 0; unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED; DP (puts ("i2c_read\n")); i2c_init (i2cFreq, 0); /* set the i2c frequency */ status = i2c_start (); if (status) { #ifdef DEBUG_I2C printf ("Transaction start failed: 0x%02x\n", status); #endif return status; } status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */ if (status) { #ifdef DEBUG_I2C printf ("Failed to set slave address & offset: 0x%02x\n", status); #endif return status; } i2c_init (i2cFreq, 0); /* set the i2c frequency again */ status = i2c_start (); if (status) { #ifdef DEBUG_I2C printf ("Transaction restart failed: 0x%02x\n", status); #endif return status; } status = i2c_select_device (dev_addr, 1, 0); /* send the slave address */ if (status) { #ifdef DEBUG_I2C printf ("Address not acknowledged: 0x%02x\n", status); #endif return status; } status = i2c_get_data (data, len); if (status) { #ifdef DEBUG_I2C printf ("Data not recieved: 0x%02x\n", status); #endif return status; } return 0; }
static uint32_t i2c_read(uint8_t reg) { // while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) { // } i2c_send_start(I2C_PORT); /* Wait for master mode selected */ while (!((I2C_SR1(I2C_PORT) & I2C_SR1_SB) & (I2C_SR2(I2C_PORT) & (I2C_SR2_MSL | I2C_SR2_BUSY)))); i2c_send_7bit_address(I2C_PORT, SLAVE_ADDRESS, I2C_WRITE); /* Waiting for address is transferred. */ while (!(I2C_SR1(I2C_PORT) & I2C_SR1_ADDR)); /* Cleaning ADDR condition sequence. */ uint32_t reg32 = I2C_SR2(I2C_PORT); (void) reg32; /* unused */ /* Common stuff ABOVE HERE */ i2c_send_data(I2C_PORT, reg); while (!(I2C_SR1(I2C_PORT) & (I2C_SR1_BTF))); i2c_send_start(I2C_PORT); /* Wait for master mode selected */ while (!((I2C_SR1(I2C_PORT) & I2C_SR1_SB) & (I2C_SR2(I2C_PORT) & (I2C_SR2_MSL | I2C_SR2_BUSY)))); i2c_send_7bit_address(I2C_PORT, SLAVE_ADDRESS, I2C_READ); /* Waiting for address is transferred. */ while (!(I2C_SR1(I2C_PORT) & I2C_SR1_ADDR)); i2c_disable_ack(I2C_PORT); /* Cleaning ADDR condition sequence. */ reg32 = I2C_SR2(I2C_PORT); (void) reg32; /* unused */ i2c_send_stop(I2C_PORT); while (!(I2C_SR1(I2C_PORT) & I2C_SR1_RxNE)); uint32_t result = i2c_get_data(I2C_PORT); i2c_enable_ack(I2C_PORT); I2C_SR1(I2C_PORT) &= ~I2C_SR1_AF; return result; }
static int i2c_get_ack() { int error=0; int ack; error+= i2c_set_lines(0,1); error+= i2c_set_lines(1,1); ack = i2c_get_data(); error+= i2c_set_lines(0,1); if (error) { LOG(8,("I2C: get_ack - %d value:%x\n",error,ack)); } return ack; }
static unsigned char i2c_readbyte(int ack_required) { int i; unsigned char data=0; /*read data*/ i2c_set_lines(0,1); for (i=7; i>=0; i--) { i2c_set_lines(1,1); if (i2c_get_data()==1) data |= (1<<i); i2c_set_lines(0,1); } /*send acknowledge*/ if (ack_required) i2c_send_ack(); return data; }
static uint32_t i2c_read(uint32_t i2c, uint8_t address, uint8_t reg) { while ((I2C_SR2(i2c) & I2C_SR2_BUSY)); i2c_start(i2c, address, I2C_WRITE); i2c_send_data(i2c, reg); while (!(I2C_SR1(i2c) & (I2C_SR1_BTF))); i2c_start(i2c, address, I2C_READ); i2c_send_stop(i2c); while (!(I2C_SR1(i2c) & I2C_SR1_RxNE)); uint32_t result = i2c_get_data(i2c); I2C_SR1(i2c) &= ~I2C_SR1_AF; return result; }
void read_i2c(uint32_t i2c, uint8_t i2c_addr, uint8_t reg, uint8_t size, uint8_t *data) { int wait; int i; while (i2c_busy(i2c) == 1); while (i2c_is_start(i2c) == 1); /*Setting transfer properties*/ i2c_set_bytes_to_transfer(i2c, 1); i2c_set_7bit_address(i2c, i2c_addr); i2c_set_write_transfer_dir(i2c); i2c_disable_autoend(i2c); /*start transfer*/ i2c_send_start(i2c); wait = true; while (wait) { if (i2c_transmit_int_status(i2c)) { wait = false; } while (i2c_nack(i2c)); /* Some error */ } i2c_send_data(i2c, reg); while (i2c_is_start(i2c) == 1); /*Setting transfer properties*/ i2c_set_bytes_to_transfer(i2c, size); i2c_set_7bit_address(i2c, i2c_addr); i2c_set_read_transfer_dir(i2c); i2c_enable_autoend(i2c); /*start transfer*/ i2c_send_start(i2c); for (i = 0; i < size; i++) { while (i2c_received_data(i2c) == 0); data[i] = i2c_get_data(i2c); } }
// Doc ID 13902 Rev 11 p 712/1072 // Transfer Sequence Diagram for Master Receiver for N>2 static inline enum STMI2CSubTransactionStatus stmi2c_readmany(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans) { uint16_t SR1 = I2C_SR1(i2c); // Start Condition Was Just Generated if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) ) { i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN); // The first data byte will be acked in read many so the slave knows it should send more i2c_nack_current(i2c); i2c_enable_ack(i2c); // Clear the SB flag i2c_send_data(i2c, trans->slave_addr | 0x01); // Document the current Status periph->status = I2CAddrRdSent; } // Address Was Sent else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) ) { periph->idx_buf = 0; // Enable RXNE: receive an interrupt any time a byte is available // only enable if MORE than 3 bytes need to be read if (periph->idx_buf < (trans->len_r - 3)) { i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN); } // ACK is still on to get more DATA // Read SR2 to clear the ADDR (next byte will start arriving) uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c); // Document the current Status periph->status = I2CReadingByte; } // one or more bytes are available AND we were interested in Buffer interrupts else if ( (BIT_X_IS_SET_IN_REG(I2C_SR1_RxNE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_ITBUFEN, I2C_CR2(i2c))) ) { // read byte until 3 bytes remain to be read (e.g. len_r = 6, -> idx=3 means idx 3,4,5 = 3 remain to be read if (periph->idx_buf < (trans->len_r - 3)) { trans->buf[periph->idx_buf] = I2C_DR(i2c); periph->idx_buf ++; } // from : 3bytes -> last byte: do nothing // // finally: this was the last byte else if (periph->idx_buf >= (trans->len_r - 1)) { i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN); // Last Value trans->buf[periph->idx_buf] = i2c_get_data(i2c); periph->idx_buf ++; // We got all the results trans->status = I2CTransSuccess; return STMI2C_SubTra_Ready_StopRequested; } // Check for end of transaction: start waiting for BTF instead of RXNE if (periph->idx_buf < (trans->len_r - 3)) { i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN); } else // idx >= len-3: there are 3 bytes to be read { // We want to halt I2C to have sufficient time to clear ACK, so: // Stop listening to RXNE as it will be triggered infinitely since we did not empty the buffer // on the next (second in buffer) received byte BTF will be set (buffer full and I2C halted) i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN); } } // Buffer is full while this was not a RXNE interrupt else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) ) { // Now the shift register and data register contain data(n-2) and data(n-1) // And I2C is halted so we have time // --- Make absolutely sure the next 2 I2C actions are performed with no delay __I2C_REG_CRITICAL_ZONE_START; // First we clear the ACK while the SCL is held low by BTF i2c_disable_ack(i2c); // Now that ACK is cleared we read one byte: instantly the last byte is being clocked in... trans->buf[periph->idx_buf] = i2c_get_data(i2c); periph->idx_buf ++; // Now the last byte is being clocked. Stop in MUST be set BEFORE the transfer of the last byte is complete PPRZ_I2C_SEND_STOP(i2c); __I2C_REG_CRITICAL_ZONE_STOP; // --- end of critical zone ----------- // Document the current Status periph->status = I2CStopRequested; // read the byte2 we had in the buffer (BTF means 2 bytes available) trans->buf[periph->idx_buf] = i2c_get_data(i2c); periph->idx_buf ++; // Ask for an interrupt to read the last byte (which is normally still busy now) // The last byte will be received with RXNE i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN); } else // Event Logic Error { return STMI2C_SubTra_Error; } return STMI2C_SubTra_Busy; }