Chinaunix首页 | 论坛 | 博客
  • 博客访问: 249300
  • 博文数量: 128
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 487
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-24 17:43
个人简介

人生境界:明智、中庸、诚信、谦逊

文章分类

全部博文(128)

文章存档

2014年(12)

2013年(116)

我的朋友

分类: 嵌入式

2013-11-07 14:46:01

    CC2530 DMA控制器操作流程图如下:
    
    CC2530中不能用设置寄存器的方式配置DMA的参数,而要使用一种特殊的DMA配置结构体,DMA Configuration Data Structure结构体,IAR编译环境中位域字段默认取向采用小端模式,配置结构体声明前使用#pragma bitfields=reversed取反向,声明结束后恢复IAR默认方式。

DMA配置结构体:

  1. // Place the bitfield members from the most significant bit to the least significant bit.
  2. #pragma bitfields=reversed
  3. typedef struct {
  4.    uint8 SRCADDRH;            //源地址高字节
  5.    uint8 SRCADDRL;            //源地址低字节
  6.    uint8 DESTADDRH;           //目的地址高字节
  7.    uint8 DESTADDRL;           //目的地址低字节
  8.    uint8 VLEN : 3;            //变长传输模式选择
  9.    uint8 LENH : 5;            //传输长度高字节
  10.    uint8 LENL : 8;            //传输长度低字节
  11.    uint8 WORDSIZE : 1;        //字节传输或字传输
  12.    uint8 TMODE : 2;           //传输模式选择
  13.    uint8 TRIG : 5;            //触发时间选择
  14.    uint8 SRCINC : 2;          //源地址增量方式选择
  15.    uint8 DESTINC : 2;         //目的地址增量方式选择
  16.    uint8 IRQMASK : 1;         //中断屏蔽位
  17.    uint8 M8 : 1;              //字节传输模式时用,8或7 bit传输长度
  18.    uint8 PRIORITY : 2;        //优先级选择
  19. } DMA_DESC;
  20. #pragma bitfields=default
    根据CC253x编程手册中的相关介绍:
    DMA共有四种传输模式
    单次传输模式:触发条件发生后启动一次传输,接着DMA通道等待下次触发发生。当传输长度字段指定的传输次数完成后,设置中断标志位通知CPU并卸载DMA通道配置参数。
    块传输模式:触发条件发生后,尽快完成长度字段指定的传输次数,完成后通知CPU并卸载DMA通道配置参数,即执行DMAARMn = 0。
    重复单次传输模式:与单次模式前段相同,只是会重装通道配置参数。
    重复块传输模式:与块模式前段相同,只是会重装通道配置参数。
    四种方式的差别具体看上边DMA操作流程图。

    DMA编程流程:
    1.DMA配置结构体赋值
    2.将配置结构体内存地址赋值给DMAxCFGH:DMAxCFGL
    3.DMAARMx相应通道位置1,装载通道配置参数,根据手册要求,装载通道时需要延迟9个时钟周期使其生效
    4.手动触发或等待触发条件
    5.清除中断标志位,无论中断屏蔽位关闭与否,传输完成后相应中断标志位都会置位

     CC2541_43_44_45_Peripherals_Software_Examples中DMA例程分析

dma_man_trigger.c 该例程展示了如何手动触发DMA,使用DMA方式复制内存数据到内存其他区域中

  1. /*******************************************************************************
  2.   Filename: dma_man_trigger.c

  3.   Description: This example shows how to trigger the DMA manually and use
  4.                DMA to move data from one area of RAM to another.

  5. *******************************************************************************/

  6. /*******************************************************************************
  7. * INCLUDES
  8. */

  9. // Include Name definitions of individual bits and bit-fields in the CC254x device registers.
  10. #include <ioCC254x_bitdef.h>
  11. #include <hal_types.h>
  12. #include <dma.h>
  13. // Include device specific file
  14. #include "ioCC2530.h"


  15. /*******************************************************************************
  16. * CONSTANTS
  17. */

  18. // String length.
  19. #define DATA_AMOUNT 16


  20. /*******************************************************************************
  21. * LOCAL VARIABLES
  22. */

  23. // The data that is to be copied to another place in memory.
  24. static char data[DATA_AMOUNT] = "DMA man trigger!";

  25. // The area where the data is to be copied to.
  26. static char copy[DATA_AMOUNT];

  27. // DMA configuration descriptor used for memory copy.
  28. static DMA_DESC dmaConfig0;


  29. /*******************************************************************************
  30. * LOCAL FUNCTIONS
  31. */


  32. /*******************************************************************************
  33. * @fn main
  34. *
  35. * @brief Sets up the DMA configuration struct, saves its address, arms the
  36. * DMA channel and triggers it manually. After the DMA transfer is
  37. * complete, the DMA channel 0 interrupt flag is cleared (it is
  38. * automatically set).
  39. *
  40. * @param void
  41. *
  42. * @return void
  43. *******************************************************************************/
  44. void main(void)
  45. {
  46.     /* Configure DMA channel 0. Settings:
  47.      * SRCADDR: address of the data to be copied (increasing).
  48.      * DESTADDR: address the data will be copied to (increasing).
  49.      * VLEN: use LEN for transfer count.
  50.      * LEN: equal to the number of bytes to be transferred.
  51.      * WORDSIZE: each transfer should transfer one byte.
  52.      * TMODE: block mode.
  53.      * TRIG: let the DMA channel be triggered manually, i.e., by setting the
  54.      * [DMAREQ.DMAREQ0] bit.
  55.      * SRCINC: increment by one byte.
  56.      * DESTINC: increment by one byte.
  57.      * IRQMASK: disable interrupts from this channel.
  58.      * M8: 0, irrelevant since we use LEN for transfer count.
  59.      * PRIORITY: high.
  60.      */
  61.     dmaConfig0.SRCADDRH = ((uint16)data >> 8) & 0x00FF;
  62.     dmaConfig0.SRCADDRL = (uint16)data & 0x00FF;
  63.     dmaConfig0.DESTADDRH = ((uint16)copy >> 8) & 0x00FF;
  64.     dmaConfig0.DESTADDRL = (uint16)copy & 0x00FF;
  65.     dmaConfig0.VLEN = DMA_VLEN_USE_LEN;             //使用固定长度
  66.     dmaConfig0.LENH = (DATA_AMOUNT >> 8) & 0x00FF;
  67.     dmaConfig0.LENL = DATA_AMOUNT & 0x00FF;        
  68.     dmaConfig0.WORDSIZE = DMA_WORDSIZE_BYTE;        //字节传输
  69.     dmaConfig0.TMODE = DMA_TMODE_BLOCK;             //块传输方式
  70.     dmaConfig0.TRIG = DMA_TRIG_NONE;                //手动触发
  71.     dmaConfig0.SRCINC = DMA_SRCINC_1;
  72.     dmaConfig0.DESTINC = DMA_DESTINC_1;
  73.     dmaConfig0.IRQMASK = DMA_IRQMASK_DISABLE;       //关闭DMA中断方式
  74.     dmaConfig0.M8 = DMA_M8_USE_8_BITS;
  75.     dmaConfig0.PRIORITY = DMA_PRI_HIGH;

  76.     /* The DMA configuration data structure may reside at any location in
  77.      * unified memory space, and the address location is passed to the DMA
  78.      * through DMA0CFGH:DMA0CFGL.
  79.      */
  80.     DMA0CFGH = ((uint16)&dmaConfig0 >> 8) & 0x00FF;
  81.     DMA0CFGL = (uint16)&dmaConfig0 & 0x00FF;

  82.     /* Arm the DMA channel, so that a DMA trigger can initiate DMA writing,
  83.     and apply 9 NOPs to allow the DMA arming to actually take effect. */
  84.     DMAARM |= DMAARM_DMAARM0;
  85.     NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP(); // 9 NOPs

  86.     // Trigger the DMA channel manually.
  87.     DMAREQ |= DMAREQ_DMAREQ0;

  88.     // Wait for the DMA transfer to complete.
  89.     while ( !(DMAIRQ & DMAIRQ_DMAIF0) );

  90.     /* By now, the transfer is completed, so the transfer count is reached.
  91.      * The DMA channel 0 interrupt flag is then set, so we clear it here.
  92.      */
  93.     
  94.     // Clear interrupt flag by R/W0, see datasheet.
  95.     DMAIRQ = ~DMAIRQ_DMAIF0;
  96.     
  97.     // End function with infinite loop (for debugging purposes).
  98.     while(1);
  99. }

