garfield

【原创】飞思卡尔kinetis增强直接存储访问(EDMA)控制器

0
阅读(3683)

这篇博文主要介绍了飞思卡尔kinetis处理器EDMA模块的性能以及使用方法,提供了代码示例和快速参考材料。

简介:

DMA 控制器提供了将数据从一个映射到另一个位置的能力。它配置和启动后,DMA 控制器在核心中并行操作,进行数据传输,否则将被CPU 接管。这样的结果是减少CPU 的负载和相应增加系统性能。图7-1 提供说明了一个DMA 控制器。

image

Kinetis 系列具备为数据移动而准备的增强直接存储访问(eDMA)控制器,Kinetis 系列的EDMA 控制器包含一个16 位的数据缓冲区作为临时存储,见图7-1。因为的Kinetis 是一个交叉的基础架构,CPU 是主要的总线主控挂钩M0 和M1 的主端口。 EDMA 是交叉开关连接到M2 的主端口。因此CPU 和EDMA 可以同时访问不同的从端口。有了这个多主架构,该系统可以最大限度的提升EDMA 功能。图7-2 显示的Kinetis 的EDMA系统的基本架构。

image

交叉开关(crossbar)构成了这个多主架构的核心,它连接每个主到所需的从属设备。如果所有主尝试联合访问相同的从属设备,一个仲裁方案开始消除总线争用。可以选择固定优先级和循环仲裁计划。如果所有的主试图访问两个不同的从属设备,由一个仲裁计划判定。

EDMA的工作

每个 Kinetis EDMA 模块的通道可触发启动DMA 从外围设备或软件的多个来源的传输。该EDMA 模块化集成的DMA 复用器路由不同的16 个通道的触发源。高达63个在其他外设事件的发生可以激活EDMA 传输。在许多模块,事件标志为可以置位eDMA或中断请求,这些可以通过选择DMAMUX_CHCFGn[SOURCE]寄存器来配置。

DMA 通道的多路复用有助于配置eDMA 源。52 个外围槽和10 个永久槽可以被路由到16个通道。前四个通道提供额外的定期触发功能。每个通道路由器可以分配到52 个外围DMA槽之一或是10 个永久槽之一。图7-3 说明了该DMA 复用器的逻辑结构。

image

DMA 复用支持支持三种不同的选择触发DMA 传输请求。
·禁用模式——没有请求信号传输到通道和通道被禁用。这是在DMA 复用中重置状态通道。禁用模式也可以用于暂停一个eDMA 通道来重新配置。
·正常模式——DMA 访问请求直接发送到指定的eDMA 通道。
·周期触发模式——这个模式只能用在eDMA 通道0~3。

图7 - 4 显示PIT 周期触发,外围传输源请求,和传输激活之间的关系。

image

传输过程

每个通道需要一个 32 比特的传输控制描述符(TCD)用来定义所需的数据移动操作。通道描述符用连续的顺序存储在eDMA 本地存储器系统中。
每次一个通道被激活并执行,N 个字节从源传输到目的地。这被称为一个次要传输回路。一个主要的传输回路包括一些次要的传输回路。这个数字是在指定的TCD 里。次要的回路迭代完成后,当前迭代CITER)TCD 领域递减。当当前迭代领域已经耗尽,该通道完成了主要的传输回路。图7-6 表明了主要和次要回路之间的关系。在这个例子中配置的通道,使主回路包括三个迭代的次要回路。次要回路配置为传输4 个比特。

image

EDMA配置

配置 eDMA 初始化步骤必须遵循以下:
1、写 eDMA 控制寄存器(仅需要在默认配置更需要的情况下)。
2、配置通道优先级寄存器中的 DCHPRIn(如果需要)。
3、使能错误中断使用 DMAEEI 或DMASEEI 寄存器(如果需要)。
4、为将被使用的通道写传输控制描述。
5、配置相应的外设模块和以适当的渠道配置 EDMA MUX 路线激活信号。
所有通道的传输属性在独特的通道TCD 中定义。每一个32 位的TCD 存储在eDMA 控制器模块。只有DONE,ACTIVE 和STATUS 域初始化复位。所有的其他TCD 域在通道被激活前,复位时未定义,必须用软件初始化。如果没有这样做,会产生不可预料的结果。

例子

输入到 ADC0 必须每毫秒进行一次采样。要做到这一点,当该模块可以接受命令的时候,一个32 位的AD 命令字必须在没毫秒提供给ADC0_SC1A(0x4003B000)。命令字是在内部SRAM 中。这个例子只需要单一的命令字提供给AD。它存储在一个标记为“command”的变量中。之后AD 完成转换。其结果放在AD 结果寄存器ADC0_RA,位于0x4003b010,到0x1fff9000 的SRAM 地址。

