Tokens#
There are three main types of tokens:
Manufacturing tokens: Tokens that are set at the factory and must not be changed through software operations.
Stack-level tokens: Tokens that can be changed via the appropriate stack API calls.
Application level tokens: Tokens that can be set via the token system API calls in this file.
The token system API controls writing tokens to non-volatile data and reading tokens from non-volatile data. If an application wishes to use application specific normal tokens, it must do so by creating its own token header file similar to token-stack.h. The macro APPLICATION_TOKEN_HEADER
should be defined to equal the name of the header file in which application tokens are defined. If an application wishes to use application specific manufacturing tokens, it must do so by creating its own manufacturing token header file similar to token-manufacturing.h. The macro APPLICATION_MFG_TOKEN_HEADER
should be defined to equal the name of the header file in which manufacturing tokens are defined.
Because the token system is based on memory locations within non-volatile storage, the token information could become out of sync without some kind of version tracking. The two defines, CURRENT_MFG_TOKEN_VERSION
and CURRENT_STACK_TOKEN_VERSION
, are used to make sure the stack stays in sync with the proper token set. If the application defines its own tokens, it is recommended that the application also define an application token to be a application version to ensure the application stays in sync with the proper token set.
The most general format of a token definition is:
#define CREATOR_name 16bit_value
#define NVM3KEY_name 20bit_value
#ifdef DEFINETYPES
typedef data_type type
#endif
#ifdef DEFINETOKENS
DEFINE_*_TOKEN(name, type, ... ,defaults)
#endif
The defined CREATOR is used as a distinct identifier tag for the token when using Simulated EEPROM or with manufacturing tokens. The CREATOR is necessary because the token name is defined differently depending on underlying implementation, so the CREATOR makes sure token definitions and data stay tagged and known. The only requirement on these creator definitions is that they all must be unique. A favorite method for picking creator codes is to use two ASCII characters inorder to make the codes more memorable. The 'name' part of the #define CREATOR_name
must match the 'name' provided in the DEFINE_*_TOKEN
because the token system uses this name to automatically link the two.
The defined NVM3KEY is used to map the token to an NVM3 key and is needed using NVM3 as the underlying storage mechanism. This key can also be used as an identifier for a token's NVM3 object when using the native NVM3 API. The NVM3 keys must be unique for one instance of the NVM3 backing storage. All tokens share the same NVM3 instance and hence all NVM3KEYS for tokens must be unique. The 'name' part of the #define NVM3KEY_name
must match the 'name' provided in the DEFINE_*_TOKEN
because the token system uses this name to automatically link the two. For indexed tokens, the 127 NVM3KEY values following the defined NVM3KEY for a token should also be reserved. This is done as one NVM3KEY is used for each index in an indexed token and hence these NVM3KEYS should not collide with the eys of other tokens.
As NVM3 is shared among several stacks and application code, the NVM3KEY values chosen must be defined in the correct region to avoid collisions.
The following NVM3KEY regions are defined: 0x0xxxx : User objects 0x1xxxx : zigbee stack objects 0x2xxxx : Thread stack objects 0x3xxxx : Connect stack objects 0x4xxxx : Bluetooth stack objects
The typedef provides a convenient and efficient abstraction of the token data. Since some tokens are structs with multiple pieces of data inside of them, type defining the token type allows more efficient and readable local copies of the tokens throughout the code.
The typedef is wrapped with an #ifdef DEFINETYPES
because the typdefs and token defs live in the same file, and DEFINETYPES is used to select only the typedefs when the file is included. Similarly, the DEFINE_*_TOKEN
is wrapped with an #ifdef DEFINETOKENS
as a method for selecting only the token definitions when the file is included.
The abstract definition, DEFINE_*_TOKEN(name, type, ... ,defaults)
, has seven possible complete definitions:DEFINE_BASIC_TOKEN(name, type, ...) DEFINE_INDEXED_TOKEN(name, type, arraysize, ...) DEFINE_COUNTER_TOKEN(name, type, ...) DEFINE_MFG_TOKEN(name, type, address, ...)
The three fields common to all DEFINE_*_TOKEN
are:
name - The name of the token, which all information is tied to.
type - Type of the token which is the same as the typedef mentioned before.
... - The default value to which the token is set upon initialization.
Note
The old DEFINE_FIXED* token definitions are no longer used. They remain defined for backwards compatibility. In current systems, the Simulated EEPROM or NVM3 is used for storing non-manufacturing tokens and the Simulated EEPROM or NVM3 intelligently manages where tokens are stored to provide wear leveling across the flash memory and increase the number of write cycles. Manufacturing tokens live at a fixed address, but they must use DEFINE_MFG_TOKEN so the token system knows they are manufacturing tokens.
DEFINE_BASIC_TOKEN is the simplest definition and will be used for the majority of tokens (tokens that are not indexed, not counters, and not manufacturing). Basic tokens are designed for data storage that is always accessed as a single element.
DEFINE_INDEXED_TOKEN should be used on tokens that look like arrays. For example, data storage that looks like:
uint32_t myData[5]
<br<blockquote> This example data storage can be a token with typedef of uint32_t and defined as INDEXED with arraysize of 5. The extra field in this token definition is: arraysize - The number of elements in the indexed token. Indexed tokens are designed for data storage that is logically grouped together, but elements are accessed individually. Note that when assigning an NVM3KEY for an indexed token, the 126 higher numbered NVM3KEYs following the NVM3KEY that you define are reserved for that token and no other tokens should be defined with NVM3KEYs in this region.
DEFINE_COUNTER_TOKEN should be used on tokens that are simple numbers where the majority of operations on the token is to increment the count. The reason for using DEFINE_COUNTER_TOKEN instead of DEFINE_BASIC_TOKEN is the special support that the token system provides for incrementing counters. The function call halCommonIncrementCounterToken()
only operates on counter tokens and is more efficient in terms of speed, data compression, and write cyles for incrementing simple numbers in the token system.
DEFINE_MFG_TOKEN is a DEFINE_BASIC_TOKEN token at a specific address and the token is manufacturing data that is written only once. The major difference is this token is designated manufacturing, which means the token system treats it differently from stack or app tokens. Primarily, a manufacturing token is written only once and lives at a fixed address outside of the Simulated EEPROM or NVM3 system. Being a write once token, the token system will also aid in debugging by asserting if there is an attempt to write a manufacturing token.
Here is an example of two application tokens. The definition is compatible with both Simulated EEPROM and NVM3 as both CREATOR and NVM3KEY defines are included.
#define CREATOR_SENSOR_NAME 0x5354
#define CREATOR_SENSOR_PARAMETERS 0x5350
#define NVM3KEY_SENSOR_NAME 0x0AB54
#define NVM3KEY_SENSOR_PARAMETERS 0x00150
#ifdef DEFINETYPES
typedef uint8_t tokTypeSensorName[10];
typedef struct {
uint8_t initValues[5];
uint8_t reportInterval;
uint16_t calibrationValue;
} tokTypeSensorParameters;
#endif
#ifdef DEFINETOKENS
DEFINE_BASIC_TOKEN(SENSOR_NAME,
tokTypeSensorName,
{'U','N','A','M','E','D',' ',' ',' ',' '})
DEFINE_BASIC_TOKEN(SENSOR_PARAMETERS,
tokTypeSensorParameters,
{{0x01,0x02,0x03,0x04,0x05},5,0x0000})
#endif
Here is an example of how to use the two application tokens:
{
tokTypeSensorName sensor;
tokTypeSensorParameters params;
halCommonGetToken(&sensor, TOKEN_SENSOR_NAME);
halCommonGetToken(¶ms, TOKEN_SENSOR_PARAMETERS);
if(params.calibrationValue == 0xBEEF) {
params.reportInterval = 5;
}
halCommonSetToken(TOKEN_SENSOR_PARAMETERS, ¶ms);
}
See token-stack.h to see the default set of tokens and their values.
The nodetest utility app can be used for generic manipulation such as loading default token values, viewing tokens, and writing tokens. The nodetest utility cannot work with customer defined application tokens or manufacturing tokens. Using the nodetest utility will erase customer defined application tokens in the Simulated EEPROM and NVM3.
The Simulated EEPROM or NVM3 will initialize tokens to their default values if the token does not yet exist, the token's creator code is changed, or the token's size changes.
Changing the number indexes in an INDEXED token will not alter existing entries. If the number of indexes is reduced, the entires that still fit in the token will retain their data and the entries that no longer fit will be erased. If the number of indexes is increased, the existing entries retain their data and the new entries are initialized to the token's defaults.
Further details on exact implementation can be found in code comments in token-stack.h file, the platform specific token-manufacturing.h file, the platform specific token.h file, and the platform specific token.c file.
Some functions in this file return an EmberStatus value. See error-def.h for definitions of all EmberStatus return values.
See hal/micro/token.h for source code.
Functions#
Initializes and enables the token system. Checks if the manufacturing and stack non-volatile data versions are correct.
Macros#
Macro that copies the token value from non-volatile storage into a RAM location. This macro can only be used with tokens that are defined using DEFINE_BASIC_TOKEN.
Macro that copies the token value from non-volatile storage into a RAM location. This macro can only be used with tokens that are defined using DEFINE_MFG_TOKEN.
Macro that copies the token value from non-volatile storage into a RAM location. This macro can only be used with tokens that are defined using DEFINE_INDEXED_TOKEN.
Macro that sets the value of a token in non-volatile storage. This macro can only be used with tokens that are defined using DEFINE_BASIC_TOKEN.
Macro that sets the value of a token in non-volatile storage. This macro can only be used with tokens that are defined using DEFINE_INDEXED_TOKEN.
Macro that increments the value of a token that is a counter. This macro can only be used with tokens that are defined using either DEFINE_COUNTER_TOKEN.
Function Documentation#
halStackInitTokens#
EmberStatus halStackInitTokens (void )
Initializes and enables the token system. Checks if the manufacturing and stack non-volatile data versions are correct.
N/A |
Returns
An EmberStatus value indicating the success or failure of the command.
294
of file /mnt/raid/workspaces/ws.SZ9MaSA5u/overlay/gsdk/platform/base/hal/micro/token.h
Macro Definition Documentation#
halCommonGetToken#
#define halCommonGetToken
Macro that copies the token value from non-volatile storage into a RAM location. This macro can only be used with tokens that are defined using DEFINE_BASIC_TOKEN.
Note
To better understand the parameters of this macro, refer to the example of token usage above.
318
of file /mnt/raid/workspaces/ws.SZ9MaSA5u/overlay/gsdk/platform/base/hal/micro/token.h
halCommonGetMfgToken#
#define halCommonGetMfgToken
Macro that copies the token value from non-volatile storage into a RAM location. This macro can only be used with tokens that are defined using DEFINE_MFG_TOKEN.
Note
To better understand the parameters of this macro, refer to the example of token usage above.
333
of file /mnt/raid/workspaces/ws.SZ9MaSA5u/overlay/gsdk/platform/base/hal/micro/token.h
halCommonGetIndexedToken#
#define halCommonGetIndexedToken
Macro that copies the token value from non-volatile storage into a RAM location. This macro can only be used with tokens that are defined using DEFINE_INDEXED_TOKEN.
Note
To better understand the parameters of this macro, refer to the example of token usage above.
349
of file /mnt/raid/workspaces/ws.SZ9MaSA5u/overlay/gsdk/platform/base/hal/micro/token.h
halCommonSetToken#
#define halCommonSetToken
Macro that sets the value of a token in non-volatile storage. This macro can only be used with tokens that are defined using DEFINE_BASIC_TOKEN.
Note
To better understand the parameters of this macro, refer to the example of token usage above. For EFR32 devices this function must not be called in IRQ context as it can cause data corruption.
365
of file /mnt/raid/workspaces/ws.SZ9MaSA5u/overlay/gsdk/platform/base/hal/micro/token.h
halCommonSetIndexedToken#
#define halCommonSetIndexedToken
Macro that sets the value of a token in non-volatile storage. This macro can only be used with tokens that are defined using DEFINE_INDEXED_TOKEN.
Note
To better understand the parameters of this macro, refer to the example of token usage above.
382
of file /mnt/raid/workspaces/ws.SZ9MaSA5u/overlay/gsdk/platform/base/hal/micro/token.h
halCommonIncrementCounterToken#
#define halCommonIncrementCounterToken
Macro that increments the value of a token that is a counter. This macro can only be used with tokens that are defined using either DEFINE_COUNTER_TOKEN.
Note
To better understand the parameters of this macro, refer to the example of token usage above.
395
of file /mnt/raid/workspaces/ws.SZ9MaSA5u/overlay/gsdk/platform/base/hal/micro/token.h