1029 lines
25 KiB
C++
1029 lines
25 KiB
C++
/***********************************************************
|
|
Author: Bernard Borredon
|
|
Version: 1.3
|
|
- Correct write(uint32_t address, int8_t data[], uint32_t length) for eeprom >= T24C32.
|
|
Tested with 24C02, 24C08, 24C16, 24C64, 24C256, 24C512, 24C1025 on LPC1768 (mbed online and µVision V5.16a).
|
|
- Correct main test.
|
|
|
|
Date : 12 decembre 2013
|
|
Version: 1.2
|
|
- Update api documentation
|
|
|
|
Date: 11 december 2013
|
|
Version: 1.1
|
|
- Change address parameter size form uint16_t to uint32_t (error for eeprom > 24C256).
|
|
- Change size parameter size from uint16_t to uint32_t (error for eeprom > 24C256).
|
|
- Correct a bug in function write(uint32_t address, int8_t data[], uint32_t length) :
|
|
last step must be done only if it remain datas to send.
|
|
- Add function getName.
|
|
- Add function clear.
|
|
- Initialize _name array.
|
|
|
|
Date: 27 december 2011
|
|
Version: 1.0
|
|
|
|
************************************************************/
|
|
#include "eeprom.h"
|
|
|
|
#define BIT_SET(x, n) (x=x | (0x01<<n))
|
|
#define BIT_TEST(x, n) (x & (0x01<<n))
|
|
#define BIT_CLEAR(x, n) (x=x & ~(0x01<<n))
|
|
|
|
const char *const EEPROM::_name[] = {"24C01", "24C02", "24C04", "24C08", "24C16", "24C32",
|
|
"24C64", "24C128", "24C256", "24C512", "24C1024", "24C1025"};
|
|
|
|
/**
|
|
* EEPROM(PinName sda, PinName scl, uint8_t address, TypeEeprom type) : _i2c(sda, scl)
|
|
*
|
|
* Constructor, initialize the eeprom on i2c interface.
|
|
* @param sda sda i2c pin (PinName)
|
|
* @param scl scl i2c pin (PinName)
|
|
* @param address eeprom address, according to eeprom type (uint8_t)
|
|
* @param type eeprom type (TypeEeprom)
|
|
* @return none
|
|
*/
|
|
EEPROM::EEPROM(PinName sda, PinName scl, uint8_t address, TypeEeprom type) : _i2c(sda, scl) {
|
|
|
|
_errnum = EEPROM_NoError;
|
|
_type = type;
|
|
|
|
// Check address range
|
|
_address = static_cast<int>(address);
|
|
switch (type) {
|
|
case T24C01 :
|
|
case T24C02 : {
|
|
if (address > 7U) {
|
|
_errnum = EEPROM_BadAddress;
|
|
}
|
|
_address = _address << 1;
|
|
_page_write = 8U;
|
|
_page_number = 1U;
|
|
}
|
|
break;
|
|
case T24C04 : {
|
|
if (address > 7U) {
|
|
_errnum = EEPROM_BadAddress;
|
|
}
|
|
_address = (_address & 0xFE) << 1;
|
|
_page_write = 16U;
|
|
_page_number = 2U;
|
|
}
|
|
break;
|
|
case T24C08 : {
|
|
if (address > 7U) {
|
|
_errnum = EEPROM_BadAddress;
|
|
}
|
|
_address = (_address & 0xFC) << 1;
|
|
_page_write = 16U;
|
|
_page_number = 4U;
|
|
}
|
|
break;
|
|
case T24C16 : {
|
|
_address = 0;
|
|
_page_write = 16U;
|
|
_page_number = 8U;
|
|
}
|
|
break;
|
|
case T24C32 :
|
|
case T24C64 : {
|
|
if (address > 7U) {
|
|
_errnum = EEPROM_BadAddress;
|
|
}
|
|
_address = _address << 1;
|
|
_page_write = 32U;
|
|
_page_number = 1U;
|
|
}
|
|
break;
|
|
case T24C128 :
|
|
case T24C256 : {
|
|
if (address > 3U) {
|
|
_errnum = EEPROM_BadAddress;
|
|
}
|
|
_address = _address << 1;
|
|
_page_write = 64U;
|
|
_page_number = 1U;
|
|
}
|
|
break;
|
|
case T24C512 : {
|
|
if (address > 3U) {
|
|
_errnum = EEPROM_BadAddress;
|
|
}
|
|
_address = _address << 1;
|
|
_page_write = 128U;
|
|
_page_number = 1U;
|
|
}
|
|
break;
|
|
case T24C1024 : {
|
|
if (address > 7U) {
|
|
_errnum = EEPROM_BadAddress;
|
|
}
|
|
_address = (_address & 0xFE) << 1;
|
|
_page_write = 128U;
|
|
_page_number = 2U;
|
|
}
|
|
break;
|
|
case T24C1025 : {
|
|
if (address > 3U) {
|
|
_errnum = EEPROM_BadAddress;
|
|
}
|
|
_address = _address << 1;
|
|
_page_write = 128U;
|
|
_page_number = 2U;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Size in bytes
|
|
_size = _type;
|
|
if (_type == T24C1025) { _size = T24C1024; }
|
|
|
|
// Set I2C frequency
|
|
_i2c.frequency(400'000);
|
|
|
|
}
|
|
|
|
/**
|
|
* void write(uint32_t address, int8_t data)
|
|
*
|
|
* Write byte
|
|
* @param address start address (uint32_t)
|
|
* @param data byte to write (int8_t)
|
|
* @return none
|
|
*/
|
|
void EEPROM::write(uint32_t address, int8_t data) {
|
|
uint8_t page;
|
|
uint8_t addr;
|
|
uint8_t cmd[3];
|
|
int len;
|
|
int ack;
|
|
|
|
// Check error
|
|
if (_errnum) { return; }
|
|
|
|
// Check address
|
|
if (!checkAddress(address)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
// Compute page number
|
|
page = 0U;
|
|
if (_type < T24C32) { page = static_cast<uint8_t> (address / 256U); }
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address | (page << 1);
|
|
|
|
if (_type < T24C32) {
|
|
len = 2;
|
|
|
|
// Word address
|
|
cmd[0] = static_cast<uint8_t> (address - page * 256U);
|
|
|
|
// Data
|
|
cmd[1] = static_cast<uint8_t> (data);
|
|
} else {
|
|
len = 3;
|
|
|
|
// First word address (MSB)
|
|
cmd[0] = static_cast<uint8_t> (address >> 8);
|
|
|
|
// Second word address (LSB)
|
|
cmd[1] = static_cast<uint8_t> (address);
|
|
|
|
// Data
|
|
cmd[2] = static_cast<uint8_t> (data);
|
|
}
|
|
|
|
ack = _i2c.write(static_cast<int> (addr), reinterpret_cast<char *> (cmd), len);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
|
|
}
|
|
|
|
/**
|
|
* void write(uint32_t address, int8_t data[], uint32_t length)
|
|
*
|
|
* Write array of bytes (use the page mode)
|
|
* @param address start address (uint32_t)
|
|
* @param data bytes array to write (int8_t[])
|
|
* @param size number of bytes to write (uint32_t)
|
|
* @return none
|
|
*/
|
|
void EEPROM::write(uint32_t address, const int8_t data[], uint32_t length) {
|
|
uint8_t page;
|
|
uint8_t addr = 0U;
|
|
uint8_t blocs;
|
|
uint8_t remain;
|
|
uint8_t fpart;
|
|
uint8_t lpart;
|
|
uint8_t i;
|
|
uint8_t j;
|
|
uint8_t ind;
|
|
uint8_t cmd[129];
|
|
int ack;
|
|
|
|
// Check error
|
|
if (_errnum) { return; }
|
|
|
|
// Check address
|
|
if (!checkAddress(address)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
// Check length
|
|
if (!checkAddress(address + length - 1U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
// Compute blocs numbers
|
|
blocs = length / _page_write;
|
|
|
|
// Compute remaining bytes
|
|
remain = length - blocs * _page_write;
|
|
|
|
for (i = 0U; i < blocs; i++) {
|
|
// Compute page number
|
|
page = 0U;
|
|
if (_type < T24C32)
|
|
page = static_cast<uint8_t> (address / 256U);
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address | (page << 1);
|
|
|
|
if (_type < T24C32) {
|
|
// Word address
|
|
cmd[0] = static_cast<uint8_t> (address - page * 256U);
|
|
|
|
if ((uint8_t) ((address + _page_write) / 256U) == page) { // Data fit in the same page
|
|
// Add data
|
|
for (j = 0U; j < _page_write; j++)
|
|
cmd[j + 1] = (uint8_t) data[i * _page_write + j];
|
|
|
|
// Write data
|
|
ack = _i2c.write((int) addr, (char *) cmd, _page_write + 1);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
|
|
// Increment address
|
|
address += _page_write;
|
|
} else { // Data on 2 pages. We must split the write
|
|
// Number of bytes in current page
|
|
fpart = (page + 1U) * 256U - address;
|
|
|
|
// Add data for current page
|
|
for (j = 0U; j < fpart; j++)
|
|
cmd[j + 1] = (uint8_t) data[i * _page_write + j];
|
|
|
|
// Write data for current page
|
|
ack = _i2c.write((int) addr, (char *) cmd, fpart + 1);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
|
|
// Increment address
|
|
address += fpart;
|
|
|
|
if (page < _page_number - 1) {
|
|
// Increment page
|
|
page++;
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address | (page << 1);
|
|
|
|
// Word address
|
|
cmd[0] = (uint8_t) (address - page * 256U);
|
|
|
|
// Data index
|
|
ind = i * _page_write + fpart;
|
|
|
|
// Number of bytes in next page
|
|
lpart = _page_write - fpart;
|
|
|
|
// Add data for next page
|
|
for (j = 0U; j < lpart; j++)
|
|
cmd[j + 1] = (uint8_t) data[ind + j];
|
|
|
|
// Write data for next page
|
|
ack = _i2c.write((int) addr, (char *) cmd, lpart + 1);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
|
|
// Increment address
|
|
address += lpart;
|
|
}
|
|
}
|
|
} else {
|
|
// First word address (MSB)
|
|
cmd[0] = (uint8_t) (address >> 8);
|
|
|
|
// Second word address (LSB)
|
|
cmd[1] = (uint8_t) address;
|
|
|
|
// Add data
|
|
for (j = 0U; j < _page_write; j++)
|
|
cmd[j + 2] = (uint8_t) data[i * _page_write + j];
|
|
|
|
// Write data
|
|
ack = _i2c.write((int) addr, (char *) cmd, _page_write + 2);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
|
|
// Increment address
|
|
address += _page_write;
|
|
}
|
|
}
|
|
|
|
if (remain) {
|
|
// Compute page number
|
|
page = 0U;
|
|
if (_type < T24C32)
|
|
page = (uint8_t) (address / 256U);
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address | (page << 1);
|
|
|
|
if (_type < T24C32) {
|
|
// Word address
|
|
cmd[0] = (uint8_t) (address - page * 256U);
|
|
|
|
if ((uint8_t) ((address + remain) / 256U) == page) { // Data fit in the same page
|
|
// Add data for the current page
|
|
for (j = 0U; j < remain; j++)
|
|
cmd[j + 1] = (uint8_t) data[blocs * _page_write + j];
|
|
|
|
// Write data for the current page
|
|
ack = _i2c.write((int) addr, (char *) cmd, remain + 1);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
} else { // Data on 2 pages. We must split the write
|
|
// Number of bytes in current page
|
|
fpart = (page + 1) * 256U - address;
|
|
|
|
// Add data for current page
|
|
for (j = 0U; j < fpart; j++)
|
|
cmd[j + 1] = (uint8_t) data[blocs * _page_write + j];
|
|
|
|
// Write data for current page
|
|
ack = _i2c.write((int) addr, (char *) cmd, fpart + 1);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
|
|
// Increment address
|
|
address += fpart;
|
|
|
|
if (page < _page_number - 1) {
|
|
// Increment page
|
|
page++;
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address | (page << 1);
|
|
|
|
// Word address
|
|
cmd[0] = (uint8_t) (address - page * 256U);
|
|
|
|
// Data index
|
|
ind = blocs * _page_write + fpart;
|
|
|
|
// Number of bytes in next page
|
|
lpart = remain - fpart;
|
|
|
|
// Add data for next page
|
|
for (j = 0U; j < lpart; j++)
|
|
cmd[j + 1] = (uint8_t) data[ind + j];
|
|
|
|
// Write data for next page
|
|
ack = _i2c.write((int) addr, (char *) cmd, lpart + 1);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
}
|
|
}
|
|
} else {
|
|
// Fist word address (MSB)
|
|
cmd[0] = (uint8_t) (address >> 8);
|
|
|
|
// Second word address (LSB)
|
|
cmd[1] = (uint8_t) address;
|
|
|
|
// Add data for the current page
|
|
for (j = 0U; j < remain; j++)
|
|
cmd[j + 2] = (uint8_t) data[blocs * _page_write + j];
|
|
|
|
// Write data for the current page
|
|
ack = _i2c.write((int) addr, (char *) cmd, remain + 2);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Wait end of write
|
|
ready();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* void write(uint32_t address, int16_t data)
|
|
*
|
|
* Write short
|
|
* @param address start address (uint32_t)
|
|
* @param data short to write (int16_t)
|
|
* @return none
|
|
*/
|
|
void EEPROM::write(uint32_t address, int16_t data) {
|
|
int8_t cmd[2];
|
|
|
|
// Check error
|
|
if (_errnum)
|
|
return;
|
|
|
|
// Check address
|
|
if (!checkAddress(address + 1U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
(void) memcpy(cmd, &data, 2U);
|
|
|
|
write(address, cmd, 2U);
|
|
|
|
}
|
|
|
|
/**
|
|
* void write(uint32_t address, int32_t data)
|
|
*
|
|
* Write long
|
|
* @param address start address (uint32_t)
|
|
* @param data long to write (int32_t)
|
|
* @return none
|
|
*/
|
|
void EEPROM::write(uint32_t address, int32_t data) {
|
|
int8_t cmd[4];
|
|
|
|
// Check error
|
|
if (_errnum)
|
|
return;
|
|
|
|
// Check address
|
|
if (!checkAddress(address + 3U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
(void) memcpy(cmd, &data, 4U);
|
|
|
|
write(address, cmd, 4U);
|
|
|
|
}
|
|
|
|
/**
|
|
* void write(uint32_t address, float data)
|
|
*
|
|
* Write float
|
|
* @param address start address (uint32_t)
|
|
* @param data float to write (float)
|
|
* @return none
|
|
*/
|
|
void EEPROM::write(uint32_t address, float data) {
|
|
int8_t cmd[4];
|
|
|
|
// Check error
|
|
if (_errnum)
|
|
return;
|
|
|
|
// Check address
|
|
if (!checkAddress(address + 3U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
(void) memcpy(cmd, &data, 4);
|
|
|
|
write(address, cmd, 4U);
|
|
|
|
}
|
|
|
|
/**
|
|
* void write(uint32_t address, void *data, uint32_t size)
|
|
*
|
|
* Write anything (use the page write mode)
|
|
* @param address start address (uint32_t)
|
|
* @param data data to write (void *)
|
|
* @param size number of bytes to write (uint32_t)
|
|
* @return none
|
|
*/
|
|
void EEPROM::write(uint32_t address, void *data, uint32_t size) {
|
|
int8_t *cmd = nullptr;
|
|
|
|
// Check error
|
|
if (_errnum)
|
|
return;
|
|
|
|
// Check address
|
|
if (!checkAddress(address + size - 1U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
cmd = (int8_t *) malloc(size);
|
|
if (cmd == nullptr) {
|
|
_errnum = EEPROM_MallocError;
|
|
return;
|
|
}
|
|
|
|
(void) memcpy(cmd, (uint8_t *) data, size);
|
|
|
|
write(address, cmd, size);
|
|
|
|
free(cmd);
|
|
|
|
}
|
|
|
|
/**
|
|
* void read(uint32_t address, int8_t& data)
|
|
*
|
|
* Random read byte
|
|
* @param address start address (uint32_t)
|
|
* @param data byte to read (int8_t&)
|
|
* @return none
|
|
*/
|
|
void EEPROM::read(uint32_t address, int8_t &data) {
|
|
uint8_t page;
|
|
uint8_t addr;
|
|
uint8_t cmd[2];
|
|
uint8_t len;
|
|
int ack;
|
|
|
|
// Check error
|
|
if (_errnum)
|
|
return;
|
|
|
|
// Check address
|
|
if (!checkAddress(address)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
// Compute page number
|
|
page = 0U;
|
|
if (_type < T24C32) { page = static_cast<uint8_t> (address / 256U); }
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address | (page << 1);
|
|
|
|
if (_type < T24C32) {
|
|
len = 1U;
|
|
|
|
// Word address
|
|
cmd[0] = static_cast<uint8_t> (address - page * 256U);
|
|
} else {
|
|
len = 2U;
|
|
|
|
// First word address (MSB)
|
|
cmd[0] = static_cast<uint8_t> (address >> 8);
|
|
|
|
// Second word address (LSB)
|
|
cmd[1] = static_cast<uint8_t> (address);
|
|
}
|
|
|
|
// Write command
|
|
ack = _i2c.write(static_cast<int> (addr), reinterpret_cast<char *> (cmd), len, true);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Read data
|
|
ack = _i2c.read(static_cast<int>(addr), reinterpret_cast<char *>(&data), sizeof(data));
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* void read(uint32_t address, int8_t *data, uint32_t size)
|
|
*
|
|
* Sequential read byte
|
|
* @param address start address (uint32_t)
|
|
* @param data bytes array to read (int8_t[]&)
|
|
* @param size number of bytes to read (uint32_t)
|
|
* @return none
|
|
*/
|
|
void EEPROM::read(uint32_t address, int8_t *data, uint32_t size) {
|
|
uint8_t page;
|
|
uint8_t addr;
|
|
uint8_t cmd[2];
|
|
uint8_t len;
|
|
int ack;
|
|
|
|
// Check error
|
|
if (_errnum)
|
|
return;
|
|
|
|
// Check address
|
|
if (!checkAddress(address)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
// Check size
|
|
if (!checkAddress(address + size - 1U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
// Compute page number
|
|
page = 0U;
|
|
if (_type < T24C32) { page = static_cast<uint8_t> (address / 256U); }
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address | (page << 1U);
|
|
|
|
if (_type < T24C32) {
|
|
len = 1U;
|
|
|
|
// Word address
|
|
cmd[0] = static_cast<uint8_t> (address - page * 256U);
|
|
} else {
|
|
len = 2U;
|
|
|
|
// First word address (MSB)
|
|
cmd[0] = static_cast<uint8_t> (address >> 8);
|
|
|
|
// Second word address (LSB)
|
|
cmd[1] = static_cast<uint8_t> (address);
|
|
}
|
|
|
|
// Write command
|
|
ack = _i2c.write(static_cast<int>(addr), reinterpret_cast<char *> (cmd), len, true);
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
// Sequential read
|
|
ack = _i2c.read(static_cast<int>(addr), reinterpret_cast<char *>(data), static_cast<int>(size));
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* void read(int8_t& data)
|
|
*
|
|
* Current address read byte
|
|
* @param data byte to read (int8_t&)
|
|
* @return none
|
|
*/
|
|
void EEPROM::read(int8_t &data) {
|
|
uint8_t addr;
|
|
int ack;
|
|
|
|
// Check error
|
|
if (_errnum)
|
|
return;
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address;
|
|
|
|
// Read data
|
|
ack = _i2c.read(static_cast<int>(addr), reinterpret_cast<char *>(&data), sizeof(data));
|
|
if (ack != 0) {
|
|
_errnum = EEPROM_I2cError;
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* void read(uint32_t address, int16_t& data)
|
|
*
|
|
* Random read short
|
|
* @param address start address (uint32_t)
|
|
* @param data short to read (int16_t&)
|
|
* @return none
|
|
*/
|
|
void EEPROM::read(uint32_t address, int16_t &data) {
|
|
int8_t cmd[2];
|
|
|
|
// Check error
|
|
if (_errnum)
|
|
return;
|
|
|
|
// Check address
|
|
if (!checkAddress(address + 1U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
read(address, cmd, 2U);
|
|
|
|
(void) memcpy(&data, cmd, 2);
|
|
|
|
}
|
|
|
|
/**
|
|
* void read(uint32_t address, int32_t& data)
|
|
*
|
|
* Random read long
|
|
* @param address start address (uint32_t)
|
|
* @param data long to read (int32_t&)
|
|
* @return none
|
|
*/
|
|
void EEPROM::read(uint32_t address, int32_t &data) {
|
|
int8_t cmd[4];
|
|
|
|
// Check error
|
|
if (_errnum) { return; }
|
|
|
|
// Check address
|
|
if (!checkAddress(address + 3U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
read(address, cmd, 4U);
|
|
|
|
(void) memcpy(&data, cmd, 4U);
|
|
|
|
}
|
|
|
|
/**
|
|
* void read(uint32_t address, float& data)
|
|
*
|
|
* Random read float
|
|
* @param address start address (uint32_t)
|
|
* @param data float to read (float&)
|
|
* @return none
|
|
*/
|
|
void EEPROM::read(uint32_t address, float &data) {
|
|
int8_t cmd[4];
|
|
|
|
// Check error
|
|
if (_errnum) { return; }
|
|
|
|
// Check address
|
|
if (!checkAddress(address + 3U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
read(address, cmd, 4U);
|
|
|
|
(void) memcpy(&data, cmd, 4U);
|
|
|
|
}
|
|
|
|
/**
|
|
* void read(uint32_t address, void *data, uint32_t size)
|
|
*
|
|
* Random read anything
|
|
* @param address start address (uint32_t)
|
|
* @param data data to read (void *)
|
|
* @param size number of bytes to read (uint32_t)
|
|
* @return none
|
|
*/
|
|
void EEPROM::read(uint32_t address, void *data, uint32_t size) {
|
|
int8_t *cmd = nullptr;
|
|
|
|
// Check error
|
|
if (_errnum) { return; }
|
|
|
|
// Check address
|
|
if (!checkAddress(address + size - 1U)) {
|
|
_errnum = EEPROM_OutOfRange;
|
|
return;
|
|
}
|
|
|
|
cmd = reinterpret_cast<int8_t *>(malloc(size));
|
|
|
|
if (cmd == nullptr) {
|
|
_errnum = EEPROM_MallocError;
|
|
return;
|
|
}
|
|
|
|
read(address, reinterpret_cast<int8_t *> (cmd), size);
|
|
|
|
(void) memcpy(data, cmd, size);
|
|
|
|
free(cmd);
|
|
|
|
}
|
|
|
|
/**
|
|
* void clear(void)
|
|
*
|
|
* Clear eeprom (write with 0)
|
|
* @param none
|
|
* @return none
|
|
*/
|
|
void EEPROM::clear() {
|
|
int32_t data;
|
|
uint32_t i;
|
|
|
|
data = 0;
|
|
|
|
for (i = 0U; i < _size / 4U; i++) {
|
|
write(static_cast<uint32_t> (i * 4U), data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* void ready(void)
|
|
*
|
|
* Wait eeprom ready
|
|
* @param none
|
|
* @return none
|
|
*/
|
|
void EEPROM::ready() {
|
|
int ack;
|
|
uint8_t addr;
|
|
uint8_t cmd[2];
|
|
|
|
// Check error
|
|
if (_errnum) { return; }
|
|
|
|
// Device address
|
|
addr = EEPROM_Address | _address;
|
|
|
|
cmd[0] = 0U;
|
|
|
|
// Wait end of write
|
|
do {
|
|
ack = _i2c.write(static_cast<int>(addr), reinterpret_cast<char *> (cmd), 0);
|
|
ThisThread::sleep_for(1ms);
|
|
} while (ack != 0);
|
|
|
|
}
|
|
|
|
/**
|
|
* uint32_t getSize(void)
|
|
*
|
|
* Get eeprom size in bytes
|
|
* @param none
|
|
* @return size in bytes (uint32_t)
|
|
*/
|
|
uint32_t EEPROM::getSize() {
|
|
return (_size);
|
|
}
|
|
|
|
/**
|
|
* const char* getName(void)
|
|
*
|
|
* Get eeprom name
|
|
* @param none
|
|
* @return name (const char*)
|
|
*/
|
|
const char *EEPROM::getName() {
|
|
uint8_t i = 0U;
|
|
|
|
switch (_type) {
|
|
case T24C01 :
|
|
i = 0U;
|
|
break;
|
|
case T24C02 :
|
|
i = 1U;
|
|
break;
|
|
case T24C04 :
|
|
i = 2U;
|
|
break;
|
|
case T24C08 :
|
|
i = 3U;
|
|
break;
|
|
case T24C16 :
|
|
i = 4U;
|
|
break;
|
|
case T24C32 :
|
|
i = 5U;
|
|
break;
|
|
case T24C64 :
|
|
i = 6U;
|
|
break;
|
|
case T24C128 :
|
|
i = 7U;
|
|
break;
|
|
case T24C256 :
|
|
i = 8U;
|
|
break;
|
|
case T24C512 :
|
|
i = 9U;
|
|
break;
|
|
case T24C1024 :
|
|
i = 10U;
|
|
break;
|
|
case T24C1025 :
|
|
i = 11U;
|
|
break;
|
|
}
|
|
|
|
return (_name[i]);
|
|
}
|
|
|
|
/**
|
|
* uint8_t getError(void)
|
|
*
|
|
* Get the current error number (EEPROM_NoError if no error)
|
|
* @param none
|
|
* @return none
|
|
*/
|
|
uint8_t EEPROM::getError() {
|
|
return (_errnum);
|
|
}
|
|
|
|
/**
|
|
* bool checkAddress(uint32_t address)
|
|
*
|
|
* Check if address is in the eeprom range address
|
|
* @param address address to check (uint32_t)
|
|
* @return true if in eeprom range, overwise false (bool)
|
|
*/
|
|
bool EEPROM::checkAddress(uint32_t address) {
|
|
bool ret = true;
|
|
|
|
switch (_type) {
|
|
case T24C01 :
|
|
if (address >= T24C01) { ret = false; }
|
|
break;
|
|
case T24C02 :
|
|
if (address >= T24C02) { ret = false; }
|
|
break;
|
|
case T24C04 :
|
|
if (address >= T24C04) { ret = false; }
|
|
break;
|
|
case T24C08 :
|
|
if (address >= T24C08) { ret = false; }
|
|
break;
|
|
case T24C16 :
|
|
if (address >= T24C16) { ret = false; }
|
|
break;
|
|
case T24C32 :
|
|
if (address >= T24C32) { ret = false; }
|
|
break;
|
|
case T24C64 :
|
|
if (address >= T24C64) { ret = false; }
|
|
break;
|
|
case T24C128 :
|
|
if (address >= T24C128) { ret = false; }
|
|
break;
|
|
case T24C256 :
|
|
if (address >= T24C256) { ret = false; }
|
|
break;
|
|
case T24C512 :
|
|
if (address >= T24C512) { ret = false; }
|
|
break;
|
|
case T24C1024 :
|
|
if (address >= T24C1024) { ret = false; }
|
|
break;
|
|
case T24C1025 :
|
|
if (address >= T24C1025 - 1) { ret = false; }
|
|
break;
|
|
}
|
|
|
|
return (ret);
|
|
}
|