416 lines
9.8 KiB
C
416 lines
9.8 KiB
C
/*
|
|
* eeprom.c
|
|
*
|
|
* Created on: Jun 10, 2022
|
|
* Author: Keith.Lloyd
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "fsl_spi.h"
|
|
#include <fsl_clock.h>
|
|
#include <fsl_ctimer.h>
|
|
|
|
#include "m95512.h"
|
|
#include "spi.h"
|
|
#include "timer.h"
|
|
#include "System/system.h"
|
|
#include "bootloader.h"
|
|
#include "frq.h"
|
|
#include "eeprom.h"
|
|
#include "Fonts/translate.h"
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
#define EE_BUFFER_SIZE (8) //size of buffer for send/receive 4-byte words
|
|
#define EE_BYTES_PER_WORD (4)
|
|
|
|
#define EE_HEADER_NUM_BYTES (3) //number of bytes in m95512 header - instruction, addrH, addrL
|
|
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
extern SYSTEM_DATA_t sys;
|
|
extern spi_transfer_t SPI0_xfer;
|
|
extern uint8_t frequency;
|
|
extern TIMER_t tmr;
|
|
/*******************************************************************************
|
|
* Static Function Declarations
|
|
******************************************************************************/
|
|
|
|
|
|
/*******************************************************************************
|
|
* Static Functions
|
|
******************************************************************************/
|
|
|
|
static bool EE_Busy(void)
|
|
{
|
|
uint8_t sr;
|
|
M95512_ReadStatus(&sr);
|
|
return sr & EE_SR_WIP;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Public Functions
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* Load data from EEPROM
|
|
*/
|
|
void EE_LoadData(void)
|
|
{
|
|
//Check for blank EEPROM
|
|
EE_ReadBytes(EE_SYS_MFG, sys.manufacturer, SYS_INFO_LENGTH);
|
|
if(sys.manufacturer[0] == 0xff)
|
|
{
|
|
SYS_LoadFactoryDefaults();
|
|
EE_SaveData();
|
|
}
|
|
|
|
//System Data
|
|
EE_ReadBytes(EE_SYS_MFG, sys.manufacturer, SYS_INFO_LENGTH);
|
|
EE_ReadBytes(EE_SYS_MODEL_NUMBER, sys.modelNumber, SYS_INFO_LENGTH);
|
|
EE_ReadBytes(EE_SYS_MODEL_NAME, sys.modelName, SYS_INFO_LENGTH);
|
|
EE_ReadBytes(EE_SYS_SERIAL, sys.serialNumber, SYS_INFO_LENGTH);
|
|
EE_ReadBytes(EE_SYS_MFG_DATE, sys.mfgDate, SYS_INFO_LENGTH);
|
|
|
|
EE_ReadMemoryUINT32(BL_VERSION_EEPROM_ADDR, &sys.bootloaderVersion);
|
|
|
|
EE_ReadMemoryUINT32(EE_DATA_LANGUAGE, &sys.language);
|
|
if(sys.language > NUM_TRANSLATION_STRINGS)
|
|
sys.language = LANG_ENGLISH;
|
|
|
|
EE_ReadBytes(EE_DATA_FREQUENCY, &frequency, 1); //1 byte only
|
|
|
|
EE_ReadBytes(EE_DATA_TIMER, &tmr.autoShutdown, 1); //timer 1 byte only
|
|
if(tmr.autoShutdown >= SD_NUM)
|
|
tmr.autoShutdown = SD_1_HR;
|
|
|
|
if(frequency > FREQ_MAX_NUM)
|
|
frequency = 1;
|
|
|
|
|
|
}
|
|
|
|
bool EE_LoadFrequencies(void)
|
|
{
|
|
bool success = true;
|
|
|
|
//Load frequencies
|
|
uint32_t tempNumFreqs = EE_ReadUINT32(EE_FREQ_NUM);
|
|
if((tempNumFreqs > FREQ_MAX_NUM) || (tempNumFreqs == 0)) //Error check numFreqs
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
for(uint32_t i = 0; i < tempNumFreqs; i++)
|
|
{
|
|
uint32_t packedFreq = EE_ReadUINT32(EE_FREQ_START + EE_BYTES_PER_WORD * i);
|
|
FREQ_AddPackedFrequency(packedFreq);
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
/*
|
|
* Save data to EEPROM
|
|
*/
|
|
void EE_SaveData(void)
|
|
{
|
|
EE_WriteBytes(EE_SYS_MFG, sys.manufacturer, SYS_INFO_LENGTH);
|
|
EE_WriteBytes(EE_SYS_MODEL_NUMBER, sys.modelNumber, SYS_INFO_LENGTH);
|
|
EE_WriteBytes(EE_SYS_MODEL_NAME, sys.modelName, SYS_INFO_LENGTH);
|
|
EE_WriteBytes(EE_SYS_SERIAL, sys.serialNumber, SYS_INFO_LENGTH);
|
|
EE_WriteBytes(EE_SYS_MFG_DATE, sys.mfgDate, SYS_INFO_LENGTH);
|
|
|
|
EE_WriteUINT32(EE_DATA_LANGUAGE, sys.language);
|
|
|
|
EE_WriteBytes(EE_DATA_FREQUENCY, &frequency, 1);
|
|
|
|
EE_WriteBytes(EE_DATA_TIMER, &tmr.autoShutdown, 1); // Save Power down timer status
|
|
|
|
//Save Frequencies
|
|
uint32_t numFreqs = FREQ_GetNumFrequencies();
|
|
EE_WriteUINT32(EE_FREQ_NUM, numFreqs);
|
|
for(uint32_t i = 0; i < numFreqs; i++)
|
|
{
|
|
EE_WriteUINT32(EE_FREQ_START + EE_BYTES_PER_WORD * i, FREQ_GetPackedFrequency(i));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Erase ALL EEPROM data except for bootloader data
|
|
* Write 0xff to all
|
|
*/
|
|
void EE_EraseAllData(void)
|
|
{
|
|
for(uint32_t i = EE_PAGE_SYS; i < EE_PAGE_DATA; i++) //EE_DATA_END; i++)
|
|
{
|
|
EE_WriteUINT32(i, 0xffffffff);
|
|
}
|
|
}
|
|
|
|
void EE_Test(void)
|
|
{
|
|
uint32_t data = 0;
|
|
uint32_t TEST_START_ADDR = 256;
|
|
uint32_t numWords = 64;
|
|
|
|
uint32_t writeData[numWords]; //write to EEPROM
|
|
uint32_t readData[numWords]; //read from EEPROM
|
|
|
|
static uint32_t numGood = 0;
|
|
static uint32_t numBad = 0;
|
|
|
|
//Init writeData
|
|
for(uint32_t i = 0; i < numWords; i++)
|
|
{
|
|
writeData[i] = i;
|
|
}
|
|
|
|
|
|
|
|
//Write data to EEPROM
|
|
for(uint32_t i = 0; i < numWords; i++)
|
|
{
|
|
data = i;
|
|
EE_WriteMemoryUINT32(TEST_START_ADDR + i*EE_BYTES_PER_WORD, &writeData[i]);
|
|
}
|
|
|
|
|
|
//Read back
|
|
memset(readData, 0, sizeof(readData));
|
|
|
|
for(uint32_t i = 0; i < numWords; i++)
|
|
{
|
|
EE_ReadMemoryUINT32(TEST_START_ADDR + i*EE_BYTES_PER_WORD, &readData[i]);
|
|
}
|
|
|
|
//COMPARE DATA
|
|
if(0 == memcmp(writeData, readData, numWords))
|
|
{
|
|
numGood++;
|
|
}
|
|
else
|
|
{
|
|
numBad++;
|
|
}
|
|
|
|
|
|
|
|
|
|
//Write zeros to EEPROM
|
|
for(uint32_t i = 0; i < numWords; i++)
|
|
{
|
|
data = 0;
|
|
EE_WriteMemoryUINT32(TEST_START_ADDR + i*EE_BYTES_PER_WORD, &data);
|
|
}
|
|
|
|
//Read back
|
|
memset(readData, 0, sizeof(readData));
|
|
|
|
for(uint32_t i = 0; i < numWords; i++)
|
|
{
|
|
EE_ReadMemoryUINT32(TEST_START_ADDR + i*EE_BYTES_PER_WORD, &readData[i]);
|
|
}
|
|
|
|
}
|
|
|
|
void EE_TestBytes(void)
|
|
{
|
|
uint32_t data = 0;
|
|
uint32_t TEST_START_ADDR = 256;
|
|
uint32_t numBytes = 128;
|
|
|
|
uint8_t writeData[numBytes]; //write to EEPROM
|
|
uint8_t readData[numBytes]; //read from EEPROM
|
|
|
|
static uint32_t numGood = 0;
|
|
static uint32_t numBad = 0;
|
|
|
|
//Init writeData
|
|
for(uint32_t i = 0; i < numBytes; i++)
|
|
{
|
|
writeData[i] = i;
|
|
}
|
|
|
|
//Write data to EEPROM
|
|
EE_WriteBytes(TEST_START_ADDR, writeData, numBytes);
|
|
|
|
|
|
//Read back
|
|
memset(readData, 0, numBytes);
|
|
|
|
EE_ReadBytes(TEST_START_ADDR, readData, numBytes);
|
|
|
|
//COMPARE DATA
|
|
if(0 == memcmp(writeData, readData, numBytes))
|
|
{
|
|
numGood++;
|
|
}
|
|
else
|
|
{
|
|
numBad++;
|
|
}
|
|
|
|
|
|
|
|
|
|
//Write zeros to EEPROM
|
|
memset(writeData, 0, sizeof(writeData));
|
|
EE_WriteBytes(TEST_START_ADDR, writeData, numBytes);
|
|
|
|
//Read back
|
|
memset(readData, 0, sizeof(readData));
|
|
EE_ReadBytes(TEST_START_ADDR, readData, numBytes);
|
|
|
|
}
|
|
|
|
|
|
void EE_WriteMemoryUINT32(uint16_t address, uint32_t *pdata)
|
|
{
|
|
TMR_Stop(); //Stop the timer to prevent interrupts from breaking EEPROM comms
|
|
uint32_t data;
|
|
uint8_t srcBuff[EE_BUFFER_SIZE];
|
|
|
|
M95512_WriteEnable();
|
|
|
|
data = *pdata;
|
|
srcBuff[0] = WRITE_MEM_ARRAY;
|
|
srcBuff[1] = address >> 8;
|
|
srcBuff[2] = address;
|
|
srcBuff[3] = (data & 0xff000000) >> 24;
|
|
srcBuff[4] = (data & 0x00ff0000) >> 16;
|
|
srcBuff[5] = (data & 0x0000ff00) >> 8;
|
|
srcBuff[6] = (data & 0x000000ff);
|
|
SPI0_SendBytes(srcBuff, 7, E2PROM);
|
|
|
|
//Wait for EEPROM WIP flag low
|
|
while(EE_Busy());
|
|
|
|
TMR_Start();
|
|
}
|
|
|
|
void EE_ReadMemoryUINT32(uint16_t address, uint32_t *pdata)
|
|
{
|
|
TMR_Stop(); //Stop the timer to prevent interrupts from breaking EEPROM comms
|
|
|
|
uint32_t data;
|
|
uint8_t srcBuff[EE_BUFFER_SIZE];
|
|
memset(srcBuff, 0, EE_BUFFER_SIZE); //Zero out srcBuff[]. byte 3 was 1???
|
|
|
|
srcBuff[0] = READ_MEM_ARRAY;
|
|
srcBuff[1] = address >> 8; //ADDR high
|
|
srcBuff[2] = address; //ADDR low
|
|
SPI0_SendBytes(srcBuff, 7, E2PROM);
|
|
|
|
for(uint16_t i = 3; i < 7; i++){
|
|
data <<= 8;
|
|
data += SPI0_xfer.rxData[i];
|
|
}
|
|
*pdata = data;
|
|
|
|
TMR_Start();
|
|
}
|
|
|
|
void EE_WriteUINT32(uint16_t address, uint32_t data)
|
|
{
|
|
TMR_Stop(); //Stop the timer to prevent interrupts from breaking EEPROM comms
|
|
uint8_t srcBuff[EE_BUFFER_SIZE];
|
|
|
|
M95512_WriteEnable();
|
|
|
|
srcBuff[0] = WRITE_MEM_ARRAY;
|
|
srcBuff[1] = address >> 8;
|
|
srcBuff[2] = address;
|
|
srcBuff[3] = (data & 0xff000000) >> 24;
|
|
srcBuff[4] = (data & 0x00ff0000) >> 16;
|
|
srcBuff[5] = (data & 0x0000ff00) >> 8;
|
|
srcBuff[6] = (data & 0x000000ff);
|
|
SPI0_SendBytes(srcBuff, 7, E2PROM);
|
|
|
|
//Wait for EEPROM WIP flag low
|
|
while(EE_Busy());
|
|
|
|
TMR_Start();
|
|
}
|
|
|
|
uint32_t EE_ReadUINT32(uint16_t address)
|
|
{
|
|
TMR_Stop(); //Stop the timer to prevent interrupts from breaking EEPROM comms
|
|
|
|
uint32_t data;
|
|
uint8_t srcBuff[EE_BUFFER_SIZE];
|
|
memset(srcBuff, 0, EE_BUFFER_SIZE); //Zero out srcBuff[]. byte 3 was 1???
|
|
|
|
srcBuff[0] = READ_MEM_ARRAY;
|
|
srcBuff[1] = address >> 8; //ADDR high
|
|
srcBuff[2] = address; //ADDR low
|
|
SPI0_SendBytes(srcBuff, 7, E2PROM);
|
|
|
|
for(uint16_t i = 3; i < 7; i++){
|
|
data <<= 8;
|
|
data += SPI0_xfer.rxData[i];
|
|
}
|
|
|
|
TMR_Start();
|
|
return data;
|
|
}
|
|
|
|
/* Write bytes to EEPROM
|
|
* CAUTION: avoid writing across a 128 byte page boundary! This will cause rollover per the datasheet section 6.6
|
|
*/
|
|
void EE_WriteBytes(uint16_t address, uint8_t *pdata, uint16_t numBytes)
|
|
{
|
|
|
|
if((address % EE_PAGE_SIZE) + numBytes > EE_PAGE_SIZE) //Prevent writing across page boundary
|
|
{
|
|
//while(1); //Use for debugging
|
|
return;
|
|
}
|
|
|
|
TMR_Stop(); //Stop the timer to prevent interrupts from breaking EEPROM comms
|
|
|
|
uint8_t srcBuff[SPI_XFER_BUFFER_SIZE + EE_HEADER_NUM_BYTES]; //temporary buffer for data
|
|
|
|
M95512_WriteEnable();
|
|
|
|
srcBuff[0] = WRITE_MEM_ARRAY;
|
|
srcBuff[1] = address >> 8;
|
|
srcBuff[2] = address;
|
|
memcpy(&srcBuff[3], pdata, numBytes); //copy pData to srcBuf
|
|
SPI0_SendBytes(srcBuff, numBytes + EE_HEADER_NUM_BYTES, E2PROM);
|
|
|
|
//Wait for EEPROM WIP flag low
|
|
while(EE_Busy());
|
|
|
|
TMR_Start();
|
|
}
|
|
|
|
/* Read bytes from EEPROM
|
|
*
|
|
*/
|
|
void EE_ReadBytes(uint16_t address, uint8_t *pdata, uint16_t numBytes)
|
|
{
|
|
TMR_Stop(); //Stop the timer to prevent interrupts from breaking EEPROM comms
|
|
|
|
uint8_t srcBuff[SPI_XFER_BUFFER_SIZE + EE_HEADER_NUM_BYTES];
|
|
memset(srcBuff, 0, SPI_XFER_BUFFER_SIZE); //Zero out srcBuff[]. byte 3 was 1???
|
|
|
|
srcBuff[0] = READ_MEM_ARRAY;
|
|
srcBuff[1] = address >> 8; //ADDR high
|
|
srcBuff[2] = address; //ADDR low
|
|
SPI0_SendBytes(srcBuff, numBytes + EE_HEADER_NUM_BYTES, E2PROM);
|
|
|
|
memcpy(pdata, &SPI0_xfer.rxData[3], numBytes); //copy received data to pdata
|
|
|
|
TMR_Start();
|
|
}
|