加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

u-boot-2009.08在mini2440上的移植 增加nor flash功能

发布时间:2020-12-15 06:33:46 所属栏目:百科 来源:网络整理
导读:通常,在嵌入式bootloader中,有两种方式来引导启动内核:从Nor Flash启动和从Nand Flash启动。u-boot中默认是从Nor Flash启动,再从上一节测试运行的结果的中看,还发现几个问题:第一,我开发板的Nor Flash是2M的,而这里显示的是512kB;第二,出现Warning

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

2.1,修改u-boot源码,使其完全支持Nor Flash。

【1】添加对我们mini2440开发板上2M的Nor Flash(型号为SST39VF1601)的支持

在虽然 S3C2440 和S3C2410 对于Nor Flash 的链接都是一样的,但是SBC2410 使用的AMD 的Nor Flash 芯片,而mini2440 使用的SST 的Nor Flash。这两款芯片在写入时所使用的块大小、时序和指令代码有差别,所以必须根据芯片的数据手册进行修改。主要的差别请看数据手册的对比:
SST39VF1601:

?Am29LV160:

?

在u-boot中对Nor Flash的操作分别有初始化、擦除和写入,所以我们主要修改与硬件密切相关的三个函数flash_init、flash_erase、write_hword。

用gedit打开board/samsung/mini2440/flash.c,定位到31行附近,修改如下:

#define FLASH_BANK_SIZE?PHYS_FLASH_SIZE
//#define MAIN_SECT_SIZE? 0x10000?/* 64 KB */
#define MAIN_SECT_SIZE???? 0x1000? //定义为4k,刚好是一个扇区的大小

flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];

... ...

Nor Flash硬件连接

?

有原理图可知,一般NorFlash放在Bank0.所以CONFIG_SYS_BASE=0,但是开启mmu后baseaddr=地址0映射到的新地址。0x555<<1的原因是LADDR1与A0连接。也就是0x555表示片内第0x555个word(16bit)。

#define CMD_UNLOCK_BYPASS 0x00000020

#if defined(CONFIG_SST_VF1601)
#define MEM_FLASH_ADDR1? (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000005555 << 1)))
#define MEM_FLASH_ADDR2? (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AAA << 1)))
#else

#define MEM_FLASH_ADDR1? (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 1)))
#define MEM_FLASH_ADDR2? (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 1)))
#endif

#define BIT_ERASE_DONE? 0x00000080

在flash_init 函数中修改或添加后代码如下:

ulong flash_init (void)
{
?int i,j;
?ulong size = 0;

for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
? ulong flashbase = 0;

... ...

#elif defined(CONFIG_AMD_LV800)
??????????? (AMD_MANUFACT & FLASH_VENDMASK) |
??????????? (AMD_ID_LV800B & FLASH_TYPEMASK);
#elif defined(CONFIG_SST_39VF1601)??
??????????? (SST_MANUFACT & FLASH_VENDMASK) |
??????????? (SST_ID_xF1601 & FLASH_TYPEMASK);
#else
#error "Unknown flash configured"
#endif

... ...

for (j = 0; j < flash_info[i].sector_count; j++) {
#ifndef CONFIG_SST_VF1601
?? if (j <= 3) {
??? /* 1st one is 16 KB */

... ...
#else
??? flash_info[i].start[j] =
???? flashbase + (j) * MAIN_SECT_SIZE;
#endif


?}
? size += flash_info[i].size;
?}

? ... ...

??? return size;

}

在flash_print_info 函数中修改或添加后代码如下:

void flash_print_info (flash_info_t * info)
{
???? int i;

??? switch (info->flash_id & FLASH_VENDMASK) {
????????????? case (AMD_MANUFACT & FLASH_VENDMASK):
????????????? printf ("AMD: ");
????????????? break;
????????????? case (SST_MANUFACT & FLASH_VENDMASK):
????????????? printf ("SST: ");
????????????? break;

????????????? default:
????????????? printf ("Unknown Vendor ");
????????????? break;
??? }

??? switch (info->flash_id & FLASH_TYPEMASK) {
?????????????? case (AMD_ID_LV400B & FLASH_TYPEMASK):
?????????????? printf ("1x Amd29LV400BB (4Mbit)n");
?????????????? break;
?????????????? case (AMD_ID_LV800B & FLASH_TYPEMASK):
?????????????? printf ("1x Amd29LV800BB (8Mbit)n");
?????????????? break;
?????????????? case (SST_ID_xF1601 & FLASH_TYPEMASK):
?????????????? printf ("1x SST39VF1610 (16Mbit)n");
?????????????? break;


?????????????? default:
?????????????? printf ("Unknown Chip Typen");
?????????????? goto Done;
?????????????? break;


??? }

?? ... ...

??? Done:;
}

在flash_erase函数中修改或添加后代码如下:

