Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1210336
  • 博文数量: 322
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 3276
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-17 09:21
文章分类

全部博文(322)

文章存档

2010年(155)

2009年(167)

我的朋友

分类: 嵌入式

2009-12-20 11:53:07

环境:

u-boot-1.1.4

FC3

NorFlash SST39VF1601

toolchains Arm-linux-uclibc-

 

u-boot-1.1.4版本中带有移植好的SMDK2410源代码,使用SMDK2410的配置生成的u-boot.bin烧写到开发板中,已经可以运行和驱动CS8900网卡芯片,但是Flash驱动不同,故环境变量的保存无法实现。本文档主要论述Flash驱动的修改和环境变量保存的实现。

 

解压u-boot-1.1.4源码包

make smdk2410_config

修改主Makefile

在export CROSS_COMPILE上一行加上CROSS_COMPILE = arm-linux-uclibc-

make

此时会出现一个错误:cc1: error: invalid option `abi=apcs-gnu'

修改/cpu/arm920t/下的config.mk:

PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)

改成:

PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,$(call cc-option,-mabi=apcs-gnu),)

再次make

这次可以完全编译成功,主目录下生成u-boot.bin,使用Flash Programmer主目录下带的BinToS19.exe将u-boot.bin转化为u-boot.s19格式

使用Flash Programmer烧写到FS2410可以看到下列启动画面

 

从启动画面可以看到,Flash的大小显示的是错误的,并且反复开机都有bad crc出现。测试savenev命令显示可以保存环境变量,但是开机后环境变量还是默认值。

上述问题是由于开发板所使用的Flash与的不同而造成,故下面我们来改写它的flash.c文件。

找一找board中有没有使用SST160 Flash的板子

grep –R ‘SST160A’ ./

看到一大堆的板子,我们选用名字为dave中的flash.c,拷贝这个flash.c到smdk2410目录,

cp board/dave/common/flash.c board/smdk2410/

使用source insight建立一个工程来分析一下这个文件(可以把源码中不相关的内容删掉些)

首先看一下SST39VF1601的datasheet

这个flash是16Mbit的也就是2MB大小

sector 2Kword也就是4Kbyte

block 32Kword也就是64Kbyte

这里要弄清楚这两个参数的目的主要是flash的擦除是要按照sector或block的方式来进行的,每种有不同的指令。

这里我们选用block的方式,故2M的Flash有32个block。这些参数都是要定义到头文件里面的,故我们首先来修改SMDK2410板子的头文件include/configs/smdk2410.h。

在第157行定义的是#define CONFIG_AMD_LV4001    

我们把它注掉定义上自己的flash

#define CONFIG_SST_VF160     1    

#ifdef CONFIG_SST_VF160

 

#define PHYS_FLASH_SIZE       0x00200000 /* 2MB */

#define CFG_MAX_FLASH_SECT     (32)/* max number of blocks on one chip */

#define CFG_ENV_ADDR          (CFG_FLASH_BASE + 0x030000) /* addr of environment */

#define FLASH_BANK_SIZE    0x01000000

 

#define   CFG_ENV_IS_IN_FLASH   1

#define CFG_ENV_SIZE          0x10000 /*64K Total Size of Environment Sector */

 

 

#define CFG_FLASH_ADDR0        0x5555

#define CFG_FLASH_ADDR1        0x2aaa

#define CFG_FLASH_WORD_SIZE    unsigned short      /* flash word size  */

 

#define CFG_FLASH_READ0            0x0000   /* A0 = 0                   */

#define CFG_FLASH_READ1            0x0001   /* A0 = 1              */

#define CFG_FLASH_READ2            0x0002   

 

#define CFG_MONITOR_LEN           (256 * 1024)  /* Reserve 256 kB for Monitor     */

#define CFG_MONITOR_BASE  TEXT_BASE

#endif

这里有几个参数先说明一下,

PHYS_FLASH_SIZE

这个参数定义Flash的容量,因为在flash初始化的时候,程序会去读flash的Manufacturer’s ID和Device ID,然后会根据这个ID来匹配Flash的容量,SST39VF601的参数如下:

Manufacturer’s ID      BFH

Device ID             234BH

 

CFG_MAX_FLASH_SECT 

CFG_ENV_ADDR

CFG_ENV_SIZE        

第一个参数确定最大的block的数量(我们是按照block来的),值为32(32*64KB = 2M)

第二个参数区定的u-boot环境变量的起始地址,由于Flash的擦除是按块或扇区的,所以需要对其,我们使用64KB块方式,故我们把环境变量的首地址暂时设在0x30000(192KB)处。

第三个参数代表环境变量的大小,我们设置为0x10000,正好是一个block的大小。

 

CFG_FLASH_ADDR0      

CFG_FLASH_ADDR1      

CFG_FLASH_WORD_SIZE      

前面两个参数是flash软件编程命令字中规定的地址,可以看datasheet。

第三个参数是Flash数据线工作的模式,我们的Flash工作于16bit模式,故这个定义为unsigned char。

 

CFG_FLASH_READ0 

CFG_FLASH_READ1 

CFG_FLASH_READ2 

这些是用于查询Flash操作状态的,在datasheet中有详细地说明。

CFG_MONITOR_LEN

这个宏和Flash的写保护设置有关。

 

 

定义好了这些宏后我们开始来逐个分析flash.c中的函数啦,按照u-boot的启动流程,在board.c中首先要进行flash_init (),但是这个Flash.c中并没有这个函数,我们在dave目录下的b2目录中的flash.c中把这个函数拷贝到我们的flash.c中。为了清除我们去掉它开头和结尾的ifdef和endif

首先我们分析一下里面的flash_get_size函数。根据前述Flash的特点把

      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;

改为

      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;   

 

这个函数中不识别device ID为234BH的SST39VF1601的片子,故给它添加上如下case代码在include/flash.h中添加宏#define FLASH_SST1601  0x004B

      case (CFG_FLASH_WORD_SIZE)SST_ID_xF1601:

            info->flash_id += FLASH_SST1601;

             info->sector_count = 32;

             info->size = 0x00200000;

             break;                         /* => 2 MB           */

 

注释/* set up sector start address table */下面的代码是建立flash的block的分区地址表,我们的block的大小是64KB(0x10000)从下面的代码看出,它的和我们的相符,故不用修改。

             info->start[i] = base + (i * 0x00010000);

 

其次在检查一下flash_get_offsets函数,发现里面的偏移也是64KB,故不用修改。

至此flash_init ()函数修改完毕。

然后我们来检查一下flash的写函数和擦除函数

int   flash_erase (flash_info_t *info, int s_first, int s_last)

根据我们Flash的特点,将

             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; /* block erase */

改为:

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

下面还有扇区擦出的命令字也按这种方式改。

将   

while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080)

addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0;/* reset bank */

改为

while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x0080) != (CFG_FLASH_WORD_SIZE)0x0080)

addr[0] = (CFG_FLASH_WORD_SIZE)0x00F0;/* reset bank */

按照上面的方法修改static int write_word (flash_info_t *info, ulong dest, ulong data)种对应的项。

最后修改int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)函数

把里面的#ifdef CONFIG_B2换成CONFIG_SMDK2410

 

在flash_print_info (flash_info_t *info)

加入:

      case FLASH_SST1601: printf ("SST39LF/VF1601 (16 Mbit, uniform. sector size)\n";

   break;

至此u-boot-1.1.4 for FS2410的主体移植工作已经完成。

 

烧入一下,看下我们的成果

 

发现开机后会显示bad CRC。其实这是正常的,我们可以分析一下u-boot中的源码,首次运行的话u-boot中的环境变量中的crc值时空的,故肯定会显示bad crc,

在env_relocate (void)函数中会检查gd->env_valid的值,而这个值是在env_init中更新的,首次开机检查到的gd->env_valid值为0,故会显示bad crc,随后会执行env_crc_update ()函数将正确的crc记录到环境变量中,此时你要输入一下saveenv命令,把这个crc固化到flash中。故二次开机后就可以了。

如果遇到开机后环境变量没有被跟新的情况,可以按一下方法解决

这是由于ENV_IS_EMBEDDED定义造成的,而此变量定义是在envcrc.c中:

# if (CFG_ENV_ADDR >= CFG_MONITOR_BASE) && \

((CFG_ENV_ADDR + CFG_ENV_SIZE) <= (CFG_MONITOR_BASE + CFG_MONITOR_LEN))

# define ENV_IS_EMBEDDED 1

# endif

前述定义的#define CFG_MONITOR_BASE      TEXT_BASE就是为了解决这个问题的,这样可以使ENV_IS_EMBEDDED 1这个宏不被定义。

 

使U-boot更加易于使用

u-boot提供了强大的命令行参数,可以发挥出巨大的作用,下面我们举个例子来说明。

在environment.c中定义有

#ifdef CONFIG_EXTRA_ENV_SETTINGS

      CONFIG_EXTRA_ENV_SETTINGS

#endif

可以在smdk2410.h中可以加上下面的宏,定义一些额外命令行参数。

阅读(937) | 评论(0) | 转发(1) |
0

上一篇:正确刷牙的方法

下一篇:Source Insight 教程

给主人留下些什么吧!~~