代码改变世界

AT91RM9200引导程序的建立(三)--------U-Boot1.1.4在AT91RM9200上的移植

2007-02-12 16:23  htc开发  阅读(180)  评论(0编辑  收藏  举报

 

BootLoader概述
       Boot Loader就是在操作系统内核运行之前运行的一段小程序。通过这段BootLoader,我们来初始化硬件设备,为硬件设备准备地址空间,中断号等,建立内存空间的映射,从而将系统的软硬件环境带到一个合适的状态。
AT91RM9200处理器启动有两种情况,一种是从外部启动,如Flash,EEPROM,DATAFLASH等;一种是从内部的BOOTROM固化代码引导。我们的ARM板是直接通过JTAG接口从主机下载到目标板的flash中直接启动。
       系统上电后,我们的CPU从0x00000000取它的第一条指令,而我们的flash就是被映射到这个地址上。CPU就首先执行我们烧在flash上的BootLoader 程序,通过它来引导Linux系统。
U-Boot是一个通用的Bootloader,可以方便地移植到其他硬件平台。现在已经成为ARM平台事实上的标准。
U-Boot的源码包可以从sourceforge网站下载。我们使用U-Boot1.1.4来作为我们移植的Bootloader。
 
U-Boot1.1.4移植
u-boot修改。
由于我们的板子和atmel的DK板不同,所以针对我们的硬件,要重新修改u-boot代码,特别是flash驱动部分。
 
1)修改board/at91rm9200dk/config.mk
TEXT_BASE=0x21f00000 将U-Boot载入32MSDRAM的高端部分,即最高端1M的空间留给U-Boot代码。
 
2)修改include/configs/at91rm9200dk.h
 修改Flash和SDRAM的大小:
 
   #define PHYS_SDRAM_SIZE 0x2000000 /* 32 megs */
    #define PHYS_FLASH_SIZE 0x200000 /* 2 megs main flash */
同时定义如下环境变量:
#define CONFIG_DEFAULT_ENVIRONMENT
#define CONFIG_BOARDNAME "AT91RM9200DK"
#define CONFIG_ETHADDR "00:11:22:33:44:55"
#define CONFIG_IPADDR "192.168.1.100"
#define CONFIG_SERVERIP "192.168.1.1"
//#define CONFIG_GATEWAYIP "192.168.18.1"
#define CONFIG_BOOTCOMMAND "tftp 0x20008000 zImage; tftp 0x20410000 ramdisk;go 0x20008000"
#define CONFIG_DEFAULT_KERNEL "2.6.17"
从上面可以看出,我们板子的IP地址是192.168.1.100,而我们的宿主机IP地址为192.168.1.1 ,我们的网卡Mac为:00:11:22:33:44:55。
3)修改flash驱动
borad/at91rm9200dk/flash.c这个文件修改的部分比较的多。
1.     首先是OrgDef的定义,加上目前的flash
   
OrgDef OrgSSTvF6401B[]=
{
                                     {2048,4*1024},   /*2048*64KBytes sectors*/
};
修改函数flash_identification(flash_info_t * info),显示正确的信息。
void flash_identification (flash_info_t * info)
{
       volatile u16 manuf_code, device_code, add_device_code;
 
       MEM_FLASH_ADDR1 = FLASH_CODE1;
       MEM_FLASH_ADDR2 = FLASH_CODE2;
       MEM_FLASH_ADDR1 = ID_IN_CODE;
 
       manuf_code = *(volatile u16 *) CFG_FLASH_BASE;
       device_code = *(volatile u16 *) (CFG_FLASH_BASE + 2);
       add_device_code = *(volatile u16 *) (CFG_FLASH_BASE + (3 << 1));
 
       MEM_FLASH_ADDR1 = FLASH_CODE1;
       MEM_FLASH_ADDR2 = FLASH_CODE2;
       MEM_FLASH_ADDR1 = ID_OUT_CODE;
 
       /* Vendor type */
       /*
       if(info->flash_id = ATM_MANUFACT & FLASH_VENDMASK)
       {
                 printf ("Atmel: ");
       }
       */
       if(info->flash_id=SST_MANUFACT & FLASH_VENDMASK)    //zzl061206
       {
                 printf("SST:");
       }
/*atmel identify*/
       if ((device_code & FLASH_TYPEMASK) == (ATM_ID_BV1614 & FLASH_TYPEMASK)) {
 
                 if ((add_device_code & FLASH_TYPEMASK) ==
                            (ATM_ID_BV1614A & FLASH_TYPEMASK)) {
                            info->flash_id |= ATM_ID_BV1614A & FLASH_TYPEMASK;
                            printf ("AT49BV1614A (16Mbit)/n");
                 } else {                                 /* AT49BV1614 Flash */
                            info->flash_id |= ATM_ID_BV1614 & FLASH_TYPEMASK;
                            printf ("AT49BV1614 (16Mbit)/n");
                 }
 
       } else if ((device_code & FLASH_TYPEMASK) == (ATM_ID_BV6416 & FLASH_TYPEMASK)) {  
                 info->flash_id |= ATM_ID_BV6416 & FLASH_TYPEMASK;
                 printf ("AT49BV6416 (64Mbit)/n");
       }
       /*sst identify*/
      else if((device_code & FLASH_TYPEMASK) == (SST_ID_xF6401B & FLASH_TYPEMASK)) //zzl061206
      {
               info->flash_id |= SST_ID_xF6401B & FLASH_TYPEMASK;
               printf("vF6401B(64Mbit)/n");
      }
}
 
