2010年(130)
分类: LINUX
2010-01-16 00:24:56
移植U-Boot.1.2.0到博创2410-S(S3C2410A) 一、在U-Boot中建立自己的开发板类型,并测试编译。我为开发板取名叫: tekkaman2410 0 在工作目录下解压U-Boot。 $tar zxvf u-boot.git.tar.gz 1 进入U-Boot目录,修改Makefile $cd u-boot.git/ $vi Makefile #为tekkaman2410建立编译项 smdk2410_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0 tekkaman2410_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t tekkaman2410 tekkaman s3c24x0 各项的意思如下: arm: CPU的架构(ARCH) arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。 tekkaman2410: 开发板的型号(BOARD),对应于board/tekkaman/tekkaman2410目录。 tekkaman: 开发者/或经销商(vender)。 s3c24x0: 片上系统(SOC)。 同时在“ifndef CROSS_COMPILE ”之前 加上自己交叉编译器的路径,比如我使用crosstool-0.43制作的基于2.6.22.2内核和gcc-4.1.0-glibc-2.3.2的ARM9TDMI交叉编译器,则: CROSS_COMPILE=/home/tekkaman/working/crosstool-gcc410-k26222/gcc-4.1.0-glibc-2.3.2/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu- 2 在/board子目录中建立自己的开发板tekkaman2410目录 由于我在上一步板子的开发者/或经销商(vender)中填了 tekkaman ,所以开发板tekkaman2410目录一定要建在/board子目录中的tekkaman目录下 ,否则编译会出错。 $cd board $mkdir tekkaman tekkaman/tekkaman2410 $cp -arf smdk2410/* tekkaman/tekkaman2410/ $cd tekkaman/tekkaman2410 $mv smdk2410.c tekkaman2410.c 还要记得修改自己的开发板tekkaman2410目录下的Makefile文件,不然编译时会出错: COBJS := tekkaman2410.o flash.o $vi Makefile 3 在include/configs/中建立配置头文件 $cd ../../.. $cp include/configs/smdk2410.h include/configs/tekkaman2410.h 4 测试编译能否成功 $make tekkaman2410_config Configuring for tekkaman2410 board... (如果出现: $ make tekkaman2410_config Makefile:1927: *** 遗漏分隔符 。 停止。 请在U-boot的根目录下的Makefile的 @$(MKCONFIG) $(@:_config=) arm arm920t tekkaman2410 tekkaman) 前加上“Tab”键) $make 我到这一步测试交叉编译成功!! ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 二、修改U-Boot中的文件,以匹配博创的2410-S实验箱。 1 修改/cpu/arm920t/start.S (1)修改中断禁止部分 # if defined(CONFIG_S3C2410) ldr r1, =0x7ff //根据2410芯片手册,INTSUBMSK有11位可用, //vivi也是0x7ff,不知为什么U-Boot一直没改过来。 ldr r0, =INTSUBMSK str r1, [r0] # endif (2)修改时钟设置(可以不修改,因为后面的board_init函数也会将时钟设为202.8MHz) /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] mrc p15, 0, r1, c1, c0, 0 /*read ctrl register tekkaman*/ orr r1, r1, #0xc0000000 /*Asynchronous tekkaman*/ mcr p15, 0, r1, c1, c0, 0 /*write ctrl register tekkaman*/ /*now, CPU clock is 202.8 Mhz tekkaman*/ mov r1, #CLK_CTL_BASE /* tekkaman*/ mov r2, #MDIV_200 /* mpll_200mhz tekkaman*/ add r2, r2, #PSDIV_200 /* mpll_200mhz tekkaman*/ str r2, [r1, #0x04] /* MPLLCON tekkaman */ #endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */ 红色部分是我添加的,因为 U-Boot 使用的是 /* default FCLK is 120 MHz ! */ 我利用博创提供的vivi的代码,将其设为202.8MHz 并在前面加上: #elif defined(CONFIG_S3C2410) # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* clock divisor register */ #define CLK_CTL_BASE 0x4C000000 /* tekkaman */ #define MDIV_200 0xa1 << 12 /* tekkaman */ #define PSDIV_200 0x31 /* tekkaman */ (3)将从Flash启动改成从NAND Flash启动。 将以下U-Boot的重定向语句段: #ifndef CONFIG_SKIP_RELOCATE_UBOOT relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ add r2, r0, r2 /* r2 <- source end address */ copy_loop: ldmia r0!, {r3-r10} /* copy from source address [r0] */ stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop #endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 替换成: #ifdef CONFIG_S3C2410_NAND_BOOT @tekkaman@@@@@@@@@@@@@@@@SSSSSSSSSSSSS @ reset NAND mov r1, #NAND_CTL_BASE ldr r2, =0xf830 @ initial value str r2, [r1, #oNFCONF] ldr r2, [r1, #oNFCONF] bic r2, r2, #0x800 @ enable chip str r2, [r1, #oNFCONF] mov r2, #0xff @ RESET command strb r2, [r1, #oNFCMD] mov r3, #0 @ wait nand1: add r3, r3, #0x1 cmp r3, #0xa blt nand1 nand2: ldr r2, [r1, #oNFSTAT] @ wait ready tst r2, #0x1 beq nand2 ldr r2, [r1, #oNFCONF] orr r2, r2, #0x800 @ disable chip str r2, [r1, #oNFCONF] @ get read to call C functions (for nand_read()) ldr sp, DW_STACK_START @ setup stack pointer mov fp, #0 @ no previous frame, so fp=0 @ copy U-Boot to RAM ldr r0, =TEXT_BASE mov r1, #0x0 mov r2, #0x20000 bl nand_read_ll tst r0, #0x0 beq ok_nand_read bad_nand_read: loop2: b loop2 @ infinite loop ok_nand_read: @ verify mov r0, #0 ldr r1, =TEXT_BASE mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes go_next: ldr r3, [r0], #4 ldr r4, [r1], #4 teq r3, r4 bne notmatch subs r2, r2, #4 beq stack_setup bne go_next notmatch: loop3: b loop3 @ infinite loop #endif @ CONFIG_S3C2410_NAND_BOOT @tekkaman@@@@@@@@@@@@@@@@@@EEEEEEEEE 在 “ _start_armboot: .word start_armboot ” 后加入: .align 2 DW_STACK_START: .word STACK_BASE+STACK_SIZE-4 附:顺便提一下,在start.S文件的注释部分有个小错误(红色部分:原来是2): cpu_init_crit: ...... /* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) orr r0, r0, #0x00000002 @ set bit 1 (A) Align ...... 2 在board/tekkaman/tekkaman2410加入NAND Flash读函数,建立nand_read.c文件,加入如下内容(copy from vivi): #include #define __REGb(x) (*(volatile unsigned char *)(x)) #define BUSY 1 inline void wait_idle(void) { while(!(NFSTAT & BUSY)) /* low level nand read function */ if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { /* chip Enable */ for(i=start_addr; i < (start_addr + size);) { /* Write Address */ wait_idle(); for(j=0; j < NAND_SECTOR_SIZE; j++, i++) { /* chip Disable */ return 0; 3 修改board/tekkaman/tekkaman2410/Makefile文件 4 修改include/configs/tekkaman2410.h文件,添加如下内容: 5 修改board/tekkaman/tekkaman2410/lowlevel_init.S文件 6 修改/board/tekkaman/tekkaman2410/tekkaman2410.c
(请格外注意:如果编译时报错,在Linux下用KWrite等有高亮显示的文本编辑器看看文件的注释是不是为注释应有的颜色(KWrite中为灰色),如果不是,则将注释删除。因为#define后面的注释被认为是程序的一部分。建议注释和#define分行写) ...... /* * Hardware drivers */ //#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */ //#define CS8900_BASE 0x19000300 //#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */ #define CONFIG_DRIVER_NE2000 #define CONFIG_DRIVER_NE2000_BASE (0x10000000+0x200) ...... /*********************************************************** * Command definition ***********************************************************/ #define CONFIG_COMMANDS \ (CONFIG_CMD_DFL | \ CFG_CMD_CACHE | \ CFG_CMD_NAND | \ CFG_CMD_NET | \ /*CFG_CMD_EEPROM |*/ \ /*CFG_CMD_I2C |*/ \ /*CFG_CMD_USB |*/ \ CFG_CMD_PING | \ CFG_CMD_ENV | \ CFG_CMD_REGINFO | \ CFG_CMD_DATE | \ CFG_CMD_ELF) /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include #define CONFIG_CMDLINE_TAG //增加U-Boot对内核参数传递的功能, //具体内容请参阅对《U-BOOT下使用bootm引导内核方法》的补充说明
static struct nand_flash_dev nand_flash_ids[] = { ......{"Samsung KM29N16000",NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000, 0}, {"Samsung K9F1208U0M", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000, 0}, {"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000, 0}, ...... {NULL,} }; 9 修改/lib_arm中的board.c。 static int display_banner (void) ...... #ifdef CONFIG_INFERNO #error CONFIG_INFERNO not supported yet #endif int nand_legacy_rw (struct nand_chip* nand, int cmd, size_t start, size_t len, size_t * retlen, u_char * buf); extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, size_t len, int clean); /* info for NAND chips, defined in drivers/nand/nand.c */ extern nand_info_t nand_info[CFG_MAX_NAND_DEVICE]; ...... #else /* ! CFG_ENV_OFFSET_REDUND */ int saveenv(void) { ulong total; int ret = 0; puts ("Erasing Nand..."); //if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) if (nand_legacy_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SIZE, 0)) return 1; puts ("Writing to Nand... "); total = CFG_ENV_SIZE; //ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); ret = nand_legacy_rw(nand_dev_desc + 0, 0x00 | 0x02, CFG_ENV_OFFSET, CFG_ENV_SIZE, &total, (u_char*)env_ptr); if (ret || total != CFG_ENV_SIZE) return 1; puts ("done\n"); return ret; ...... #else /* ! CFG_ENV_OFFSET_REDUND */ /* * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ void env_relocate_spec (void) { #if !defined(ENV_IS_EMBEDDED) ulong total; int ret; total = CFG_ENV_SIZE; //ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); ret = nand_legacy_rw(nand_dev_desc + 0, 0x01 | 0x02, CFG_ENV_OFFSET, CFG_ENV_SIZE, &total, (u_char*)env_ptr); ...... 11 在/board/tekkaman/tekkaman2410/tekkaman2410.c文件的末尾添加对Nand Flash 的初始化函数(在后面Nand Flash的操作都要用到) u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。Nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nnd/nand.c中的nand_init();否则调用自己在board/smdk2410/smdk2410.c中的nand_init()函数。这里我选择第二种方式。 #if (CONFIG_COMMANDS & CFG_CMD_NAND) static inline void NF_Conf(u16 conf) nand->NFCONF = conf; static inline void NF_Cmd(u8 cmd) nand->NFCMD = cmd; static inline void NF_CmdW(u8 cmd) static inline void NF_Addr(u8 addr) nand->NFADDR = addr; static inline void NF_SetCE(NFCE_STATE s) switch (s) { case NFCE_HIGH: static inline void NF_WaitRB(void) while (!(nand->NFSTAT & (1<<0))); static inline void NF_Write(u8 data) nand->NFDATA = data; static inline u8 NF_Read(void) return(nand->NFDATA); static inline void NF_Init_ECC(void) nand->NFCONF |= (1<<12); static inline u32 NF_Read_ECC(void) return(nand->NFECC); #endif /** NAND flash initialization.
NF_SetCE(NFCE_LOW);
NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0)); NF_Reset(); void NF_Init(); 12 修正U-Boot的NE2000驱动的低级错误 将第45行: 13 因为没有Nor Flash芯片,所以注释掉/common/cmd_bootm.c中关于imls命令的程序段和/common/cmd_flash.c中的程序。不然,按上面的修改,编译会出错。 三、交叉编译U-Boot。 不过我建议:在看懂U-Boot的基础上移植,不然当有错误时你会狂郁闷,不知如何下手! |