Flash

The flash is split into erasable pages of 4 kB. The various sections of flash and their associate linker files are as follows.

  • Flash Reset Vector Table: This table holds the first 16 reset vectors that are critical for booting up the device. These vectors are set at build time and cannot be dynamically changed. See Flash Vector Table below for more information.
  • Simple NV (SNV) Area: used for nonvolatile memory storage by the GAP Bond Manager and also available for use by the application. See Using Simple NV for Flash Storage for configuring SNV. When configured, the SNV flash storage area is part of the stack image.

For projects where the stack project builds a library:

  • Application and Stack Image Code Space: A single region that contains both application and stack code in flash. This image is configured in the linker configuration file of the application: <device name>_app_and_stack.icf (IAR) and <device name>_app.cmd (CCS).

Flash Vector Table

This table contains the first 16 critical interrupt vectors required for the bootup process. The location of this table is controlled by m3Hwi.resetVectorAddress within the TI-RTOS config file (*.cfg), it defaults to address 0x00000000. At bootup time, the TI-RTOS kernel will run a first function to initialize the Hwi module. At this time the flash vector table will be copied to the RAM location shown in Table 8. and the VTOR register will be moved to point to the RAM table. For more information about the vector table format, please refer to Cortex-M3 Vector Table.

For more information on the kernel boot process and first functions, please see: SYS/BIOS Boot Wiki.

Using Simple NV for Flash Storage

The Simple NV (SNV) area of flash is used for storing persistent data, such as encryption keys from bonding or to store custom defined parameters. The protocol stack can be configured to reserve up to two 4 kB flash pages for SNV, although valid data is only stored in one active flash page. To minimize the number of erase cycles on the flash, the SNV manager performs compaction on the flash sector (or sectors) when the sector has 80% invalidated data. A compaction is the copying of valid data to a temporary area followed by an erase of the sector where the data was previously stored. Depending on the OSAL_SNV value as described in OSAL_SNV Values, this valid data is then either placed back in the newly erased sector or remains in a new sector. The number of flash sectors allocated to SNV can be configured by setting the OSAL_SNV preprocessor symbol in the stack project. Table 9. lists the valid values that can be configured as well as the corresponding trade-offs.

Table 9. OSAL_SNV Values
OSAL_SNV Value Description
0 SNV is disabled. Storing of bonding keys in NV is not possible. Maximizes code space for the application and/or stack project. GAP Bond Manager must be disabled. In the Stack project, set pre- processor symbol NO_OSAL_SNV and disable GAP Bond Manager. See Stack Configurations for configuring Bluetooth Low Energy protocol stack features.
1 (default) One flash sector is allocated to SNV. Bonding information is stored in NV. Set preprocessor symbol OSAL_SNV=1 in the Stack project.
2 Two flash sectors are allocated to SNV. Bonding information is stored in NV. SNV data is protected against power-loss during compaction.

Other values for OSAL_SNV are invalid. Using less than the maximum value has the net effect of allocating more code space to the application or stack project. SNV can be read from or written to using the following APIs.

uint8 osal_snv_read( osalSnvId_t id, osalSnvLen_t len, void *pBuf)

  Read data from NV
Parameters

id - valid NV item

len - length of data to read

pBuf - pointer to buffer to store data read

Returns

SUCCESS: NV item read successfully

NV_OPER_FAILED: failure reading NV item

uint8 osal_snv_write( osalSnvId_t id, osalSnvLen_t len, void *pBuf)

  Write data to NV
Parameters

id - valid NV item

len - length of data to write

pBuf - pointer to buffer containing data to be written. All contents are updated at once.

Returns

SUCCESS: NV item write successfully

NV_OPER_FAILED: failure writing NV item

Because SNV is shared with other modules in BLE-Stack such as the GAP Bond Manager, carefully manage the NV item IDs. By default, the IDs available to the customer are defined in bcomdef.h as shown in Listing 30.

Listing 30. Usable SNV IDs available to customers
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// Device NV Items -    Range 0 - 0x1F
#define BLE_NVID_IRK                    0x02  //!< The Device's IRK
#define BLE_NVID_CSRK                   0x03  //!< The Device's CSRK
#define BLE_NVID_ADDR_MODE              0x04  //!< The Device's address type (@ref GAP_Addr_Modes_t)
#define BLE_LRU_BOND_LIST               0x05  //!< The Device's order of bond indexes in least recently used order
#define BLE_NVID_RANDOM_ADDR            0x06  //!< The Device's random address if set by the current @ref GAP_DeviceInit

