mirror of
https://github.com/thelsing/knx.git
synced 2025-10-12 11:15:54 +02:00
git-subtree-dir: examples/knx-cc1310/coresdk_cc13xx_cc26xx git-subtree-split: 0d78d3280357416a5c0388148cda13717c9ffaa5
360 lines
15 KiB
C
360 lines
15 KiB
C
/*
|
|
* Copyright (c) 2015-2019, Texas Instruments Incorporated
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of Texas Instruments Incorporated nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
/*!*****************************************************************************
|
|
* @file NVSCC26XX.h
|
|
* @brief Non-Volatile Storage driver for CC13XX/CC26XX devices.
|
|
*
|
|
* ## Interrupt Latency During Flash Operations #
|
|
*
|
|
* When writing or erasing flash, interrupts must be disabled to avoid
|
|
* executing code in flash while the flash is being reprogrammed. This
|
|
* constraint is handled by the driver. Application code does not need
|
|
* to safeguard against this.
|
|
*
|
|
* Additionally, to avoid extremely large interrupt latencies that would be
|
|
* incurred if entire blocks were written with interrupts disabled, block
|
|
* writes to flash are broken into multiple smaller sizes.
|
|
*
|
|
* Even with this scheme in place, latencies of roughly 64 microseconds will
|
|
* be incurred while flash is being written to.
|
|
*
|
|
* A similar caveat applies to flash erase operations. Erasing an entire
|
|
* flash sector (the minimal amount that can be erased at a time) can take
|
|
* roughly 8 milliseconds. This entire operation must be performed with
|
|
* interrupts disabled. Here again, this requirement is met internally
|
|
* by the driver and flash region erases are performed one sector at a
|
|
* time to minimize this significant latency impact.
|
|
*
|
|
* Care must be taken by the user to not perform flash write or erase
|
|
* operations during latency critical phases of an application. See the
|
|
* NVS_lock() and NVS_unlock() API descriptions for more information.
|
|
*
|
|
* ## Maximum flash writes before erase #
|
|
*
|
|
* On CC13XX & CC26XX memory rows can be 128 or 256 bytes in length; refer to
|
|
* the device datasheet for the exact size. A maximum of 83 write operations
|
|
* can be performed on a memory row. Once the limit is reached, the row must
|
|
* be erased before it is written to again. It is the developer's
|
|
* responsibility to ensure that this limit is not exceeded in their
|
|
* applications. The developer may also opt to use the third party SPIFFS
|
|
* library implementation supported by TIRTOS which does track writes.
|
|
*
|
|
* \note The 83 write limit persists through device reset & power cycles.
|
|
* If 60 write operations were performed on a memory row & the device is
|
|
* reset; the page can still only be written to 23 more times before it must
|
|
* be erased.
|
|
*
|
|
* A write "Scoreboard" can be enabled in this driver; the scoreboard keeps
|
|
* track of how many times a page has been written to. It is provided as a
|
|
* debug tool to ensure the 83 write limit is not exceeded. If a page is
|
|
* written to more than 83 times, the NVSCC26XX driver will spin forever.
|
|
* Each byte in the scoreboard corresponds to a memory page in the NVS region.
|
|
* The byte is incremented when the memory is written to & set to 0 when
|
|
* erased.
|
|
*
|
|
* To enable the "scoreboard" the "NVSCC26XX_INSTRUMENTED" symbol must be
|
|
* defined when the driver is compiled. Three new fields are added to the
|
|
* #NVSCC26XX_HWAttrs structure:
|
|
* * scoreboard - a buffer provided by the application where each byte
|
|
* represents how many times a page has been written to.
|
|
* * scoreboardSize - number of bytes in the scoreboard.
|
|
* * flashPageSize - number of bytes in a flash page (i.e. 128 or 256)
|
|
*
|
|
* When configured correctly, the scoreboard can be viewed in a memory browser.
|
|
*
|
|
* \note The scoreboard will only keep track of writes to flash within a
|
|
* NVS region using a NVS driver. Writes performed outside the NVS
|
|
* region or without the NVS driver are untracked.
|
|
*
|
|
* \note The scoreboard is in RAM & will be lost on reset or power cycle.
|
|
*
|
|
*
|
|
* ============================================================================
|
|
*/
|
|
|
|
#ifndef ti_drivers_nvs_NVSCC26XX__include
|
|
#define ti_drivers_nvs_NVSCC26XX__include
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#if defined (__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*!
|
|
* @brief Error status code returned by NVS_erase(), NVS_write().
|
|
*
|
|
* This error status is returned if the system voltage is too low to safely
|
|
* perform the flash operation. Voltage must be 1.5V or greater.
|
|
*/
|
|
#define NVSCC26XX_STATUS_LOW_VOLTAGE (NVS_STATUS_RESERVED - 1)
|
|
|
|
/*!
|
|
* @internal @brief NVS function pointer table
|
|
*
|
|
* 'NVSCC26XX_fxnTable' is a fully populated function pointer table
|
|
* that can be referenced in the NVS_config[] array entries.
|
|
*
|
|
* Users can minimize their application code size by providing their
|
|
* own custom NVS function pointer table that contains only those APIs
|
|
* used by the application.
|
|
*
|
|
* An example of a custom NVS function table is shown below:
|
|
* @code
|
|
* //
|
|
* // Since the application does not use the
|
|
* // NVS_control(), NVS_lock(), and NVS_unlock() APIs,
|
|
* // these APIs are removed from the function
|
|
* // pointer table and replaced with NULL
|
|
* //
|
|
* const NVS_FxnTable myNVS_fxnTable = {
|
|
* NVSCC26XX_close,
|
|
* NULL, // remove NVSCC26XX_control(),
|
|
* NVSCC26XX_erase,
|
|
* NVSCC26XX_getAttrs,
|
|
* NVSCC26XX_init,
|
|
* NULL, // remove NVSCC26XX_lock(),
|
|
* NVSCC26XX_open,
|
|
* NVSCC26XX_read,
|
|
* NULL, // remove NVSCC26XX_unlock(),
|
|
* NVSCC26XX_write
|
|
* };
|
|
* @endcode
|
|
*/
|
|
extern const NVS_FxnTable NVSCC26XX_fxnTable;
|
|
|
|
/*!
|
|
* @brief NVSCC26XX hardware attributes
|
|
*
|
|
* The NVSCC26XX hardware attributes define hardware specific settings
|
|
* for a NVS driver instance.
|
|
*
|
|
* \note Care must be taken to ensure that the linker does not place application
|
|
* content (such as .text or .const) in the flash regions defined by the
|
|
* this hardware attributes structure.
|
|
*
|
|
* For CCS and IAR tools, defining and reserving flash memory regions can
|
|
* be done entirely within the Board.c file. For GCC, additional content is
|
|
* required in the application's linker script to achieve the same
|
|
* result.
|
|
*
|
|
* The example below defines a char array @p flashBuf. Preprocessor logic is
|
|
* used so that this example will work with either the TI, IAR or GCC tools.
|
|
* For the TI and IAR tools, pragmas are used to place @p flashBuf at the
|
|
* flash location specified by #NVSCC26XX_HWAttrs.regionBase.
|
|
*
|
|
* For the GCC tool, the @p flashBuf array is placed into a named linker output
|
|
* section, @p .nvs. This section is defined in the application's linker
|
|
* script. The section placement command is carefully chosen to only RESERVE
|
|
* space for the @p flashBuf array, and not to actually initialize it during
|
|
* the application load process, thus preserving the content of flash.
|
|
*
|
|
* Regardless of tool chain, the @p flashBuf array in the example below is
|
|
* placed at the @p NVS_REGIONS_BASE address and has an overall size of
|
|
* @p REGIONSIZE bytes. Theoretically, the memory reserved by @p flashBuf can
|
|
* be divided into four separate regions, each having a size of @p SECTORSIZE
|
|
* bytes. Each region must always be aligned to the flash sector size,
|
|
* @p SECTORSIZE. This example below shows two regions defined.
|
|
*
|
|
* An array of two #NVSCC26XX_HWAttrs structures is defined. Each index
|
|
* of this structure defines a region of on-chip flash memory. Both regions
|
|
* utilize memory reserved by the @p flashBuf array. The two regions do not
|
|
* overlap or share the same physical memory locations. The two regions do
|
|
* however exist adjacent to each other in physical memory. The first
|
|
* region is defined as starting at the @p NVS_REGIONS_BASE address and has a
|
|
* size equal to the flash sector size, as defined by @p SECTORSIZE. The second
|
|
* region is defined as starting at (NVS_REGIONS_BASE + SECTORSIZE), that is,
|
|
* the @p NVS_REGIONS_BASE address offset by @p SECTORSIZE bytes. The second region
|
|
* has a size equal to (3 * SECTORSIZE) bytes. These regions together fully
|
|
* occupy @p REGIONSIZE bytes of physical on-chip flash memory as reserved by
|
|
* the @p flashBuf array.
|
|
*
|
|
* @code
|
|
* #define NVS_REGIONS_BASE 0x1B000
|
|
* #define SECTORSIZE 0x1000
|
|
* #define REGIONSIZE (SECTORSIZE * 4)
|
|
*
|
|
* //
|
|
* // Reserve flash sectors for NVS driver use
|
|
* // by placing an uninitialized byte array
|
|
* // at the desired flash address.
|
|
* //
|
|
* #if defined(__TI_COMPILER_VERSION__)
|
|
*
|
|
* //
|
|
* // Place uninitialized array at FLASH_REGION_BASE
|
|
* //
|
|
* #pragma LOCATION(flashBuf, FLASH_REGION_BASE);
|
|
* #pragma NOINIT(flashBuf);
|
|
* char flashBuf[REGIONSIZE];
|
|
*
|
|
* #elif defined(__IAR_SYSTEMS_ICC__)
|
|
*
|
|
* //
|
|
* // Place uninitialized array at FLASH_REGION_BASE
|
|
* //
|
|
* __no_init char flashBuf[REGIONSIZE] @ FLASH_REGION_BASE;
|
|
*
|
|
* #elif defined(__GNUC__)
|
|
*
|
|
* //
|
|
* // Place the flash buffers in the .nvs section created in the gcc linker file.
|
|
* // The .nvs section enforces alignment on a sector boundary but may
|
|
* // be placed anywhere in flash memory. If desired the .nvs section can be set
|
|
* // to a fixed address by changing the following in the gcc linker file:
|
|
* //
|
|
* // .nvs (FIXED_FLASH_ADDR) (NOLOAD) : AT (FIXED_FLASH_ADDR) {
|
|
* // *(.nvs)
|
|
* // } > REGION_TEXT
|
|
* //
|
|
*
|
|
* __attribute__ ((section (".nvs")))
|
|
* char flashBuf[REGIONSIZE];
|
|
*
|
|
* #endif
|
|
*
|
|
* NVSCC26XX_HWAttrs nvsCC26XXHWAttrs[2] = {
|
|
* //
|
|
* // region 0 is 1 flash sector in length.
|
|
* //
|
|
* {
|
|
* .regionBase = (void *)flashBuf,
|
|
* .regionSize = SECTORSIZE,
|
|
* },
|
|
* //
|
|
* // region 1 is 3 flash sectors in length.
|
|
* //
|
|
* {
|
|
* .regionBase = (void *)(flashBuf + SECTORSIZE),
|
|
* .regionSize = SECTORSIZE * 3,
|
|
* }
|
|
* };
|
|
* @endcode
|
|
*
|
|
* Example GCC linker script file content. This example places an output
|
|
* section, @p .nvs, at the memory address @p 0x1B000. The @p NOLOAD directive
|
|
* is used so that this memory is not initialized during program load to the
|
|
* target.
|
|
*
|
|
* @code
|
|
* MEMORY
|
|
* {
|
|
* FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x0001ffa8
|
|
* FLASH_CCFG (RX) : ORIGIN = 0x0001ffa8, LENGTH = 0x00000058
|
|
* SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00005000
|
|
* }
|
|
*
|
|
* .nvs (0x1b000) (NOLOAD) : AT (0x1b000) {
|
|
* *(.nvs)
|
|
* } > REGION_TEXT
|
|
* @endcode
|
|
*
|
|
* If the write "scoreboard" is enabled, three new fields are added to the
|
|
* NVSCC26XX_HWAttrs structure:
|
|
* * scoreboard - a buffer provided by the application where each byte
|
|
* represents how many times a page has been written to. It is important
|
|
* that this buffer be large enough such that there is a byte for each
|
|
* page of memory in the NVS region. For example:
|
|
* - 64k NVS region
|
|
* - 256 byte page size
|
|
* - 64k / 256 = 256; the scoreboard buffer must be 256 bytes in length
|
|
*
|
|
* * scoreboardSize - number of bytes in the scoreboard.
|
|
*
|
|
* * flashPageSize - number of bytes in a flash page (i.e. 128 or 256)
|
|
*/
|
|
typedef struct
|
|
{
|
|
void *regionBase; /*!< The regionBase field specifies the base
|
|
address of the on-chip flash memory to be
|
|
managed. The regionBase must be aligned
|
|
to the flash sector size. This memory
|
|
cannot be shared and must be for exclusive
|
|
use by one NVS driver instance. */
|
|
|
|
size_t regionSize; /*!< The regionSize field specifies the
|
|
overall size of the on-chip flash memory
|
|
to be managed. The regionSize must be at
|
|
least 1 flash sector size AND an integer
|
|
multiple of the flash sector size. For most
|
|
CC26XX/CC13XX devices, the flash sector
|
|
size is 4096 bytes. The NVSCC26XX driver
|
|
will determine the device's actual sector
|
|
size by reading internal system
|
|
configuration registers. */
|
|
|
|
#if defined(NVSCC26XX_INSTRUMENTED)
|
|
uint8_t *scoreboard; /*!< Pointer to scoreboard */
|
|
size_t scoreboardSize; /*!< Scoreboard size in bytes */
|
|
uint32_t flashPageSize; /*!< Size of a memory page in bytes */
|
|
#endif
|
|
} NVSCC26XX_HWAttrs;
|
|
|
|
/*
|
|
* @brief NVSCC26XX Object
|
|
*
|
|
* The application must not access any member variables of this structure!
|
|
*/
|
|
typedef struct
|
|
{
|
|
bool opened; /* Has this region been opened */
|
|
} NVSCC26XX_Object;
|
|
|
|
/*!
|
|
* @cond NODOC
|
|
* NVSCC26XX driver public APIs
|
|
*/
|
|
|
|
extern void NVSCC26XX_close(NVS_Handle handle);
|
|
extern int_fast16_t NVSCC26XX_control(NVS_Handle handle, uint_fast16_t cmd,
|
|
uintptr_t arg);
|
|
extern int_fast16_t NVSCC26XX_erase(NVS_Handle handle, size_t offset,
|
|
size_t size);
|
|
extern void NVSCC26XX_getAttrs(NVS_Handle handle, NVS_Attrs *attrs);
|
|
extern void NVSCC26XX_init();
|
|
extern int_fast16_t NVSCC26XX_lock(NVS_Handle handle, uint32_t timeout);
|
|
extern NVS_Handle NVSCC26XX_open(uint_least8_t index, NVS_Params *params);
|
|
extern int_fast16_t NVSCC26XX_read(NVS_Handle handle, size_t offset,
|
|
void *buffer, size_t bufferSize);
|
|
extern void NVSCC26XX_unlock(NVS_Handle handle);
|
|
extern int_fast16_t NVSCC26XX_write(NVS_Handle handle, size_t offset,
|
|
void *buffer, size_t bufferSize, uint_fast16_t flags);
|
|
/*! @endcond */
|
|
|
|
#if defined (__cplusplus)
|
|
}
|
|
#endif /* defined (__cplusplus) */
|
|
|
|
/*@}*/
|
|
#endif /* ti_drivers_nvs_NVSCC26XX__include */
|