天天看點

WinCE5.0 SMDK2410 BSP在GEC2410開發闆上的移植(1)-NBoot

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的移植将在後文中闡述

WinCE5.0 SMDK2410 BSP在GEC2410開發闆上的移植(1)-NBoot

繼續閱讀