Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1907332
  • 博文数量: 496
  • 博客积分: 12043
  • 博客等级: 上将
  • 技术积分: 4778
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-27 14:26
文章分类

全部博文(496)

文章存档

2014年(8)

2013年(4)

2012年(181)

2011年(303)

2010年(3)

分类: 嵌入式

2011-03-17 11:57:40

1.1 移植环境介绍

U-boot版本:u-boot 2010-6

Linux平台:虚拟机下 13

交叉编译工具:gcc-4.4.3

arm开发板:mini2440CPUS3C2440 SDRAM64MNor Flash2MNand Flash256M,网卡:DM9000EP

1.2 删减u-boot文件

删除arch目录下除arm目录以外的所有目录,arm\cpu目录下除arm920tmulu以外的所有目录,arch\arm\cpu\arm920t录下除s3c24x0目录以外的所有目录(该目录下的文件不要删),arch\arm\include\asm目录下除archs3c24x0目录以外的所有archxxxx目录(该目录下的文件不要删) 删除board目录下除samsung目录以外的所有目录,board\samsung目录下除smdk2410目录以外的所有目录 删除include\configs目录下除smdk2410.h文件以外的所有头文件。

 

1.3 修改顶层Makefile文件

# set default to nothing for native builds

ifeq ($(HOSTARCH),$(ARCH))

#CROSS_COMPILE ?=

#=========指定交叉编译工具========

CROSS_COMPILE ?= arm-linux-gcc 

Endif

 

smdk2410_config   :      unconfig

       @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0

#仿照smdk2410,配置自己的开发板

mini2440_config   :      unconfig

       @$(MKCONFIG) $(@:_config=) arm arm920t mini2440 s3c24x0

 

开发板配置选项中各项的含义如下:

arm

CPU 的类型(CPU)

arm920t

其对应于cpu/arm920t 子目录

zcrarm

开发者/或经销商(vender),对应于board/zcrarm目录

mini2440

开发板的型号(BOARD),对应于board/ zcrarm /mini2440 目录

s3c24x0

片上系统(SOC)定义

 

1.4 /board 中建立mini2440 目录和文件

#cd board

#mkdir -p mini2440

#cp -arf  samsung/smdk2410/* samsung/mini2440/

#cd mini2440/

#mv smdk2410.c mini2440.c

 

1.5 修改mini2440 目录下的Makefile文件

LIB = $(obj)lib$(BOARD).a

#COBJS := sbc2410x.o flash.o

COBJS := mini2440.o flash.o

SOBJS := lowlevel_init.o

SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)

 

1.6 include/configs/中建立开发板配置文件

#cp include/configs/smdk2410.h include/configs/mini2440.h

 

1.7 测试编译环境(此问题在以前移植u-boot时出现)

至此,最基本的配置已经完成。

[root@angel u-boot-2009.11]# make mini2440_config

Configuring for mini2440 board...

ln: 创建符号链接 asm: 不支持的操作

make: *** [mini2440_config] 错误 1

出现错误了,会是什么原因呢?测试一下U-boot本身附带的配置:

[root@angel u-boot-2009.11]# make smdk2410_config

Configuring for smdk2410 board...

ln: 创建符号链接 asm: 不支持的操作

make: *** [smdk2410_config] 错误 1

依然是这个错误,于是猜测错误原因不是在自己的配置上,上网查了下,发现错误原因是:Windows分区使用此命令,Windows分区不支持linux上的链接。

恍然大悟啊,自己把U-boot解压在虚拟机的共享文件夹下了,修改文件夹路径,编译……OK.

二.基本功能实现


2.1  mini2440开发板u-bootstage1阶段的硬件设备初始化

由于在u-boot启动代码处有两行是AT91RM9200DKLED初始代码,但我们mini2440上的LED资源与该开发板的不一致,所以我们要删除或屏蔽该处代码,再加上mini2440LED驱动代码(注:添加my2440 LED功能只是用于表示u-boot运行的状态,给调试带来方便,可将该段代码放到任何你想调试的地方),代码如下:

#gedit cpu/arm920t/start.S

 

/*bl coloured_LED_init  //这两行是AT91RM9200DK开发板的LED初始化,注释掉

    bl red_LED_on*/

#if defined(CONFIG_S3C2440)  //区别与其他开发板

//根据mini2440原理图可知LED分别由S3C2440PB5678口来控制,以下是PB端口寄存器基地址(2440DataSheet得知)

#define GPBCON 0x56000010

#define GPBDAT 0x56000014

#define GPBUP  0x56000018     

