PowerPC从NorFlash启动的过程
写在最前面: ??? 本文介绍的是PowerPC从NorFlash启动的过程及NorFLASH在启动过程中地址空间的设置。基于的硬件是飞思卡尔的PowerPC -> P2020。软件是u-boot+Linux。ARM平台原理也都是相通的,大家可以借鉴。这篇文章完全看懂的话,你首先要了解一些:处理器的架构,启动方式和流程。我假设读者已经懂了。 我的NorFlash硬件连接的方式??? 备注:我用FPGA做了地址锁存。同时使得FPGA变成了PowerPC的LocalBus外设。 ??? PPC从NorFlash启动的秘密??? 在PPC从NorFlash启动时,很多人不太明白各种相关的地址空间的映射。至少我做PPC多年了,以前一直就是这样理解的:PPC启动时,会访问一个特定的地址,从这个地址上读取第一条指令,然后继续执行。这个理解是没错的,但是不够透彻。今天我在这里写个明白。 ??? 首先PPC在启动的过程中,会访问一个特定的地址,这个地址是被内核决定了的。比如采用e500内核架构的PowerPC,他的复位地址是在0xfffffffc上,也就是说当系统产生复位之后,PowerPC会去这个地址上取到第一条指令。“BOOK E-兼容的内核,并没有沿用和AIM版本的PowerPC架构相同的复位向量。复位的地址更换为0xFFFFFFFC”*这句话翻译自E500CORERM手册(你可以在飞思卡尔的官网上下载到 E500CORERM Rev. 1,4/2005)。 ??? 此时,如果你把PowerPC配置为从NorFlash启动的话,“在系统未初始化之前,boot片选的操作,允许地址对于一个boot ROM解析,LCS0_N是boot片选的输出。他的操作和系统复位之后的其他片选型号的操作是不同的。当系统复位之后,LCS0_N允许访问每一种LocalBUS的入口,直到BR0和OR0被配置。”(翻译自P2020的使用手册12.4.2.5)。 ??? 这两段话结合起来,我们就应该明白了,为何上电没有配置,PPC就可以访问LocalBUS总线。上电之后。LCS0_N的操作寄存器被硬件配置,并且可以通过LocalBUS,透出e500内核的访问空间。 ??? NorFlash初始化在u-boot中的相关内容??? (1) 第一段相关的代码———地址空间映射 ???????首先我们快进一下(假使你对PPC的启动流程很熟悉)现在已经初始化了PPC的寄存器空间也就是说PPC的寄存器空间已经可以使用了(这些东西一般在u-boot对应的CPU的start.S中的cpu_init_early_f),PPC也在内核的地址空间上也划分出了可以访问FLASH物理空间的TLB(这部分内容一般在tlb.c中,init_tlbs(),使用tlb_table[i]结构体完成一系列内核entry的配置)。在这个时候,你的NorFlash应该已经可以在PPC的默认状态下可读了。???? ???????详细的初始化流程: ???????首先在boot/cup/mpc85xx/start.S中,运行到了 bl?? cpu_init_early_f??? 跳转到boot/cup/mpc85xx/cpu_init_early.ccpu_init_early_f()函数。在这个函数中设置了PPC的CCSR寄存器的访问空间(此时PPC的大多数寄存器都可以访问了)。然后依旧在这个函数(cpu_init_early_f())中跳转到了init_tlbs();在这个函数中初始化了PPC的大部分内核的访问空间(TLB)。此时e500内核可以访问NorFlash所在的地址空间了,但是他在道理上依旧应该是无法访问Norflash(但是我们现在就是在NorFlash中启动啊,怎么能说是不能访问呢?这个问题请查阅本文第二小节,PPC从NorFlash启动的秘密)。 ???????然后程序在boot/cup/mpc85xx/start.S中继续执行,执行到了bl??? cpu_init_f 跳转到了boot/cup/mpc85xx/cpu_init.c,在这个函数中,程序配置了BR0,OR0寄存器。从这个时候开始,NorFlash已经可以按照配置的内容,正常使用了。附1小节,列出两段代码,来帮助理解内核访问的地址空间和LocalBus的配置。 ??? (2)第二段相关的代码———Flash的初始化 ???????现在我们的程序应该已经跑到了u-boot的board_init_r()函数中。然后执行到了flash_init()(这个函数的返回值是flash的大小)。在这个函数中,得到了Flash的大小。 ??? (3)第三段相关的代码———Flash的读写擦操作 ???????这部分内容就是NorFlash的驱动程序。能看懂这篇文章的想必都熟的不能再熟了,就不再赘述了。 ? 附1 内核访问的地址空间与Localbus的配置 ??? (1)内核地址空间的配置通过这个函数。 void init_tlbs(void) { inti; for(i = 0; i < num_tlb_entries; i++) { write_tlb(tlb_table[i].mas0,tlb_table[i].mas1,tlb_table[i].mas2,tlb_table[i].mas3,tlb_table[i].mas7); } return; } 其中,tlb_table的结构体如下 struct fsl_e_tlb_entry tlb_table[] = { /*这里我只是摘取的一部分代码,这里删除了很多代码*/ /*W**G* - Flash/promjet,localbus */ /*This will be changed to *I*G* after relocation to RAM. */ SET_TLB_ENTRY(1,CONFIG_SYS_FLASH_BASE,CONFIG_SYS_FLASH_BASE_PHYS,MAS3_SX|MAS3_SR,MAS2_W|MAS2_G,2,BOOKE_PAGESZ_256M,1),/*这里我只是摘取的一部分代码,这里删除了很多代码*/ }; 通过 SET_TLB_ENTRY(1, 可以看到u-boot首先配置了一块256M的地址空间,起始位置在CONFIG_SYS_FLASH_BASE,给内核使用。 ???????? (2)LocalBus的配置 if (! memctl->br1 & 1) { #if defined(CONFIG_SYS_BR0_PRELIM)&& defined(CONFIG_SYS_OR0_PRELIM) memctl->br0= CONFIG_SYS_BR0_PRELIM; memctl->or0= CONFIG_SYS_OR0_PRELIM; #endif #if defined(CONFIG_SYS_BR1_PRELIM) &&defined(CONFIG_SYS_OR1_PRELIM) memctl->or1= CONFIG_SYS_OR1_PRELIM; memctl->br1= CONFIG_SYS_BR1_PRELIM; #endif } ???????? 用这一段代码,CPU又配置了LocalBUS的CS0的寄存器,配置了CS0的片选地址空间及其他信息。自此,NorFlash所有相关的初始化结束。 ? 文章更新记录: V1.00???????????????? 吉超???????? 起草了这个文档。shmilyduo@icloud.com (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |