AM3517缓存与MMU的调试
产品要求高速和高精度,每秒钟数据采样与处理在两千次以上,初步做两种方案,一种是在Linux操作系统下,稳定性高,升级方便,但操作系统对主控芯片的开销会增大,担心不能满足要求;第二种:是前后台模式。
选了AM3505这款芯片,主频600M,理论推算可以满足要求,因为暂时没有界面处理,所以选了一个不带图形加速器的,但在样片申请时AM3505暂时没有,就给了AM3517,很感谢TI的样片申请业务。
系统:主控芯片AM3517,内存:美光DDR2 MT47H64M16HR-25,Flash:三星K9K8G08U0A,电源芯片:tps65910,网卡:IP101A,另外预留了HDMI和CAN接口,芯片型号:TFP410PAP和ISO1050等。
应用开始:
第一步,焼写启动代码,从ti技术支持得到的开发包,TI的启动代码包含了两部分一个是X-loader TI自己做到,另一个是linux通用引导U-boot。用ti的flash tool烧写工具,用之前需要根据自己的硬件类型做一些配置,如NandFlash是几位的,最大容量,块大小,页大小等,对相应的只修改一下。其他还有一些配置,由于个人没有用过就不再多说,有问题时建议多看Help文件,Ti论坛也有很多相关资料。
接下来是将x-loader和U-boot合并到一起。X-loader存在的原因可能是,U-boot内容过多,芯片内部Ram有限(64K),所以就做了一级缓冲,先运行x-loader对硬件环境一个简单的初始化,然后将u-boot拷贝到内存中,再将控制权交给U-boot。
对编译后的X-loader做了一下分析,发现x-loader头部是一个固定的内容,就是X-loader的大小,合并方法是将U-boot的对硬件必要的初始化和添加搬运自己代码到内存中的这段程序压缩到64K以内,等Uboot把自己搬运完了就跳到内存中从新运行U-boot,在U-boot中要判断自己是在内存中还是在Flash中,这个可以通过地址来判断,在Flash中就运行拷贝自己的程序,在内存中就跳过。这个很简单,都是U-boot内部函数的一些拷贝。
第二步:网卡移植,IP101A非常好用,我们用的是RMII精简接口,需要给AM3517的网络部分提供一个50M的时钟,IP101A内部可以产生这个时钟,其他都用默认配置即可。在U-boot里添加以下IP101A的PHY地址做个判断就可以。
第三步:一键更新,使用u-boot通过网络自己更新自己、内核、文件系统会很方便,而且速度很快,只是指令多了点。这里就是把u-boot的tftp下载命令,擦出nand flash命令和写命令综合到一起,其他也没什么,值得说的就是,烧写u-boot时用的是硬件1bit Ecc校验,这个是am3517内部定义的。烧写内核时用的是硬件Ecc 4 bit校验方式。
第四步:在U-boot里验证开启指令缓存,数据缓存后与开启前的速度对比。
在A8(整个ARM体系里具有MMU的内核)里指令缓存是可以单独单开的,但数据缓存必须与MMU同时打开,初始化步骤是先建立MMU页表,可以使用虚拟地址,也可以不用虚拟地址,但页表必须要建立,也就是必须要做映射(因为打开了MMU),在建立页表的时候可以根据自己的需要对相应的内存地址做允许缓存和不允许被缓存,页表是存储在内存空间里的一个,建立页表是一个比较复杂的过程,
以下是建立以及页表的程序:
static inline unsigned int initializeMMU()
{
unsigned int adat,rr2,rr3,i;
rr2 = 0xdfe;
adat = get_cr() & 0xfffffffe; //Read Control Register
asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR" : : "r" (adat) : "cc"); //disable MMU
asm volatile("mcr p15, 0, %0, c7, c5, 0 @ set CR" : : "r" (0) : "cc"); //invalidate caches jay
asm volatile("mcr p15, 0, %0, c7, c5, 6 @ set CR" : : "r" (0) : "cc"); //clear the whole jump target of cache
asm volatile("mcr p15, 0, %0, c7, c5, 7 @ set CR" : : "r" (0) : "cc"); //invalidate VA from branch predictor array
asm("MRC p15, 0, %0, c1, c0, 1 @ get CR" : "=r" (adat) : : "cc"); //Read Auxiliary Control Register
adat &= 0x3d;
asm volatile("mcr p15, 0, %0, c1, c0, 1 @ set CR" : : "r" (adat) : "cc"); //disable L2
asm volatile("mcr p15, 0, %0, c8, c7, 0 @ set CR" : : "r" (0) : "cc"); //invalidate TLBs //Invalidate Inst-TLB and Data-TLB
asm volatile("mcr p15, 0, %0, c2, c0, 2 @ set CR" : : "r" (0) : "cc"); //selected table reg 0 //Write Translation Table Base Control Register
asm volatile("mcr p15, 0, %0, c2, c0, 0 @ set CR" : : "r" (0x80000000) : "cc"); //set start of translation table //Write Translation Table Base Register
for( i=0;i<0x400;i++ ) //initialize the nand space page table (0 - 0x3fffffff)
{
rr3 = (rr2 | ( i<<20 ));
(*(volatile unsigned int*)(0x80000000+(i<<2))) = rr3;
}
for( i=0x400;i<0x800;i++ ) //initialize the on-chip Memory space page table (0x40000000 - 0x7fffffff)
{
rr3 = (rr2 | ( i<<20 )) & 0xfffffff2;
(*(volatile unsigned int*)(0x80000000+(i<<2))) = rr3;
}
rr3 = (rr2 | ( 0x800<<20 ));
(*(volatile unsigned int*)(0x80000000+(0x800<<2))) = rr3 & 0xfffff01f; //initialize the store page table space in the sdram (0x80000000 - 0x80100000)
for( i=0x801;i<0x900;i++ ) //initialize the SDRAM main address space(SMS) page table (0x80000000 - 0xbfffffff)
{
rr3 = rr2 | ( i<<20 );
(*(volatile unsigned int*)(0x80000000+(i<<2))) = rr3;
}
asm volatile("mcr p15, 0, %0, c3, c0, 0 @ set CR" : : "r" (0xfffffffd) : "cc"); //Setup domain control register Enable all domains to client mode //Write Domain Access Control Register
asm("MRC p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (adat) : : "cc"); //read CP15 register 1 into adat
//adat &= ~((1<<12)|(1<<2)); //disable icache and dcache
adat |= 1 | (1<<12) | (1<<2);
asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR" : : "r" (adat) : "cc");
|