DMA

DMA 有2个一个在HCPU,一个在LCPU, 分别都支持内存-内存,内存-外设,外设-内存,外设-外设之间的传输.

主要特性

  • 8个独立的可配置通道

  • 每个通道的DMA请求可在16个硬件请求中选择1个,或由软件请求

  • 每个通道支持4档优先级配置,优先级相同时依照通道编号大小判决

  • 支持内存-内存,内存-外设,外设-内存,外设-外设传输

  • 源地址和目标地址均独立支持单字节/双字节/4字节访问,并都可以独立选择地址是否自动递增

  • 支持循环缓冲模式,单次传输完成后自动重新启动

  • 每个通道支持3种事件标志-传输完成,过半传输,传输出错,并能各自独立产生中断请求

  • 单次配置最大传输单元数为65536,每单元根据不同配置分别为单字节/双字节/4字节传输

DMAC对应的外设request id

req_sel

DMAC1

DMAC2

0

mpi1

usart4_tx

1

mpi2

usart4_rx

2

/

usart5_tx

3

i2c4

usart5_rx

4

usart1_tx

/

5

usart1_rx

/

6

usart2_tx

btim3

7

usart2_rx

btim4

8

gptim1_update

/

9

gptim1_trigger

/

10

gptim1_cc1

/

11

gptim1_cc2

/

12

gptim1_cc3

/

13

gptim1_cc4

/

14

btim1

/

15

btim2

/

16

atim1_update

/

17

atim1_trigger

/

18

atim1_cc1

/

19

atim1_cc2

/

20

atim1_cc3

/

21

atim1_cc4

/

22

i2c1

/

23

i2c2

/

24

i2c3

/

25

atim1_com

/

26

usart3_tx

/

27

usart3_rx

/

28

spi1_tx

/

29

spi1_rx

/

30

spi2_tx

/

31

spi2_rx

/

32

i2s1_tx

/

33

i2s1_rx

/

34

/

/

35

/

/

36

pdm1_rx_l

/

37

pdm1_rx_r

/

38

gpadc

/

39

adc0

/

40

adc1

/

41

dac0

/

42

dac1

/

43

gptim2_update

/

44

gptim2_trigger

/

45

gptim2_cc1

/

46

audprc_tx_out_ch1

/

47

audprc_tx_out_ch0

/

48

audprc_tx_ch3

/

49

audprc_tx_ch2

/

50

audprc_tx_ch1

/

51

audprc_tx_ch0

/

52

audprc_rx_ch1

/

53

audprc_rx_ch0

/

54

gptim2_cc2

/

55

gptim2_cc3

/

56

gptim2_cc4

/

57

sdmmc1

/

58

/

/

59

/

/

60

/

/

61

/

/

62

/

/

63

/

/

使用 DMA示例1

内存-内存 4字节传输 4096字节.

    DMA_HandleTypeDef hdma;
    HAL_StatusTypeDef err;

    uint32_t SrcAddress = 0x10000000;
    uint32_t DstAddress = 0x20000000;
    uint32_t Counts     = 1024;  //Transfer unit is word, so Counts= 4096 / 4
    
    /* Init DMA configure*/
    hdma.Instance                 = DMA1_Channel6;
    hdma.Init.Request             = 0;                     //Request id is useless while memory to memory, just set to 0
    hdma.Init.Direction           = DMA_MEMORY_TO_MEMORY;
    hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
    hdma.Init.PeriphInc           = DMA_PINC_ENABLE;
    hdma.Init.MemInc              = DMA_MINC_ENABLE;
    hdma.Init.Mode                = DMA_NORMAL;
    hdma.Init.Priority            = DMA_PRIORITY_MEDIUM;

    hdma.XferHalfCpltCallback = DMA_Xfer_Half_Callback_Func;
    hdma.XferCpltCallback     = DMA_Xfer_Complete_Callback_Func;
    hdma.XferErrorCallback    = DMA_Xfer_Error_Callback_Func;

    err = HAL_DMA_Init(&hdma);
    if (err != HAL_OK)
        return err;

    err = HAL_DMA_Start_IT(hadc->DMA_Handle, SrcAddress, DstAddress, Counts);
    if (err != HAL_OK)
        return err;

使用 DMA示例2

ADC模块-内存 4字节传输 4096字节.


    DMA_HandleTypeDef hdma;
    HAL_StatusTypeDef err;

    uint32_t SrcAddress = 0x10000000;
    uint32_t DstAddress = 0x20000000;
    uint32_t Counts     = 1024;  //Transfer unit is word, so Counts= 4096 / 4
    
    /* Init DMA configure*/
    hdma.Instance                 = DMA1_Channel6;
    hdma.Init.Request             = DMA_REQUEST_12;
    hdma.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
    hdma.Init.PeriphInc           = DMA_PINC_DISABLE;      //Periphral address NOT auto-increment
    hdma.Init.MemInc              = DMA_MINC_ENABLE;
    hdma.Init.Mode                = DMA_NORMAL;
    hdma.Init.Priority            = DMA_PRIORITY_MEDIUM;

    hdma.XferHalfCpltCallback = DMA_Xfer_Half_Callback_Func;
    hdma.XferCpltCallback     = DMA_Xfer_Complete_Callback_Func;
    hdma.XferErrorCallback    = DMA_Xfer_Error_Callback_Func;

    err = HAL_DMA_Init(&hdma);
    if (err != HAL_OK)
        return err;

    err = HAL_DMA_Start_IT(hadc->DMA_Handle, SrcAddress, DstAddress, Counts);
    if (err != HAL_OK)
        return err;

使用 DMA示例3

内存->FLASH1模块 1字节传输 4096字节.


    DMA_HandleTypeDef hdma;
    HAL_StatusTypeDef err;

    uint32_t SrcAddress = 0x20000000;
    uint32_t DstAddress = hflash->Instance->DR;
    uint32_t Counts = 4096;  //Transfer unit is byte, so Counts= 4096 / 1
    
    /* Init DMA configure*/
    hdma.Instance                 = DMA1_Channel6;
    hdma.Init.Request             = DMA_REQUEST_0;
    hdma.Init.Direction           = DMA_MEMORY_TO_PERIPH;
    hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
    hdma.Init.PeriphInc           = DMA_PINC_DISABLE;      //Periphral address NOT auto-increment
    hdma.Init.MemInc              = DMA_MINC_ENABLE;
    hdma.Init.Mode                = DMA_NORMAL;
    hdma.Init.Priority            = DMA_PRIORITY_MEDIUM;

    hdma.XferHalfCpltCallback = DMA_Xfer_Half_Callback_Func;
    hdma.XferCpltCallback = DMA_Xfer_Complete_Callback_Func;
    hdma.XferErrorCallback = DMA_Xfer_Error_Callback_Func;

    err = HAL_DMA_Init(&hdma);
    if (err != HAL_OK)
        return err;

    err = HAL_DMA_Start_IT(hadc->DMA_Handle, SrcAddress, DstAddress, Counts);
    if (err != HAL_OK)
        return err;

API参考

bf0_hal_crc.h