1.23.24 Serial Quad Interface (SQI)
The SQI module is a synchronous serial interface that provides access to serial Flash memories and other serial devices. The SQI module supports Single Lane (identical to SPI), Dual Lane, and Quad Lane interface modes.
The SQI peripheral library operates in two transfer modes:
-
DMA Mode:
-
DMA mode is a higher throughput data transfer mode, where the internal SQI DMA engine off-loads the Host processor by using predefined Buffer Descriptors for data transfers
-
Each Buffer Descriptor can handle up to 256Bytes of data and multiple descriptors can be chained to support larger portions of data transfers
-
Four words cumulatively are called a Buffer Descriptor (BD), and are part of the transmit and receive structure
-
Individually, a Buffer Descriptor describes an area within the Host memory where data is waiting to be transmitted from or received into
-
Host software creates a single or linked list of Buffer Descriptors based on the buffer size and places them in the system memory
-
This is the Default mode set during SQIx_Initialize()
-
-
XIP Mode:
-
XIP mode is used to execute code out of serial Flash devices
-
SQIx_XIPSetup() should be called at run time to switch SQI peripheral to XIP mode
-
The SQI module supports two data flow modes: SPI Mode 0 and Mode 3. Each transfer mode (XIP/DMA) can use any of the data flow modes as desired by the application.
Using The Library
The SQI Peripheral Library operates only in DMA and XIP mode to interface with the SQI based Serial Flash Memories operating in Single-bit SPI, Dual SPI, and Quad SPI.
The SQI peripheral library is by default configured to interrupt mode. Use SQIx_RegisterCallback() function to receive event on transfer completion.
The SQI Peripheral library provides non-Blocking API's, which can be used to perform the following functionalities on the SQI Slave device.
-
Start a DMA Transfer
-
sqi_dma_desc_t data type needs to filled to send a transfer request to the slave device
-
The transfer request can be
-
Sending commands (ERASE, Write Enable, etc..)
-
Reading/Writing status registers
-
Writing to the Serial flash memory
-
Reading from the serial flash memory
-
-
-
Setup Execute in Place (XIP)
-
SQIx_XIPSetup() function can be used to configure SQI peripheral to XIP mode
-
Here is an example code to read data from SQI memory with DMA desciptor chaining
#define PAGE_SIZE (256U) #define SECTOR_SIZE (4096U) //Erase, Write and Read 80KBytes of memory #define SECTORS_TO_EWR (20U) #define BUFFER_SIZE (SECTOR_SIZE * SECTORS_TO_EWR) #define MIN_DMA_BUFFER_LEN (CACHE_LINE_SIZE) #define CMD_DESC_NUMBER 5 #define BUFF_DESC_NUMBER (BUFFER_SIZE / PAGE_SIZE) #define MEM_START_ADDRESS (0x0U) #define SST26VF_HS_READ 0x0B volatile bool xfer_done = false; uint8_t CACHE_ALIGN readData[BUFFER_SIZE]; uint8_t CACHE_ALIGN sqi_cmd_hsr[MIN_DMA_BUFFER_LEN]; uint8_t CACHE_ALIGN sqi_cmd_dummy[MIN_DMA_BUFFER_LEN]; sqi_dma_desc_t CACHE_ALIGN sqiCmdDesc[CMD_DESC_NUMBER]; sqi_dma_desc_t CACHE_ALIGN sqiBufDesc[BUFF_DESC_NUMBER]; static void APP_EventHandler(uintptr_t context) { xfer_done = true; } void APP_Read( void *rx_data, uint32_t rx_data_length, uint32_t address ) { uint32_t pendingBytes = rx_data_length; uint8_t *readBuffer = (uint8_t *)rx_data; uint32_t numBytes = 0; uint32_t i = 0; xfer_done = false; // Construct parameters to issue SST26 high speed read command sqi_cmd_hsr[0] = SST26VF_HS_READ; sqi_cmd_hsr[1] = (0xff & (address>>16)); sqi_cmd_hsr[2] = (0xff & (address>>8)); sqi_cmd_hsr[3] = (0xff & (address>>0)); sqi_cmd_hsr[4] = 0; // SQI Read: High Speed Read command (0x0B), 3 byte address, and 1 byte mode // Chip Select remains asserted after the transfer sqiCmdDesc[0].bd_ctrl = ( SQI_BDCTRL_BUFFLEN_VAL(5) | SQI_BDCTRL_MODE_QUAD_LANE | SQI_BDCTRL_SQICS_CS1 | SQI_BDCTRL_DESCEN); sqiCmdDesc[0].bd_bufaddr = (uint32_t *)KVA_TO_PA(&sqi_cmd_hsr); sqiCmdDesc[0].bd_stat = 0; sqiCmdDesc[0].bd_nxtptr = (sqi_dma_desc_t *)KVA_TO_PA(&sqiCmdDesc[1]); // SQI Read: 2 byte dummy read // Chip Select remains asserted after the transfer sqiCmdDesc[1].bd_ctrl = ( SQI_BDCTRL_BUFFLEN_VAL(2) | SQI_BDCTRL_MODE_QUAD_LANE | SQI_BDCTRL_SQICS_CS1 | SQI_BDCTRL_DESCEN); sqiCmdDesc[1].bd_bufaddr = (uint32_t *)KVA_TO_PA(&sqi_cmd_dummy); sqiCmdDesc[1].bd_stat = 0; sqiCmdDesc[1].bd_nxtptr = (sqi_dma_desc_t *)KVA_TO_PA(&sqiBufDesc[0]); // SQI Read: Reads the values from the memory // Create Descriptor chain. Enable packet interrupt. // Chip Select is de-asserted after the transfer for (i = 0; (i < BUFF_DESC_NUMBER) && (pendingBytes > 0); i++) { if (pendingBytes > PAGE_SIZE) { numBytes = PAGE_SIZE; } else { numBytes = pendingBytes; } sqiBufDesc[i].bd_ctrl = ( SQI_BDCTRL_BUFFLEN_VAL(numBytes) | SQI_BDCTRL_PKTINTEN | SQI_BDCTRL_MODE_QUAD_LANE | SQI_BDCTRL_DIR_READ | SQI_BDCTRL_SQICS_CS1 | SQI_BDCTRL_DESCEN); sqiBufDesc[i].bd_bufaddr = (uint32_t *)KVA_TO_PA(readBuffer); sqiBufDesc[i].bd_stat = 0; sqiBufDesc[i].bd_nxtptr = (sqi_dma_desc_t *)KVA_TO_PA(&sqiBufDesc[i+1]); pendingBytes -= numBytes; readBuffer += numBytes; } // The last descriptor must indicate the end of the descriptor list and last packaet sqiBufDesc[i-1].bd_ctrl |= (SQI_BDCTRL_LASTPKT | SQI_BDCTRL_LASTBD | SQI_BDCTRL_DEASSERT); sqiBufDesc[i-1].bd_nxtptr = 0x00000000; // Initialize the root buffer descriptor SQI1_DMA_Transfer((sqi_dma_desc_t *)KVA_TO_PA(&sqiBufDesc[0])); // Wait for transfer to complete while(xferDone == false); } void main() { // Other calls .. SQI1_RegisterCallback(APP_EventHandler, (uintptr_t)NULL); APP_Read((uint32_t *)readBuffer, BUFFER_SIZE, MEM_START_ADDRESS); }
Library Interface
SQI peripheral library provides the following interfaces:
Functions
Name | Description |
---|---|
SQIx_Initialize | Initializes given instance of the SQI peripheral |
SQIx_DMASetup | Sets up SQI peripheral to DMA mode |
SQIx_DMATransfer | Starts a DMA transfer to the SQI slave device |
SQIx_XIPSetup | Sets up SQI peripheral to XIP mode |
SQIx_RegisterCallback | Sets the pointer to the function (and it's context) to be called when the operation is complete |
Data types and constants
Name | Type | Description |
---|---|---|
SQI_EVENT_HANDLER | Typedef | Defines the data type and function signature for the SQI peripheral event handler function |
SQI_LANE_MODE | Enum | Defines the data type to specify the type of lane |
SQI_XIP_ADDR_BYTES | Enum | Defines the data type to specify the number of address bytes |
SQI_XIP_DEV_SELECT | Enum | Defines the data type to specify the device to be used |
sqi_dma_desc_t | Struct | Defines the data type for the SQI DMA based transfer |