SAM4E单片机之旅——20、DMAC之使用Multi-buffer进行内存拷贝

发布者:知音学友最新更新时间:2017-01-07 来源: eefocus关键字:SAM4E  单片机  DMAC  Multi-buffer  内存拷贝 手机看文章 扫描二维码
随时随地手机看文章

这次使用这个DMAC的Multi-buffer传输功能,将两个缓冲区的内容拷贝至一个连续的缓冲区中。

 

一、 DMAC

在M4中,DMA控制器(DMAC)比外设DMA控制器(PDC)要复杂,但是功能更加强大。

为适应不同的传输要求,DMAC 可以进行灵活的自定义配置,甚至配备了一个FIFO缓存。比如可以为源设备和目标设备分别设定传输时,地址的变动方式(递增、递减或固定);以及一次传输的数据量(字节、半字或字)。

DMAC有4个通道,每个通道可以进行一个传输任务。进行传输的设备可分为“内存”及“非内存”:内存表示随时可以对该设备进行访问,而非内存表示需要一个信号(握手接口)来触发或控制对设备的访问。握手接口可以选择硬件或软件的,并且可以在传输的过程中动态配置。

另外,比起PDC只能设置下一次传输的参数(传输地址,数据量大小等),DMAC可以先在内存中保存好若干次传输的参数,然后自动进行多次传输(Multi-buffer传输)。

 

二、 Multi-buffer传输的实现机制

每个通道有若干个寄存器。其中:源地址和目的地址寄存器(SADDR和DADDR),描述符地址寄存器(DSCR),控制器存器(CTRLA和CTRLB)这几个寄存器可以根据需要进行自动修改。在内存中有一块区域(LLI),连续地储存着这几个寄存器的目标设置。然后就像一个链表一样,DSCR表示下一个区域的地址:

image

在启用通道时,如果DSCR为0,则表示只需进行一次传输,在传输完成后就关闭通道。

如果DSCR不为0,则表示进行多次传输,而这几个寄存器的更新过程如下:

  1. 获取DSCR指向的LLI的内容。如果DSCR为0,则任务结束。

  2. 根据当前CTRLB寄存器的内容,判断是否需要根据该LLI更新SADDR及DADDR。然后根据该LLI更新其余寄存器(CTRLA,CTRLB,DSCR)。

  3. 根据新的寄存器内容进行传输。

  4. 传输完成后,将CTRLA的内容回写至内存中(传输中仅有该寄存器的BTSIZE和DONE字段会发生该变)。

  5. 根据通道CFG寄存器的Stop On Done(SOD)字段判断是否需要重新执行以上过程。

所以,在启用通道前,除了要设置好CFG寄存器外,也需要设置好CTRLB。

 

三、 实现思路

重申一下目标:将两个缓冲区的内容拷贝至一个连续的缓冲区中。

由于源缓冲区有两个,所以我们将使用两个LLI。其中每个LLI的SADDR指向每个源缓冲区的首地址,并且在每次获取LLI时,更新SADDR。而由于目标缓冲区是连续的,所以不需要更新DADDR。

然后在启用通道前,设置好DADDR。同时,设置CTRLB,该通道不从LLI中更新DADDR地址;设置好DSCR,使其指向第一个LLI。

 

四、 使用LLI

  1. 定义LLI结构体。

    LLI的内存布局不复杂,但是使用结构体来进行操作也很有助于简化工作。而且由于布局简单,也不用太关注内存对齐的细节。(另外,在使用LLI时,需要它的地址是字对齐的。)

    1
    2
    3
    4
    5
    6
    7
    typedef struct _lli{
        uint32_t SADDR;
        uint32_t DADDR;
        uint32_t CTRLA;
        uint32_t CTRLB;
        uint32_t DSCR;
    }LLI;
  2. LLI的初始化。

    由于两个LLI的设置有许多相同的部分,所以将共同的部分抽象出来。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // lli:     需要初始化的LLI的地址
    // saddr:       源地址
    // btsize:  传输次数
    // next_lli:    下一个LLI的地址。如果是最后一个LLI,该参数为NULL即可
    void InitLLI(LLI* lli, void* saddr, uint16_t btsize, LLI* next_lli)
    {
        lli->SADDR = (uint32_t)saddr;
        lli->DADDR = 0;      // DADDR 不会被使用,初始化为即可
        lli->DSCR = DMAC_DSCR_DSCR_Msk & (uint32_t)next_lli;
        lli->CTRLA =
              DMAC_CTRLA_BTSIZE(btsize)     // 传输次数
            | DMAC_CTRLA_SRC_WIDTH_WORD     // 源设备一次传输一个字
            | DMAC_CTRLA_DST_WIDTH_WORD     // 目标设备一次传输一个字
            ;
        lli->CTRLB =
              DMAC_CTRLB_SRC_DSCR_FETCH_FROM_MEM    // 从LLI中更新SRC地址
            | DMAC_CTRLB_DST_DSCR_FETCH_DISABLE // 不更新DST地址
            | DMAC_CTRLB_FC_MEM2MEM_DMA_FC      // 设备类型:内存至内存
            | DMAC_CTRLB_SRC_INCR_INCREMENTING  // 传输时,源地址递增
            | DMAC_CTRLB_DST_INCR_INCREMENTING  // 传输时,目标地址递增
            ;
    }

 

 

