2020TPC-SW/2020TPCApp1.cydsn/NVM/NVM_OnChipEEPROM.c
2025-02-01 19:52:04 -06:00

260 lines
No EOL
9.2 KiB
C

/** \file
* \brief This file contains functions that manage the on-chip EEPROM.
*
*/
/* Include Files */
#include "KTag.h"
/* Local Definitions and Constants */
/* External Variables [Only if necessary!] */
/* External Function Prototypes [Only if necessary!] */
/* Public Variables */
//! Mutex controlling access to the EEPROM to ensure data/CRC integrity.
SemaphoreHandle_t xSemaphoreOnChipEEPROMLock;
TaskHandle_t NVM_OnChipEEPROM_Task_Handle;
volatile bool NVM_IsOnChipEEPROMInitialized = false;
/* Private Variables */
static QueueHandle_t xQueueOnChipEEPROM;
#if CY_PSOC4
const uint8_t Emulated_EEPROM_Storage[On_Chip_Emulated_EEPROM_PHYSICAL_SIZE]
__ALIGNED(CY_FLASH_SIZEOF_ROW) = {0u};
#endif // CY_PSOC4
/* Private Function Prototypes */
/* Inline Functions */
#if CY_PSOC4
//! Reads a block of \a n bytes from EEPROM address \a source to SRAM \a destination.
static inline void EEPROM_read_block(uint8_t * destination, uint16_t source, size_t n)
{
On_Chip_Emulated_EEPROM_Read(source, destination, n);
}
//! Writes a block of \a n bytes from SRAM \a source to EEPROM address \a destination.
static inline void EEPROM_write_block(uint8_t * source, uint16_t destination, size_t n)
{
On_Chip_Emulated_EEPROM_Write(destination, source, n);
}
#endif // CY_PSOC4
#if CY_PSOC5
//! Reads a block of \a n bytes from EEPROM address \a source to SRAM \a destination.
static inline void EEPROM_read_block(uint8_t * destination, uint16_t source, size_t n)
{
for (uint_fast16_t i = 0; i < n; i++)
{
uint8_t temp = On_Chip_EEPROM_ReadByte(source + i);
*(destination + i) = temp;
}
}
//! Writes a block of \a n bytes from SRAM \a source to EEPROM address \a destination.
static inline void EEPROM_write_block(uint8_t * source, uint16_t destination, size_t n)
{
for (uint_fast16_t i = 0; i < n; i++)
{
On_Chip_EEPROM_WriteByte(*(source + i), destination + i);
}
}
#endif // CY_PSOC5
#if CY_PSOC6
//! Reads a block of \a n bytes from EEPROM address \a source to SRAM \a destination.
static inline void EEPROM_read_block(uint8_t * destination, uint16_t source, size_t n)
{
cy_en_em_eeprom_status_t result = On_Chip_EEPROM_Read(source, destination, n);
if (result != CY_EM_EEPROM_SUCCESS)
{
CY_ASSERT(0);
}
}
//! Writes a block of \a n bytes from SRAM \a source to EEPROM address \a destination.
static inline void EEPROM_write_block(uint8_t * source, uint16_t destination, size_t n)
{
cy_en_em_eeprom_status_t result = On_Chip_EEPROM_Write(destination, source, n);
if (result != CY_EM_EEPROM_SUCCESS)
{
CY_ASSERT(0);
}
}
#endif // CY_PSOC6
/* Public Functions */
//! Sets up the on-chip EEPROM, but does not read from it (yet).
void NVM_InitOnChipEEPROM(void)
{
/// Create a mutex-type semaphore.
xSemaphoreOnChipEEPROMLock = xSemaphoreCreateMutex();
if (xSemaphoreOnChipEEPROMLock == NULL)
{
CY_ASSERT(0);
}
xQueueOnChipEEPROM = xQueueCreate(5, sizeof(uint8_t));
#if CY_PSOC4
On_Chip_Emulated_EEPROM_Init((uint32_t)Emulated_EEPROM_Storage);
#endif // CY_PSOC4
#if CY_PSOC5
On_Chip_EEPROM_Start();
#endif // CY_PSOC5
#if CY_PSOC6
// From the docs: "For PSoC 6, if Emulated EEPROM is selected for EEPROM storage, the start address will be
// overwritten to some address from Emulated EEPROM flash area."
On_Chip_EEPROM_Init(0);
#endif // CY_PSOC6
}
//! Handles the ongoing on-chip EEPROM tasks.
/*!
* First, it loops through all the on-chip EEPROM entries, and reads them in to RAM.
* Then, it priodically loops through all the on-chip EEPROM entries, and saves the ones that have been flagged.
*/
void NVM_OnChipEEPROMTask(void * pvParameters)
{
portBASE_TYPE xStatus;
static TickType_t xTicksToWait = pdMS_TO_TICKS(NVM_ON_CHIP_EEPROM_TASK_RATE_IN_ms);
for (uint8_t i = 0; i < NVM_N_ONCHIP_EEPROM_ENTRIES; i++)
{
NVM_CRC_t calculated_crc;
NVM_CRC_t stored_crc = 0;
EEPROM_read_block(NVM_OnChipEEPROMEntries[i]->Value, NVM_OnChipEEPROMEntries[i]->EE_Address, NVM_OnChipEEPROMEntries[i]->Size);
EEPROM_read_block((uint8_t *)&stored_crc, NVM_OnChipEEPROMEntries[i]->EE_CRC_Address, sizeof(NVM_CRC_t));
calculated_crc = NVM_CRC_init();
calculated_crc = NVM_CRC_update(calculated_crc, NVM_OnChipEEPROMEntries[i]->Value, NVM_OnChipEEPROMEntries[i]->Size);
calculated_crc = NVM_CRC_finalize(calculated_crc);
if (calculated_crc == stored_crc)
{
NVM_OnChipEEPROMEntries[i]->State = NVM_STATE_IDLE;
}
else
{
NVM_OnChipEEPROMEntries[i]->State = NVM_STATE_CRC_FAILED;
COMM_Console_Print_String("[NVMOn ");
COMM_Console_Print_UInt16((uint16_t) i);
COMM_Console_Print_String("] Calculated/Stored CRCs: ");
COMM_Console_Print_UInt16((uint16_t) calculated_crc);
COMM_Console_Print_String("/");
COMM_Console_Print_UInt16((uint16_t) stored_crc);
COMM_Console_Print_String("\n");
COMM_Console_Print_String("[NVMOn ");
COMM_Console_Print_UInt16((uint16_t) i);
COMM_Console_Print_String("] Applying defaults.\n");
memcpy(NVM_OnChipEEPROMEntries[i]->Value, NVM_OnChipEEPROMEntries[i]->Default, NVM_OnChipEEPROMEntries[i]->Size);
// Auto-fix the CRC.
NVM_SaveOnChipEEPROMEntry(NVM_OnChipEEPROMEntries[i]);
}
}
taskENTER_CRITICAL();
NVM_IsOnChipEEPROMInitialized = true;
taskEXIT_CRITICAL();
while(true)
{
uint8_t dummy;
// Wait for a call to NVM_SaveOnChipEEPROMEntry().
xStatus = xQueueReceive(xQueueOnChipEEPROM, &dummy, xTicksToWait);
if (xStatus == pdPASS)
{
for (uint8_t i = 0; i < NVM_N_ONCHIP_EEPROM_ENTRIES; i++)
{
NVM_CRC_t crc;
#if (defined CY_PSOC4) || (defined CY_PSOC6)
if (NVM_OnChipEEPROMEntries[i]->State == NVM_STATE_SAVE_REQUESTED)
{
if (xSemaphoreTake(xSemaphoreOnChipEEPROMLock, ( TickType_t ) 1000) == pdTRUE)
{
EEPROM_write_block(NVM_OnChipEEPROMEntries[i]->Value, NVM_OnChipEEPROMEntries[i]->EE_Address, NVM_OnChipEEPROMEntries[i]->Size);
// Calculate the CRC.
crc = NVM_CRC_init();
crc = NVM_CRC_update(crc, NVM_OnChipEEPROMEntries[i]->Value, NVM_OnChipEEPROMEntries[i]->Size);
crc = NVM_CRC_finalize(crc);
EEPROM_write_block((uint8_t *)&crc, NVM_OnChipEEPROMEntries[i]->EE_CRC_Address, sizeof(uint16_t));
NVM_OnChipEEPROMEntries[i]->State = NVM_STATE_IDLE;
xSemaphoreGive(xSemaphoreOnChipEEPROMLock);
}
}
#endif // (defined CY_PSOC4) || (defined CY_PSOC6)
#if CY_PSOC5
// From the component datasheet:
// "[On_Chip_EEPROM_UpdateTemperature()] updates the store temperature value. This should
// be called anytime the EEPROM is active and temperature may have changed by more than
// 10°C."
if (On_Chip_EEPROM_UpdateTemperature() == CYRET_SUCCESS)
{
if (NVM_OnChipEEPROMEntries[i]->State == NVM_STATE_SAVE_REQUESTED)
{
if (On_Chip_EEPROM_Query() == CYRET_SUCCESS)
{
if (xSemaphoreTake(xSemaphoreOnChipEEPROMLock, ( TickType_t ) 1000) == pdTRUE)
{
EEPROM_write_block(NVM_OnChipEEPROMEntries[i]->Value, NVM_OnChipEEPROMEntries[i]->EE_Address, NVM_OnChipEEPROMEntries[i]->Size);
// Calculate the CRC.
crc = NVM_CRC_init();
crc = NVM_CRC_update(crc, NVM_OnChipEEPROMEntries[i]->Value, NVM_OnChipEEPROMEntries[i]->Size);
crc = NVM_CRC_finalize(crc);
EEPROM_write_block((uint8_t *)&crc, NVM_OnChipEEPROMEntries[i]->EE_CRC_Address, sizeof(uint16_t));
NVM_OnChipEEPROMEntries[i]->State = NVM_STATE_IDLE;
xSemaphoreGive(xSemaphoreOnChipEEPROMLock);
}
}
}
}
else
{
vSerialPutString("ERROR: Couldn't update EEPROM temperature!", 80);
}
#endif // CY_PSOC5
}
}
}
}
//! Flags the given on-chip EEPROM entry to be saved next time the NVM_OnChipEEPROMTask() is run.
void NVM_SaveOnChipEEPROMEntry(NVM_EEPROMEntry_T * const this)
{
if (xSemaphoreTake(xSemaphoreOnChipEEPROMLock, ( TickType_t ) 1000) == pdTRUE)
{
this->State = NVM_STATE_SAVE_REQUESTED;
xSemaphoreGive(xSemaphoreOnChipEEPROMLock);
uint8_t dummy = 0;
xQueueSend(xQueueOnChipEEPROM, &dummy, 0);
}
}
/* Private Functions */