blob: 6f4272c1c9cf8445b4c091078d0b09be7bf21a72 [file] [log] [blame]
/*
* Copyright (c) 2017, 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 NVS_erase() command assumes that regions with sectorSize = 4096 bytes
* are erased using the SPIFLASH_SUBSECTOR_ERASE command (0x20). Otherwise the
* SPIFLASH_SECTOR_ERASE command (0xD8) is used to erase the flash sector.
* It is up to the user to ensure that each region's sectorSize matches these
* sector erase rules.
*
* For each managed flash region, a corresponding SPI instance must be
* provided to the NVSSPI25X driver. As well, a GPIO instance index must be
* provided to the driver so that the SPI flash device's chip select can
* be asserted during SPI transfers.
*
* 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.
*
* Regardless of whether a region's SPI instance is opened by the driver or
* elsewhere within the application, the GPIO instance used to select the SPI
* flash device during SPI operations MUST be provided. The GPIO pin will be
* configured as "GPIO_CFG_OUT_STD" and assertion of this pin is
* assumed to be active LOW.
*/
#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)
/*!
* @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,
* .spiCsGpioIndex = 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,
* .spiCsGpioIndex = 12,
* }
* };
* @endcode
*/
typedef struct NVSSPI25X_HWAttrs {
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 */
uint16_t spiCsnGpioIndex; /*!< SPI chip select GPIO index from Board file */
} NVSSPI25X_HWAttrs;
/*
* @brief NVSSPI25X Object
*
* The application must not access any member variables of this structure!
*/
typedef struct NVSSPI25X_Object {
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);
/*! @endcond */
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */
/** @}*/
#endif /* ti_drivers_nvs_NVSSPI25X__include */