knx/source/ti/drivers/nvs/NVSSPI25X.h
Nanosonde e51b65f8c2 Squashed 'examples/knx-cc1310/coresdk_cc13xx_cc26xx/' content from commit 0d78d32
git-subtree-dir: examples/knx-cc1310/coresdk_cc13xx_cc26xx
git-subtree-split: 0d78d3280357416a5c0388148cda13717c9ffaa5
2020-10-21 10:00:49 +02:00

370 lines
16 KiB
C

/*
* Copyright (c) 2017-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 NVSSPI25X.h
* @brief Non-Volatile Storage driver implementation
* for SPI flash peripherals
*
* # Overview #
*
* The NVSSPI25X module allows you to manage SPI flash memory.
* This driver works with most 256 byte/page SPI flash memory devices
* such as:
*
* Winbond W25xx family
* Macronics MX25Rxx family
* Micron N25Qxx family
*
* The SPI flash commands used by this driver are as follows:
*
* @code
* #define SPIFLASH_PAGE_WRITE 0x02 // Page Program (up to 256 bytes)
* #define SPIFLASH_READ 0x03 // Read Data
* #define SPIFLASH_READ_STATUS 0x05 // Read Status Register
* #define SPIFLASH_WRITE_ENABLE 0x06 // Write Enable
* #define SPIFLASH_SUBSECTOR_ERASE 0x20 // SubSector (4K bytes) Erase
* #define SPIFLASH_SECTOR_ERASE 0xD8 // Sector (usually 64K bytes) Erase
* #define SPIFLASH_RDP 0xAB // Release from Deep Power Down
* #define SPIFLASH_DP 0xB9 // Deep Power Down
* #define SPIFLASH_MASS_ERASE 0xC7 // Erase entire flash.
* @endcode
*
* It is assumed that the SPI flash device used by this driver supports
* the byte programmability of the SPIFLASH_PAGE_WRITE command and that
* write page size is 256 bytes. The erase sector and subsector sizes are
* assumed to be 64K and 4K respectively.
*
* The NVS_erase() command will issue a sector or subsector erase command
* based on the input size and offset.
*
* The driver must query the SPI flash to ensure that the part is ready before
* commands are issued. If the part responds as busy, the poll function sleeps
* for a number of microseconds determined by the
* #NVSSPI25X_HWAttrs.statusPollDelayUs field. A value of 0 means that the
* driver will continuously poll the external flash until it is ready, which
* may affect other threads ability to execute.
*
* ## SPI Interface Management ##
*
* For each managed flash region, a corresponding SPI instance must be
* provided to the NVSSPI25X driver.
*
* The SPI instance can be opened and closed
* internally by the NVSSPI25X driver, or alternatively, a SPI handle can be
* provided to the NVSSPI25X driver, indicating that the SPI instance is being
* opened and closed elsewhere within the application. This mode is useful
* when the SPI bus is share by more than just the SPI flash device.
*
* If the SPI instance is to be managed internally by the NVSSPI25X driver, a SPI
* instance index and bit rate must be configured in the region's HWAttrs.
* If the same SPI instance is referenced by multiple flash regions
* the driver will ensure that SPI_open() is invoked only once, and that
* SPI_close() will only be invoked when all flash regions using the SPI
* instance have been closed.
*
* If the SPI bus that the SPI flash device is on is shared with other
* devices accessed by an application, then the SPI handle used to manage
* a SPI flash region can be provided in the region's HWAttrs "spiHandle"
* field. Keep in mind that the "spiHandle" field is a POINTER to a
* SPI Handle, NOT a SPI Handle. This allows the user to simply initialize
* this field with the name of the global variable used for the SPI handle.
* In this mode, the user MUST open the SPI instance prior to opening the NVS
* region instance so that the referenced spiHandle is valid.
*
* By default, the "spiHandle" field is set to NULL, indicating that the user
* expects the NVS driver to open and close the SPI instance internally using
* the 'spiIndex' and 'spiBitRate' provided in the HWAttrs.
*
* ## @anchor SPI_CS_MGMT SPI Flash Chip Select Management ##
*
* ### Option 1: NVSSPI25X Driver Manages Chip Select ###
* By default, the NVSSPI25X driver will assert and de-assert a GPIO
* driver managed pin to select the SPI flash device before and after
* each SPI transfer to and from the device.
*
* To enable this behavior, a valid GPIO driver instance index must be
* provided in the NVS region's [spiCsnGpioIndex]
* (@ref NVSSPI25X_HWAttrs.spiCsnGpioIndex) field of the
* NVSSPI25X_HWAttrs structure. The corresponding GPIO pin will be
* configured at runtime by the NVSSPI25X driver as "GPIO_CFG_OUT_STD"
* and assertion of this pin is assumed to be active LOW.
*
* ### Option 2: SPI Driver Manages Chip Select ###
* Some SPI peripherals can be configured to manage their own chip
* select. Setting the [spiCsnGpioIndex]
* (@ref NVSSPI25X_HWAttrs.spiCsnGpioIndex) field of the NVSSPI25X_HWAttrs
* structure to #NVSSPI25X_SPI_MANAGES_CS informs the NVSSPI25X driver
* that the SPI peripheral used by the NVS driver has been configured
* that way.
*
* ### Option 3: User Manages Chip Select ###
* Alternatively, the user can manage the assertion and de-assertion of
* the SPI flash chip select entirely themselves by providing implementations
* of the following 4 APIs in their application code:
*
* @code
* void NVSSPI25X_initSpiCs(NVS_Handle nvsHandle, uint16_t csId);
* @endcode
* - This function is invoked within the NVS_open() API and is where the
* user should do whatever is required to initialize the hardware
* used for asserting and de-assering the SPI chip select signal.
* - The 'nvsHandle` argument is the NVS handle associated with the
* corresponding NVS region.
* - The 'csId' argument passed to this API is a copy of the [spiCsnGpioIndex]
* (@ref NVSSPI25X_HWAttrs.spiCsnGpioIndex)
* field of the corresponding NVS region's NVSSPI25X_HWAttrs structure.
*
* @code
* void NVSSPI25X_deinitSpiCs(NVS_Handle nvsHandle, uint16_t csId);
* @endcode
* - This function is invoked within the NVS_close() API and is where the
* user should do whatever is required to de-initialize the hardware
* used for asserting and de-assering the SPI chip select signal.
* - The 'nvsHandle` argument is the NVS handle associated with the
* corresponding NVS region.
* - The 'csId' argument passed to this API is a copy of the [spiCsnGpioIndex]
* (@ref NVSSPI25X_HWAttrs.spiCsnGpioIndex)
* field of the corresponding NVS region's NVSSPI25X_HWAttrs structure.
*
* @code
* void NVSSPI25X_assertSpiCs(NVS_Handle nvsHandle, uint16_t csId);
* @endcode
* - This function is called PRIOR to every SPI transfer to and from the SPI
* flash device performed by the NVSSPI25X driver. The user code should
* perform the corresponding action required to select the SPI flash
* device to prepare for the SPI transfer.
* - The 'nvsHandle` argument is the NVS handle associated with the
* corresponding NVS region.
* - The 'csId' argument passed to this API is a copy of the [spiCsnGpioIndex]
* (@ref NVSSPI25X_HWAttrs.spiCsnGpioIndex)
* field of the corresponding NVS region's NVSSPI25X_HWAttrs structure.
*
* @code
* void NVSSPI25X_deassertSpiCs(NVS_Handle nvsHandle, uint16_t csId);
* @endcode
* - This function is called AFTER every SPI transfer to and from the SPI
* flash device performed by the NVSSPI25X driver. The user code should
* perform the corresponding action required to de-select the SPI flash
* device.
* following the SPI transfer.
* - The 'nvsHandle` argument is the NVS handle associated with the
* corresponding NVS region.
* - The 'csId' argument passed to this API is a copy of the [spiCsnGpioIndex]
* (@ref NVSSPI25X_HWAttrs.spiCsnGpioIndex)
* field of the corresponding NVS region's NVSSPI25X_HWAttrs structure.
*
* @warning All 4 of the above APIs must be provided by the user if this
* option is used, otherwise default internal implementations of the APIs
* will be called that will likely lead to application failure.
*/
#ifndef ti_drivers_nvs_NVSSPI25X__include
#define ti_drivers_nvs_NVSSPI25X__include
#include <stdint.h>
#include <stdbool.h>
#include <ti/drivers/SPI.h>
#if defined (__cplusplus)
extern "C" {
#endif
/*!
* @brief Command to perform mass erase of entire flash
*
* As this command can erase flash memory outside the region associated
* with the NVS_Handle passed to the control command, the user must
* carefully orchestrate the use of the command.
*
* Mass Erase is the only control command supported.
*/
#define NVSSPI25X_CMD_MASS_ERASE (NVS_CMD_RESERVED + 0)
/*!
* @brief Disable internal management of SPI chip select
*
* Some SPI peripherals can be configured to manage their own chip
* select. Setting the [spiCsnGpioIndex]
* (@ref NVSSPI25X_HWAttrs.spiCsnGpioIndex) field of the NVSSPI25X_HWAttrs
* structure to #NVSSPI25X_SPI_MANAGES_CS informs the NVSSPI25X driver
* that the SPI peripheral used by the NVS driver is configured
* to manage its own chip select signal.
*/
#define NVSSPI25X_SPI_MANAGES_CS ((uint16_t)(~0))
/*!
* @internal @brief NVS function pointer table
*
* 'NVSSPI25X_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.
*/
extern const NVS_FxnTable NVSSPI25X_fxnTable;
/*!
* @brief NVSSPI25X attributes
*
* The 'regionBaseOffset' is the offset, in bytes, from the base of the
* SPI flash, of the flash region to be managed.
*
* The 'regionSize' must be an integer multiple of the flash sector size.
*
* The 'sectorSize' is SPI flash device specific. This parameter should
* correspond to the number of bytes erased when the
* 'SPIFLASH_SUBSECTOR_ERASE' (0x20) command is issued to the device.
*
* The 'verifyBuf' and 'verifyBufSize' parameters are used by the
* NVS_write() command when either 'NVS_WRITE_PRE_VERIFY' or
* 'NVS_WRITE_POST_VERIFY' functions are requested in the 'flags'
* argument. The 'verifyBuf' is used to successively read back portions
* of the flash to compare with the data being written to it.
*
* @code
* //
* // Only one region write operation is performed at a time
* // so a single verifyBuf can be shared by all the regions.
* //
* uint8_t verifyBuf[256];
*
* NVSSPI25X_HWAttrs nvsSPIHWAttrs[2] = {
* //
* // region 0 is 1 flash sector in length.
* //
* {
* .regionBaseOffset = 0,
* .regionSize = 4096,
* .sectorSize = 4096,
* .verifyBuf = verifyBuf;
* .verifyBufSize = 256;
* .spiHandle = NULL,
* .spiIndex = 0,
* .spiBitRate = 40000000,
* .spiCsnGpioIndex = 12,
* },
* //
* // region 1 is 3 flash sectors in length.
* //
* {
* .regionBaseOffset = 4096,
* .regionSize = 4096 * 3,
* .sectorSize = 4096,
* .verifyBuf = verifyBuf; // use shared verifyBuf
* .verifyBufSize = 256;
* .spiHandle = NULL,
* .spiIndex = 0,
* .spiBitRate = 40000000,
* .spiCsnGpioIndex = 12,
* }
* };
* @endcode
*/
typedef struct
{
size_t regionBaseOffset; /*!< Offset from base of SPI flash */
size_t regionSize; /*!< The size of the region in bytes */
size_t sectorSize; /*!< Erase sector size */
uint8_t *verifyBuf; /*!< Write Pre/Post verify buffer */
size_t verifyBufSize; /*!< Write Pre/Post verify buffer size */
SPI_Handle *spiHandle; /*!< ptr to SPI handle if provided by user. */
uint16_t spiIndex; /*!< SPI instance index from Board file */
uint32_t spiBitRate; /*!< SPI bit rate in Hz */
/*! @brief SPI Flash Chip Select GPIO index
This field should be set to either an index within the
GPIO driver's GPIO_Config table, or to #NVSSPI25X_SPI_MANAGES_CS.
see [SPI Flash Chip Select Management] (@ref SPI_CS_MGMT) for more
details.
*/
uint16_t spiCsnGpioIndex;
/*! @brief External Flash Status Poll Delay
*
* This field determines how many microseconds the driver waits after
* querying the external flash status. Increasing this value can help
* mitigate CPU starvation if the external flash is busy for long periods
* of time, but may also result in increased latency.
*/
uint32_t statusPollDelayUs;
} NVSSPI25X_HWAttrs;
/*
* @brief NVSSPI25X Object
*
* The application must not access any member variables of this structure!
*/
typedef struct
{
bool opened; /* Has this region been opened */
SPI_Handle spiHandle;
size_t sectorBaseMask;
} NVSSPI25X_Object;
/*
* @cond NODOC
* NVSSPI25X driver public APIs
*/
extern void NVSSPI25X_close(NVS_Handle handle);
extern int_fast16_t NVSSPI25X_control(NVS_Handle handle, uint_fast16_t cmd,
uintptr_t arg);
extern int_fast16_t NVSSPI25X_erase(NVS_Handle handle, size_t offset,
size_t size);
extern void NVSSPI25X_getAttrs(NVS_Handle handle, NVS_Attrs *attrs);
extern void NVSSPI25X_init();
extern int_fast16_t NVSSPI25X_lock(NVS_Handle handle, uint32_t timeout);
extern NVS_Handle NVSSPI25X_open(uint_least8_t index, NVS_Params *params);
extern int_fast16_t NVSSPI25X_read(NVS_Handle handle, size_t offset,
void *buffer, size_t bufferSize);
extern void NVSSPI25X_unlock(NVS_Handle handle);
extern int_fast16_t NVSSPI25X_write(NVS_Handle handle, size_t offset,
void *buffer, size_t bufferSize, uint_fast16_t flags);
/*
* Weakly defined APIs that can be overridden by the user
*/
extern void NVSSPI25X_initSpiCs(NVS_Handle spiHandle, uint16_t csId);
extern void NVSSPI25X_deinitSpiCs(NVS_Handle spiHandle, uint16_t csId);
extern void NVSSPI25X_assertSpiCs(NVS_Handle spiHandle, uint16_t csId);
extern void NVSSPI25X_deassertSpiCs(NVS_Handle spiHandle, uint16_t csId);
/*! @endcond */
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */
/** @}*/
#endif /* ti_drivers_nvs_NVSSPI25X__include */