Microchip® Advanced Software Framework

S_Nv-SamR21.c File Reference

NV component implementation.

Copyright (c) 2018 Microchip Technology Inc. and its subsidiaries.

#include "S_Nv_Bindings.h"
#include "S_Nv_Init.h"
#include "S_Nv.h"
#include "pdsDataServer.h"
#include "D_Nv.h"
#include "assert.h"
#include <compiler.h>
#include "wlPdsMemIds.h"
#include "string.h"
#include "sysTimer.h"

Data Structures

struct  BlockHeader_t
 
struct  BlockHeaderSNv1_t
 
struct  Item_t
 Structure used to store where to find an item. More...
 
struct  SectorHeader_t
 16 byte sector header used in flash located at the start of the active sector. More...
 
struct  SectorHeaderSnv1_t
 16 byte sector header used in flash located at the start of the active sector. More...
 

Macros

#define BLOCK_HEADER_SIZE   ((uint16_t) sizeof(BlockHeader_t))
 The size of the block header. More...
 
#define COMPACT_ITEM_DELAY_MS   3000u
 Delay before performing a compact item operation. More...
 
#define COMPACT_ITEM_THRESHOLD   100u
 Perform a compact item operation if the number of partial writes is larger than this. More...
 
#define COMPACT_SECTOR_DELAY_MS   10000u
 Delay before performing a preemptive compact operation. More...
 
#define COMPID   "S_Nv"
 
#define ERASE_SECTOR_DELAY_MS   7000u
 Delay before erasing a sector. More...
 
#define EVENT_COMPACT_ITEM   2u
 
#define EVENT_COMPACT_SECTOR   1u
 
#define EVENT_ERASE_SECTOR   0u
 Timer event used to erase a sector. More...
 
#define FIRST_SECTOR   D_NV_FIRST_SECTOR
 
#define INITIAL_SECTOR_SEQUENCE_NUMBER   0xFFFFFFFEuL
 The sequence number to use for the initial sector. More...
 
#define ITEMS_AREA_START_ADDRESS   NVMCTRL_ROW_SIZE
 
#define MAX_ITEM_COUNT   PDS_MAX_ID
 The maximum number of items. More...
 
#define MAX_ITEM_LENGTH   2048u
 The maxumum length of an item. More...
 
#define PERSISTENT_NV_ITEMS_APPLICATION   0xFFFu
 
#define PREEMPTIVE_COMPACT_SECTOR_THRESHOLD   (MAX_ITEM_LENGTH + BLOCK_HEADER_SIZE)
 Perform a compact sector operation with a delay if the sector has less free space than this. More...
 
#define ROW_SIZE   NVMCTRL_ROW_SIZE
 
#define SECTOR_COUNT   D_NV_SECTOR_COUNT
 
#define SECTOR_HEADER_SIZE   ((uint16_t) sizeof(SectorHeader_t))
 The size of the sector header. More...
 
#define SECTOR_SIZE   D_NV_SECTOR_SIZE
 

Typedefs

typedef struct BlockHeader_t BlockHeader_t
 
typedef struct BlockHeaderSNv1_t BlockHeaderSNv1_t
 
typedef struct Item_t Item_t
 Structure used to store where to find an item. More...
 
typedef struct SectorHeader_t SectorHeader_t
 16 byte sector header used in flash located at the start of the active sector. More...
 
typedef struct SectorHeaderSnv1_t SectorHeaderSnv1_t
 16 byte sector header used in flash located at the start of the active sector. More...
 

Enumerations

enum  ItemAlignment_t {
  ITEM_NO_ALIGNMENT,
  ITEM_16BYTE_ALIGNMENT,
  ITEM_64BYTE_ALIGNMENT
}
 Enumerations for Snv Item alignments. More...
 
enum  SnvRevisioin_t {
  SNV_REV_1 = 1,
  SNV_REV_2
}
 Enumerations for Snv revisions. More...
 

Functions

static S_Nv_ReturnValue_t CompactItem (void)
 
static void compactItemTimerFired (struct SYS_Timer_t *timer)
 Compact item timer callback. More...
 
static bool CompactSector (void)
 
static void CompactSectorIfNeeded (uint16_t immediateThreshold)
 
static void compactSectorTimerFired (struct SYS_Timer_t *timer)
 Compact sector timer callback. More...
 
static uint16_t ComputeCrc (uint8_t *pData, uint16_t length, uint16_t crc)
 
static uint16_t ComputeDataCrc (uint8_t sourceSector, uint16_t blockPointer, BlockHeader_t *pBlockHeader)
 
static uint16_t ComputeHeaderCrc (BlockHeader_t *pBlockHeader)
 
static uint16_t ComputeHeaderCrcSnv1 (BlockHeaderSNv1_t *pBlockHeader)
 
static uint16_t ComputeSectorHeaderCrc (SectorHeader_t *pSectorHeader)
 
static Item_tCreateItemCache (uint16_t id)
 Return a pointer to a cache for a new item. More...
 
static void DeleteItemCache (uint16_t id)
 Removes the specified item from the cache array. More...
 
static bool EraseSector (void)
 
static void eraseSectorTimerFired (struct SYS_Timer_t *timer)
 Erase sector timer callback. More...
 
static uint16_t FindItem (uint16_t id)
 Return a pointer to the last written block for the item. More...
 
static Item_tFindItemCache (uint16_t id)
 Return a pointer to the cache for the item. More...
 
static bool GatherData (uint8_t sourceSector, uint16_t lastBlockPointer, uint16_t offset, uint16_t length, void *pData)
 Gather data from an item for a read or compact operation. More...
 
static bool IsEmpty (uint8_t *pData, uint16_t length)
 Check if the RAM buffer contains all 0xFF values (flash erased) More...
 
static bool IsPersistent (uint16_t id)
 
static void LoadSector (SnvRevisioin_t revisionNumber)
 
static bool PowerSupplyTooLow ()
 Check the power supply. More...
 
void S_Nv_CompactSector_Impl (void)
 
S_Nv_ReturnValue_t S_Nv_Delete_Impl (S_Nv_ItemId_t id)
 Interface function, see S_Nv_Delete. More...
 
void S_Nv_EarlyInit (void)
 Initializes the internal flash service for early access. More...
 
S_Nv_ReturnValue_t S_Nv_EraseAll_Impl (bool includingPersistentItems)
 Interface function, see S_Nv_EraseAll. More...
 
void S_Nv_Init (void)
 Initializes the component and tells which items are persistent against S_Nv_EraseAll(FALSE). More...
 
bool S_Nv_IsItemAvailable_Impl (S_Nv_ItemId_t id)
 Interface function, see S_Nv_IsItemAvailable. More...
 
S_Nv_ReturnValue_t S_Nv_ItemInit_Impl (S_Nv_ItemId_t id, uint16_t itemLength, void *pDefaultData)
 Interface function, see S_Nv_ItemInit. More...
 
uint16_t S_Nv_ItemLength_Impl (S_Nv_ItemId_t id)
 Interface function, see S_Nv_ItemLength. More...
 
S_Nv_ReturnValue_t S_Nv_Read_Impl (S_Nv_ItemId_t id, uint16_t offset, uint16_t dataLength, void *pData)
 Interface function, see S_Nv_Read. More...
 
void S_Nv_SetPowerSupplyCheckingFunction_Impl (S_Nv_PowerSupplyCheckingFunction_t pf)
 Interface function, see S_Nv_SetPowerSupplyCheckingFunction. More...
 
S_Nv_ReturnValue_t S_Nv_Write_Impl (S_Nv_ItemId_t id, uint16_t offset, uint16_t dataLength, void *pData)
 Interface function, see S_Nv_Write. More...
 
static bool SmartCompacting (uint8_t *compactBlock, uint16_t curItemLength)
 
static void UpdateSectorHead (uint16_t increment, ItemAlignment_t itemAlignment)
 Update the sector head with increment as per Alignement. More...
 
static bool WriteAndCheck (uint16_t offset, uint8_t *pData, uint16_t length)
 
static bool WriteBlockHeader (BlockHeader_t *pBlockHeader)
 
static bool WriteDataBlockAndHeader (BlockHeader_t *pBlockHeader, uint8_t *pData)
 
static bool WriteSectorHeader (uint32_t sequenceNumber)
 

Variables

static uint16_t compactBlockOffset = 0u
 
static SYS_Timer_t compactItemTimer
 
static SYS_Timer_t compactSectorTimer
 
static uint16_t currentCompactLength = 0u
 
static uint8_t dataBlock [ROW_SIZE]
 
static SYS_Timer_t eraseSectorTimer
 
static uint16_t s_compactItemId = 0x0000u
 The item to perform a compact operation on and the length of this item. More...
 
static uint16_t s_compactItemLength = 0x0000u
 
static bool s_earlyInitDone = false
 Check if the early init function is called already. More...
 
static Item_t s_itemCache [MAX_ITEM_COUNT]
 
static uint8_t s_itemCount = 0u
 The number of read, and thus cached, items. More...
 
static uint16_t s_nextPageAddressAfterCompact
 
static const uint16_t s_persistentItems [] = {PERSISTENT_NV_ITEMS_APPLICATION}
 
static
S_Nv_PowerSupplyCheckingFunction_t 
s_powerSupplyCheckingFunction = NULL
 Callback function called before changing flash contents. More...
 
static uint8_t s_sector
 The active sector. More...
 
static uint16_t s_sectorHead
 Location of the first unprogrammed byte in the active sector. More...
 
static uint8_t s_sectorToErase = 0xFFu
 The sector to erase in the EVENT_ERASE_SECTOR handler. More...
 

#define BLOCK_HEADER_SIZE   ((uint16_t) sizeof(BlockHeader_t))
#define COMPACT_ITEM_DELAY_MS   3000u

Delay before performing a compact item operation.

Referenced by S_Nv_Write_Impl().

#define COMPACT_ITEM_THRESHOLD   100u

Perform a compact item operation if the number of partial writes is larger than this.

Referenced by S_Nv_Write_Impl().

#define COMPACT_SECTOR_DELAY_MS   10000u

Delay before performing a preemptive compact operation.

Referenced by CompactSectorIfNeeded().

#define COMPID   "S_Nv"
#define ERASE_SECTOR_DELAY_MS   7000u

Delay before erasing a sector.

Referenced by S_Nv_Init().

#define EVENT_COMPACT_ITEM   2u
#define EVENT_COMPACT_SECTOR   1u
#define EVENT_ERASE_SECTOR   0u

Timer event used to erase a sector.

#define FIRST_SECTOR   D_NV_FIRST_SECTOR
#define INITIAL_SECTOR_SEQUENCE_NUMBER   0xFFFFFFFEuL

The sequence number to use for the initial sector.

Referenced by S_Nv_EarlyInit().

#define ITEMS_AREA_START_ADDRESS   NVMCTRL_ROW_SIZE

Referenced by EraseSector(), and LoadSector().

#define MAX_ITEM_COUNT   PDS_MAX_ID

The maximum number of items.

Referenced by CreateItemCache(), and S_Nv_ItemInit_Impl().

#define MAX_ITEM_LENGTH   2048u

The maxumum length of an item.

Referenced by S_Nv_ItemInit_Impl().

#define PERSISTENT_NV_ITEMS_APPLICATION   0xFFFu
#define PREEMPTIVE_COMPACT_SECTOR_THRESHOLD   (MAX_ITEM_LENGTH + BLOCK_HEADER_SIZE)

Perform a compact sector operation with a delay if the sector has less free space than this.

Referenced by CompactSectorIfNeeded().

#define ROW_SIZE   NVMCTRL_ROW_SIZE
#define SECTOR_COUNT   D_NV_SECTOR_COUNT
#define SECTOR_HEADER_SIZE   ((uint16_t) sizeof(SectorHeader_t))

The size of the sector header.

Referenced by CompactSector(), S_Nv_EarlyInit(), and WriteSectorHeader().

#define SECTOR_SIZE   D_NV_SECTOR_SIZE

typedef struct BlockHeader_t BlockHeader_t
typedef struct Item_t Item_t

Structure used to store where to find an item.

16 byte sector header used in flash located at the start of the active sector.

16 byte sector header used in flash located at the start of the active sector.

Enumerations for Snv Item alignments.

Enumerator
ITEM_NO_ALIGNMENT 
ITEM_16BYTE_ALIGNMENT 
ITEM_64BYTE_ALIGNMENT 

Enumerations for Snv revisions.

Enumerator
SNV_REV_1 
SNV_REV_2 

static void compactItemTimerFired ( struct SYS_Timer_t timer)
static

Compact item timer callback.

References CompactItem().

Referenced by S_Nv_Write_Impl().

static void compactSectorTimerFired ( struct SYS_Timer_t timer)
static

Compact sector timer callback.

References CompactSector(), and PowerSupplyTooLow().

Referenced by CompactSectorIfNeeded().

