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.
你好:
我用的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位)
以上是我的猜测,可能不正确,供参考。我也在调这一部分