//以下对寄存器的操作参照S3C2440DataSheet进行操作

    ldr r0, =GPBUP

    ldr r1, =0x7FF    //即:二进制11111111111,关闭PB口上拉

    str r1, [r0]

    ldr r0, =GPBCON  //配置PB5678为输出口,对应PBCON寄存器的第10-17

    ldr r1, =0x154FD  //即:二进制010101010011111101

    str r1, [r0]

 

    ldr r0, =GPBDAT

    ldr r1, =0x1C0    //即:二进制111000000PB5设为低电平,678为高电平

    str r1, [r0]

#endif

 

//此段代码使u-boot启动后,点亮开发板上的LED1LED2LED3LED4不亮

include/configs/mini2440.h头文件中添加CONFIG_S3C2440

#gedit include/configs/mini2440.h

#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 */

#define CONFIG_S3C2440         1    /* in a SAMSUNG S3C2440 SoC    */

现在编译u-boot,在根目录下会生成一个u-boot.bin文件。然后我们利用mini2440原有的superviviu-boot.bin下载到RAM中运行测试(注意:我们使用supervivi进行下载时已经对CPURAM进行了初始化,所以我们在u-boot中要屏蔽掉对CPURAM的初始化),如下:

/*#ifndef CONFIG_SKIP_LOWLEVEL_INIT //start.S文件中屏蔽u-bootCPURAM的初始

   bl cpu_init_crit                        //

#endif*/

#make my2440_config

#make

2.2 u-boot中添加对S3C2440一些寄存器的支持、添加中断禁止部分和时钟设置部分

由于24102440的寄存器及地址大部分是一致的,所以这里就直接在2410的基础上再加上对2440的支持即可,代码如下:

#gedit cpu/arm920t/start.S

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

    /* 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     //下面24102440的寄存器地址是一致的

# define pWTCON     0x53000000

# define INTMSK     0x4A000008    /* Interupt-Controller base addresses */

# define INTSUBMSK  0x4A00001C

# define CLKDIVN    0x4C000014    /* clock divisor register */

# endif

    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, =0x3ff

    ldr  r0, =INTSUBMSK

    str  r1, [r0]

# endif

# if defined(CONFIG_S3C2440)    //添加s3c2440的中断禁止部分

    ldr  r1, =0x7fff              //根据2440芯片手册,INTSUBMSK寄存器有15位可用  

    ldr  r0, =INTSUBMSK

    str  r1, [r0]

# endif

 

# if defined(CONFIG_S3C2440)      //添加s3c2440的时钟部分

#define MPLLCON   0x4C000004   //系统主频配置寄存器基地址

#define UPLLCON   0x4C000008   //USB时钟频率配置寄存器基地址

    ldr  r0, =CLKDIVN           //设置分频系数FCLK:HCLK:PCLK = 1:4:8

    mov  r1, #5

str  r1, [r0]

 

    ldr  r0, =MPLLCON  //设置系统主频为405MHz 

    ldr  r1, =0x7F021    //这个值参考芯片手册“PLL VALUE SELECTION TABLE”部分

str  r1, [r0]

 

    ldr  r0, =UPLLCON  //设置USB时钟频率为48MHz  

    ldr  r1, =0x38022    //这个值参考芯片手册“PLL VALUE SELECTION TABLE”部分

    str  r1, [r0]

 

# else //其他开发板的时钟部分,这里就不用管了,我们现在是做2440

    /* FCLK:HCLK:PCLK = 1:2:4 */

    /* default FCLK is 120 MHz ! */ 

    ldr  r0, =CLKDIVN

    mov  r1, #3

    str  r1, [r0]

# endif

#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440 */

S3C2440的时钟部分除了在start.S中添加外,还要分别在board/samsung/mini2440/mini2440.carch/arm/cpu/arm920t/s3c24x0/speed.c中修改或添加部分代码,如下:

#gedit board/samsung/mini2440/mini2440.c //设置主频和USB时钟频率参数与start.S中的一致

#define FCLK_SPEED 2       //设置默认等于2,即下面红色代码部分有效

 

#if FCLK_SPEED==0          /* Fout = 203MHz, Fin = 12MHz for Audio */

#define M_MDIV    0xC3

#define M_PDIV    0x4

#define M_SDIV    0x1

#elif FCLK_SPEED==1        /* Fout = 202.8MHz */

#define M_MDIV    0xA1

#define M_PDIV    0x3

#define M_SDIV    0x1

#elif FCLK_SPEED==2        /* Fout = 405MHz */

#define M_MDIV    0x7F     //这三个值根据S3C2440芯片手册“PLL VALUE SELECTION //TABLE”部分进行设置

#define M_PDIV    0x2

#define M_SDIV    0x1

#endif

 

#define USB_CLOCK 2        //设置默认等于2,即下面红色代码部分有效

 

#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

#elif USB_CLOCK==2         /* Fout = 48MHz */

#define U_M_MDIV    0x38   //这三个值根据S3C2440芯片手册“PLL VALUE SELECTION //TABLE”部分进行设置

