U-boot-2014.04移植到MINI2440(9) nor flash启动和nand flash
在mini2440上,nor flash启动和nand flash启动可以满足不同的需要,这里进行移植,nor的启动移植比较简单,因为不需要进行代码的重定向,nand的启动相对复杂,这里先从nor开始,进入正题: ?????? ?????? 一.修改支持nor flash启动 ?????? 第一步:修改mini2440.h ?????? 在第27行: ?????? #define CONFIG_SYS_TEXT_BASE?????? 0x30008000 ?????? 这里将这个值改为0x0,因为从nor flash启动,直接在0地址执行就可以,不需要再拷贝到sdram中。修改为: ?????? #define CONFIG_SYS_TEXT_BASE?????? 0x0 ?????? 之前我的帖子分析的start.s启动过程等等,都是对应的没有做代码重定向,没有从nand启动,因为那时候只在sdram里执行u-boot,在第37行: ?????? //#define CONFIG_SKIP_LOWLEVEL_INIT ?????? 将其注释掉,这样程序执行: #ifndef CONFIG_SKIP_LOWLEVEL_INIT ?????? bl??? cpu_init_crit #endif ?????? 因为我们没有定义CONFIG_SKIP_LOWLEVEL_INIT,所以程序就会跳转到cpu_init_crit里面,在cpu_init_crit里面,程序进一步跳转到???? mov?????? ip,lr ?????? bl??? lowlevel_init ?????? mov?????? lr,ip ?????? 进入lowlevel_init以后,就会执行这一段代码: ?????? ldr????r0,=SMRDATA ?????? ldr?? r1,=CONFIG_SYS_TEXT_BASE ?????? sub? r0,r0,r1 ?????? 因为TEXT_BASE现在被我们设置为了0,SMRDATA就会从相对0地址的地方开始,这样我们就可以从nor flash启动。 ?????? 第二步:修改lowlevel_init.s ?????? 第113行: ?????? #define REFCNT??????????????????? 1113?????? ?????? 这个REFCNT其实是位宽和刷新频率的设置,这里需要做一个修改,改为如下: ?????? #define REFCNT??????????????????? 0x4f4 ?????? 第三步:编译测试 ?????? 这里我编译没有问题,下载进去在执行erase的时候,无法擦除我的nor flash,这可能是我原来的u-boot对nor flash的第一个块进行了保护,即使protectoff all也没用,但是可以擦除别的块,所以这里我借助了j-link来下载我移植的u-boot到nor flash。具体的下载步骤不懂得可以上网查下,下载进去之后启动,输出如下信息: U-Boot 2014.04 (Sep 02 2015 - 15:09:02) ? CPUID: 32440001 FCLK:?????400 MHz HCLK:?????100 MHz PCLK:??????50 MHz DRAM:?64 MiB WARNING: Caches not enabled Flash: 2 MiB NAND:?256 MiB *** Warning - bad CRC,using defaultenvironment ? In:???serial Out:??serial Err:??serial Net:??dm9000 MINI2440 Deep_l_zh # 说明我们是可以从nor启动了,下面进入nand的移植,我们一般nor只是用来调试和学习,所以掌握从nand启动是很重要的。 ?????? ?????? 二.nand flash启动移植 ?????? 第一步:去除-pie选项 ?????? 在arch/arm/config.mk中,第82行,修改如下: ?????? # needed for relocation #LDFLAGS_u-boot += -pie ?????? 这里是为了避免重定向后新的地址比较复杂,所以还是采用老的办法进行修改。 ?????? 第二步:修改mini2440.h ?????? 重新将TEXT_BASE制定为0x33f80000 ?????? #define CONFIG_SYS_TEXT_BASE?????? 0x33f80000 ?????? 第三步:添加nand_read_b.c文件并修改makefile ?????? 在/board/mini2440/mini2440下,修改Makefile,将其编译进去,修改部分如下: obj-y????? :=mini2440.o obj-y????? += nand_read_b.o obj-y????? +=lowlevel_init.o ?????? 接着再该目录下创建nand_read_b.c文件,该文件所有内容如下: #define NFCONF(*((volatile unsigned long*)0x4E000000)) #define NFCONT(*((volatileunsigned long *)0x4E000004)) #define NFCMMD(*((volatileunsigned char *)0x4E000008)) #define NFADDR(*((volatileunsigned char *)0x4E00000C)) #define NFDATA(*((volatileunsigned char *)0x4E000010)) #define NFSTAT(*((volatileunsigned char *)0x4E000020)) ? ? ? static void nand_read_b(unsignedint addr,unsigned char *buf,unsigned int len); ? static intisBootFromNorFlash(void) { ?????? volatileint *p = (volatile int *)0; ?????? intval; ?????? val= *p; ?????? *p= 0x12345678; ?????? if(*p == 0x12345678) ?????? { ?????? /*写成功,是 nand 启动 */ ?????? *p= val; ?????? return0; ?????? }???? ?????? else ????????????? { ???????????????????? /*NOR 不能像内存一样写 */ ???????????????????? return1; ???????????????????? } } ? void nand_init_b(void) { ????????????? #defineTACLS 3 ????????????? #defineTWRPH0 3 ????????????? #defineTWRPH1 2 ????????????? /*设置时序 */ ????????????? NFCONF= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); ????????????? /*使能 NAND Flash 控制器,初始化 ECC,禁止片选 */ ????????????? NFCONT= (1<<4)|(1<<1)|(1<<0); } ? void copy_code_to_sdram(unsignedchar *src,unsigned char *dest,unsigned int len) { int i = 0; /* 如果是 NOR 启动 */ ?????? if(isBootFromNorFlash()) ?????? { ?????? while(i < len) ????????????? { ???????????????????? dest[i]= src[i]; ????????????? i++; ????????????? } ?????? } else ?????? { ?????? nand_init_b(); ?????? nand_read_b((unsignedint)src,dest,len); ?????? } } ? void clear_bss(void) { ?????? externint __bss_start,__bss_end; ?????? int*p = &__bss_start; ?????? for(; p < &__bss_end; p++) ?????? *p= 0; } ? static void nand_select(void) { ??? NFCONT &= ~(1<<1); } ? static void nand_deselect(void) { ??? NFCONT |= (1<<1); } ? static void nand_cmd(unsignedchar cmd) { ?????? volatileint i; ?????? NFCMMD= cmd; ?????? for(i = 0; i < 10; i++); } ? static void nand_addr(unsignedint addr) { ?????? unsignedint col = addr % 2048; ?????? unsignedint page = addr / 2048; ?????? volatileint i; ?????? NFADDR= col & 0xff; ?????? for(i = 0; i < 10; i++); ?????? NFADDR= (col >> 8) & 0xff; ?????? for(i = 0; i < 10; i++); ?????? NFADDR= page & 0xff; ?????? for(i = 0; i < 10; i++); ?????? NFADDR= (page >> 8) & 0xff; ?????? for(i = 0; i < 10; i++); ?????? NFADDR= (page >> 16) & 0xff; ?????? for(i = 0; i < 10; i++); } ? static void nand_wait_ready(void) { ??? while (!(NFSTAT & 1)); } static unsigned charnand_data(void) { ??return NFDATA; } ? static void nand_read_b(unsignedint addr,unsigned int len) { int col = addr % 2048; int i = 0; /* 1. 选中 */ nand_select(); while (i < len) ?????? { ?????? /*2. 发出读命令 00h */ ?????? nand_cmd(0x00); ?????? /*3. 发出地址(分 5 步发出) */ ?????? nand_addr(addr); ?????? /*4. 发出读命令 30h */ ?????? nand_cmd(0x30); ?????? /*5. 判断状态 */ ?????? nand_wait_ready(); ?????? /*6. 读数据 */ ?????? for(; (col < 2048) && (i < len); col++) ????????????? { ????????????? buf[i]= nand_data(); ????????????? i++; ????????????? addr++; ????????????? } ?????? col= 0; ?????? } /* 7. 取消选中 */ nand_deselect(); } ? 第四步:修改crt0.S ?????? 在arch/arm/lib/crt0.S文件中,修改如下: ?????? ENTRY(_main) ? /* ?* Set up initial C runtime environment andcall board_init_f(0). ?*/ ? #ifdefined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ?????? ldr?? sp,=(CONFIG_SPL_STACK) #else ?????? ldr?? sp,=(CONFIG_SYS_INIT_SP_ADDR) #endif ?????? bic? sp,sp,#7????? /* 8-byte alignment for ABIcompliance */ ?????? sub? sp,#GD_SIZE???? /* allocate one GD aboveSP */ ?????? bic? sp,#7????? /* 8-byte alignment for ABIcompliance */ ?????? mov?????? r9,sp??????????? /* GD is above SP */ ?????? ?????? #if 1 ?????? __TEXT_BASE: ?????? .word CONFIG_SYS_TEXT_BASE ?????? mov r0,#0 ?????? ldr r1,__TEXT_BASE ?????? ldr r2,__TEXT_BASE ?????? ldr r3,=__bss_end ?????? sub r2,r3,r2 ?????? bl copy_code_to_sdram ?????? bl clear_bss ?????? ldr pc,=call_board_init_f ?????? call_board_init_f: ?????? mov r0,#0 ?????? bl board_init_f ?????? ldr sp,[r9,#GD_START_ADDR_SP] /* sp =gd->start_addr_sp */ ?????? bic sp,#7 /* 8-byte alignment forABI compliance */ ?????? ldr r9,#GD_BD] /* r9 = gd->bd */ ?????? subr9,r9,#GD_SIZE /* new GD is below bd*/ ?????? ldr r1,__TEXT_BASE ?????? bl board_init_r ?????? #else ?????? mov?????? r0,#0 ?????? bl??? board_init_f ? #if !defined(CONFIG_SPL_BUILD) ? /* ?* Set up intermediate environment (new sp andgd) and call ?* relocate_code(addr_moni). Trick here is thatwe'll return ?* 'here' but relocated. ?*/ ? ?????? ldr?? sp,#GD_START_ADDR_SP] /* sp =gd->start_addr_sp */ ?????? bic? sp,#7????? /* 8-byte alignment for ABIcompliance */ ?????? ldr?? r9,#GD_BD]???????????? /* r9 = gd->bd*/ ?????? sub? r9,#GD_SIZE???????????? /* new GD isbelow bd */ ? ?????? adr? lr,here ?????? ldr?? r0,#GD_RELOC_OFF]????????? /* r0 =gd->reloc_off */ ?????? add lr,lr,r0 ?????? ldr?? r0,#GD_RELOCADDR]??????? /* r0 =gd->relocaddr */ ?????? b???? relocate_code here: ? /* Set up final(full) environment */ ? ?????? bl??? c_runtime_cpu_setup /* we still call old routine here */ ? ?????? ldr?? r0,=__bss_start?? /* this is auto-relocated!*/ ?????? ldr?? r1,=__bss_end?????????? /* this isauto-relocated! */ ? ?????? mov?????? r2,#0x00000000??????? /* prepare zero toclear BSS */ ? clbss_l:cmp?? r0,r1??????????????????? /*while not at end of BSS */ ?????? strlo?????? r2,[r0]????????? /* clear 32-bit BSS word */ ?????? addlo???? r0,#4????????????? /* move to next */ ?????? blo? clbss_l ? ?????? bl coloured_LED_init ?????? bl red_led_on ? ?????? /* call board_init_r(gd_t *id,ulongdest_addr) */ ?????? mov????r0,r9????????????????? /* gd_t */ ?????? ldr?? r1,#GD_RELOCADDR] /* dest_addr */ ?????? /* call board_init_r */ ?????? ldr?? pc,=board_init_r?????? /* this isauto-relocated! */ ? ?????? /* we should not return here. */ #endif #endif ? ENDPROC(_main) ? ?????? 第五步:修改board_init_f函数 ?????? 在arch/arm/lib/board.c中,第265行,修改为: ?????? unsigned intboard_init_f(ulong bootflag) { bd_t *bd; ?????? init_fnc_t **init_fnc_ptr; ?????? gd_t *id; ?????? 注释掉372的addr,添加新的addr: ?????? //addr -= gd->mon_len; ?????? //addr &= ~(4096 - 1); addr=CONFIG_SYS_TEXT_BASE; 在结尾461行添加: ?????? memcpy(id,(void *)gd,sizeof(gd_t)); ?????? return (unsignedint)id; } ? ?????? 第六步:修改common.h ?????? 在/include下,common.h第298行,修改为: ?????? unsigned int board_init_f(ulong); ?????? 第七步:修改链接脚本u-boot.lds ?????? 在arch/arm/cpu/下,u-boot.lds,第20行: *(.__image_copy_start) ?????? CPUDIR/start.o (.text*) ?????? board/mini2440/mini2440/lowlevel_init.o(.text*) ?????? board/mini2440/mini2440/nand_read_b.o(.text*) ?????? *(.text*) ?????? 同时需要修改/board/mini2440/mini2440下的Makefile,修改如下: ? ? ? ? obj-y????? :=mini2440.o extra-y?? :=nand_read_b.o extra-y?? +=lowlevel_init.o ?????? ?????? 第八步:修改顶层/arch/arm/config.mk ?????? 注释掉checkarmreloc这部分,否则编译会出错 在第105行: ?????? #ALL-y += checkarmreloc ?????? ?????? 第九步:编译测试 ?????? 从nor启动,然后下载到nand之后,关闭电源,s2开关打到nand处启动,出现如下信息: ?U-Boot 2014.04 (Sep 02 2015 - 18:54:01) CPUID: 32440001 FCLK:?????400 MHz HCLK:?????100 MHz PCLK:??????50 MHz DRAM:?64 MiB WARNING: Caches not enabled Flash: *** failed *** ### ERROR ### Please RESET the board ### ?????? 因为这时候从nand启动,检测不到nor flash的信息,但是使用友善的u-boot从nand启动是可以读到nor的信息的,并且可以使用nor的命令对其进行操作,看来这个地址空间还有很多文章,这里能够从nand启动进行内核引导的是我们的目的。所以,屏蔽这个错误,这个错误在我们移植nor flash读写的时候就探讨过了,这里进去arch/arm/lib/board.c,第577行: ?????? # endif /* CONFIG_SYS_FLASH_CHECKSUM */ ?????? } else { ????????????? puts(failed); ?????? //???? hang(); ?????? } ?????? 把这个hang()函数注释掉。 ?????? 再次编译下载。 ?U-Boot 2014.04 (Sep 02 2015 - 19:06:04) CPUID: 32440001 FCLK:?????400 MHz HCLK:?????100 MHz PCLK:??????50 MHz DRAM:?64 MiB WARNING: Caches not enabled Flash: *** failed *** NAND:?256 MiB *** Warning - bad CRC,using defaultenvironment ? In:???serial Out:??serial Err:??serial Net:??dm9000 MINI2440 Deep_l_zh # ?????? 可以看到成功了,不得不说,移植过程参照网上大神移植到tq2440的帖子,但是期间遇到了很多小问题,这里没有一一写下来,对自己还是收获不少,如有不正确,还请指出,大家共同进步! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |