1.22.26.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);
}