#define U_M_PDIV    0x2

#define U_M_SDIV    0x2

#endif

 

#gedit cpu/arm920t/s3c24x0/speed.c //根据设置的分频系数FCLK:HCLK:PCLK = 1:4:8修改获取时

//频率的函数

static ulong get_PLLCLK(int pllreg)

{

    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

    ulong r, m, p, s;

 

    if (pllreg == MPLL)

    r = clk_power->MPLLCON;

    else if (pllreg == UPLL)

    r = clk_power->UPLLCON;

    else

    hang();

 

    m = ((r & 0xFF000) >> 12) + 8;

    p = ((r & 0x003F0) >> 4) + 2;

    s = r & 0x3;

 

#if defined(CONFIG_S3C2440)

    if(pllreg == MPLL)

    {   //参考S3C2440芯片手册上的公式:PLL=(2 * m * Fin)/(p * 2s)

        return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));

    }

#endif

    return((CONFIG_SYS_CLK_FREQ * m) / (p << s));

}

/* return HCLK frequency */

ulong get_HCLK(void)

{

    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

#if defined(CONFIG_S3C2440)

    return(get_FCLK()/4);

#endif

    return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());

}

 

修改完毕后我们再重新编译u-boot,然后再下载到RAM中运行测试。结果终端有输出信息并且出现类似Shell的命令行,这说明这一部分移植完成。示意图如下:

 

三.添加对Nor Flash的支持

通常,在嵌入式bootloader中,有两种方式来引导启动内核:从Nor Flash启动和从Nand Flash启动。u-boot中默认是从Nor Flash启动,再从上一节这个运行结果图中看,还发现几个问题:第一,我开发板的Nor Flash2M的,而这里显示的是512kB;第二,出现Warning - bad CRC, using default environment的警告信息。不是u-boot默认是从Nor Flash启动的吗?为什么会有这些错误信息呢?这是因为我们还没有添加对我们自己的Nor Flash的支持,u-boot默认的是其他型号的Nor Flash,而我们的Nor Flash的型号是SST39VF1601

下面我们一一来解决这些问题,让u-boot完全对我们Nor Flash的支持。首先我们修改头文件代码如下:

#gedit include/configs/mini2440.h //修改命令行前的名字和Nor Flash参数部分的定义

#define CONFIG_SYS_PROMPT   "[Backkom@2440]#"  

 

/*-----------------------------------------------------------------------

 * FLASH and environment organization

 */

#if 0    //注释掉下面两个类型的Nor Flash设置,因为不是我们所使用的型号

#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

#define CONFIG_SYS_MAX_FLASH_BANKS 1  /* max number of memory banks */

#define CONFIG_SST_39VF1601  1

#ifdef  CONFIG_AMD_LV800

#define PHYS_FLASH_SIZE            0x00100000  /* 1MB */

#define CONFIG_SYS_MAX_FLASH_SECT  (19)        /* max number of sectors on one chip */

#define CONFIG_ENV_ADDR  (CONFIG_SYS_FLASH_BASE + 0x0F0000) // addr of environment

#endif

#ifdef CONFIG_AMD_LV400

#define PHYS_FLASH_SIZE            0x00080000  /* 512KB */

#define CONFIG_SYS_MAX_FLASH_SECT  (11)        /* max number of sectors on one chip */

#define CONFIG_ENV_ADDR  (CONFIG_SYS_FLASH_BASE + 0x070000) //addr of environment

#endif

#ifdef CONFIG_SST_39VF1601               //添加mini2440开发板Nor Flash设置

#define PHYS_FLASH_SIZE            0x200000 //我们开发板的Nor Flash2M

#define CONFIG_SYS_MAX_FLASH_SECT  (512)    //根据SST39VF1601的芯片手册描述,对其//进行操作有两种方式:块方式和扇区方式。现采用扇区方式(sector)1 sector = 2Kword = 4Kbyte//所以2MNor Flash共有512sector

#define CONFIG_ENV_ADDR   (CONFIG_SYS_FLASH_BASE + 0x040000) //暂设置环境变量的

//地址为0x040000(即:256Kb)

#endif

然后添加对我们mini2440开发板上2MNor Flash(型号为SST39VF1601)的支持。在u-boot中对Nor Flash的操作分别有初始化、擦除和写入,所以我们主要修改与硬件密切相关的三个函数flash_initflash_erasewrite_hword,修改代码如下:

#gedit board/samsung/my2440/flash.c

//修改定义部分如下:

//#define MAIN_SECT_SIZE   0x10000

#define MAIN_SECT_SIZE     0x1000  //定义为4k,刚好是一个扇区的大小

 

//#define MEM_FLASH_ADDR1  (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 1)))

//#define MEM_FLASH_ADDR2  (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 1)))

#define MEM_FLASH_ADDR1    (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00005555 << 1)))  //这两个参数看SST39VF1601手册      

