<!-- 本文件由脚本自动转换生成，请勿手动编辑 -->

> **《LKS32MC08x User Manual》DMA** . 完整目录见 [README.md](README.md)
>
> **声明**：本文档由芯片用户手册自动转换生成，仅供检索与查阅参考。Markdown 格式可被自由编译、修改，本文档不构成正式技术文件，相关内容以凌鸥创芯官方网站正式发布的手册为准。
>
> 南京凌鸥创芯电子有限公司 . (C) 2019, 版权归凌鸥创芯所有 . 机密文件，未经许可不得扩散

# DMA

## 概述

增加DMA后，总线上主设备由CPU增加为CPU和DMA，总线架构需要由AHB
lite演进为multi-layer AHB
lite架构。如图7-1所示。其中部分设备不需要被DMA访问，仅仅挂载于与CPU相连的AHB
bridge
0上。**包括ADC/DAC/SPI/I2C/MCPWM/UART/SRAM在内的设备被CPU和DMA共享访问，挂载于AHB
bridge 1上。而Timer/DSP/GPIO/Hall/Flash等设备，DMA无法访问。**

从设备端的仲裁模块本质上相当于一个二选一的多路选择器。只有端口上有仲裁器的从设备才能被DMA访问到，否则无法被DMA访问，而所有外设设备均可被CPU访问。

【图片已删除】为控制知识库体积，本文档不携带图片，相关图示请查阅凌鸥创芯官网发布的正式手册。

图7-1
multi-layer AHB lite总线架构

出于功耗控制考虑，DMA模块可以通过设置DMA_CTRL.EN位为0来被禁用（要求关闭DMA使能前先关闭4个通道对应的使能DMA_CCRx.EN），此时DMA时钟被门控关闭。DMA包含配置寄存器（相当于一个从设备，被CPU配置）和数据搬运模块（对于总线为主设备，向总线发起各种设备访问请求）。

DMA支持8, 16或32 bit (byte, half-word, or word)
三种位宽的传输操作，通过配置DMA_CCRx.PBTW和DMA_CCRx.MBTW来选择外设和内存访问的位宽，外设访问的位宽与内存访问的位宽可以不同。

DMA
每完成一次传输，地址根据DMA_CCRx.PINC和DMA_CCRx.MINC决定是否自动递增。所有的外设寄存器地址都是word对齐的，所以外设的地址递增永远是0/4
(根据DMA_CCRx.PINC=0/1设置)。例如对于UART/SPI/I2C，因为每次都是访问UART_DATA或SPI/I2C
FIFO接口的固定地址,
DMA_CCRx.PINC=0；如要访问ADC数据寄存器，则地址通常需要自动加4，需要设置DMA_CCRx.PINC=1。而对于内存，如果设置了DMA_CCRx.MINC=1，每次地址递增的值，根据内存数据位宽(DMA_CCRx.MBTW)设定，对于内存访问位宽为byte的情况，地址自动加1，对于half-word，地址自动加2，对于word，地址自动加4。

需要注意的是，我们将DMA的传输分为多个轮次，每轮传输内可以有多次传输。DMA_CCRx.PINC用于控制外设地址每次传输是否递增。外设地址每轮传输一定重复上一轮的地址，即轮内可以递增，轮间不递增；DMA_CCRx.MINC用于控制内存地址轮间是否递增，每次传输一定递增。

【图片已删除】为控制知识库体积，本文档不携带图片，相关图示请查阅凌鸥创芯官网发布的正式手册。

图 7-2 DMA地址递增控制

DMA有循环模式和单次模式两种模式，由DMA_CCRx.CIRC控制。循环模式下DMA完成一定大小的数据块搬运后重新开始下一轮搬运，如果是搬运数据到内存，则覆盖之前搬运至内存的数据；如果是搬运至外设，则重复一轮数据发射。以将ADC数据搬运至内存为例，设定数据块大小为16bit×12channel×8次，则在循环模式下DMA完成一轮96个half
word搬运后重新开始下一轮搬运，并覆盖之前使用的内存地址，不设置DMA完成中断标志位。单次模式下，DMA完成一定大小的数据块搬运后即完成本次DMA操作，设置完成DMA完成中断标志位，同时硬件自动关闭对应的DMA通道，即硬件电路自动在该通道传输完成后将DMA_CCRx.EN设为0。DMA需要搬运的轮次由DMA_CTMS寄存器进行控制。

【图片已删除】为控制知识库体积，本文档不携带图片，相关图示请查阅凌鸥创芯官网发布的正式手册。

图7-4
DMA通道优先级

## 仲裁

当DMA处于空闲状态，或刚刚完成某一通道的DMA传输后，若此时恰好有一个或多个DMA请求发生，应根据优先级设定进行仲裁，优先级高的外设请求率先得到DMA服务。比如ADC连续模式下，每完成一轮ADC数据搬运，ADC的采样完成事件标志被DMA清零，DMA回到空闲状态或转而服务其他外设请求；对于UART，每搬运一个byte重新仲裁；对于SPI/I2C每搬运完一个FIFO的数据，重新仲裁。

CPU访问RAM的优先级始终高于DMA。

为了避免CPU或DMA长期占用外设/SRAM，在外设/SRAM的端口仲裁模块中加入了时间片机制，即一个主设备占用一段时间后释放访问权，仲裁模块观测另一个主设备是否在请求访问，如果是则转而允许另一个主设备访问，否则继续当前主设备未完成的访问。

## 中断

DMA的一个通道完成DMA操作后或出错则产生DMA中断。当DMA某一个通道完成操作后，会自动关闭该通道的使能为DMA_CCRx.EN。

## 寄存器

### 地址分配

DMA控制器模块寄存器的基地址是0x4001_3000，寄存器列表如下：

表7-2
DMA寄存器列表

||||
|---|---|---|
|名称|偏移地址|说明|
|DMA_CCR0|0x00|DMA通道0通道配置寄存器|
|DMA_CTMS0|0x04|DMA通道0传输次数寄存器|
|DMA_CPAR0|0x08|DMA通道0外设地址寄存器|
|DMA_CMAR0|0x0C|DMA通道0内存地址寄存器|
|DMA_CCR1|0x10|DMA通道1通道配置寄存器|
|DMA_CTMS1|0x14|DMA通道1传输次数寄存器|
|DMA_CPAR1|0x18|DMA通道1外设地址寄存器|
|DMA_CMAR1|0x1C|DMA通道1内存地址寄存器|
|DMA_CCR2|0x20|DMA通道2通道配置寄存器|
|DMA_CTMS2|0x24|DMA通道2传输次数寄存器|
|DMA_CPAR2|0x28|DMA通道2外设地址寄存器|
|DMA_CMAR2|0x2C|DMA通道2内存地址寄存器|
|DMA_CCR3|0x30|DMA通道3通道配置寄存器|
|DMA_CTMS3|0x34|DMA通道3传输次数寄存器|
|DMA_CPAR3|0x38|DMA通道3外设地址寄存器|
|DMA_CMAR3|0x3C|DMA通道3内存地址寄存器|
|DMA_CTRL|0x40|DMA控制寄存器|
|DMA_IF|0x44|DMA中断标志寄存器|

### DMA_CTRL DMA控制寄存器

地址：0x4001_3040

复位值：0x0

表7-3 DMA控制寄存器DMA_CTRL

|||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
|||||||||||||||PRIORITY|EN|
|||||||||||||||RW|RW|
|||||||||||||||0|0|

||||
|---|---|---|
|位置|位名称|说明|
|\[31:2\]||未使用|
|\[1\]|PRIORITY|0:CPU优先级高；1:DMA优先级高，此版本必须设置CPU优先级高|
|\[0\]|EN|DMA使能|

### DMA_IF DMA中断标志寄存器

地址：0x4001_3044

复位值：0x0

表7-4 DMA中断标志寄存器DMA_IF

|||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
|||||||||CH3_EIF|CH2_EIF|CH1_EIF|CH0_EIF|CH3_FIF|CH2_FIF|CH1_FIF|CH0_FIF|
|||||||||RW1C|RW1C|RW1C|RW1C|RW1C|RW1C|RW1C|RW1C|
|||||||||0|0|0|0|0|0|0|0|

