This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

关于CORTEX-M4的UDMA的传输问题

你好:

      我用的IC是LM4F231H5QR,系统想用UDAM进行UART的接收和发送,软件如下:

       1.   UART的初始化:

void UartInit(void)
{
 ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
 ROM_uDMAEnable();
 ROM_uDMAControlBaseSet(ucControlTable);
 uDMAChannelAssign(UDMA_CH17_UART3TX);
 uDMAChannelAssign(UDMA_CH16_UART3RX);
 /*** config the UART *************/
    ROM_UARTConfigSetExpClk(UART3_BASE, ROM_SysCtlClockGet(), 115200,
                            UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                            UART_CONFIG_PAR_NONE);
    ROM_UARTFIFOLevelSet(UART3_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    ROM_UARTEnable(UART3_BASE);
    ROM_UARTDMAEnable(UART3_BASE, UART_DMA_RX | UART_DMA_TX);
    /*********************************/
    /**   RX  ***/
    ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC2,
                                    UDMA_ATTR_USEBURST |
                                    UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);
    uDMAChannelControlSet(UDMA_CHANNEL_ADC2 | UDMA_PRI_SELECT,
                              UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
                              UDMA_ARB_4);
    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC2 | UDMA_PRI_SELECT,
                               UDMA_MODE_BASIC,  (void *)(UART3_BASE + UART_O_DR),
                               rx_buffer,
                               sizeof(rx_buffer));
//    ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC2, UDMA_ATTR_USEBURST);
    ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC2);
    /******* TX  ********/
    ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC3,
                                    UDMA_ATTR_USEBURST |
                                    UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);
    ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT,
                              UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |
                              UDMA_ARB_4);

    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT,
           UDMA_MODE_BASIC,
           tx_buffer,(void *)(UART3_BASE + UART_O_DR),
                                sizeof(tx_buffer));
//    ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC3, UDMA_ATTR_USEBURST);

    /***** when we want to send , then enable it *****/
 //   ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC3);
 /**************************************************************************************/

    //
    // Enable the UART peripheral interrupts.  Note that no UART interrupts
    // were enabled, but the uDMA controller will cause an interrupt on the
    // UART interrupt signal when a uDMA transfer is complete.
    //
    ROM_IntEnable(INT_UART3);
}

对于上面的程序,如果我使能了卒发请求(图中红色背景),在接受256个字节的时候,后4个字节一直接收不到,后来我用:

data = ROM_UARTCharGet(UART3_BASE); 查看FIFO内的内容, 发现

后四个字节还在UART的FIFO里面,没有移入rx_buffer,如果我取消掉这个语句(图中红色背景),那么256个可以完整接收,而对于发送,似乎是否使能卒发请求(绿色背景部分),

都没什么影响。

我的问题是:

1.     对于我上面说到的情况,应如何解释?

2.     对于卒发请求,不是很理解,规格书看了也不大清楚,是否可以帮忙解释透彻一些?谢谢。

3.     在UDAM中,以UART为例,设定的FIFO的深度,同仲裁字节,他们的设定有没有什么根据?是否两个都要设成一样,如果不一样,情况如何?

        A.     仲裁字节比FIFO多。

        B.     仲裁字节比FIFO少。

4.     既然设定了仲裁的数目,那么系统如何实现可以一次传多个字节?以前认为每发生一次仲裁,系统就会中断一次,后来发现,我发送256个字节,

       等发送完毕后,系统才中断一次。

5.    由于UART每次接收的字节数不一样,对于UDMA,能不能做到:在开始接收第一个数据开始,等一段时间,如果没有数据进来,系统产生中断(不用等到你

       设定的字节数填充完了,才产生中断)。

 

  • 楼主您好,关于您的问题:

    1 - 4.

    Arbitration Size决定的是uMDA模块连续占用总线的时间片的最大大小(但会随时被CPU打断),主要用于多个DMA channel同时工作时的仲裁。所以这个大小和FIFO并无什么关系,和中断的时间也无关。

    由于uDMA工作机制是透明的,手册里确实没有其工作机制的详细说明,楼主出现所述的现象比较难判断原因,建议楼主不用Arbitration。

    5. 

    这样不行。建议用Timer实现

  • 谢谢。

    我的程序里,没有其它程序运行,只是写了这个,所以问题也就在这些设置上。

    对于“卒发”不太了解,您能不能帮忙扫下盲。

    还有,为什么会出现上面我提到的问题,您能不能帮我分析下?

    如何用timer实现?

    是不是利用一个定时器,定期扫描UDMA内的未接收数,如果两次一样的话,说明接收完成,可以停止接收,处理数据?(这样是否可行?),还是有更好的办法?

    这里先谢谢了

  • 楼主您好,

    1. 没听过“卒发”这个概念,但看楼主的问题,应该指的是突然大量数据(数据块)的传输

    2. DMA工作机制是未知的,很难分析原因

    3. 您的方法可行,不过建议数据包中包含数据长度信息,这样可以分析数据是否已经收全

  • 楼主,你所说的“卒发”是不是Burst模式?如果是:

    1. DMA的请求信号有两种:single和burst。single是一次传一个,即FIFO有数据,哪怕只是一个也会产生请求;burst是一次传递一组数据,具体大小依据FIFO中的Level定义,比如FIFO是16级深度,FIFOlevel选择1/4,则当FIFO中有4个数据时会产生DMA请求(这一点不知对不对,和你程序对应不上)。

    2. 如果你最后使能了Burst模式(红色Code),含义是仅仅使能Burst请求,所以一般不使能,这样Single和Burst两种请求都会,这样UART每来一个数据,都会请求DMA将其搬走,如果DMA搬的慢了(相对于UART通信很快),则当FIFO达到1/4时,会产生一次Burst请求,DMA会一次将其都搬走(手册上说这样效率比较高,估计是由于1/4刚好是32位)

    以上是我的猜测,可能不正确,供参考。我也在调这一部分