UART+FIFO+DMA for 44b0

来源:互联网 发布:豆瓣约 知乎 编辑:程序博客网 时间:2024/05/16 00:57

    在搞启用fifo和BDMA的UART时,确实走了不少弯路。昨天一下午的时间我都在用轮询法检测DMA的运行情况,加上BDMA配置上犯了这样那样的错误,昨天一直都在报RUNOVER。总算在昨晚熄灯的最后时刻,停止了溢出,可接包总是丢失。对于这种最稳定的模式,这种现象是不该出现的。

    考虑来考虑去,原来是我犯了低级错误。轮询怎么能用在DMA模式呢?而且我保接包数量放在普通函数中计算,通过轮询BDCON的SET位。结果可想而知。本身BDMA的数据传输就不经过CPU,而执行计数函数前又要执行其他函数或中断函数,漏查是在所难免的。好在今天觉悟了。换成中断。

void Uart_BDMAInit(void)

 BDMApt=(char*)RAM_ADDRESS;
 //*BDMApt=0;
 //pool=BDMApt;
 //rBDICNT0=0x0<<20;
 //BDMApt=SaveBDMA;
 //Savept=(Savept)|(0x0c200000)|(0x9<<27)|(0x2<<29);
 rBDCON0=0x0;
 rBDISRC0=0x31d00024;
 rBDIDES0=(0xc200000)|(0x9<<28);
 rBDICNT0=(0x8<<28)|(0xe<<20)|(0x4<<24)|(0x10);
 
 rBDICNT0|=1<<20;
 rBDCON0|=0x0;
}

///////////////////////////////////////////////////////////////////////////////////////

void __irq Uart_BDMA(void)
{
 rI_ISPC=BIT_BDMA0;
 //printf("UART ERROR/n");
 //Uart_BackSend();
 e++;
 
}

注释我就不加了,相信都能看得懂。

结果,很OK。做了多次测试丢包数量0。另外,我的发送启用了FIFO但用的是轮询模式(前面我提过,这种模式很山寨的,慢,而且不稳,不过我这是低速场合,还好没有写溢出(丢包)的问题)。对于FIFO触发这里再多说几句,发送BDMA设的是下线,即发送过程中要保证发送FIFO不空,而接受FIFO设的上限触发,即接受过程要保证不出现RUNOVER。发送BDMA无需自动重装。因为,对于发送我们往往知道数据包大小,若不考虑总线占用问题可一次搞定所有数据。而接收时BDMA同样前提是,前提你申请的缓冲区足够大(同样是在不考虑总线占用的情况)。若为配置自动重装且BDMA计数器设为16时,每次DMA操作后移动16字节数据到设定地缓冲区(这往往在BDMA中断中完成,另外这里所说的缓冲区需要另开辟,而非BDMA目的地址,这样便有了释放总线的时间,总线不会被一直在占用)。若发非连续数据可不设自动重装,因为接收FIFO(或接收缓冲区)不触发DMA,这时是不占用总线的。连续数据需要考虑总线的占用问题(这是可以设自动重装,并需另开辟缓存区)。

    如果一次发送数据不足以触发BDMA,我们就需要设一个接收超时中断,而发送则不需要设置,发送只要给数据就发出去了,不存在在FIFO中暂存的情况。超时中断函数中我们需要做以下几点,回写服务位,读接收FIFO中暂存的数据(一定要考虑这种不溢出的情况,否则就会丢包)。如读出后,后续数据满足触发条件。则后续数据直接通过BDMA存放在我们申请的缓存中。

void __irq Uart_TimeOut(void)
{
 char TimeOutData=0;
 rI_ISPC=BIT_UERR01;
 TimeOutData=rUFSTAT0&0x000f;
 for(;TimeOutData>0;TimeOutData--)
 {
  ot[TimeOutData]=rURXH0;
 }
}

这样就完成了UART+BDMA+FIFO模式下定的数据接收。

                                                                                                                      DIY