STM32H7的MDMA基础知识

  • MDMA的基础特性
  • MDMA的硬件框图
  • MDMA块传输、缓冲传输和列表传输的区别(重要)
  • MDMA列表模式及其循环方式
  • MDMA的触发源
  • MDMA软件触发
  • MDMA的初始化流程总结
  • MDMA(Master direct memory access),可以这么理解其是DMA的加强版。

    MDMA 位于 D1 域,使用的 64 位的 AXI 总线,可以操作 TCM 空间(前面章节讲解的 DMA2D,通

    用 DMA 和 BDMA 不支持操作 TCM 空间)。

    对于本节,重点要了解 MDMA 的 buffer 缓冲传输,block 块传输和 list 列表模式的区别。

    MDMA的基础特性

    1. MDMA 有两个主控总线接口,一个是 AXI/AHB 总线接口,主要用存储器或者外设访问,另一个是AHBS 总线接口,仅用于 TCM 空间访问。
    2. 有个 16 个通道,32 个硬件触发源。每个通道都可以选择 1 个触发源,当然,也可以通过软件触发。
    3. 16 个通道的传输请求,既可以外设,也可以来自 DMA1 或 DMA2
    4. MDMA 具有一个 256 级的 DMA 空间,被分为两个 128 级空间使用。
    5. MDMA 的优先级可通过软件配置,支持 very high, high, medium, low 四个等级,如果配置的优先级相同,则由 channel 的序号决定,channel0 最高,channel15 最低。
    6. 数据宽度可以设置字节,半字,字和双字。源地址和目的地址的数据宽度可不同。
    7. 源地址和目标地址的大小和地址增量可以独立选择。
    8. 数据的打包和拆解是采用的小端格式。
    9. 支持突发模式,最大可传输 128 字节。
    10. 当源地址和目的地址的增量和数据大小相同,且位宽小于等于 32bit 时,才允许 TCM 使用突发模式。

    MDMA的硬件框图


    ◆ mdma_it
    mdma 的中断触发信号。
    ◆ mdma_str0 到 mdma_str31 触发源
    mdma 的输入请求。
    ◆ mdma_hclk
    MDMA 的 HCLK 时钟。

    MDMA块传输、缓冲传输和列表传输的区别(重要)

    初学MDMA、要搞清楚MDMA支持的块传输,缓冲传输和列表传输的区别。

    缓冲传输(MDMA_BUFFER_TRANSFER)
    这个模式主要用于 QSPI,DCMI,硬件 JPEG 等外设上。每个请求都会触发 BufferTransferLength
    (最大 128 字节)大小的数据传输,此大小由 HAL_MDMA_Init 调用的参数配置。

    块传输(MDMA_BLOCK_TRANSFER)
    此方式与 DMA1 和 DMA2 的数据传输相似,每次请求,触发一次块传输,块大小由
    HAL_MDMA_Start/HAL_MDMA_Start_IT 定义,或者列表模式里面的参数。

    多块传输(MDMA_REPEAT_BLOCK_TRANSFER)
    顾名思义,多块传输就是执行多次块传输,每次请求,触发多次的块传输,块大小和块数由
    HAL_MDMA_Start/HAL_MDMA_Start_IT 定义,或者列表模式里面的参数。

    列表传输(MDMA_FULL_TRANSFER)
    这种模式可以方便的实现多种 MDMA 配置进行切换,轮番实现,而且可以实现列表的循环方式。每次请求,将触发所有块和节点的传输(如果用户调用了函数HAL_MDMA_LinkedList_CreateNode \HAL_MDMA_LinkedList_AddNode),

    MDMA列表模式及其循环方式

    列表模式包含多种 MDMA 的配置表,每个表包含一组完整 MDMA 配置。用户可以使用函数
    HAL_MDMA_LinkedList_CreateNode 创建节点,再通过函数 HAL_MDMA_LinkedList_AddNode 将节点添加到列表里面。
    ◆ 使用列表模式的话,函数 HAL_MDMA_Init 创建的是节点 0。
    ◆ 使用函数 HAL_MDMA_LinkedList_EnableCircularMode 使能循环模式,注意是从节点 1 开始循环的,将节点 1 和末尾的节点相连,不包含 HAL_MDMA_Init 创建的节点 0。
    ◆ 节点 0 是初始配置,仅在初始化 MDMA 传输时使用一次,比如调用函数 HAL_MDMA_Start_IT。
    ◆ 如果要禁止循环模式,可以调用函数 HAL_MDMA_LinkedList_DisableCircularMode。
    ◆ 通过函数 HAL_MDMA_LinkedList_RemoveNode 还可以删除指定节点。

    MDMA的触发源

    MDMA支持的触发源如下,主要包含 DMA1,DMA2,DMA2D,LTDC,JPEG,QSPI,DSI,SDMMC和软件触发:

    #define MDMA_REQUEST_DMA1_Stream0_TC ((uint32_t)0x00000000U) 
    #define MDMA_REQUEST_DMA1_Stream1_TC ((uint32_t)0x00000001U) 
    #define MDMA_REQUEST_DMA1_Stream2_TC ((uint32_t)0x00000002U) 
    #define MDMA_REQUEST_DMA1_Stream3_TC ((uint32_t)0x00000003U) 
    #define MDMA_REQUEST_DMA1_Stream4_TC ((uint32_t)0x00000004U)
    #define MDMA_REQUEST_DMA1_Stream5_TC ((uint32_t)0x00000005U) 
    #define MDMA_REQUEST_DMA1_Stream6_TC ((uint32_t)0x00000006U)
    #define MDMA_REQUEST_DMA1_Stream7_TC ((uint32_t)0x00000007U) 
    #define MDMA_REQUEST_DMA2_Stream0_TC ((uint32_t)0x00000008U) 
    #define MDMA_REQUEST_DMA2_Stream1_TC ((uint32_t)0x00000009U) 
    #define MDMA_REQUEST_DMA2_Stream2_TC ((uint32_t)0x0000000AU) 
    #define MDMA_REQUEST_DMA2_Stream3_TC ((uint32_t)0x0000000BU) 
    #define MDMA_REQUEST_DMA2_Stream4_TC ((uint32_t)0x0000000CU) 
    #define MDMA_REQUEST_DMA2_Stream5_TC ((uint32_t)0x0000000DU)
    #define MDMA_REQUEST_DMA2_Stream6_TC ((uint32_t)0x0000000EU) 
    #define MDMA_REQUEST_DMA2_Stream7_TC ((uint32_t)0x0000000FU)
    #define MDMA_REQUEST_LTDC_LINE_IT ((uint32_t)0x00000010U) 
    #define MDMA_REQUEST_JPEG_INFIFO_TH ((uint32_t)0x00000011U) 
    #define MDMA_REQUEST_JPEG_INFIFO_NF ((uint32_t)0x00000012U) 
    #define MDMA_REQUEST_JPEG_OUTFIFO_TH ((uint32_t)0x00000013U) 
    #define MDMA_REQUEST_JPEG_OUTFIFO_NE ((uint32_t)0x00000014U) 
    #define MDMA_REQUEST_JPEG_END_CONVERSION ((uint32_t)0x00000015U) 
    #define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U) 
    #define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U) 
    #define MDMA_REQUEST_DMA2D_CLUT_TC ((uint32_t)0x00000018U) 
    #define MDMA_REQUEST_DMA2D_TC ((uint32_t)0x00000019U) 
    #define MDMA_REQUEST_DMA2D_TW ((uint32_t)0x0000001AU)
    #if defined(DSI)
    #define MDMA_REQUEST_DSI_TEARINGE_FFECT ((uint32_t)0x0000001BU) 
    #define MDMA_REQUEST_DSI_END_REFRESH ((uint32_t)0x0000001CU) 
    #endif /* DSI */
    #define MDMA_REQUEST_SDMMC1_ED_DATA ((uint32_t)0x0000001DU) 
    #define MDMA_REQUEST_SW ((uint32_t)0x40000000U)
    

    MDMA软件触发

    MDMA 配置为 MDMA_REQUEST_SW 软件触发时,可以通过函数
    HAL_MDMA_GenerateSWRequest 产生触发请求,使用此函数要注意以下两个问题:
    ◆ 如果传输结束或者传输还没有启动,调用此函数会返回 error。
    ◆ 如果传输还在进行中断,调用此函数会返回 error,这次请求会被忽略。
    ◆ MDMA 配置为 MDMA_BUFFER_TRANSFER 模式,软件触发。
    ◆ 注册回调函数 HAL_MDMA_XFER_BUFFERCPLT_CB_ID。
    ◆ 调用函数 HAL_MDMA_Start_IT 会触发一次 BufferTransferLength 长度的数据传输。
    ◆ 传输结束会进入回调函数,用户可以在回调函数里面再次调用HAL_MDMA_GenerateSWRequest
    启动传输。

    MDMA的初始化流程总结

    第 1 步:基本的初始化。
    函数 HAL_MDMA_Init 配置 MDMA 的基本参数。
    第 2 步:列表模式。
    如果使用列表模式,用户可以使用函数 HAL_MDMA_LinkedList_CreateNode 创建节点,再通过函
    数 HAL_MDMA_LinkedList_AddNode 将节点添加到列表里面。
    第 3 步:查询模式。
    函数 HAL_MDMA_Start 启动传输。
    函数 HAL_MDMA_PollForTransfer 查询传输完成。
    函数 HAL_MDMA_Abort 终止传输。
    第 4 步:中断方式。
    函数 HAL_NVIC_SetPriority 设置 MDMA 中断优先级。
    函数 HAL_NVIC_EnableIRQ 使能中断。
    函数 HAL_MDMA_Start_IT 启动中断传输。
    MDMA 的中断服务程序 MDMA_IRQHandler 里面调用 HAL_MDMA_IRQHandler,如果用户
    注册了各种回调函数,会在此函数里面执行。
    函数 HAL_MDMA_Abort_IT 可以终止 MDMA 中断传输,终止完成后,会调用回调函数XferAbortCallback(如果设置了的话)
    第 5 步:中断回调函数。
    函数 HAL_MDMA_RegisterCallback 注册回调函数,函数 HAL_MDMA_UnRegisterCallback 取消
    注册回调函数。
    XferCpltCallback : 传输完成回调。
    XferBufferCpltCallback : buffer 传输完成回调。
    XferBlockCpltCallback : block 传输完成回调。
    XferRepeatBlockCpltCallback : repeated block 传输完成回调。
    XferErrorCallback : 传输错误回调。
    XferAbortCallback : 传输终止回调。

    作者:爱煲汤的夏二

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32H7的MDMA基础详解

    发表回复