Andy Lin 2024-04-26 17:19:05 +08:00 zatwierdzone przez GitHub
commit 1daafbc479
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
4 zmienionych plików z 73 dodań i 20 usunięć

Wyświetl plik

@ -193,14 +193,30 @@ static bool s_i2c_write_command(i2c_master_bus_handle_t i2c_master, i2c_operatio
i2c_master->async_break = true;
}
} else {
i2c_master->cmd_idx++;
i2c_master->trans_idx++;
i2c_master->i2c_trans.cmd_count--;
if (i2c_master->async_trans == false) {
if (xPortInIsrContext()) {
xSemaphoreGiveFromISR(i2c_master->cmd_semphr, do_yield);
// Handle consecutive i2c write operations
i2c_operation_t next_transaction = i2c_master->i2c_trans.ops[i2c_master->trans_idx + 1];
if (next_transaction.hw_cmd.op_code == I2C_LL_CMD_WRITE) {
portENTER_CRITICAL_SAFE(&handle->spinlock);
i2c_ll_master_write_cmd_reg(hal->dev, hw_end_cmd, i2c_master->cmd_idx + 1);
portEXIT_CRITICAL_SAFE(&handle->spinlock);
i2c_master->cmd_idx = 0;
i2c_master->trans_idx++;
i2c_master->i2c_trans.cmd_count--;
if (i2c_master->async_trans == false) {
i2c_hal_master_trans_start(hal);
} else {
xSemaphoreGive(i2c_master->cmd_semphr);
i2c_master->async_break = true;
}
} else {
i2c_master->cmd_idx++;
i2c_master->trans_idx++;
i2c_master->i2c_trans.cmd_count--;
if (i2c_master->async_trans == false) {
if (xPortInIsrContext()) {
xSemaphoreGiveFromISR(i2c_master->cmd_semphr, do_yield);
} else {
xSemaphoreGive(i2c_master->cmd_semphr);
}
}
}
}
@ -524,7 +540,6 @@ static void s_i2c_send_command_async(i2c_master_bus_handle_t i2c_master, BaseTyp
needs_start = s_i2c_read_command(i2c_master, i2c_operation, &fifo_fill, do_yield);
} else {
s_i2c_start_end_command(i2c_master, i2c_operation, &address_fill, do_yield);
}
}
i2c_hal_master_trans_start(hal);
@ -1076,6 +1091,27 @@ esp_err_t i2c_master_transmit(i2c_master_dev_handle_t i2c_dev, const uint8_t *wr
return ESP_OK;
}
esp_err_t i2c_master_prefixed_transmit(i2c_master_dev_handle_t i2c_dev, const uint8_t *reg_buffer, size_t reg_size, const uint8_t *write_buffer, size_t write_size, int xfer_timeout_ms)
{
ESP_RETURN_ON_FALSE(i2c_dev != NULL, ESP_ERR_INVALID_ARG, TAG, "i2c handle not initialized");
ESP_RETURN_ON_FALSE((reg_buffer != NULL) && (reg_size > 0), ESP_ERR_INVALID_ARG, TAG, "i2c register/command buffer or size invalid");
ESP_RETURN_ON_FALSE((write_buffer != NULL) && (write_size > 0), ESP_ERR_INVALID_ARG, TAG, "i2c transmit buffer or size invalid");
i2c_operation_t i2c_ops[] = {
{.hw_cmd = I2C_TRANS_START_COMMAND},
{.hw_cmd = I2C_TRANS_WRITE_COMMAND(i2c_dev->ack_check_disable ? false : true), .data = (uint8_t *)reg_buffer, .total_bytes = reg_size},
{.hw_cmd = I2C_TRANS_WRITE_COMMAND(i2c_dev->ack_check_disable ? false : true), .data = (uint8_t *)write_buffer, .total_bytes = write_size},
{.hw_cmd = I2C_TRANS_STOP_COMMAND},
};
if (i2c_dev->master_bus->async_trans == false) {
ESP_RETURN_ON_ERROR(s_i2c_synchronous_transaction(i2c_dev, i2c_ops, DIM(i2c_ops), xfer_timeout_ms), TAG, "I2C transaction failed");
} else {
ESP_RETURN_ON_ERROR(s_i2c_asynchronous_transaction(i2c_dev, i2c_ops, DIM(i2c_ops), xfer_timeout_ms), TAG, "I2C transaction failed");
}
return ESP_OK;
}
esp_err_t i2c_master_transmit_receive(i2c_master_dev_handle_t i2c_dev, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms)
{
ESP_RETURN_ON_FALSE(i2c_dev != NULL, ESP_ERR_INVALID_ARG, TAG, "i2c handle not initialized");

Wyświetl plik

@ -123,6 +123,27 @@ esp_err_t i2c_master_bus_rm_device(i2c_master_dev_handle_t handle);
*/
esp_err_t i2c_master_transmit(i2c_master_dev_handle_t i2c_dev, const uint8_t *write_buffer, size_t write_size, int xfer_timeout_ms);
/**
* @brief Perform a write transaction with prefixed register/command bytes on the I2C bus.
* The transaction will be undergoing until it finishes or it reaches
* the timeout provided.
*
* @note If a callback was registered with `i2c_master_register_event_callbacks`, the transaction will be asynchronous, and thus, this function will return directly, without blocking.
* You will get finish information from callback. Besides, data buffer should always be completely prepared when callback is registered, otherwise, the data will get corrupt.
*
* @param[in] i2c_dev I2C master device handle that created by `i2c_master_bus_add_device`.
* @param[in] reg_buffer Register/command bytes to send on the I2C bus.
* @param[in] reg_size Size, in bytes, of the register/command buffer.
* @param[in] write_buffer Data bytes to send on the I2C bus.
* @param[in] write_size Size, in bytes, of the write buffer.
* @param[in] xfer_timeout_ms Wait timeout, in ms. Note: -1 means wait forever.
* @return
* - ESP_OK: I2C master transmit success
* - ESP_ERR_INVALID_ARG: I2C master transmit parameter invalid.
* - ESP_ERR_TIMEOUT: Operation timeout(larger than xfer_timeout_ms) because the bus is busy or hardware crash.
*/
esp_err_t i2c_master_prefixed_transmit(i2c_master_dev_handle_t i2c_dev, const uint8_t *reg_buffer, size_t reg_size, const uint8_t *write_buffer, size_t write_size, int xfer_timeout_ms);
/**
* @brief Perform a write-read transaction on the I2C bus.
* The transaction will be undergoing until it finishes or it reaches

Wyświetl plik

@ -16,7 +16,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define I2C_EEPROM_MAX_TRANS_UNIT (48)
// Different EEPROM device might share one I2C bus
static const char TAG[] = "i2c-eeprom";
@ -25,8 +24,9 @@ esp_err_t i2c_eeprom_init(i2c_master_bus_handle_t bus_handle, const i2c_eeprom_c
{
esp_err_t ret = ESP_OK;
i2c_eeprom_handle_t out_handle;
out_handle = (i2c_eeprom_handle_t)calloc(1, sizeof(i2c_eeprom_handle_t));
out_handle = (i2c_eeprom_handle_t)calloc(1, sizeof(i2c_eeprom_t));
ESP_GOTO_ON_FALSE(out_handle, ESP_ERR_NO_MEM, err, TAG, "no memory for i2c eeprom device");
ESP_GOTO_ON_FALSE(eeprom_config->addr_wordlen <= 4, ESP_ERR_NO_MEM, err, TAG, "max possible addr_wordlen is 4");
i2c_device_config_t i2c_dev_conf = {
.scl_speed_hz = eeprom_config->eeprom_device.scl_speed_hz,
@ -37,9 +37,6 @@ esp_err_t i2c_eeprom_init(i2c_master_bus_handle_t bus_handle, const i2c_eeprom_c
ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(bus_handle, &i2c_dev_conf, &out_handle->i2c_dev), err, TAG, "i2c new bus failed");
}
out_handle->buffer = (uint8_t*)calloc(1, eeprom_config->addr_wordlen + I2C_EEPROM_MAX_TRANS_UNIT);
ESP_GOTO_ON_FALSE(out_handle->buffer, ESP_ERR_NO_MEM, err, TAG, "no memory for i2c eeprom device buffer");
out_handle->addr_wordlen = eeprom_config->addr_wordlen;
out_handle->write_time_ms = eeprom_config->write_time_ms;
*eeprom_handle = out_handle;
@ -58,21 +55,20 @@ esp_err_t i2c_eeprom_write(i2c_eeprom_handle_t eeprom_handle, uint32_t address,
{
ESP_RETURN_ON_FALSE(eeprom_handle, ESP_ERR_NO_MEM, TAG, "no mem for buffer");
for (int i = 0; i < eeprom_handle->addr_wordlen; i++) {
eeprom_handle->buffer[i] = (address & (0xff << ((eeprom_handle->addr_wordlen - 1 - i) * 8))) >> ((eeprom_handle->addr_wordlen - 1 - i) * 8);
eeprom_handle->addr_buffer[i] = (address & (0xff << ((eeprom_handle->addr_wordlen - 1 - i) * 8))) >> ((eeprom_handle->addr_wordlen - 1 - i) * 8);
}
memcpy(eeprom_handle->buffer + eeprom_handle->addr_wordlen, data, size);
return i2c_master_transmit(eeprom_handle->i2c_dev, eeprom_handle->buffer, eeprom_handle->addr_wordlen + size, -1);
return i2c_master_prefixed_transmit(eeprom_handle->i2c_dev, eeprom_handle->addr_buffer, eeprom_handle->addr_wordlen, data, size, -1);
}
esp_err_t i2c_eeprom_read(i2c_eeprom_handle_t eeprom_handle, uint32_t address, uint8_t *data, uint32_t size)
{
ESP_RETURN_ON_FALSE(eeprom_handle, ESP_ERR_NO_MEM, TAG, "no mem for buffer");
ESP_RETURN_ON_FALSE(eeprom_handle, ESP_ERR_NO_MEM, TAG, "no mem for address buffer");
for (int i = 0; i < eeprom_handle->addr_wordlen; i++) {
eeprom_handle->buffer[i] = (address & (0xff << ((eeprom_handle->addr_wordlen - 1 - i) * 8))) >> ((eeprom_handle->addr_wordlen - 1 - i) * 8);
eeprom_handle->addr_buffer[i] = (address & (0xff << ((eeprom_handle->addr_wordlen - 1 - i) * 8))) >> ((eeprom_handle->addr_wordlen - 1 - i) * 8);
}
return i2c_master_transmit_receive(eeprom_handle->i2c_dev, eeprom_handle->buffer, eeprom_handle->addr_wordlen, data, size, -1);
return i2c_master_transmit_receive(eeprom_handle->i2c_dev, eeprom_handle->addr_buffer, eeprom_handle->addr_wordlen, data, size, -1);
}
void i2c_eeprom_wait_idle(i2c_eeprom_handle_t eeprom_handle)

Wyświetl plik

@ -20,7 +20,7 @@ typedef struct {
struct i2c_eeprom_t {
i2c_master_dev_handle_t i2c_dev; /*!< I2C device handle */
uint8_t addr_wordlen; /*!< block address wordlen */
uint8_t *buffer; /*!< I2C transaction buffer */
uint8_t addr_buffer[4]; /*!< I2C transaction address buffer */
uint8_t write_time_ms; /*!< I2C eeprom write time(ms)*/
};