基于MPC8641HPCN上的UBoot源代码分析

本文深入探讨了U-Boot在MPC8641HPCN开发板上的启动过程,包括上电后的初始指令执行、关键函数分析及硬件资源初始化等步骤。

第一部分:U-Boot概述

Bootloader(引导加载程序)是操作系统运行前执行的第一段程序,其作用是初始化硬件设备,建立内存空间映射表,为最终调用系统内核建立适当的系统软硬件环境.嵌入式系统一般没有通用的Bootloader,不同的系统硬件组成结构对应不同的代码,因而,针对特定的硬件平台,需要对Bootloader进行移植.在嵌入式系统中,常见的引导加载程序有U-Boot,Red Boot和BLOB等.其中U—Boot功能最多,灵活性最强,能够支持PowerPC,ARM,MPIS,X86体系架构的上百种开发板,引导加载Linux,VXWorks,QNX等多种操作系统,有丰富的开发调试文档资料与强大的网络技术支持。我将以自己接触到的MPC8641HPCN开发版上的U-Boot为例,来讨论U-Boot的实现机制!

 

U-Boot是遵循GPL版权协议的自由软件,具有和Linux源文件相似的目录结构.在相关目录下分别存放不同的源码,这些源码是通过GCC和Makefile组织编译的,可以很方便地在不同的硬件平台上进行移植.顶层目录下的Makefile设置各类开发板的定义,递归地调用各级子目录下的Makefile,源码结构可查看顶层目录下的readme文件。

关于U-Boot的详细信息参考:http://www.denx.de/wiki/U-Boot

各个版本的U-Boot的下载网址:http://ftp.denx.de/pub/u-boot/

从2008年末开始,U-Boot的按照固定的时间间隔发布新的版本,大概是每隔3个月一个版本,版本名称采用YYYY.MM(即年.月)的格式。例如我讨论的U-Boot版本是u-boot-2010.09.tar.bz2

之所以选这个版本,没有别的意思,仅仅是喜欢而已。大家如果发现我的分析有什么问题,

请给我留言或者email:cwsun@mail.ustc.edu.cn。

第二部分 基于MPC8641HPCN开发板的Uboot编译

利用我建立的基于PowerPC的交叉编译器(

参考:http://blog.sina.com.cn/s/blog_70dd16910100y7vj.html)来编译基于MPC8641HPCN开发板上UBoot,由于u-boot-2010.09版本已经包含支持MPC8641HPCN的源码,这个编译过程非常简单,只要使用以下命令即可:

$tar xvf u-boot-2010.09.tar.bz2

$make CROSS_COMPILE=powerpc-tom-linux-gnu- MPC8641HPCN_config

$make CROSS_COMPILE=powerpc-tom-linux-gnu-

备注:下面的叙述我不加注释的话,默认的都是在u-boot-2010.09目录中。

编译完的效果如下:

基于MPC8641HPCN上的UBoot源代码分析 <wbr>一

然后把u-boot.bin烧写到基于MPC8641HPCN的模拟器上来加载我们编译的Linux-2.6.38-smp内核映象,示意图如下:
基于MPC8641HPCN上的UBoot源代码分析 <wbr>一
基于MPC8641HPCN上的UBoot源代码分析 <wbr>一
备注:在include/config/包含着U-Boot版本所支持的各个开发板的配置文件,这些配置文件定义了CPU的体系结构、外围设备的配置信息、内存映射、以及U-Boot的功能定制等等。它们都是一个供参考的范本,我们可以参考README文件获取更多这方面的信息。
由于我选择的这个U-Boot版本已经支持MPC8641HPCN开发板,所以在include/config/目录下存在MPC8641HPCN.h文件。这因为如此,我才可以不对U-Boot源码做任何修改就可以用上述的命令进行编译。
另外我的交叉编译器自己编译的,建立的过程在我的博文中已经相信的说明,这里就不在赘述。

第三部分 基于MPC8641d的U-Boot的源码分析

3.1 MPC8641d上电后从OxFFF00100物理地址处执行指令

当MPC8641d上电或者施加复位信号时,CPU通过读取硬复位配置信号,启动Local bus存储控制器CS0#(对应于Flash的片选信号)有效,选中Flash,CPU地址线上输出硬件复位中断向量对应的地址OxFFF00100,开始读第l条指令,从

board/freescale/mpc8641hpcn/ u-boot.lds链接脚本文件可以看到,这条指令对

应于arch/powerpc/cpu/mpc86xx/start.S中的_start: 标号处.下面我们将介绍uboot启动过程中的几个关键函数和文件:

关于u-boot.lds文件的分析可以参考:基于MPC8641d的U-Boot的GOT表分析和u-boot.lds解读

具体代码如下:

_start:

       li      r21, BOOTFLAG_COLD      // Normal Power-On: Boot from FLASH

          boot_cold                                                        <1>

boot_cold:

boot_warm:

       // NOTE: Only Cpu 0 will ever come here.  Other cores go to an

       // address specified by the BPTR

1:

       // Invalidate BATs

       bl     invalidate_bats                                                 <2>

       sync

       // Invalidate all of TLB before MMU turn on

       bl      clear_tlbs                                                     <3>

       sync

#ifdef CONFIG_SYS_L2

       // init the L2 cache

       lis    r3, L2_INIT@h

       ori   r3, r3, L2_INIT@l

       mtspr      l2cr, r3                                                   <4>

       // invalidate the L2 cache

       bl     l2cache_invalidate                                             <5>

       sync

#endif

       // Calculate absolute address in FLASH and jump there

       lis    r3, CONFIG_SYS_MONITOR_BASE_EARLY@h                            <6>

       ori   r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l

       addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET

       mtlr r3

       blr

in_flash:

       // let the C-code set up the rest                  

       // Be careful to keep code relocatable !        

       // perform low-level init

       // enable extended addressing

       bl     enable_ext_addr                                                <7>

       // setup the bats

       bl     early_bats                                                     <8>

       // Cache must be enabled here for stack-in-cache trick.

       // This means we need to enable the BATS.

       // Cache should be turned on after BATs, since by default

       // everything is write-through.

       // enable address translation

       mfmsr     r5

       ori   r5, r5, (MSR_IR | MSR_DR)                                       <9>

       lis    r3,addr_trans_enabled@h

       ori   r3, r3, addr_trans_enabled@l

       mtspr      SPRN_SRR0,r3

       mtspr      SPRN_SRR1,r5

       rfi

代码解释:

<1>: b    boot_cold      

U-Boot规定了两种启动方式:

第一种:系统上电启动U-Boot(我们称之为冷启动),把冷启动标签BOOTFLAG_COLD放入通用寄存器r21,CPU从boot_cold:标签处执行;

第二种:软件重启U-boot(我们称之为暖启动),把暖启动标签BOOTFLAG_WARM放入通用寄存器r21,CPU从_start_warm:标签处执行;

备注:BOOTFLAG_COLD和BOOTFLAG_WARM在include/configs/MPC8641HPCN.h文件中定义,代码如下:

#define BOOTFLAG_COLD         0x01       // Normal Power-On: Boot from FLASH

#define BOOTFLAG_WARM         0x02       // Software reboot

<2>:bl  invalidate_bats

执行invalidate_bats函数,该函数比较简单目的就是把E600内核的8组BAT寄存器IBATxU/DBATxL(x=0至7)的内容全部初始化为0,具体代码如下:

       .globl      invalidate_bats

invalidate_bats:

       li      r0, 0

       //invalidate BATs

       mtspr      IBAT0U, r0

       mtspr      IBAT1U, r0

       mtspr      IBAT2U, r0

       mtspr      IBAT3U, r0

       mtspr      IBAT4U, r0

       mtspr      IBAT5U, r0

       mtspr      IBAT6U, r0

       mtspr      IBAT7U, r0

 

       isync

       mtspr      DBAT0U, r0

       mtspr      DBAT1U, r0

       mtspr      DBAT2U, r0

       mtspr      DBAT3U, r0

       mtspr      DBAT4U, r0

       mtspr      DBAT5U, r0

       mtspr      DBAT6U, r0

       mtspr      DBAT7U, r0

       isync

       sync

       blr

<3>: bl      clear_tlbs

调用clean_tlbs清空tlb表,clear_tlbs的具体代码如下:

       .globl clear_tlbs

clear_tlbs:

       addis   r3, 0, 0x0000  <3,1>

       addis   r5, 0, 0x4     <3,2>

       isync

tlblp:                        <3,3>

       tlbie   r3

       sync

       addi    r3, r3, 0x1000

       cmp     0, 0, r3, r5

       blt tlblp

       blr

解释;

<3,1>:r3指向TLB表的首地址  0x0 0000

<3,2>:r5执行TLB表的末地址  0x4 0000

<3,3>:TLB表示256KB,其中每一个页表是4KB,所以<3,1>使用tlbie指令循环了64次,让TLB表中的64个页表均为无效。

备注:

tlbie r3:r3寄存器所指向的页表项如果在TLB快表中,就将这个页表项从TLB中移除(即使得TLB中这个页表项无效)。

有一个注意疑问:从上面的代码中我们可以看出TLB是256K包含64个页表,但是我们查看MPC8641d的芯片手册,E600包含ITLBDTLB,每个均为512K,包含256个页表。所以上面的初始化E600内核中ITLB和DTLB的前64个页表,并没有把TLB的所有内容均初始化。这是一个bug吗???!!!

<4> lis    r3, L2_INIT@h

    ori   r3, r3, L2_INIT@l

    mtspr     l2cr, r3                                  

解释:

l2cr寄存器是L2 Cache控制寄存器(L2 Cache Control Register),它的第0位控制着L2 Cache的开启和关闭。

L2_INITinclude/configs/MPC8641HPCN.h文件中定义为0,所以上述汇编指令的作用就是关闭L2 Cache

<5>:bl    l2cache_invalidate

解释:在L2 Cache已经关闭的情况下,调用l2cache_invalidate函数来清空L2 Cache中的内容,具体代码如下:

 // Invalidate L2 cache using L2I, assume L2 is enabled

_GLOBAL(l2cache_invalidate)

       mfspr      r3, l2cr

       rlwinm.   r3, r3, 0, 0, 0     <5,1>

       beq  1f

       mfspr      r3, l2cr

       rlwinm    r3, r3, 0, 1, 31      

#ifdef      CONFIG_ALTIVEC

       dssall

#endif

       sync

       mtspr      l2cr, r3

       sync

1:     mfspr      r3, l2cr           <5,2>

       oris  r3, r3, L2CR_L2I@h

       mtspr      l2cr, r3

invl2:                               <5,3>

       mfspr      r3, l2cr

       andis.      r3, r3, L2CR_L2I@h

       bne  invl2

       blr

解释:

<5,1>:通过测试l2cr寄存器的第0位来核实L2 Cache是否关闭,如果没有关闭,紧接着的指令来关闭L2 Cache,如果已经关闭了,就跳转到<5,2>;

<5,2>:设置l2cr寄存器的第10位,使得L2 Cache的内容无效,也就是清空L2 Cache;

<5,3>:核实是否已经清空L2 Cache,如果没有清空的话,就陷入无限的死循环,O(∩_∩)O~

 

<6>:

       lis    r3, CONFIG_SYS_MONITOR_BASE_EARLY@h  

       ori   r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l          <6,1>

       addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET     <6,2>

       mtlr       r3

       blr

解释:

CONFIG_SYS_MONITOR_BASE_EARLY在include/configs/MPC8641HPCN.h定义为:

#define CONFIG_SYS_MONITOR_BASE_EARLY   0xfff00000

在include/mpc86xx.h中EXC_OFF_SYS_RESET定义如下:

#define EXC_OFF_SYS_RESET   0x0100    // System reset       offset

#define _START_OFFSET       EXC_OFF_SYS_RESET

<6,1>:把CONFIG_SYS_MONITOR_BASE_EARLY,即0xfff0 0000赋值给r3寄存器

<6,2>: in_flash - _start计算得到的是in_flash:标签在U-Boot的_start函数中的偏移地址,这个偏移在我们的MPC8641HPCN中为0x1f38。

所以in_flash - _start + EXC_OFF_SYS_RESET的值为0x2038;

进而我们可以得到in_flash标签的运行地址为0xfff0 0000 + 0x2038 = 0xfff0 2038,示意图如下:

基于MPC8641HPCN上的UBoot源代码分析 <wbr>一

我们把计算得到的in_flash标签的运行地址0xfff0 2038放入lr寄存器,然后通过指令:

       mtlr r3

       blr

转到in_flash:标签处运行。

in_flash:

<7> bl    enable_ext_addr

解释:enable_ext_addr的作用就是通过设置E600中HID0(Hardware Implementation-Dependent Register 0)寄存器中的HIGH_BAT_EN、XAEN以及XBSEN位来开启4组IBATs (4–7) 和4组 DBATs (4–7)、开启扩展的块地址映射机制、以及开启32位的有效地址到36物理地址映射。

备注:我们在讨论MPC8641HPCN上Linux的启动过程中介绍过32为块地址映射块的尺寸最大只有256G,在E600的块地址映射经过扩展之后,块的尺寸可以达到512G,1G,2G以及4G的空间。

enable_ext_addr的汇编指令如下:

enable_ext_addr:

       mfspr      r0, HID0

       lis    r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h

       ori   r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l

       mtspr      HID0, r0

       sync

       isync

       blr

<8>: bl   early_bats

early_bats函数的汇编序列如下:、

early_bats:

       // IBAT 3      

       lis    r4, CONFIG_SYS_IBAT3L@h

       ori     r4, r4, CONFIG_SYS_IBAT3L@l     <8,1>

       lis    r3, CONFIG_SYS_IBAT3U@h

       ori     r3, r3, CONFIG_SYS_IBAT3U@l     <8,2>

       mtspr   IBAT3L, r4

       mtspr   IBAT3U, r3

       isync

       // DBAT 3

       lis    r4, CONFIG_SYS_DBAT3L@h

       ori     r4, r4, CONFIG_SYS_DBAT3L@l     <8,3>

       lis    r3, CONFIG_SYS_DBAT3U@h

       ori     r3, r3, CONFIG_SYS_DBAT3U@l     <8,4>

       mtspr   DBAT3L, r4

       mtspr   DBAT3U, r3

       isync

       // IBAT 5

       lis    r4, CONFIG_SYS_IBAT5L@h

       ori     r4, r4, CONFIG_SYS_IBAT5L@l     <8,5>

       lis    r3, CONFIG_SYS_IBAT5U@h

       ori     r3, r3, CONFIG_SYS_IBAT5U@l     <8,6>

       mtspr   IBAT5L, r4

       mtspr   IBAT5U, r3

       isync

       // DBAT 5

       lis    r4, CONFIG_SYS_DBAT5L@h

       ori     r4, r4, CONFIG_SYS_DBAT5L@l     <8,7>

       lis    r3, CONFIG_SYS_DBAT5U@h

       ori     r3, r3, CONFIG_SYS_DBAT5U@l     <8,8>

       mtspr   DBAT5L, r4

       mtspr   DBAT5U, r3

       isync

       // IBAT 6

       lis    r4, CONFIG_SYS_IBAT6L_EARLY@h

       ori     r4, r4, CONFIG_SYS_IBAT6L_EARLY@l    <8,9>

       lis    r3, CONFIG_SYS_IBAT6U_EARLY@h

       ori     r3, r3, CONFIG_SYS_IBAT6U_EARLY@l    <8,10>

       mtspr   IBAT6L, r4

       mtspr   IBAT6U, r3

       isync

       // DBAT 6

       lis    r4, CONFIG_SYS_DBAT6L_EARLY@h

       ori     r4, r4, CONFIG_SYS_DBAT6L_EARLY@l    <8,11>

       lis    r3, CONFIG_SYS_DBAT6U_EARLY@h

       ori     r3, r3, CONFIG_SYS_DBAT6U_EARLY@l    <8,12>

       mtspr   DBAT6L, r4

       mtspr   DBAT6U, r3

       isync                                                       

#if(CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)

       lis    r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@h

       ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@l  <8,13>

       lis    r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@h

       ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@l  <8,14>

       mtspr   IBAT7L, r4

       mtspr   IBAT7U, r3

       isync

 

       lis    r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@h

       ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@l  <8,15>

       lis    r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@h

       ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@l  <8,16>

       mtspr   DBAT7L, r4

       mtspr   DBAT7U, r3

       isync

#endif

       blr

待续。。。。。。。。。。。。。。。。。

转载地址:http://blog.sina.com.cn/s/blog_70dd16910100za79.html

光伏储能虚拟同步发电机VSG并网仿真模型(Similink仿真实现)内容概要:本文档介绍了光伏储能虚拟同步发电机(VSG)并网仿真模型的Simulink实现方法,重点在于通过建立光伏储能系统与虚拟同步发电机相结合的仿真模型,模拟其在并网过程中的动态响应与控制特性。该模型借鉴了同步发电机的惯性和阻尼特性,提升了新能源并网系统的频率和电压支撑能力,增强了系统的稳定性与可控性。文档还提及相关电力系统仿真技术的应用,包括逆变器控制、储能配置、并网稳定性分析等,并提供了完整的Simulink仿真文件及技术支持资源链接,便于科研人员复现与二次开发。; 适合人群:电气工程、自动化、能源系统等相关专业的研究生、科研人员及从事新能源并网技术开发的工程师。; 使用场景及目标:①用于研究光伏储能系统在弱电网条件下的并网稳定性问题;②掌握虚拟同步发电机(VSG)控制策略的设计与仿真方法;③支持高水平论文(如EI/SCI)的模型复现与创新研究;④为微电网、智能电网中的分布式能源接入提供技术参考。; 阅读建议:建议结合提供的Simulink模型文件与文档说明逐步操作,重点关注VSG控制模块的参数设置与动态响应分析,同时可延伸学习文中提及的MPPT、储能管理、谐波分析等相关技术,以提升综合仿真能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值