【STM32H7教程】第40章 STM32H7的BDMA基础知识和HAL库API

发布时间:2023-04-13  

40.1 初学者重要提示

  1. BDMA只能操作D3域的存储器和外设,这点比较重要,操作的时候容易被遗忘。详情看本章2.6小节。

  2. BDMA支持8路通道。虽然是8路,但这8路不是并行工作的,而是由BDMA的仲裁器决定当前处理哪一路。

  3. BDMA不支持硬件FIFO,但是支持双缓冲。

  4. BDMA不支持突发模式。

  5. BDMA最大传输次数65535次,每次传输单位可以是字节、半字和字。

  6. BDMA的循环模式不可用于存储器到存储器模式。

  7. HAL库没有配套BDMA的双缓,当前的HAL库V1.3.0版本没有对双缓冲进行支持

40.2 BDMA基础知识

BDMA的几个关键知识点放在开头说:

  • 由于总线矩阵的存在,各个主控的道路四通八达,从而可以让DMA和CPU同时开工,但是注意一点,如果他们同时访问的同一个外设,会有一点性能影响的。

  • BDMA支持存储器到外设,外设到存储器,存储器到存储器和外设到外设的传输,其中外设到外设的传输,DMA1和DMA2是不支持的,这个模式在低功耗模式下比较有用。

  • BDMA只有一个AHB总线主控,而DMA1和DMA2是有两个的,可以分别用于源地址和目的地址的传输。

  • 源地址和目的地址的数据宽度可以不同,但是数据地址必须要跟其数据类型对齐。比如源地址是uint32类型的,那么此数组的地址必须4字节对齐。

  • BDMA主要有两种模式,一个是Normal正常模式,传输一次后就停止传输;另一种是Circular循环模式,会一直循环的传输下去,即使有DMA中断,传输也是一直在进行的。

  • BDMA的通道请求(Channel0 – Channel7)的优先级可编程,分为四级Very high priority,High priority,Medium priority和Low priority。通道的优先级配置相同的情况下,如果同时产生请求,会优先响应编号低的,即Channel0优先响应。

40.2.1 BDMA硬件框图

认识一个外设,最好的方式就是看他的框图,方便我们快速的了解BDMA的基本功能,然后再看手册了解细节。框图如下所示:

(注:ST做的DMA框图没有其它外设做的好,不够详细)

通过这个框图,我们可以得到如下信息:

  • bdma_tcif[0:7]接口

通道0 – 通道7的传输完成标志。

  • bdma_it[0:7]接口

通道0 – 通道7的中断触发。

  • bdma_req[0:7]接口

通道0 –通道7的请求信号接口。

  • Arbiter仲裁器

用于仲裁当期要处理的DMA请求。通过这里我们可以看出虽然是8路,但这8路不是并行工作的,而是由BDMA的仲裁器决定当前处理哪一路。

  • AHB总线接口

BDMA只有一个AHB总线主控,而DMA1和DMA2是有两个的,可以分别用于源地址和目的地址的传输。

DMA1和DMA2:

40.2.2 BDMA传输

BDMA支持如下几种传输模式:

  • 存储器到外设。

  • 外设到存储器。

  • 存储器到存储器。

  • 外设到外设的传输。

其中外设到外设的传输,DMA1和DMA2是不支持的,这个模式在低功耗模式下比较有用。

关于这几种传输方式要注意以下两个问题:

  • 源地址和目的地址的数据宽度可以不同,但是数据地址必须要跟其数据类型对齐。比如源地址是uint32类型的,那么此数组的地址必须4字节对齐。

  • BDMA不可以操作TCM区,其它的SRAM区均可操作,在第25章专门讲解过这个问题。

  • 拓展知识

MDK中全局变量的数据对齐问题说明:

armbbs.cn/forum.php? 。

40.2.3 BDMA的循环模式和正常模式

BDMA主要有两种模式,一个是Normal正常模式,传输一次后就停止传输;另一种是Circular循环模式,会一直循环的传输下去,即使有DMA中断,传输也是一直在进行的。

这两种模式各有用途。

  • Normal正常模式

适合用于单次传输,比如存储器到存储器的数据复制粘贴,又比如串口的数据单次发送,下次还需要发送的时候,使能下即可。

  • Circular循环模式

适合用于需要连续传输的场合,比如定时器触发BDMA实现任意IO的PWM输出。

另外特别注意,循环模式不可用于存储器到存储器模式。

40.2.4 BDMA数据封装和解封

独立的源和目标传输宽度(字节、半字、字):源和目标的数据宽度不相等时, DMA 自动封装/解封必要的传输数据来优化带宽。无需像F1系列那样强行要求数据缓冲的4字节对齐。下面是各种源地址和目的地址数据宽度传输4次的效果,可以帮助大家更好的理解。

40.2.5 BDMA双缓冲

BDMA也是支持双缓冲模式的,双缓冲的含义是源地址或者目的地址可以设置两个缓冲区,这种方式的好处是一个缓冲区在接收或者发送数据的时候,另一个缓冲区可以动态更新数据或者处理已经接收到的数据。

当用户开启了BDMA传输完成中断后,通过寄存器CCRx的CT位判断当前使用的是哪个缓冲区

  • 如果CT = 1表示当前正在使用缓冲区1,即寄存器BDMA_CM1ARx记录的地址。

  • 如果CT = 0表示当前正在使用缓冲区0,即寄存器BDMA_CM0ARx记录的地址。

