245 lines
7.6 KiB
C
245 lines
7.6 KiB
C
/***
|
|
* @file BSP_EE24.c
|
|
* This file contains functions to interact with an EEPROM driver and perform
|
|
* read and write operations on it. The driver uses I2C protocol and supports
|
|
* multiple partitions, which can be used to store different types of data.
|
|
*/
|
|
|
|
#include "BSP_EE24.h"
|
|
#include "ee24.h"
|
|
#include "i2c.h"
|
|
#include "cmsis_os2.h"
|
|
#include "gpio.h"
|
|
|
|
#define BSP_EE24_I2C &hi2c2
|
|
#define BSP_EE24_ADDRESS EE24_ADDRESS_DEFAULT
|
|
#define BSP_EE24_TIMEOUT 500
|
|
#define BSP_EE24_MUTEXT_TIMEOUT osWaitForever
|
|
|
|
// Main Pariton Table
|
|
static BSP_EE24_Partion PartionTable[__BSP_EE24_PART_MAX__] = {
|
|
[BSP_EE24_PART_HEAD_PARTION] = {
|
|
.address = -1,
|
|
.len = sizeof(BSP_EE24_TableHeader)
|
|
},
|
|
[BSP_EE24_PART_GLOBAL_LIGHT] = {
|
|
.address = -1,
|
|
.len = 64,
|
|
},
|
|
[BSP_EE24_PART_RESERVED] = {
|
|
.address = -1,
|
|
.len = 128,
|
|
}
|
|
};
|
|
static const uint32_t PartionTableVersion = 1;
|
|
static EE24_HandleTypeDef hee24 = {0};
|
|
static osMutexId_t ee24_lock;
|
|
|
|
void BSP_EE24_TableMigrate(uint32_t ee_version);
|
|
|
|
/**
|
|
* Initializes the EEPROM Partition Table.
|
|
*
|
|
* This function calculates the addresses of each element in the Partition Table
|
|
* based on their lengths and the previous element's address. It assumes that the
|
|
* Partition Table is ordered by ascending addresses, and that there are no gaps
|
|
* between elements.
|
|
*/
|
|
void BSP_EE24_InitTable() {
|
|
uint32_t address = 0; // Start at address 0
|
|
for (int i = 0; i < __BSP_EE24_PART_MAX__; i++) {
|
|
if (PartionTable[i].len > 0) {
|
|
PartionTable[i].address = address;
|
|
address += PartionTable[i].len;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Initializes the EEPROM driver and performs any necessary migrations.
|
|
*/
|
|
bool BSP_EE24_Init(void) {
|
|
BSP_EE24_InitTable();
|
|
// Initialize the EE24 driver with the I2C interface and address
|
|
bool status = EE24_Init(&hee24,BSP_EE24_I2C,BSP_EE24_ADDRESS);
|
|
if(!status) {
|
|
return status;
|
|
}
|
|
|
|
// os mutext
|
|
ee24_lock = osMutexNew(NULL);
|
|
|
|
// wc control high disables write
|
|
HAL_GPIO_WritePin(EEPROM_WC_GPIO_Port, EEPROM_WC_Pin, GPIO_PIN_SET);
|
|
|
|
// Read the Partition Table header from the EEPROM
|
|
BSP_EE24_TableHeader header = {0};
|
|
status = BSP_EE24_PartRead(BSP_EE24_PART_HEAD_PARTION, (uint8_t*)&header, sizeof(header));
|
|
if(!status) {
|
|
return status;
|
|
}
|
|
|
|
// Check if the Partition Table version is different from the expected version
|
|
uint32_t fw_table_version = PartionTableVersion;
|
|
uint32_t ee_table_version = header.version;
|
|
if(ee_table_version != fw_table_version) {
|
|
BSP_EE24_TableMigrate(ee_table_version);
|
|
if(!status) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Reads data from the EEPROM.
|
|
* This function is blocking for the operation to complete.
|
|
*
|
|
* @param[in] Address The starting address of the data to be read.
|
|
* @param[out] Data A pointer to a buffer where the data will be stored.
|
|
* @param[in] Len The number of bytes to be read.
|
|
* @return true if the operation was successful, false otherwise.
|
|
*/
|
|
bool BSP_EE24_Read(uint32_t Address, uint8_t *Data, size_t Len) {
|
|
osMutexAcquire(ee24_lock,BSP_EE24_MUTEXT_TIMEOUT);
|
|
bool status = EE24_Read(&hee24,Address,Data,Len,BSP_EE24_TIMEOUT);
|
|
osMutexRelease(ee24_lock);
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* Writes data to the EEPROM.
|
|
* This function is blocking for the operation to complete.
|
|
*
|
|
* @param[in] Address The starting address of the data to be written.
|
|
* @param[out] Data A pointer to a buffer containing the data to be written.
|
|
* @param[in] Len The number of bytes to be written.
|
|
* @return true if the operation was successful, false otherwise.
|
|
*/
|
|
bool BSP_EE24_Write(uint32_t Address, uint8_t *Data, size_t Len) {
|
|
osMutexAcquire(ee24_lock,BSP_EE24_MUTEXT_TIMEOUT);
|
|
HAL_GPIO_WritePin(EEPROM_WC_GPIO_Port, EEPROM_WC_Pin, GPIO_PIN_RESET); // low enables write;
|
|
bool status = EE24_Write(&hee24,Address,Data,Len,BSP_EE24_TIMEOUT);
|
|
HAL_GPIO_WritePin(EEPROM_WC_GPIO_Port, EEPROM_WC_Pin, GPIO_PIN_SET); // high disables write;
|
|
osMutexRelease(ee24_lock);
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* Reads data from a specific partition in the EEPROM.
|
|
* This function is blocking for the operation to complete.
|
|
*
|
|
* @param[in] part The identifier of the partition to read from.
|
|
* Must be one of the BSP_EE24_PART_* constants.
|
|
* @param[out] Data A pointer to a buffer where the data will be stored.
|
|
* @param[in] LenBuffer The maximum number of bytes to be read from the partition.
|
|
* @return true if the operation was successful, false otherwise.
|
|
*/
|
|
bool BSP_EE24_PartRead(BSP_EE24_PartionEntry_e part, uint8_t *Data, size_t LenBuffer) {
|
|
// Check if the partition is valid and has data to read
|
|
if (!(part < __BSP_EE24_PART_MAX__ && PartionTable[part].len > 0)) {
|
|
return false;
|
|
}
|
|
|
|
// Read the Partion address
|
|
uint32_t Address = PartionTable[part].address;
|
|
|
|
// Calculate the length to be read
|
|
uint32_t Len = 0;
|
|
if (PartionTable[part].len < LenBuffer) {
|
|
Len = PartionTable[part].len;
|
|
} else {
|
|
Len = LenBuffer;
|
|
}
|
|
|
|
return BSP_EE24_Read(Address,Data,Len);
|
|
|
|
}
|
|
|
|
/**
|
|
* Writes data to a specific partition in the EEPROM.
|
|
* This function is blocking for the operation to complete.
|
|
*
|
|
* @param[in] part The identifier of the partition to write to.
|
|
* Must be one of the BSP_EE24_PART_* constants.
|
|
* @param[out] Data A pointer to a buffer containing the data to be written.
|
|
* @param[in] LenBuffer The maximum number of bytes to be written to the partition.
|
|
* @return true if the operation was successful, false otherwise.
|
|
*/
|
|
bool BSP_EE24_PartWrite(BSP_EE24_PartionEntry_e part, uint8_t *Data, size_t LenBuffer) {
|
|
// Check if the partition is valid and has data to read
|
|
if (!(part < __BSP_EE24_PART_MAX__ && PartionTable[part].len > 0)) {
|
|
return false;
|
|
}
|
|
|
|
// Read the Partion address
|
|
uint32_t Address = PartionTable[part].address;
|
|
|
|
// Calculate the length to be read
|
|
uint32_t Len = 0;
|
|
if (PartionTable[part].len < LenBuffer) {
|
|
Len = PartionTable[part].len;
|
|
} else {
|
|
Len = LenBuffer;
|
|
}
|
|
|
|
return BSP_EE24_Write(Address,Data,Len);
|
|
}
|
|
|
|
static inline size_t MIN_MEM(size_t a, size_t b) { return((a) < (b) ? a : b); }
|
|
|
|
|
|
/**
|
|
* Clear a new or undefined eeprom
|
|
*/
|
|
void BSP_EE24_FullClear() {
|
|
size_t len = 0;
|
|
for (int i = 1; i < __BSP_EE24_PART_MAX__; i++) {
|
|
len += PartionTable[i].len;
|
|
}
|
|
|
|
BSP_EE24_TableHeader header = {
|
|
.version = PartionTableVersion,
|
|
.used_len = len,
|
|
.reserved = {0},
|
|
};
|
|
|
|
// write header
|
|
BSP_EE24_PartWrite(BSP_EE24_PART_HEAD_PARTION, (uint8_t*)&header, sizeof(header));
|
|
|
|
// Calculate the start address and length of the clear operation
|
|
uint32_t clear_start = PartionTable[BSP_EE24_PART_HEAD_PARTION].address + PartionTable[BSP_EE24_PART_HEAD_PARTION].len;
|
|
uint32_t clear_len = header.used_len - PartionTable[BSP_EE24_PART_HEAD_PARTION].len;
|
|
|
|
// Use a 16-byte buffer to perform the write operation in chunks of 16 bytes
|
|
uint8_t clear_buffer[16] = {0};
|
|
|
|
while (clear_start < header.used_len) {
|
|
size_t chunk_size = MIN_MEM(clear_len, sizeof(clear_buffer));
|
|
BSP_EE24_Write(clear_start, clear_buffer, chunk_size);
|
|
clear_start += chunk_size;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* migrate form diffrent versions of the eeprom
|
|
*/
|
|
void BSP_EE24_TableMigrate(uint32_t ee_version) {
|
|
|
|
if(ee_version == PartionTableVersion) {
|
|
// current fw version, do nothing
|
|
return;
|
|
}
|
|
|
|
switch (ee_version)
|
|
{
|
|
|
|
default: // undefined write zeros.
|
|
BSP_EE24_FullClear();
|
|
break;
|
|
}
|
|
} |