Initial public release.
This commit is contained in:
parent
7b169e8116
commit
dac4af8d25
255 changed files with 68595 additions and 2 deletions
302
2020TPCAppNoDFU.cydsn/NVM/NVM_ExternalEEPROM.c
Normal file
302
2020TPCAppNoDFU.cydsn/NVM/NVM_ExternalEEPROM.c
Normal file
|
@ -0,0 +1,302 @@
|
|||
/** \file
|
||||
* \brief This file contains functions that manage the external EEPROM.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
//! This is the same for both the MCP98243 and the CAT24C256.
|
||||
#define EXTERNAL_EEPROM_I2C_ADDRESS 0x50
|
||||
#define EXTERNAL_EEPROM_TEMP_SENSOR_I2C_ADDRESS 0x18
|
||||
|
||||
//! Read-only register used to identify the temperature sensor capability.
|
||||
#define MCP98243_REGISTER_CAPABILITY 0x00
|
||||
//! Sensor configuration register.
|
||||
#define MCP98243_REGISTER_CONFIG 0x01
|
||||
//! Upper temperature limit register.
|
||||
#define MCP98243_REGISTER_T_UPPER 0x02
|
||||
//! Lower temperature limit register.
|
||||
#define MCP98243_REGISTER_T_LOWER 0x03
|
||||
//! Critical temperature limit register.
|
||||
#define MCP98243_REGISTER_T_CRIT 0x04
|
||||
//! Ambient temperature register.
|
||||
#define MCP98243_REGISTER_T_A 0x05
|
||||
//! Read-only register used to identify the manufacturer of the device.
|
||||
#define MCP98243_REGISTER_MANUFACTURER_ID 0x06
|
||||
//! Read-only register indicating the device identification and device revision.
|
||||
#define MCP98243_REGISTER_DEVICE_ID 0x07
|
||||
//! Temperature sensor resolution register.
|
||||
#define MCP98243_REGISTER_RESOLUTION 0x08
|
||||
|
||||
|
||||
/* 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 xSemaphoreExternalEEPROMLock;
|
||||
|
||||
TaskHandle_t NVM_ExternalEEPROM_Task_Handle;
|
||||
|
||||
volatile bool NVM_IsExternalEEPROMInitialized = false;
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
static QueueHandle_t xQueueExternalEEPROM;
|
||||
|
||||
//! Shared master transfer configuration variable.
|
||||
static cy_stc_scb_i2c_master_xfer_config_t Master_Transfer_Config =
|
||||
{
|
||||
.slaveAddress = EXTERNAL_EEPROM_I2C_ADDRESS,
|
||||
.buffer = NULL,
|
||||
.bufferSize = 0U,
|
||||
.xferPending = false
|
||||
};
|
||||
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Inline Functions */
|
||||
|
||||
//! Waits a given time for an I²C transfer to complete.
|
||||
/*!
|
||||
* \param timeout_in_ms The time (in milliseconds) to wait for the transfer to complete.
|
||||
* \return #true if the transfer completed, or #false if the time ran out without
|
||||
* a successful transfer.
|
||||
*/
|
||||
static inline bool Wait_For_Transfer_To_Complete(uint16_t timeout_in_ms)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// Time to wait for an in-process transfer before looking again. This wait grows longer as time
|
||||
// passes, until timeout_in_ms runs out.
|
||||
uint16_t HOLDOFF_TIME_IN_ms = 1;
|
||||
|
||||
while ((success == false) && (timeout_in_ms > 0))
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(HOLDOFF_TIME_IN_ms));
|
||||
|
||||
if (timeout_in_ms > HOLDOFF_TIME_IN_ms)
|
||||
{
|
||||
timeout_in_ms -= HOLDOFF_TIME_IN_ms;
|
||||
|
||||
// Wait a little longer next time.
|
||||
HOLDOFF_TIME_IN_ms++;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout_in_ms = 0;
|
||||
}
|
||||
|
||||
if ((I2C_MasterGetStatus() & CY_SCB_I2C_MASTER_BUSY) != CY_SCB_I2C_MASTER_BUSY)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//! 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)
|
||||
{
|
||||
uint8_t xfer_buffer[5];
|
||||
|
||||
if (xSemaphoreTake(COMM_I2C_Bus_Mutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
// Write the initial address to the EEPROM.
|
||||
xfer_buffer[0] = (source >> 8);
|
||||
xfer_buffer[1] = source & 0xFF;
|
||||
|
||||
Master_Transfer_Config.buffer = (uint8_t *)xfer_buffer;
|
||||
Master_Transfer_Config.bufferSize = 2;
|
||||
|
||||
cy_en_scb_i2c_status_t errStatus = I2C_MasterWrite(&Master_Transfer_Config);
|
||||
|
||||
if (errStatus == CY_SCB_I2C_SUCCESS)
|
||||
{
|
||||
(void) Wait_For_Transfer_To_Complete(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
// What?
|
||||
}
|
||||
|
||||
// Read n bytes at EEPROM[source].
|
||||
Master_Transfer_Config.buffer = (uint8_t *)destination;
|
||||
Master_Transfer_Config.bufferSize = n;
|
||||
|
||||
errStatus = I2C_MasterRead(&Master_Transfer_Config);
|
||||
|
||||
if (errStatus == CY_SCB_I2C_SUCCESS)
|
||||
{
|
||||
(void) Wait_For_Transfer_To_Complete(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
// What?
|
||||
}
|
||||
|
||||
xSemaphoreGive(COMM_I2C_Bus_Mutex);
|
||||
}
|
||||
}
|
||||
|
||||
//! 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)
|
||||
{
|
||||
uint8_t xfer_buffer[4];
|
||||
|
||||
if (xSemaphoreTake(COMM_I2C_Bus_Mutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
// Write the data one byte at a time.
|
||||
for (uint8_t i = 0; i < n; i++)
|
||||
{
|
||||
uint16_t destination_address = destination + i;
|
||||
xfer_buffer[0] = (destination_address >> 8);
|
||||
xfer_buffer[1] = destination_address & 0xFF;
|
||||
xfer_buffer[2] = *(source + i);
|
||||
|
||||
Master_Transfer_Config.buffer = (uint8_t *)xfer_buffer;
|
||||
Master_Transfer_Config.bufferSize = 3;
|
||||
|
||||
cy_en_scb_i2c_status_t errStatus = I2C_MasterWrite(&Master_Transfer_Config);
|
||||
|
||||
if (errStatus == CY_SCB_I2C_SUCCESS)
|
||||
{
|
||||
(void) Wait_For_Transfer_To_Complete(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
// What?
|
||||
}
|
||||
|
||||
// The CAT24C256 has a nominal Write Cycle time (t_WR) of 5ms (no maximum specified).
|
||||
// Wait 6ms between writes to have some margin (and avoid being NAKed).
|
||||
vTaskDelay(pdMS_TO_TICKS(6));
|
||||
}
|
||||
|
||||
xSemaphoreGive(COMM_I2C_Bus_Mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
//! Sets up the external EEPROM, but does not read from it (yet).
|
||||
void NVM_InitExternalEEPROM(void)
|
||||
{
|
||||
/// Create a mutex-type semaphore.
|
||||
xSemaphoreExternalEEPROMLock = xSemaphoreCreateMutex();
|
||||
|
||||
if (xSemaphoreExternalEEPROMLock == NULL)
|
||||
{
|
||||
CY_ASSERT(0);
|
||||
}
|
||||
|
||||
xQueueExternalEEPROM = xQueueCreate(5, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
//! Handles the ongoing external EEPROM tasks.
|
||||
/*!
|
||||
* First, it loops through all the external EEPROM entries, and reads them in to RAM.
|
||||
* Then, it priodically loops through all the external EEPROM entries, and saves the ones that have been flagged.
|
||||
*/
|
||||
void NVM_ExternalEEPROMTask(void * pvParameters)
|
||||
{
|
||||
portBASE_TYPE xStatus;
|
||||
static TickType_t xTicksToWait = pdMS_TO_TICKS(NVM_EXTERNAL_EEPROM_TASK_RATE_IN_ms);
|
||||
|
||||
for (uint8_t i = 0; i < NVM_N_EXTERNAL_EEPROM_ENTRIES; i++)
|
||||
{
|
||||
NVM_CRC_t calculated_crc;
|
||||
NVM_CRC_t stored_crc = 0;
|
||||
|
||||
EEPROM_read_block(NVM_ExternalEEPROMEntries[i]->Value, NVM_ExternalEEPROMEntries[i]->EE_Address, NVM_ExternalEEPROMEntries[i]->Size);
|
||||
EEPROM_read_block((uint8_t *)&stored_crc, NVM_ExternalEEPROMEntries[i]->EE_CRC_Address, sizeof(NVM_CRC_t));
|
||||
|
||||
calculated_crc = NVM_CRC_init();
|
||||
calculated_crc = NVM_CRC_update(calculated_crc, NVM_ExternalEEPROMEntries[i]->Value, NVM_ExternalEEPROMEntries[i]->Size);
|
||||
calculated_crc = NVM_CRC_finalize(calculated_crc);
|
||||
|
||||
if (calculated_crc == stored_crc)
|
||||
{
|
||||
NVM_ExternalEEPROMEntries[i]->State = NVM_STATE_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NVM_ExternalEEPROMEntries[i]->State = NVM_STATE_CRC_FAILED;
|
||||
|
||||
COMM_Console_Print_String("[NVMEx ");
|
||||
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("[NVMEx ");
|
||||
COMM_Console_Print_UInt16((uint16_t) i);
|
||||
COMM_Console_Print_String("] Applying defaults.\n");
|
||||
|
||||
memcpy(NVM_ExternalEEPROMEntries[i]->Value, NVM_ExternalEEPROMEntries[i]->Default, NVM_ExternalEEPROMEntries[i]->Size);
|
||||
|
||||
// Auto-fix the CRC.
|
||||
NVM_SaveExternalEEPROMEntry(NVM_ExternalEEPROMEntries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
NVM_IsExternalEEPROMInitialized = true;
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
while(true)
|
||||
{
|
||||
uint8_t dummy;
|
||||
|
||||
// Wait for a call to NVM_SaveExternalEEPROMEntry().
|
||||
xStatus = xQueueReceive(xQueueExternalEEPROM, &dummy, xTicksToWait);
|
||||
|
||||
if (xStatus == pdPASS)
|
||||
{
|
||||
for (uint8_t i = 0; i < NVM_N_EXTERNAL_EEPROM_ENTRIES; i++)
|
||||
{
|
||||
NVM_CRC_t crc;
|
||||
|
||||
if (NVM_ExternalEEPROMEntries[i]->State == NVM_STATE_SAVE_REQUESTED)
|
||||
{
|
||||
if (xSemaphoreTake(xSemaphoreExternalEEPROMLock, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
EEPROM_write_block(NVM_ExternalEEPROMEntries[i]->Value, NVM_ExternalEEPROMEntries[i]->EE_Address, NVM_ExternalEEPROMEntries[i]->Size);
|
||||
|
||||
// Calculate the CRC.
|
||||
crc = NVM_CRC_init();
|
||||
crc = NVM_CRC_update(crc, NVM_ExternalEEPROMEntries[i]->Value, NVM_ExternalEEPROMEntries[i]->Size);
|
||||
crc = NVM_CRC_finalize(crc);
|
||||
EEPROM_write_block((uint8_t *)&crc, NVM_ExternalEEPROMEntries[i]->EE_CRC_Address, sizeof(uint16_t));
|
||||
NVM_ExternalEEPROMEntries[i]->State = NVM_STATE_IDLE;
|
||||
xSemaphoreGive(xSemaphoreExternalEEPROMLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Flags the given external EEPROM entry to be saved next time the NVM_ExternalEEPROMTask() is run.
|
||||
void NVM_SaveExternalEEPROMEntry(NVM_EEPROMEntry_T * const this)
|
||||
{
|
||||
if (xSemaphoreTake(xSemaphoreExternalEEPROMLock, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
this->State = NVM_STATE_SAVE_REQUESTED;
|
||||
xSemaphoreGive(xSemaphoreExternalEEPROMLock);
|
||||
uint8_t dummy = 0;
|
||||
xQueueSend(xQueueExternalEEPROM, &dummy, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Private Functions */
|
Loading…
Add table
Add a link
Reference in a new issue