Nor Flash的移植,以及提示符的修改。
1、首先将提示符由原来的SMDK2410修改为
u-boot@SMDK2440:
[root@Gong-Computer u-boot-2010.06]# vi include/configs/smdk2440.h
119 //#define CONFIG_SYS_PROMPT "SMDK2410 # " /* Monitor Command Prompt */
120 #define CONFIG_SYS_PROMPT "u-boot@SMDK2440 # " /* Monitor Command
Prompt(提示符)*/
然后修改Nor Flash的代码。
2、通
常,在嵌入式bootloader 中,有两种方式来引导启动内核:从Nor Flash 启动和从 Nand Flash 启动。
u-boot 中默认是从Nor Flash 启动的。
EN29LV160A特性:
Flexible Sector Architecture:
- One 16-Kbyte, two 8-Kbyte, one 32-Kbyte,
and thirty-one 64-Kbyte sectors (byte mode)
- One 8-Kword, two 4-Kword, one 16-Kword
and thirty-one 32-Kword sectors (word mode)
EN29LV160A是16位的Nor Flash,一
共存在35个页,前4页的数据较小,而后面的31页数据均为
64k字节,第一页数据为16K字节,第二、三页8K字节,第四段为32K字节.存在两种工作模式根据。
The signal set on the
BYTE# Pin controls whether the device data I/O pins DQ15-DQ0 operate in the byte or
word configuration. When the Byte# Pin is set
at logic ‘1’, then the device is in word configuration, DQ15-
DQ0 are active and are controlled by CE# and OE#. On the other hand, if the Byte# Pin is set
at logic ‘0’,
then the device is in byte configuration, and only data I/O pins DQ0-DQ7 are active and controlled by CE#
and OE#. The data I/O pins DQ8- DQ14 are tri-stated, and the DQ15 pin is used as an input for the LSB (A-1
) address function.
A bit cannot be programmed from a “0” back to a “1”. Only erase operations can convert a “0” to a “1”.
说明了BYTE决定了FLASH的模式,TQ2440的BYTE接了高电平,因此采用了Word模式。
TQ2440的ADDR1-ADDR20接到了Flash的A0-A19,另外两个A20和A21是没有作用的,这与
Flash封装相同但是大小不同存在很大的关系。
Nor Flash的片选端接在了TQ2440的nGCS0上,说明
了Nor Flash映射到内存映射的第0块区域,(阅读S3C2440A的第5章)
由于SMDK2410板子中支持AMD_LV400和AMD_LV800,因此需要添加关于EN29LV160A的支持,
2.1、屏蔽掉AMD_LV400和AMD_LV800,然后添加新的支持项CONFIG_EON_29LV160AB 1 。
/*新添加的芯片EON_29LV160AB*/
[root@Gong-Computer u-boot-2010.06]# vi include/configs/smdk2440.h
168 #define CONFIG_EON_29LV160AB 1
169
170 #define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */
171
/*屏蔽两种芯片的信息*/
174 #ifdef CONFIG_AMD_LV800
175 #define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
176 #define CONFIG_SYS_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
177 #define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x0F0000) /* addr of
environment */
178 #endif
179 #ifdef CONFIG_AMD_LV400
180 #define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
181 #define CONFIG_SYS_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
182 #define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000) /* addr of
environment */
183 #endif
186 /*添加新芯片的信息*/
187 #ifdef CONFIG_EON_29LV160AB
188 #define PHYS_FLASH_SIZE 0x200000 /*存储器的实际大小*/
189 #define CONFIG_SYS_MAX_FLASH_SECT (35) /*芯片的页数,也就是扇区数,35个,芯
片资料中有*/
190 #define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x80000)
191 /*环境变量的存储地址,0x80000,215K字,环境变量的首地址是在0x80000处*/
192 #endif
2.2、为flash添加ID号,这个ID 号是一个固定的值,由于是采用了bottom boot block ,从低地址到
高地址增长的形式。可知ID 号是2249。添加ID号的函数为:
[root@Gong-Computer u-boot-2010.06]# vi include/flash.h
182 /*添加两种不同扇区方式的ID标号,标号在手册中可以找到*/
183 #define EON_ID_LV160AB_T 0x22C422C4 /* LV160AB ID (16 M, top boot sector) */
184 /*top boot sect 是第一个分区在最高位,bottom boot sect 是第一个分区在最低位*/
185 #define EON_ID_LV160AB_B 0x22492249 /* LV160AB ID (16 M, bottom boot sect) */
2.3、同时查找EON公司的代号,便于后面添加信息。
173 /* Manufacturers inside bank 1 have ids like 0x01xx01xx */
174 #define EON_MANUFACT 0x011C011C /* EON manuf. ID in D23..D16, D7..D0 */ /
2.4、定义分区大小,同时实现操作,显示厂商信息
[root@Gong-Computer u-boot-2010.06]# vi board/samsung/smdk2440/flash.c
修改主分区的大小
32 //#define MAIN_SECT_SIZE 0x10000 /* 64 KB */
33 /*这个分区的大小是按着模式来分的,
34 *当按着字模式时,分区大小就是32K Word
35 *当按着字节模式时,分区的大小就是64K Byte
36 *TQ2440时按着字模式工作的,因此分区大小为32K
37 */
38 #define MAIN_SECT_SIZE 0x8000 /* 32 K Word */
39
40 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
理解两个宏定义:
58 #define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE +
(0x00000555 << 1)))
59 #define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE +
(0x000002AA << 1)))
这两句的理解是于硬件相关的,其中的CONFIG_SYS_FLASH_BASE 是指Flash对应的基地址,
同时后面的两个数是由芯片本身决定的,不同的芯片其参数不一样,需要查看芯片手册。Flash操作
过程中都是在一定的时间周期内在一定的地址写上特定的数据实现不同的操作的。在EN29LV1602
的芯片手册中规定了在两个不同的模式下的各种操作:
在字模式下: 在两个周期下分别对地址0x555和0x2AA写上相应的数据即可实现相应的操作。
在字节模式下:在两个周期下分别对地址0xAAA和0x555分别写上不同的数据实现相应的操作。
这两组地址都是对Flash芯片而言的绝对地址,但是对于CPU而言是一个相对地址,是相对于Flash
的基地址而言的,因此需要加上CONFIG_SYS_FLASH_BASE 。
由于TQ2440的ADDR1接在了EON29LV1602的A0上,因此每一次写相应的地址都需要左移1位,
才能正确的访问实际需要访问的地址,如果是ADDR0接在A0上,则不需要实现该操作,同时是按
着字模式进行控制,因此得到了相应的数据,如上所示。由于Flash就是处于第0块上,因此基地址
就是0x00000000.
修改ulong flash_init (void)
73 ulong flash_init (void)//初始化flash
.........
88 /*添加芯片的厂家信息*/
89 #elif defined(CONFIG_EON_29LV160AB)
90 (EON_MANUFACT & FLASH_VENDMASK) |/*添加厂商*/
91 (EON_ID_LV160AB_B & FLASH_TYPEMASK);/*添加芯片的ID号*/
修改每一次访问的大小,这个需要根据芯片进行实际的修改,EON_29LV1602的参数参看手册。
103 if (j <= 3) {
104 /* 1st one is 8 KB ,第一分区的大小是8K字*/
105 if (j == 0) {
106 flash_info[i].start[j] =
107 flashbase + 0;
108 }
109
110 /* 2nd and 3rd are both 4 KB ,第二第三分区的大小是4K 字*/
111 if ((j == 1) || (j == 2)) {
112 /*0x2000就是第一分区的8K,0x1000就是4K*/
113 flash_info[i].start[j] =
114 /* flashbase + 0x4000 + (j -
115 1) *
116 0x2000;*/
117 flashbase + 0x2000 + (j -
118 1)*
119 0x1000;
120 }
121
122 /* 4th 16 KB ,第四个分区的大小为16K*/
123 if (j == 3) {
124 flash_info[i].start[j] =
125 /* flashbase + 0x8000;*/
126 flashbase + 0x4000;
127 }
128 } else {/*其他的分区为32K*/
129 flash_info[i].start[j] =
130 flashbase + (j - 3) * MAIN_SECT_SIZE;
131 }
修改void flash_print_info (flash_info_t * info) //打印信息
150 void flash_print_info (flash_info_t * info) //打印信息
.....
case (AMD_MANUFACT & FLASH_VENDMASK):
156 printf ("AMD: ");
157 break;
158 /*添加答应厂商的信息*/
159 case (EON_MANUFACT & FLASH_VENDMASK):
160 printf("EON: ") ;
161 break;
171 case (AMD_ID_LV800B & FLASH_TYPEMASK):
172 printf ("1x Amd29LV800BB (8Mbit)\n");
173 break;
174 /*添加ID信息*/
175 case (EON_ID_LV160AB_B & FLASH_TYPEMASK):
176 printf ("1x EON_29LV160AB (16Mbit)\n");
177 break;
修改int flash_erase (flash_info_t * info, int s_first, int s_last)
203 int flash_erase (flash_info_t * info, int s_first, int s_last)
..........
218 /*厂商检测,需要确保正确操作*/
219 if ((info->flash_id & FLASH_VENDMASK) !=
220 /* (AMD_MANUFACT & FLASH_VENDMASK)) {*/
221 (EON_MANUFACT & FLASH_VENDMASK)) {
222 return ERR_UNKNOWN_FLASH_VENDOR;
223 }
编译的过程中可能会出错,检查自己修改过的代码应该就能找到原因了。
编译调试:make distclean
make clean
make smdk2440_config
make -d
Invoking recipe from Makefile:426 to update target `System.map'.
Putting child 0x8adb688 (System.map) PID 9015 on the chain.
Live child 0x8adb688 (System.map) PID 9015
Reaping winning child 0x8adb688 PID 9015
Removing child 0x8adb688 PID 9015 from chain.
Successfully remade target file `System.map'.
Finished prerequisites of target file `all'.
Must remake target `all'.
Successfully remade target file `all'.
编译成功
调试,将debug的u-boot通过tftp加载到内存中,然后通过go 命令测试是否成功。
EmbedSky> tftpboot 0x30000000 u-boot_debug_nor.bin
dm9000 i/o: 0x20000300, id: 0x90000a46
MAC: 0a:1b:2c:3d:4e:5f
TFTP from server 192.168.10.154; our IP address is 192.168.10.122
Filename 'u-boot_debug_nor.bin'.
Load address: 0x30000000
Loading: T #######
done
Bytes transferred = 101252 (18b84 hex)
EmbedSky> go 0x30000000
## Starting application at 0x30000000 ...
U-Boot 2010.06 (Oct 06 2011 - 21:00:13)
Flash: 2 MiB
In: serial
Out: serial
Err: serial
Net: CS8900-0
u-boot@SMDK2440 #
以上说明修改的Nor Flash成功。
u-boot@SMDK2440 # printenv
bootdelay=3
baudrate=115200
ipaddr=10.0.0.110
serverip=10.0.0.1
netmask=255.255.255.0
ethact=CS8900-0
stdin=serial
stdout=serial
stderr=serial
Environment size: 143/65532 bytes
u-boot@SMDK2440 # saveenv
Saving Environment to Flash...
Un-Protected 2 sectors
Erasing Flash...Erasing sector 19 ... ok.
Erasing sector 20 ... ok.
Erased 2 sectors
Writing to Flash... done
Protected 2 sectors
u-boot@SMDK2440 #
命令测试成功。