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
370 lines
16 KiB
C
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 */
|