int flash_erase (flash_info_t * info,int s_first,int s_last)
{
??? ushort result;
??? int iflag,cflag,prot,sect;
??? int rc = ERR_OK;
??? int chip;

???? .... ....

??? if ((s_first < 0) || (s_first > s_last)) {
??? return ERR_INVAL;
??? }

?if ((s_first < 0) || (s_first > s_last)) {
? return ERR_INVAL;
?}

#ifdef CONFIG_SST_VF1601
?if ((info->flash_id & FLASH_VENDMASK) !=
???? (SST_MANUFACT & FLASH_VENDMASK)) {
? return ERR_UNKNOWN_FLASH_VENDOR;
?}
#else

?if ((info->flash_id & FLASH_VENDMASK) !=
???? (AMD_MANUFACT & FLASH_VENDMASK)) {
? return ERR_UNKNOWN_FLASH_VENDOR;
?}
#endif
?prot = 0;

... ...

?? if (info->protect[sect] == 0) { /* not protected */


?? vu_short *addr = (vu_short *) (info->start[sect]);

?? MEM_FLASH_ADDR1 = CMD_UNLOCK1;
?? MEM_FLASH_ADDR2 = CMD_UNLOCK2;
?? MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;

?? MEM_FLASH_ADDR1 = CMD_UNLOCK1;
?? MEM_FLASH_ADDR2 = CMD_UNLOCK2;
?? *addr = CMD_ERASE_CONFIRM;

?? /* wait until flash is ready */

#if 0

? chip = 0;

?? do {

... ...

??? printf ("ok.n");
?? } else { /* it was protected */

??????? printf ("protected!n");
?? }
}
#endif
?? while(1){
????????? unsigned short i;
????????? i = *((volatile unsigned short *)addr) & 0x40;
????????? if(i != (*((volatile unsigned short *)addr) & 0x40))
?????????????? continue;
????????? if((*((volatile unsigned short *)addr)) & 0x80)
?????????????? break;
??? }
??? printf ("ok.n");
?? } else { /* it was protected */
?? printf ("protected!n");
? }
}

在write_hword函数中修改或添加后代码如下:

tatic int write_hword (flash_info_t * info,ulong dest,ushort data)
{
??? vu_short *addr = (vu_short *) dest;
??? ushort result;
??? int rc = ERR_OK;
??? int cflag,iflag;
??? int chip;

??? ... ...

??? 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;

??? /* arm simple,non interrupt dependent timer */
??? reset_timer_masked ();

??? /* wait until flash is ready */

#if 0?

?chip = 0;
?? do {
?? result = *addr;

... ...

??? } while (!chip);

??? *addr = CMD_READ_ARRAY;

??? if (chip == ERR || *addr != data)
??????? rc = ERR_PROG_ERROR;
#endif

? while(1){
???????? unsigned short i = *(volatile unsigned short *)addr & 0x40;
???????? if(i != (*(volatile unsigned short *)addr & 0x40))?? //D6 == D6
???????????? continue;
???????? if((*(volatile unsigned short *)addr & 0x80) == (data & 0x80)){
???????????? rc = ERR_OK;
???????? break;???? //D7 == D7
????????? }
??????? }
?? if (iflag)
???? enable_interrupts ();

?? if (cflag)
???? icache_enable ();

??? return rc;
}

修改完后,保存。

【2】修改lowlevel_init.S 文件

为了匹配mini2440 的存储器配置(总线上连接的Nor Flash 和SDRAM),需要修改lowlevel_init.S文件。这个所连接的Nor Flash位数有关。至于SDRAM的参数,可以从芯片手册查到。据说有人将其64MB的内存升到了128MB,其参数就是在这里修改的,有需要可以看MINI2440: Auto probe for SDRAM size 。以下的64MB 内存的参数修改:

打开/board/samsung/mini2440/lowlevel_init.S,定位到123行,修改如下:

/* REFRESH parameter */
#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 */
#if defined(CONFIG_S3C2440)
#define Trp??? 0x2 /* 4clk */
#define REFCNT?? 1012
#else
#define Trp??? 0x0 /* 2clk */
#define REFCNT?? 1113 /* period=15.6us,HCLK=60Mhz,(2048+1-15.6*60) */
#endif
/**************************************/

在这个 lowlevel_init.S 有一个小bug,使得无法使用OpenJTAG 下载到内存中直接运行,修正如下:

lowlevel_init:
?/* memory control configuration */
?/* make r0 relative the current location so that it */
?/* reads SMRDATA out of FLASH rather than memory ! */
?ldr???? r0,=SMRDATA
?//ldr r1,_TEXT_BASE
?ldr r1,=lowlevel_init
?sub r0,r0,r1
?adr r3,lowlevel_init /* r3 <- current position of code */
?add r0,r3
?ldr r1,=BWSCON /* Bus Width Status Controller */
?add???? r2,#13*4

修改完后,保存。

【3】修改开发板终端中命令行提示符