||||
|---|---|---|
|位置|位名称|说明|
|\[31:8\]||未使用|
|\[7\]|CH3_EIF|通道3错误中断标志|
|\[6\]|CH2_EIF|通道2错误中断标志|
|\[5\]|CH1_EIF|通道1错误中断标志|
|\[4\]|CH0_EIF|通道0错误中断标志|
|\[3\]|CH3_FIF|通道3完成中断标志|
|\[2\]|CH2_FIF|通道2完成中断标志|
|\[1\]|CH1_FIF|通道1完成中断标志|
|\[0\]|CH0_FIF|通道0完成中断标志|

### DMA通道配置寄存器

#### DMA_CCRx ( x = 0,1,2,3)

地址分别是：0x4001_3000，0x4001_3010，0x4001_3020，0x4001_3030

复位值：0x0

表7-5 DMA通道配置寄存器DMA_CCRx

|||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
|SW_TRIG|REQ_EN|||MBTW||PBTW||MINC|PINC|CIRC|DIR||TEIE|TCIE|EN|
|RW|RW|||RW||RW||RW|RW|RW|RW||RW|RW|RW|
|0|0|||0||0||0|0|0|0||0|0|0|

||||
|---|---|---|
|位置|位名称|说明|
|\[31:16\]||未使用|
|\[15\]|SW_TRIG|软件触发，高有效\*2|
|\[14:12\]|REQ_EN|通道x三个硬件DMA请求使能\*1，高有效|
|\[11:10\]|MBTW|内存访问位宽，0:byte, 1:half-word, 2:word, 3:保留|
|\[9:8\]|PBTW|外设访问位宽，0:byte, 1:half-word, 2:word, 3:保留|
|\[7\]|MINC|内存地址第二轮是否在第一轮地址的基础上递增（轮内一定递增），高有效|
|\[6\]|PINC|指示外设地址每轮内是否递增（外设地址第二轮一定重复第一轮地址），高有效|
|\[5\]|CIRC|循环模式，高有效|
|\[4\]|DIR|传输方向，0:外设至内存，1:内存至外设|
|\[3\]||保留|
|\[2\]|TEIE|错误中断使能，高有效|
|\[1\]|TCIE|传输完成中断使能，高有效|
|\[0\]|EN|通道x使能，高有效，在通道操作全部完成后由DMA清除此位|

\*1以通道0为例，DMA_CCR0.REQ_EN\[2:0\]分别为Timer1、Timer0、ADC0的DMA请求使能。且DMA的通道中配置的内存、外设地址应与使能的外设中断请求相对应，这一点需要由应用软件保证。其中软件请求始终处于使能状态，即软件写入DMA_CCRx.SW_TRIG位即开始一次DMA传输。来自外设的硬件请求进入DMA后通过或逻辑形成一个请求信号，每一个DMA通道同时只应使能一个硬件DMA请求。\*2
软件触发标志DMA_CCRx.SW_TRIG写入1后需要软件清0。

表7-6
DMA通道请求信号

||||
|---|---|---|
|DMA通道|设备请求信号编号|外设|
|Channel 0|0|ADC0|
||1|Timer0|
||2|Timer1|
|Channel 1|0|SPI_RX|
||1|MCPWM|
||2|Timer2|
|Channel 2|0|UART0|
||1|SPI_TX|
||2|Timer3|
|Channel 3|0|UART1|
||1|CAN|
||2|I2C|

#### DMA_CTMSx ( x = 0,1,2,3)

地址分别是：0x4001_3004，0x4001_3014，0x4001_3024，0x4001_3034

复位值：0x0

表7-7
DMA传输次数寄存器DMA_CTMSx

|||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|31|30|29|28|27|26|25|24||23||22|21|20|19|18|17|16|
|||||||||||ROUND||||||||
|||||||||||RW||||||||
|||||||||||0||||||||
|15|14|13|12|11|10|9|8||7||6|5|4|3|2|1|0|
|||||||||TIMES||||||||||
|||||||||RW||||||||||
|||||||||0||||||||||

||||
|---|---|---|
|位置|位名称|说明|
|\[31:24\]||未使用|
|\[23:16\]|ROUND|DMA通道x采样轮数|
|\[15:9\]||未使用|
|\[8:0\]|TIMES|DMA通道x每轮数据搬运次数，0 ~ 512。此寄存器在该通道使能后变为只读。|

DMA_CTMSx 寄存器只有在通道禁用，即DMA_CCRx.EN=0之后才可以写入数据。

