DMAC 示例

单块

  1. 分配一个空闲通道

    ch_num = GDMA_ChnlAlloc(gdma.index, (IRQ_FUN) Dma_memcpy_int, (u32)(&gdma), 3);
    

    这个函数同时包含以下操作:

    • 注册 IRQ 处理程序(如果使用中断模式)

    • 启用 NVIC 中断

    • 注册要使用的 DMAC 通道

  2. 配置中断类型

    PGDMA_InitTypeDef->GDMA_IsrType = (TransferType | ErrType);
    
  3. 配置中断处理函数

    在中断处理函数中清除挂起的中断。

    GDMA_ClearINT(0, PGDMA_InitTypeDef->GDMA_ChNum);
    
  4. 传输配置

    PGDMA_InitTypeDef->GDMA_SrcMsize   = MsizeEight;
    PGDMA_InitTypeDef->GDMA_SrcDataWidth = TrWidthFourBytes;
    PGDMA_InitTypeDef->GDMA_DstMsize = MsizeEight;
    PGDMA_InitTypeDef->GDMA_DstDataWidth = TrWidthFourBytes;
    PGDMA_InitTypeDef->GDMA_BlockSize = DMA_CPY_LEN >> 2;
    PGDMA_InitTypeDef->GDMA_DstInc = IncType; // if dst type is peripheral:no change
    PGDMA_InitTypeDef->GDMA_SrcInc = IncType; // if src type is peripheral:no change
    
  5. 配置硬件握手接口(如果目的端或源端为外设)

    PGDMA_InitTypeDef->GDMA_SrcHandshakeInterface= GDMA_HANDSHAKE_INTERFACE_AUDIO_RX;
    

    PGDMA_InitTypeDef->GDMA_DstHandshakeInterface = GDMA_HANDSHAKE_INTERFACE_AUDIO_TX;
    
  6. 配置传输地址

    PGDMA_InitTypeDef->GDMA_SrcAddr = (u32)BDSrcTest;
    PGDMA_InitTypeDef->GDMA_DstAddr = (u32)BDDstTest;
    
  7. 使用 GDMA_Init() 函数设置 DMAC 索引、通道、数据宽度、msize、传输方向、地址递增模式、硬件握手接口、重载控制、中断类型、块大小、多块配置,以及源地址和目的地址

    GDMA_Init(gdma.index, gdma.ch_num, PGDMA_InitTypeDef);
    
  8. 清理缓存

    DCache_CleanInvalidate();
    
  9. 启用 DMAC 通道

GDMA_Cmd(gdma.index, gdma.ch_num, ENABLE);

多块

这是 SRC 自动重载模式的示例。与单块相比,多块的 步骤 2 ~ 步骤 4 不同。

  1. 分配一个空闲通道

    ch_num = GDMA_ChnlAlloc(gdma.index, (IRQ_FUN) Dma_memcpy_int, (u32)(&gdma), 3);
    

    这个函数同时包含以下操作:

    • 注册 IRQ 处理程序(如果使用中断模式)

    • 启用 NVIC 中断

    • 注册要使用的 DMAC 通道

  2. 配置中断类型

    PGDMA_InitTypeDef->GDMA_IsrType = (BlockType | TransferType | ErrType);
    
  3. 配置中断处理函数

    1. 清除中断

      GDMA_ClearINT(0, PGDMA_InitTypeDef->GDMA_ChNum);
      
    2. 在最后一个数据块开始之前清除自动重载模式

      GDMA_ChCleanAutoReload(0, PGDMA_InitTypeDef->GDMA_ChNum, CLEAN_RELOAD_SRC);
      
  4. 传输配置

    PGDMA_InitTypeDef->GDMA_SrcMsize   = MsizeEight;
    PGDMA_InitTypeDef->GDMA_SrcDataWidth = TrWidthFourBytes;
    PGDMA_InitTypeDef->GDMA_DstMsize = MsizeEight;
    PGDMA_InitTypeDef->GDMA_DstDataWidth = TrWidthFourBytes;
    PGDMA_InitTypeDef->GDMA_BlockSize = DMA_CPY_LEN >> 2;
    PGDMA_InitTypeDef->GDMA_DstInc = IncType; // If DST type is peripheral: no change
    PGDMA_InitTypeDef->GDMA_SrcInc = IncType; // If SRC type is peripheral: no change
    PGDMA_InitTypeDef->GDMA_ReloadSrc = 1;
    PGDMA_InitTypeDef->GDMA_ReloadDst = 0;
    
  5. 配置硬件握手接口(如果目的端或源端为外设)

    PGDMA_InitTypeDef->GDMA_SrcHandshakeInterface= GDMA_HANDSHAKE_INTERFACE_AUDIO_RX;
    

    PGDMA_InitTypeDef->GDMA_DstHandshakeInterface = GDMA_HANDSHAKE_INTERFACE_AUDIO_TX;
    
  6. 配置传输地址

    PGDMA_InitTypeDef->GDMA_SrcAddr = (u32)BDSrcTest;
    PGDMA_InitTypeDef->GDMA_DstAddr = (u32)BDDstTest;
    
  7. 使用 GDMA_Init() 函数设置 DMAC 索引、通道、数据宽度、msize、传输方向、地址递增模式、硬件握手接口、重载控制、中断类型、块大小、多块配置,以及源地址和目的地址

    GDMA_Init(gdma.index, gdma.ch_num, PGDMA_InitTypeDef);
    
  8. 清理缓存

    DCache_CleanInvalidate();
    
  9. 启用 DMAC 通道

    GDMA_Cmd(gdma.index, gdma.ch_num, ENABLE);