uboot移植
目标平台NANO2410A
目录
准备工作 我的移植工作是基于1.3.2来进行的,因为在网上看到1.3.3之后的版本Makefile会有点小问题 下载好uboot源码之后,解压 tar zxvf u-boot-1.3.2.tar.gz 在board下建立自己板子对应的文件,以smdk2410为模板 cp -r smdk2410 xxx2410 修改Makefile,将smdk2410修改成对应的xxx2410 原理 Nand Flash和Nor Flash不同,其中Nand Flash不能直接读写,需要通过驱动程序控制 在每次CPU上电之后,CPU会通过内置的Nand控制器将Bank0上面的前4K内容映射到一片叫做Steppingstone的buffer中 于是,我们需要将一段代码放在这前4K中,并且在这4K代码中实现将整个uboot载入内存并开始执行。 好在有vivi的代码可以参考,我们不难发现在跳转到C入口之前会先执行copy_myself #ifdef CONFIG_S3C2410_NAND_BOOT /* CONFIG_S3C2410_NAND_BOOT=y */ @ @ copy_myself: copy vivi to ram @ copy_myself: mov r10,lr @ reset NAND mov r1,#NAND_CTL_BASE ldr r2,=0xf830 @ initial value str r2,[r1,#oNFCONF] ldr r2,#oNFCONF] bic r2,r2,#0x800 @ enable chip str r2,#oNFCONF] mov r2,#0xff @ RESET command strb r2,#oNFCMD] mov r3,#0 @ wait 1: add r3,r3,#0x1 cmp r3,#0xa blt 1b 2: ldr r2,#oNFSTAT] @ wait ready tst r2,#0x1 beq 2b ldr r2,#oNFCONF] orr r2,#0x800 @ disable chip str r2,#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 vivi to RAM ldr r0,=VIVI_RAM_BASE mov r1,#0x0 mov r2,#0x20000 bl nand_read_ll tst r0,#0x0 beq ok_nand_read #ifdef CONFIG_DEBUG_LL /* is not set */ bad_nand_read: ldr r0,STR_FAIL ldr r1,SerBase bl PrintWord 1: b 1b @ infinite loop @ 我认为应把这条指令放到#ifdef...#endif之外 #endif ok_nand_read: #ifdef CONFIG_DEBUG_LL /* is not set */ ldr r0,STR_OK ldr r1,SerBase bl PrintWord #endif @ verify mov r0,#0 ldr r1,=0x33f00000 @VIVI_RAM_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,#4 beq done_nand_read bne go_next notmatch: #ifdef CONFIG_DEBUG_LL /* is not set */ sub r0,r0,#4 ldr r1,SerBase bl PrintHexWord ldr r0,SerBase bl PrintWord #endif 1: b 1b done_nand_read: #ifdef CONFIG_DEBUG_LL /* is not set */ ldr r0,SerBase bl PrintWord #endif mov pc,r10 这段程序非常简单,哪怕是完全不会arm汇编也基本能稍微看出一点眉目来
移植工作 有了以上原理性的东西,我们实际动手起来就方便多了 #ifdef CONFIG_S3C2410_NAND_BOOT bl copy_myself #endif /* CONFIG_S3C2410_NAND_BOOT */ 我们需要在这之前先将整个uboot载入到内存当中 #ifdef CONFIG_S3C2410_NAND_BOOT copy_myself: mov r10,lr @save return address to r10 ldr sp,DW_STACK_START mov fp,#0 bl NF_Init ldr r0,=UBOOT_RAM_BASE mov r1,#0x0 mov r2,#0x30000 @192K(size of uboot) bl nand_read_whole tst r0,#0x0 beq ok_nand_read 1: b 1b /* Verify */ ok_nand_read: mov r0,#0x00000000 ldr r1,=UBOOT_RAM_BASE mov r2,#0x400 go_next: ldr r3,#4 beq done_nand_read bne go_next notmatch: 1: b 1b done_nand_read: mov pc,r10 #endif DW_STACK_START: .word STACK_BASE+STACK_SIZE-4 代码结构和vivi中的完全一样,只不过我们将Nand Flash初始化部分改成了C语言实现 #include <common.h> #include <s3c2410.h> #include <config.h> /*s3c2410 datasheet P216*/ #define rNFCONF (*(volatile unsigned int *)0x4e000000) #define rNFCMD (*(volatile unsigned char *)0x4e000004) #define rNFADDR (*(volatile unsigned char *)0x4e000008) #define rNFDATA (*(volatile unsigned char *)0x4e00000c) #define rNFSTAT (*(volatile unsigned int *)0x4e000010) #define rNFECC (*(volatile unsigned int *)0x4e000014) #define rNFECC0 (*(volatile unsigned char *)0x4e000014) #define rNFECC1 (*(volatile unsigned char *)0x4e000015) #define rNFECC2 (*(volatile unsigned char *)0x4e000016) /* Nand Flash ops */ #define NF_CMD(cmd) {rNFCMD=cmd;} #define NF_ADDR(addr) {rNFADDR=addr;} #define NF_nFCE_L() {rNFCONF&=~(1<<11);} #define NF_nFCE_H() {rNFCONF|=(1<<11);} #define NF_RSTECC() {rNFCONF|=(1<<12);} #define NF_RDDATA() (rNFDATA) #define NF_WRDATA(data) {rNFDATA=data;} #define NF_WAITRB() {while(!(rNFSTAT&(1<<0)));} static void NF_Reset(void) { int i; NF_nFCE_L(); /* Enable */ NF_CMD(0xFF); /* Reset Command */ for(i=0;i<10;i++); /* Delay 100ns */ NF_WAITRB(); /* wait for busy */ NF_nFCE_H(); /* Disable */ } void NF_Init(void) { /* * initial value is 0xf830 * copy form vivi */ rNFCONF=0xF830; NF_Reset(); } int nand_read_whole(unsigned char *buf,unsigned long start_addr,int size) { int i,j; /* align with nand block */ if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { return 1; } NF_nFCE_L(); for(i=0; i<10; i++); /* delay 100ns */ i = start_addr; while(i < start_addr + size) { /* Zone A */ rNFCMD = 0; /* Generate 4 cycle address */ rNFADDR = i & 0xff; rNFADDR = (i >> 9) & 0xff; rNFADDR = (i >> 17) & 0xff; rNFADDR = (i >> 25) & 0xff; NF_WAITRB(); /* Read a whole page */ for(j=0; j < NAND_SECTOR_SIZE; j++,i++) { *buf = (rNFDATA & 0xff); buf++; } } NF_nFCE_H(); return 0; } 记得将对应的文件加入Makefile的依赖中。 后续 至此便完成了大部分的工作,我们还需要在相应的板卡配置中稍作修改 #define CONFIG_S3C2410_NAND_BOOT 1 #define STACK_BASE 0x31f00000 #define STACK_SIZE 0x8000 #define UBOOT_RAM_BASE 0x31f80000 #define CONFIG_CMD_NAND #define CONFIG_CMD_PING #define CONFIG_CMD_ENV 修改?CFG_PROMET?为"XXX2410: " #define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ #define CFG_ENV_OFFSET (0x80000-0x4000) #define CONFIG_ARCH_SMDK2410 1 #define CFG_NAND_BASE 0x4E000000 /* Nand Flash控制器在SFR区中起始寄存器地址 */ #define CFG_MAX_NAND_DEVICE 1 /* 支持的最在Nand Flash数据 */ #define SECTORSIZE 512 /* 1页的大小 */ #define NAND_SECTOR_SIZE SECTORSIZE #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1) /* 页掩码 */ #define ADDR_COLUMN 1 /* 一个字节的Column地址 */ #define ADDR_PAGE 2 /* 3字节的页块地址,A9A25*/ #define ADDR_COLUMN_PAGE 3 /* 总共4字节的页块地址 */ #define NAND_ChipID_UNKNOWN 0x00 /* 未知芯片的ID号 */ #define NAND_MAX_FLOORS 1 #define NAND_MAX_CHIPS 1 /* Nand Flash命令层底层接口函数 */ #define WRITE_NAND_COMMAND(d,adr) do {rNFCMD = d;} while(0) #define WRITE_NAND_ADDRESS(d,adr) do {rNFADDR = d;} while(0) #define WRITE_NAND(d,adr) do {rNFDATA = d;} while(0) #define READ_NAND(adr) (rNFDATA) #define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));} #define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);} #define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);} /* 下面一组操作对Nand Flash无效 */ #define NAND_CTL_CLRALE(nandptr) #define NAND_CTL_SETALE(nandptr) #define NAND_CTL_CLRCLE(nandptr) #define NAND_CTL_SETCLE(nandptr) /* 允许Nand Flash写校验 */ #define CONFIG_MTD_NAND_VERIFY_WRITE 1 至此,移植完成 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |