第一部分
根据uboot-2008.10,移植出能在mini2440 nor flash上运行的uboot
1 修改Makefile:
在uboot-2008.10顶层目录中的Makefile中,参考smdk2410_config,添加新的配置选项。 # add,flyriz
mini2440_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
2 修改cpu/arm920t/start.S: 2.1添加支持S3C2440的编译条件
/* #if defined(CONFIG_S3C2400)||defined(CONFIG_S3C2410) */
/*modify,flyriz*/
#if defined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
2.2添加S3C2440寄存器的定义 #else
# define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* clock divisor register */ # endif
/*add,flyriz,for 2440,register define*/
#define CLK_CTL_BASE 0x4C000000 #define MDIV_405 0x7f<<12 #define PSDIV_405 0x21
#define UPLL_MDIV_48 0x38<<12 #define UPLL_PSDIV_48 0x22 #define MDIV_200 0xa1<<12 #define PSDIV_200 0x31 /****************************/
2.3修改中断禁止代码
# if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif
/*add,flyriz*/
# if defined(CONFIG_S3C2440) ldr r1, =0x7fff /* S3C2440有15个子中断[0...14] */ ldr r0, =INTSUBMSK str r1, [r0] # endif
2.4 修改时钟设置
/********************
* FCLK:HCLK:PCLK = 1:2:4 *
* default FCLK is 120 MHz ! * ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] #endif * CONFIG_S3C2400 || CONFIG_S3C2410 * ********************/
/*modify,flyriz*/
#if defined(CONFIG_S3C2440) /*FCLK:HCLK:PCLK=1:4:8*/ ldr r0,=CLKDIVN mov r1,#5 str r1,[r0] mrc p15,0,r1,c1,c0,0 /* CP15中的寄存器C1是一个控制寄存器,用于配置MMU中的一些操作 */
orr r1,r1,#0xc0000000 mcr p15,0,r1,c1,c0,0 mov r1,#CLK_CTL_BASE /* 0x4C000000 LOCKTIME:PLL lock time counter */ mov r2,#UPLL_MDIV_48 add r2,r2,#UPLL_PSDIV_48 str r2,[r1,#0x08] /* 0x4C000008 UPLLCON=0x38<<12||0x22,output 48MHz */ mov r2,#MDIV_405 add r2,r2,#PSDIV_405 str r2,[r1,#0x04] /* 0x4C000004 MPLLCON=0x7f<<12||0x21,output 405MHz */ #else ldr r0,=CLKDIVN mov r1,#3 str r1,[r0] mrc p15,0,r1,c1,c0,0 orr r1,r1,#0xc0000000 mcr p15,0,r1,c1,c0,0 mov r1,#CLK_CTL_BASE mov r2,#MDIV_200 add r2,r2,#PSDIV_200 str r2,[r1,#0x04] #endif
#endif /*CONFIG_S3C2400||CONFIG_S3C2410||CONFIG_S3C2440*/ /**********************************************************/
3 修改cpu/arm920t/s3c24x0/interrupts.c
3.1 在条件编译的宏定义里加入对s3c2440的支持:
/* #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */
/*modify,flyriz*/
#if defined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)||defined(CONFIG_TRAB)
/* #elif defined(CONFIG_S3C2410) */ /*modify,flyriz*/
#elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
3.2 在get_tbclk函数中,添加对mini2440的支持:
#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB) tbclk = timer_load_val * 100; #elif defined(CONFIG_SBC2410X) || \\ defined(CONFIG_SMDK2410) || \\ defined(CONFIG_MINI2440) || \\
defined(CONFIG_VCMA9) /*modify,flyriz,add:CONFIG_MINI2440*/ tbclk = CFG_HZ; /*get_tbclk函数的作用?CFG_HZ又是什么?*/
4 修改cpu/arm920t/s3c24x0/speed.c
4.1 在条件编译的宏定义里加入对s3c2440的支持:
/*#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410)|| defined (CONFIG_TRAB)*/ /*modify,flyriz*/
#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_S3C2440) || defined (CONFIG_TRAB)
/*#elif defined(CONFIG_S3C2410)*/ /*modify,flyriz*/
#elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
4.2 修改get_PLLCLK函数: m = ((r & 0xFF000) >> 12) + 8; p = ((r & 0x003F0) >> 4) + 2; s = r & 0x3;
/*add,flyriz*/
#if defined(CONFIG_S3C2440) if(pllreg==MPLL) return ((CONFIG_SYS_CLK_FREQ*m*2)/(p<4.3 修改get_HCLK函数: ulong get_HCLK(void) {
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); /*return ((clk_power->CLKDIVN&0x2)?get_FCLK()/2:get_FCLK()); delete,flyriz*/ /*add,flyriz*/ #if defined(CONFIG_S3C2440) if(clk_power->CLKDIVN & 0x6) { 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()); #else return ((clk_power->CLKDIVN&0x2)?get_FCLK()/2:get_FCLK()); #endif }
5 修改include/asm-arm/mach-types.h,添加mini2440的机器ID(必须与内核提供的ID保持一致): #define MACH_TYPE_GENEVA 1873
#define MACH_TYPE_MINI2440 1999 /*add,flyriz,mini2440机器ID,必须与内核提供的ID相同*/
6 修改cpu/arm920t/s3c24x0/serial.c
/*#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)*/ /*modify,flyriz*/
#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_S3C2440) || defined (CONFIG_TRAB)
/*#elif defined(CONFIG_S3C2410)*/ /*modify,flyriz*/
#elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
7 修改drivers/rtc/s3c24x0_rtc.c /* #elif defined(CONFIG_S3C2410) */
#elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440) /*modify,flyriz*/
8 修改include/s3c24x0.h /*#ifdef CONFIG_S3C2410*/
#if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440) /*modify,flyriz*/ (所有ifdef CONFIG_S3C2410全部替换)
/* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) */ /* (see S3C2410 manual chapter 7) */ typedef struct { S3C24X0_REG32 LOCKTIME; S3C24X0_REG32 MPLLCON; S3C24X0_REG32 UPLLCON; S3C24X0_REG32 CLKCON; S3C24X0_REG32 CLKSLOW; S3C24X0_REG32 CLKDIVN; /*add,flyriz*/
#if defined(CONFIG_S3C2440) S3C24X0_REG32 CAMDIVN; /*增加CAMDIVN的定义*/ #endif
} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;
9 为开发板新建一个目录
在board目录中新建一个目录mini2440,将board/smdk2410下的所有文件拷贝到board/mini2440中,然后对mini2440中的文件做修改:将smdk2410.c改为mini2440.c;将Makefile中的代码COBJS :=smdk2410.o flash.o 改为COBJS :=mini2440.o flash.o
10 修改board/mini2440/mini2440.c 10.1 修改PLL的配置 /***************** #elif FCLK_SPEED==1 // Fout = 202.8MHz #define M_MDIV 0xA1 #define M_PDIV 0x3 #define M_SDIV 0x1 #endif
#define USB_CLOCK 1*/
/*modify,flyriz*/
#elif FCLK_SPEED==1
#if defined(CONFIG_S3C2410) /*Fout=202.8MHz*/
#define M_MDIV 0xA1 #define M_PDIV 0x3 #define M_SDIV 0x1 #endif
#if defined(CONFIG_S3C2440) /*Fout=405MHz*/
#define M_MDIV 0x7f #define M_PDIV 0x2
#define M_SDIV 0x1 #endif #endif
#define USB_CLOCK 1 /*****************/
10.2 修改UPLL的配置 /*************** #if USB_CLOCK==0
#define U_M_MDIV 0xA1 #define U_M_PDIV 0x3 #define U_M_SDIV 0x1 #elif USB_CLOCK==1 #define U_M_MDIV 0x48 #define U_M_PDIV 0x3 #define U_M_SDIV 0x2 #endif*/
/*modify,flyriz*/ #if USB_CLOCK==0
#define U_M_MDIV 0xA1 #define U_M_PDIV 0x3 #define U_M_SDIV 0x1 #elif USB_CLOCK==1
#if defined(CONFIG_S3C2410) #define U_M_MDIV 0x48 #define U_M_PDIV 0x3 #endif
#if defined(CONFIG_S3C2440) #define U_M_MDIV 0x38 #define U_M_PDIV 0x2 #endif
#define U_M_SDIV 0x2 #endif
/*****************/
10.3 修改board_init函数,以引导内核 /* arch number of SMDK2410-Board */ /* gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; */ /*modify,flyriz*/ gd->bd->bi_arch_number = MACH_TYPE_MINI2440;
11 修改board/mini2440/lowlevel_init.S中REFRESH的刷新周期 /* REFRESH parameter */ #define REFEN 0x1 /* Refresh enable */ #define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */ /* #define Trp 0x0 2clk */ /*modify,flyriz*/ #define Trp 0x2 /* 4clk */
#define Trc 0x3 /* 7clk */ #define Tchr 0x2 /* 3clk */ /* #define REFCNT 1113 period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */ /*modify,flyriz*/ #define REFCNT 1012 /**************************************/
12 添加并修改配置文件
为开发板添加新的配置文件,复制include/configs/smdk2410.h,另存为include/configs/mini2440.h,并对其进行修改 12.1 添加s3c2440的宏定义 #define CONFIG_ARM920T 1 /* This is an ARM920T Core */ /* #define CONFIG_S3C2410 1 in a SAMSUNG S3C2410 SoC */ /* #define CONFIG_SMDK2410 1 on a SAMSUNG SMDK2410 Board */ /*modify,flyriz*/
#define CONFIG_S3C2440 1 #define CONFIG_MINI2440 1
12.2 修改命令提示符
#defineCFG_LONGHELP /* undef to save memory */ /* #define CFG_PROMPT \"SMDK2410 # \" Monitor Command Prompt */ /*modify,flyriz*/
#define CFG_PROMPT \"Mini2440 # \"
一个具备基本功能的UBOOT代码修改部分已经完成。
第二部分
基于第一部分的修改,完成网卡驱动部分的修改。 1 修改配置文件include/configs/mini2440.h
1.1屏蔽原来的网卡配置,添加对DM9000的配置 /*modify,flyriz,shield this part*/ #if 0
#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 */ #endif
/*add,flyriz,DM9000*/
#define CONFIG_DRIVER_DM9000 1 #define CONFIG_DM9000_USE_16BIT 1 #define CONFIG_DM9000_BASE 0x20000300 #define DM9000_IO 0x20000300 #define DM9000_DATA 0x20000304 /****************************************/
1.2添加对ping命令的支持 #define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE #define CONFIG_CMD_ELF
/*add,flyriz,PING CMD*/ #defineCONFIG_CMD_PING
2 修改网卡驱动drivers\\net\\dm9000x.c
/*delete,flyriz*/ #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; } } /* 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 \ break; } printf(\"mode\\n\"); #endif
网卡驱动的程序修改完成。
第三部分
进一步完成flash驱动移植,实现nor flash的读、写、擦除操作。 1 参考SST39VF1601数据手册,熟悉其工作原理
2 查找移植参考的代码
以board/dave/common/flash.c作为移植参考的代码,并将其拷贝到board/mini2440目录下。
3 移植flash_init函数
3.1 从board/dave/B2/flash.c中拷贝函数flash_init到board/mini2440/flash.c中 /*add,flyriz,flash_init function*/ unsigned long flash_init (void) { unsigned long size_b0; int i; /* Init: no FLASHes known */ for (i=0; i 4 修改flash.c中的flash_get_size()函数 4.1根据FLASH的数据手册,修改ID读取部分的代码 /* Write auto select command: read Manufacturer ID */ /**** addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090; ****/ /*modify,flyriz,Software ID Entry*/ addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA; addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x0055; addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x0090; 4.2在flash.c的开始处添加以下宏定义 #define FLASH_SST1601 0x004B 4.3在flash_get_size函数的device ID匹配部分添加如下代码 ...... value = addr2[CFG_FLASH_READ1]; /* device ID */ switch (value) { case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400T: ...... /*add,flyriz*/ case (CFG_FLASH_WORD_SIZE)SST_ID_xF1601: info->flash_id += FLASH_SST1601; info->sector_count = 32; info->size = 0x00200000; break; /* => 2 MB */ 4.4将flash_get_size函数中倒数第4行代码做如下修改 /* *addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0; */ /* modify,flyriz */ *addr2 = (CFG_FLASH_WORD_SIZE)0x00F0; /* reset bank */ 最后记得要在flash.c的开始处声明flash_get_size()函数。 5 修改擦除函数flash_erase() /* Start erase on unprotected sectors */ for (sect = s_first; sect<=s_last; sect++) { if (info->protect[sect] == 0) { /* not protected */ addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]); if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { /******** addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080; addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; addr2[0] = (CFG_FLASH_WORD_SIZE)0x00500050; ********/ /*modify,flyriz*/ addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA; addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x0055; addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x0080; addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA; addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x0055; addr2[0] = (CFG_FLASH_WORD_SIZE)0x0050; /* block erase */ --------------------------------------- start = get_timer (0); last = start; addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]); /* while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) { */ /* modify,flyriz */ while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x0080) != (CFG_FLASH_WORD_SIZE)0x0080) { if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { printf (\"Timeout\\n\"); return 1; } /* show that we're waiting */ if ((now - last) > 1000) { /* every second */ putc ('.'); last = now; } } DONE: /* reset to read mode */ addr = (CFG_FLASH_WORD_SIZE *)info->start[0]; /* addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; */ /* modify,flyriz */ addr[0] = (CFG_FLASH_WORD_SIZE)0x00F0; /* reset bank */ 6 修改写函数write_word() for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++) { /**** addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;*/ /*modify,flyriz*/ addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA; addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x0055; addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A0; ...... /* while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) != (data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) { */ /* modify,flyriz */ while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x0080) != (data2[i] & (CFG_FLASH_WORD_SIZE)0x0080)) { 7 修改write_buf()函数 将该函数中的所有CONFIG_B2改为CONFIG_MINI2440 8 修改flash_print_info()函数 在switch (info->flash_id & FLASH_TYPEMASK)的判断中增加如下代码: /* add,flyriz */ case FLASH_SST1601: printf (\"SST39VF1601 (16 Mbit, uniform sector size)\\n\"); break; 9 在flash.c的开始部分添加宏定义 #define CFG_FLASH_ADDR0 0x5555 #define CFG_FLASH_ADDR1 0x2AAA #define CFG_FLASH_WORD_SIZE unsigned short #define CFG_FLASH_READ0 0x0000 #define CFG_FLASH_READ1 0x0001 #define CFG_FLASH_READ2 0x0002 /********************************/ 10 修改配置文件include/configs/mini2440.h 屏蔽原来的有关FLASH的宏定义,并添加新的宏定义 /* delete,flyriz */ #if 0 #define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */ #define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */ #endif #ifdef CONFIG_AMD_LV400 #define PHYS_FLASH_SIZE 0x00080000 /* 512KB */ #define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */ #define CONFIG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */ #endif /* add,flyriz */ #define PHYS_FLASH_SIZE 0x00200000 #define CFG_MAX_FLASH_SECT (32) #define CONFIG_ENV_ADDR (CFG_FLASH_BASE+0x030000) #define CFG_MONITOR_BASE TEXT_BASE #define CFG_MONITOR_LEN (256*1024) flash驱动移植的工作已经完成。
因篇幅问题不能全部显示,请点此查看更多更全内容