以外设数据宽度为16，内存数据宽度为32，即CTMS.TIMES=16，CTMS.ROUND=2为例，DMA每轮需要读取外设数据16bit×16=32byte，写入内存数据32bit×16=64byte。一共需要搬运两轮，即读取外设64byte，输入内存128byte；

即使仅仅搬运一轮，也需要设置CTMS.ROUND =1，而不能让其为0。

当设置DMA_CCRx.CIRC=1（即循环模式）时，CTMS.ROUND不再起作用，相当于无限轮；其他情况需要相应设置CTMS.ROUND，如CTMS.ROUND=1，用于搬运一轮数据。

当DMA_CTRL=1且DMA_CCRx.EN=0时，重新填写CTMSx值，可以将DMA内部已搬运的轮数次数计数器清零。

通常在开启DMA之前需要将触发DMA启动的外设接收中断标志位清零，防止之前留下的中断标志位成为DMA触发源造成一次错误触发。以UART为例，通常DMA被配置为多轮搬运，每轮搬运一次，每次搬运一个字节。如果UART接收FIFO不空，且UART_IF\[1\]未清零，则使能DMA通道后立即发生一次DMA搬运，但此时的DMA搬运的数据是UART之前遗留的数据，并非实际需要搬运的数据，且此时DMA内部的轮次增1，可能会导致接收的UART数据帧发生错位。出现这种情况，可以通过重写DMA_CTMS来讲DMA内部的轮次计数重置。

而在使用DMA通过UART发送数据时，通常使用的是UART
TX_FIFO空标志作为DMA请求，外设上电后发送FIFO空即有效，无须软件清除这一标志。否则无法向DMA产生第一次的发送请求。

【图片已删除】为控制知识库体积，本文档不携带图片，相关图示请查阅凌鸥创芯官网发布的正式手册。

地址分别是：0x4001_3008，0x4001_3018，0x4001_3028，0x4001_3038

复位值：0x0

表7-8
DMA外设地址寄存器DMA\_ CPARx

|||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
||||||||||||||||PERI_ADDR|
||||||||||||||||RW|
||||||||||||||||0|
|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
|PERI_ADDR||||||||||||||||
|RW||||||||||||||||
|0||||||||||||||||

||||
|---|---|---|
|位置|位名称|说明|
|\[31:17\]||未使用|
|\[16:0\]|PERI_ADDR|DMA通道x外设地址|

当DMA_CCRx.PBTW=2’b01时，即配置为以16bit为单位搬运外设数据。CPARx.PERI_ADDR\[0\]值无效，外设地址会以2为单位递增。

当DMA_CCRx.PBTW=2’b10时，即配置为以32bit为单位搬运外设数据。CPARx.PERI_ADDR\[1:0\]值无效，外设地址会以4为单位递增。

**注意：**DMA_CPARx
寄存器只有在通道禁用，即DMA_CCRx.EN=0之后才可以写入数据！！！

由于只进行内存与外设间的数据搬运，因此DMA_CPAR只存储外设地址的低17位，高15位恒为0x2000，高20位可能为0x40000(对应SYS寄存器)或0x4001\*(对应外设寄存器)。

#### DMA_CMARx ( x = 0,1,2,3)

地址分别是：0x4001_300C，0x4001_301C，0x4001_302C，0x4001_303C

复位值：0x0

表7-9
DMA内存地址寄存器DMA_CMARx

|||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
||||MEM_ADDR|||||||||||||
||||RW|||||||||||||
||||0|||||||||||||

||||
|---|---|---|
|位置|位名称|说明|
|\[31:13\]||未使用|
|\[12:0\]|MEM_ADDR|DMA通道x内存地址|

当DMA_CCRx.MBTW=2’b01时，即配置为以16bit为单位搬运内存数据。CMARx.MEM_ADDR\[0\]值无效，内存地址会以2为单位递增。

当DMA_CCRx.MBTW=2’b10时，即配置为以32bit为单位搬运内存数据。CMARx.MEM_ADDR\[1:0\]值无效，内存地址会以4为单位递增。

**注意：**DMA_CMARx
寄存器只有在通道禁用，即DMA_CCRx.EN=0之后才可以写入数据！！！

由于只进行内存与外设间的数据搬运，因此DMA_CMAR只存储地址的低13位，对应SRAM
8kB地址空间。高19位恒为0x10000。

