Bootstrap的启动过程
一、 说明:
Bootstrap启动代码是官方提供的一级启动代码,包括汇编和C语言两部分组成。对AT91SAM9260来说编译完成后,代码长度必须小于4KB,烧写到dataflash中的0x00000000.
二、系统上电准备Bootstrap启动。
当系统启动选择片内启动(BMS=1)时,程序上电后,启动内部ROM的的固化程序,自动将检测dataflash中前48个字节的数据,如果数据正确,说明是Bootstrap启动代码。这时候系统自动将存在flashdta中的Bootstrap启动代码搬到SRAM0中去,接下来就进行存储器的REMAP,经过remap后,SRAM0从映射前的0x200000地址被映射到了0x000000地址并且程序从此处开始执行。
三、Bootstrap汇编启动过程
1、建立中断向量表。
2、设置堆栈SP的值。
3、主晶振使能为主时钟。
4、数据段的拷贝。
5、对零初始化的数据进行初始化。
6,跳转到C语言main函数。
四、BootstrapC语言初始化过程
1、关闭看门狗。
writel(AT91C_WDTC_WDDIS, AT91C_BASE_WDTC + WDTC_WDMR);
2、配置PLLA时钟
pmc_cfg_plla(PLLA_SETTINGS, PLL_LOCK_TIMEOUT);
3、配置MCK时钟
pmc_cfg_mck(MCKR_SETTINGS, PLL_LOCK_TIMEOUT);
4、配置PLLB时钟
pmc_cfg_pllb(PLLB_SETTINGS, PLL_LOCK_TIMEOUT);
5、配置CP15协处理器
6、配置PIO控制器
pio_setup(hw_pio);
7、配置外部总线接口EBI
writel((readl((AT91C_BASE_MATRIX+MATRIX_SCFG3))&~0xFF)|0x40,(AT91C_BASE_MATRIX+MATRIX_SCFG3));
8、初始化总线矩阵。
writel(readl(AT91C_BASE_CCFG + CCFG_EBICSA) | AT91C_EBI_CS1A_SDRAMC, AT91C_BASE_CCFG + CCFG_EBICSA);
9、配置SDRAM控制器
sdram_init(…….)
10、dataflash的SPI初始化
df_spi_init(pcs, DF_CS_SETTINGS);
11、dataflash的复原初始化
df_recovery(pDf);
12、将dataflash中以0x8400开始的连续0x80000字节的数据搬移到SDRAM中以0x23F00000为起始地址处。
df_download(pDf, img_addr, img_size, img_dest);
13、程序最后跳转到0x23F00000处在sdram中运行K2CMSTART程序代码。
注意:K2CMSTART程序代码是真正的要运行的程序,存在dataflash中以0x8400开始的连续0x80000字节。是我们自己要正真编写的程序。下面提到这程序中的函数变量都是以一个K2CMSTART程序例子来说的。
五、程序应用
该部分BOOT程序为系统的一级启动程序,完成最低层最基本的硬件初始化,为进入到上一级程序进行引导。
AT91sam9260上电后,启动内部ROM的的固化程序,按照dataflash、nandflash的顺序依次来找合法的BOOT程序。所谓合法的指的是在这些存储设备的开始地址处连续的存放的32个字节,也就是8条指令必须是跳转指令或者装载PC的指令,其实这样规定就是把这8条指令当作是异常向量表来处理。必须注意的是第6条指令要包含将要装载的映像的大小。一旦合法的映像找到之后,则固化程序会把找到的映像搬到SRAM中去,所以映像的大小是非常有限的,不能超过4K的大小。当固化程序完成了把合法的映像搬到SRAM的任务以后,接下来就进行存储器的REMAP,经过REMAP之后,SRAM从映设前的0X200000地址处被映设到了0X0地址并且程序从0X0处开始执行。
上电后,我们一般把存储在dataflash中的bootstrap 映像搬移到sram中,bootstrap 完成一些静态初始化工作, 如PMCS,PIOs,再把第二级的K2CMSTART引导程序从dataflash中搬移到sdram中运行。
虽然是BOOT程序,但由于受到内部4KB的SRAM的限制,程序不能实现太多功能,比如进行人机交互操作,查看系统内部某些数据,更新程序软件、更新数据等。当然在保证有足够的SRAM空间的前提下,增加一个串口,进行简单的输入输出信息查看还是可以的,但这也相对没什么意义。但我们如果真要进行复杂的人机交互操作的话,肯定要进入二级引导程序K2CMSTART里进行。
K2CMSTART的启动过程
一、 汇编启动代码
1、 建立中断向量表。
2、 将此中断向量表函数。(根据Scatter里的数据段的定义调用系统函数完成数据段的搬移)
二、C语言函数代码。
3、 1、调用BoardVolMa拷贝到内部SRAM中0X200000起始处。
4、 设置7种异常模式下的堆栈区。
5、 进入低级初始化函数AT91F_LowLevelInit(void)。
程序进入C语言的__mainnageIni()初始化
2、调用ARMTargetInit()初始化硬件
3、调用InitLoadFile()初始化下载文件。
4、循环中调用ReadSmcSoftVolFromScb()函数,超时退出循环
5、主程序主循环中,调用DrvRunLedFlash(100,100,100)函数LED灯闪烁。
6、主程序主循环中,调用MainMenu()函数中的Loadfile()下的net_handle()函数,通过UDP/IP协议传过来的数据进行判别执行相应的操作和更新。
6.1通过arp_rcv_packet()函数对上位机ARP包进行处理;
6.2通过ip_rcv_packet ()函数对上位机IP包进行处理;
6.2.1通过icmp_rcv_packet ()函数对上位机的ICMP网间控制报文协议进行处理;
6.2.2通过udp_rcv_packet ()函数对UDP协议包数据处理;
6.2.2.1用户利用上位机通过TFTP协议可以读取系统的参数信息,也可以更改系统的参数信息。
tftp_rcv_packet()函数实现具体操作,实现对文件的读写操作。tftp_rcv_wrq(struct sk_buff *skb)函数接收三个参数文件到缓冲区;tftp_rcv_rrq(struct sk_buff *skb)函数根据人机交互的命令要求读三个参数文件。
6.2.2.2用户利用上位机通过CCTP协议(端口号=2800)接收命令执行相应的操作。
cctp_rcv_data()函数实现具体操作。
6.2.2.3用户利用上位机通过端口号=2002接收命令执行相应的操作。
AsyCmd_Rcv_Data()函数实现具体操作。
7、主程序主循环中,调用MainMenu()函数中的RcvCctpOptCmdDeal()函数,根据判断结构体变量S_CctpRxBuf来执行操作。
7.1当((S_CctpRxBuf.buf[0]==0x1b)&&(S_CctpRxBuf.buf[2]==0x4d)时,进入JumpToApp_menu()函数时,执行read_dataflash( 0xd0088400,512*1024,0x23e00000 )函数,将dataflash中的应用程序(以0xd0088400为起始地址的512*1024字节)复制到0x23e00000为起始地址SDRAM中,最后程序执行(void (*)(void))0x23e00000 ()跳转到应用程序处运行。
7.2 当(S_CctpRxBuf.buf[0]==0x1b)&&(S_CctpRxBuf.buf[4]==0x3e)时,进入ScbJumpToApp()函数。
三、程序应用。
1、经过一级BOOT程序的引导,我们可以很快进入到二级的引导程序中。在这里我们可以访问系统的全部资源。我们可以更改一级BOOT程序、二级引导程序、包括之后要运行的主应用程序。
2、人机交互最常用的就是异步串口通信,连接简单可靠,不需要专门的上位机软件;缺点是传输距离近,数据传输速度慢,如果要进行大数据量传输肯定太慢。如果我们只简单的传输命令和回传一些简单信息还是一种很好的工具。在系统启动过程中通过串口输出一些系统版本信息,方便我们查看。
3、我们可以利用以太网口进行文件传输、下载。通过INTERNET,我们甚至可以在不同城市间就可以与系统进行交互操作,方便故障诊断维修。
4、利用USB也可以进行数据传输拷贝,但相对来说用的比较少。
5、可以进行这样设置:
5.1、系统开机进入一级BOOT程序后,进入二级程序引导,在进入二级程序引导的时候,正常的话就进入应用程序。如果不能进入应用程序或在引导时按DEL建,利用串口通信,则进入二级引导界面。
5.2、二级引导界面里设置很多选项,如:更新dataflash中一级BOOT程序、更新dataflash中二级引导程序、更新dataflash中应用程序、下载文件到指定地址的dataflash中、下载程序到指定地址的SDRAM中、程序跳到指定的SDRAM中运行、读取指定dataflash中地址的数据、读取指定SDRAM中地址的数据、重新启动、网络设置等
5.3、通过串口选择相应的操作,按提示操作,数据传输的时候可以通过网络传输。网络的参数如IP、网关等也经过串口设置确保可以正常建立网络连接。