基于DWC2的USB驱动开发-发送相关的寄存器DMA寄存器详解 (qq.com)
如下寄存器DIEPxxx,对应IN端点,和发送数据相关,这一篇先介绍和DMA相关的两个寄存器,其他的后续再讲,
并且通过观察其寄存器的实际值的变化来加深理解。
了解这些值的含义以及何时如何变化,可以在有问题时帮助进行调试,知道当前出于何种状态。
以下实例是以Scatter/Gather DMA模式IN端点1进行操作
寄存器的地址偏移分别是
0x900+i*0x20
0x908+i*0x20
0x910+i*0x20
0x914+i*0x20
0x918+i*0x20
0x91C+i*0x20
寄存器偏移:0x914 + i*20
Scatter/Gather DMA模式时该寄存器的值即用户指定的描述符链表的地址
非Scatter/Gather DMA时该寄存器的值即用户指定的DMA待发送数据的地址。
必须DWORD即8字节对齐。
比如这里描述符链表使用了全局数组,用attribute指定对齐大小
attribute ((aligned(8))) static uint32_t s_dam[1024][2];
注意该寄存器在每次处理完描述符后会递增,用户可以通过该寄存器判断DMA是否进行了描述符的处理。
注意该寄存器需要CTL寄存器ENA置位后才能回读否则读到的是0.
我们以一个实例来看该寄存器值的变化,以下是关键代码,即准备一次DMA发送,前面描述符的准备过程不在这里贴出。
void ep_writedma(uint32_t dma, uint8_t epnum)
{
REG_DIEP_DMA(epnum) = dma;
REG_DIEP_CTL(epnum) |= (DEP_ENA_BIT | DEP_CLEAR_NAK);
}
以下是执行REG_DIEP_DMA(epnum) = dma;前,寄存器DIEPDMA1的值为0
传入的参数即描述符链表的地址是0x81008d8是8字节的对齐的
此时a0为0x81008d8,即我们的描述符链表的地址
a4为寄存器地址0x3000934,sw a0,0(a4) 即将0x81008d8写入寄存器0x3000934
注意在CTL寄存器使能端点之前是不能回读该寄存器的值的,如下为0
执行完sw语句再来看,此时DIEPDMA1还是0
在执行完使能,CTL寄存器的ENA置位后才能看到,如下此时看待DIEPDMA1的值变为了0x08100968,为什么不是写入的0x81008d8呢,也就时之前说的,ENA一置位,DMA就会去处理该描述符,0x08100968-0x81008d8=0x90=144 ,144/8=18个描述符(一个描述符2个WORD8字节)。
那么为什么该寄存器值递增了这么多呢
那是因为我们这里配置p_dam就是配置了18个描述符,如下18个DWORD,所以可以看到如下18个描述符一起处理完了,最后一个描述符标志了是最后一个。
寄存器偏移:0x91C + i*20
该寄存器只有Scatter/Gather DMA模式有效,非Scatter/Gather DMA模式,DIEPDMAi就是用户缓冲区的地址,也就是Scatter/Gather DMA模式的本寄存器。
用于指示当前正在处理的用户缓冲区的地址,DMA处理完指定缓冲区后就会更新。
所以从该寄存器可以看到是否处理了用户的缓冲区数据。
同样是CTL的ENA置位后,处理完描述符后更新,从以下可以看出最后一个描述的用户数据缓冲区地址为0x8704400长度为0x3C1,所以处理完后DIEPDMAB1更新为了0x87047C1
这里重点讲解了DMA相关的两个寄存器,主要是他们可以协助分析数据发送,比如有时候数据没有发出,可以从这里看出是否处理了描述符,是否处理了用户数据,来协助判断当前状态。
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !