Live & Learn
分类: 嵌入式
2009-10-08 22:34:05
特别注意:
在u-boot1.3.3及以上版本Makefile有一定的变化,使得对于24x0处理器从nand启动的遇到问题。也就是网上有人说的:无法运行过lowlevel_init。其实这个问题是由于编译器将我们自己添加的用于nandboot的子函数nand_read_ll放到了4K之后造成的(到这不理解的话,请仔细看看24x0处理器nandboot原理)。运行失败后,利用mini2440的4个LED调试发现u-boot根本没有完成自我拷贝,然后看uboot根目录下的System.map文件可知道原因。解决办法其实很简单,将下面这个语句:
__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
改为:
__LIBS := $(subst $(obj),,$(LIBBOARD)) $(subst $(obj),,$(LIBS))
Configuring for yc2410 board...
测试编译:
$ make
测试通过,则说明开发板配置平台搭建没问题,可以进行下一步工作
3. 加入S3C2440相关代码,使得U-BOOT可以在S3C2440上启动
3.1.加入S3C2440的时钟相关的寄存器定义时钟初始化,以使S3C2440工作405Mhz
/cpu/arm920t/start.s中。
(1)删除AT91RM9200使用的LED代码
#include
#include
//#include
......
start_code:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
//bl coloured_LED_init
//bl red_LED_on
(2)修改编译条件支持2440,修改寄存器地址定义
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)|| defined (CONFIG_S3C2440)
(3)修改中断禁止部分
注释掉以前的2410部分 /* # if defined(CONFIG_S3C2410) */ 新的中断部分 #if defined(CONFIG_S3C2410) (4)修改时钟设置(2440的405MHZ) # if defined(CONFIG_S3C2440) mov r2, #UPLL_MDIV_48 /*UPLL */ mov r2, #MDIV_405 /* mpll_405mhz hugerat*/ #else mrc p15, 0, r1, c1, c0, 0 /*read ctrl register hugerat*/ /*now, CPU clock is 202.8 Mhz hugerat*/ # endif //被注释掉以前的。。 (5)在调用start_armboot之前点亮LED #if defined(CONFIG_rat2440_LED) 3.2 lowlevel_init.s(加入S3C2440内存控制寄存器的定义) (1)然后修改 REFRESH 的刷新周期 /* REFRESH parameter */ /**************************************/
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
#define pWTCON 0x15300000
#define INTMSK 0x14400008 /* Interupt-Controller base addresses */
#define CLKDIVN 0x14800014 /* clock divisor register */
#else
#define pWTCON 0x53000000
#define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
#define INTSUBMSK 0x4A00001C
#define CLKDIVN 0x4C000014 / #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
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
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, =INTSUBMSK
str r1, [r0]
#endif
/* FCLK:HCLK:PCLK = 1:4:8 */
ldr r0, =CLKDIVN
mov r1, #5
str r1, [r0]
mrc p15, 0, r1, c1, c0, 0 /*read ctrl register hugerat*/
orr r1, r1, #0xc0000000 /*Asynchronous hugerat*/
mcr p15, 0, r1, c1, c0, 0 /*write ctrl register hugerat*/
/*now, CPU clock is 405.00 Mhz hugerat*/
mov r1, #CLK_CTL_BASE /* hugerat*/
add r2, r2, #UPLL_PSDIV_48
str r2, [r1, #0x08] /*write UPLL first,48MHz */
add r2, r2, #PSDIV_405 /* mpll_405mhz hugerat*/
str r2, [r1, #0x04] /* MPLLCON hugerat */
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 12 MHz ! 在这里U-Boot有一个错误:以为默认时钟为120MHz。其实如果没有添加以下设置FCLK的语句,芯片内部的PLL是无效的,即FCLK为12MHz。S3C24x0的芯片手册说得很明白。*/
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
orr r1, r1, #0xc0000000 /*Asynchronous hugerat*/
mcr p15, 0, r1, c1, c0, 0 /*write ctrl register hugerat*/
mov r1, #CLK_CTL_BASE /* hugerat*/
mov r2, #MDIV_200 /* mpll_200mhz hugerat*/
add r2, r2, #PSDIV_200 /* mpll_200mhz hugerat*/
str r2, [r1, #0x04]
/* 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 */
#endif /*CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440*/
@ LED1 on u-boot stage 1 is ok!
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_B
ldr r2,=0x155aa
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP]
mov r2, #0x1c0
str r2, [r1, #oGPIO_DAT]
#endif
#define REFEN 0x1 /* Refresh enable */
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
//#define Trp 0x0 /* 2clk */
#define Trc 0x3 /* 7clk */
#define Tchr 0x2 /* 3clk */
//#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1- 15.6*60) */
# if defined(CONFIG_S3C2440)
#define Trp 0x2 /* 4clk */
#define REFCNT 1012
#else
#define Trp 0x0 /* 2clk */
#define REFCNT 0x0459
#endif
3.3 修改GPIO,PLL的设置,应注意GPBCON的设置,不要让蜂鸣器
board/mini2440/2440.c
//设置分频系数
#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
//屏蔽不要的代码
/*
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
*/
//USB分频系数
#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_MDIV 0x48
#define U_M_PDIV 0x3
*/
//为连接LED和蜂鸣器的GPIO修改配置寄存器(函数board_init()中):
#if defined(CONFIG_rat2440_LED)
gpio->GPBCON = 0x00055555;
#else
gpio->GPBCON = 0x00044555;
#endif
//屏蔽不要的代码
/*
gpio->GPBCON = 0x00044555;
*/
//为引导linux 内核,修改开发板的类型代码
#if defined(CONFIG_S3C2410)
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
#endif
#if defined(CONFIG_S3C2440)
/* arch number of S3C2440 -Board */
gd->bd->bi_arch_number = MACH_TYPE_mini2440 ;
#endif
/* arch number of SMDK2410-Board */
//gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
//int board_init (void)设置完成后,LED1和LED2会亮起
# if defined(CONFIG_rat2440_LED)
gpio->GPBDAT = 0x180; //hugerat
3.3 设置环境变量 include/configs/mini2440.h
(1)添加对2440的宏定义:
#define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
#define CONFIG_mini2440 1 /* on a SAMSUNG mini2440 Board */
#define CONFIG_mini2440_LED 1 /* Use the LED on Board */
//#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
//#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
/* input clock of PLL */
(2) Nor FLASH environment organization(NOR Flash类型的支持)
//#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
//#if 0
//#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
//#endif
#define CONFIG_AMD_LV800 /*mini2440上用的是1M*16bit的nor flash*/
(3)添加对LED显示代码的支持
# if defined(CONFIG_rat2440_LED)
/* GPIO */
#define GPIO_CTL_BASE 0x56000000
#define oGPIO_B 0x10
#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
3.4 以下文件主要加入CONFIG_S3C2440宏定义以使得编译一些S3C2410的代码,和加入led灯的控制。
以指示u-boot程序进程
(1)/inlcude/s3c24x0.h 文件(定义的结构体)
将所有的“#ifdef CONFIG_S3C2410”改为
//#ifdef CONFIG_S3C2410
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
(2) cpu/arm920t/s3c24x0/interrupts.c
将所有有“#ifdef CONFIG_S3C2410”增加“|| defined(CONFIG_S3C2440)”增加对2440的支持
(3)cpu/arm920t/s3c24x0/serial.c
将所有有“#ifdef CONFIG_S3C2410”增加“|| defined(CONFIG_S3C2440)”增加对2440的支持
(4)cpu/arm920t/s3c24x0/speed.c
(4.1)头文件对S3C2440的支持:
#include
//屏蔽掉
//#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)
//新加入
#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)
#include
#if defined(CONFIG_S3C2400)
#include
//#elif defined(CONFIG_S3C2410)
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#include
#endif
(4.2)由于S3C2410和S3C2440的MPLL、UPLL计算公式不一样,所以get_PLLCLK函数也需要修改:
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));
(4.3) 由于S3C2410和S3C2440的设置方法也不一样,所以get_HCLK函数也需要修改:
ulong get_HCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
#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
//return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
}
/* return PCLK frequency */
(5).cpu/arm920t/s3c24x0/usb_ohci.c
添加对2440的支持
defined(CONFIG_S3C2400) || \
defined(CONFIG_S3C2410) || \
defined(CONFIG_S3C2440) || \
defined(CONFIG_S3C6400) || \
defined(CONFIG_440EP) || \
defined(CONFIG_PCI_OHCI) || \
defined(CONFIG_MPC5200) || \
defined(CFG_OHCI_USE_NPS)
# define OHCI_USE_NPS /* force NoPowerSwitching mode */
#endif
(6)cpu/arm920t/s3c24x0/i2c.c
#include
//#elif defined(CONFIG_S3C2410)
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#include
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
//#ifdef CONFIG_S3C2410
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
return (gpio->GPEDAT & 0x8000) >> 15;
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
//#ifdef CONFIG_S3C2410
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
gpio->GPEDAT = (gpio->GPEDAT & ~0x4000) | (x&1) << 14;
#endif
if ((status & I2CSTAT_BSY) || GetI2CSDA () == 0) {
//#ifdef CONFIG_S3C2410
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
ulong old_gpecon = gpio->GPECON;
#endif
/* bus still busy probably by (most) previously interrupted transfer */
//#ifdef CONFIG_S3C2410
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
/* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */
/* restore pin functions */
//#ifdef CONFIG_S3C2410
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
gpio->GPECON = old_gpecon;
#endif
(7) /cpu/arm920t/s3c24x0/usb.c
修改头文件的引用:
#if defined(CONFIG_S3C2400)
# include
//#elif defined(CONFIG_S3C2410)
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
# include
#endif
(8) /drivers/usb/usb_ohci.c
修改头文件的引用:
#if defined(CONFIG_S3C2400)
# include
//#elif defined(CONFIG_S3C2410)
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
# include
#endif
(9) /drivers/usb/usb_ohci.c
/*#if defined(CONFIG_ARM920T) || \
defined(CONFIG_S3C2400) || \
defined(CONFIG_S3C2410) || \
defined(CONFIG_S3C6400) || \
defined(CONFIG_440EP) || \
defined(CONFIG_PCI_OHCI) || \
defined(CONFIG_MPC5200) || \
defined(CFG_OHCI_USE_NPS)*/
#if defined(CONFIG_ARM920T) || \
defined(CONFIG_S3C2400) || \
defined(CONFIG_S3C2410) || \
defined(CONFIG_S3C2440) || \
defined(CONFIG_S3C6400) || \
defined(CONFIG_440EP) || \
defined(CONFIG_PCI_OHCI) || \
defined(CONFIG_MPC5200) || \
defined(CFG_OHCI_USE_NPS)
(10)drivers/rtc/s3c24x0_rtc.c
//#elif defined(CONFIG_S3C2410)
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
(11)/lib_arm/board.c
1)添加头文件
#include
2)在函数display_banner(),增加LED闪烁程序
//在串口初始化和console初始化完成,串口输出信息之前,LED1、LED2、LED3会亮起!
# if defined(CONFIG_rat2440_LED)
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
gpio->GPBDAT = 0x100;
3)在void start_armboot (void)中加入灯的闪烁程序。
#if defined(CONFIG_rat2440_LED)
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
#endif
# if defined(CONFIG_rat2440_LED)
gpio->GPBDAT = 0x0;
//在进入命令提示符之前,四个LED会同时亮起!
#endif
/*-------------------------------------*/
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
编译成功。将u-boot.bin烧入nor-flash即可运行。
#if 0
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
……
break;
}
printf("mode\n");
#endif
return 0;
}
4、移植nand-flash驱动
注意此阶段工作仅是让u-boot可以操作读写nand flash。还不能让它从nand flash启动。
4.1 u-boot启用其自带nand flash驱动,并设置相应的nand flash参数。
//nand Flash param
#define CONFIG_CMD_NAND
#define CONFIG_CMDLINE_EDITING
#ifdef CONFIG_CMDLINE_EDITING
#undef CONFIG_AUTO_COMPLETE
#else
#define CONFIG_AUTO_COMPLETE
#endif//#define CONFIG_NAND_LEGACY
//不使用LEGACY,以使用自带的nand flash驱动
/*
* NAND flash settings
*/
#if defined(CONFIG_CMD_NAND)
#define CFG_NAND_BASE 0x4E000000
/* NandFlash控制器在SFR区起始寄存器地址 */
#define CFG_MAX_NAND_DEVICE 1
/* Max number of NAND devices */#define CONFIG_MTD_NAND_VERIFY_WRITE 1 //使能flash写校验
/* #undef CONFIG_MTD_NAND_VERIFY_WRITE */
#endif /* CONFIG_CMD_NAND */
#define CONFIG_ENV_IS_IN_NAND 1
#define CONFIG_ENV_OFFSET 0x30000
//#define CFG_ENV_OFFSET 0X30000//#define CONFIG_ENV_IS_IN_FLASH 1
要说明的是,此版的u-boot已自带board_nand_init(),此在/cpu/arm920t/s3c24x0/nand.c中实现。并且此版已不支持定义CFG_NAND_LEGACY,如定义此宏,则编译是会报 #error "U-Boot legacy NAND support not available for S3C2410"的错误。故此版已不能使用网上流传非nand_leagcy方式的自加nand flash初始化函数的方法,只能用其自带的初始化函数下载到内存中运行,报None nand devices!!!,这是当然的。因为S3C2410和S3C2440在FLASH控制器上,差别较大,必须改写代码。
4.2 改写主要在/cpu/arm920t/s3c24x0/nand.c中进行。(此文件内是与芯片紧密相关的代码),
一是board_nand_init函数,一是s3c2410_hwcontrol,参照2440的手册,改写相关代码。还要在此文件的开始部分加入S3C2440 nand flash控制器相关寄存器的定义。