Functional Description
Transfer Type Flow Control
GR5526 supports DMA as flow controller only. There are four transfer types:
- Memory to memory
- Memory to peripheral
- Peripheral to memory
- Peripheral to peripheral
Transfer Width
For memory, the source transfer width must be less than or equal to the data bus width of AHB master interface, normally 8, 16, or 32 bits. For a non-memory, the source transfer width is equal to the peripheral FIFO width.
For memory, the destination transfer width must be less than or equal to the data bus width of AHB master interface, normally 8, 16, or 32 bits. For a non-memory, the destination transfer width is equal to the peripheral FIFO width.
Source and Destination Address Increment
- Source address increment: It indicates whether to increase, decrease, or remain the source address on every source transfer. If the device is fetching data from a source peripheral FIFO with a fixed address, then set this field to No change.
- Destination address increment: This decides on whether to increment, decrement, or remain the destination address on every source transfer. If the device is fetching data from a destination peripheral FIFO with a fixed address, then set this field to No change.
Channel Priority
Each channel has a programmable priority in the range of 0–5 (each DMA has 6 channels), from lowest to highest. Channel priority applies to most scenarios except those on master bus. It is worth noting that a request for the master bus interface can be made at any time, but the request is granted only after the current AHB transfer (burst or single) completes. Therefore, when the master interface is transferring data for a low-priority channel while a high priority channel requests service, it completes the current AHB transfer (burst or single) for the low-priority channel before switching to data transfer for the high one.
DMA Transfers
DMA has 6 channels in total; each channel has a FIFO and is independent from each other. The FIFO of each channel is 32-bit wide. After the DMA channel is enabled, the DMA obtains data from the source according to the bit width configured for the source and stores the data into the DMA's FIFO. The DMA takes out the data from the DMA FIFO according to the bit width configured for the target and sends the data to the destination. Regardless of the configured transmission bit width, the data obtained from the source is compactly stored (this helps maximize the use of DAM's FIFO storage space). For example, the transmission bit width is 16 bits, and the FIFO bit width is 32 bits, so one depth of DMA FIFO will store two 16-bit data entries. It is worth mentioning that when DMA is used as flow control, the total number of bytes (blk_size_bytes_dma) transmitted by DMA in a single transmission depends on the product of the source transmission bit width (src_single_size_bytes) and the block size (CTLx.BLOCK_TS). The detailed calculation methods are as follows:
Source Interface Width | Destination Interface Width | Block Size (DMA as Flow Control) | Source Content: Address/Data | Transfer Operations | Destination Content: Address/Data |
---|---|---|---|---|---|
8 |
8 |
4 |
@0x0/B0 @0x1/B1 @0x2/B2 @0x3/B3 |
1: READ B0[7:0] @0x0 To DMA then WRITE B0[7:0] @0x0 2 :READ B1[7:0] @0x1 To DMA then WRITE B1[7:0] @0x1 3: READ B2[7:0] @0x2 To DMA then WRITE B2[7:0] @0x2 4: READ B3[7:0] @0x3 To DMA then WRITE B3[7:0] @0x3 |
@0x0/B0 @0x1/B1 @0x2/B2 @0x3/B3 |
8 |
16 |
4 |
@0x0/B0 @0x1/B1 @0x2/B2 @0x3/B3 |
1 :READ B0[7:0] @0x0 To DMA 2: READ B1[7:0] @0x1 To DMA then WRITE B1B0[15:0] @0x0 3: READ B2[7:0] @0x2 To DMA 4: READ B3[7:0] @0x3 To DMA then WRITE B3B2[15:0] @0x2 |
@0x0/B1B0 @0x2/B3B2 |
8 |
32 |
4 |
@0x0/B0 @0x1/B1 @0x2/B2 @0x3/B3 |
1: READ B0[7:0] @0x0 To DMA 2: READ B1[7:0] @0x1 To DMA 3: READ B2[7:0] @0x2 To DMA 4: READ B3[7:0] @0x3 To DMA then WRITE B3B2B1B0[32:0] @0x0 |
@0x0/B3B2B1B0 |
16 |
8 |
2 |
@0x0/B1B0 @0x2/B3B2 |
1: READ B1B0[15:0] @0x0 To DMA then WRITE B0[7:0] @0x0 2: WRITE B1[7:0] @0x1 3: READ B3B2[15:0] @0x2 To DMA then WRITE B2[7:0] @0x2 4: WRITE B3[7:0] @0x3 |
@0x0/B0 @0x1/B1 @0x2/B2 @0x3/B3 |
16 |
16 |
2 |
@0x0/B1B0 @0x2/B3B2 |
1: READ B1B0[15:0] @0x0 To DMA then WRITE B1B0[15:0] @0x0 2: READ B3B2[15:0] @0x2 To DMA then WRITE B3B2[15:0] @0x2 |
@0x0/B1B0 @0x2/B3B2 |
16 |
32 |
2 |
@0x0/B1B0 @0x2/B3B2 |
1: READ B1B0[15:0] @0x0 To DMA 2: READ B3B2[15:0] @0x2 To DMA then WRITE B3B2B1B0[32:0] @0x0 |
@0x0/B3B2B1B0 |
32 |
8 |
1 |
@0x0/B3B2B1B0 |
1: READ B3B2B1B0[32:0] @0x0 To DMA then WRITE B0[7:0] @0x0 2: WRITE B1[7:0] @0x1 3: WRITE B2[7:0] @0x2 4: WRITE B3[7:0] @0x3 |
@0x0/B0 @0x1/B1 @0x2/B2 @0x3/B3 |
32 |
16 |
1 |
@0x0/B3B2B1B0 |
1: READ B3B2B1B0[32:0] @0x0 To DMA then WRITE B1B0[15:0] @0x0 2: WRITE B3B2[15:0] @0x2 |
@0x0/B1B0 @0x2/B3B2 |
32 |
32 |
1 |
@0x0/B3B2B1B0 |
1: READ B3B2B1B0[32:0] @0x0 To DMA then WRITE B3B2B1B0[32:0] @0x0 |
@0x0/B3B2B1B0 |
Gather and Scatter
Gather or scatter is a function that supports input and output data into/from multiple buffers. As shown in the figure below, gather refers to writing data fetched from multiple buffers to a channel (collecting data); scatter refers to reading data fetched from one channel to multiple buffers (scattering data).
Gather is relevant to a source transfer. The source address is incremented or decremented by a programmed amount when a gather boundary is reached. The number of source transfers between successive gather boundaries is programmed into the Source Gather Count (SGRx.SGC) field. The source address is incremented or decremented by the value stored in the Source Gather Increment (SGRx.SGI) field multiplied by the number of bytes in a single AHB transfer from the source – (decoded value of CTLx.SRC_TR_WIDTH)/8 – when a gather boundary is reached. Gather is enabled by writing a 1 to the CTLx.SRC_GATHER_EN field.
If the CTLx.SINC field indicates a fixed-address control throughout a DMA transfer, then the CTLx.SRC_GATHER_EN field is ignored, and the gather feature is automatically disabled.
图 155 shows an example of a source gather transfer:
Scatter is relevant to a destination transfer. The destination address is incremented or decremented by a programmed amount – the scatter increment – when a scatter boundary is reached. The destination address is incremented or decremented by the value stored in the destination scatter increment (DSRx.DSI) field, multiplied by the number of bytes in a single AHB transfer to the destination (decoded value of CTLx.DST_TR_WIDTH)/8 – when a scatter boundary is reached. The number of destination transfers between successive scatter boundaries is programmed into the Destination Scatter Count (DSC) field of the DSRx register. Scatter is enabled by writing a 1 to the CTLx.DST_SCATTER_EN field.
If the CTLx.DINC field indicates a fixed-address control throughout a DMA transfer, then the CTLx.DST_SCATTER_EN field is ignored, and the scatter feature is automatically disabled.
图 156 shows an example of a destination scatter transfer:
Multi-block DMA Transfer
DMA transfer may consist of multiple DW_AHB_DMAC blocks. Multi-block DMA transfers are supported through block chaining (linked list pointers) and auto-reloading channel registers. The DMA transfer modes for source and destination can be independently selected.
Auto-reloading
During auto-reloading, the channel registers are reloaded with their initial values at the completion of each block and the new values used for the new block. Some or all of the SRC_ADDR_CHx, DEST_ADDR_CHx, and CTRL_CHx channel registers are reloaded from their initial values at the start of a block transfer.
By configuring the Configuration Register (CFG_CHx.RELOAD_SRC), you can program the register if the SRC_ADDR_CHx register can be automatically reloaded from its initial value at the end of every block for multi-block transfers.
By configuring the Configuration Register (CFG_CHx.RELOAD_DST), you can program the register if the DEST_ADDR_CHx register can be automatically reloaded from its initial value at the end of every block for multi-block transfers.
Linked Lists (Block Chaining)
Linked list pointer (LLP) points to the location in system memory where the next linked list item (LLI) exists. The LLI is a set of registers that describe the next block (block descriptor) and an LLP register. The DMA fetches the LLI at the beginning of every block when block chaining is enabled. Each LLI is composed of the following parts: SAR, DAR, LLP, CTL, SSTAT, and DSTAT. Therefore, to use block chaining, a series of linked lists need to be implemented in memory. The LLP bit field of each LLI block stores the first address of the next LLI, thus forming a linked list of blocks. The following figure shows how to use chained linked lists in memory to define multi-block transfers using block chaining.
The DMA reprograms the channel registers prior to the start of each block by fetching the block descriptor for that block from system memory. This is known as an LLI update. The SARx, DARx, LLPx, and CTLx registers are fetched from system memory on an LLI update. After that, the updated contents of the CTLx, SSTATx, and DSTATx registers are written back to memory on block completion.
LLI accesses are always 32-bit accesses (Hsize = 2) aligned to 32-bit boundaries and cannot be changed or programmed to anything other than 32-bit, even if the AHB master interface of the LLI supports more than a 32-bit data width.
DMA Interrupt
For each channel, there are three types of interrupt sources:
- IntTfr: DMA Transfer Complete Interrupt
- IntBlock: Block Transfer Complete Interrupt. This interrupt is generated on DMA block transfer completion to the destination peripheral.
- IntErr: Error Interrupt. This interrupt is generated when an ERROR response is received from an AHB slave on the HRESP bus during a DMA transfer. In addition, the DMA transfer is cancelled, and the channel is disabled.
The INT_RSTAT, INT_STAT, INT_MASK, and INT_CLR registers are provided to manage interrupts. The INT_MASK registers is used to enable or disable the block transfer complete interrupt, DMA transfer complete interrupt, and error interrupt. By reading the INT_STAT registers or INT_RSTAT registers, you can check whether the interruption have occurred. To clear interrupts, write 1 to the INT_CLR registers.
- INT_MASK registers: Used to enable or disable the block transfer complete interrupt, DMA transfer complete interrupt, and error interrupt.
- INT_STAT or INT_RSTAT registers: Used to reply whether the interruption have occurred.
- INT_CLR registers: Write 1 to INT_CLR to clear interrupts.
DMA Hardware Interface Assignment
Each channel of DMA can communicate with designated peripheral devices through the assigned hardware handshake interface. The hardware handshaking interfaces are assigned as shown in the following table. The developer can program the CFG_CHx.DEST_PER or CFG_CHx.SRC_PER to assign a handshaking interface for each channel source and destination.
DMA0 Request | Hardware Handshake Choice0 | Handshake Peripheral Description | Hardware Handshake Choice1 | Handshake Peripheral Description |
---|---|---|---|---|
0x0 | QSPI0 TX | QSPI0 Master Transmit | NC | / |
0x1 | QSPI0 RX | QSPI0 Master Receive | NC | / |
0x2 | SPIM TX | SPI Master Transmit | I2C2 TX | I2C2 Transmit |
0x3 | SPIM RX | SPI Master Receive | I2C2 RX | I2C2 Receive |
0x4 | SPIS TX | SPI Slave Transmit | UART3 TX | UART3 Transmit |
0x5 | SPIS RX | SPI Slave Receive | UART3 RX | UART3 Receive |
0x6 | UART0 TX | UART0 Transmit | I2C5 TX | I2C5 Transmit |
0x7 | UART0 RX | UART0 Receive | I2C5 RX | I2C5 Receive |
0x8 | UART1 TX | UART1 Transmit | I2C4 TX | I2C4 Transmit |
0x9 | UART1 RX | UART1 Receive | I2C4 RX | I2C4 Receive |
0xA | SNSADC | Sense ADC | UART4 TX | UART4 Transmit |
0xB | NC | / | UART4 RX | UART4 Receive |
0xC | OSPI TX | OSPI Master Transmit | QSPI1 TX | QSPI1 Master Transmit |
0xD | OSPI RX | OSPI Master Receive | QSPI1 RX | QSPI1 Master Receive |
0xE | UART2 TX | UART2 Transmit | I2C3 TX | I2C3 Transmit |
0xF | UART2 RX | UART2 Receive | I2C3 RX | I2C3 Receive |
DMA1 Request | Hardware Handshake Choice0 | Handshake Peripheral Description | Hardware Handshake Choice1 | Handshake Peripheral Description |
---|---|---|---|---|
0x0 | OSPI TX | OSPI Master Transmit | SPIM TX | SPI Master Transmit |
0x1 | OSPI RX | OSPI Master Receive | SPIM RX | SPI Master Receive |
0x2 | QSPI2 TX | QSPI2 Master Transmit | DSPIM TX | DSPI Master Transmit |
0x3 | QSPI2 RX | QSPI2 Master Receive | DSPIM RX | DSPI Master Receive |
0x4 | I2SM TX | I2S Master Transmit | QSPI1 TX | QSPI1 Master Transmit |
0x5 | I2SM RX | I2S Master Receive | QSPI1 RX | QSPI1 Master Receive |
0x6 | I2SS TX | I2S Slave Transmit | UART3 TX | UART3 Transmit |
0x7 | I2SS RX | I2S Slave Receive | UART3 RX | UART3 Receive |
0x8 | PDM | PDM Receive | UART4 TX | UART4 Transmit |
0x9 | NC | / | UART4 RX | UART4 Receive |
0xA | QSPI1 TX | QSPI1 Master Transmit | UART5 TX | UART5 Transmit |
0xB | QSPI1 RX | QSPI1 Master Receive | UART5 RX | UART5 Receive |
0xC | I2C0 TX | I2C0 Transmit | NC | / |
0xD | I2C0 RX | I2C0 Receive | NC | / |
0xE | I2C1 TX | I2C1 Transmit | UART0 TX | UART0 Transmit |
0xF | I2C1 RX | I2C1 Receive | UART0 RX | UART0 Receive |