LPCOpen SPIFI FLASH Library (LPCSPIFILIB)
Documentation for the LPCSPIFILIB library
LPCSPIFILIB library use model

The LPCSPIFILIB library API is designed to to provide a common set of functions that work across many different SPIFI FLASH device families. These functions include support for device detection, device capabilites and statuses, program/erase/read, and lock/unlock support.

The basic use mode of the LPCSPIFILIB library is like this:

A typical example using the LPCSPIFILIB library with error checking shown below.

#include "board.h"
#include "spifilib_api.h"

/* Set macro to the base address of spifi controller for this MCU */
#define SPIFLASH_BASE_ADDRESS 0x14000000

/* Board level pin muxing set, enable SPIFI controller clocking, setup initial
   SPIFI controller clokc rate (Possible LPC18xx/43xx method shown) */
uint32_t spifiBaseClockRate = Chip_Clock_GetClockInputHz(CLKIN_MAINPLL);
Chip_Clock_SetDivider(CLK_IDIV_E, CLKIN_MAINPLL,
    (1 + (spifiBaseClockRate / 15000000)));
Chip_Clock_SetBaseClock(CLK_BASE_SPIFI, CLKIN_IDIVE, true, false);

/* Initialize LPCSPIFILIB library, reset the interface */
spifiInit(LPC_SPIFI_BASE, true);

/* Register the family for the device */
spifiRegisterFamily(spifi_REG_FAMILY_CommonCommandSet);

/* Return the number of devices this library supports */
int idx = spifiGetSuppFamilyCount();

/* Get required memory for detected device, this may vary per device family */
uint32_t memSize = spifiGetHandleMemSize(LPC_SPIFI_BASE);
if (memSize == 0) {
    /* No device detected, error */
}

/* Initialize and detect a device and get device context */
SPIFI_HANDLE_T pSpifi = spifiInitDevice(&lmem, sizeof(lmem), LPC_SPIFI_BASE, SPIFLASH_BASE_ADDRESS);
if (pSpifi == NULL) {
    /* Error initializing device */
}

/* Get maximum clock rate for the detected device and setup new SPIFI interface clock */
uint32_t maxSpifiClock = spifiDevGetInfo(pSpifi, SPIFI_INFO_MAXCLOCK);
Chip_Clock_SetDivider(CLK_IDIV_E, CLKIN_MAINPLL, (1 + (spifiBaseClockRate / maxSpifiClock)));

/* Get some info needed for the application */
uint32_t caps = spifiDevGetInfo(pSpifi, SPIFI_INFO_CAPS); /* OR'ed list of capabilities */
uint32_t numBlocks = spifiDevGetInfo(pSpifi, SPIFI_INFO_ERASE_BLOCKS); /* Number of blocks */
uint32_t blockSize = spifiDevGetInfo(pSpifi, SPIFI_INFO_ERASE_BLOCKSISZE); /* Size of a block */
uint32_t numSubBlocks = spifiDevGetInfo(pSpifi, SPIFI_INFO_ERASE_SUBBLOCKS); /* Number of sub-blocks */
uint32_t subBlockSize = spifiDevGetInfo(pSpifi, SPIFI_INFO_ERASE_SUBBLOCKSISZE); /* Size of a sub-block */
uint32_t pageSize = spifiDevGetInfo(pSpifi, SPIFI_INFO_PAGESIZE); /* Maximum program size in a single call */
uint32_t readSize = spifiDevGetInfo(pSpifi, SPIFI_INFO_MAXREADSIZE); /* Maximum read size in a single call */

/* Lock device */
errCode = spifiDevUnlockDevice(pSpifi);
if (errCode != SPIFI_ERR_NONE) {
    /* Error unlocking device */
}

/* Erase full device */
errCode = spifiDevEraseAll(pSpifi);
if (errCode != SPIFI_ERR_NONE) {
    /* Error erasing device */
}

/* Program a page, limited program operation to the size of a single page (pageSize). */
errCode = spifiDevPageProgram(pSpifi, SPIFLASH_BASE_ADDRESS, buff, 256);
if (errCode != SPIFI_ERR_NONE) {
    /* Error programming page */
}

/* Read data, limited read operation to the value of readSize */
errCode = spifiDevRead(pSpifi, SPIFLASH_BASE_ADDRESS, buffin, 256);
if (errCode != SPIFI_ERR_NONE) {
    /* Error reading data */
}

/* Lock device */
errCode = spifiDevLockDevice(pSpifi);
if (errCode != SPIFI_ERR_NONE) {
    /* Error locking device */
}

/* Place device and controller into memory mode. This memory maps the device
   to a range of addresses on the LPC device */
spifiDevSetMemMode(pSpifi, true);

/* Done, shutdown the driver. This will not alter memory mode. If the device and
   controller are not in memory mode, it places them into memory mode. */
spifiDevDeInit(pSpifi);

Using device familiy capabilites
Different devices or device families will have different capabilites that the library can support. Use the spifiDevGetInfo(pSpifi, SPIFI_INFO_CAPS) function to get a list of capabilities for the device.

Example:

uint32_t caps = spifiDevGetInfo(pSpifi, SPIFI_INFO_CAPS); /* OR'ed list of capabilities */

if ((caps & SPIFI_CAP_QUAD_READ) != 0) {
    /* Driver supports QUAD READ operation */
}

if ((caps & SPIFI_CAP_BLOCKLOCK) != 0) {
    /* Driver supports individual block lock and unlock via the spifiDevUnlockBlock()
       and spifiDevLockBlock() functions */
}

if ((caps & SPIFI_CAP_NOBLOCK) != 0) {
    /* Driver supports non-blocking erase and program */
}

if ((caps & SPIFI_CAP_SUBBLKER) != 0) {
    /* Driver supports sub-block erase */
}

Sub-block erase
Some devices support erasing of sub-blocks. If the device supports sub-block erase, the spifiDevEraseSubBlock() function can be used to erase sub-blocks instead of full size blocks. The number of sub-block sizing and the number of blocks can be determined with the spifiDevGetInfo(pSpifi, SPIFI_INFO_ERASE_SUBBLOCKS) and spifiDevGetInfo(pSpifi, SPIFI_INFO_ERASE_SUBBLOCKSISZE) functions.

Example:

if ((spifiDevGetInfo(pSpifi, SPIFI_INFO_CAPS) & SPIFI_CAP_SUBBLKER) != 0) {
    /* Erase all sub-blocks */
    for (i = 0; i < spifiDevGetInfo(pSpifi, SPIFI_INFO_ERASE_SUBBLOCKS); i++) {
        errCode = spifiDevEraseSubBlock(pSifif, (uint32_t) i);
        if (errCode != SPIFI_ERR_NONE) {
            /* Error erasing syb-block */
        }
    }
}

Other support functions
Other functions exist in the LPCSPIFILIB API for converting between block numbers and mapped memory addresses and device writes and reads larger than the maximum device write (page) and read sizes.

Copyright (C) 2014 NXP Semiconductors. All rights reserved.