Files
TX/source/eeprom.c

446 lines
10 KiB
C
Raw Normal View History

/*
* 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 "fgen.h"
#include "Fonts/translate.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* 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
******************************************************************************/
/*
* Pack frequency data and return
* Packed data is used for saving to FLASH
*/
uint32_t EE_GetPackedFrequency(uint32_t index)
{
FREQUENCY_t *freq = fgen_getByIndex(index);
uint32_t packed = freq->frequency;
//packed |= freqArray[index].type << FREQ_PACK_SHIFT_TYPE;
packed |= (uint32_t)freq->enabled << FREQ_PACK_SHIFT_ENABLED;
//packed |= (uint32_t)freqArray[index].inMenu << FREQ_PACK_SHIFT_INMENU;
return packed;
}
/*
* Add a frequency to the list from packed data
* Packed data is used for saving to FLASH
*/
void EE_AddPackedFrequency(uint32_t packedFreq)
{
uint32_t frequency = packedFreq & FREQ_PACK_MASK_FREQ;
//FREQ_TYPE_t type = (packedFreq & FREQ_PACK_MASK_TYPE) >> FREQ_PACK_SHIFT_TYPE;
bool enabled = packedFreq & FREQ_PACK_MASK_ENABLED;
//bool inMenu = packedFreq & FREQ_PACK_MASK_INMENU;
fgen_addFrequency(frequency, enabled, 1, FT_ACTIVE); //inMenu always 1, all FT_ACTIVE
}
/*
* 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);
EE_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 = fgen_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, EE_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();
}