diff --git a/lib/i2c_master.c b/lib/i2c_master.c index ad4f5d2..c27172f 100644 --- a/lib/i2c_master.c +++ b/lib/i2c_master.c @@ -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 diff --git a/lib/i2c_master.h b/lib/i2c_master.h index 84f734b..80684ab 100644 --- a/lib/i2c_master.h +++ b/lib/i2c_master.h @@ -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);