另外注意,存储器到存储器的BDMA传输不支持双缓冲模式,仅可以用于存储器到外设或者外设到存储器。

40.2.6 BDMA可以操作的区域

根据第3章的总线互联方式,BDMA仅可以操作:AHB4,APB4的外设以及SRAM4,Backup RAM。

实际应用的时候要特别注意,防止操作错误。

40.3 BDMA的HAL库用法

BDMA的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置GPIO、时钟,并根据需要配置NVIC、中断和DMA。下面我们逐一展开为大家做个说明。

40.3.1 BDMA寄存器结构体

BDMA相关的寄存器是通过HAL库中的结构体DMA_TypeDef和DMA_Stream_TypeDef定义的,在stm32h743xx.h中可以找到这个类型定义:

typedef struct

{

  __IO uint32_t ISR;    /*!< DMA interrupt status register,       Address offset: 0x00 */

  __IO uint32_t IFCR;   /*!< DMA interrupt flag clear register,   Address offset: 0x04 */

} BDMA_TypeDef;


typedef struct

{

  __IO uint32_t CCR; /*!< DMA channel x configuration register  Addr offset: 0x08 + 0x14 * x,x = 0 to 7 */

  __IO uint32_t CNDTR;/*!< DMA channel x number of data register Addr offset: 0x0C + 0x14 * x,x = 0 to 7 */

  __IO uint32_t CPAR; /*!< DMA channel x peripheral address register Addr offset: 0x10 + 0x14 * x, x = 0 to 7*/

  __IO uint32_t CMAR; /*!< DMA channel x memory address register, Addr offset: 0x14 + 0x14 * x, x = 0 to 7 */

} BDMA_Channel_TypeDef;

__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:


#define     __O     volatile             /*!< Defines 'write only' permissions */

#define     __IO    volatile             /*!< Defines 'read / write' permissions */

与其它外设的的定义方式不同,BDMA有8组通道,每个通道都有一组BDMA_Channel_TypeDef结构体所定义的寄存器。


解决这个问题的办法就是定义一套BDMA_Channel0 - BDMA_Channel7来解决,定义在stm32h743xx.h文件。


#define PERIPH_BASE         ((uint32_t)0x40000000)

#define D3_AHB1PERIPH_BASE  (PERIPH_BASE + 0x18020000)

#define BDMA_BASE           (D3_AHB1PERIPH_BASE + 0x5400)

#define BDMA                ((BDMA_TypeDef *) BDMA_BASE)


#define BDMA_Channel0_BASE    (BDMA_BASE + 0x0008)

#define BDMA_Channel1_BASE    (BDMA_BASE + 0x001C)

#define BDMA_Channel2_BASE    (BDMA_BASE + 0x0030)

#define BDMA_Channel3_BASE    (BDMA_BASE + 0x0044)

#define BDMA_Channel4_BASE    (BDMA_BASE + 0x0058)

#define BDMA_Channel5_BASE    (BDMA_BASE + 0x006C)

#define BDMA_Channel6_BASE    (BDMA_BASE + 0x0080)

#define BDMA_Channel7_BASE    (BDMA_BASE + 0x0094)


#define BDMA_Channel0  ((BDMA_Channel_TypeDef *) BDMA_Channel0_BASE)

#define BDMA_Channel1  ((BDMA_Channel_TypeDef *) BDMA_Channel1_BASE)

#define BDMA_Channel2  ((BDMA_Channel_TypeDef *) BDMA_Channel2_BASE)

#define BDMA_Channel3  ((BDMA_Channel_TypeDef *) BDMA_Channel3_BASE)

#define BDMA_Channel4  ((BDMA_Channel_TypeDef *) BDMA_Channel4_BASE)

#define BDMA_Channel5  ((BDMA_Channel_TypeDef *) BDMA_Channel5_BASE)

#define BDMA_Channel6  ((BDMA_Channel_TypeDef *) BDMA_Channel6_BASE)

#define BDMA_Channel7  ((BDMA_Channel_TypeDef *) BDMA_Channel7_BASE)

我们访问BDMA的ISR寄存器可以采用这种形式:BDMA->ISR = 0,而访问通道0的CCR就可以采用这种形式BDMA_Channel0->CCR = 0。


40.3.2 BDMA句柄结构体DMA_HandleTypeDef

HAL库在DMA_TypeDef的基础上封装了一个结构体DMA_HandleTypeDef,定义如下:


typedef struct __DMA_HandleTypeDef

{

  void                            *Instance;                                         

  DMA_InitTypeDef                 Init;                                                       

  HAL_LockTypeDef                 Lock;                                                        

  __IO HAL_DMA_StateTypeDef       State;                                                    

  void                            *Parent;                                                       

  void                            (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma);     

  void                            (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);   

  void                            (* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma);     

  void                            (* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);  

  void                            (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma);      

  void                            (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma);       

 __IO uint32_t                    ErrorCode;                                                        

 uint32_t                         StreamBaseAddress;                                              

 uint32_t                         StreamIndex;                                                 

 DMAMUX_Channel_TypeDef           *DMAmuxChannel;                                                

 DMAMUX_ChannelStatus_TypeDef     *DMAmuxChannelStatus;                                         

 uint32_t                         DMAmuxChannelStatusMask;                                        

 DMAMUX_RequestGen_TypeDef        *DMAmuxRequestGen;                                              

 DMAMUX_RequestGenStatus_TypeDef  *DMAmuxRequestGenStatus;                                    

 uint32_t                         DMAmuxRequestGenStatusMask;                                 

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>