用gedit打开include/configs/mini2440.h头文件,定位到116行,其中的 "SMDK2410 # " 就是开发板在终端中显示的提示符,现在将其改为 "[u-boot@MINI2440]# " ,如下所示

/*
?* Miscellaneous configurable options
?*/
#define CONFIG_SYS_LONGHELP??? /* undef to save memory? */
#define CONFIG_SYS_PROMPT? "[u-boot@MINI2440]# " /* Monitor Command Prompt */

?【4】修改Nor Flash参数的部分定义

然后定位到157行附近,注释掉下面两个类型的Nor Flash设置,因为不是我们所使用的型号,然后加入新的定义,如下所示

/*-----------------------------------------------------------------------
?* 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_SST_39VF1601??????? 1??????? //添加mini2440开发板Nor Flash设置


?... ...

#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
#define PHYS_FLASH_SIZE? 0x00200000 /* 2MB */
#define CONFIG_SYS_MAX_FLASH_SECT (32) /* max number of sectors on one chip */
#define CONFIG_ENV_ADDR? (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET) /* addr of environment */
#endif

?宏 CFG_ENV_ADDR定义了存放uboot变量的地址,换算一下为1MB-64KB=960KB地方,而实际uboot编译出来的大小仅为120KB 左右,由此可以得出,即使从新烧录了新编译的uboot到Nor flash内,也不会影响先前设定使用的uboot变量。

修改完后,保存。

?

2.2,重新编译,运行测试

[root@localhost u-boot-2009.08]# make clean
Generating include/autoconf.mk
[root@localhost u-boot-2009.08]# make
... ...

arm-linux-objcopy -O srec u-boot u-boot.srec
arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
[root@localhost u-boot-2009.08]#
编译完成后,将根目录u-boot-2009.08下的u-boot.bin文件复制到/tftpboot目录下。在与开发板相连的终端中执行如下命令:

##### FriendlyARM BIOS 2.0 for 2440 #####
[x] format NAND FLASH for Linux
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[a] Absolute User Application
[n] Download Nboot for WinCE
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin
[d] Download & Run
[z] Download zImage into RAM
[g] Boot linux from RAM
[f] Format the nand flash
[b] Boot the system
[s] Set the boot parameters
[u] Backup NAND Flash to HOST through USB(upload)
[r] Restore NAND Flash from HOST through USB
[q] Goto shell of vivi
Enter your selection: d
Clear the free memory
USB host is connected. Waiting a download.

Now,Downloading [ADDRESS:31000000h,TOTAL:99674]
RECEIVED FILE SIZE:?? 99674 (97KB/S,1S)
Downloaded file at 0x30000000,size = 99664 bytes


U-Boot 2009.08 ( 5鏈?05 2011 - 22:39:33)

DRAM:? 64 MB
Flash:? 2 MB
In:??? serial
Out:?? serial
Err:?? serial
[u-boot@MINI2440]#

从运行结果看,Nor Flash的大小可以正确检测到了,命令行前面的名字也由原来的SMDK2410改成自己定义的[u-boot@MINI2440]# 了,但是有会出现bad CRC的警告信息,其实这并不是什么问题,只是还没有将环境变量设置到Nor Flash中,我们执行一下u-boot的:saveenv命令就可以了。如下所示:

[u-boot@MINI2440]# saveenv
Saving Environment to Flash...
Un-Protected 16 sectors
Erasing Flash...Erasing sector 64 ... ok.
Erasing sector 65 ... ok.
Erasing sector 66 ... ok.
Erasing sector 67 ... ok.
Erasing sector 68 ... ok.
Erasing sector 69 ... ok.
Erasing sector 70 ... ok.
Erasing sector 71 ... ok.
Erasing sector 72 ... ok.
Erasing sector 73 ... ok.
Erasing sector 74 ... ok.
Erasing sector 75 ... ok.
Erasing sector 76 ... ok.
Erasing sector 77 ... ok.
Erasing sector 78 ... ok.
Erasing sector 79 ... ok.
Erased 16 sectors
Writing to Flash... done
Protected 16 sectors
[u-boot@MINI2440]#

因为DRAM运行的是现在的u-boot,其下载命令还未实现,需要给开发板重新上电,再重新下载u-boot.bin到DRAM中运行

Enter your selection: d
Clear the free memory
USB host is connected. Waiting a download.

Now,TOTAL:99682]
RECEIVED FILE SIZE:?? 99682 (97KB/S,size = 99672 bytes


U-Boot 2009.08 ( 5鏈?05 2011 - 22:50:40)

DRAM:? 64 MB
Flash:? 2 MB
In:??? serial
Out:?? serial
Err:?? serial
[u-boot@MINI2440]#

可以观察到不会出现警告信息了,这时候u-boot已经对我们开发板上的Nor Flash完全支持了。

接下来将进入u-boot的第三阶段,为u-boot-2009.08增加nand flash支持。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读