五、 实现过程

  1. 缓冲区。

    1
    2
    3
    4
    5
    6
    7
    8
    // 源缓冲区
    uint32_t src1[2];
    uint32_t src2[3];
    // 目标缓冲区
    uint32_t dst[5];
    // 向源缓冲区时填充内容
    src1[0] = 50; src1[1] = 51;
    src2[0] = 52; src2[1] = 53; src2[2] = 54;
  2. 设置LLI。

    注意,要确保LLI的实例在整个程序的运行过程中都是有效的。比如如果LLI是储存在函数的栈中的话,那么函数退出后,该LLI即无效了。所以可以选择在堆中分配LLI实例的空间,或是将其定义为全局变量,也可以在main函数中定义实例。

    1
    2
    3
    LLI first_lli, last_lli;
    InitLLI(&first_lli, (void*)src1, 2, &last_lli);
    InitLLI(&last_lli, (void*)src2, 3, 0);
  3. 启用DMAC。

    1
    2
    3
    4
    5
    // PMC
    PMC->PMC_PCER0 = 1 << ID_DMAC;
    DMAC->DMAC_GCFG =
         DMAC_GCFG_ARB_CFG_ROUND_ROBIN; // 轮转优先级
    DMAC->DMAC_EN = DMAC_EN_ENABLE;
  4. 配置通道。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 使用的通道为通道0
    #define DMAC_CH 0
    // 使DSCR指向first_lli
    DMAC->DMAC_CH_NUM[DMAC_CH].DMAC_DSCR =
            (uint32_t)(void*)(&first_lli);
    // 设置目标地址
    DMAC->DMAC_CH_NUM[DMAC_CH].DMAC_DADDR =
    (uint32_t)(void*) dst;
    // 设置CTRLB,使通道从LLI中更新源地址
    DMAC->DMAC_CH_NUM[DMAC_CH].DMAC_CTRLB =
              DMAC_CTRLB_SRC_DSCR_FETCH_FROM_MEM
            | DMAC_CTRLB_DST_DSCR_FETCH_DISABLE;
    // 配置CFG寄存器
    DMAC->DMAC_CH_NUM[DMAC_CH].DMAC_CFG =
    DMAC_CFG_SOD_DISABLE
            | DMAC_CFG_FIFOCFG_ALAP_CFG
            ;
  5. 启用通道。

    1
    DMAC->DMAC_CHER = DMAC_CHER_ENA0 << DMAC_CH;
  6. 等待通道关闭,即传输完成。

    1
    2
    const uint32_t check_bit = DMAC_CHSR_ENA0 << DMAC_CH;
    while( (DMAC->DMAC_CHSR & check_bit) != 0);


关键字:SAM4E  单片机  DMAC  Multi-buffer  内存拷贝 引用地址:SAM4E单片机之旅——20、DMAC之使用Multi-buffer进行内存拷贝

上一篇:SAM4E单片机之旅——19、CAN间通信
下一篇:SAM4E单片机之旅——21、DMAC之USART回显

推荐阅读最新更新时间:2024-03-16 15:29