dma_pre_trigger.c 通道0采用手动触发方式,通道1追踪通道0完成时触发

  1. /*******************************************************************************
  2.   Filename: dma_prev_trigger.c

  3.   Description: This example shows both how to trigger a DMA channel manually and
  4.                how to trigger a DMA channel by the completion of the previous
  5.                channel. Both channels copy data in RAM. Channel 0 makes the
  6.                first copy and channel 1 makes a copy of the first copy.


  7. *******************************************************************************/

  8. /*******************************************************************************
  9. * INCLUDES
  10. */

  11. // Include Name definitions of individual bits and bit-fields in the CC254x device registers.
  12. #include <ioCC254x_bitdef.h>
  13. #include <hal_types.h>
  14. #include <dma.h>
  15. // Include device specific file
  16. #include "ioCC2530.h"

  17. /*******************************************************************************
  18. * CONSTANTS
  19. */

  20. // String length.
  21. #define DATA_AMOUNT 16


  22. /*******************************************************************************
  23. * LOCAL VARIABLES
  24. */

  25. // The data that is to be copied to another place in memory.
  26. static char data[DATA_AMOUNT] = "DMA prev trigger";

  27. // The araes where data is to be copied to.
  28. static char copy1[DATA_AMOUNT];
  29. static char copy2[DATA_AMOUNT];

  30. // DMA configuration descriptor used for memory copy.
  31. static DMA_DESC dmaConfig0, dmaConfig1;


  32. /*******************************************************************************
  33. * LOCAL FUNCTIONS
  34. */


  35. /*******************************************************************************
  36. * @fn main
  37. *
  38. * @brief Sets up DMA configuration structs for both channel 0 and 1, saves
  39. * their addresses, arms both DMA channels and triggers channel 0
  40. * manually. After the first DMA transfer is completed, the DMA
  41. * channel 0 interrupt flag is cleared (it is automatically set).
  42. * The completion of the channel 0 transfer triggers the transfer on
  43. * channel 1, which copies the same data yet again. After the second
  44. * DMA transfer is completed, the DMA channel 0 interrupt flag is
  45. * also cleared and the program terminates.
  46. *
  47. * @param void
  48. *
  49. * @return void
  50. *******************************************************************************/
  51. void main(void)
  52. {
  53.     /* Configure DMA channel 0. Settings:
  54.      * SRCADDR: address of the data to be copied (increasing).
  55.      * DESTADDR: address the data will be copied to (increasing).
  56.      * VLEN: use LEN for transfer count.
  57.      * LEN: equal to the number of bytes to be transferred.
  58.      * WORDSIZE: each transfer should transfer one byte.
  59.      * TMODE: block mode.
  60.      * TRIG: let the DMA channel be triggered manually, i.e., by setting the
  61.      * [DMAREQ.DMAREQ0] bit.
  62.      * SRCINC: increment by one byte.
  63.      * DESTINC: increment by one byte.
  64.      * IRQMASK: disable interrupts from this channel.
  65.      * M8: 0, irrelevant since we use LEN for transfer count.
  66.      * PRIORITY: high.
  67.      */
  68.     dmaConfig0.SRCADDRH = ((uint16)data >> 8) & 0x00FF;
  69.     dmaConfig0.SRCADDRL = (uint16)data & 0x00FF;
  70.     dmaConfig0.DESTADDRH = ((uint16)copy1 >> 8) & 0x00FF;
  71.     dmaConfig0.DESTADDRL = (uint16)copy1 & 0x00FF;
  72.     dmaConfig0.VLEN = DMA_VLEN_USE_LEN;
  73.     dmaConfig0.LENH = (DATA_AMOUNT >> 8) & 0x00FF;
  74.     dmaConfig0.LENL = DATA_AMOUNT & 0x00FF;
  75.     dmaConfig0.WORDSIZE = DMA_WORDSIZE_BYTE;
  76.     dmaConfig0.TMODE = DMA_TMODE_BLOCK;
  77.     dmaConfig0.TRIG = DMA_TRIG_NONE;
  78.     dmaConfig0.SRCINC = DMA_SRCINC_1;
  79.     dmaConfig0.DESTINC = DMA_DESTINC_1;
  80.     dmaConfig0.IRQMASK = DMA_IRQMASK_DISABLE;
  81.     dmaConfig0.M8 = DMA_M8_USE_8_BITS;
  82.     dmaConfig0.PRIORITY = DMA_PRI_HIGH;

  83.     /* Configure DMA channel 1. Settings:
  84.      * Same as for channel 0, except for different source and destination
  85.      * addresses and let the DMA channel be triggered by the completion of the
  86.      * previous channel.
  87.      */
  88.     dmaConfig1.SRCADDRH = ((uint16)copy1 >> 8) & 0x00FF;
  89.     dmaConfig1.SRCADDRL = (uint16)copy1 & 0x00FF;
  90.     dmaConfig1.DESTADDRH = ((uint16)copy2 >> 8) & 0x00FF;
  91.     dmaConfig1.DESTADDRL = (uint16)copy2 & 0x00FF;
  92.     dmaConfig1.VLEN = DMA_VLEN_USE_LEN;
  93.     dmaConfig1.LENH = (DATA_AMOUNT >> 8) & 0x00FF;
  94.     dmaConfig1.LENL = DATA_AMOUNT & 0x00FF;
  95.     dmaConfig1.WORDSIZE = DMA_WORDSIZE_BYTE;
  96.     dmaConfig1.TMODE = DMA_TMODE_BLOCK;
  97.     dmaConfig1.TRIG = DMA_TRIG_PREV;        //前一个通道传输完成触发该通道
  98.     dmaConfig1.SRCINC = DMA_SRCINC_1;
  99.     dmaConfig1.DESTINC = DMA_DESTINC_1;
  100.     dmaConfig1.IRQMASK = DMA_IRQMASK_DISABLE;
  101.     dmaConfig1.M8 = DMA_M8_USE_8_BITS;
  102.     dmaConfig1.PRIORITY = DMA_PRI_HIGH;

  103.     /* The DMA configuration data structures may reside at any location in
  104.      * unified memory space, and the address locations is passed to the DMA
  105.      * through DMA0CFGH:DMA0CFGL and DMA1CFGH:DMA1CFGL for channel 0 and 1,
  106.      * respectively.
  107.      */
  108.     DMA0CFGH = ((uint16)&dmaConfig0 >> 8) & 0x00FF;
  109.     DMA0CFGL = (uint16)&dmaConfig0 & 0x00FF;
  110.     DMA1CFGH = ((uint16)&dmaConfig1 >> 8) & 0x00FF;
  111.     DMA1CFGL = (uint16)&dmaConfig1 & 0x00FF;

  112.     /* Arm DMA channel 0 and 1, so that they can be triggered by their
  113.        respective triggers, and apply 18 NOPs to allow the DMA arming
  114.        to actually take effect. */
  115.     DMAARM |= (DMAARM_DMAARM0 | DMAARM_DMAARM1);
  116.     NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP(); // 9 NOPs //装载通道的延时时间随装载通道数累加
  117.     NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP(); // 9 NOPs

  118.     // Trigger the DMA channel 0 manually.
  119.     DMAREQ |= DMAREQ_DMAREQ0;

  120.     // Wait for DMA transfer on channel 0 to complete.
  121.     while ( !(DMAIRQ & DMAIRQ_DMAIF0) );

  122.     /* By now, the first transfer is completed. The DMA channel 0 interrupt flag
  123.      * is then set, so we clear it here.
  124.      */
  125.     
  126.     // Clear interrupt flag by R/W0, see datasheet.
  127.     DMAIRQ = ~DMAIRQ_DMAIF0;

  128.     /* Wait for DMA transfer on channel 1 to complete. Then clear its interrupt
  129.      * flag.
  130.      */
  131.     
  132.     while ( !(DMAIRQ & DMAIRQ_DMAIF1) );
  133.     // Clear interrupt flag by R/W0, see datasheet.
  134.     DMAIRQ = ~DMAIRQ_DMAIF1;

  135.     // End function with infinite loop (for debugging purposes).
  136.     while(1);
  137. }
    调试时将断点打在DMAREQ |= DMAREQ_DMAREQ0;处,观察数组内存值的变化,可以看到,只要执行该条语句,两个通道的DMA操作接连完成,中断标志位都置位了,while ( !(DMAIRQ & DMAIRQ_DMAIF0) );及后续指令无需等到。

已经将平台修改为CC2530,源代码附件
dma.zip

阅读(5678) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~