mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
Merge branch 'bugfix/eeprom_write_page' into 'master'
fix(examples): fix EEPROM API to allow variable page sizes See merge request espressif/esp-idf!46526
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_log.h"
|
||||
@@ -16,11 +17,22 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#define I2C_EEPROM_MAX_TRANS_UNIT (48)
|
||||
/* Smallest EEPROMs have a page size of 8 bytes */
|
||||
#define I2C_EEPROM_MINIMUM_PAGE_SIZE (8)
|
||||
/* Biggest EEPROMs have a page size of 256 bytes (24CM01/24CM02) */
|
||||
#define I2C_EEPROM_MAX_PAGE_SIZE (256)
|
||||
// Different EEPROM device might share one I2C bus
|
||||
|
||||
static const char TAG[] = "i2c-eeprom";
|
||||
|
||||
struct i2c_eeprom_t {
|
||||
i2c_master_dev_handle_t i2c_dev; /*!< I2C device handle */
|
||||
uint8_t addr_wordlen; /*!< block address wordlen */
|
||||
uint8_t page_size; /*!< eeprom page size */
|
||||
uint8_t *buffer; /*!< I2C transaction buffer */
|
||||
uint8_t write_time_ms; /*!< I2C eeprom write time(ms)*/
|
||||
};
|
||||
|
||||
esp_err_t i2c_eeprom_init(i2c_master_bus_handle_t bus_handle, const i2c_eeprom_config_t *eeprom_config, i2c_eeprom_handle_t *eeprom_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
@@ -37,11 +49,15 @@ 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);
|
||||
out_handle->buffer = (uint8_t*)calloc(1, eeprom_config->addr_wordlen + I2C_EEPROM_MAX_PAGE_SIZE);
|
||||
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;
|
||||
|
||||
/* Page size cannot exceed the maximum since it is encoded on 8-bit */
|
||||
out_handle->page_size = MAX(eeprom_config->page_size, I2C_EEPROM_MINIMUM_PAGE_SIZE);
|
||||
|
||||
*eeprom_handle = out_handle;
|
||||
|
||||
return ESP_OK;
|
||||
@@ -54,23 +70,44 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2c_eeprom_write(i2c_eeprom_handle_t eeprom_handle, uint32_t address, const uint8_t *data, uint32_t size)
|
||||
static void i2c_eeprom_prepare_address(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);
|
||||
}
|
||||
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);
|
||||
esp_err_t i2c_eeprom_write(i2c_eeprom_handle_t eeprom_handle, uint32_t address, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(eeprom_handle, ESP_ERR_NO_MEM, TAG, "no mem for buffer");
|
||||
|
||||
/* We cannot write more than page size at once, so we have to write in chunks */
|
||||
uint8_t *chunk_data = eeprom_handle->buffer + eeprom_handle->addr_wordlen;
|
||||
esp_err_t err = ESP_OK;
|
||||
while (size > 0) {
|
||||
uint32_t chunk_size = MIN(size, eeprom_handle->page_size);
|
||||
i2c_eeprom_prepare_address(eeprom_handle, address);
|
||||
memcpy(chunk_data, data, chunk_size);
|
||||
err = i2c_master_transmit(eeprom_handle->i2c_dev, eeprom_handle->buffer, eeprom_handle->addr_wordlen + chunk_size, -1);
|
||||
if (err != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
size -= chunk_size;
|
||||
address += chunk_size;
|
||||
data += chunk_size;
|
||||
/* Do not wait for completion for the last chunk (let the caller do it) */
|
||||
if (size > 0) {
|
||||
i2c_eeprom_wait_idle(eeprom_handle);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
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");
|
||||
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);
|
||||
}
|
||||
i2c_eeprom_prepare_address(eeprom_handle, address);
|
||||
|
||||
return i2c_master_transmit_receive(eeprom_handle->i2c_dev, eeprom_handle->buffer, eeprom_handle->addr_wordlen, data, size, -1);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -13,20 +13,13 @@ extern "C" {
|
||||
|
||||
typedef struct {
|
||||
i2c_device_config_t eeprom_device; /*!< Configuration for eeprom device */
|
||||
uint8_t page_size; /*!< eeprom page size */
|
||||
uint8_t addr_wordlen; /*!< block address wordlen */
|
||||
uint8_t write_time_ms; /*!< eeprom write time, typically 10ms*/
|
||||
} i2c_eeprom_config_t;
|
||||
|
||||
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 write_time_ms; /*!< I2C eeprom write time(ms)*/
|
||||
};
|
||||
|
||||
typedef struct i2c_eeprom_t i2c_eeprom_t;
|
||||
|
||||
/* handle of EEPROM device */
|
||||
typedef struct i2c_eeprom_t i2c_eeprom_t;
|
||||
typedef struct i2c_eeprom_t *i2c_eeprom_handle_t;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user