#define MEM_FLASH_ADDR2    (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00002AAA << 1)))

 

//修改flash_init函数如下:

#elif defined(CONFIG_AMD_LV800)

            (AMD_MANUFACT & FLASH_VENDMASK) |

            (AMD_ID_LV800B & FLASH_TYPEMASK);

#elif defined(CONFIG_SST_39VF1601)   //CONFIG_AMD_LV800后面添加CONFIG_SST_39VF1601        

            (SST_MANUFACT & FLASH_VENDMASK) |

            (SST_ID_xF1601 & FLASH_TYPEMASK);

 

for (j = 0; j < flash_info[i].sector_count; j++) {

    //if (j <= 3) {

    //    /* 1st one is 16 KB */

    //    if (j == 0) {

    //        flash_info[i].start[j] = flashbase + 0;

    //    }

 

    //    /* 2nd and 3rd are both 8 KB */

    //    if ((j == 1) || (j == 2)) {

    //        flash_info[i].start[j] = flashbase + 0x4000 + (j - 1) * 0x2000;

    //    }

 

    //    /* 4th 32 KB */

    //    if (j == 3) {

    //        flash_info[i].start[j] = flashbase + 0x8000;

    //    }

    //} else {

    //    flash_info[i].start[j] = flashbase + (j - 3) * MAIN_SECT_SIZE;

    //}

 

    flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;

}

 

 

 

//修改flash_print_info函数如下:  

case (AMD_MANUFACT & FLASH_VENDMASK):

    printf ("AMD: ");

    break;

case (SST_MANUFACT & FLASH_VENDMASK):    //添加SST39VF1601

    printf ("SST: ");

    break;

 

case (AMD_ID_LV800B & FLASH_TYPEMASK):

    printf ("1x Amd29LV800BB (8Mbit)\n");

    break;

case (SST_ID_xF1601 & FLASH_TYPEMASK):   //添加SST39VF1601

    printf ("1x SST39VF1610 (16Mbit)\n");

    break;

 

//修改flash_erase函数如下:

//if ((info->flash_id & FLASH_VENDMASK) !=

// (AMD_MANUFACT & FLASH_VENDMASK)) {

//    return ERR_UNKNOWN_FLASH_VENDOR;

//}

if ((info->flash_id & FLASH_VENDMASK) !=

 (SST_MANUFACT & FLASH_VENDMASK)) {

    return ERR_UNKNOWN_FLASH_VENDOR;

}

 

///* wait until flash is ready */

//chip = 0;

//do {

//    result = *addr;

//    /* check timeout */

//    if (get_timer_masked () >

//     CONFIG_SYS_FLASH_ERASE_TOUT) {

//        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;

//        chip = TMO;

//        break;

//    }

 

//    if (!chip

//     && (result & 0xFFFF) & BIT_ERASE_DONE)

//        chip = READY;

 

//    if (!chip

//     && (result & 0xFFFF) & BIT_PROGRAM_ERROR)

//        chip = ERR;

//} while (!chip);

 

//MEM_FLASH_ADDR1 = CMD_READ_ARRAY;

 

//if (chip == ERR) {

//    rc = ERR_PROG_ERROR;

//    goto outahere;

//}

 

//if (chip == TMO) {

//    rc = ERR_TIMOUT;

//    goto outahere;

//}

while (1)

{

    if ((*addr & 0x40) != (*addr & 0x40))

        continue;

    if (*addr & 0x80)

    {

        rc = ERR_OK;

        break;

    }

}

//修改write_hword函数如下:

MEM_FLASH_ADDR1 = CMD_UNLOCK1;

MEM_FLASH_ADDR2 = CMD_UNLOCK2;

//MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;

MEM_FLASH_ADDR1 = CMD_PROGRAM;  

//*addr = CMD_PROGRAM;

*addr = data;

 

///* wait until flash is ready */

//chip = 0;

//do {

//    result = *addr;

//    /* check timeout */

//    if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) {

//        chip = ERR | TMO;

//        break;

//    }

 

//    if (!chip && ((result & 0x80) == (data & 0x80)))

//        chip = READY;

 

//    if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {

//        result = *addr;

//        if ((result & 0x80) == (data & 0x80))

//            chip = READY;

//        else

//            chip = ERR;

//    }

//} while (!chip);

 

//*addr = CMD_READ_ARRAY;

 

//if (chip == ERR || *addr != data)

//    rc = ERR_PROG_ERROR;

while (1)

{

    if ((*addr & 0x40) != (*addr & 0x40))

        continue;

 

    if ((*addr & 0x80) == (data & 0x80))

    {

        rc = ERR_OK;

        break;

    }

}

修改完后重新编译u-boot,下载到RAM中运行结果如下图:

阅读(1408) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~