第十一章 DMA试验 本章将向大家介绍W7500的 DMA。在本章中,将利用 W7500的DMA将串口接收到的数据传送到变量中,在通过串口将变量输出打印出来。
本章分为如下几个部分:
11.1 W7500 DMA 简介
11.2 硬件设计
11.3 软件设计
11.4 下载验证
11.1 W7500 DMA 简介直接内存访问 (DMA) 用于外设与内存之间、内存与内存之间的高速数据传送。无需 CPU 参与,数据即可快速传送。这样就为 CPU 执行其他操作留出了资源空间。W7500的 DMA 控制器共有6个通道,每个通道都用于管理来自某个或多个外设的内存访问请求。在DMA 请求过程中,有一个处理优先级的裁决。 W7500 的 DMA 有以下一些特性: u 6个通道 u 每一个通道用于连接专门的硬件 DMA 请求,并同时支持软件触发器。 u 软件编译来自 DMA 通道的请求优先级 (系统默认为高级)。 u 内存到内存传输 (仅支持软件请求)。 u TCP/IP 到内存传输 (仅支持软件请求)。 u SPI/UART 到内存传输 (支持软件及硬件请求)。 u 获取 Flash, SRAM, APB 及 AHB 外设作为源和目的地。 从外设(UART0, UART1, SSP0, SSP1)产生的 DMA 请求,通过逻辑或输入到DMA 控制器,这就意味着同时只能有一个请求有效,如图11.1.1所示: 图11.1.1 W7500 DMA通道功能表 备注:软件请求是内存到内存及 TCP/IP 到内存之间使用 DMA 的唯一方式。 这里介绍一下 DMA设置相关的几个寄存器。 第一个是DMA的状态寄存器(DMA_STATUS),如图11.1.2所示: 图11.1.2 W7500 DMA的状态寄存器 这个寄存器是只读的寄存器,读取ENABLE这个位可以获取DMA控制器的状态,读取STATE[4]-[7]位可以看到控制状态机的当前状态。 第二个是DMA 的控制数据库指针寄存器(DMA_CTRL_BASE_PTR),如图11.1.3所示: 图11.1.3 W7500 DMA 的控制数据库指针寄存器 把数据源的地址写入该寄存器。 第三个是DMA 的通道设置使能寄存器(DMA_CHNL_ENABLE_SET),如图11.1.4所示: 图11.1.4 W7500 DMA 的通道设置使能寄存器 该寄存器可以使能要开启的DMA通道。 第四个是DMA的通道软件请求寄存器(DMA_CHNL_SW_REQUEST),如图11.1.5所示: 图11.1.5 W7500 DMA的通道软件请求寄存器 在需要的时候设置对应的位来开启DMA的传输。 DMA配置可以直接调用函数库的dma_init函数来对DMA进行初始化。
[mw_shl_code=applescript,true]void dma_init(void);[/mw_shl_code]如果要进行数据传输可以调用dma_memory_copy函数。 [mw_shl_code=applescript,true]void dma_memory_copy (uint32_t chnl_num, unsigned int src, unsigned int dest, unsigned int size, unsigned int num);[/mw_shl_code]dma_memory_copy函数的第一个参数为传输通道,第二个参数为数据源地址,第三个为数据目的地地址,第四个参数是传输的数据大小,第五个参数是传输数据的长度。如果要将tx_data中的数据通过DMA通道0传输到rx_data中可以这样写: [mw_shl_code=applescript,true]uint32_t tx_data = 0xFFF;
uint32_t rx_data;
dma_memory_copy (0, &tx_data, &rx_data , 2, 1);[/mw_shl_code]11.2 硬件设计本章用到的硬件资源有: 1) 串口 2) DMA 11.3 软件设计在W7500EVB DMA工程里,可以看到,user文件中多了 bsp_dma.c 文件和其头文件 bsp_dma.h,同时要引入 dma 相关的库函数文件 W7500x_dma.c 和W7500x _dma.h。 打开bsp_dma.c 文件, 主要代码如下: [mw_shl_code=applescript,true]void dma_mm_init(void)
{
dma_data_struct_init(); //初始化DMA数据结构体
dma_init(); //初始化DMA
}
void DMA_Memory_Copy(uint32_t chnl_num, unsigned int *src, unsigned int *dest, unsigned int size, unsigned int num)
{
uint32_t current_state;
dma_memory_copy(chnl_num, (unsigned int) src,(unsigned int) dest , size, num);
do{
current_state = (DMA->DMA_STATUS >> 4) & 0xF;
}while (current_state!=0);
}[/mw_shl_code]该部分代码有2个函数,第一个dma_mm_init函数是DMA的初始化。第二个DMA_Memory_Copy函数是进行数据传输的。 最后看看W7500x_it.c文件如下: [mw_shl_code=applescript,true]void UART2_Handler(void)
{
uint32_t rx_data;
DMA_Memory_Copy(3, (unsigned int*) &UART2->DATA,(unsigned int*) &rx_data , 0, 1);
S_UART_SendData(rx_data);
S_UART_ClearITPendingBit(S_UART_IT_FLAG_RXI);
}[/mw_shl_code]这里可以看到并没有使用串口2的数据接收函数,而是有DMA通道3将UART2数据寄存器的数据传输到了rx_data变量中在利用串口2打印出来。 11.4 下载验证在代码编译成功之后,下载代码到W7500EVB上,打开串口调试助手向W7500EVB发送数据,W7500EVB也会回发数据给我们,如图11.4.1所示: 图11.4.1 W7500EVB DMA试验结果
|