S3C6410移植DMA的一点经验总结[bootloader级]

时间:2022-02-24 19:51:28

0.DMA Controller, DMA 通道 的关系:
1):DMA Controller:
DMA_UNIT{}指有四个DMA Controller :
DMA0 DMA1 SDMA0 SDMA1

2)DMA_CH{}:
指8个DMA Channel: DMA_A .. DMA_H

4个DMA Controller,每个DMA Controller有8个DMA Transfer Channel组成,每个DMA Controller又提供16 个外设DMA Request Lines,能让16个外设进行DMA请求

系统中支持64个 DMA Sources,每个DMA Controller支持16个DMA Sources,让这16个DMA Sources进行DMA Request,但由于只有8个DMA Transfer Channel,所以只能同时有8个DMA Sources进行DMA Transfer

3)DMAC{}:
m_uBaseAddr: 保存哪个DMA 控制器的起始地址
m_uChAddr: 保存哪个DMA 通道地址的偏移地址:DMA_CH0...DMA_CH7
sCh->m_uBaseAddr+sCh->m_uChAddr+offset

4)DMA_CH0... ...DMA_CH7:
DMA Channel Reg 的起始地址,用于于DMACH_Setup()中对DMAC{}->m_uChAddr进行初始化,然后 于宏:DmaChOutp32(), DmaChInp32()中对通道Reg进行寻址用

5)DMASELECT_ID{}与DREQ_SRC{}的关系:
DMASELECT_eID{}里的各个宏:eSEL_AC_PCMOUT, eSEL_AC_PCMIN, eSEL_AC_MICIN均是DMA 选择子,即选择是GDMA还是SDMA,用于SYSC_SelectDMA()中对P158 SDMA_SEL进行DMA Selection

而DREQ_SRC{}则是用于:指定DMA Request的来源,用于后面的DMACH_Setup()中,设置 DMACCXCONTROL0[D|S],即用来选定AHB master select
后面在DMACH_SoftBurstReq(), DMACH_SoftBurstLastReq()中手工依据是哪个中断源,来手工为这个硬件来产生对应其的中断请求


有2类DMA来源:
eSrcReq==>eSrcAhb==>Destination AHB master select
eDstReq==>eDstAhb==>Source AHB master select
===>
===>
DMACCxCONTROL0[D|S]从而决定是AHB Master 1 AXI_SYSTEM 内存总线还是AHB Master 2 AXI_PERI 外设总线


这里的AHB Master选择的方法是:
当eDstReq为MEM, 或是DMA0_OND_RX, DMA1_EXTERNAL, DMA_MODEM[即是:DMA0_MODEM_RX,
DMA0_MODEM_TX, DMA1_MODEM_RX, DMA1_MODEM_TX]则选择AXI_SYSTEM ==AHB Master 1
其余商量选择AXI_PERI ==AHB Master 2

eSrcReq选择方法同上

注意:DMA_MODEM 是由这几类组成的。DMA0_MODEM_RX,
DMA0_MODEM_TX, DMA1_MODEM_RX, DMA1_MODEM_TX
当为这些时,还要额外设置:DMACCXCONFIGURATION

同时DMA_SRC{}的值与P11-4表对应,只是属于DMA1或SDMA1的,多出DMA0或SDMA0的0x20,
这个值x (如:DMA1_AC_PCMout 0x26)用 (x*0xf)得到0x06后就是要写入DMACCxConfiguration[DestPeripheral|SrcPeripheral]的值

所以总结之:
DMA_SRC{}用途:
0.入口参数: eSrcReq, eDstReq
为DREQ_SRC{}中的值,在ac97中,多为MEM, DMA1_AC_PCMout, DMA1_AC_PCMin, DMA1_AC_MICin

1.与DMA0_MODEM_RX, DMA0_MODEM_TX,DMA1_MODEM_RX,DMA1_MODEM_TX
相比较 ,看是否为Modem I/F Mem to Mem
对DMACCxConfigurationExp进行设置

2.与 MEM, DMA0_OND_TX, DMA1_EXTERNAL, DMA_MODEM[DMA0_MODEM_RX, DMA0_MODEM_TX,DMA1_MODEM_RX,DMA1_MODEM_TX]相比较
确定AHB_MASTER2 AXI_PERI 还是AHB_MASTER1 AXI_SYSTEM

对DMACCxControl0[D|S]进行Destination|Source AHB Master Select

3.
配置DMACCxConfiguration
配置好FlowCntrl: Memory to peripheral或是Peripheral to memory ...
[MEM, DMA1_NAND_TX, DMA0_OND_TX, DMA_MODEM(DMA0_MODEM_RX, DMA0_MODEM_TX,DMA1_MODEM_RX,DMA1_MODEM_TX) ]是这些地方均视为memory,剩下的为Peripheral


4.将eDstReq
((((eDstReq == MEM)||(eSrcReq == DMA_MODEM))? 0:(eDstReq&0xf))<<6)
当eDstReq为内存则忽略,否则当成外设,要设置DMACCxConfiguration[DestPeripheral]位

