最近开发一个基于2440平台的bootloader,偶有所获.现将相关经验记录一下.
现在的开发平台基本上使用了nand做为引导ROM来使用.故这里所讲到的bootloader也是基于nand的.2410/2440系列在通过nand引导时,只能加载4k代码到内存并运行.但大部分bootloader都会超过这个数.因而,在设计时必须将在前4K代码中对全部bootloader进行手工加载.现在讲述其中的方法.
主要步骤:
1/在进入主函数前的汇编初始化中,加入
bl copy_from_nand ; 跳转到下面的标号去
...........
;***********************************************************
IMPORT UBOOT_CopySelf ; 引入C语言实现的COPY自身函数
copy_from_nand
mov r10, lr ; 保存返回地址
ldr sp, =0x33fffffc ; 为C函数实始化堆栈指针
mov fp, #0
bl UBOOT_CopySelf ; 执行跳转,进入C函数实现COPY
ldr r0, =|Image$$RO$$Base| ;读取RO段在内存中运行时地址
add pc, r10, r0 ;对返回地址进行调整后,执行返回
2/在C代码中实现nand读写,并复制自身到内存.注意,C代码必须要保存位于前4K.在LINUX下通过修改MAKEFILE文件可以手工实现将汇编与C合成一目标文件,并做为初始段,ADS中无法实现,只好手工确保复制作身代码尽可能地靠前.
// 检查是否坏块
int UBOOT_ReadPage(U32 page, U8 *buffer)
{
int i;
U8 * bufpt = buffer;
rNFCONT &= ~(1<<1);
rNFSTAT |= (1<<2);
rNFCMD = 0x00;
rNFADDR = 0;
rNFADDR = page & 0xff;
rNFADDR = (page >> 8) & 0xff;
rNFADDR = (page >> 16) & 0xff;
for(i=0;i<10;i++);
while(!(rNFSTAT & (1<<2)));
for(i=0; i<512; i++) *bufpt++ = rNFDATA8;
rNFCONT |= (1<<1);
return 0;
}
void UBOOT_CopySelf(void)
{
U8 *pDes = (U8 *)UBOOT_RAM_BASE;
U32 page;
rNFCONF = 0xFFF0;
rNFCONT = 0x01;
for(page = 0; page < (UBOOT_BLOCK_SIZE * NAND_PAGES_IN_BLOCK) ; page ++)
{
UBOOT_ReadPage(page, pDes);
pDes += 512;
}
}
程序中使用到的宏定义相信大家基本知道是什么值.以上代码经过实际运行.但未加入坏块校验.如有需要,可以进行添加相应功能.但应当尽可能保证长度.