static uint16_t ComputeCrc ( uint8_t *  pData,
uint16_t  length,
uint16_t  crc 
)
static
static uint16_t ComputeDataCrc ( uint8_t  sourceSector,
uint16_t  blockPointer,
BlockHeader_t pBlockHeader 
)
static
static uint16_t ComputeHeaderCrc ( BlockHeader_t pBlockHeader)
static
static uint16_t ComputeHeaderCrcSnv1 ( BlockHeaderSNv1_t pBlockHeader)
static
static uint16_t ComputeSectorHeaderCrc ( SectorHeader_t pSectorHeader)
static
static Item_t* CreateItemCache ( uint16_t  id)
static

Return a pointer to a cache for a new item.

Parameters
idThe id to create cache for
Returns
A pointer to the cache for the ID

References FindItemCache(), Item_t::id, MAX_ITEM_COUNT, and s_itemCount.

Referenced by LoadSector(), and S_Nv_ItemInit_Impl().

static void DeleteItemCache ( uint16_t  id)
static

Removes the specified item from the cache array.

Parameters
idThe id to delete the cache for

References FindItemCache(), and s_itemCount.

Referenced by LoadSector(), S_Nv_Delete_Impl(), and S_Nv_EraseAll_Impl().

static bool EraseSector ( void  )
static
static void eraseSectorTimerFired ( struct SYS_Timer_t timer)
static

Erase sector timer callback.

References D_Nv_EraseSector, PowerSupplyTooLow(), and s_sectorToErase.

Referenced by S_Nv_Init().

static uint16_t FindItem ( uint16_t  id)
static

Return a pointer to the last written block for the item.

Parameters
idThe id to find
Returns
A pointer to the last written block, or 0x0000u if the item was not found

References FindItemCache(), and Item_t::lastBlock.

Referenced by S_Nv_Delete_Impl(), S_Nv_IsItemAvailable_Impl(), S_Nv_ItemInit_Impl(), S_Nv_ItemLength_Impl(), and S_Nv_Read_Impl().

static Item_t* FindItemCache ( uint16_t  id)
static

Return a pointer to the cache for the item.

Parameters
idThe id to find
Returns
A pointer to the cache for the ID, or NULL if it was not found

References Item_t::id, Item_t::lastBlock, and s_itemCount.

Referenced by CompactItem(), CreateItemCache(), DeleteItemCache(), FindItem(), LoadSector(), and S_Nv_Write_Impl().

static bool GatherData ( uint8_t  sourceSector,
uint16_t  lastBlockPointer,
uint16_t  offset,
uint16_t  length,
void *  pData 
)
static

Gather data from an item for a read or compact operation.

Parameters
sourceSector
lastBlockPointerPointer to the last block written for the item
offsetThe start of the range of bytes to copy from the item
lengthThe size of the range of bytes to copy from the item
pDataPointer to destination buffer in RAM for a read operation. NULL for a compact operation.

This function is used by both the read and the compact operation.

  • For a read operation, the pBuffer parameter points to a buffer in RAM.
  • For a compact operation, pBuffer parameter is NULL and the data will be copied to the flash memory s_sectorHead in sector s_sector.

References BLOCK_HEADER_SIZE, BlockHeader_t::blockLength, BlockHeader_t::blockOffset, D_Nv_Read, and BlockHeader_t::previousBlock.

Referenced by CompactItem(), CompactSector(), ComputeDataCrc(), and S_Nv_Read_Impl().

static bool IsEmpty ( uint8_t *  pData,
uint16_t  length 
)
static

Check if the RAM buffer contains all 0xFF values (flash erased)

Parameters
pDataThe buffer to check
lengthThe length of the buffer
Returns
TRUE if the buffer contains all 0xFF, FALSE otherwise

References i.

Referenced by LoadSector().

static bool IsPersistent ( uint16_t  id)
static

References i, and s_persistentItems.

Referenced by S_Nv_EraseAll_Impl().

static bool PowerSupplyTooLow ( )
static

Check the power supply.

Returns
TRUE if the power supply is too low, FALSE when the the power supply is OK or when there is no callback installed.

References s_powerSupplyCheckingFunction.

Referenced by CompactItem(), compactSectorTimerFired(), eraseSectorTimerFired(), S_Nv_Delete_Impl(), S_Nv_EraseAll_Impl(), S_Nv_ItemInit_Impl(), and S_Nv_Write_Impl().

void S_Nv_CompactSector_Impl ( void  )

References CompactSector().

void S_Nv_EarlyInit ( void  )

Initializes the internal flash service for early access.

Note
It is not required to call this function if the application does not require early access to internal Nv. Note that the S_Nv component is fully functional after calling S_Nv_EarlyInit(), but until S_Nv_Init() is called, chances are much higher that the component blocks when a sector becomes full. Only after S_Nv_Init() is called, compacting the sector is decoupled as much as possible.

