关于杨创YC2440uboot移植
?
欢迎大家有空可以看下我的http://ltdzhuwai.taobao.com ?U-Boot1.2.0移植YC2440
分类:
U-BOOT 2010-12-22 19:48 185人阅读
评论(2)
收藏
举报
移植U-Boot-1.2.0到YC2440 首先,U-Boot-1.2.0还没有支持s3c2440,这次移植是用s3c2410的文件修改而成。本移植参考网上一位叫tekkaman网友完成。感谢他们无私奉献、共享。 链接:http://blog.chinaunix.net/u1/34474/showart_410294.html U-Boot源码:ftp://ftp.denx.de/pub/u-boot/ 红色为修改的地方,蓝色为运行指令、注释地方 ? 一、在U-Boot中建立自己开发板类型,测试编译 1 进入U-Boot目录,修改Makefile # tar –jxvf? u-boot-1.2.0.tar.bz2 # cd u-boot-1.2.0 # gedit Makefile //为liao2440建立编译项 sbc2410x_config: unconfig ??? @$(MKCONFIG) $(@:_config=) arm arm920t sbc2410x NULL s3c24x0 liao2440_config : unconfig ??????? @$(MKCONFIG) $(@:_config=) arm arm920t liao2440 liao s3c24x0 说明: arm: CPU的架构(ARCH) arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。 liao2440: 开发板的型号(BOARD),对应于board/liao/liao2440目录。 liao: 开发者/或经销商(vender)。 s3c24x0: 片上系统(SOC)。 ? 同时在“ifndef CROSS_COMPILE”之前? 加上自己交叉编译器的路径,比如我使用crosstool-0.43制作的基于2.6.24内核和gcc-4.1.1-glibc-2.3.2的ARM9TDMI交叉编译器,则: ? CROSS_COMPILE=CROSS_COMPILE=/home/liao/crosstool/gcc-4.1.1-glibc-2.3.2/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu- ? 2 /board子目录中建立自己开发板liao2440目录 ? 由于上一步板子的开发者/或经销商(vender)中填了liao,所以开发板liao2440目录一定要建在/board子目录liao目录下 ,否则编译会出错。 ? # cd board # mkdir liao liao/liao2440 # cp -arf sbc2410x/*?? liao/liao2440/ # cd liao/liao2440 # mv sbc2410x.c liao2440.c ? 修改自己开发板liao2440目录下Makefile文件 # gedit Makefile COBJS := sbc2410x.o flash.o ? COBJS := liao2440.o flash.o ? 3 建立配置头文件在include/configs/ # cd …/u-boot-1.2.0/include/configs # cp include/configs/sbc2410x.h ?include/configs/liao2440.h ? 4 测试编译是否成功 # make liao2440_config Configuring for liao2440 board… (如果出现: Makefile:1927: *** 遗漏分隔符 。 停止。 请在U-boot的根目录下的Makefile的 ??????? @$(MKCONFIG) $(@:_config=) arm arm920t liao2440 liao) 前加上“Tab”键) # make ? ??? Ok,到这里前期准备工作完成!!!!!!! ? 二、修改U-Boot中文件,根据开发板YC2440配置 1 修改/cpu/arm920t/start.S 1.1修改寄存器定义 /* turn off the watchdog */ # if defined(CONFIG_S3C2400) # define pWTCON??????? 0x15300000 # define INTMSK??????? 0x14400008??? /* Interupt-Controller base addresses */ # define CLKDIVN??? 0x14800014??? /* clock divisor register */ # elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) # define pWTCON??????? 0x53000000 # define INTMSK??????? 0x4A000008??? /* Interupt-Controller base addresses */ # define INTSUBMSK??? 0x4A00001C # define CLKDIVN??? 0x4C000014??? /* clock divisor register */ # define CLK_CTL_BASE??????? 0x4C000000 # if defined(CONFIG_S3C2440) # define MDIV_405?????? 0x7f << 12 # define PSDIV_405?????? 0x21 # endif # if defined(CONFIG_S3C2410) # define MDIV_200??????? 0xa1 << 12 # define PSDIV_200??????? 0x31 # endif /*这一段为后面修改时钟定义的一些参数*/ # endif ? 1.2修改中断禁止部分 # if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) ??? ldr???? ?r0,=pWTCON ??? mov?? ?r1,#0x0 ??? str???? ?r1,[r0] ? ???? /* ???? * mask all IRQs by setting all bits in the INTMR - default ???? */ ??? mov??? r1,#0xffffffff ??? ldr?? ??r0,=INTMSK ??? str?? ??r1,[r0] # if defined(CONFIG_S3C2410) ??? ldr??? r1,=0x7ff? ???//根据2410芯片手册,INTSUBMSK有11位可用, ?????????????????????? //vivi也是0x7ff,不知为什么U-Boot一直没改过来。 ??? ldr??? r0,=INTSUBMSK ??? str??? r1,[r0] # endif # if? defined(CONFIG_S3C2440) ??? ldr??? r1,=0x7fff?? //根据2440芯片手册,INTSUBMSK有15位可用 ??? ldr??? r0,[r0] # endif ? 1.3 修改时钟设置 /*时钟控制逻辑单元能够产生s3c2440需要的时钟信号,包括CPU使用的主频FCLK,AHB总线使用的HCLK,APB总线设备使用的PCLK,2440里面的两个锁相环(PLL),其中一个对应FCLK、HCLK、PCLK,另外一个对应UCLK(48MHz)*/ /* FCLK:HCLK:PCLK = 1:4:8 */ ??? ldr??? r0,=CLKDIVN ? ??mov??? r1,#5 ??? str??? r1,[r0] /* 下面协处理器指令是用来把CPU的模式设置成Asynchronous 模式,为什么要这样做?s3c2440的datasheet说得很清楚,具体可在datasheet中搜索R1_nF或R1_iA内容。至于R1_nF和R1_iA的值可以在vivi源码的s3c2440.h中得到。 单从指令上看,下面指令的作用把协处理器p15的寄存器c1的最高两位置1,仔细看过《arm 体系结构与编程》的朋友可能会发现个问题:《arm 体系结构与编程》里面说 p15 的bit30和bit31是保留的,那么下面的指令又怎么会有意义呢?其实《arm 体系结构与编程》里面说这两个bit是保留的是针对arm7的,对arm9的s3c2440并不适用。 */ ??? mrc??? p15,r1,c1,c0,0??????? /*read ctrl register?? liao*/ ??? orr??? r1,#0xc0000000???????? /*Asynchronous? liao*/ ??? mcr??? p15,0????? /*write ctrl register liao*/ ? # if defined(CONFIG_S3C2440) ??? /*now,CPU clock is 405.00 Mhz? */ ??? mov??? r1,#CLK_CTL_BASE ??? mov??? r2,#MDIV_405?????????????????? /* mpll_405mhz??? liao*/ ??? add??? r2,r2,#PSDIV_405???????????? /* mpll_405mhz??? liao*/ ??? str??? r2,[r1,#0x04]?????????????? /* MPLLCON liao */ # endif # if defined(CONFIG_S3C2410) ??? /*now,CPU clock is 202.8 Mhz?? liao*/ ??? mov??? r1,#CLK_CTL_BASE??? /* liao*/ ??? mov??? r2,#MDIV_200?????????????????? /* mpll_200mhz??? liao*/ ??? add??? r2,#PSDIV_200???????????? /* mpll_200mhz??? liao*/ ??? str??? r2,#0x04]?????????????? /* MPLLCON liao */ # endif # endif??? /* CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 */ /*时钟设置参照vivi代码,主频405MHZ*/ ? 1.4 将Flash启动改为从NAND Flash启动(2410与2440不同,参照vivi) # if 0 # 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 */ # endif /*参照vivi代码,nandflash拷贝*/ # ifdef CONFIG_S3C2440_NAND_BOOT?? ??? @ reset NAND ??? mov??? r1,#NAND_CTL_BASE ??? ldr??? r2,=( (7<<12)|(7<<8)|(7<<4)|(0<<0) ) ??? str??? r2,#oNFCONF]??? ?/*这些宏在includes/configs/liao2440.h中定义*/ ??? ldr??? r2,#oNFCONF] ? ??? ldr??? r2,=( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control ??? str??? r2,#oNFCONT] ??? ldr??? r2,#oNFCONT] ? ??? ldr??? r2,=(0x6)??????? @ RnB Clear ??? str??? r2,#oNFSTAT] ??? ldr??? r2,#oNFSTAT] ??? ??? mov??? r2,#0xff??????? @ RESET command ??? strb??? r2,#oNFCMD] ? ? ??mov r3,#0?????????????????? @ wait nand1: ? ??add? r3,#0x1 ? ??cmp r3,#0xa ? ??blt?? nand1 ? nand2: ?? ?ldr?? r2,#oNFSTAT]????? @ wait ready ? ??tst??? r2,#0x4 ? ??beq? nand2 ? ? ??? ldr??? r2,#oNFCONT] ??? orr??? r2,#0x2??????? @ Flash Memory Chip Disable ??? str??? r2,#oNFCONT] /*汇编调用C函数,初始化栈*/ @ 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 /*nand_read_ll为uboot拷贝代码入口函数,r0,r1,r2为入口参数 tst? r0,#0x0中r0为函数返回值*/ ?? ?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,#4 ?? ?beq? stack_setup ?? ?bne? go_next ? notmatch: loop3:???? b???? loop3???????? @ infinite loop ? #endif @ CONFIG_S3C2440_NAND_BOOT ? 1.5 调出start.S前,利用点灯大法查看程序运行位置 在 ldr? pc,_start_armboot 之前加入LED mov??? r1,#GPIO_CTL_BASE add??? r1,#oGPIO_F ldr??? r2,=0x55aa str??? r2,#oGPIO_CON] mov??? r2,#0xff str??? r2,#oGPIO_UP] mov??? r2,#0xe0 str??? r2,#oGPIO_DAT] /*YC2440开发板有4个LED,GPIO_F[4:7],点亮一个LED,下面函数进入第二阶段*/ ldr? pc,_start_armboot _start_armboot:????? .word start_armboot .align???? 2????????????????? DW_STACK_START:? .word? STACK_BASE+STACK_SIZE-4 /*栈空间是从高地址向低地址增长,用于调用nand_read_ll函数时设置占空间,STACK_BASE STACK_SIZE定义在后面/include/configs/liao2440.h */ ? 2 在board/liao/liao2440加入NAND Flash读函数文件,复制vivi中nand_read.c文件 #include <config.h> ? #define __REGb(x)??? (*(volatile unsigned char *)(x)) #define __REGi(x)??? (*(volatile unsigned int *)(x)) #define NF_BASE??????? 0x4e000000 ? #define NFCONF??????? __REGi(NF_BASE + 0x0) #define NFCONT??????? __REGi(NF_BASE + 0x4) #define NFCMD??????? __REGb(NF_BASE + 0x8) #define NFADDR??????? __REGb(NF_BASE + 0xC) #define NFDATA??????? __REGb(NF_BASE + 0x10) #define NFSTAT??????? __REGb(NF_BASE + 0x20) ? //#define GPDAT??????? __REGi(GPIO_CTL_BASE+oGPIO_F+oGPIO_DAT) ? #define NAND_CHIP_ENABLE? (NFCONT &= ~(1<<1)) #define NAND_CHIP_DISABLE (NFCONT |=? (1<<1)) #define NAND_CLEAR_RB????? (NFSTAT |=? (1<<2)) #define NAND_DETECT_RB????? { while(! (NFSTAT&(1<<2)) );} ? #define BUSY 4 inline void wait_idle(void) { ??? while(!(NFSTAT & BUSY)); ??? NFSTAT |= BUSY; } ? #define NAND_SECTOR_SIZE??? 512 #define NAND_BLOCK_MASK??????? (NAND_SECTOR_SIZE - 1) ? /* low level nand read function */ int nand_read_ll(unsigned char *buf,unsigned long start_addr,int size) { ??? int i,j; /* 下面if保证对flash的读操作是从某一页的页头开始的,也就是保证start_addr[0:8]位都为0, 本次flash的一页的大小位512-bytes,也就是从0x0到0x1ff */ ??? if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { ??????? return -1;??? /* invalid alignment */ ??? } ? ??? NAND_CHIP_ENABLE; ? ??? for(i=start_addr; i < (start_addr + size);) { ??????? /* READ0 */ ??????? NAND_CLEAR_RB;??????? ??????? NFCMD = 0; ? ??????? /* Write Address */ /*下面这个送地址的过程最难懂的一部分,为什么送进nand flash的地址忽略了bit8,纵观整个for(i) 循环,i并不是一个随机的地址,而应该是每一页的首地址。其实nand flash并不是忽略了bit8这个地址,而是bit8早就被定下来了,就是上面的NFCMD = 0;语句,(K9F1208U0B)支持从半页开始读取,从而它有两个读的命令,分别是0x00(从一页的上半页开始读) 和 0x01(从一页的下半页开始读),当取0x00时,bit8=0,当取0x01时 bit8=1*/ ??????? NFADDR = i & 0xff; ??????? NFADDR = (i >> 9) & 0xff; ??????? NFADDR = (i >> 17) & 0xff; ??????? NFADDR = (i >> 25) & 0xff; ? ??????? NAND_DETECT_RB; ? ??????? for(j=0; j < NAND_SECTOR_SIZE; j++,i++) { ??????????? *buf = (NFDATA & 0xff); ??????????? buf++; ??????? } ??? } ??? NAND_CHIP_DISABLE; ??? return 0; } ? 3.修改board/liao/liao2440/Makefile文件 ...... OBJS := liao2440.o nand_read.o flash.o ...... ? 4.修改include/configs/liao2440.h文件 在文件末尾添加定义 /*2410 2440 nand flash控制寄存器不同,不能混用*/ /* ?* Nandflash Boot ?*/ #define CONFIG_S3C2440_NAND_BOOT 1 #define STACK_BASE??? 0x33f00000 #define STACK_SIZE??? 0x8000 //#define UBOOT_RAM_BASE??? 0x33f80000 /* NAND Flash Controller */ #define NAND_CTL_BASE??????? 0x4E000000 #define bINT_CTL(Nb)??????? __REG(INT_CTL_BASE + (Nb)) /* Offset */ #define oNFCONF??????????? 0x00 #define oNFCONT??????????? 0x04 #define oNFCMD??????????? 0x08 #define oNFADDR??? ????????0x0c #define oNFDATA??????????? 0x10 #define oNFSTAT??????????? 0x20 #define oNFECC??????????? 0x2c ? /* GPIO */ #define GPIO_CTL_BASE??????? 0x56000000 #define oGPIO_F??????????? 0x50 #define oGPIO_CON?????? 0x0?? /* R/W,Configures the pins of the port */ #define oGPIO_DAT??????? 0x4??? /* R/W,??? Data register for port */ #define oGPIO_UP??????? 0x8??? /* R/W,Pull-up disable register */ # endif??? /* __CONFIG_H */ ? 5.修改board/liao/liao2440/lowlevel_init.S文件 依照开发板的内存区的配置情况,修改board/liao/liao2440/lowlevel_init.S文件 ...... /* REFRESH parameter */ #define REFEN???????????? 0x1??? /* Refresh enable */ #define TREFMD???????????? 0x0??? /* CBR(CAS before RAS)/Auto refresh */ #define Trp???????????? 0x2??? /* 4clk */ #define Trc???????????? 0x3??? /* 7clk */ #define Tchr???????????? 0x2??? /* 3clk */ #define REFCNT???????????? 1012??? ...... /*到这里第一阶段配置全部完成,下面就是C函数初始化配置*/ ? 6 修改board/liao/liao2440/liao2440.c 修改其对GPIO和PLL的配置,参阅开发板硬件说明和2440芯片手册 ...... #elif FCLK_SPEED==1??????? /* Fout = 405MHz */ //#define M_MDIV??? 0x5c //#define M_PDIV??? 0x4 //#define M_SDIV??? 0x0 #define M_MDIV??? 0x7f #define M_PDIV??? 0x2 #define M_SDIV??? 0x1 ...... #elif USB_CLOCK==1 //#define U_M_MDIV??? 0x48 //#define U_M_PDIV??? 0x3 #define U_M_MDIV??? 0x38 #define U_M_PDIV??? 0x2 #define U_M_SDIV??? 0x2 ...... ? /* set up the I/O ports */ gpio->GPACON = 0x007FFFFF; …… // gpio->GPFCON = 0x000055AA; gpio->GPFCON = 0x5500; /*for LED*/ ...... /* arch number of S3C2440 -Board */ gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ; /* adress of boot parameters */ gd->bd->bi_boot_params = 0x30000100; icache_enable(); dcache_enable(); gpio->GPFDAT = 0xc0; /*for LED*/ ? return 0; ? 7. 实现NAND Flash的读写,再次修改/include/configs/liao2440.h ...... /* ?* High Level Configuration Options ?* (easy to change) ?*/ #define CONFIG_ARM920T??????? 1??? /* This is an ARM920T Core??? */ //#define CONFIG_S3C2410????? ??1??? /* in a SAMSUNG S3C2410 SoC???? */ //#define CONFIG_SBC2410X????? 1??? /* on a friendly-arm SBC-2410X Board? */ #define??? CONFIG_S3C2440????? 1??? /* in a SAMSUNG S3C2440 SoC???? */ #define CONFIG_liao2440??? ?1? ??/* on a SAMSUNG liao2440 Board? */ /*很多地方调用CONFIG_S3C2440,在这里定义 CONFIG_liao2440是针对本开发板配置的宏控制*/ ...... /*********************************************************** ?* 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_DHCP???? | / ??????????? CFG_CMD_ELF) ? /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include <cmd_confdefs.h> …… #define??? CFG_LONGHELP??????????????? /* undef to save memory??????? */ #define??? CFG_PROMPT?? "[liao2440]#"??????? /*Monitor Command Prompt? */ #define??? CFG_CBSIZE??????? 256???????????????? /* Console I/O Buffer Size??? */ …… #undef? CFG_CLKS_IN_HZ????????????? /* everything,incl board info,in Hz */ #define??? CFG_LOAD_ADDR???????????? 0x30008000??? /* default load address?? */ /*linux kernel放在这里执行*/ /* the PWM TImer 4 uses a counter of 15625 for 10 ms,so we need */ …… /* timeout values are in ticks */ #define CFG_FLASH_ERASE_TOUT?? (5*CFG_HZ) /* Timeout for Flash Erase */ #define CFG_FLASH_WRITE_TOUT? (5*CFG_HZ) /* Timeout for Flash Write */ //#define? CFG_ENV_IS_IN_FLASH??? 1 #define??? CFG_ENV_IS_IN_NAND??? 1 #define CFG_ENV_OFFSET? 0X20000 #define CFG_NAND_LEGACY /*注意:网上很多地方都有关于CONFIG_CMD_NAND 、CFG_NAND_LEGACY、drivers/mtd/nand/nand.c中的nand_init()函数以及board/qljt/qljt2440/qljt2440.c中的nand_init()函数这四个东西的关系,请参考附录。*/ #define CFG_ENV_SIZE??? 0x10000?? /* Total Size of Environment Sector */ /*---------------------------------------------------------------------- ?* NAND flash settings ?*/ #if (CONFIG_COMMANDS & CFG_CMD_NAND) #define CFG_NAND_BASE 0x4E000000?? /* NandFlash控制器在SFR区起始寄存器地址 */ #define CFG_MAX_NAND_DEVICE 1 #define SECTORSIZE 512?????????????? /* 1页的大小 */ #define NAND_SECTOR_SIZE SECTORSIZE #define NAND_BLOCK_MASK 511????????? /* 页掩码 */ /*在其它地方定义过,留着也不碍事*/ ? #define ADDR_COLUMN 1? ??????????????/* 一个字节的Column地址 */ #define ADDR_PAGE 3????????????????? /* 3字节的页块地址*/ #define ADDR_COLUMN_PAGE 4?????????? /* 总共4字节的页块地址*/ ? #define NAND_ChipID_UNKNOWN 0x00???? /* 未知芯片的ID号 */ #define NAND_MAX_FLOORS 1 #define NAND_MAX_CHIPS 1???????????? /* Nand Flash命令层底层接口函数 */ ? //#define NAND_WAIT_READY(nand) NF_WaitRB() //#define NAND_DISABLE_CE(nand)? NF_SetCE(NFCE_HIGH) //#define NAND_ENABLE_CE(nand)?? NF_SetCE(NFCE_LOW) //#define WRITE_NAND_COMMAND(d,adr)??? NF_Cmd(d) //#define WRITE_NAND_COMMANDW(d,adr) NF_CmdW(d) //#define WRITE_NAND_ADDRESS(d,adr)????? NF_Addr(d) //#define WRITE_NAND(d,adr)????????? NF_Write(d) //#define READ_NAND(adr)?????????????? NF_Read() ? #define WRITE_NAND_COMMAND(d,adr) {rNFCMD = d;} #define WRITE_NAND_ADDRESS(d,adr) {rNFADDR = d;} #define WRITE_NAND(d,adr) {rNFDATA = d;} #define READ_NAND(adr) (rNFDATA) #define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));} #define NAND_DISABLE_CE(nand) {rNFCONT |= (1<<1);} #define NAND_ENABLE_CE(nand) {rNFCONT &= ~(1<<1);} #define WRITE_NAND_COMMANDW(d,adr) NF_CmdW(d) /* the following functions are NOP's because S3C24X0 handles this in hardware */ #define NAND_CTL_CLRALE(nandptr) #define NAND_CTL_SETALE(nandptr) #define NAND_CTL_CLRCLE(nandptr) #define NAND_CTL_SETCLE(nandptr) #define CONFIG_MTD_NAND_VERIFY_WRITE 1 …… #define rNFCONF (*(volatile unsigned int *)0x4e000000) #define rNFCONT (*(volatile unsigned int *)0x4e000004) #define rNFCMD (*(volatile unsigned char *)0x4e000008) #define rNFADDR (*(volatile unsigned char *)0x4e00000c) #define rNFDATA (*(volatile unsigned char *)0x4e000010) #define rNFSTAT (*(volatile unsigned int *)0x4e000020) #define rNFECC (*(volatile unsigned int *)0x4e00002c) ? #endif???? /* __CONFIG_H */ ? 8.在一些文件中添加CONFIG_S3C2440,使得原来s3c2410代码可以编译进来 8.1 /include/common.h文件的第454行: #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440) ? 8.2 /include/s3c24x0.h文件的第85、95、99、110、148、404行: #if defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) ? 8.3 /cpu/arm920t/s3c24x0/interrupts.c文件的第33、38行: #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440) ? #elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) ? 8.4 /cpu/arm920t/s3c24x0/serial.c文件的第22、26行: #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440) #elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) void serial_setbrg (void) { ???????? S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); ???????? int i; ???????? unsigned int reg = 0; ? ???????? /* value is calculated so : (int)(PCLK/16./baudrate) -1 */ ???????? reg = get_PCLK() / (16 * gd->baudrate) - 1; ???????? /* FIFO enable,Tx/Rx FIFO clear */ ???????? uart->UFCON = 0x00; ???????? uart->UMCON = 0x0; ???????? /* Normal,No parity,1 stop,8 bit */ ???????? uart->ULCON = 0x3; ...... } ? 8.5 /cpu/arm920t/s3c24x0/speed.c文件的第33、37行: #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440) #elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) ? static ulong get_PLLCLK(int pllreg) { ??? ...... ? ??? m = ((r & 0xFF000) >> 12) + 8; ??? p = ((r & 0x003F0) >> 4) + 2; ??? s = r & 0x3; #if defined(CONFIG_S3C2440) ?? ?if (pllreg == MPLL) ??? return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); ? ??else if (pllreg == UPLL) #endif ??? return((CONFIG_SYS_CLK_FREQ * m) / (p << s)); } ? /* return FCLK frequency */ ulong get_FCLK(void) { ??? return(get_PLLCLK(MPLL)); } ? /* return HCLK frequency */ ulong get_HCLK(void) { ??? S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); ?? ?if (clk_power->CLKDIVN & 0x6)??? ??? { ?????? ?/*CAMDIVN 在12中定义*/ ?? ? ?if ((clk_power->CLKDIVN & 0x6)==2)????? ????????????? return(get_FCLK()/2); ???? if ((clk_power->CLKDIVN & 0x6)==6)?????? ????????????? return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 : get_FCLK()/3);???????? ?????? ?if ((clk_power->CLKDIVN & 0x6)==4)??????? ????????????? return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 : get_FCLK()/4);???????? ?????? ?return(get_FCLK()); ??? } ??? else?????? ??? { ?????? ?????? return(get_FCLK()); ??? } ??? //return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK()); } ? 8.6 /cpu/arm920t/s3c24x0/usb_ohci.c文件的第45行: #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) /*i2c没用到,文件还没修改*/ ? 8.7 /rtc/s3c24x0_rtc.c文件的第35行: #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) ? 8.8 /cpu/arm920t/s3c24x0/interrupts.c文件的第181行:? defined(CONFIG_VCMA9) || defined(CONFIG_liao2440) /*添加defined(CONFIG_liao2440),使得原来sbc2410X的代码可以编译进来*/ ? 9.在include/linux/mtd/nand_ids.h的结构体nand_flash_ids加入 static struct nand_flash_dev nand_flash_ids[] = { ...... ??? {"Samsung KM29N16000",NAND_MFR_SAMSUNG,0x64,21,1,2,0x1000,0}, ??? {"Samsung K9F1208U0B",? NAND_MFR_SAMSUNG,0x76,26,3,0x4000, ??? {"Samsung unknown 4Mb",0x6b,22,0x2000, ...... }; /*下面说说上面结构体的8个参数是怎么得出来的,以便日后再次移植的时候会更换nand flash*/ ? /* 1.“厂家 型号”:这个从nand flash的datasheet就可以直接找到了吧。 2. 生产商的编号:也就是datasheet里面的Maker code,它也同时被存放在nand flash里面的ID(nand flash应该有一个读ID命令的)信息里面)。 3. 本模块的编号:也就是datasheet里面的device code,跟Maker code一样它也被放到ID信息里面。 4. 总共容纳的地址位数:也就是有效的地址位数。针对于本flash(K9F1208U0M)可以参考它的datasheet第7页。 5. 一页所存储的字节数是否为256个:针对于本flash(K9F1208U0M)可以参考它的datasheet第7页。 6. 地址需要多少字节数减一(行列地址总共):举个例子可能更容易明白,第4点中可以知道本flash(K9F1208U0M)有26位,而对本flash地址的写入每次只能写8位,所以至少要写4次才能把26位地址写入本flash,4次的写入针对于编程来说就是[0:3],所以本falsh相对于该结构体的该变量的值是3. 7. 擦除1个block的大小:简单来说就是1个block的大小,本flash 1block=32 pages,1 page=512 bytes,所以 1 block=512x32=16 k-bytes,也就是0x4000。 8. 是否为16位总线:本flash地址和数据总线共用,都是8位的,所以上面值为0 */ ? 10.修改lib_arm/board.c ...... #include <common.h> #include <command.h> #include <malloc.h> #include <devices.h> #include <version.h> #include <net.h> #include <s3c2410.h> ...... static int display_banner (void) { ?????? S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); ??????? gpio->GPFDAT = 0x80; /*在串口初始化和console初始化完成,串口输出信息之前,LED1、LED2、LED3会亮起*/ ?????? printf ("/n/n%s/n/n",version_string); ?????? debug ("U-Boot code: %08lX -> %08lX? BSS: -> %08lX/n", ?????? ?????? _armboot_start,_bss_start,_bss_end); ?????? printf ("U-Boot code: %08lX -> %08lX? BSS: -> %08lX/n",_bss_end); #ifdef CONFIG_MODEM_SUPPORT ?????? debug ("Modem Support enabled/n"); #endif #ifdef CONFIG_USE_IRQ ?????? debug ("IRQ Stack: %08lx/n",IRQ_STACK_START); ?????? debug ("FIQ Stack: %08lx/n",FIQ_STACK_START); #endif ? ?????? return (0); } …… void start_armboot (void) { ???????? init_fnc_t **init_fnc_ptr; ???????? char *s; #ifndef CFG_NO_FLASH ???????? ulong size; #endif ? #if defined(CONFIG_VFD) || defined(CONFIG_LCD) ???????? unsigned long addr; #endif ? ???????? S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); ...... ? ?????? ??gpio->GPBDAT = 0x00; /*在进入命令提示符之前,四个LED会同时亮起*/ ???????? /* main_loop() can return to retry autoboot,if so just run it again. */ ???????? for (;;) { ?????????????????? main_loop (); ???????? } ???????? /* NOTREACHED - no way out of command loop except booting */ } ? 11.修改common/env_nand.c #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,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_SIZE,0))?? ????????????? return 1; ? ?????? puts ("Writing to Nand... "); ?????? total = CFG_ENV_SIZE; ?????? //ret = nand_write(&nand_info[0],&total,(u_char*)env_ptr); ?????? ret = nand_legacy_rw(nand_dev_desc + 0, ????????????? 0x00 | 0x02, ????????????? &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],0x01 | 0x02, ????????????? CFG_ENV_SIZE,(u_char*)env_ptr); ? ??? if (ret || total != CFG_ENV_SIZE) ????????????? return use_default(); ? 12. /board/liao/liao2440/liao2440.c文件末尾添加NAND Flash初始化函数 u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nand/nand.c中的nand_init();否则调用自己在board/liao/liao2440/liao2440.c中的nand_init()函数。这里我选择第二种方式。 #if (CONFIG_COMMANDS & CFG_CMD_NAND) typedef enum { NFCE_LOW, NFCE_HIGH } NFCE_STATE; static inline void NF_Conf(u16 conf) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? nand->NFCONF = conf; } static inline void NF_Cont(u16 cont) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? nand->NFCONT = cont; } static inline void NF_Cmd(u8 cmd) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? nand->NFCMD = cmd; } static inline void NF_CmdW(u8 cmd) { ?????? NF_Cmd(cmd); ?????? udelay(1); } static inline void NF_Addr(u8 addr) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? nand->NFADDR = addr; } static inline void NF_SetCE(NFCE_STATE s) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? switch (s) { ????????????? case NFCE_LOW: ???????????????????? nand->NFCONT &= ~(1<<1); ???????????????????? break; ? ????????????? case NFCE_HIGH: ???????????????????? nand->NFCONT |= (1<<1); ???????????????????? break; ????????????? ??? } } static inline void NF_WaitRB(void) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? while (!(nand->NFSTAT & (1<<0))); } static inline void NF_Write(u8 data) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? nand->NFDATA = data; } static inline u8 NF_Read(void) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? return(nand->NFDATA); } static inline void NF_Init_ECC(void) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? nand->NFCONT |= (1<<4); } static inline u32 NF_Read_ECC(void) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? return(nand->NFECC); }???? #endif ? #if (CONFIG_COMMANDS & CFG_CMD_NAND) ?????? extern ulong nand_probe(ulong physadr); ? static inline void NF_Reset(void) { ?????? int i; ?????? NF_SetCE(NFCE_LOW); ?????? NF_Cmd(0xFF); /* reset command */ ?????? for(i = 0; i < 10; i++); /* tWB = 100ns. */ ?????? NF_WaitRB(); /* wait 200~500us; */ ?????? NF_SetCE(NFCE_HIGH); } static inline void NF_Init(void) { #if 0 /* a little bit too optimistic */ ?????? #define TACLS 0 ?????? #define TWRPH0 3 ?????? #define TWRPH1 0 #else ?????? #define TACLS 0 ?????? #define TWRPH0 4 ?????? #define TWRPH1 2 #endif ??? NF_Conf((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)); ?????? NF_Cont((1<<6)|(1<<4)|(1<<1)|(1<<0)); //nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8) |(TWRPH0<<4)|(TWRPH1<<0); /* 1 1 1 1,1 xxx,r xxx,r xxx */ /* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */ ?????? NF_Reset(); } void nand_init(void) { ?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); ?????? NF_Init(); #ifdef DEBUG ?????? printf("NAND flash probing at 0x%.8lX/n",(ulong)nand); #endif ?????? printf ("%4lu MB/n",nand_probe((ulong)nand) >> 20); } #endif ? 13. /include/s3c24x0.h加入2440 NAND Flash寄存器定义和CAMDIVN定义 ...... typedef struct { ???????? S3C24X0_REG32?? LOCKTIME; ???????? S3C24X0_REG32?? MPLLCON; ???????? S3C24X0_REG32?? UPLLCON; ???????? S3C24X0_REG32?? CLKCON; ???????? S3C24X0_REG32?? CLKSLOW; ???????? S3C24X0_REG32?? CLKDIVN; ???????? S3C24X0_REG32?? CAMDIVN; } /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER; ...... #if defined(CONFIG_S3C2410) /* NAND FLASH (see S3C2410 manual chapter 6) */ typedef struct { ???????? S3C24X0_REG32?? NFCONF; ???????? S3C24X0_REG32?? NFCMD; ???????? S3C24X0_REG32?? NFADDR; ?? ??????S3C24X0_REG32?? NFDATA; ???????? S3C24X0_REG32?? NFSTAT; ???????? S3C24X0_REG32?? NFECC; } /*__attribute__((__packed__))*/ S3C2410_NAND; #endif #if defined (CONFIG_S3C2440) /* NAND FLASH (see S3C2440 manual chapter 6) */ typedef struct { ???????? S3C24X0_REG32?? NFCONF; ???????? S3C24X0_REG32?? NFCONT; ???????? S3C24X0_REG32?? NFCMD; ???????? S3C24X0_REG32?? NFADDR; ???????? S3C24X0_REG32?? NFDATA; ???????? S3C24X0_REG32?? NFMECC0; ???????? S3C24X0_REG32?? NFMECC1; ???????? S3C24X0_REG32?? NFSECC; ?? ??????S3C24X0_REG32?? NFSTAT; ???????? S3C24X0_REG32?? NFESTAT0; ???????? S3C24X0_REG32?? NFESTAT1; ???????? S3C24X0_REG32?? NFECC; } /*__attribute__((__packed__))*/ S3C2410_NAND; #endif ? 14.DM9000网卡移植 修改/include/configs/liao2440.h /* ?* 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 */ /* CONFIG_DM9000_BASE参数根据开发板设置*/ #define CONFIG_DRIVER_DM9000 1 #define CONFIG_DM9000_BASE 0x18000300 #define DM9000_IO CONFIG_DM9000_BASE #define DM9000_DATA (CONFIG_DM9000_BASE+4) #define CONFIG_DM9000_USE_16BIT 修正drivers/dm9000x.c中两个BUG 网卡MAC地址错误的解决方法 /* Initilize dm9000 board*/ int eth_init(bd_t * bd) { ??? ...... ??? /* Set Node address */ ??? /* for (i = 0; i < 6; i++) ??????? ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);*/ ??? char *tmp = getenv ("ethaddr"); ??? char *end; ??? for (i=0; i<6; i++) ??? { ??????? bd->bi_enetaddr[i] = tmp ? simple_strtoul(tmp,&end,16) : 0; ?? ?????if (tmp) ??????????? tmp = (*end) ? end+1 : end; ??? } /*屏蔽原有获取MAC地址的语句,替换成从U-Boot的参数区读取数据并存到bd->bi_enetaddr[i] */ ??? printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x/n",bd->bi_enetaddr[0], ?????????? bd->bi_enetaddr[1],bd->bi_enetaddr[2],bd->bi_enetaddr[3], ?????????? bd->bi_enetaddr[4],bd->bi_enetaddr[5]); ...... /* Initilize dm9000 board*/ int eth_init(bd_t * bd) { ??? ...... ??? DM9000_iow(DM9000_RCR,RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);??? /* RX enable */ ??? DM9000_iow(DM9000_IMR,IMR_PAR);??? /* Enable TX/RX interrupt mask */ #if 0 ??? i = 0; ??? while (!(phy_read(1) & 0x20)) {??? /* autonegation complete bit */ ??????? udelay(1000); ??????? i++; ??????? if (i == 10000) { ??????????? printf("could not establish link/n"); ??????????? return 0; ??????? } ??????? printf(" link=%d/n",i); ??? } ? ??? /* see what we've got */ ??? lnk = phy_read(17) >> 12; ??? printf("operating at "); ??? switch (lnk) { ??? case 1: ??????? printf("10M half duplex "); ??????? break; ??? case 2: ??????? printf("10M full duplex "); ??????? break; ??? case 4: ??????? printf("100M half duplex "); ??????? break; ??? case 8: ??????? printf("100M full duplex "); ??????? break; ??? default: ??????? printf("unknown: %d ",lnk); ??????? break; ??? } ??? printf("mode/n"); #endif /*could not establish link提示和慢响应的解决方法*/ ??? return 0; } YC2440的网卡是DM9000AEP,暂时还有点问题,后面继续研究。 ? 三、交叉编译U-Boot # cd u-boot # make 如何利用已有U-Boot在SDRAM调试U-Boot 1 board/liao/liao2440/config.mk文件中修改TEXT_BASE=0x33000000,避免新的U-Boot与原来重复。 2 cpu/arm920t/start.S中屏蔽cpu_init_crit,此函数会将SDRAM清空一次,后果可想而知 #ifndef CONFIG_SKIP_LOWLEVEL_INIT @bl cpu_init_crit #endif 3 在1.4节中加入一段代码,判断U-Boot是否在SDRAM,从而是否需要拷贝 @ 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 ? @ test uboot on sdram so decided whether need copy ? adr r0,_start ? ldr r1,_TEXT_BASE ? cmp r0,r1 ? beq stack_setup ? @ 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 4 启动原来的U-Boot,调试新的 # tftp 33000000 u-boot.bin # go 33000000 ? ? 附录: 1.在u-boot-1.3.1前(不含u-boot-1.3.1)nand_init函数的调用关系,它的调用是被“CONFIG_COMMANDS&CFG_CMD_NAND”和“CFG_NAND_LEGACY”控制的,1:表示该值为真,0:表示该值为假 A :/drivers/mtd/nand/nand.c中的nand_init()函数 B :/board/liao/liao2440/liao2440.c中的nand_init()函数
2.在u-boot-1.3.1后(含u-boot-1.3.1)nand_init函数的调用关系,它的调用是被“CONFIG_CMD_NAND”和“CFG_NAND_LEGACY”控制的。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |