1.23.24.3 SQIx_DMATransfer Function
C
void SQIx_DMATransfer( sqi_dma_desc_t *sqiDmaDesc ); // x - Instance of the SQI peripheral
Summary
Starts a DMA transfer to the SQI slave device.
Description
This function can be used to trigger a DMA transfer to the SQI slave device. The sqiDmaDesc can be a single descriptor or a chain of descriptors doing multiple operations.
A callback will be given to the client once the DMA transfer is completed if the SQI_BDCTRL_PKTINTEN or SQI_BDCTRL_BDDONEINTIEN is set in sqiDmaDesc->bd_ctrl register.
Precondition
SQIx_Initialize must have been called for the associated SQI instance. The DMA Descriptor address passed should be from the non-cachable region.
Parameters
Param | Description |
---|---|
*sqiDmaDesc | Pointer to SQI DMA descriptor buffer start address. |
Returns
None
Example
The Macros used to populate DMA Descriptors vary based on device family. Refer to the peripheral header file for actual macros to be used.
#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); }
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_BD_BUFLEN(5) | SQI_BDCTRL_MODE(QUAD_MODE) | SQI_BDCTRL_SPI_DEV_SEL10(0x00) | SQI_BDCTRL_DESC_EN_Msk); sqiCmdDesc[0].bd_bufaddr = (uint32_t *)&sqi_cmd_hsr; sqiCmdDesc[0].bd_stat = 0; sqiCmdDesc[0].bd_nxtptr = (sqi_dma_desc_t *)&sqiCmdDesc[1]; DCACHE_CLEAN_BY_ADDR((uint32_t *)&sqiCmdDesc[0], sizeof(sqiCmdDesc[0])); // SQI Read: 2 byte dummy read // Chip Select remains asserted after the transfer sqiCmdDesc[1].bd_ctrl = ( SQI_BDCTRL_BD_BUFLEN(2) | SQI_BDCTRL_MODE(QUAD_MODE) | SQI_BDCTRL_SPI_DEV_SEL10(0x00) | SQI_BDCTRL_DESC_EN_Msk); sqiCmdDesc[1].bd_bufaddr = (uint32_t *)&sqi_cmd_dummy; sqiCmdDesc[1].bd_stat = 0; sqiCmdDesc[1].bd_nxtptr = (sqi_dma_desc_t *)&sqiBufDesc[0]; DCACHE_CLEAN_BY_ADDR((uint32_t *)sqi_cmd_hsr, sizeof(sqi_cmd_hsr)); DCACHE_CLEAN_BY_ADDR((uint32_t *)&sqiCmdDesc[0], 2 * sizeof(sqi_dma_desc_t)); // 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_BD_BUFLEN(numBytes) | SQI_BDCTRL_PKT_INT_EN_Msk | SQI_BDCTRL_MODE(QUAD_MODE) | SQI_BDCTRL_DIR_Msk | SQI_BDCTRL_SPI_DEV_SEL10(0x00) | SQI_BDCTRL_DESC_EN_Msk); sqiBufDesc[i].bd_bufaddr = (uint32_t *)readBuffer; sqiBufDesc[i].bd_stat = 0; sqiBufDesc[i].bd_nxtptr = (sqi_dma_desc_t *)&sqiBufDesc[i+1]; pendingBytes -= numBytes; readBuffer += numBytes; } // The last descriptor must indicate the end of the descriptor list sqiBufDesc[i-1].bd_ctrl |= (SQI_BDCTRL_LIFM_Msk | SQI_BDCTRL_LAST_BD_Msk | SQI_BDCTRL_CS_ASSERT_Msk); sqiBufDesc[i-1].bd_nxtptr = 0x00000000; DCACHE_CLEAN_BY_ADDR((uint32_t *)&sqiBufDesc[0], (i * sizeof(sqi_dma_desc_t))); // Initialize the root buffer descriptor SQI1_DMATransfer((sqi_dma_desc_t *)&sqiCmdDesc[0]); // Wait for transfer to complete while(xferDone == false); } void main() { // Other calls .. SQI1_RegisterCallback(APP_EventHandler, (uintptr_t)NULL); DCACHE_INVALIDATE_BY_ADDR((uint32_t *)readBuffer, BUFFER_SIZE); APP_Read((uint32_t *)readData, BUFFER_SIZE, MEM_START_ADDRESS); }