富士通半导体发布84款FM4系列32位微控制器产品
富士通半导体(上海)有限公司日前宣布,推出首批基于ARM® Cortex™-M4处理器内核的FM4系列32位RISC 微控制器。富士通半导体本次共推出84款MB9B560R/460R/360R/160R 系列产品,将于2013年7月底开始提供样片。 FM4系列是基于现有的FM3系列,能够提供具有更高计算性能和增强的外设性能的产品。FM4系列推出的新品继承了FM3系列的高品质和易用性,应用领域较FM3更广泛。新品适合需要先进高速计算性能的应用领域,例如:通用变频器、伺服电机、可编程逻辑控制器(PLC)和其它工业设备及使用变频的家电。 富士通半导体自2010年推出FM3系列产品以来,致力于提供易于选择、使用且
[单片机]
51单片机蓝牙空气质量PM2.5检测设计
享一个很好的蓝牙+PM2.5空气质量+DHT11温湿度上下限报警的设计,主控芯片是51单片机. 实物图: 仿真原理图如下 元件列表: Comment Designator LibRef Quantity 蜂鸣器 BUUZER BUZZER 1 电解电容 C1 10uF 1 电解电容 C2 220uF 1 瓷片电容 C3, C4 18pF 2 电解电容 C5 470uF 1 瓷片电容 C6 104 1 排针 DC 5V Header 2 2P 触点开关 JIA, JIAN,RESET SW-PB 3 液晶 LCD1602 LCD
[单片机]
51<font color='red'>单片机</font>蓝牙空气质量PM2.5检测设计
单片机有效地址的访问和禁止地址写入的后果
下面我们看看对有效地址的访问和对禁止地址写入时造成的后果 第一段程序的意图是将两个数据31H和11H分别存入外部数据 存储器 的两个单元中,但程序中却使用了第一片存储器物理空间00单元所对应的两个逻辑单元,其结 果是第二个数据11H覆盖了第一片存储器物理地址00单元中的第一个数据31H,这段程序说明的问题是外部存储器的一个物理单元对应两个逻辑地址,但它仍旧只是一个存储器,不能当两个存储器使用。 第二段程序的意图是将数据31H存入第二片外部数据存储器物理单元00中,然后再分别使用该物理单元所对应的两个逻辑地址从该单元中取数据,其效 果一样,说明对某一物理单元访问时,使用该单元对应的任一个逻辑地址都可以。 第三段程序的意图是向禁止
[单片机]
对<font color='red'>单片机</font>有效地址的访问和禁止地址写入的后果
基于单片机的对讲机加密系统设计
CTCSS(Continuous Tone Controlled Squelch Systern,连续语音控制静噪系统)是一种将低于音频频率的频率(67.0~250.3 Hz)附加在音频信号中一起传输的技术。国际标准的CTCSS编码一共有38组频率,因为这些静噪信号频率为67.0~250.3 Hz,低于话音通信带宽的下限,所以被称为“亚音频”。CTCSS技术已经广泛用于无线电通信中,是传统无线电台通信中一种常见的收发限制手段。在电台的中继站和对讲机中,采用CTCSS技术可以避免接收到不相干的呼叫。   在对讲机设计中采用亚音频技术,其目的是避免不同用户的相互干扰,避免收听无关的呼叫和干扰信号。因为它可以在共同信道中制止来自其他用
[单片机]
基于<font color='red'>单片机</font>的对讲机加密系统设计
与编译器开发商密切合作优化微控制器开发
微控制器开发团队与编译器开发人员的合作成果是生成的代码效率更高,性能更好。本文介绍的是为了使ATMEL AVR微控制器系列更适合C编译器,开发者在编译器开发阶段对微控制器架构和指令集所进行的调整。 AVR架构的核心是一个可快速访问RISC寄存器文件。该文件由32个8位通用寄存器构成。微控制器可在一个单时钟周期内加载该文件中的任意两个寄存器到算术逻辑单元(Arithmetic Logical Unit, ALU),完成所要求的操作,将结果写回到任意一个寄存器。ALU支持寄存器间或某一寄存器与一个常数之间的运算和逻辑功能,单寄存器操作也是在ALU中执行的。微控制器使用一个哈佛(Harvard)架构,在该架构中,程序存储器空间与数
[工业控制]
与编译器开发商密切合作优化<font color='red'>微控制器</font>开发
基于ATmega16单片机 程控滤波器程序源代码
#include avr/io.h #include avr/signal.h #include avr/interrupt.h #include util/delay.h #define uint unsigned int #define uchar unsigned char static uchar interrupt ,count; static uchar b; uint a; SIGNAL(SIG_OVERFLOW1)/*溢出中断*/ { TCNT1H=0X7F; TCNT1L=0XFC; interrupt++; if(interrupt==a) { interrupt=0;
[单片机]
利用小型MCU实现LED照明的色彩控制
LED用于通用照明已指日可待。LED在通用照明系统中优势很多,如寿命更长以及效率更高。然而, LED技术还面临着一些挑战。其中一个挑战就是如何产生高品质的白光。白光LED的构成包含了蓝光LED 和能将光输出移至光谱的其他波段的一种荧光粉。许多白光LED都无法产生高显色指数(Color Rendering Index,CRI),该参数用于衡量光源真实重现色彩的能力。 通过混合两种或两种以上颜色的LED光,可以获得品质更高的白光系统。在这些多色系统中,每种色源的光输出会随时间和温度而漂移。光传感器和小型单片机(MCU)可用于维持特定颜色和相关色温(Correlated Color Temperature,CCT)。在本文中,我们将进一
[电源管理]
利用小型<font color='red'>MCU</font>实现LED照明的色彩控制
基于16位单片机的音频信号分析仪的设计
目前,大多数音频信号处理仪不但体积大而且价格贵,在一些特殊方面难以普及使用,而嵌入式系统分析仪具有小巧可靠的特点,所以开发基于特殊功能单片机的音频分析仪器是语音识别的基础,具有很好的现实意义。信号分析原理是将信号从时间域转换成频率域,使原始信号中不明显特性变得明显,便于分析处理。对于音频信号来说,其主要特征参数为幅度谱、功率谱。该音频信号分析仪的工作过程为:对音频信号限幅放大、模数转换、快速傅里叶变换(FFT,时域到频域的转换)、特征值提取;从到音频信号的幅度谱,进而得到音频信号的功率谱。   1 硬件设计   “智能家居”(SmartHome)也称智能住宅。家居网络智能控制系统就是利用先进的计算机技术、通讯技术和嵌入式技术,将
[单片机]
基于16位<font color='red'>单片机</font>的音频信号分析仪的设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved