The AXI CDMA provides high-bandwidth Direct Memory Access (DMA) between a memory-mapped source address and a memory-mapped destination address using the AXI4 protocol. An optional Scatter
Gather (SG) feature can be used to offload control and sequencing tasks from thesystem CPU.
初始化,状态和控制寄存器都是通过AXI4-Lite slave接口控制 特点概要
-
Independent AXI4-Lite slave interface for register access
- Fixed 32-bit data width
-
Optional asynchronous operation mode
- Independent AXI4 Master interface for the primary CDMA datapath. Parameterizable width of 32, 64, 128, 256, 512, and 1,024 bits with fixed-address burst (key hole) support.
- Independent AXI4 Master interface for optional Scatter/Gather function. Fixed 32-bit data width.
-
Optional Data Realignment Engine for the primary CDMA datapath. Available with 32
and 64-bit datapath widths. -
Provides Simple DMA only mode and an optional hybrid mode supporting both Simple
DMA and Scatter Gather automation. -
Support for up to 64-bit Address Space
If the DRE is enabled, data reads can start from any Address byte offset. Similarly, when the DRE is enabled, the writes can happen at any byte offset address. For example, if Memory Map Data Width = 32, data is aligned if it is located at address offsets of 0x0, 0x4, 0x8, 0xC, etc. Data is unaligned if it is located at address offsets of 0x1, 0x2, 0x3 and so forth.
Note: Performing unaligned transfers when DRE is disabled will give unpredictable results
执行不对齐传输会出现不可预测的结果,那这种方式的优势是什么? 关于Register Space要注意的 The registers are 32-bits wide, and the register memory space must be aligned on 128-byte (80h) boundaries. AXI CDMA Register Summary 这个寄存器偏移地址的表格可能会经常使用,具体的寄存器经参考官方文档 [td]
Address Space Offset | Name | Description |
00h | CDMACR | CDMA Control |
04h | CDMASR CDMA | Status |
08h | CURDESC_PNTR | Current Descriptor Pointer |
0Ch | CURDESC_ | PNTR_MSB Current Descriptor Pointer. MSB 32 bits. Applicable only when the address space is greater than 32. |
10h | TAILDESC_PNTR | Tail Descriptor Pointer |
14h | TAILDESC_PNTR_MSB | Tail Descriptor Pointer. MSB 32 bits. Applicable only when the address space is greater than 32. |
18h | SA | Source Address |
1Ch | SA_MSB | Source Address. MSB 32 bits. Applicable only when the address space is greater than 32. |
20h | DA | Destination Address |
24h | DA_MSB | Destination Address. MSB 32 bits. Applicable only when the address space is greater than 32. |
28h | BTT | Bytes to Transfer |
1. Verify CDMASR.IDLE = 1.(检测状态寄存器看看是不是在运行,运行的时候是不能配置的)
2. Program the CDMACR.IOC_IrqEn bit to the desired state for interrupt generation on transfer completion. Also set the error interrupt enable (CDMACR.ERR_IrqEn), if so desired.(配置中断,中断应该可以不使能吧???待确定!)
3. Write the desired transfer source address to the Source Address (SA) register. The transfer data at the source address must be valid and ready for transfer.(设置源地址,读数据的地址,偏移地址是18h) If the address space selected is more than 32, write the SA_MSB register also.
4.* Write the desired transfer destination address to the Destination Address (DA) register.*(设置目的地址,写数据的地址,偏移地址是20h)If the address space selected is more than 32, then write the DA_MSB register also.
5. Write the number of bytes to transfer to the CDMA Bytes to Transfer (BTT) register. Up to 8,388,607 bytes can be specified for a single transfer (unless DataMover Lite is being used). Writing to the BTT register also starts the transfer.(设置需要传输的长度,设置完成就开始传输)
6. Either poll the CDMASR.IDLE bit for assertion (CDMASR.IDLE = 1) or wait for the CDMA to generate an output interrupt (assumes CDMACR.IOC_IrqEn = 1).(等待传输完毕,如果没设置中断则当CDMASR.IDLE = 1的时候表示传输完成,如果设置了中断,传出完成(maybe)会进入中断)
7. If interrupt based, determine the interrupt source (transfer completed or an error has occurred).
8. Clear the CDMASR.IOC_Irq bit by writing a 1 to the DMASR.IOC_Irq bit position.(清除中断请求位,个人理解如果可以不使能中断应该不需要这一步)
9. Ready for another transfer. Go back to step 1.(返回到STEP1开始下一次的传输) Scatter Gather Mode(minimum steps) Scatter Gather is a mechanism that allows for automated data transfer scheduling through a pre-programmed instruction list of transfer escriptors (Scatter Gather Transfer Descriptor Definition). This
list of instructions is organized into what is referred to as a transfer descriptor chain. Each descriptor has an address pointer to the next sequential descriptor to be processed(类似于C语言的链表). The last descriptor in the chain generally points back to the first descriptor in the chain but it is not required.
1. Write a valid pointer to the channel CURDESC_PNTR register (Offset 0x08). If the address space selected is more than 32, then write the CURDESC_PNTR_MSB to specify the upper bits of current descriptor pointer.(设置当前数据块的指针)
PS:CURDESC_PNTR Register Details(删减了一些) [td]
Bits | Field Name | Default Value | Access Type | CDMA Mode Used | Description |
31 to 6 | Current Descriptor Pointer | 0 | R/W (RO) | SG | Current Descriptor Pointer. Indicates the pointer of the current descriptor being worked on. This register must contain a pointer to a valid descriptor prior to writing to the TAILDESC_PTR register. When the CDMA SG Engine is running (CDMASR.IDLE = 0), the CURDESC_PNTR register is updated by the SG Engine to reflect the starting address of the current descriptor being executed. Descriptor addresses written to this field must be aligned to 64-byte boundaries (sixteen 32-bit words). Examples are 0x00, 0x40, 0x80. Any other alignment has undefined results. This register is cleared when CDMACR.SGMode = 0. |
5 to 0 | Reserved | 0 | RO | N/A | Writing to these bits has no effect and they are always read as zeros. |
3. Write a valid pointer to the channel TAILDESC_PNTR register (Offset 0x10). This starts the channel fetching and processing descriptors(这是尾数据块的指针).If the address space selected is more than 32, then write the AILDESC_PNTR_MSB to specify the upper bits of current descriptor pointer.
4. CDMA scatter gather operations continue until the descriptor at TAILDESC_PNTR is processed, and then the engine idles as indicated by CDMASR.Idle = 1. Cyclic CDMA Mode(循环模式) AXI CDMA can be run in cyclic mode by making certain changes to the BD chain setup.** In cyclic mode, CDMA fetches and processes the same BDs without any interruption. (数据传输会自动的在数据块之间轮询,没有中断产生,效率较高)The CDMA continues to fetch and process until it is stopped or reset. **To enable cyclic operation, the BD chain should be set up as show in Figure 3-1.
……
(还有一些寄存器,这里先略去) 中断概要 An interrupt output is provided by the AXI CDMA. This output drives High when an internal interrupt event is logged in the CDMA Status Register (CDMASR) and the associated interrupt enable bit is set in the CDMA Control Register (CDMACR).
IMPORTANT: This interrupt output is synchronized to the s_axi_lite_aclk clock input.
Internal interrupt events are different depending on whether the AXI CDMA is operating in Simple DMA mode or SG Mode. Simple DMA mode generates an IOC interrupt whenever a programmed transfer is completed.(简单模式每次传输完成都会有产生中断,效率较低) In addition, three error conditions reported by the DataMover (internal error, slave error, and decode error) can also generate an interrupt assertion. For Scatter Gather mode, the delay interrupt and the three SG engine error interrupt events are added to the interrupt event mix(SG模式可以只产生一次中断,通过中断级联减少中断频率). API 函数部分传输模式(两种)
-
simple DMA transfer
-
仅仅需要 source buffer address, destination buffer address and transfer length,每次只能传输一个BD(buffer descriptor )
-
仅仅需要 source buffer address, destination buffer address and transfer length,每次只能传输一个BD(buffer descriptor )
-
scatter gather (SG) DMA transfer
-
A SG DMA transfer 需要设置多个(>=1)BD, 多个BDs之间以链表的形式相连。同时也需要 source buffer address, destination buffer address, and transfer length.
-
A SG DMA transfer 需要设置多个(>=1)BD, 多个BDs之间以链表的形式相连。同时也需要 source buffer address, destination buffer address, and transfer length.
官方的API函数初始化方法一般步骤(以AXI CDMA为例):
CfgPtr = XAxiCdma_LookupConfig(DeviceId);
Status = XAxiCdma_CfgInitialize(&AxiCdmaInstance, CfgPtr, CfgPtr->BaseAddress); 函数原型 这个函数查找硬件里有没有我们要使用的设备(AXI CDMA等等)
XAxiCdma_Config* XAxiCdma_LookupConfig ( u32 DeviceId )
Look up the hardware configuration for a device instance Parameters:
-
DeviceId is the unique device ID of the device to lookup for
-
The configuration structure for the device. If the device ID is not found,a NULL pointer is returned.
This function initializes the driver. It should be called before any other function calls to the driver.
It sets up the driver according to the hardware build. It resets the hardware at the end. Parameters
- InstancePtr is the driver instance that is working on
- CfgPtr is the pointer to the hardware configuration structure
-
EffectiveAddr is the virtual address of the hardware instance. If address translation is not in use, please use the physical address
- XST_SUCCESS for success
- XST_INVALID_PARAM if word length is less than 4
-
XST_FAILURE for reset failure
/*******************************************************************/
/**
* The example to do the simple transfer through polling. The constant
* NUMBER_OF_TRANSFERS defines how many times a simple transfer is repeated.
*
* @param DeviceId is the Device Id of the XAxiCdma instance
*
* @return
* - XST_SUCCESS if example finishes successfully
* - XST_FAILURE if error occurs
*
* @note If the hardware build has problems with interrupt,
* then this function hangs
*
*
********************************************************************/
int XAxiCdma_SimplePollExample(u16 DeviceId)
{
XAxiCdma_Config *CfgPtr;
int Status;
int SubmitTries = 10; /* try 10 times on submission */
int Tries = NUMBER_OF_TRANSFERS;
int Index; /* Initialize the XAxiCdma device. */CfgPtr = XAxiCdma_LookupConfig(DeviceId);if (!CfgPtr) { return XST_FAILURE;}Status = XAxiCdma_CfgInitialize(&AxiCdmaInstance, CfgPtr, CfgPtr->BaseAddress);if (Status != XST_SUCCESS) { return XST_FAILURE;}/* Disable interrupts, we use polling mode */XAxiCdma_IntrDisable(&AxiCdmaInstance, XAXICDMA_XR_IRQ_ALL_MASK);for (Index = 0; Index < Tries; Index++) { Status = DoSimplePollTransfer(&AxiCdmaInstance, BUFFER_BYTESIZE, SubmitTries); if (Status != XST_SUCCESS) { return XST_FAILURE; }}/* Test finishes successfully */return XST_SUCCESS; }
/*******************************************************************/
/*
* The entry point for this example. It invokes the example function,
* and reports the execution status.
*
* @param None.
*
* @return
* - XST_SUCCESS if example finishes successfully
* - XST_FAILURE if example fails.
*
* @note None.
*
********************************************************************/
int main()
{
int Status; xil_printf("\r\n--- Entering main() --- \r\n");/* Run the poll example for simple transfer */Status = XAxiCdma_SimplePollExample(DMA_CTRL_DEVICE_ID);if (Status != XST_SUCCESS) { xil_printf("AxiCdma_SimplePollExample: Failed\r\n"); return XST_FAILURE;}xil_printf("AxiCdma_SimplePollExample: Passed\r\n");xil_printf("--- Exiting main() --- \r\n");return XST_SUCCESS; }