安全性相关
当DMAC从复位状态退出时,对于:
-
DMA管理线程.DMA Status寄存器的DNS bit提供了DMA管理线程的安全状态。
-
irq[x]信号。Configuration寄存器的INS bit提供了这些信号的安全状态。
-
外设请求接口。Configuration寄存器的PNS bit提供了这些接口的安全状态。
另外,每个DMA channel线程有一个动态的non-secure bit, CNS,当这个channel不处于Stopped状态时有效。
安全状态下的DMA管理线程
如果DNS bit为0,DMA管理线程工作在安全状态下,它只执行安全的取指。它处理:
DMAG0 | 它使用ns bit提供的安全设置,要设置DMA channel的安全状态,需要写这个channel的CNS bit。 |
DMAWFE | 在event发生之前它会停止线程执行。当event发生时,DMAC继续执行这个线程,不管对应INS bit的安全状态。 |
DMASEV | 它发起对应irq[x]的信号,不管对应INS bit的安全状态。 |
非安全状态下的DMA管理线程
如果DNS bit为1,DMA管理线程工作在非安全状态下,它只执行非安全的取指。它处理:
DMAG0 | 它使用ns bit提供的安全设置,要控制它是否启动一个DMA channel线程,要: ns = 0 DMAC不启动一个DMA channel,而是去 1. 执行一个NOP 2. 设置Fault Status DMA Manager寄存器 3. 设置Fault Type DMA Manager寄存器的dmago_err bit 4. 让DMA manager进入Faulting状态 ns = 1 DMAC启动一个非安全状态的DMA channel线程,并且编程CNS bit为非安全 |
DMAWFE | 在event发生前停止线程执行。当event发生时,DMAC只会在对应INS bit处于非安全状态下时继续执行线程。如果INS bit是安全状态,则DMAC会: 1. 执行一个NOP 2. 设置Fault Status DMA Manager寄存器 3. 设置Fault Type DMA Manager寄存器的mgr_evnt_err bit 4. 让DMA manager进入Faulting状态 |
DMASEV | 它只会针对对应INS bit为非安全状态下的irq[x]产生信号。如果INS bit为安全状态,DMAC会: 1. 执行一个NOP 2. 设置Fault Status DMA Manager寄存器 3. 设置Fault Type DMA Manager寄存器的mgr_evnt_err bit 4. 让DMA manager进入Faulting状态 |
安全状态下的DMA channel线程
如果CNS bit为0,DMA channel线程工作在安全状态下,它只执行安全的取指。它处理:
DMAWFE | 在event发生之前它会停止线程执行。当event发生时,DMAC继续执行这个线程,不管对应INS bit的安全状态。 |
DMASEV | 它发起对应irq[x]的信号,不管对应INS bit的安全状态。 |
DMAWFP | 在外设用发信号表明有DMA请求之前,它会停止线程执行。当这种情况发生时,DMAC继续执行线程,不管对应PNS bit的安全状态。 |
DMALDP,DMASTP | 它发送消息到外设用于告知数据传输完成,不管对应PNS bit的安全状态。 |
DMAFLUSHP | 它清除外设状态,并且发送一个消息到外设用于重发它的电平状态,,不管对应PNS bit的安全状态。 |
当DMA channel线程处于安全状态时,它能够让DMAC执行安全的和非安全的AXI访问。
非安全状态下的DMA channel线程
如果CNS bit为1,DMA channel线程工作在非安全状态下,它只执行非安全的取指。它处理:
DMAWFE | 在event发生之前它会停止线程执行。当event发生时,DMAC只会在对应INS bit处于非安全状态时才继续执行线程。如果INS bit是安全状态,DMAC会: 1. 执行一个NOP 2. 设置Fault Status DMA Channel寄存器里对应channel号的bit 3. 设置Fault Type DMA Channel寄存器的ch_evnt_err bit 4. 让DMA channel进入Faulting compleing状态 |
DMASEV | 它只会在对应INS bit处于非安全状态时才用信号通知对应的irq[x]。如果INS bit是安全状态,DMAC会: 1. 执行一个NOP 2. 设置Fault Status DMA Channel寄存器里对应channel号的bit 3. 设置Fault Type DMA Channel寄存器的ch_evnt_err bit 4. 让DMA channel进入Faulting compleing状态 |
DMAWFP | 在外设用发信号表明有DMA请求之前,它会停止线程执行。当这种情况发生时,DMAC只会在对应PNS bit处于非安全状态时才继续线程执行。如果INS bit是安全状态,DMAC会: 1. 执行一个NOP 2. 设置Fault Status DMA Channel寄存器里对应channel号的bit 3. 设置Fault Type DMA Channel寄存器的ch_periph_err bit 4. 让DMA channel进入Faulting compleing状态 |
DMALDP,DMASTP | 它发送消息到外设用于告知数据传输完成,只会在对应PNS bit处于非安全状态时进行。如果INS bit是安全状态,DMAC会: 1. 执行一个NOP 2. 设置Fault Status DMA Channel寄存器里对应channel号的bit 3. 设置Fault Type DMA Channel寄存器的ch_periph_err bit 4. 让DMA channel进入Faulting compleing状态 |
DMAFLUSHP | 它清除外设状态,并且发送一个消息到外设用于重发它的电平状态,只会在对应PNS bit处于非安全状态时进行。如果INS bit是安全状态,DMAC会: 1. 执行一个NOP 2. 设置Fault Status DMA Channel寄存器里对应channel号的bit 3. 设置Fault Type DMA Channel寄存器的ch_periph_err bit 4. 让DMA channel进入Faulting compleing状态 |
当一个DMA channel线程处于非安全态下,并且一个DMAMOV CCR指令尝试去执行一个安全的AXI 事务时,DMAC会:
1. 执行一个NOP
2. 设置Fault Status DMA Channel寄存器里对应channel号的bit
3. 设置Fault Type DMA Channel寄存器的ch_rdwr_err bit
4. 让DMA channel进入Faulting compleing状态
使用约束和限制
DMA channel仲裁
DMAC使用一个round-robin策略来服务active DMA channel。为了保证DMAC能持续地服务DMA管理器,它总是会优先于下一个要服务的DMA channel,先服务DMA管理器。
没有可能去修改DMAC的这种仲裁机制。
DMAC channel优先级
DMAC对于所有active的DMA channels使用同样的优先级响应。没有可能增加某个DMA channel使其优先级高于其它DMA channels。
指令缓存延迟
当cache miss发生时,服务请求的延迟主要取决于AXI bus的读延迟。DMAC所增加的延迟已经最小化了。
编程限制
固定非对齐burst
DMAC不支持固定非对齐burst。如果有下列条件则属于编程错误:
非对齐 read |
|
非对齐 write |
|
大小端交换大小限制
如果编程Channel Control寄存器的endian_swap_size字段,想要使DMA channel执行大小端转换,那么必须设置Source Address寄存器和Destination Address寄存器,让里面的地址对齐到endian_swap_size字段所配的大小值
还有,如果要编程Channel Control寄存器的src_inc字段来使用一个固定地址,那么必须要把src_burst_size的值配置为大于等于endian_swap_size字段所指定的值。类似的对于dst_inc字段来说如果要配置为使用固定地址,那么dst_burst_size也要大于等于endian_swap_size字段所指定的值。
在一个DMA周期中更新DMA channel controle寄存器
在一个DMA周期开始之前,Channel Control、Source Address和Destination Adress寄存器的值控制着DMAC在从源地址传输数据到目的地址时所执行的数据byte通道(data byte lane)。
如果在一个DMA周期中去更新Destination Address寄存器,或部分Channel Control寄存器的字段,那么DMAC会在MFIFO里创建一个新的表项。为了让DMAC传输MFIFO里之前的表项,它会等待用于那个DMA channel的active AXI事务完成。当对应AXI事务结束后,DMAC会在MFIFO里删除掉这个表项,表项所关联的任何剩余的数据不再被DMAC所访问。DMAC随后使用MFIFO里的新表项来存储那个DMA channel的AXI事务。
DMAC会在目的数据因为更新了以下内容变得非连续的时候,在MFIFO里创建一个新表项:
Destination Address寄存器
Channel Control寄存器的这些字段:src_inc,dst_inc,dst_burst_size(当dst_inc设置为0时),endian_swap_size
满MFIFO导致DMAC watchdog去abort一个DMA channel
当编程DMAC的时候,必须小心不要执行过多的load指令,这样可能会完全填满MFIFO。当MFIFO满了,并且当前或下一条更新MFIFO的指令是一个load的时候,DMAC就不能执行任何更多的DMA transfer了,并且内存的watchdog会abort掉这个DMA channel。
Single DMA channel and lock-up situation 下面是一个会导致DMAC lock-up的程序,其中read queue深度为2,MFIFO深度为8
下面是改写后的程序,不会导致DMAC锁住 这个程序load和store交错进行,这样DMAC会清掉MFIFO,因此不会锁住 通过循环的方式改写后为: |
Multiple DMA channels and lock-up situation 下面是一个在多个DMA channels的情况下发生lock-up的程序,DMAC的read queue深度为2,MFIFO深度为8。 当只有一个DMA channel处于active状态时,程序会: 1. DMAC取DMALD (1) 到read queue。它执行这条指令,MFIFO处于半满的状态。指令完成后DMAC从read queue中移除了DMALD (1) 。 2. DMAC取DMALD (2)到read queu。它执行这条指令,MFIFO完全填满。指令完成后DMAC从read queue中移除了DMALD (2)。 3. DMAC取DMAST到write queue。它执行这条指令,MFIFO被清空。 指令完成后DMAC从write queue中移除了 DMAST。 4. DMAC重复执行3次步骤1-3,知道loop退出,DMAC事务成功完成 当多个DMA channel处于active时,程序会: 1. DMAC取DMALD (1) 到read queue。它执行这条指令,MFIFO处于半满的状态。指令完成后DMAC从read queue中移除了DMALD (1) 。 2. DMAC取DMALD (2)到read queu。它执行这条指令,MFIFO完全填满。指令完成后DMAC从read queue中移除了DMALD (2)。 如果此时DMAC发生仲裁,另一个DMAC channel开始加载数据: 3. DMAC取DMALD(1)到read queue。它执行这条指令,但由于MFIFO满了,AXI read事务无法完成,指令会留在read queue。 4. DMAC取DMALD(2)到read queue。它执行这条指令,但由于MFIFO满了,AXI read事务无法完成,指令会留在read queue。 如果此时DMAC发生仲裁,另一个DMAC channel开始加载数据: 5. 由于read queue满了,DMAC无法取更多DMALD指令,MFIFO也是满的装填。DMAC会锁住,任何outstanding DMA 事务都会无法完成。当watchdog超时后,DMAC会abort掉线程。 为了避免DMAC的MFIFO满导致lock-up发生,必须确保在DMAC获取和执行DMAST指令前,DMALD指令的数量要小于等于 read queue深度 + MFIFO能够存储的完整的bursts的数量。
对于一个包含4个active DMA channel的DMAC来说,如果执行上面的程序代码,要使用这个等式来计算所需要的read queue深度,以此来避免lock-up发生,具体如下:
因此,Read queue 深度 >= (8 - 8/8 = 7) 下图展示了有4个active DMA channel的DMAC都执行上面lock-up的代码,但read queue深度为7,MFIFO深度为8的情况,此时不会发生lock-up (注意: 此图展示了最坏的情况,即DMAC在执行完每一条指令后发生仲裁,选择了一个不同的DMA channel; 调度器使用round-robin仲裁机制,但当一个channel没有准备好的时候能够bypass掉这个channel。图中展示了channel0在DMAC执行了最后一个DMALD(1)之后被bypass掉的情况 ) 从图中可以看到write queue深度必须>=4。 write queue深度可以使用下面的等式计算: (图中,当DMAC为DMA channel 0执行DMAST时,它写了目的数据但只能提供一半的数据。这是因为DMAC由于MFIFO满了后没有完成DMALD(2)的执行导致的) |