您的位置:首页 > 其它

WinCE5.0 SMDK2410 BSP在GEC2410开发板上的移植(1)-NBoot

2009-06-28 13:56 615 查看
GEC2410开发板自带的Eboot需要通过自带的Bootloader下载后才能运行,这个Eboot只起到下载内核镜像的作用,重启后是通过Nboot启动内核而不是Eboot。而且也不支持KITL,BSP的结构也完全是4.2下的,非常凌乱。不知道开发板商为什么不能按照5.0的架构做一个支持KITL内核调试的Eboot。
因此产生了移植一个上电后能直接运行的Eboot的想法。由于S3C2410支持4K的Steppintstone,可以从Nand Flash启动,我把Eboot放在Nand Flash中,用Nboot进行引导。NBoot位于NandFlash的Block 0,Eboot位于Block 2。上电后,位于前4K的Nboot被复制到RAM中运行,然后Nboot复制Eboot到RAM中,最后跳转到Eboot,由Eboot进行下一步的工作。
或者把Eboot放到Nor Flash中,也不需要Nboot,之后将介绍基于Nor Flash的移植
整个工程位于:http://download.csdn.net/source/620556中的NBoot_2410(Eboot)目录下。

一、开发环境
编译器: ADS1.2
目标板: GEC2410 S3C2410A,NAND Flash:64M K9F1208,NOR Flash:2M SST39VF1601 SDRAM 64M,CS8900

二、开始移植
(1)一般Nboot的结构
板子自带的Nboot是用来直接引导CE内核的,它需要一个toc结构的变量,保存了被引导镜像的地址大小等信息。
typedef struct _TOC {
DWORD               dwSignature;
BYTE    udid[8];
// How to boot the images in this TOC.
// This could be moved into the image descriptor if desired,
// but I prefer to conserve space.
BOOT_CFG            BootCfg;

// Array of Image Descriptors.
IMAGE_DESCRIPTOR    id[MAX_TOC_DESCRIPTORS];

CHAININFO           chainInfo;
} TOC, *PTOC;           // 512 bytes

开发板自带的Eoot被下载后将在Block 1写入这个toc结构,然后Nboot在读取信息来引导CE Image。
同理如果用来启动Eboot,只需要把Eboot的信息写入这个结构即可。我们不把toc放入Block 1然后再去读,而是直接在程序中定义好,因为Eboot大小位置都是固定的。

(2)修改Nboot
我在网上找到一个最近似我需求的Nboot,已经把toc结构成员进行了初始化,只需要修改相应的参数即可。

(3)串口驱动
我使用UART1 38400kbps,用来输出Nboot的启动信息。
#define BAUD_RATE       38400

void Uart_Init(void)
{
int i;

rUFCON1 = 0x0;      // FIFO disable
rUMCON1 = 0x0;      // AFC disable
rULCON1 = 0x3;      // Normal,No parity,1 stop,8 bits
rUCON1  = 0x245;
rUBRDIV1=( (int)(PCLK/16./BAUD_RATE) -1 );
for(i=0;i<100;i++);
}

其他的初始化部分我参考我的资源中的工程

(4)ReadEbootFromNand函数
ReadEbootFromNand这个函数是这个工程中的核心,用来读取NandFlash起始位置为Block 2的Eboot到指定的SDRAM地址中,然后跳转到Eboot运行。
几个重要的参数为
#define EBOOT_RAM_IMAGE_SIZE        0x00040000  //256K Eboot
#define EBOOT_BLOCK                         2                    //Eboot起始Block
#define EBOOT_RAM_IMAGE_BASE       0x8c038000   //Eboot在SDRAM的地址

DWORD ReadEbootFromNand()
{
DWORD dwSectorsNeeded;
DWORD dwSector, dwLength;         // Start Sector & Length
DWORD dwRAM, i;

//Init Toc
toc.id[0].dwVersion     = (EBOOT_VERSION_MAJOR << 16) | EBOOT_VERSION_MINOR;
toc.id[0].dwSignature   = IMAGE_EBOOT_SIG;
toc.id[0].dwImageType   = IMAGE_TYPE_RAMIMAGE;
//以上三个参数其实实际并未用到
toc.id[0].dwLoadAddress = EBOOT_RAM_IMAGE_BASE;//Eboot在SDRAM的地址
toc.id[0].dwJumpAddress = EBOOT_RAM_IMAGE_BASE;
toc.id[0].dwTtlSectors  = FILE_TO_SECTOR_SIZE(EBOOT_RAM_IMAGE_SIZE);//Eboot所占Sectors数目
// 1 contigious segment
toc.id[0].sgList[0].dwSector = BLOCK_TO_SECTOR(EBOOT_BLOCK);//计算Eboot起始Sector
toc.id[0].sgList[0].dwLength = toc.id[0].dwTtlSectors;//传递Sectors数
dwSectorsNeeded = toc.id[0].dwTtlSectors;

dwRAM    = VIRTUAL_TO_PHYSICAL(toc.id[0].dwLoadAddress);//计算Eboot在RAM中的物理地址
JumpAddr = toc.id[0].dwJumpAddress ? VIRTUAL_TO_PHYSICAL(toc.id[0].dwJumpAddress) :
VIRTUAL_TO_PHYSICAL(toc.id[0].dwLoadAddress);//Eboot复制完成后的跳转地址

i = 0;
//从NandFlash Block 2开始复制Eboot到SDRAM中
while (dwSectorsNeeded && i < MAX_SG_SECTORS)
{
dwSector = toc.id[0].sgList[i].dwSector;
dwLength = toc.id[0].sgList[i].dwLength;
// read each sg segment
while (dwLength) {
if ( !FMD_ReadSector(dwSector, (LPBYTE)dwRAM, NULL, 1) )
{
//                  Uart_SendString("ERR_DISK_OP_FAIL2: ");
//                  Uart_SendDWORD(dwSector, TRUE);
}
dwSector++;
dwLength--;
dwRAM += SECTOR_SIZE;
}
dwSectorsNeeded -= toc.id[0].sgList[i].dwLength;
i++;
}
return ERR_SUCCESS;
}

(5)启动Eboot
通过调用Launch(JumpAddr)函数跳转到Eboot
Launch是用汇编写的,Eboot中也会调用这个函数来跳转到内核

EXPORT Launch
Launch
nop
nop
nop
nop

mov     pc, r0  ; Jump to PhysicalAddress
nop
MOV_PC_LR

END

(6)Main
void Main(void)
{
DWORD  err;

MMU_EnableICache();
Uart_Init();
Uart_SendString(SIGN_ON);
NF_Init();
ReadEbootFromNand();
Launch(JumpAddr);
Uart_SendString("/nBoot ERROR:");
Uart_SendDWORD(err, TRUE);
while (1);
}

(7)超级终端中的显示结果,关于Eboot的移植将在后文中阐述

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