// Bonding NV Items -   Range  0x20 - 0x5F    - This allows for 10 bondings
#define BLE_NVID_GAP_BOND_START         0x20  //!< Start of the GAP Bond Manager's NV IDs
#define BLE_NVID_GAP_BOND_END           0x5f  //!< End of the GAP Bond Manager's NV IDs Range

// GATT Configuration NV Items - Range  0x70 - 0x79 - This must match the number of Bonding entries
#define BLE_NVID_GATT_CFG_START         0x70  //!< Start of the GATT Configuration NV IDs
#define BLE_NVID_GATT_CFG_END           0x79  //!< End of the GATT Configuration NV IDs

// Customer NV Items - Range  0x80 - 0x8F - This must match the number of Bonding entries
#define BLE_NVID_CUST_START             0x80  //!< Start of the Customer's NV IDs
#define BLE_NVID_CUST_END               0x8F  //!< End of the Customer's NV IDs

Listing 31. shows how to read and write an array of bytes from SNV flash:

Listing 31. Using SNV Example Code
/*********************************************************************
* GLOBAL VARIABLES
*/
#define BUF_LEN 4
#define SNV_ID_APP 0x80
uint8 buf[BUF_LEN] ={0,};

static void SimplePeripheral_taskFxn(UArg a0, UArg a1)
{
  // Initialize application
  SimpleBLEPeripheral_init();
  uint8 status = SUCCESS;

  status = osal_snv_read(SNV_ID_APP, BUF_LEN, (uint8 *)buf);
  if(status != SUCCESS)
  {
    Display_print1(dispHandle, 0, 0, "SNV READ FAIL: %d", status);
    //Write first time to initialize SNV ID
    osal_snv_write(SNV_ID_APP, BUF_LEN, (uint8 *)buf);
  }

  //Increment first element of array and write to SNV flash
  buf[0]++;
  status = osal_snv_write(SNV_ID_APP, BUF_LEN, (uint8 *)buf);
  if(status != SUCCESS)
  {
    Display_print1(dispHandle, 0, 0, "SNV WRITE FAIL: %d", status);
  }
  else
  {
    Display_print1(dispHandle, 0, 0, "Num of Resets: %d", buf[0]);
  }

  // Application main loop
  for (;;)
  {
  //...
  }
}

No prior initialization of a NV item ID is required; the OSAL SNV manager initializes the NV ID when first accessed by a successful osal_snv_write() call.

When reading or writing large amounts of data to SNV, TI recommends placing the read/write data in statically (linker) allocated arrays or buffers allocated from the heap. Placing large amounts of data in local arrays may result in a task stack overflow.

By default, osalSnvId_t and osalSnvLen_t are type defined as uint8. To use uint16-type definitions, define the preprocessor symbol OSAL_SNV_UINT16_ID in both the application and stack projects.

Using osal_snv_read and osal_snv_write is only permitted from within a task context. Calling this API is not possible from within Swis or Hwis.

Some care must be taken to not be close to 80% (or other compaction threshold) SNV utilization of a sector. BLE stack uses at most 1.5-2kB with 10 bonds stored. Frequent compactions are costly in terms of power consumption and can cause resets and lost SNV content (NVOCOP) and will also wear out the flash.

Customer Configuration (CCFG) Table

The CCFG is placed at the end of the last flash page and lets customer configure various chip and system parameters in the Customer Configuration (CCFG) table. The CCFG table is defined in ccfg_app_ble.c, which can be found in the Startup folder of the application project. The last (sizeof(ccfg_t)) bytes of the CCFG sector are reserved by the system for the CCFG table. By default, the linker allocates the unused flash of the last flash page to the application image for code and data use.

See the CC13x0 CC26x0 SimpleLink Wireless MCU Technical Reference Manual for details on CCFG fields and related configuration options, including how to set the CCFG to disable access to internal flash memory contents.

Note

The CCFG cannot be relocated, and must reside at the end of the last page of flash. Consult the CC13x0 CC26x0 SimpleLink Wireless MCU Technical Reference Manual for more information.