Nvm
Data definitions for the Cortex-M3 Non-Volatile Memory data storage system.
More...
Defines |
#define | NVM_FLASH_PAGE_COUNT (1) |
| Define the number of physical flash pages that comprise a NVM page.
|
#define | NVM_DATA_SIZE_B (MFB_PAGE_SIZE_B*NVM_FLASH_PAGE_COUNT) |
| Define the total size of a NVM page, in bytes.
|
#define | NVM_LEFT_PAGE ((int32u)nvmStorageLeft) |
| Define the absolute address of the LEFT page.
|
#define | NVM_RIGHT_PAGE ((int32u)nvmStorageRight) |
| Define the absolute address of the RIGHT page.
|
#define | NVM_MGMT_SIZE_B (4) |
| Define the number of bytes that comprise the NVM management bytes.
|
Functions |
StStatus | halCommonReadFromNvm (void *data, int32u offset, int16u length) |
| Copy the NVM data from flash into the provided RAM location.
|
int16u * | halCommonGetAddressFromNvm (int32u offset) |
| Return the address of the token in NVM.
|
StStatus | halCommonWriteToNvm (const void *data, int32u offset, int16u length) |
| Write the NVM data from the provided location RAM into flash.
|
Detailed Description
Data definitions for the Cortex-M3 Non-Volatile Memory data storage system.
Cortex-M3 Non-Volatile Memory data storage system.
This header defines all of the data sets in the NVM data storage. Each piece of data in NVM storage uses an offset to indicate where the data lives and a size to indicate the size of that data. Both the offset and size are defined in bytes and must be a mupltiple of 16bits. The offset is from the start of an NVM page, defined by NVM_LEFT_PAGE and NVM_RIGHT_PAGE. The offset and size must be below the maximum size of NVM storage as defined by NVM_DATA_SIZE_B. All NVM data must start above NVM_MGMT_SIZE_B, since this is where the management bytes live.
- Note:
- This file is not directly used by the nvm.c or nvm.h files. This file is intended to be a convenient place to define all data that lives in NVM so it can be seen together in one group. nvm.h includes this file which means any code that includes nvm.h to call the read and write functions also has access to these defines.
This header defines the API for NVM data storage. This header also describes the algorithm behind the NVM data storage system with notes on algorithm behavior.
See hal/micro/cortexm3/nvm.h for source code.
- Note:
- The algorithm description uses "page" to indicate an area of memory that is a multiple of physical flash pages. There are two pages: LEFT and RIGHT. The term "flash page" is used to refer to a page of physical flash.
NVM data storage works by alternating between two pages: LEFT and RIGHT. The basic algorithm is driven by a call to halCommonSaveToNvm(). It will:
- erase the inactive page
- write the new data to the inactive page
- copy existing data from the active page to the inactive page
- mark the inactive page as the new active page
- mark the old active page as the new inactive page To accomplish alternating between two pages and knowing which page has the valid set of data, the algorithm uses 4 bytes of mgmt data that exists at the top of both LEFT and RIGHT (the term "mgmt" is shorthand referring to the management data). The management data is comprised of a Valid marker, an Active marker, a Dead marker, and a Spare byte. Viewing the management data as a single 32 bit quantity yields:
- Valid is mgmt[0]
- Active is mgmt[1]
- Dead is mgmt[2]
- Spare is mgmt[3] The algorithm is based on a simple, circular state machine. The following discussion details all of the possible mgmt bytes and the states they correspond to. The "Reads from" line indicates which page a call to halCommonReadFromNvm() will read from (an 'x' page will stuff the read data with 0xFF). The vertical "erase" and "write" words indicate the flash altering actions taken between those states. Invalid mgmt bytes is equivalent to erased mgmt bytes (state 0) and will trigger an erase of both LEFT and RIGHT. State 3 and state 7 are the only exit states. When the algorithm is run, regardless of starting state, it will advance to the next exit state. This means if the "Read from" is LEFT then the state machine will advance until state 7 and then exit. If "Read from" is RIGHT, then the state machine will advance until state 3 and then exit.
Starting from erased or invalid mgmt, write to LEFT
State # 0 0 1 2 3
Reads from: x x e w L L L
Valid xx|xx FF|FF r r 00|FF 00|FF 00|00
Active xx|xx FF|FF a i 00|FF 00|FF 00|00
Dead xx|xx FF|FF s t FF|FF FF|00 FF|00
Spare xx|xx FF|FF e e FF|FF FF|FF FF|FF
Starting from LEFT page, transition to RIGHT page:
State # 3 4 5 6 7
Reads from: L e L w R R R
Valid 00|00 r 00|FF r 00|00 00|00 00|00
Active 00|00 a 00|FF i 00|FF 00|FF 00|00
Dead FF|00 s FF|FF t FF|FF 00|FF 00|FF
Spare FF|FF e FF|FF e FF|FF FF|FF FF|FF
Starting from RIGHT page, transition to LEFT page:
State # 7 8 9 10 3
Reads from: R e R w L L L
Valid 00|00 r FF|00 r 00|00 00|00 00|00
Active 00|00 a FF|00 i FF|00 FF|00 00|00
Dead 00|FF s FF|FF t FF|FF FF|00 FF|00
Spare FF|FF e FF|FF e FF|FF FF|FF FF|FF
Based on the 10 possible states, there are 5 valid 32bit mgmt words:
- 0xFFFFFFFF
- 0xFFFFFF00
- 0xFFFF0000
- 0xFF000000
- 0xFF00FFFF The algorithm determines the current state by using these 5 mgmt words with the 10 possible combinations of LEFT mgmt and RIGHT mgmt.
Detailed State Description:
- State 0: In this state the mgmt bytes do not conform to any of the other states and therefore the entire NVM system, both the LEFT and RIGHT, is invalid. Invalid could be as simple as both LEFT and RIGHT are erased or as complex as serious memory corruption or a bug caused bad data to be written to the NVM. By using a small set of very strict, precise, valid states (versus other management systems such as a simple counter), the algorithm/data gains some protection against not only corruption, but also executing the NVM algorithm on a chip that previously did not have the NVM system running on it.
- State 1, 4, 8 In these states, mgmt is saying that one page is valid and active, while the other page is erased. This tells the algorithm which page to read from and indicates that the other page has already been erased.
- State 2 This state is only necessary for transitioning from state 0. From state 0, the goal is to arrive at state 3. Ideally, the RIGHT mgmt would be written with 0xFF000000, but the flash library only permits 16 bit writes. If a reset were to occur in the middle of this section of the algorithm, we want to ensure that the mgmt is left in a known state, state 2, so that the algorithm could continue from where it got interrupted.
- State 5, 9 These states indicate that the other page has just become valid because the new data has just been written. Once at these states, reading from the NVM will now pull data from the other page.
- State 6, 10 These states indicate that the old page is now dead and not in use. While the algorithm already knows to read from the new page, the Dead mgmt byte is primarily used to indicate that the other page needs to be erased. Conceptually, the Dead byte can also be considered a type of "garbage collection" flag indicating the old page needs to be destroyed and has not yet been erased.
- State 3, 7 These states are the final exit points of the circular state machine. Once at these states, the current page is marked Valid and Active and the old page is marked as Dead. The algorithm knows which page to read from and which page needs to be erased on the next write to the NVM.
Notes on algorithm behavior:
- Refer to nvm-def.h for a list of offset/length that define the data stored in NVM storage space.
- All writes to flash are 16bit granularity and therefore the internal flash writes cast the data to int16u. Length is also required to be a multiple of 16bits.
- Flash page erase uses a granularity of a single flash page. The size of a flash page depends on the chip and is defined in memmap.h with the define MFB_PAGE_SIZE_B.
- Erasing will only occur when halCommonSaveToNvm() is called.
- Erasing will always occur when halCommonSaveToNvm() is called unless the page intended to be erased is already entirely 0xFFFF.
- When reading and management is invalid, the read will return 0xFF for data.
- Calling halCommonSaveToNvm() while in any state is always valid and the new data will be written to flash.
- halCommonSaveToNvm() will always advance the state machine to 3 or 7.
- When writing and management is invalid, both LEFT and RIGHT will be erased and the new data will be written to LEFT.
- Writing causes the new data being passed into halCommonSaveToNvm() to be written to flash. The data already existing in the currently valid page will be copied over to the new page.
- Reading or writing to an offset equal to or greater than NVM_DATA_SIZE_B is illegal and will cause an assert.
- Offset and length must always be multiples of 16bits. If not, both a read and a write will trigger an assert.
- Offset and length must be supplied in bytes.
- All data in NVM storage must exist above the mgmt bytes, denoted by NVM_MGMT_SIZE_B.
- The bottom 64 bytes of NVM storage are allocated to radio calibration values. These 64 bytes *must* exist for the radio to function.
- There is no error checking beyond checking for 16bit alignment. This means it is possible to use data offset and size combinations that exceed NVM storage space or overlap with other data. Be careful!
Define Documentation
#define NVM_DATA_SIZE_B (MFB_PAGE_SIZE_B*NVM_FLASH_PAGE_COUNT) |
Define the total size of a NVM page, in bytes.
This must be a multiple of the memory map define MFB_PAGE_SIZE_B. Note that 4 bytes of the total size of an NVM page are dedicated to page management.
- Note:
- DO NOT EDIT THIS DEFINE. Instead, edit NVM_FLASH_PAGE_COUNT.
Definition at line 249 of file nvm.h.
Referenced by halCommonReadFromNvm(), and halCommonWriteToNvm().
#define NVM_FLASH_PAGE_COUNT (1) |
Define the number of physical flash pages that comprise a NVM page.
Since NVM_DATA_SIZE_B must be a multiple of MFB_PAGE_SIZE_B, increasing the size of NVM storage should be done by modifying this define.
- Note:
- The total flash area consumed by NVM storage is double this value. This is due to the fact that there are two NVM pages, LEFT and RIGHT, which the algorithm alternates between.
Definition at line 240 of file nvm.h.
#define NVM_LEFT_PAGE ((int32u)nvmStorageLeft) |
#define NVM_MGMT_SIZE_B (4) |
Define the number of bytes that comprise the NVM management bytes.
All data must begin at an offset above the management bytes.
- Note:
- This value must not change.
Definition at line 274 of file nvm.h.
#define NVM_RIGHT_PAGE ((int32u)nvmStorageRight) |
Function Documentation
int16u* halCommonGetAddressFromNvm |
( |
int32u |
offset |
) |
|
StStatus halCommonReadFromNvm |
( |
void * |
data, |
|
|
int32u |
offset, |
|
|
int16u |
length | |
|
) |
| | |
Copy the NVM data from flash into the provided RAM location.
It is illegal for the offset to be greater than NVM_DATA_SIZE_B.
- Parameters:
-
| data | A (RAM) pointer to where the data should be copied. |
| offset | The location from which the data should be copied. Must be 16bit aligned. |
| length | The length of the data in bytes. Must be 16bit aligned. |
- Returns:
- An StStatus value indicating the success of the function.
- ST_SUCCESS if the read completed cleanly.
- ST_ERR_FATAL if the NVM storage management indicated an invalid state. The function will return entirely 0xFF in the data parameter.
Definition at line 98 of file nvm.c.
References NVM_DATA_SIZE_B, NVM_LEFT_PAGE, and NVM_RIGHT_PAGE.
StStatus halCommonWriteToNvm |
( |
const void * |
data, |
|
|
int32u |
offset, |
|
|
int16u |
length | |
|
) |
| | |
Write the NVM data from the provided location RAM into flash.
It is illegal for the offset to be greater than NVM_DATA_SIZE_B.
- Parameters:
-
| data | A (RAM) pointer from where the data should be taken. |
| offset | The location to which the data should be written. Must be 16bit aligned. |
| length | The length of the data in bytes. Must be 16bit aligned. |
- Returns:
- An StStatus value indicating the success of the function.
- ST_SUCCESS if the write completed cleanly.
- Any other status value is an error code generated by the low level flash erase and write API. Refer to flash.h for details.
Definition at line 280 of file nvm.c.
References NVM_DATA_SIZE_B, NVM_LEFT_PAGE, NVM_RIGHT_PAGE, and TRUE.
Referenced by halCommonGetAddressFromNvm().