References ComputeSectorHeaderCrc(), D_Nv_Read, EraseSector(), FIRST_SECTOR, SectorHeader_t::headerCrc, INITIAL_SECTOR_SEQUENCE_NUMBER, SectorHeaderSnv1_t::isActive, LoadSector(), s_earlyInitDone, s_itemCount, s_nextPageAddressAfterCompact, s_sector, SECTOR_COUNT, SECTOR_HEADER_SIZE, SectorHeader_t::sequenceNumber, SectorHeader_t::sequenceParity, SectorHeader_t::signature, SNV_REV_1, SNV_REV_2, and WriteSectorHeader().

Referenced by S_Nv_Init().

S_Nv_ReturnValue_t S_Nv_EraseAll_Impl ( bool  includingPersistentItems)

Interface function, see S_Nv_EraseAll.

Important: EraseAll leaves the file system in a non-working state if persistent items are also deleted. This is because all sectors are deleted without initializing a new one or even clearing the cache, so reinitialization of the driver is needed.

References CompactSector(), D_Nv_EraseSector, DeleteItemCache(), FIRST_SECTOR, Item_t::id, IsPersistent(), PowerSupplyTooLow(), s_itemCount, S_Nv_ReturnValue_Ok, S_Nv_ReturnValue_PowerSupplyTooLow, and SECTOR_COUNT.

void S_Nv_Init ( void  )
bool S_Nv_IsItemAvailable_Impl ( S_Nv_ItemId_t  id)

Interface function, see S_Nv_IsItemAvailable.

Important: This will check whether the item is found in the storage area

References FindItem().

uint16_t S_Nv_ItemLength_Impl ( S_Nv_ItemId_t  id)
S_Nv_ReturnValue_t S_Nv_Read_Impl ( S_Nv_ItemId_t  id,
uint16_t  offset,
uint16_t  dataLength,
void *  pData 
)
void S_Nv_SetPowerSupplyCheckingFunction_Impl ( S_Nv_PowerSupplyCheckingFunction_t  pf)
static bool SmartCompacting ( uint8_t *  compactBlock,
uint16_t  curItemLength 
)
static
static void UpdateSectorHead ( uint16_t  increment,
ItemAlignment_t  itemAlignment 
)
static

Update the sector head with increment as per Alignement.

Parameters
incrementThe length updated

References ITEM_16BYTE_ALIGNMENT, ITEM_64BYTE_ALIGNMENT, ITEM_NO_ALIGNMENT, and s_sectorHead.

Referenced by CompactItem(), CompactSector(), LoadSector(), SmartCompacting(), WriteBlockHeader(), and WriteDataBlockAndHeader().

static bool WriteAndCheck ( uint16_t  offset,
uint8_t *  pData,
uint16_t  length 
)
static

uint16_t compactBlockOffset = 0u
static

Referenced by CompactSector(), and SmartCompacting().

SYS_Timer_t compactItemTimer
static
SYS_Timer_t compactSectorTimer
static
uint16_t currentCompactLength = 0u
static

Referenced by CompactSector(), and SmartCompacting().

SYS_Timer_t eraseSectorTimer
static
uint16_t s_compactItemId = 0x0000u
static

The item to perform a compact operation on and the length of this item.

Referenced by CompactItem(), CompactSector(), S_Nv_ItemInit_Impl(), and S_Nv_Write_Impl().

uint16_t s_compactItemLength = 0x0000u
static
bool s_earlyInitDone = false
static

Check if the early init function is called already.

Referenced by S_Nv_EarlyInit(), and S_Nv_Init().

Item_t s_itemCache[MAX_ITEM_COUNT]
static
uint8_t s_itemCount = 0u
static
uint16_t s_nextPageAddressAfterCompact
static
const uint16_t s_persistentItems[] = {PERSISTENT_NV_ITEMS_APPLICATION}
static

Referenced by IsPersistent().

S_Nv_PowerSupplyCheckingFunction_t s_powerSupplyCheckingFunction = NULL
static

Callback function called before changing flash contents.

Referenced by PowerSupplyTooLow(), and S_Nv_SetPowerSupplyCheckingFunction_Impl().

uint16_t s_sectorHead
static
uint8_t s_sectorToErase = 0xFFu
static

The sector to erase in the EVENT_ERASE_SECTOR handler.

Referenced by CompactSector(), and eraseSectorTimerFired().