实施这个例子两个 EDMA 通道是必需的:一个是传输命令字另一个是传输的结果。命令传输需求1 毫秒的PIT 触发和一个总是触发。该DMA MUX 必需为PIT 门控通道激活配置。通道1 配置为执行这次传输。通道0 是用来传输AD 结果到RAM。当具有AD 结果准备标志时,这种传输是激活的。默认通道选择通道1 优先于通道0。这种配置保证了AD 能没1 毫秒接收一个命令字。但是在他们被eDMA 移走之前可能导致在结果寄存器中结果被覆盖,如通道读取结果没有优先权。
本设置是可以改变的,确保每个结果捕获给通道读取的结果拥有更高的优先权。该DMA MUX
配置通道0 和1 是:
/* Configure DMAMux for Channel 0 */
DMAMUX_CHCONFIG0 = (0
| DMAMUX_ENABLE /* Enable routing of DMA request */
| DMAMUX_SOURCE(40)); /* Channel Activation Source: AD_A Result */
/* Configure DMAMux for Channel 1 */
DMAMUX_CHCONFIG1 = (0
| DMAMUX_ENABLE /* Enable routing of DMA request */
| DMAMUX_TRIG /* Trigger Mode: Periodic */
| DMAMUX_SOURCE(54)); /* Channel Activation Source: AD_A Command */
通道1配置使用一个周期触发——PIT1。该PIT模块必须为所需的时间间隔启用和配置。在开始DMA传输时,AD模块的命令数据必须准备根据AD命令寄存器的定义(使能PIT1)。每个通道在这个例子中传输数据或分别从静态地址,32位长指令或结果寄存器。因此,当主要或次要回路完成时,有必要在TCD中恢复地址指针。这个例子没有表中的数据传输,所以需要完成的主回路只有一个次要回路。完成主要回路后,资源和目的地址因而恢复。该TCD为通道0和1配置。
/* Configure DMA Channel 0 TCD */
EDMAC_TCD0_W0 = EDMAC_SADDR(0x4003B010);/* Source Address = AD Result
Register
EDMAC_TCD0_W1 = (0
| EDMAC_SMOD(0x0) /* Source Modulo, feature disabled */
| EDMAC_SSIZE(0x2) /* Source Size = 0x2 -> 32-bit transfers */
| EDMAC_DMOD(0x0) /* Destination Modulo, feature disabled */
| EDMAC_DSIZE(0x2) /* Destination Size = 0x2 -> 32-bit transfers */
| EDMAC_SOFF(0x0)); /* Source addr offset = 0x0, do not increment */
EDMAC_TCD0_W2 = EDMAC_NBYTES(0x4); /* Transfer 4 bytes per channel
activation */
EDMAC_TCD0_W3 = EDMAC_SLAST(0x0); /* Do not adjust SADDR upon channel
completion */
EDMAC_TCD0_W4 = EDMAC_DADDR(0x1FFF9000); /* Destination Address = 0x500,
Ext RAM */
EDMAC_TCD0_W5 = (0
/*| EDMAC_CITER_E_LINK /* Do not set ELINK bit, no channel linking */
| EDMAC_CITER(0x1) /* Current Iter Count -> 1 "NBYTES" transfer */
| EDMAC_DOFF(0x0)); /* Destination addr offset = 0x0, no increment */
EDMAC_TCD0_W6 = EDMAC_DLAST(0x0); /* Do not adjust DADDR upon channel
completion */
EDMAC_TCD0_W7 = (0
| EDMAC_BITER(0x1) /* Beginning Iteration Count = 1 = CITER */
| EDMAC_BWC(0x0) /* Bandwidth control = 0 -> No eDMA stalls */
| EDMAC_MAJOR_LINKCH(0x0)); /* Ignored, no channel linking */
/* Configure DMA Channel 1 TCD */
EDMAC_TCD1_W0 = EDMAC_SADDR((uint32)&command);/* Source Addr = address
of command var */
EDMAC_TCD1_W1 = (0
| EDMAC_SMOD(0x0) /* Source Modulo, feature disabled */
| EDMAC_SSIZE(0x2) /* Source Size = 0x2 -> 32-bit transfers */
| EDMAC_DMOD(0x0) /* Destination Modulo, feature disabled */
| EDMAC_DSIZE(0x2) /* Destination Size = 0x2 -> 32-bit transfers */
| EDMAC_SOFF(0x0)); /* Source addr offset = 0x0, do not increment */
EDMAC_TCD1_W2 = EDMAC_NBYTES(0x4); /* Transfer 4 bytes per channel
activation */
EDMAC_TCD1_W3 = EDMAC_SLAST(0x0); /* Do not adjust SADDR upon channel
completion */
EDMAC_TCD1_W4 = EDMAC_DADDR(0x4003B000);/* Dest Addr = ATD Command Word
Register */
EDMAC_TCD1_W5 = (0
/*| EDMAC_CITER_E_LINK /* Do not set ELINK bit, no channel linking */
| EDMAC_CITER(0x1) /* Current Iter Count -> 1 "NBYTES" transfer */
| EDMAC_DOFF(0x0)); /* Destination addr offset = 0x0, no increment */
EDMAC_TCD1_W6 = EDMAC_DLAST(0x0); /* Do not adjust DADDR upon channel
completion */
EDMAC_TCD1_W7 = (0
/*| EDMAC_BITER_E_LINK /* Do not set ELINK bit, no channel linking */
| EDMAC_BITER(0x1) /* Beginning Iteration Count = 1 = CITER */
| EDMAC_BWC(0x0) /* Bandwidth control = 0 -> No eDMA stalls */
| EDMAC_MAJOR_LINKCH(0x0)); /* Ignored, no channel linking */

Baidu
map