2. 修改初始化Flash函数ulong flash_init
(void)ulong flash_init (void)
{
       int i, j, k;
       unsigned int flash_nb_blocks, sector;
       unsigned int start_address;
       OrgDef *pOrgDef;
 
       ulong size = 0;
 
       for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
                 ulong flashbase = 0;
 
                 flash_identification (&flash_info[i]);
 
                 if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==
                            (ATM_ID_BV1614 & FLASH_TYPEMASK)) {
 
                            pOrgDef = OrgAT49BV16x4;
                            flash_nb_blocks = sizeof (OrgAT49BV16x4) / sizeof (OrgDef);
                 } else if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==
                            (ATM_ID_BV1614A & FLASH_TYPEMASK)){      /* AT49BV1614A Flash */
 
                            pOrgDef = OrgAT49BV16x4A;
                            flash_nb_blocks = sizeof (OrgAT49BV16x4A) / sizeof (OrgDef);
                 } else if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==
                            (ATM_ID_BV6416 & FLASH_TYPEMASK)){       /* AT49BV6416 Flash */
 
                            pOrgDef = OrgAT49BV6416;
                            flash_nb_blocks = sizeof (OrgAT49BV6416) / sizeof (OrgDef);
                 }
                 /*zzl*/
               else if((flash_info[i].flash_id & FLASH_TYPEMASK)==
                        (SST_ID_xF6401B & FLASH_TYPEMASK))
               {
                        pOrgDef=OrgSSTvF6401B;
                        flash_nb_blocks = sizeof (OrgSSTvF6401B) / sizeof (OrgDef);
               }
                 else {
                            flash_nb_blocks = 0;
                            pOrgDef = OrgAT49BV16x4;
                 }
 
                 flash_info[i].sector_count = flash_number_sector(pOrgDef, flash_nb_blocks);
                 memset (flash_info[i].protect, 0, flash_info[i].sector_count);
 
                 if (i == 0)
                            flashbase = PHYS_FLASH_1;
                 else
                            panic ("configured too many flash banks!/n");
 
                 sector = 0;
                 start_address = flashbase;
                 flash_info[i].size = 0;
 
                 for (j = 0; j < flash_nb_blocks; j++) {
                            for (k = 0; k < pOrgDef[j].sector_number; k++) {
                                      flash_info[i].start[sector++] = start_address;
                                      start_address += pOrgDef[j].sector_size;
                                      flash_info[i].size += pOrgDef[j].sector_size;
                            }
                 }
 
                 size += flash_info[i].size;
 
                 if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==
                            (ATM_ID_BV6416 & FLASH_TYPEMASK)){       /* AT49BV6416 Flash */   /*zzl*/
 
                            /* Unlock all sectors at reset */
                            for (j=0; j<flash_info[i].sector_count; j++){
                                      flash_unlock_sector(&flash_info[i], j);
                            }
                 }
       }
 
       /* Protect binary boot image */
       flash_protect (FLAG_PROTECT_SET,
                        CFG_FLASH_BASE,
                        CFG_FLASH_BASE + CFG_BOOT_SIZE - 1, &flash_info[0]);
 
       /* Protect environment variables */
       flash_protect (FLAG_PROTECT_SET,
                        CFG_ENV_ADDR,
                        CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
 
       /* Protect U-Boot gzipped image */
       flash_protect (FLAG_PROTECT_SET,
                        CFG_U_BOOT_BASE,
                        CFG_U_BOOT_BASE + CFG_U_BOOT_SIZE - 1, &flash_info[0]);
 
       return size;
 
3.修改 函数flash_erase(),将检测flash类型注释掉,因为先前已经检测过
 
      /* first look for protection bits */
/*zzl 20061206
       if (info->flash_id == FLASH_UNKNOWN)
                 return ERR_UNKNOWN_FLASH_TYPE;
 
       if ((s_first < 0) || (s_first > s_last)) {
                 return ERR_INVAL;
       }
 
       if ((info->flash_id & FLASH_VENDMASK) !=
                 (ATM_MANUFACT & FLASH_VENDMASK)) {
                 return ERR_UNKNOWN_FLASH_VENDOR;
       }
*/
但是这里出现了一个问题,编译后IP地址为0.192.168.1,serverip也是0.192.168.1。修改net/net.c中获得IP地址的函数。
IPaddr_t getenv_IPaddr (char *var)
{
       /*zzl*/
       char tmp_str[64];
       strcpy(tmp_str,getenv(var));
if(isxdigit(*tmp_str))     /*测试环境变量字符是否是16进制,如果是,从第一个字符开始取4个字节,如果不是,则从第二个字符开始取4个字节。*/
                 return (string_to_ip(tmp_str));
       else
                 return(string_to_ip(tmp_str+1));
      
/*old code
       return (string_to_ip(getenv(var)));
       */
}
重新编译
#make distclean
#make at91rm9200dk_config
#make all
编译成功后得到u-boot.bin的二进制文件,即为需要的可执行映象文件,将其用仿真器通过JTAG烧进flash中。板子重新上电,U-Boot启动成功。(注:U-Boot1.1.4已经不需要将其压缩为u-boot.gz。直接烧入flash的0地址后,便能启动,进入u-boot下。)