In this above code writing data into eeprom and reading it.
Entering into EEPROM TEST manual for testing data write and read.
After running the eeprom for sometime paused the run and manually entered into EEPROM TEST value of the switch case is 8.
On there taken some structure using memset assigned the value of 0xaa wrote into EEPROM while reading back first 72 data's only getting correctly rest are filled with 0xff
likewise,
0x55 getting perfectly 0x00 getting perfectly actual data of structure getting some random value tried splitting the structure also still facing the same issue.
EEPROM size is 2MB
structure size is 156
Tried with the array and also got the same values.
kindly give some solution Pl. Thank you
/* Includes */
#include "MyMain.h"
/* Declaration of external global variables */
extern I2C_HandleTypeDef hi2c1;
extern uint32_t error_flag[];
extern uint32_t event_flag[];
extern CIR_BUF rs485_tx_cir_buf[];
extern CIR_BUF rs485_rx_cir_buf[];
extern uint8_t semaphore[]; // Semaphores for shared peripherals - SPI1, SPI3 & I2C1
// Structures being stored in EEPROM as individual bytes
extern uint8_t I2C1_tx_rdy;
extern uint8_t I2C1_rx_rdy;
extern VP_CRED_RW_STR login_cred_str[];
extern VP_CAL_RD_STR cal_par_str; // Backed up in EEPROM
extern CAL_PT_STR cal_pt_str[]; // Backed up in EEPROM
extern VP_PARAM_RW_STR vp_param_rw_str; // Backed up in EEPROM
extern VP_CAL_RD_STR cal_par_str; // Backed up in EEPROM
extern COMM_PAR comm_par; // Communication parameters to be stored in EEPROM
/* Declaration of global variables */
EEPROM_INFO eeprom_info;
CIR_BUF eeprom_rd_cir_buf[EEPROM_CIR_BUF_DEPTH];
CIR_BUF eeprom_wr_cir_buf[EEPROM_CIR_BUF_DEPTH];
uint8_t I2C1_buf[I2C_TXN_PAGE_SIZE];
uint16_t i2c_err_sts;
const uint8_t eeprom_seg_addr[] = {
EEPROM_SEG1_ADDR,
EEPROM_SEG2_ADDR,
EEPROM_SEG3_ADDR,
EEPROM_SEG4_ADDR,
};
/* Declaration of static local variables */
/* Declaration of local functions */
/*
* **************************************
* **************************************
* Function Declarations start here
* **************************************
* **************************************
*/
/*
* *****************************************************************************
* Function name: I2C1_TxCallback
* Created by :
* Date:
* Description:
* This is the call-back function of I2C1 transmit interrupt events
* Parameters:
* Input : Handle to I2C1 structure
* Return : None
* Note:
*
* *****************************************************************************
*/
void I2C1_TxCallback(I2C_HandleTypeDef *hi2c)
{
I2C1_tx_rdy = 1;
}
/*
* *****************************************************************************
* Function name: I2C1_RxCallback
* Created by :
* Date:
* Description:
* This is the call-back function of I2C1 receive interrupt events
* Parameters:
* Input : Handle to I2C1 structure
* Return : None
* Note:
*
* *****************************************************************************
*/
void I2C1_RxCallback(I2C_HandleTypeDef *hi2c)
{
I2C1_rx_rdy = 1;
}
/*
* *****************************************************************************
* Function name: I2C1_ErrCallback
* Created by :
* Date:
* Description:
* This is the call-back function of I2C1 error interrupt events
* Parameters:
* Input : Handle to I2C1 structure
* Return : None
* Note:
*
* *****************************************************************************
*/
void I2C1_ErrCallback(I2C_HandleTypeDef *hi2c)
{
i2c_err_sts = hi2c->Instance->ISR;
}
/*
* *****************************************************************************
* Function name: EEPROM_init()
* Created by:
* Date:
* Description:
* This is the function to initialize the EEPROM structure.
* Parameters:
* Input: None
* Return: None
* Note:
*
* *****************************************************************************
*/
void EEPROM_init(void)
{
eeprom_info = EEPROM_INFO_DEFAULT;
if ((HAL_I2C_RegisterCallback(&hi2c1, HAL_I2C_MASTER_TX_COMPLETE_CB_ID, I2C1_TxCallback) == HAL_OK) &&
(HAL_I2C_RegisterCallback(&hi2c1, HAL_I2C_MASTER_RX_COMPLETE_CB_ID, I2C1_RxCallback) == HAL_OK) &&
(HAL_I2C_RegisterCallback(&hi2c1, HAL_I2C_ERROR_CB_ID, I2C1_ErrCallback) == HAL_OK))
{
// Callback functions initialized
}
}
/*
* *****************************************************************************
* Function name: EEPROM_proc()
* Created by:
* Date:
* Description:
* This is the FSM function to transfer the data between MCU and the EEPROM memory over I2C bus.
* Parameters:
* Input: pointer to data buffer, size of the data block and mode of operation on the data
* Return: Status (0: SUCCESS, 1:FAILED)
* Note:
*
* *****************************************************************************
*/
void EEPROM_proc(void)
{
static uint32_t curr_bytes = 0;
static uint32_t addr, size, k[64]={0};
static uint32_t i , j;
static uint8_t test_in_prog = 0, test_state = 0;
uint8_t *ptr;
uint16_t offset ;
switch(eeprom_info.state)
{
case EEPROM_POWERON:
// Read calibration data from EEPROM
if ((EEPROM_request(EEPROM_READ, (uint8_t*)&cal_par_str, (uint8_t*)EEPROM_ADDR_CALIB, sizeof(VP_CAL_RD_STR)) >= 0) &&
(EEPROM_request(EEPROM_READ, (uint8_t*)&login_cred_str, (uint8_t*)EEPROM_ADDR_UC, sizeof(VP_CRED_RW_STR)*(MAX_ADMIN_ACCOUNTS+MAX_USER_ACCOUNTS)) >= 0) &&
(EEPROM_request(EEPROM_READ, (uint8_t*)&vp_param_rw_str, (uint8_t*)EEPROM_ADDR_PARAM, sizeof(VP_PARAM_RW_STR)) >= 0) &&
(EEPROM_request(EEPROM_READ, (uint8_t*)&comm_par, (uint8_t*)EEPROM_ADDR_COMM, sizeof(COMM_PAR)) >= 0))
eeprom_info.state = EEPROM_STRT;
break;
case EEPROM_STRT:
if (semaphore[SEMAPHORE_I2C1] == 0)
{
// Check for read from EEPROM request by a calling function through the FIFO circular read buffer
for (i=0; ((i<EEPROM_CIR_BUF_DEPTH) && (eeprom_rd_cir_buf[i].state == BUF_EMPTY)); i++);
if (i < EEPROM_CIR_BUF_DEPTH)
{
semaphore[SEMAPHORE_I2C1] = 1;
// Get the starting address (destination) of data buffer from first 4 locations of "eeprom_rd_cir_buf[i].buffer"
eeprom_info.data = (uint8_t*)((eeprom_rd_cir_buf[i].buffer[3] << 24) | (eeprom_rd_cir_buf[i].buffer[2] << 16) | (eeprom_rd_cir_buf[i].buffer[1] << 8) | eeprom_rd_cir_buf[i].buffer[0]);
// Get the starting address (source) of EEPROM from the next 4 locations of "eeprom_rd_cir_buf[i].buffer"
addr = (eeprom_rd_cir_buf[i].buffer[7] << 24) | (eeprom_rd_cir_buf[i].buffer[6] << 16) | (eeprom_rd_cir_buf[i].buffer[5] << 8) | eeprom_rd_cir_buf[i].buffer[4];
// Get the pay-load size from the next 4 locations of "eeprom_rd_cir_buf[i].buffer"
eeprom_info.size = (eeprom_rd_cir_buf[i].buffer[11] << 24) | (eeprom_rd_cir_buf[i].buffer[10] << 16) | (eeprom_rd_cir_buf[i].buffer[9] << 8) | eeprom_rd_cir_buf[i].buffer[8];
size = eeprom_info.size;
EEPROM_read(eeprom_info.data, addr, size);
eeprom_info.state = EEPROM_RX_STRT;
}
else
{
// Check for write into EEPROM request by a calling function through the FIFO circular read buffer
for (i=0; ((i<EEPROM_CIR_BUF_DEPTH) && (eeprom_wr_cir_buf[i].state == BUF_EMPTY)); i++);
if (i < EEPROM_CIR_BUF_DEPTH)
{
semaphore[SEMAPHORE_I2C1] = 1;
// Get the starting address (source) of data buffer from first 4 locations of "eeprom_wr_cir_buf.buffer"
eeprom_info.data = (uint8_t*)((eeprom_wr_cir_buf[i].buffer[3] << 24) | (eeprom_wr_cir_buf[i].buffer[2] << 16) | (eeprom_wr_cir_buf[i].buffer[1] << 8) | eeprom_wr_cir_buf[i].buffer[0]);
// Get the starting address (destination) of EEPROM from the next 4 locations of "eeprom_wr_cir_buf.buffer"
addr = (eeprom_wr_cir_buf[i].buffer[7] << 24) | (eeprom_wr_cir_buf[i].buffer[6] << 16) | (eeprom_wr_cir_buf[i].buffer[5] << 8) | eeprom_wr_cir_buf[i].buffer[4];
// Get the pay-load size from the next 4 locations of "eeprom_wr_cir_buf.buffer"
eeprom_info.size = (eeprom_wr_cir_buf[i].buffer[11] << 24) | (eeprom_wr_cir_buf[i].buffer[10] << 16) | (eeprom_wr_cir_buf[i].buffer[9] << 8) | eeprom_wr_cir_buf[i].buffer[8];
size = eeprom_info.size;
EEPROM_write(eeprom_info.data, addr, size);
eeprom_info.state = EEPROM_TX_STRT;
}
else
{
// Do nothing
} // End of "else" of "if (i < EEPROM_CIR_BUF_DEPTH)" for write
} // End of "else" of "if (i < EEPROM_CIR_BUF_DEPTH)" for read
} // End of "if (semaphore[SEMAPHORE_I2C1] == 0)"
break;
//////////////////
// EEPROM Reading
//////////////////
case EEPROM_RX_STRT:
if (size > I2C_TXN_PAGE_SIZE)
{
curr_bytes = I2C_TXN_PAGE_SIZE;
size -= I2C_TXN_PAGE_SIZE;
}
else
{
curr_bytes = size;
size = 0;
}
I2C1_rx_rdy = 1;
Set_delay(SW_TMR_I2C1, DLY_I2C_TIMEOUT, &eeprom_info.dly_flag);
if (HAL_I2C_Master_Receive(&hi2c1, eeprom_info.dev_sel_code, \
eeprom_info.data, curr_bytes, 10) == HAL_OK)
{
// Initiate receive process
eeprom_info.state = EEPROM_RX_DONE;
}
else
{
// Failed to initiate receive process
error_flag[0] |= ERR_EEPROM_TXN;
semaphore[SEMAPHORE_I2C1] = 0;
eeprom_info.state = EEPROM_ERR;
}
break;
case EEPROM_RX_DONE:
if (I2C1_rx_rdy)
{
// Read successfully
if (size == 0)
{
// Successfully read the whole memory content
semaphore[SEMAPHORE_I2C1] = 0;
error_flag[0] &= ~ERR_I2C_TIMEOUT;
error_flag[0] &= ~ERR_EEPROM_TXN;
eeprom_rd_cir_buf[i].state = BUF_EMPTY;
eeprom_info.state = EEPROM_RX_READY;
}
else
{
addr += I2C_TXN_PAGE_SIZE;
eeprom_info.data += I2C_TXN_PAGE_SIZE;
eeprom_info.dev_sel_code += I2C_TXN_PAGE_SIZE;
eeprom_info.state = EEPROM_RX_STRT;
}
}
else if (eeprom_info.dly_flag)
{
// Failed to read from EEPROM
test_state = 0;
error_flag[0] |= ERR_EEPROM_TXN;
semaphore[SEMAPHORE_I2C1] = 0;
eeprom_info.state = EEPROM_ERR;
}
else
{
// Do nothing. Just wait
}
break;
case EEPROM_RX_READY:
if (test_in_prog)
{
// Test mode
eeprom_info.state = EEPROM_TEST;
}
else
{
// Run mode - Check if default values are applicable to "cal_par_str" structure
ptr = (uint8_t*)&cal_par_str;
for (offset=0; ((offset<sizeof(VP_CAL_RD_STR)) && ((*ptr == 0x00) || (*ptr == 0xff))); offset++, ptr++)
{
// Continue
}
if (offset == sizeof(VP_CAL_RD_STR))
{
cal_par_str = CAL_PAR_DEFAULT;
}
// Check if default values are applicable to "login_cred_str" structure
ptr = (uint8_t*)login_cred_str;
j = sizeof(VP_CRED_RW_STR)*(MAX_ADMIN_ACCOUNTS+MAX_USER_ACCOUNTS);
for (offset=0; ((offset<j) && ((*ptr == 0x00) || (*ptr == 0xff))); offset++, ptr++)
{
// Continue
}
if (offset == j)
{
for (j=0; j<(MAX_ADMIN_ACCOUNTS+MAX_USER_ACCOUNTS); j++)
{
login_cred_str[j] = LOGIN_CRED_DEFAULT;
}
}
// Check if default values are applicable to "vp_param_rw_str" structure
ptr = (uint8_t*)&vp_param_rw_str;
for (offset=0; ((offset<sizeof(VP_PARAM_RW_STR)) && ((*ptr == 0x00) || (*ptr == 0xff))); offset++, ptr++)
{
// Continue
}
if (offset == sizeof(vp_param_rw_str))
{
vp_param_rw_str = VP_PARAM_DEFAULT;
}
// Check if default values are applicable to "comm_par" structure
ptr = (uint8_t*)&comm_par;
for (offset=0; ((offset<sizeof(COMM_PAR)) && ((*ptr == 0x00) || (*ptr == 0xff))); offset++, ptr++)
{
// Continue
}
if (offset == sizeof(COMM_PAR))
{
Def_comm_par();
}
eeprom_info.state = EEPROM_STRT;
}
break;
//////////////////
// EEPROM WRITING
//////////////////
case EEPROM_TX_STRT:
if (size > I2C_TXN_PAGE_SIZE)
{
curr_bytes = I2C_TXN_PAGE_SIZE;
size -= I2C_TXN_PAGE_SIZE;
}
else
{
curr_bytes = size;
size = 0;
}
I2C1_tx_rdy = 1;
Set_delay(SW_TMR_I2C1, DLY_I2C_TIMEOUT, &eeprom_info.dly_flag);
if (HAL_I2C_Master_Transmit(&hi2c1, EEPROM_SEG1_ADDR | (uint8_t)(eeprom_info.seg << 1) | I2C_WR, \
eeprom_info.data, curr_bytes, 10) == HAL_OK)
{
// Initiate transmit process
eeprom_info.state = EEPROM_TX_DONE;
}
else
{
// Failed to initiate transmit process
error_flag[0] |= ERR_EEPROM_TXN;
semaphore[SEMAPHORE_I2C1] = 0;
eeprom_info.state = EEPROM_ERR;
}
break;
case EEPROM_TX_DONE:
if ((I2C1_tx_rdy) && (eeprom_info.dly_flag))
{
// Wrote successfully and waited for at least 10ms to complete the internal write operation
if (size == 0)
{
// Successfully wrote the whole memory content into EEPROM
semaphore[SEMAPHORE_I2C1] = 0;
error_flag[0] &= ~ERR_EEPROM_TXN;
error_flag[0] &= ~ERR_I2C_TIMEOUT;
eeprom_wr_cir_buf[0].state = BUF_EMPTY;
if (eeprom_info.reset == 1)
{
// Restart processes that use these parameters
while (1)
{
// Wait here until the watch-dog resets the MCU
}
eeprom_info.reset = 0; // You will never hit this line...
}
else
{
if (test_in_prog == 0)
{
// Run mode
eeprom_info.state = EEPROM_TX_READY;
}
else
{
// Test mode
eeprom_info.state = EEPROM_TEST;
} // End of "else" of "if (test_in_prog == 0)"
} // End of "else" of "if (eeprom_info.reset == 1)"
} // End of "if (size == 0)"
else
{
addr += I2C_TXN_PAGE_SIZE;
eeprom_info.data += I2C_TXN_PAGE_SIZE;
eeprom_info.dev_sel_code += I2C_TXN_PAGE_SIZE;
eeprom_info.state = EEPROM_TX_STRT;
} // End of "else" of "if (size == 0)"
} // End of "if ((I2C1_tx_rdy) && (eeprom_info.dly_flag))"
else if (eeprom_info.dly_flag)
{
// Failed to write into the EEPROM
test_state = 0;
error_flag[0] |= ERR_EEPROM_TXN;
semaphore[SEMAPHORE_I2C1] = 0;
eeprom_info.state = EEPROM_ERR;
}
else
{
// Do nothing. Just wait
}
break;
case EEPROM_TX_READY:
eeprom_info.state = EEPROM_STRT;
break;
// Enter into this state manually. The logic will not get in here by itself under any conditions
case EEPROM_TEST:
// EEPROM WRITE operation
if (test_state == 0)
{
test_in_prog = 1;
eeprom_info.state = EEPROM_ERR;
ptr = (uint8_t*)&login_cred_str;
memset(ptr, 0xAA, sizeof(VP_CRED_RW_STR)*(MAX_ADMIN_ACCOUNTS+MAX_USER_ACCOUNTS));
if ((EEPROM_request(EEPROM_WRITE, (uint8_t*)&login_cred_str, (uint8_t*)EEPROM_ADDR_UC, sizeof(VP_CRED_RW_STR)*(MAX_ADMIN_ACCOUNTS+MAX_USER_ACCOUNTS)) >= 0))
{
eeprom_info.state = EEPROM_STRT;
test_state = 1;
}
}
// EEPROM READ operation
else if (test_state == 1)
{
ptr = (uint8_t*)&login_cred_str;
memset(ptr, 0xff, sizeof(VP_CRED_RW_STR)*(MAX_ADMIN_ACCOUNTS+MAX_USER_ACCOUNTS));
if ((EEPROM_request(EEPROM_READ, (uint8_t*)&login_cred_str, (uint8_t*)EEPROM_ADDR_UC, sizeof(VP_CRED_RW_STR)*(MAX_ADMIN_ACCOUNTS+MAX_USER_ACCOUNTS)) >= 0))
{
eeprom_info.state = EEPROM_STRT;
test_state = 2;
}
}
// EEPROM VERIFY operation
else // if (test_state == 2)
{
// Verify data read just now with the data written already
ptr = (uint8_t*)&login_cred_str;//&k
j = sizeof(VP_CRED_RW_STR)*(MAX_ADMIN_ACCOUNTS+MAX_USER_ACCOUNTS);
for (i=0; ((i<j) && (*(ptr+i) == 0x55)); i++)
{
j = j; // Continue
}
if (i == j)//eprom_info.size)
{
// EEPROM read/write test passed
vp_param_rw_str = VP_PARAM_DEFAULT;
eeprom_info.state = EEPROM_STRT;
}
else
{
// EEPROM read/write test failed
eeprom_info.state = EEPROM_ERR;
}
test_in_prog = 0; //TODO - Stop here in debug mode to verify EEPROM write and verify operations
test_state = 0;
}
break;
case EEPROM_ERR:
// Wait here until the calling function acknowledges status
break;
default:
eeprom_info.state = EEPROM_STRT;
break;
}
}
/*
* *****************************************************************************
* Function name: EEPROM_read()
* Created by:
* Date:
* Description:
* This is the function to start the transfer of data to MCU from the EEPROM memory over I2C bus.
* Parameters:
* Input: Pointer to data buffer in RAM (destination), starting address of EEPROM location & size of the data block
* Return: Status
* Note:
*
* *****************************************************************************
*/
uint8_t EEPROM_read(uint8_t *data, uint32_t addr, uint32_t size)
{
if (size > 0)
{
eeprom_info.data = data;
eeprom_info.seg = (size & 0x030000) >> 16; // Number of segments (max.4), each of size 64KB (Addr[17:16])
eeprom_info.size = (size & 0x03ffff); // Max size limited to 256KB size of the device
eeprom_info.strt_addr = (uint16_t)(addr & 0x0003ffff);
eeprom_info.dev_sel_code = (EEPROM_SEG1_ADDR | (eeprom_info.seg << 1) | I2C_RD); // Generate the device select code
return 1;
}
return 0;
}
/*
* *****************************************************************************
* Function name: EEPROM_write()
* Created by:
* Date:
* Description:
* This is the function to start transfer of data to EEPROM from the MCU memory over I2C bus.
* Parameters:
* Input: Pointer to data buffer in RAM (source), starting address of EEPROM location & size of the data block
* Return: Status
* Note:
*
* *****************************************************************************
*/
uint8_t EEPROM_write(uint8_t *data, uint32_t addr, uint32_t size)
{
if (size > 0)
{
eeprom_info.data = data;
eeprom_info.seg = (size & 0x030000) >> 16; // Number of segments (max.4), each of size 64KB
eeprom_info.size = (size & 0x03ffff); // Max size limited to 256KB size of the device
eeprom_info.strt_addr = (uint16_t)(addr & 0x0003ffff);
eeprom_info.dev_sel_code = (EEPROM_SEG1_ADDR | (eeprom_info.seg << 1) | I2C_WR); // Generate the device select code
return 1;
}
return 0;
}
/*
* *****************************************************************************
* Function name: EEPROM_request()
* Created by:
* Date:
* Description:
* This is the function that can be called from any other module and used to generate
* a request for an EEPROM operation - Read, Write or Erase.
* Parameters:
* Input: Request type, Source address, Destination address & size
* Return: Status: -1 - Declined, >=0 - Accepted with Circular buffer ID
* Note:
*
* *****************************************************************************
*/
int8_t EEPROM_request(EEPROM_REQ req, uint8_t *dbuf, uint8_t *ebuf, uint32_t size)
{
uint8_t i;
if (req == EEPROM_READ)
{
for (i=0; ((i<EEPROM_CIR_BUF_DEPTH) && (eeprom_rd_cir_buf[i].state == BUF_FULL)); i++);
if (i < EEPROM_CIR_BUF_DEPTH)
{
// Push the address of data buffer at first 4 locations
*((uint32_t*)eeprom_rd_cir_buf[i].buffer) = (uint32_t)dbuf;
// Push the starting address of EEPROM at next 4 locations
*((uint32_t*)eeprom_rd_cir_buf[i].buffer+1) = (uint32_t)ebuf;
// Push the pay-load size at next 4 locations
*((uint32_t*)eeprom_rd_cir_buf[i].buffer+2) = size;
eeprom_rd_cir_buf[i].size = 12;
eeprom_rd_cir_buf[i].state = BUF_FULL;
}
}
else if (req == EEPROM_WRITE)
{
for (i=0; ((i<EEPROM_CIR_BUF_DEPTH) && (eeprom_wr_cir_buf[i].state == BUF_FULL)); i++);
if (i < EEPROM_CIR_BUF_DEPTH)
{
// Push the address of data buffer at first 4 locations
*((uint32_t*)eeprom_wr_cir_buf[i].buffer) = (uint32_t)dbuf;
// Push the starting address of EEPROM at next 4 locations
*((uint32_t*)eeprom_wr_cir_buf[i].buffer+1) = (uint32_t)ebuf;
// Push the pay-load size at next 4 locations
*((uint32_t*)eeprom_wr_cir_buf[i].buffer+2) = size;
eeprom_wr_cir_buf[i].size = 12;
eeprom_wr_cir_buf[i].state = BUF_FULL;
}
}
else
{
// Do nothing. Just return error code
return -1;
}
return i;
}
/*
* *********************************
* *********************************
* End of the module: EEPROM.c
* *********************************
* *********************************
*/