i2c_master: fix 1 byte read

This commit is contained in:
King Kévin 2020-02-11 12:21:35 +01:00
parent 25ce80b73a
commit 4bfcca9d50
2 changed files with 15 additions and 12 deletions

View File

@ -433,14 +433,10 @@ enum i2c_master_rc i2c_master_read(uint32_t i2c, uint8_t* data, size_t data_size
return I2C_MASTER_RC_NOT_READY;
}
// prepare (N)ACK (EV6_3 in RM0008)
if (1 == data_size) {
i2c_nack_current(i2c); // [N]ACK current byte
i2c_disable_ack(i2c); // NACK after first byte
} else if (2 == data_size) {
i2c_nack_next(i2c); // [N]ACK next byte
i2c_enable_ack(i2c); // NACK first byte
} else {
i2c_nack_current(i2c); // ACK current byte
i2c_enable_ack(i2c); // NAK after next byte
}
uint16_t sr2 = I2C_SR2(i2c); // reading SR2 will also also clear ADDR in SR1 and start the transaction
@ -453,11 +449,13 @@ enum i2c_master_rc i2c_master_read(uint32_t i2c, uint8_t* data, size_t data_size
// read data
for (size_t i = 0; i < data_size; i++) { // read bytes
if (2 == data_size - i) { // prepare to sent NACK for second last byte
i2c_nack_next(i2c); // NACK next byte
// set (N)ACK (EV6_3, EV6_1)
if (1 == data_size - i) { // prepare to sent NACK for last byte
i2c_send_stop(i2c); // already indicate we will send a stop (required to not send an ACK, and this must happen before the byte is transferred, see errata)
i2c_nack_current(i2c); // (N)ACK current byte
i2c_disable_ack(i2c); // NACK received to stop slave transmission
} else if (1 == data_size - i) { // prepare to sent NACK for last byte
i2c_nack_current(i2c); // ACK current byte
} else if (2 == data_size - i) { // prepare to sent NACK for second last byte
i2c_nack_next(i2c); // NACK next byte
i2c_disable_ack(i2c); // NACK received to stop slave transmission
} else {
i2c_enable_ack(i2c); // ACK received byte to continue slave transmission

View File

@ -69,20 +69,21 @@ enum i2c_master_rc i2c_master_start(uint32_t i2c);
*/
enum i2c_master_rc i2c_master_select_slave(uint32_t i2c, uint16_t slave, bool address_10bit, bool write);
/** read data over I²C
* @warning the slave device must be selected before this operation
* @param[in] i2c I²C base address
* @param[out] data array to store bytes read
* @param[in] data_size number of bytes to read
* @note the last read byte is NACKed, but the I²C peripheral will clock the read for at least 2 more bytes after the NACK
* @return I²C return code
* @warning the slave device must be selected before this operation
* @note a stop condition will be sent at the end (I²C does not permit multiple reads, and this is necessary for 1-byte transfer)
*/
enum i2c_master_rc i2c_master_read(uint32_t i2c, uint8_t* data, size_t data_size);
/** write data over I²C
* @warning the slave device must be selected before this operation
* @param[in] i2c I²C base address
* @param[in] data array of byte to write to slave
* @param[in] data_size number of bytes to write
* @return I²C return code
* @warning the slave device must be selected before this operation
* @note no stop condition is sent at the end, allowing multiple writes
*/
enum i2c_master_rc i2c_master_write(uint32_t i2c, const uint8_t* data, size_t data_size);
/** sent stop condition
@ -97,6 +98,7 @@ enum i2c_master_rc i2c_master_stop(uint32_t i2c);
* @param[out] data array to store bytes read
* @param[in] data_size number of bytes to read
* @return I²C return code
* @note start and stop conditions are included
*/
enum i2c_master_rc i2c_master_slave_read(uint32_t i2c, uint16_t slave, bool address_10bit, uint8_t* data, size_t data_size);
/** write data to slave device
@ -106,6 +108,7 @@ enum i2c_master_rc i2c_master_slave_read(uint32_t i2c, uint16_t slave, bool addr
* @param[in] data array of byte to write to slave
* @param[in] data_size number of bytes to write
* @return I²C return code
* @note start and stop conditions are included
*/
enum i2c_master_rc i2c_master_slave_write(uint32_t i2c, uint16_t slave, bool address_10bit, const uint8_t* data, size_t data_size);
/** read data at specific address from an I²C memory slave
@ -117,6 +120,7 @@ enum i2c_master_rc i2c_master_slave_write(uint32_t i2c, uint16_t slave, bool add
* @param[out] data array to store bytes read
* @param[in] data_size number of bytes to read
* @return I²C return code
* @note start and stop conditions are included
*/
enum i2c_master_rc i2c_master_address_read(uint32_t i2c, uint16_t slave, bool address_10bit, const uint8_t* address, size_t address_size, uint8_t* data, size_t data_size);
/** write data at specific address on an I²C memory slave
@ -128,5 +132,6 @@ enum i2c_master_rc i2c_master_address_read(uint32_t i2c, uint16_t slave, bool ad
* @param[in] data array of byte to write to slave
* @param[in] data_size number of bytes to write
* @return I²C return code
* @note start and stop conditions are included
*/
enum i2c_master_rc i2c_master_address_write(uint32_t i2c, uint16_t slave, bool address_10bit, const uint8_t* address, size_t address_size, const uint8_t* data, size_t data_size);