(((eSrcReq == MEM)||(eSrcReq == DMA_MODEM))? 0:(eSrcReq&0xf))<<1)
当(((eSrcReq 为内存则忽略,否则当成外设,要设置DMACCxConfiguration[SrcPeripheral]位

注意:为内存的条件少了两个: DMA1_NAND_TX, DMA0_OND_TX由另外两位管理了

(((eDstReq == DMA0_OND_RX)? 1 : 0)<<10) |
(((eSrcReq == DMA0_OND_TX)? 1 : 0)<<5) |


==================================
1.DMAC_InitCh():
依据DMA_UNIT是哪个DMA Controller来设置sCh->m_uBaseAddr指向哪个DMA Controller的基地址

DMAC Controller En


==================================
2.DMACH_Stop():
Refer 6410 P11-10
比较两类:
Disabling DMA Channel and losing data in the FIFO
Disabling DMA Channel without losing data in the FIFO

这里是Disable DMA Channel and losing data the FIFO

==================================
3.DMACH_IsTransferDone():
检查DMA Channel配置Reg的Channel 使能位来确认是否传输完成:
DMACCxConfiguration Reg:
当Channel Enable位处于disabled时,可能是last LLI is reached,也可能是a channel error is encountered.

Refer 6410 P11-10:有三种Disabling A DMA Channel的方法
其中第三种说明了当transfer completes时,Channel will be disabled automatically.
所以DMACH_IsTransferDone()是通过查询等transfer completes时,channel被自动disabled时来确认传输完成的。但尚不能确认是否在DMA Transfer时,遇到Channel Error


==================================
4.DMACH_Start():
4-1):DMA Controller与DMA 通道En/Dis的比较:
En DMA通道之前要先fully initialized,再En DMA Controller,最后才En DMA 通道

4-2):Dis DMA Controller之前要保证先Dis All DMA 通道

6410 P11-11:当DMA Channel En bit is set, DMA Channel is automatically Enabled.DMA 传输开始了。

==================================
5.DMACH_AddrSetup():
DMA_CH{}: 8 个DMA 通道 DMA_A..DMA_H
DMA_CH0...DMA_CH7: DMA 通道地址的偏移地址
sCh->m_uChAddr: == DMA_CH0...DMA_CH7

==================================
6.DMACH_Setup():
6-1):uLLIAddr: 设置要点:
1:必须DMA Channel没有En
2:4-word aligned (more efficient)
3:AHB Master 1
Refer P 11-21 P 1323
AHB Master 1: AXI_SYSTEM serves as a system bus memory bus
AHB Master 2: AXI_PERI implements a channel for SFR access peripheral bus

6-2):DBSize,SBSize: Burst Size
max 16B , 8B, 4B, 1B
于BURST_MODE{}中选

6-3):Dwidth,SWidth:
由uTrWidth,eDataSz来设置
DATA_SIZE{}来设置大小

6-4):D|S选择AHB Master 1/2:
由eDstAhb,eSrcAhb来设置之,进而由eSrcReq, eDstAhb来设置


6-5)DMACCxControl1 Reg:
Transfer Size 当按32bit 对齐 即要cnt/4
而于DMACCxControl0 Reg中的Dwidth, Swidth则用的为16bit Half Word
注意比较:
DMACCxControl0 [DWidth, SWidth]: 16bit transfer width
DMACCxControl1 []: Transfer Size 总共要传输的大小,以32bit来计算

==============================
PCMOutDMA的有关DMACH_Setup()的eSrcReq, eDstReq的设置:

1.入口参数:
eSrcReq==MEM (0x14) ====> eDstReq == DMA1_AC_PCMout (0x20)

代码流程:
2.
==>switch(eSrcReq) {...} ===> uReg = 0x0
==>switch(eDstReq) {...} ===> uReg = 0x0
==>DMA_CH_CONFIGEXP 寄存器写入0 即Disable Peripheral DMA Request
这个DMACCxCONFIGURATIONExp Reg 用于Peripheral DMA Request for Mem-to-mem access,而不用于Peri-to-mem


3.
eDstAhb==AHB_MASTER2 == 1 //Use Peripheral Bus
P11-21 : DMACCxCONTROL0[D] = 1 AXI_PERI for destination transfer
eSrcAhb同上,也是为AHB_MASTER2,
DMACCxCONTROL0[S] = 1 AXI_PERI for Source transfer

4.


====>注意DREQ_SRC{}作用:
而DREQ_SRC{}则是用于:指定DMA Request的来源,用于后面的DMACH_Setup()中,设置 DMACCXCONTROL0[D|S],即用来选定AHB master select

有2类DMA来源:
eSrcReq==>eSrcAhb==>Destination AHB master select
eDstReq==>eDstAhb==>Source AHB master select
===>
===>
DMACCxCONTROL0[D|S]从而决定是AHB Master 1 AXI_SYSTEM 内存总线还是AHB Master 2 AXI_PERI 外设总线


这里的AHB Master选择的方法是:
当eDstReq为MEM, 或是DMA0_OND_RX, DMA1_EXTERNAL, DMA_MODEM[即是:DMA0_MODEM_RX,
DMA0_MODEM_TX, DMA1_MODEM_RX, DMA1_MODEM_TX]则选择AXI_SYSTEM ==AHB Master 1
其余商量选择AXI_PERI ==AHB Master 2

eSrcReq选择方法同上

注意:DMA_MODEM 是由这几类组成的。DMA0_MODEM_RX,
DMA0_MODEM_TX, DMA1_MODEM_RX, DMA1_MODEM_TX
当为这些时,还要额外设置:DMACCXCONFIGURATION

==============================================
具体对PCMOutDMA()而言:
1.设置流控及传输类型
eSrcReq=MEM==>0<<12
eDstReq=DMA1_AC_PCMOut==>1<<11
从而表示为Memory to peripheral Refer to P11-20

2.(eDstReq&0x0f)<<6 ==>(DMA1_AC_PCMOut&0x0f)<<6==>(0x26&0xf)<<6==>0x6<<6
写入DMA Destination Request Peripheral


3.eSrcReq==MEM===>0<<1===>DMA Source Request==>Ignored