summaryrefslogtreecommitdiff
path: root/utils/spi_flash.c
diff options
context:
space:
mode:
authorYuval Adam <yuv.adm@gmail.com>2014-03-16 14:41:11 +0200
committerYuval Adam <yuv.adm@gmail.com>2014-03-16 14:41:11 +0200
commit990090a4cc9070837d31e66b58d40f0c3d038741 (patch)
treecf1b905082c364e9b223e0c5058566103138dae5 /utils/spi_flash.c
parent7f4da522479c0f00126219f0c23b804c3a93d7a6 (diff)
Add usblib and utils
Diffstat (limited to 'utils/spi_flash.c')
-rw-r--r--utils/spi_flash.c2484
1 files changed, 2484 insertions, 0 deletions
diff --git a/utils/spi_flash.c b/utils/spi_flash.c
new file mode 100644
index 0000000..6e5b24a
--- /dev/null
+++ b/utils/spi_flash.c
@@ -0,0 +1,2484 @@
+//*****************************************************************************
+//
+// spi_flash.c - Driver for a SPI flash that supports the "Intel" SPI flash
+// command set, capable of utilizing Bi-SPI and Quad-SPI.
+//
+// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Texas Instruments (TI) is supplying this software for use solely and
+// exclusively on TI's microcontroller products. The software is owned by
+// TI and/or its suppliers, and is protected under applicable copyright
+// laws. You may not combine this software with "viral" open-source
+// software in order to form a larger program.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
+// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
+// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
+// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+// DAMAGES, FOR ANY REASON WHATSOEVER.
+//
+// This is part of revision 2.1.0.12573 of the Tiva Utility Library.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_ssi.h"
+#include "inc/hw_types.h"
+#include "inc/hw_udma.h"
+#include "driverlib/rom.h"
+#include "driverlib/rom_map.h"
+#include "driverlib/ssi.h"
+#include "driverlib/udma.h"
+#include "utils/spi_flash.h"
+
+//*****************************************************************************
+//
+//! \addtogroup spi_flash_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// The commands that can be sent to the SPI flash. This is the "generic"
+// command set that is supported by a wide number of SPI flashes.
+//
+//*****************************************************************************
+#define CMD_WRSR 0x01 // Write status register
+#define CMD_PP 0x02 // Page program
+#define CMD_READ 0x03 // Read data
+#define CMD_WRDI 0x04 // Disable writes
+#define CMD_RDSR 0x05 // Read status register
+#define CMD_WREN 0x06 // Enable writes
+#define CMD_FREAD 0x0b // Fast read data
+#define CMD_SE 0x20 // Sector erase (4K)
+#define CMD_DREAD 0x3b // 1 in 2 out read data
+#define CMD_BE32 0x52 // Block erase (32K)
+#define CMD_QREAD 0x6b // 1 in 4 out read data
+#define CMD_RDID 0x9f // Read JEDEC ID
+#define CMD_CE 0xc7 // Chip erase
+#define CMD_BE64 0xd8 // Block erase (64K)
+
+//*****************************************************************************
+//
+// The states for the SPI flash interrupt handler state machine.
+//
+//*****************************************************************************
+#define STATE_IDLE 0
+#define STATE_CMD 1
+#define STATE_ADDR1 2
+#define STATE_ADDR2 3
+#define STATE_ADDR3 4
+#define STATE_READ_DUMMY 5
+#define STATE_READ_DATA_SETUP 6
+#define STATE_READ_DATA 7
+#define STATE_READ_DATA_DMA 8
+#define STATE_READ_DATA_END 9
+#define STATE_WRITE_DATA_SETUP 10
+#define STATE_WRITE_DATA 11
+#define STATE_WRITE_DATA_DMA 12
+#define STATE_WRITE_DATA_END 13
+
+//*****************************************************************************
+//
+//! Handles SSI module interrupts for the SPI flash driver.
+//!
+//! \param pState is a pointer to the SPI flash driver instance data.
+//!
+//! This function handles SSI module interrupts that are generated as a result
+//! of SPI flash driver operations. This must be called by the application in
+//! response to the SSI module interrupt when using the SPIFlashxxxNonBlocking
+//! APIs.
+//!
+//! \return Returns \b SPI_FLASH_IDLE if there is no transfer in progress,
+//! \b SPI_FLASH_WORKING is the requested transfer is still in progress, or
+//! \b SPI_FLASH_DONE if the requested transfer has completed.
+//
+//*****************************************************************************
+uint32_t
+SPIFlashIntHandler(tSPIFlashState *pState)
+{
+ uint32_t ui32Data, ui32Count;
+
+ //
+ // Set the write count to four. This is the maximum number of bytes that
+ // will be written into the SSI transmit FIFO in the interrupt handler.
+ // Writing more might be possible but makes the latency of handling future
+ // SSI interrupt critical to preventing receive FIFO overruns.
+ //
+ ui32Count = 4;
+
+ //
+ // Get the set of asserted and unmasked SSI module interrupts. Only some
+ // of these are directly handled; the others are implicitly handled via the
+ // operation of the state machine.
+ //
+ ui32Data = HWREG(pState->ui32Base + SSI_O_MIS);
+
+ //
+ // See if the uDMA transmit complete interrupt has asserted.
+ //
+ if(ui32Data & SSI_MIS_DMATXMIS)
+ {
+ //
+ // Determine the size of the uDMA transfer based on the number of bytes
+ // left to write.
+ //
+ if(pState->ui32WriteCount > 1024)
+ {
+ //
+ // There are more than 1024 bytes left to transfer, so the uDMA
+ // transfer that just completed was for a full 1024 bytes.
+ //
+ pState->ui32WriteCount -= 1024;
+
+ //
+ // If a page program is being performed, then the data buffer
+ // pointer needs to be incremented as well.
+ //
+ if(pState->ui16Cmd == CMD_PP)
+ {
+ //
+ // Increment the data buffer pointer.
+ //
+ pState->pui8Buffer += 1024;
+
+ //
+ // See if there is more than one byte left to transfer.
+ //
+ if(pState->ui32WriteCount > 1)
+ {
+ //
+ // Configure the uDMA to transmit the next portion of the
+ // data buffer.
+ //
+ uDMAChannelTransferSet(pState->ui32TxChannel,
+ UDMA_MODE_BASIC,
+ pState->pui8Buffer,
+ (void *)(pState->ui32Base +
+ SSI_O_DR),
+ (pState->ui32WriteCount > 1024) ?
+ 1024 : pState->ui32WriteCount - 1);
+
+ //
+ // Enable the uDMA transmit channel.
+ //
+ uDMAChannelEnable(pState->ui32TxChannel);
+ }
+ }
+ }
+ else
+ {
+ //
+ // There are 1024 or less bytes left to transfer, so the uDMA
+ // transfer that just copmleted was for one less than the remaining
+ // transfer count. If a page program is being performed, then the
+ // data buffer pointer needs to be incremented.
+ //
+ if(pState->ui16Cmd == CMD_PP)
+ {
+ pState->pui8Buffer += (pState->ui32WriteCount - 1);
+ }
+
+ //
+ // Set the remaining transfer count to 1. The final byte will be
+ // transferred with PIO since the end of frame flag needs to be set
+ // first.
+ //
+ pState->ui32WriteCount = 1;
+ }
+
+ //
+ // Clear the uDMA transmit complete interrupt.
+ //
+ HWREG(pState->ui32Base + SSI_O_ICR) = SSI_ICR_DMATXIC;
+ }
+
+ //
+ // See if the uDMA receive complete interrupt has asserted.
+ //
+ if(ui32Data & SSI_MIS_DMARXMIS)
+ {
+ //
+ // Determine the size of the uDMA transfer based on the number of bytes
+ // left to read.
+ //
+ if(pState->ui32ReadCount >= 1024)
+ {
+ //
+ // There are 1024 or more bytes left to transfer, so the uDMA
+ // transfer that just completed was for a full 1024 bytes.
+ //
+ pState->ui32ReadCount -= 1024;
+ if(pState->ui32WriteCount != 0)
+ {
+ pState->ui32WriteCount -= 1024;
+ }
+
+ //
+ // The data buffer pointer needs to be incremented as well.
+ //
+ pState->pui8Buffer += 1024;
+
+ //
+ // See if there is additional data to transfer.
+ //
+ if(pState->ui32ReadCount != 0)
+ {
+ //
+ // Configure the transmit uDMA if there is more than one byte
+ // left to write.
+ //
+ if(pState->ui32WriteCount > 1)
+ {
+ //
+ // Configure the uDMA to transmit the next portion of the
+ // data buffer.
+ //
+ uDMAChannelTransferSet(pState->ui32TxChannel,
+ UDMA_MODE_BASIC, pState->pui8Buffer,
+ (void *)(pState->ui32Base +
+ SSI_O_DR),
+ (pState->ui32WriteCount > 1024) ?
+ 1024 : pState->ui32WriteCount - 1);
+
+ //
+ // Enable the uDMA transmit channel.
+ //
+ uDMAChannelEnable(pState->ui32TxChannel);
+ }
+
+ //
+ // Configure the uDMA to receive the next portion of the data
+ // buffer.
+ //
+ uDMAChannelTransferSet(pState->ui32RxChannel, UDMA_MODE_BASIC,
+ (void *)(pState->ui32Base + SSI_O_DR),
+ pState->pui8Buffer,
+ (pState->ui32ReadCount >= 1024) ?
+ 1024 : pState->ui32ReadCount);
+
+ //
+ // Enable the uDMA receive channel.
+ //
+ uDMAChannelEnable(pState->ui32RxChannel);
+
+ //
+ // If this is the final receive uDMA buffer and there is a
+ // transmit uDMA buffer associated, enable the DMA transmit
+ // interrupt.
+ //
+ if((pState->ui32ReadCount <= 1024) &&
+ (pState->ui32WriteCount > 1))
+ {
+ HWREG(pState->ui32Base + SSI_O_ICR) = SSI_ICR_DMATXIC;
+ HWREG(pState->ui32Base + SSI_O_IM) = SSI_IM_DMATXIM;
+ }
+ }
+ }
+ else
+ {
+ //
+ // There are less than 1024 bytes left to transfer, so the uDMA
+ // transfer that copmleted was for the remaining transfer count.
+ //
+ pState->ui32ReadCount = 0;
+ }
+
+ //
+ // Clear the uDMA receive complete interrupt.
+ //
+ HWREG(pState->ui32Base + SSI_O_ICR) = SSI_ICR_DMARXIC;
+ }
+
+ //
+ // Drain the receive FIFO is not using uDMA.
+ //
+ if(!pState->bUseDMA)
+ {
+ //
+ // Loop while there is more data in the receive FIFO and more data to
+ // be read.
+ //
+ while((pState->ui32ReadCount != 0) &&
+ (MAP_SSIDataGetNonBlocking(pState->ui32Base, &ui32Data) != 0))
+ {
+ //
+ // Save this byte into the data buffer.
+ //
+ *(pState->pui8Buffer)++ = ui32Data & 0xff;
+
+ //
+ // Decrement the read count.
+ //
+ pState->ui32ReadCount--;
+ }
+ }
+
+ //
+ // The SPI flash state machine. Loop forever; the state machine will
+ // explicitly return to the caller when there is no further work that can
+ // be done without stalling.
+ //
+ while(1)
+ {
+ //
+ // Determine the current state.
+ //
+ switch(pState->ui16State)
+ {
+ //
+ // The state machine is idle.
+ //
+ case STATE_IDLE:
+ {
+ //
+ // Return indicating that the state machine is idle. This
+ // should never happen since no further interrupts should occur
+ // once the transfer has completed and the state machine goes
+ // into the idle state.
+ //
+ return(SPI_FLASH_IDLE);
+ }
+
+ //
+ // The state machine is in the command state.
+ //
+ case STATE_CMD:
+ {
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(pState->ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Attempt to write the command byte into the FIFO.
+ //
+ if(ui32Count == 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+ if(MAP_SSIDataPutNonBlocking(pState->ui32Base,
+ pState->ui16Cmd) == 0)
+ {
+ //
+ // The command byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+ else
+ {
+ //
+ // The command byte has been written, so move to the first
+ // address byte state.
+ //
+ pState->ui16State = STATE_ADDR1;
+
+ //
+ // Decrement the count of bytes that have been written.
+ //
+ ui32Count--;
+ }
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the first address byte state.
+ //
+ case STATE_ADDR1:
+ {
+ //
+ // Attempt to write the first address byte into the FIFO.
+ //
+ if(ui32Count == 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+ if(MAP_SSIDataPutNonBlocking(pState->ui32Base,
+ (pState->ui32Addr >> 16) &
+ 0xff) == 0)
+ {
+ //
+ // The first address byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+ else
+ {
+ //
+ // The first address byte has been written, so move to the
+ // second address byte state.
+ //
+ pState->ui16State = STATE_ADDR2;
+
+ //
+ // Decrement the count of bytes that have been written.
+ //
+ ui32Count--;
+ }
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the second address byte state.
+ //
+ case STATE_ADDR2:
+ {
+ //
+ // Attempt to write the second address byte into the FIFO.
+ //
+ if(ui32Count == 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+ if(MAP_SSIDataPutNonBlocking(pState->ui32Base,
+ (pState->ui32Addr >> 8) & 0xff) ==
+ 0)
+ {
+ //
+ // The second address byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+ else
+ {
+ //
+ // The second address byte has been written, so move to the
+ // third address byte state.
+ //
+ pState->ui16State = STATE_ADDR3;
+
+ //
+ // Decrement the count of bytes that have been written.
+ //
+ ui32Count--;
+ }
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the third address byte state.
+ //
+ case STATE_ADDR3:
+ {
+ //
+ // Attempt to write the third address byte into the FIFO.
+ //
+ if(ui32Count == 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+ if(MAP_SSIDataPutNonBlocking(pState->ui32Base,
+ pState->ui32Addr & 0xff) == 0)
+ {
+ //
+ // The third address byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+ else
+ {
+ //
+ // The third address byte has been written, so determine
+ // the next state based on the command byte.
+ //
+ if(pState->ui16Cmd == CMD_PP)
+ {
+ //
+ // A page program is being performed, so move to the
+ // write data setup state.
+ //
+ pState->ui16State = STATE_WRITE_DATA_SETUP;
+ }
+ else if(pState->ui16Cmd == CMD_READ)
+ {
+ //
+ // A read is being performed, so move to the read data
+ // setup state.
+ //
+ pState->ui16State = STATE_READ_DATA_SETUP;
+ }
+ else
+ {
+ //
+ // The other forms of read (fast read, dual read, and
+ // quad read) all require a dummy byte. Move to the
+ // dummy byte state.
+ //
+ pState->ui16State = STATE_READ_DUMMY;
+ }
+
+ //
+ // Decrement the count of bytes that have been written.
+ //
+ ui32Count--;
+ }
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the dummy byte state.
+ //
+ case STATE_READ_DUMMY:
+ {
+ //
+ // Attempt to write the dummy byte into the FIFO.
+ //
+ if(ui32Count == 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+ if(MAP_SSIDataPutNonBlocking(pState->ui32Base, 0) == 0)
+ {
+ //
+ // THe dummy byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+ else
+ {
+ //
+ // The dummy byte has been written, so move to the read
+ // data setup state.
+ //
+ pState->ui16State = STATE_READ_DATA_SETUP;
+
+ //
+ // Decrement the count of bytes that have been written.
+ //
+ ui32Count--;
+ }
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the read data setup state.
+ //
+ case STATE_READ_DATA_SETUP:
+ {
+ //
+ // Set the SSI module into the appropriate mode based on the
+ // command byte.
+ //
+ if(pState->ui16Cmd == CMD_DREAD)
+ {
+ //
+ // Bi-SPI read mode is used for the dual read command.
+ //
+ MAP_SSIAdvModeSet(pState->ui32Base, SSI_ADV_MODE_BI_READ);
+ }
+ else if(pState->ui16Cmd == CMD_QREAD)
+ {
+ //
+ // Quad-SPI read mode is used for the quad read command.
+ //
+ MAP_SSIAdvModeSet(pState->ui32Base,
+ SSI_ADV_MODE_QUAD_READ);
+ }
+ else
+ {
+ //
+ // Advanced read/write mode is used for the read and fast
+ // read commands.
+ //
+ MAP_SSIAdvModeSet(pState->ui32Base,
+ SSI_ADV_MODE_READ_WRITE);
+ }
+
+ //
+ // See if a single byte is being transferred.
+ //
+ if(pState->ui32ReadCount == 1)
+ {
+ //
+ // Disable the use of uDMA.
+ //
+ pState->bUseDMA = false;
+
+ //
+ // Move to the read data end state to transfer the single
+ // byte. This uses PIO even if uDMA has been requested.
+ //
+ pState->ui16State = STATE_READ_DATA_END;
+ }
+
+ //
+ // See if uDMA has been requested for this transfer.
+ //
+ else if(!pState->bUseDMA || (pState->ui32ReadCount < 4))
+ {
+ //
+ // Disable the use of uDMA.
+ //
+ pState->bUseDMA = false;
+
+ //
+ // Move to the read data state.
+ //
+ pState->ui16State = STATE_READ_DATA;
+ }
+
+ //
+ // This transfer should use uDMA.
+ //
+ else
+ {
+ //
+ // If the transfer is larger than 1024 bytes, enable the
+ // uDMA receive complete interrupt which will be used to
+ // move to the next block of the transfer. Otherwise,
+ // enable the uDMA transmit complete interrupt which will
+ // be used to complete the transaction.
+ //
+ if(pState->ui32ReadCount > 1024)
+ {
+ HWREG(pState->ui32Base + SSI_O_IM) = SSI_IM_DMARXIM;
+ }
+ else
+ {
+ HWREG(pState->ui32Base + SSI_O_IM) = SSI_IM_DMATXIM;
+ }
+
+ //
+ // Disable the uDMA channels.
+ //
+ HWREG(UDMA_ENACLR) = ((1 << pState->ui32TxChannel) |
+ (1 << pState->ui32RxChannel));
+
+ //
+ // Configure the attributes for the transmit uDMA channel.
+ //
+ HWREG(UDMA_USEBURSTSET) = ((1 << pState->ui32TxChannel) |
+ (1 << pState->ui32RxChannel));
+ HWREG(UDMA_ALTCLR) = ((1 << pState->ui32TxChannel) |
+ (1 << pState->ui32RxChannel));
+ HWREG(UDMA_PRIOCLR) = 1 << pState->ui32TxChannel;
+ HWREG(UDMA_PRIOSET) = 1 << pState->ui32RxChannel;
+ HWREG(UDMA_REQMASKCLR) = ((1 << pState->ui32TxChannel) |
+ (1 << pState->ui32RxChannel));
+
+ //
+ // Configure the control parameters of the uDMA channels.
+ //
+ uDMAChannelControlSet(pState->ui32TxChannel,
+ UDMA_SRC_INC_NONE |
+ UDMA_DST_INC_NONE |
+ UDMA_SIZE_8 | UDMA_ARB_2);
+ uDMAChannelControlSet(pState->ui32RxChannel,
+ UDMA_SRC_INC_NONE |
+ UDMA_DST_INC_8 |
+ UDMA_SIZE_8 | UDMA_ARB_4);
+
+ //
+ // Configure the uDMA receive channel to transfer the first
+ // portion of the data buffer.
+ //
+ uDMAChannelTransferSet(pState->ui32RxChannel,
+ UDMA_MODE_BASIC,
+ (void *)(pState->ui32Base +
+ SSI_O_DR),
+ pState->pui8Buffer,
+ (pState->ui32ReadCount >= 1024) ?
+ 1024 : pState->ui32ReadCount);
+
+ //
+ // Enable the uDMA receive channel.
+ //
+ uDMAChannelEnable(pState->ui32RxChannel);
+
+ //
+ // Configure the uDMA channel to transfer the dummy bytes
+ // for the first portion of the data buffer. The last
+ // dummy byte will not be included since it must be treated
+ // special.
+ //
+ uDMAChannelTransferSet(pState->ui32TxChannel,
+ UDMA_MODE_BASIC,
+ pState->pui8Buffer,
+ (void *)(pState->ui32Base +
+ SSI_O_DR),
+ (pState->ui32WriteCount > 1024) ?
+ 1024 : pState->ui32WriteCount - 1);
+
+ //
+ // Enable the uDMA transmit channel.
+ //
+ uDMAChannelEnable(pState->ui32TxChannel);
+
+ //
+ // Clear any previously pending uDMA completion interrupt.
+ //
+ HWREG(pState->ui32Base + SSI_O_ICR) = SSI_ICR_DMARXIC;
+
+ //
+ // Enable uDMA transmit and receive in the SSI module.
+ //
+ MAP_SSIDMAEnable(pState->ui32Base,
+ SSI_DMA_TX | SSI_DMA_RX);
+
+ //
+ // Move to the uDMA data read state.
+ //
+ pState->ui16State = STATE_READ_DATA_DMA;
+ }
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the read data state.
+ //
+ case STATE_READ_DATA:
+ {
+ //
+ // Loop while there is more than one byte left to write.
+ //
+ while(pState->ui32WriteCount != 1)
+ {
+ //
+ // Dummy bytes are written into the FIFO in order to
+ // trigger the read operation. Attempt to write another
+ // dummy byte into the FIFO.
+ //
+ if(ui32Count == 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+ if(MAP_SSIDataPutNonBlocking(pState->ui32Base, 0) == 0)
+ {
+ //
+ // The dummy byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+
+ //
+ // Decrement the count of dummy bytes to write.
+ //
+ pState->ui32WriteCount--;
+
+ //
+ // Decrement the count of bytes that have been written.
+ //
+ ui32Count--;
+ }
+
+ //
+ // Move to the read data end state.
+ //
+ pState->ui16State = STATE_READ_DATA_END;
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the uDMA read data state.
+ //
+ case STATE_READ_DATA_DMA:
+ {
+ //
+ // See if the write count is greater than one.
+ //
+ if(pState->ui32WriteCount > 1)
+ {
+ //
+ // Return indicating that the transfer is still in
+ // progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+
+ //
+ // Disable uDMA transmit in the SSI module.
+ //
+ MAP_SSIDMADisable(pState->ui32Base, SSI_DMA_TX);
+
+ //
+ // Enable the uDMA receive done and FIFO transmit interrupt.
+ //
+ HWREG(pState->ui32Base + SSI_O_IM) =
+ SSI_IM_DMARXIM | SSI_IM_TXIM;
+
+ //
+ // Move to the read data end state.
+ //
+ pState->ui16State = STATE_READ_DATA_END;
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the data read end state.
+ //
+ case STATE_READ_DATA_END:
+ {
+ //
+ // See if the final dummy byte still needs to be written.
+ //
+ if(pState->ui32WriteCount != 0)
+ {
+ //
+ // Attempt to write the final dummy byte into the FIFO and
+ // mark it as the end of the frame.
+ //
+ if(ui32Count == 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+ if(MAP_SSIAdvDataPutFrameEndNonBlocking(pState->ui32Base,
+ 0) == 0)
+ {
+ //
+ // The dummy byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+
+ //
+ // The write portion of the transfer has completed.
+ //
+ pState->ui32WriteCount = 0;
+
+ //
+ // Disable the transmit interrupt now that the write
+ // write portion of the transfer has completed.
+ //
+ HWREG(pState->ui32Base + SSI_O_IM) &= ~(SSI_IM_TXIM);
+ }
+
+ //
+ // Return indicating that the transfer is still in progress if
+ // there are still data bytes to be read.
+ //
+ if(pState->ui32ReadCount != 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+
+ //
+ // Disable uDMA receive in the SSI module.
+ //
+ MAP_SSIDMADisable(pState->ui32Base, SSI_DMA_RX);
+
+ //
+ // The transfer is complete, so disable all interrupts.
+ //
+ HWREG(pState->ui32Base + SSI_O_IM) = 0;
+
+ //
+ // Move to the idle state.
+ //
+ pState->ui16State = STATE_IDLE;
+
+ //
+ // Return indicating that the transfer has completed.
+ //
+ return(SPI_FLASH_DONE);
+ }
+
+ //
+ // The state machine is in the write data setup state.
+ //
+ case STATE_WRITE_DATA_SETUP:
+ {
+ //
+ // See if a single data byte is being transferred.
+ //
+ if(pState->ui32WriteCount == 1)
+ {
+ //
+ // Disable the use of uDMA.
+ //
+ pState->bUseDMA = false;
+
+ //
+ // Move to the write data end state to transfer the single
+ // byte. This uses PIO even if uDMA has been requested.
+ //
+ pState->ui16State = STATE_WRITE_DATA_END;
+ }
+
+ //
+ // See if uDMA has been requested for this transfer.
+ //
+ else if(!pState->bUseDMA || (pState->ui32WriteCount < 4))
+ {
+ //
+ // Disable the use of uDMA.
+ //
+ pState->bUseDMA = false;
+
+ //
+ // uDMA is not being used, so move to the write data state.
+ //
+ pState->ui16State = STATE_WRITE_DATA;
+ }
+
+ //
+ // This transfer should use uDMA.
+ //
+ else
+ {
+ //
+ // Enable the uDMA transmit complete interrupt.
+ //
+ HWREG(pState->ui32Base + SSI_O_IM) = SSI_IM_DMATXIM;
+
+ //
+ // Disable the transmit uDMA channel.
+ //
+ HWREG(UDMA_ENACLR) = 1 << pState->ui32TxChannel;
+
+ //
+ // Configure the attributes for the transmit uDMA channel.
+ //
+ HWREG(UDMA_USEBURSTSET) = 1 << pState->ui32TxChannel;
+ HWREG(UDMA_ALTCLR) = 1 << pState->ui32TxChannel;
+ HWREG(UDMA_PRIOCLR) = 1 << pState->ui32TxChannel;
+ HWREG(UDMA_REQMASKCLR) = 1 << pState->ui32TxChannel;
+
+ //
+ // Configure the control parameters of the uDMA channel.
+ //
+ uDMAChannelControlSet(pState->ui32TxChannel,
+ UDMA_SRC_INC_8 |
+ UDMA_DST_INC_NONE |
+ UDMA_SIZE_8 | UDMA_ARB_4);
+
+ //
+ // Configure the uDMA channel to transfer the next portion
+ // of the data buffer. The last byte in the buffer will
+ // not be included since it must be treated special.
+ //
+ uDMAChannelTransferSet(pState->ui32TxChannel,
+ UDMA_MODE_BASIC,
+ pState->pui8Buffer,
+ (void *)(pState->ui32Base +
+ SSI_O_DR),
+ (pState->ui32WriteCount > 1024) ?
+ 1024 : pState->ui32WriteCount - 1);
+
+ //
+ // Enable the uDMA transmit channel.
+ //
+ uDMAChannelEnable(pState->ui32TxChannel);
+ HWREG(pState->ui32Base + SSI_O_ICR) = SSI_ICR_DMATXIC;
+
+ //
+ // Enable uDMA in the SSI module.
+ //
+ MAP_SSIDMAEnable(pState->ui32Base, SSI_DMA_TX);
+
+ //
+ // Move to the uDMA data write state.
+ //
+ pState->ui16State = STATE_WRITE_DATA_DMA;
+ }
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the write data state.
+ //
+ case STATE_WRITE_DATA:
+ {
+ //
+ // Loop while there is more than one byte left to write.
+ //
+ while(pState->ui32WriteCount != 1)
+ {
+ //
+ // Attempt to write the next data byte into the FIFO.
+ //
+ if(ui32Count == 0)
+ {
+ return(SPI_FLASH_WORKING);
+ }
+ if(MAP_SSIDataPutNonBlocking(pState->ui32Base,
+ *(pState->pui8Buffer)) == 0)
+ {
+ //
+ // The next data byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+
+ //
+ // Increment the buffer pointer and decrement the byte
+ // count.
+ //
+ pState->pui8Buffer++;
+ pState->ui32WriteCount--;
+
+ //
+ // Decrement the count of bytes that have been written.
+ //
+ ui32Count--;
+ }
+
+ //
+ // Move to the write data end state.
+ //
+ pState->ui16State = STATE_WRITE_DATA_END;
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the uDMA write data state.
+ //
+ case STATE_WRITE_DATA_DMA:
+ {
+ //
+ // See if the write count is greater than one.
+ //
+ if(pState->ui32WriteCount > 1)
+ {
+ //
+ // Return indicating that the transfer is still in
+ // progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+
+ //
+ // Disable uDMA in the SSI module.
+ //
+ MAP_SSIDMADisable(pState->ui32Base, SSI_DMA_TX);
+
+ //
+ // Disable the uDMA transmit complete interrupt and enable the
+ // FIFO interrupt.
+ //
+ HWREG(pState->ui32Base + SSI_O_IM) = SSI_IM_TXIM;
+
+ //
+ // Move to the write data end state.
+ //
+ pState->ui16State = STATE_WRITE_DATA_END;
+
+ //
+ // Done with this state.
+ //
+ break;
+ }
+
+ //
+ // The state machine is in the write data end state.
+ //
+ case STATE_WRITE_DATA_END:
+ {
+ //
+ // Attempt to write the final data byte into the FIFO.
+ //
+ if(MAP_SSIAdvDataPutFrameEndNonBlocking(pState->ui32Base,
+ *(pState->pui8Buffer)) ==
+ 0)
+ {
+ //
+ // The final data byte could not be written, so return
+ // indicating that the transfer is still in progress.
+ //
+ return(SPI_FLASH_WORKING);
+ }
+
+ //
+ // The transfer is complete, so disable all interrupts.
+ //
+ HWREG(pState->ui32Base + SSI_O_IM) = 0;
+
+ //
+ // Move to the idle state.
+ //
+ pState->ui16State = STATE_IDLE;
+
+ //
+ // Return indicating that the transfer has completed.
+ //
+ return(SPI_FLASH_DONE);
+ }
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! Initializes the SPI flash driver.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Clock is the rate of the clock supplied to the SSI module.
+//! \param ui32BitRate is the SPI clock rate.
+//!
+//! This function configures the SSI module for use by the SPI flash driver.
+//! The SSI module will be placed into the correct mode of operation to allow
+//! communication with the SPI flash. This function must be called prior to
+//! calling the remaining SPI flash driver APIs. It can be called at a later
+//! point to reconfigure the SSI module, such as to increase the SPI clock rate
+//! once it has been determined that it is safe to use a higher speed clock.
+//!
+//! It is the responsibility of the caller to enable the SSI module and
+//! configure the pins that it will utilize.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashInit(uint32_t ui32Base, uint32_t ui32Clock, uint32_t ui32BitRate)
+{
+ //
+ // Configure the SPI module.
+ //
+ MAP_SSIConfigSetExpClk(ui32Base, ui32Clock, SSI_FRF_MOTO_MODE_0,
+ SSI_MODE_MASTER, ui32BitRate, 8);
+
+ //
+ // Enable the advanced mode of operation, defaulting to read/write mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_READ_WRITE);
+
+ //
+ // Enable the frame hold feature.
+ //
+ MAP_SSIAdvFrameHoldEnable(ui32Base);
+
+ //
+ // Enable the SPI module.
+ //
+ MAP_SSIEnable(ui32Base);
+}
+
+//*****************************************************************************
+//
+//! Writes the SPI flash status register.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui8Status is the value to write to the status register.
+//!
+//! This function writes the SPI flash status register. This uses the 0x01 SPI
+//! flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashWriteStatus(uint32_t ui32Base, uint8_t ui8Status)
+{
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the write status register command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_WRSR);
+
+ //
+ // Send the new status register value, marking this byte as the end of the
+ // frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, ui8Status);
+}
+
+//*****************************************************************************
+//
+//! Programs the SPI flash.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to be programmed.
+//! \param pui8Data is a pointer to the data to be programmed.
+//! \param ui32Count is the number of bytes to be programmed.
+//!
+//! This function programs data into the SPI flash, using PIO mode. This
+//! function will not return until the entire program command has been written
+//! into the SSI transmit FIFO. This uses the 0x02 SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashPageProgram(uint32_t ui32Base, uint32_t ui32Addr,
+ const uint8_t *pui8Data, uint32_t ui32Count)
+{
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the page program command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_PP);
+
+ //
+ // Send the address of the first byte to program.
+ //
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 16) & 0xff);
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 8) & 0xff);
+ MAP_SSIDataPut(ui32Base, ui32Addr & 0xff);
+
+ //
+ // Loop while there is more than one data byte left to be sent.
+ //
+ while(ui32Count-- != 1)
+ {
+ //
+ // Send the next data byte.
+ //
+ MAP_SSIDataPut(ui32Base, *pui8Data++);
+ }
+
+ //
+ // Send the last data byte, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, *pui8Data);
+}
+
+//*****************************************************************************
+//
+//! Programs the SPI flash in the background.
+//!
+//! \param pState is a pointer to the SPI flash state structure.
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to be programmed.
+//! \param pui8Data is a pointer to the data to be programmed.
+//! \param ui32Count is the number of bytes to be programmed.
+//! \param bUseDMA is \b true if uDMA should be used and \b false otherwise.
+//! \param ui32TxChannel is the uDMA channel to be used for writing to the SSI
+//! module.
+//!
+//! This function programs data into the SPI flash, using either interrupts or
+//! uDMA to transfer the data. This function will return immediately and send
+//! the data in the background. In order for this to complete successfully,
+//! several conditions must be satisfied:
+//!
+//! - Prior to calling this function:
+//! - The SSI module must be enabled in SysCtl.
+//! - The SSI pins must be configured for use by the SSI module.
+//! - The SSI module interrupt must be enabled in NVIC.
+//! - The uDMA module must be enabled in SysCtl and the control table set (if
+//! using uDMA).
+//! - The uDMA channels must be assigned to the SSI module.
+//!
+//! - After calling this function:
+//! - The interrupt handler for the SSI module must call
+//! SPIFlashIntHandler(), passing the same pState structure pointer that
+//! was supplied to this function.
+//! - No other SPI flash operation can be called until this operation has
+//! completed.
+//!
+//! Completion of the programming operation is indicated when
+//! SPIFlashIntHandler() returns \b SPI_FLASH_DONE.
+//!
+//! Like SPIFlashPageProgram(), this uses the 0x02 SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashPageProgramNonBlocking(tSPIFlashState *pState, uint32_t ui32Base,
+ uint32_t ui32Addr, const uint8_t *pui8Data,
+ uint32_t ui32Count, bool bUseDMA,
+ uint32_t ui32TxChannel)
+{
+ //
+ // Save the parameters of this program operation to the state structure.
+ //
+ pState->ui32Base = ui32Base;
+ pState->ui16Cmd = CMD_PP;
+ pState->ui16State = STATE_CMD;
+ pState->ui32Addr = ui32Addr;
+ pState->pui8Buffer = (uint8_t *)pui8Data;
+ pState->ui32ReadCount = 0;
+ pState->ui32WriteCount = ui32Count;
+ pState->bUseDMA = bUseDMA;
+ pState->ui32TxChannel = ui32TxChannel & 0x1f;
+
+ //
+ // Enable the SSI transmit interrupt. This will start the transfer. If
+ // uDMA is being used, the uDMA-related interrupt will be enabled at the
+ // appropriate time by the interrupt handler.
+ //
+ HWREG(ui32Base + SSI_O_ICR) = SSI_ICR_DMATXIC;
+ HWREG(ui32Base + SSI_O_IM) = SSI_IM_TXIM;
+}
+
+//*****************************************************************************
+//
+//! Reads data from the SPI flash.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to read.
+//! \param pui8Data is a pointer to the data buffer to into which to read the
+//! data.
+//! \param ui32Count is the number of bytes to read.
+//!
+//! This function reads data from the SPI flash, using PIO mode. This function
+//! will not return until the read has completed. This uses the 0x03 SPI flash
+//! command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashRead(uint32_t ui32Base, uint32_t ui32Addr, uint8_t *pui8Data,
+ uint32_t ui32Count)
+{
+ uint32_t ui32Trash;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0)
+ {
+ }
+
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the read command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_READ);
+
+ //
+ // Send the address of the first byte to read.
+ //
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 16) & 0xff);
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 8) & 0xff);
+ MAP_SSIDataPut(ui32Base, ui32Addr & 0xff);
+
+ //
+ // Set the SSI module into read/write mode. In this mode, dummy writes are
+ // required in order to make the transfer occur; the SPI flash will ignore
+ // the data.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_READ_WRITE);
+
+ //
+ // See if there is a single byte to be read.
+ //
+ if(ui32Count == 1)
+ {
+ //
+ // Perform a single dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+ }
+ else
+ {
+ //
+ // Perform a dummy write to prime the loop.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Loop while there is more than one byte left to be read.
+ //
+ while(--ui32Count != 1)
+ {
+ //
+ // Perform a dummy write to keep the transmit FIFO from going
+ // empty.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Read the next data byte from the receive FIFO and place it into
+ // the data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+ }
+
+ //
+ // Perform the final dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+
+ //
+ // Read the next data byte from the receive FIFO and place it into the
+ // data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+ }
+
+ //
+ // Read the final data byte from the receive FIFO and place it into the
+ // data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+}
+
+//*****************************************************************************
+//
+//! Reads data from the SPI flash in the background.
+//!
+//! \param pState is a pointer to the SPI flash state structure.
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to read.
+//! \param pui8Data is a pointer to the data buffer to into which to read the
+//! data.
+//! \param ui32Count is the number of bytes to read.
+//! \param bUseDMA is \b true if uDMA should be used and \b false otherwise.
+//! \param ui32TxChannel is the uDMA channel to be used for writing to the SSI
+//! module.
+//! \param ui32RxChannel is the uDMA channel to be used for reading from the
+//! SSI module.
+//!
+//! This function reads data from the SPI flash, using either interrupts or
+//! uDMA to transfer the data. This function will return immediately and read
+//! the data in the background. In order for this to complete successfully,
+//! several conditions must be satisfied:
+//!
+//! - Prior to calling this function:
+//! - The SSI module must be enabled in SysCtl.
+//! - The SSI pins must be configured for use by the SSI module.
+//! - The SSI module interrupt must be enabled in NVIC.
+//! - The uDMA module must be enabled in SysCtl and the control table set (if
+//! using uDMA).
+//! - The uDMA channels must be assigned to the SSI module.
+//!
+//! - After calling this function:
+//! - The interrupt handler for the SSI module must call
+//! SPIFlashIntHandler(), passing the same pState structure pointer that
+//! was supplied to this function.
+//! - No other SPI flash operation can be called until this operation has
+//! completed.
+//!
+//! Completion of the read operation is indicated when SPIFlashIntHandler()
+//! returns \b SPI_FLASH_DONE.
+//!
+//! Like SPIFlashRead(), this uses the 0x03 SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashReadNonBlocking(tSPIFlashState *pState, uint32_t ui32Base,
+ uint32_t ui32Addr, uint8_t *pui8Data,
+ uint32_t ui32Count, bool bUseDMA,
+ uint32_t ui32TxChannel, uint32_t ui32RxChannel)
+{
+ uint32_t ui32Trash;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0)
+ {
+ }
+
+ //
+ // Save the parameters of this read operation to the state structure.
+ //
+ pState->ui32Base = ui32Base;
+ pState->ui16Cmd = CMD_READ;
+ pState->ui16State = STATE_CMD;
+ pState->ui32Addr = ui32Addr;
+ pState->pui8Buffer = pui8Data;
+ pState->ui32ReadCount = ui32Count;
+ pState->ui32WriteCount = ui32Count;
+ pState->bUseDMA = bUseDMA;
+ pState->ui32TxChannel = ui32TxChannel & 0x1f;
+ pState->ui32RxChannel = ui32RxChannel & 0x1f;
+
+ //
+ // Enable the SSI transmit and receive interrupts. This will start the
+ // transfer. If uDMA is being used, the uDMA-related interrupts will be
+ // enabled at the appropriate time by the interrupt handler.
+ //
+ HWREG(ui32Base + SSI_O_ICR) = SSI_ICR_DMATXIC | SSI_ICR_DMARXIC;
+ HWREG(ui32Base + SSI_O_IM) = SSI_IM_TXIM | SSI_IM_RXIM | SSI_IM_RTIM;
+}
+
+//*****************************************************************************
+//
+//! Disables SPI flash write operations.
+//!
+//! \param ui32Base is the SSI module base address.
+//!
+//! This function sets the SPI flash to disallow program and erase operations.
+//! This uses the 0x04 SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashWriteDisable(uint32_t ui32Base)
+{
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the write disable command, marking this byte as the end of the
+ // frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, CMD_WRDI);
+}
+
+//*****************************************************************************
+//
+//! Reads the SPI flash status register.
+//!
+//! \param ui32Base is the SSI module base address.
+//!
+//! This function reads the SPI flash status register. This uses the 0x05 SPI
+//! flash command.
+//!
+//! \return Returns the value of the SPI flash status register.
+//
+//*****************************************************************************
+uint8_t
+SPIFlashReadStatus(uint32_t ui32Base)
+{
+ uint32_t ui32Data;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Data) != 0)
+ {
+ }
+
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the write status register command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_RDSR);
+
+ //
+ // Set the SSI module into read/write mode. In this mode, dummy writes are
+ // required in order to make the transfer occur; the SPI flash will ignore
+ // the data.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_READ_WRITE);
+
+ //
+ // Perform a single dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+
+ //
+ // Read the value of the status register.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Data);
+
+ //
+ // Return the status register value.
+ //
+ return(ui32Data & 0xff);
+}
+
+//*****************************************************************************
+//
+//! Enables SPI flash write operations.
+//!
+//! \param ui32Base is the SSI module base address.
+//!
+//! This function sets the SPI flash to allow program and erase operations.
+//! This must be done prior to each SPI flash program or erase operation; the
+//! SPI flash will automatically disable program and erase operations once a
+//! program or erase operation has completed. This uses the 0x06 SPI flash
+//! command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashWriteEnable(uint32_t ui32Base)
+{
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the write enable command, marking this byte as the end of the
+ // frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, CMD_WREN);
+}
+
+//*****************************************************************************
+//
+//! Reads data from the SPI flash using the fast read command.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to read.
+//! \param pui8Data is a pointer to the data buffer to into which to read the
+//! data.
+//! \param ui32Count is the number of bytes to read.
+//!
+//! This function reads data from the SPI flash with the fast read command,
+//! using PIO mode. The fast read command allows the SPI flash to be read at
+//! a higher SPI clock rate because of the addition of a dummy cycle during the
+//! command setup. This function will not return until the read has completed.
+//! This uses the 0x0b SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashFastRead(uint32_t ui32Base, uint32_t ui32Addr, uint8_t *pui8Data,
+ uint32_t ui32Count)
+{
+ uint32_t ui32Trash;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0)
+ {
+ }
+
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the fast read command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_FREAD);
+
+ //
+ // Send the address of the first byte to read.
+ //
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 16) & 0xff);
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 8) & 0xff);
+ MAP_SSIDataPut(ui32Base, ui32Addr & 0xff);
+
+ //
+ // Send a dummy byte.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Set the SSI module into read/write mode. In this mode, dummy writes are
+ // required in order to make the transfer occur; the SPI flash will ignore
+ // the data.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_READ_WRITE);
+
+ //
+ // See if there is a single byte to be read.
+ //
+ if(ui32Count == 1)
+ {
+ //
+ // Perform a single dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+ }
+ else
+ {
+ //
+ // Perform a dummy write to prime the loop.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Loop while there is more than one byte left to be read.
+ //
+ while(--ui32Count != 1)
+ {
+ //
+ // Perform a dummy write to keep the transmit FIFO from going
+ // empty.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Read the next data byte from the receive FIFO and place it into
+ // the data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+ }
+
+ //
+ // Perform the final dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+
+ //
+ // Read the next data byte from the receive FIFO and place it into the
+ // data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+ }
+
+ //
+ // Read the final data byte from the receive FIFO and place it into the
+ // data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+}
+
+//*****************************************************************************
+//
+//! Reads data from the SPI flash using the fast read command in the
+//! background.
+//!
+//! \param pState is a pointer to the SPI flash state structure.
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to read.
+//! \param pui8Data is a pointer to the data buffer to into which to read the
+//! data.
+//! \param ui32Count is the number of bytes to read.
+//! \param bUseDMA is \b true if uDMA should be used and \b false otherwise.
+//! \param ui32TxChannel is the uDMA channel to be used for writing to the SSI
+//! module.
+//! \param ui32RxChannel is the uDMA channel to be used for reading from the
+//! SSI module.
+//!
+//! This function reads data from the SPI flash with the fast read command,
+//! using either interrupts or uDMA to transfer the data. The fast read
+//! command allows the SPI flash to be read at a higher SPI clock rate because
+//! of the addition of a dummy cycle during the command setup. This function
+//! will return immediately and read the data in the background. In order for
+//! this to complete successfully, several conditions must be satisfied:
+//!
+//! - Prior to calling this function:
+//! - The SSI module must be enabled in SysCtl.
+//! - The SSI pins must be configured for use by the SSI module.
+//! - The SSI module interrupt must be enabled in NVIC.
+//! - The uDMA module must be enabled in SysCtl and the control table set (if
+//! using uDMA).
+//! - The uDMA channels must be assigned to the SSI module.
+//!
+//! - After calling this function:
+//! - The interrupt handler for the SSI module must call
+//! SPIFlashIntHandler(), passing the same pState structure pointer that
+//! was supplied to this function.
+//! - No other SPI flash operation can be called until this operation has
+//! completed.
+//!
+//! Completion of the read operation is indicated when SPIFlashIntHandler()
+//! returns \b SPI_FLASH_DONE.
+//!
+//! Like SPIFlashFastRead(), this uses the 0x0b SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashFastReadNonBlocking(tSPIFlashState *pState, uint32_t ui32Base,
+ uint32_t ui32Addr, uint8_t *pui8Data,
+ uint32_t ui32Count, bool bUseDMA,
+ uint32_t ui32TxChannel, uint32_t ui32RxChannel)
+{
+ uint32_t ui32Trash;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0)
+ {
+ }
+
+ //
+ // Save the parameters of this read operation to the state structure.
+ //
+ pState->ui32Base = ui32Base;
+ pState->ui16Cmd = CMD_FREAD;
+ pState->ui16State = STATE_CMD;
+ pState->ui32Addr = ui32Addr;
+ pState->pui8Buffer = pui8Data;
+ pState->ui32ReadCount = ui32Count;
+ pState->ui32WriteCount = ui32Count;
+ pState->bUseDMA = bUseDMA;
+ pState->ui32TxChannel = ui32TxChannel & 0x1f;
+ pState->ui32RxChannel = ui32RxChannel & 0x1f;
+
+ //
+ // Enable the SSI transmit and receive interrupts. This will start the
+ // transfer. If uDMA is being used, the uDMA-related interrupts will be
+ // enabled at the appropriate time by the interrupt handler.
+ //
+ HWREG(ui32Base + SSI_O_ICR) = SSI_ICR_DMATXIC | SSI_ICR_DMARXIC;
+ HWREG(ui32Base + SSI_O_IM) = SSI_IM_TXIM | SSI_IM_RXIM | SSI_IM_RTIM;
+}
+
+//*****************************************************************************
+//
+//! Erases a 4 KB sector of the SPI flash.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to erase.
+//!
+//! This function erases a sector of the SPI flash. Each sector is 4 KB with a
+//! 4 KB alignment; the SPI flash will ignore the lower ten bits of the address
+//! provided. The sector erase command is issued by this function;
+//! SPIFlashReadStatus() must be used to query the SPI flash to determine when
+//! the sector erase operation has completed. This uses the 0x20 SPI flash
+//! command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashSectorErase(uint32_t ui32Base, uint32_t ui32Addr)
+{
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the sector erase command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_SE);
+
+ //
+ // Send the address of the sector to be erased, marking the last byte of
+ // the address as the end of the frame.
+ //
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 16) & 0xff);
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 8) & 0xff);
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, ui32Addr & 0xff);
+}
+
+//*****************************************************************************
+//
+//! Reads data from the SPI flash using Bi-SPI.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to read.
+//! \param pui8Data is a pointer to the data buffer to into which to read the
+//! data.
+//! \param ui32Count is the number of bytes to read.
+//!
+//! This function reads data from the SPI flash with Bi-SPI, using PIO mode.
+//! This function will not return until the read has completed. This uses the
+//! 0x3b SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashDualRead(uint32_t ui32Base, uint32_t ui32Addr, uint8_t *pui8Data,
+ uint32_t ui32Count)
+{
+ uint32_t ui32Trash;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0)
+ {
+ }
+
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the dual read command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_DREAD);
+
+ //
+ // Send the address of the first byte to read.
+ //
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 16) & 0xff);
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 8) & 0xff);
+ MAP_SSIDataPut(ui32Base, ui32Addr & 0xff);
+
+ //
+ // Send a dummy byte.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Set the SSI module into Bi-SPI read mode. In this mode, dummy writes
+ // are required in order to make the transfer occur; the SSI module will
+ // ignore the data (the SPI flash will never see the dummy data since
+ // Bi-SPI read mode is a uni-directional input mode).
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_BI_READ);
+
+ //
+ // See if there is a single byte to be read.
+ //
+ if(ui32Count == 1)
+ {
+ //
+ // Perform a single dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+ }
+ else
+ {
+ //
+ // Perform a dummy write to prime the loop.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Loop while there is more than one byte left to be read.
+ //
+ while(--ui32Count != 1)
+ {
+ //
+ // Perform a dummy write to keep the transmit FIFO from going
+ // empty.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Read the next data byte from the receive FIFO and place it into
+ // the data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+ }
+
+ //
+ // Perform the final dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+
+ //
+ // Read the next data byte from the receive FIFO and place it into the
+ // data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+ }
+
+ //
+ // Read the final data byte from the receive FIFO and place it into the
+ // data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+}
+
+//*****************************************************************************
+//
+//! Reads data from the SPI flash using Bi-SPI in the background.
+//!
+//! \param pState is a pointer to the SPI flash state structure.
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to read.
+//! \param pui8Data is a pointer to the data buffer to into which to read the
+//! data.
+//! \param ui32Count is the number of bytes to read.
+//! \param bUseDMA is \b true if uDMA should be used and \b false otherwise.
+//! \param ui32TxChannel is the uDMA channel to be used for writing to the SSI
+//! module.
+//! \param ui32RxChannel is the uDMA channel to be used for reading from the
+//! SSI module.
+//!
+//! This function reads data from the SPI flash with Bi-SPI, using either
+//! interrupts or uDMA to transfer the data. This function will return
+//! immediately and read the data in the background. In order for this to
+//! complete successfully, several conditions must be satisfied:
+//!
+//! - Prior to calling this function:
+//! - The SSI module must be enabled in SysCtl.
+//! - The SSI pins must be configured for use by the SSI module.
+//! - The SSI module interrupt must be enabled in NVIC.
+//! - The uDMA module must be enabled in SysCtl and the control table set (if
+//! using uDMA).
+//! - The uDMA channels must be assigned to the SSI module.
+//!
+//! - After calling this function:
+//! - The interrupt handler for the SSI module must call
+//! SPIFlashIntHandler(), passing the same pState structure pointer that
+//! was supplied to this function.
+//! - No other SPI flash operation can be called until this operation has
+//! completed.
+//!
+//! Completion of the read operation is indicated when SPIFlashIntHandler()
+//! returns \b SPI_FLASH_DONE.
+//!
+//! Like SPIFLashDualRead(), this uses the 0x3b SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashDualReadNonBlocking(tSPIFlashState *pState, uint32_t ui32Base,
+ uint32_t ui32Addr, uint8_t *pui8Data,
+ uint32_t ui32Count, bool bUseDMA,
+ uint32_t ui32TxChannel, uint32_t ui32RxChannel)
+{
+ uint32_t ui32Trash;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0)
+ {
+ }
+
+ //
+ // Save the parameters of this read operation to the state structure.
+ //
+ pState->ui32Base = ui32Base;
+ pState->ui16Cmd = CMD_DREAD;
+ pState->ui16State = STATE_CMD;
+ pState->ui32Addr = ui32Addr;
+ pState->pui8Buffer = pui8Data;
+ pState->ui32ReadCount = ui32Count;
+ pState->ui32WriteCount = ui32Count;
+ pState->bUseDMA = bUseDMA;
+ pState->ui32TxChannel = ui32TxChannel & 0x1f;
+ pState->ui32RxChannel = ui32RxChannel & 0x1f;
+
+ //
+ // Enable the SSI transmit and receive interrupts. This will start the
+ // transfer. If uDMA is being used, the uDMA-related interrupts will be
+ // enabled at the appropriate time by the interrupt handler.
+ //
+ HWREG(ui32Base + SSI_O_ICR) = SSI_ICR_DMATXIC | SSI_ICR_DMARXIC;
+ HWREG(ui32Base + SSI_O_IM) = SSI_IM_TXIM | SSI_IM_RXIM | SSI_IM_RTIM;
+}
+
+//*****************************************************************************
+//
+//! Erases a 32 KB block of the SPI flash.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to erase.
+//!
+//! This function erases a 32 KB block of the SPI flash. Each 32 KB block has
+//! a 32 KB alignment; the SPI flash will ignore the lower 15 bits of the
+//! address provided. The 32 KB block erase command is issued by this
+//! function; SPIFlashReadStatus() must be used to query the SPI flash to
+//! determine when the 32 KB block erase operation has completed. This uses
+//! the 0x52 SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashBlockErase32(uint32_t ui32Base, uint32_t ui32Addr)
+{
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the 32 KB block erase command command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_BE32);
+
+ //
+ // Send the address of the 32 KB block to be erased, marking the last byte
+ // of the address as the end of the frame.
+ //
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 16) & 0xff);
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 8) & 0xff);
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, ui32Addr & 0xff);
+}
+
+//*****************************************************************************
+//
+//! Reads data from the SPI flash using Quad-SPI.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to read.
+//! \param pui8Data is a pointer to the data buffer to into which to read the
+//! data.
+//! \param ui32Count is the number of bytes to read.
+//!
+//! This function reads data from the SPI flash with Quad-SPI, using PIO mode.
+//! This function will not return until the read has completed. This uses the
+//! 0x6b SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashQuadRead(uint32_t ui32Base, uint32_t ui32Addr, uint8_t *pui8Data,
+ uint32_t ui32Count)
+{
+ uint32_t ui32Trash;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0)
+ {
+ }
+
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the quad read command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_QREAD);
+
+ //
+ // Send the address of the first byte to read.
+ //
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 16) & 0xff);
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 8) & 0xff);
+ MAP_SSIDataPut(ui32Base, ui32Addr & 0xff);
+
+ //
+ // Send a dummy byte.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Set the SSI module into Quad-SPI read mode. In this mode, dummy writes
+ // are required in order to make the transfer occur; the SSI module will
+ // ignore the data (the SPI flash will never see the dummy data since
+ // Quad-SPI read mode is a uni-directional input mode).
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_QUAD_READ);
+
+ //
+ // See if there is a single byte to be read.
+ //
+ if(ui32Count == 1)
+ {
+ //
+ // Perform a single dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+ }
+ else
+ {
+ //
+ // Perform a dummy write to prime the loop.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Loop while there is more than one byte left to be read.
+ //
+ while(--ui32Count != 1)
+ {
+ //
+ // Perform a dummy write to keep the transmit FIFO from going
+ // empty.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+
+ //
+ // Read the next data byte from the receive FIFO and place it into
+ // the data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+ }
+
+ //
+ // Perform the final dummy write, marking it as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+
+ //
+ // Read the next data byte from the receive FIFO and place it into the
+ // data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+ }
+
+ //
+ // Read the final data byte from the receive FIFO and place it into the
+ // data buffer.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Addr);
+ *pui8Data++ = ui32Addr & 0xff;
+}
+
+//*****************************************************************************
+//
+//! Reads data from the SPI flash using Quad-SPI in the background.
+//!
+//! \param pState is a pointer to the SPI flash state structure.
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to read.
+//! \param pui8Data is a pointer to the data buffer to into which to read the
+//! data.
+//! \param ui32Count is the number of bytes to read.
+//! \param bUseDMA is \b true if uDMA should be used and \b false otherwise.
+//! \param ui32TxChannel is the uDMA channel to be used for writing to the SSI
+//! module.
+//! \param ui32RxChannel is the uDMA channel to be used for reading from the
+//! SSI module.
+//!
+//! This function reads data from the SPI flash with Quad-SPI, using either
+//! interrupts or uDMA to transfer the data. This function will return
+//! immediately and read the data in the background. In order for this to
+//! complete successfully, several conditions must be satisfied:
+//!
+//! - Prior to calling this function:
+//! - The SSI module must be enabled in SysCtl.
+//! - The SSI pins must be configured for use by the SSI module.
+//! - The SSI module interrupt must be enabled in NVIC.
+//! - The uDMA module must be enabled in SysCtl and the control table set (if
+//! using uDMA).
+//! - The uDMA channels must be assigned to the SSI module.
+//!
+//! - After calling this function:
+//! - The interrupt handler for the SSI module must call
+//! SPIFlashIntHandler(), passing the same pState structure pointer that
+//! was supplied to this function.
+//! - No other SPI flash operation can be called until this operation has
+//! completed.
+//!
+//! Completion of the read operation is indicated when SPIFlashIntHandler()
+//! returns \b SPI_FLASH_DONE.
+//!
+//! Like SPIFlashQuadRead(), this uses the 0x6b SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashQuadReadNonBlocking(tSPIFlashState *pState, uint32_t ui32Base,
+ uint32_t ui32Addr, uint8_t *pui8Data,
+ uint32_t ui32Count, bool bUseDMA,
+ uint32_t ui32TxChannel, uint32_t ui32RxChannel)
+{
+ uint32_t ui32Trash;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0)
+ {
+ }
+
+ //
+ // Save the parameters of this read operation to the state structure.
+ //
+ pState->ui32Base = ui32Base;
+ pState->ui16Cmd = CMD_QREAD;
+ pState->ui16State = STATE_CMD;
+ pState->ui32Addr = ui32Addr;
+ pState->pui8Buffer = pui8Data;
+ pState->ui32ReadCount = ui32Count;
+ pState->ui32WriteCount = ui32Count;
+ pState->bUseDMA = bUseDMA;
+ pState->ui32TxChannel = ui32TxChannel & 0x1f;
+ pState->ui32RxChannel = ui32RxChannel & 0x1f;
+
+ //
+ // Enable the SSI transmit and receive interrupts. This will start the
+ // transfer. If uDMA is being used, the uDMA-related interrupts will be
+ // enabled at the appropriate time by the interrupt handler.
+ //
+ HWREG(ui32Base + SSI_O_ICR) = SSI_ICR_DMATXIC | SSI_ICR_DMARXIC;
+ HWREG(ui32Base + SSI_O_IM) = SSI_IM_TXIM | SSI_IM_RXIM | SSI_IM_RTIM;
+}
+
+//*****************************************************************************
+//
+//! Reads the manufacturer and device IDs from the SPI flash.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param pui8ManufacturerID is a pointer to the location into which to store
+//! the manufacturer ID.
+//! \param pui16DeviceID is a pointer to the location into which to store the
+//! device ID.
+//!
+//! This function reads the manufacturer and device IDs from the SPI flash.
+//! These values can be used to identify the SPI flash that is attached, as
+//! well as determining if a SPI flash is attached (if the \b SSIRx pin is
+//! pulled up or down, either using the pad's weak pull up/down or using an
+//! external resistor, which will cause the returned IDs to be either all zeros
+//! or all ones if the SPI flash is not attached). This uses the 0x9f SPI
+//! flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashReadID(uint32_t ui32Base, uint8_t *pui8ManufacturerID,
+ uint16_t *pui16DeviceID)
+{
+ uint32_t ui32Data1, ui32Data2;
+
+ //
+ // Drain any residual data from the receive FIFO.
+ //
+ while(MAP_SSIDataGetNonBlocking(ui32Base, &ui32Data1) != 0)
+ {
+ }
+
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the read ID command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_RDID);
+
+ //
+ // Set the SSI module into read/write mode. In this mode, dummy writes are
+ // required in order to make the transfer occur; the SPI flash will ignore
+ // the data.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_READ_WRITE);
+
+ //
+ // Send three dummy bytes, marking the last as the end of the frame.
+ //
+ MAP_SSIDataPut(ui32Base, 0);
+ MAP_SSIDataPut(ui32Base, 0);
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, 0);
+
+ //
+ // Read the first returned data byte, which contains the manufacturer ID.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Data1);
+ *pui8ManufacturerID = ui32Data1 & 0xff;
+
+ //
+ // Read the remaining two data bytes, which contain the device ID.
+ //
+ MAP_SSIDataGet(ui32Base, &ui32Data1);
+ MAP_SSIDataGet(ui32Base, &ui32Data2);
+ *pui16DeviceID = ((ui32Data1 & 0xff) << 8) | (ui32Data2 & 0xff);
+}
+
+//*****************************************************************************
+//
+//! Erases the entire SPI flash.
+//!
+//! \param ui32Base is the SSI module base address.
+//!
+//! This command erase the entire SPI flash. The chip erase command is issued
+//! by this function; SPIFlashReadStatus() must be used to query the SPI flash
+//! to determine when the chip erase operation has completed. This uses the
+//! 0xc7 SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashChipErase(uint32_t ui32Base)
+{
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the chip erase command, marking this byte as the end of the frame.
+ //
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, CMD_CE);
+}
+
+//*****************************************************************************
+//
+//! Erases a 64 KB block of the SPI flash.
+//!
+//! \param ui32Base is the SSI module base address.
+//! \param ui32Addr is the SPI flash address to erase.
+//!
+//! This function erases a 64 KB block of the SPI flash. Each 64 KB block has
+//! a 64 KB alignment; the SPI flash will ignore the lower 16 bits of the
+//! address provided. The 64 KB block erase command is issued by this
+//! function; SPIFlashReadStatus() must be used to query the SPI flash to
+//! determine when the 64 KB block erase operation has completed. This uses
+//! the 0xd8 SPI flash command.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SPIFlashBlockErase64(uint32_t ui32Base, uint32_t ui32Addr)
+{
+ //
+ // Set the SSI module into write-only mode.
+ //
+ MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
+
+ //
+ // Send the 64 KB block erase command command.
+ //
+ MAP_SSIDataPut(ui32Base, CMD_BE64);
+
+ //
+ // Send the address of the 64 KB block to be erased, marking the last byte
+ // of the address as the end of the frame.
+ //
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 16) & 0xff);
+ MAP_SSIDataPut(ui32Base, (ui32Addr >> 8) & 0xff);
+ MAP_SSIAdvDataPutFrameEnd(ui32Base, ui32Addr & 0xff);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************