/* * eeprom.c * * Created on: Jun 10, 2022 * Author: Keith.Lloyd */ #include #include "fsl_spi.h" #include #include #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 ******************************************************************************/ /******************************************************************************* * 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(); }