From d78be97154590ae5d48ebbb900182711c035274e Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Tue, 21 Nov 2017 21:10:17 +0800 Subject: [PATCH] add NACK for the last byte to read --- components/driver/i2c.c | 35 +++++++++++++++++++++----- components/driver/include/driver/i2c.h | 11 ++++++-- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 57ae7547d..e0778be70 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -65,6 +65,8 @@ static DRAM_ATTR i2c_dev_t* const I2C[I2C_NUM_MAX] = { &I2C0, &I2C1 }; #define I2C_SCL_IO_ERR_STR "scl gpio number error" #define I2C_CMD_LINK_INIT_ERR_STR "i2c command link error" #define I2C_GPIO_PULLUP_ERR_STR "this i2c pin does not support internal pull-up" +#define I2C_ACK_TYPE_ERR_STR "i2c ack type error" +#define I2C_DATA_LEN_ERR_STR "i2c data read length error" #define I2C_FIFO_FULL_THRESH_VAL (28) #define I2C_FIFO_EMPTY_THRESH_VAL (5) #define I2C_IO_INIT_LEVEL (1) @@ -958,11 +960,8 @@ esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool return i2c_cmd_link_append(cmd_handle, &cmd); } -esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, int ack) +static esp_err_t i2c_master_read_static(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, i2c_ack_type_t ack) { - I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); - I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG); - int len_tmp; int data_offset = 0; esp_err_t ret; @@ -985,20 +984,44 @@ esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t dat return ESP_OK; } -esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, int ack) +esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, i2c_ack_type_t ack) { I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG); + I2C_CHECK(ack < I2C_MASTER_ACK_MAX, I2C_ACK_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); + i2c_cmd_t cmd; cmd.ack_en = 0; cmd.ack_exp = 0; - cmd.ack_val = ack & 0x1; + cmd.ack_val = ((ack == I2C_MASTER_LAST_NACK) ? I2C_MASTER_NACK : (ack & 0x1)); cmd.byte_num = 1; cmd.op_code = I2C_CMD_READ; cmd.data = data; return i2c_cmd_link_append(cmd_handle, &cmd); } +esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, i2c_ack_type_t ack) +{ + I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); + I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG); + I2C_CHECK(ack < I2C_MASTER_ACK_MAX, I2C_ACK_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); + I2C_CHECK(data_len < 1, I2C_DATA_LEN_ERR_STR, ESP_ERR_INVALID_ARG); + + if(ack != I2C_MASTER_LAST_NACK) { + return i2c_master_read_static(cmd_handle, data, data_len, ack); + } else { + if(data_len == 1) { + return i2c_master_read_byte(cmd_handle, data, I2C_MASTER_NACK); + } else { + esp_err_t ret; + if((ret = i2c_master_read_static(cmd_handle, data, data_len - 1, I2C_MASTER_ACK)) != ESP_OK) { + return ret; + } + return i2c_master_read_byte(cmd_handle, data + data_len - 1, I2C_MASTER_NACK); + } + } +} + static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num) { i2c_obj_t* p_i2c = p_i2c_obj[i2c_num]; diff --git a/components/driver/include/driver/i2c.h b/components/driver/include/driver/i2c.h index 765eab01c..b7aceb7b1 100644 --- a/components/driver/include/driver/i2c.h +++ b/components/driver/include/driver/i2c.h @@ -69,6 +69,13 @@ typedef enum { I2C_ADDR_BIT_MAX, } i2c_addr_mode_t; +typedef enum { + I2C_MASTER_ACK = 0x0, /*!< I2C ack for each byte read */ + I2C_MASTER_NACK = 0x1, /*!< I2C nack for each byte read */ + I2C_MASTER_LAST_NACK = 0x2, /*!< I2C nack for the last byte*/ + I2C_MASTER_ACK_MAX, +} i2c_ack_type_t; + /** * @brief I2C initialization parameters */ @@ -288,7 +295,7 @@ esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t da * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, int ack); +esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, i2c_ack_type_t ack); /** * @brief Queue command for I2C master to read data from I2C bus @@ -305,7 +312,7 @@ esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, int a * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, int ack); +esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, i2c_ack_type_t ack); /** * @brief Queue command for I2C master to generate a stop signal