260 lines
No EOL
9.2 KiB
C
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 */ |