转载地址:http://bbs.witech.com.cn/thread-4094-1-1.html
平台:
虚拟机:VirtualBox Ubuntu 9.10
文件传输工具:SSHSecureShellClient-3.2.9
交叉编译环境:arm-linux-gcc-4.3.2
与开发板通信:tftp
Uboot移植步骤一:
建立交叉编译环境:arm-linux-gcc-4.3.2
1.将arm-linux-gcc-4.3.2.tgz复制到任意路径下;
2.确保安装了标准C开发环境,sudo apt-get install build-essential libncurses5-dev;
3.在终端进入arm-linux-gcc-4.3.2.tgz存放目录,再sudo tar -zxvf arm-linux-gcc-4.3.2.tgz -C /(注意大写C字母后留一个空格),这样会自动解压到/usr/local/4.3.2目录下);
4.修改环境变量,使交叉编译环境生效。
vim ~/.profile
在这个文件最后添加上自己的环境变量:export PATH=$PATH:/usr/local/arm/4.3.2/bin
然后在终端执行source ~/.profile ,即可立即生效。
5. arm-linux-gcc -v
Using built-in specs.
Target: arm-none-linux-gnueabi
Configured with: /scratch/julian/lite-respin/linux/src/gcc-4.3/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-symvers=gnu --enable-__cxa_atexit --with-pkgversion='Sourcery G++ Lite 2008q3-72' --with-bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc --with-build-sysroot=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/libc --with-gmp=/scratch/julian/lite-respin/linux/obj/host-libs-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr --with-mpfr=/scratch/julian/lite-respin/linux/obj/host-libs-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr --disable-libgomp --enable-poison-system-directories --with-build-time-tools=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/bin --with-build-time-tools=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/bin
Thread model: posix
gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72)
U-boot-2009.08移植TE2440II开发板--在SDRAM中运行
因为串口的波特率问题纠结了我2天,嘿嘿。
1.首先创建自己板子的目录
cd u-boot-2009.08
mkdir board/samsung/TE2440II
cp board/samsung/smdk2410/* board/samsung/TE2440II/
mv board/samsung/TE2440II/smdk2410.c board/samsung/TE2440II/TE2440II.c
2.添加配置文件
cp include/configs/smdk2410.h include/configs/TE2440II.h
在include/configs/smdk2410.h include/configs/TE2440II.h中添加
#define CONFIG_SKIP_LOWLEVEL_INIT 1
因为是先在SDRAM中运行,所以要跳过底层的初始化。暂时没有添加CONFIG_2440,用原来的CONFIG_2410,以提高移植速度。
注意暂时不要添加#define CONFIG_SKIP_RELOCATE_UBOOT 1
否则就要更改你的下载地址为0x33f80000,让他去搬运代码吧
3.修改board/samsung/TE2440II/ 目录下的Makefile,把COBJS := 修改为
COBJS := TE2440II.o flash.o
4.修改顶层Makefile
TE2440II_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t TE2440II samsung s3c24x0
注意有个Tab键
5. 修改顶层Makefile文件,在CROSS_COMPILE ?=后面添加自己的交叉编译工具。
CROSS_COMPILE ?= /usr/local/arm/4.3.2/bin/arm-linux-
6.完成这几步后编译一下
make TE2440II_config
make
下到SDRAM中,终端应该没有任何信息,需要设置波特率。
1. 修改TE2440II.c文件
#elif FCLK_SPEED==1 /* Fout = 405MHz */
#define M_MDIV 0x7f
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
2. 修改cpu/arm920t/start.S
外部晶振为12MHz,通过MPLLCON设置MPLL为405M
#if defined(CONFIG_S3C2410)
#define MPLLCON 0x4C000004
#define UPLLCON 0x4c000008
#define LOCKTIME 0x4C000000
#define CAMDIVN 0x4C000018
ldr r0,=LOCKTIME
ldr r1,=0xffffffff
str r1,[r0]
//清除摄像头分频寄存器的值
ldr r0,=CAMDIVN
mov r1,#0
str r1,[r0]
ldr r0, =CLKDIVN
mov r1, #5
str r1,[r0]
//手册说HDIVN不为0,加这个
mrc p15, 0, r1, c1, c0, 0 //read ctrl register
orr r1, r1, #0xc0000000 //Asynchronous
mcr p15, 0, r1, c1, c0, 0 //write ctrl register
ldr r0, =UPLLCON //同时修改UPLLCON和MPLLCON需要先修
ldr r1, =0x00038022 //改UPLLCON,且之间要间隔至少7个nop
str r1,[r0] //手册有些
nop
nop
nop
nop
nop
nop
nop
nop
ldr r0, =MPLLCON
ldr r1, =0x0007f021
str r1,[r0]
#endif
3. 修改cpu/arm920t/s3c24x0/speed.c
由于S3C2440和S3C2410的MPLL计算公式改变了,所以要改一下。
get_PLLCLK改成这样
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 (pllreg == MPLL) //MPLL的算法和UPLL是不同的。这里m=2*m
{
m <<= 1;
}
p = ((r & 0x003F0) >> 4) + 2;
s = r & 0x3;
return ((CONFIG_SYS_CLK_FREQ * m) / (p << s));
}
get_HCLK改成这样
/* return HCLK frequency */
ulong get_HCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
return get_FCLK()/4;
//return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
}
get_PCLK改成这样
/* return PCLK frequency */
ulong get_PCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
return get_HCLK()/2;
//return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());
}
4. 我出问题的地方是串口,显示的基本跟正常的一样,但是显示为乱码,是串口波特率的问题。在drivers/serial/serial_s3c24x0.c中,修改
uart->UBRDIV = 27;
我直接设定了,不用鸟u-boot再鸟算了,他自己怎么也算不对,我帮他。
5. make TE2440II_config
make
下载到SDRAM中,哈哈。
U-boot-2009.08移植TE2440II开发板--支持Norflash
TE2440II开发板使用的Norflash是INTEL的JS28F320J3D75,4M,32个block,每个128KB。本文添加对Norflash的支持,使Uboot可以烧录到Norflash,从Norflash启动,并执行Norflash下的命令。
这样需要注释掉 /include/configs/TE2440II.h中的
#define CONFIG_SKIP_LOWLEVEL_INIT 1
//#define CONFIG_SKIP_RELOCATE_UBOOT 1
把include/configs/TE2440II.h的Physical Memory Map和FLASH and environment organization修改为,这里添加了/board/cmi/flash.c中部份变量的宏定义。FLASH and environment organization这里的sector指的是手册中的bank,所以大小是128KB,为32块。#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x40000),这个偏移是自己定的,是放环境变量的,只要不在uboot的代码区就可以。
CONFIG_SYS_FLASH_ERASE_TOUT和CONFIG_SYS_FLASH_WRITE_TOUT是超时的时间,如果小了,自己改大些。cpu/arm920t/s3c24x0/timer.c中讲述了怎么获得时间的。
/*-----------------------------------------------------------------------
* Physical Memory Map
*/
#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
#define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */
#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
#define FLASH_BASE0_PRELIM PHYS_FLASH_1
#define CONFIG_SYS_MONITOR_BASE TEXT_BASE
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CONFIG_INTEL_JS28F320 1
#define PHYS_FLASH_SIZE 0x400000 /* 4M */
#define CONFIG_SYS_MAX_FLASH_SECT 32
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x40000)
/* timeout values are in ticks */
#define CONFIG_SYS_FLASH_ERASE_TOUT (2*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
#define CONFIG_SYS_FLASH_WRITE_TOUT (2*CONFIG_SYS_HZ) /* Timeout for Flash Write */
#define CONFIG_ENV_IS_IN_FLASH 1
#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
#endif /* __CONFIG_H */
用board/cmi/下的flash.c文件替换board/samsung/TE2440II/下的flash.c,因为cmi目录下的正好是JS28F320J3D75的驱动文件。删除这个write_short函数的申明和定 义、删除write_buff函数。替换成下面的两个函数:
/******************************************************************************************************
* Copy memory to flash.
*/
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
ulong cp, wp;
ushort data;
int l;
int i, rc;
wp = (addr & ~1); /* get lower word aligned address */
/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0)
{
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 8);
}
for (; i<2 && cnt>0; ++i) {
data = (data >> 8) | (*src++ << 8);
--cnt;
++cp;
}
for (; cnt==0 && i<2; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 8);
}
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 2;
}
/*
* handle word aligned part
*/
while (cnt >= 2) {
data = *((vu_short*)src);
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
src += 2;
wp += 2;
cnt -= 2;
}
if (cnt == 0) {
return ERR_OK;
}
/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
data = (data >> 8) | (*src++ << 8);
--cnt;
}
for (; i<2; ++i, ++cp) {
data = (data >> 8) | (*(uchar *)cp << 8);
}
return write_word(info, wp, data);
}
/******************************************************************************************************
* Copy memory to flash.
*/
static int write_word (flash_info_t *info, ulong dest, ushort data)
{
vu_short *addr = (vu_short *)dest, val;
int rc = ERR_OK;
int flag;
/* Check if Flash is (sufficiently) erased , fix by kavin*/
if ((*addr & data) != data)
return ERR_NOT_ERASED;
/*
* Disable interrupts which might cause a timeout
* here. Remember that our exception vectors are
* at address 0 in the flash, and we don't want a
* (ticker) exception to happen while the flash
* chip is in programming mode.
*/
flag = disable_interrupts();
/* clear status register command */
*addr = 0x50;
/* program set-up command */
*addr = 0x40;
/* latch address/data */
*addr = data;
/* arm simple, non interrupt dependent timer */
reset_timer_masked();
/* wait while polling the status register */
while(((val = *addr) & 0x80) != 0x80)
{
if (get_timer_masked() > CONFIG_SYS_FLASH_WRITE_TOUT) {
rc = ERR_TIMOUT;
/* suspend program command */
*addr = 0xB0;
goto outahere;
}
}
if(val & 0x1A) { /* check for error */
printf("\nFlash write error %02x at address %08lx\n",
(int)val, (unsigned long)dest);
if(val & (1<<3)) {
printf("Voltage range error.\n");
rc = ERR_PROG_ERROR;
goto outahere;
}
if(val & (1<<1)) {
printf("Device protect error.\n");
rc = ERR_PROTECTED;
goto outahere;
}
if(val & (1<<4)) {
printf("Programming error.\n");
rc = ERR_PROG_ERROR;
goto outahere;
}
rc = ERR_PROG_ERROR;
goto outahere;
}
outahere:
/* read array command */
*addr = 0xFF;
if (flag)
enable_interrupts();
return rc;
}
修改flash.c文件中的一个宏定义:
把:
#define FLASH_BLOCK_SIZE 0x00010000
改为:
#define FLASH_BLOCK_SIZE 0x00020000
修改开发板目录下的lowlevel_init.S文件中SDARM刷新参数为:
#define REFCNT 1258 /* period=7.8125us, HCLK=405/4 Mhz, (2048+1-7.8125*405/4) */
Lowlevel_init.S中对SDRAM进行了初始化,因为我们要把第二阶段的代码搬运到SDRAM中,REFCNT是刷新计数器,这个在移植的时候是一定要修改的。手册上有公式:Refresh period = (2^11-refresh_count+1)/HCLK,我使用的这款芯片在datasheet写着8192Refresh cycle/64ms,所以一个刷新周期为64ms/8192=7.8125us。目前公认的标准是,存储体中电容中数据有效保存期上限是64ms,也就是说每一行刷新的循环周期是64ms,这样刷新的速度就是:行数量/64ms。我的理解是CPU并不知道你用的SDRAM的刷新速度是多少,特殊功能寄存器也没有直接传递刷新速度的位,但是有一个刷新计数器,可以通过刷新计数器间接获得刷新速度,所以要设定刷新计数器。
然后就可以烧录Norflash了。
支持DM9000A
今天看了Nandflash部分,感觉不是一时半会儿能搞定的,所以先避实就虚呵呵,搞定了网卡。飞凌TE24440II使用的是双网卡,CS8900和DM9000A。已经有很好的网卡驱动代码,我们只要根据自己的板子适当修改一下就行,所以难度比Nandflash低得多。废话少说,看看怎么改。
首先注释掉跟CS8900有关的部分
//#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
//#define CS8900_BASE 0x19000300
//#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
在include/configs/TE2440II.h中添加
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_NET_MULTI 1
#define CONFIG_DM9000_NO_SROM 1
#define CONFIG_DM9000_BASE 0x20000000 //网卡片选地址
#define DM9000_IO CONFIG_DM9000_BASE //网卡命令端口
#define DM9000_DATA (CONFIG_DM9000_BASE+4) //网卡数据端口
//增加ping命令
#define CONFIG_CMD_PING
//MAC地址
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
#define CONFIG_NETMASK 255.255.255.0
//开发板的IP地址
#define CONFIG_IPADDR 192.168.1.105
//Linux主机的IP地址
#define CONFIG_SERVERIP 192.168.1.103
注释掉以前跟这个重复的。
添加网卡初始化代码: 修改board/samsung/TE2440II/TE2440II.c
#include <net.h>
#include <netdev.h>
#ifdef CONFIG_DRIVER_DM9000
int board_eth_init(bd_t *bis)
{
return dm9000_initialize(bis);
}
#endif
在drivers/net/dm9000x.c中修改(屏蔽掉dm9000_init中的这一部分,不然使用网卡的时候会报“could not establish link”的错误)
#if 0
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
i++;
if (i == 10000) {
printf("could not establish link\n");
return 0;
}
}
#endif
修改drivers/net/dm9000x.c。屏蔽掉dm9000_halt函数中的内容,否则ping不通。
/*
Stop the interface.
The interface is stopped when it is brought.
*/
static void dm9000_halt(struct eth_device *netdev)
{
//DM9000_DBG("%sn", __func__);
///* RESET devie */
//phy_write(0, 0x8000); /* PHY RESET */
//DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
//DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
//DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
}
重新编译烧录到Norflash就可以了。
这里需要注意的是#define CONFIG_DM9000_BASE 0x20000000 //网卡片选地址。而不是0x20003000,这个是DM9000,而我们使用的是DM9000A。因为CMD接在ADDR2上所以#define DM9000_DATA (CONFIG_DM9000_BASE+4)。因为DM9000A的地址信号和数据信号复用,CMD引脚决定传输的是地址信号还是数据信号。数据手册上说CMD为0时是地址信号所以DM9000_IO CONFIG_DM9000_BASE,CMD为1时,是数据信号,所以#define DM9000_DATA (CONFIG_DM9000_BASE+4)。DM9000A内部有一个4K Dword SRAM,因为数据线和地址线是复用的,所以如果这部分用地址线进行寻址,范围是16KB,所以在 0x20000000~0x20000000+16KB范围内都可以的。所以0x20003000是碰巧在这里的。第一次ping不同,第二次开始就可以ping通了,这个是正常现象。
支持Nandflash操作
分析了一下Uboot中Nandflash的驱动,u-boot-2009.08使用的是和Linux内核一样的MTD(内存技术设备)架构。在Uboot下对Nand的支持体现在命令行下实现对nand flash的操作,为:nand info,nand device,nand read,nand write,nand erease,nand bad。用到的主要数据结构有:struct nand_flash_dev,struct nand_chip。前者包括主要的芯片型号,存储容量,设备ID,I/O总线宽度等信息;后者是具体对nand flash进行操作时用到的信息。
对Nandflash驱动代码的分析:
1)lib_arm/board.c中start_armboot()函数中调用了nand_init()。
2)nand_init()函数定义在drivers/mtd/nand/Nand.c文件中,调用了同文件下的nand_init_chip()函数和board_nand_select_device()函数,并累加Nandflash的总大小。
3)nand_init_chip()函数初始化了IO_ADDR_R和IO_ADDR_W,调用board_nand_init()和nand_scan()。(在drivers/mtd/nand/S3c2410_nand.c中)
4)board_nand_init()函数在drivers/mtd/nand/S3c2410_nand.c中,初始化NFCONF配置寄存器。主要对struct nand_chip结构体的函数指针赋值,让他们指向自己为nand驱动编写的一些函数,该数据结构在include/linux/mtd/nand.h中定义。
5)nand_scan()函数在drivers/mtd/nand/Nand_base.c文件中定义,并调用了nand_scan_ident()和nand_scan_tail()函数。
6)nand_scan_ident()调用了同文件下的nand_set_defaults()和nand_get_flash_type(),nand_set_defaults()函数对struct nand_chip结构体的函数指针进行了赋值。在此函数中cmdfunc映射到了nand_command,nand_get_flash_type()读取了厂商和设备ID,并对struct nand_chip结构体的变量和mtd_info进行初始化操作。
7)nand_scan_tail()进行了ECC的设置和剩下的MTD驱动函数的初始化。
8)nand_select_device()函数用来打开或关闭nand芯片,-1是打开,0是关闭。chip->cmd_ctrl映射到hwcontrol(在drivers/mtd/nand/S3c2410_nand.c的board_nand_init()函数中)。
9)返回nand_init(),这样nand的初始化就完成了。
移植Nandflash驱动,主要是修改S3c2410_nand.c。
看一个Read操作的例子:
以common/env_nand.c里读取Nandflash的环境变量为例,
env_nand.c中调用了nand_read(&nand_info[0], offset, &len, char_ptr);
nand_read在include/nand.h中定义。
static inline int nand_read(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
{
return info->read(info, ofs, *len, (size_t *)len, buf);
}
nand_read又调用info->read,即mtd_info的read,mtd_info与nand_info_t同名。
mtd_info的read函数在drivers/nand/nand_base.c中的nand_scan_tail函数中被映射到nand_read(),在nand_read()中调用nand_do_read_ops()。这是最后一层,通过调用nand_chip中的函数完成带ECC的读操作。
现在进行移植:
修改include/configs/TE2440II.h如下
/*
* Command line configuration.
*/
#include <config_cmd_default.h>
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMDLINE_EDITING
#ifdef CONFIG_CMDLINE_EDITING
#undef CONFIG_AUTO_COMPLETE
#else
#define CONFIG_AUTO_COMLETE
#endif
/*
* NAND flash setting
*/
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE 0x4e000000
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define NAND_SAMSUNG_LP_OPTIONS 1
#define CONFIG_NAND_S3C2440 1
#endif
环境变量那部分修改:
//#define CONFIG_ENV_IS_IN_FLASH 1
#define CONFIG_ENV_IS_IN_NAND 1 /*环境变量的保存位置*/
在drivers/mtd/nand/Makefile文件中添加:
COBJS-y += s3c2440_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
我们最重要的是修改s3c2410_nand.c,把它复制重命名为s3c2440_nand.c,因为s3c2410和s3c2440在nand控制器方面有很多不同,所以要进行移植。
修改s3c2440_nand.c为:
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCONT __REGi(NF_BASE + 0x4)
#define NFCMD __REGb(NF_BASE + 0x8)
#define NFADDR __REGb(NF_BASE + 0xc)
#define NFDATA __REGb(NF_BASE + 0x10)
#define NFMECCD0 __REGi(NF_BASE + 0x14)
#define NFMECCD1 __REGi(NF_BASE + 0x18)
#define NFSECCD __REGi(NF_BASE + 0x1C)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NFSTAT0 __REGi(NF_BASE + 0x24)
#define NFSTAT1 __REGi(NF_BASE + 0x28)
#define NFMECC0 __REGi(NF_BASE + 0x2C)
#define NFMECC1 __REGi(NF_BASE + 0x30)
#define NFSECC __REGi(NF_BASE + 0x34)
#define NFSBLK __REGi(NF_BASE + 0x38)
#define NFEBLK __REGi(NF_BASE + 0x3c)
#define S3C2440_NFCONT_nCE (1<<1)
#define S3C2440_ADDR_NALE 0x0c
#define S3C2440_ADDR_NCLE 0x08
ulong IO_ADDR_W = NF_BASE;
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
if (ctrl & NAND_CTRL_CHANGE) {
IO_ADDR_W = NF_BASE;
if (!(ctrl & NAND_CLE)) //要写的是地址
{
IO_ADDR_W |= S3C2440_ADDR_NALE;}
if (!(ctrl & NAND_ALE)) //要写的是命令
{
IO_ADDR_W |= S3C2440_ADDR_NCLE;}
if (ctrl & NAND_NCE)
{NFCONT &= ~S3C2440_NFCONT_nCE; //使能nand flash
//DEBUGN("NFCONT is 0x%x ",NFCONT);
//DEBUGN("nand Enable ");
}
else
{NFCONT |= S3C2440_NFCONT_nCE; //禁止nand flash
//DEBUGN("nand disable ");
}
}
if (cmd != NAND_CMD_NONE)
writeb(cmd,(void *)IO_ADDR_W);
}
static int s3c2440_dev_ready(struct mtd_info *mtd)
{
DEBUGN("dev_ready\n");
return (NFSTAT & 0x01);
}
/******************************************************************************************/
int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
DEBUGN("board_nand_init()\n");
clk_power->CLKCON |= (1 << 4);
DEBUGN("CONFIG_S3C2440\n");
twrph0 = 4; twrph1 = 2; tacls = 0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
NFCONF = cfg;
//DEBUGN("cfg is %x\n",cfg);
//DEBUGN("NFCONF is %lx\n",NFCONF);
cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;
//DEBUGN("cfg is %lx\n",cfg);
//DEBUGN("NFCONT is %x\n",NFCONT);
/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
/* read_buf and write_buf are default */
/* read_byte and write_byte are default */
/* hwcontrol always must be implemented */
nand->cmd_ctrl = s3c2440_hwcontrol;
nand->dev_ready = s3c2440_dev_ready;
return 0;
}
s3c2440_hwcontrol函数主要控制是写命令还是写地址。
我遇到的问题,由于board_nand_init()函数我没有添加return 0,导致后面的判断没法进行,结果读出的NAND为0MiB,所以移植一定要仔细阅读源码,还有个问题就是uboot的打印信息中出现NAND_ECC_NONE selected by board driver. This is not recommended!!,这根ECC的校验模式有关,有人说“据说vivi或uboot通过软件算法产生的ecc校验码于S3C2410 NAND Flash 控制器产生的ecc校验码不一致”,所以我就没改什么,我把那个打印信息注释掉了。
支持Nandflash启动
从nandflash启动最关键的部分是rellocated,即代码重定位。s3c2440数据手册有这么一段,所以代码重定位是由nandflash控制器自动完成的,而不是一些人说的由CPU完成的。
在include/configs/TE2440II.h中添加nandflash控制器的定义:
/*
* NAND flash setting
*/
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE 0x4e000000
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define NAND_SAMSUNG_LP_OPTIONS 1 //大页要添加这个
#define CONFIG_NAND_S3C2440 1
#define CONFIG_S3C2440_NAND_BOOT 1
#define NAND_CTL_BASE 0x4E000000
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFADDR 0x0c
#define oNFDATA 0x10
#define oNFCMD 0x08
#define oNFSTAT 0x20
#define oNFECC 0x2c
#endif
在
/*
* Command line configuration.
*/
下添加
#define CONFIG_CMD_NAND
修改环境变量那部分
//#undef CONFIG_ENV_IS_IN_FLASH 1
#define CONFIG_ENV_IS_IN_NAND 1
其次,修改cpu/arm920t/start.S这个文件,使u-boot从Nand Flash启动
为了让他自动识别是从norflash还是从nandflash启动添加,BWSCON的第2,1为即OM1,OM0。为00时是从nandflash启动,其他为从norflash启动,判断OM1和OM0,就可以让uboot自动识别启动方式。
#define BWSCON 0x48000000
ldr r0, =BWSCON
ldr r1,[r0]
ands r1, r1, #0x6
beq nand_boot
nor_boot:
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
添加nandflash的启动代码,核心是relocated部分。首先设置nandflash控制器,然后将nandflash中从0开始的uboot复制到SDRAM中的TEXT_BASE处,TEXT_BASE在config.mk中定义,值为0x33f80000。复制好后,比较nandflash和SDRAM中的数据,如果前4K相同,表示搬移成功。下面的汇编代码注意ATPC标准规定r0~r3,用于参数传递和返回值。
/********************************************************/
//#define CONFIG_S3C2440_NAND_BOOT 1
nand_boot:
#define CONFIG_S3C2440_NAND_BOOT 1
#define NAND_CTL_BASE 0x4E000000
/* Offset */
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFCMD 0x08
#define oNFSTAT 0x20
#define LENGTH_UBOOT 0x40000
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
ldr r2, =((1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
str r2, [r1, #oNFCONT]
ldr r2, [r1, #oNFCONT]
ldr r2, =(0x6) @ RnB Clear
str r2, [r1, #oNFSTAT]
ldr r2, [r1, #oNFSTAT]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x4
beq nand2
ldr r2, [r1, #oNFCONT]
orr r2, r2, #0x2 @ Flash Memory Chip Disable
str r2, [r1, #oNFCONT]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy U-Boot to RAM
ldr r0, =TEXT_BASE //传递给C代码的第一个参数:u-boot在RAM中的起始地址
mov r1, #0x0 //传递给C代码的第二个参数:Nand Flash的起始地址
mov r2, #LENGTH_UBOOT //传递给C代码的第三个参数:u-boot的长度大小
/**********************************************************/
/************************************************************/
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2:
b loop2 @ infinite loop
ok_nand_read:
@ verify
mov r0, #0
ldr r1, =TEXT_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq stack_setup
bne go_next
notmatch:
loop3:
b loop3 @ infinite loop
#endif
/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
ldr pc, _start_armboot
_start_armboot: .word start_armboot
#define STACK_BASE 0x33ff8000
#define STACK_SIZE 0x10000
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
在board/samsung/TE2440II/目录下添加nand_read.c文件,内容如下,在K9F2G08的datasheet中有这么一段
所以地址由5个周期传完。前两个周期用来寻页内地址。后三个周期是页间寻址。1device=2048block=2048*64page=2048*64*(2k+64)Bytes
#include <config.h>
#include <linux/mtd/nand.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGw(x) (*(volatile unsigned short *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCONT __REGi(NF_BASE + 0x4)
#define NFCMD __REGb(NF_BASE + 0x8)
#define NFADDR __REGb(NF_BASE + 0xc)
#define NFDATA __REGb(NF_BASE + 0x10)
#define NFDATA16 __REGw(NF_BASE + 0x10)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NFSTAT_BUSY (1 << 2)
#define nand_select() (NFCONT &= ~(1 << 1))
#define nand_deselect() (NFCONT |= (1 << 1))
#define nand_clear_RnB() (NFSTAT |= NFSTAT_BUSY)
static inline void nand_wait(void)
{
int i;
while (!(NFSTAT & NFSTAT_BUSY))
for (i=0; i<10; i++);
}
/* configuration for 2440 with 2048byte sized flash */
#define NAND_5_ADDR_CYCLE
#define NAND_PAGE_SIZE 2048
#define BAD_BLOCK_OFFSET NAND_PAGE_SIZE
#define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1)
#define NAND_BLOCK_SIZE (NAND_PAGE_SIZE * 64)
static int nand_read_page_ll(unsigned char *buf, unsigned long addr)
{
unsigned int i, page_num;
nand_clear_RnB();
NFCMD = NAND_CMD_READ0;
page_num = addr >> 11; /* addr / 2048 */
/* Write Address */
NFADDR = 0;
NFADDR = 0;
NFADDR = page_num & 0xff;
NFADDR = (page_num >> 8) & 0xff;
NFADDR = (page_num >> 16) & 0xff;
NFCMD = NAND_CMD_READSTART;
nand_wait();
for (i = 0; i < NAND_PAGE_SIZE; i++)
{
*buf = (NFDATA & 0xff);
buf++;
}
return NAND_PAGE_SIZE;
}
/* low level nand read function */
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
{
return -1; /* invalid alignment */
}
/* chip Enable */
nand_select();
nand_clear_RnB();
for (i=0; i<10; i++);
for (i=start_addr; i < (start_addr + size);)
{
j = nand_read_page_ll(buf, i);
i += j;
buf += j;
}
/* chip Disable */
nand_deselect();
return 0;
}
然后在Makefile中添加
COBJS := my2440.o flash.o nand_read.o
修改TE2440II下的链接脚本u-boot.lds,使初始化和重定位代码被链接到前4KB。
.text :
{
cpu/arm920t/start.o (.text)
board/samsung/my2440/lowlevel_init.o (.text)
board/samsung/my2440/nand_read.o (.text)
*(.text)
}
支持东华 3.5寸LCD输出console信息和BMP图片、logo
由于linux启动代码,仍然出现乱码,而我将启动信息输出到lcd就没有乱码。暂时这个问题还没有解决,lcd其实早已完成,今天整理下,再解决那个问题。
下面是我绘制的主要的lcd驱动调用流程图。start_armboot()在lib_arm/board.c中,stdio_init()在common/stdio.cdrv_video_init(),video_init(),video_logo (),video_fb_address()在drivers/video/cfb_console.c中,video_hw_init()在drivers/video/s3c2410_fb.c中,board_video_init()在board/samsung/TE2440II/TE2440II.c。
最终调用了board_video_init()函数,这个函数由我们自己来编写,由于以前写过裸机的lcd程序,所以时序就可以直接拿来用,不用调了,哈哈。在这个函数中主要还是对那5个lcd的控制寄存器进行初始化。这里要注意根据不同的屏,进行x,y的调整,我用的是东华WXCAT35-TG3#001,主要就是初始化一个GraphicDevice *pGD结构体。
view plaincopy to clipboardprint?
#define MVAL (0)
#define MVAL_USED (0) //0=each frame 1=rate by MVAL
#define INVVDEN (0) //0=normal 1=inverted
#define BSWP (0) //Byte swap control
#define HWSWP (0) //Half word swap control
//TFT 240320
#define LCD_XSIZE_TFT_240320 (320)
#define LCD_YSIZE_TFT_240320 (240)
//TFT240320
#define HOZVAL_TFT_240320 (LCD_XSIZE_TFT_240320-1)
#define LINEVAL_TFT_240320 (LCD_YSIZE_TFT_240320-1)
//Timing parameter for WXCAT35-TG3#001"
#define VBPD_240320 (3)
#define VFPD_240320 (5)
#define VSPW_240320 (15)
#define HBPD_240320 (58)
#define HFPD_240320 (15)
#define HSPW_240320_WXCAT35 (8) //Adjust the horizontal displacement of the screen
#define CLKVAL_TFT_240320 (7)
//FCLK=405MHz,HCLK=101.25MHz,VCLK=4602272Hz
void board_video_init(GraphicDevice *pGD)
{
S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
/* FIXME: select LCM type by env variable */
/* Configuration for GTA01 LCM on QT2410 */
lcd->LCDCON1 = 0x00000778; /* CLKVAL=7, BPPMODE=16bpp, TFT, ENVID=0 */
lcd->LCDCON2 = (VBPD_240320<<24)|(LINEVAL_TFT_240320<<14)|(VFPD_240320<<6)|(VSPW_240320);
lcd->LCDCON3 = (HBPD_240320<<19)|(HOZVAL_TFT_240320<<8)|(HFPD_240320);
lcd->LCDCON4 = (MVAL<<8)|(HSPW_240320_WXCAT35);
lcd->LCDCON5 = 0x00000f09;
lcd->LPCSEL = 0x00000000;
}
明白上边的流程后一切变得很简单,只要根据自己的屏调整好时序就行了。添加一个驱动文件这个是一个外国的牛人已经写好的。在drivers/video/下添加s3c2410_fb.c。代码如下:
view plaincopy to clipboardprint?
/*
* (C) Copyright 2006 by OpenMoko, Inc.
* Author: Harald Welte <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#if defined(CONFIG_VIDEO_S3C2410)
#include <video_fb.h>
#include "videomodes.h"
#include <s3c2410.h>
/*
* Export Graphic Device
*/
GraphicDevice smi;
#define VIDEO_MEM_SIZE 0x200000 /* 240x320x16bit = 0x25800 bytes */
extern void board_video_init(GraphicDevice *pGD);
/*******************************************************************************
*
* Init video chip with common Linux graphic modes (lilo)
*/
void *video_hw_init (void)
{
S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();
GraphicDevice *pGD = (GraphicDevice *)&smi;
int videomode;
unsigned long t1, hsynch, vsynch;
char *penv;
int tmp, i, bits_per_pixel;
struct ctfb_res_modes *res_mode;
struct ctfb_res_modes var_mode;
// unsigned char videoout;
/* Search for video chip */
printf("Video: ");
tmp = 0;
videomode = CFG_SYS_DEFAULT_VIDEO_MODE;
/* get video mode via environment */
if ((penv = getenv ("videomode")) != NULL) {
/* deceide if it is a string */
if (penv[0] <= '9') {
videomode = (int) simple_strtoul (penv, NULL, 16);
tmp = 1;
}
} else {
tmp = 1;
}
if (tmp) {
/* parameter are vesa modes */
/* search params */
for (i = 0; i < VESA_MODES_COUNT; i++) {
if (vesa_modes.vesanr == videomode)
break;
}
if (i == VESA_MODES_COUNT) {
printf ("no VESA Mode found, switching to mode 0x%x ",
CFG_SYS_DEFAULT_VIDEO_MODE);
i = 0;
}
res_mode =
(struct ctfb_res_modes *) &res_mode_init[vesa_modes.
resindex];
bits_per_pixel = vesa_modes.bits_per_pixel;
}
else {
res_mode = (struct ctfb_res_modes *) &var_mode;
bits_per_pixel = video_get_params (res_mode, penv);
}
/* calculate hsynch and vsynch freq (info only) */
t1 = (res_mode->left_margin + res_mode->xres +
res_mode->right_margin + res_mode->hsync_len) / 8;
t1 *= 8;
t1 *= res_mode->pixclock;
t1 /= 1000;
hsynch = 1000000000L / t1;
t1 *=
(res_mode->upper_margin + res_mode->yres +
res_mode->lower_margin + res_mode->vsync_len);
t1 /= 1000;
vsynch = 1000000000L / t1;
/* fill in Graphic device struct */
sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
res_mode->yres, bits_per_pixel, (hsynch / 1000),
(vsynch / 1000));
printf ("%s\n", pGD->modeIdent);
pGD->winSizeX = res_mode->xres;
pGD->winSizeY = res_mode->yres;
pGD->plnSizeX = res_mode->xres;
pGD->plnSizeY = res_mode->yres;
switch (bits_per_pixel) {
case 8:
pGD->gdfBytesPP = 1;
pGD->gdfIndex = GDF__8BIT_INDEX;
break;
case 15:
pGD->gdfBytesPP = 2;
pGD->gdfIndex = GDF_15BIT_555RGB;
break;
case 16:
pGD->gdfBytesPP = 2;
pGD->gdfIndex = GDF_16BIT_565RGB;
break;
case 24:
pGD->gdfBytesPP = 3;
pGD->gdfIndex = GDF_24BIT_888RGB;
break;
}
/* statically configure settings */
pGD->winSizeX = pGD->plnSizeX = 320;
pGD->winSizeY = pGD->plnSizeY = 240;
pGD->gdfBytesPP = 2;
pGD->gdfIndex = GDF_16BIT_565RGB;
pGD->frameAdrs = LCD_VIDEO_ADDR;
pGD->memSize = VIDEO_MEM_SIZE;
board_video_init(pGD);
lcd->LCDSADDR1 = pGD->frameAdrs >> 1;
/* This marks the end of the frame buffer. */
lcd->LCDSADDR2 = (lcd->LCDSADDR1&0x1fffff) + (pGD->winSizeX+0) * pGD->winSizeY;
lcd->LCDSADDR3 = (pGD->winSizeX & 0x7ff);
/* Clear video memory */
memset((void *)pGD->frameAdrs, 0, pGD->memSize);
/* Enable Display */
lcd->LCDCON1 |= 0x01; /* ENVID = 1 */
return ((void*)&smi);
}
void
video_set_lut (unsigned int index, /* color number */
unsigned char r, /* red */
unsigned char g, /* green */
unsigned char b /* blue */
)
{
}
#endif /* CONFIG_VIDEO_S3C2410 */
在你的配置头文件中添加如下宏定义:
view plaincopy to clipboardprint?
#define CONFIG_CMD_BMP
#define CONFIG_VIDEO
#define CONFIG_VIDEO_S3C2410
#define CONFIG_VIDEO_LOGO
#define VIDEO_FB_16BPP_PIXEL_SWAP
#define CONFIG_VIDEO_SW_CURSOR
#define CONFIG_VIDEO_BMP_LOGO
这样就基本完成了,重新启动一下是不是就显示出samsung的logo了。如果先改成自己喜欢的图片,修改tools/logos/denx.bmp,记住一定是是8bpp的bmp图,修改Makefile文件,修改/tools目录下的Makefile文件,大约是44~46行,
view plaincopy to clipboardprint?
ifeq ($(LOGO_BMP),)
LOGO_BMP= logos/denx.bmp
endif
把 denx.bmp 替换为你需要显示的logo图片的文件名,保存退出,重新编译uboot。图片的转化方法,在终端输入命令:
jpegtopnm $1 | ppmquant 31 | ppmtobmp -bpp 8 > $2
使用方法: (脚本名) ( 待处理的JPG图片名) (输出文件名)
这样就可以显示出你自己喜欢的logo图片了。
如果想将串口的打印信息显示在lcd上,添加环境变量。
view plaincopy to clipboardprint?
#define CONFIG_EXTRA_ENV_SETTINGS \
"stdin=serial\0" \
"stdout=vga" \
"stderr=serial\0" \
只要让stdout等于vga就可以了。在lib_arm/board.c文件中可以看到console_init初始化两次,我们修改的影响第二次的初始化,第一次的不影响,所以还会有部分输出信息显示在串口上的。Lcd就到这里,有什么问题我再及时改正吧。
Linux 2.6.30.4移植TE2440II开发板
宿主机:ubuntu9.10
目标机:s3c2440
交叉编译器:arm-linux-gcc-4.3.2
交叉编译器路径:/usr/local/arm/4.3.2
要移植的内核版本:linux-2.6.30.4
文件系统类型: yaffs2
步骤包括:
1)给linux内核打上yaffs2补丁
2)修改机器码
3)修改目标板的arch和编译器路径,
4)增加devfs文件管理器支持
5)修改晶振频率
6)修改MTD分区
7)关闭ECC校验
8)修改nandflash驱动
9)配置内核
首先,从官网上下载linux-2.6.30.4的内核。
ftp://ftp.kernel.org/pub/linux/kernel/v2.6/可以找到。
新建目录mkdir /home/haker,将内核源码包解压到hacker/目录下
tar –zxvf linux-2.6.30.4.tar.gz
1)给内核打jaffs2补丁
下载最新的驱动http://www.aleph1.co.uk/cgi-bin/ ... fs2.tar.gz?view=tar
解压到/home/hacker/下
tar –zxvf yaffs2.tar.gz
进入目录
cd yaffs2
给内核打补丁
./patch-ker.sh c /home/hacker/linux-2.6.30.4
加上c 他会自动解压到后面的目录中
成功后会打印信息:
Updating /home/hacker/linux-2.6.30.4/fs/Kconfig
Updating /home/hacker/linux-2.6.30.4/fs/Makefile
2)修改机器码
暂时我使用的是飞凌的boot,自己的boot还没有完全做好,飞凌boot的默认机器码是193,修改arch/arm/tools/mach-types,将
s3c2410 ARCH_S3C2410 S3C2410 193 删掉
然后将
s3c2440 ARCH_S3C2440 S3C2440 362
修改为
s3c2440 ARCH_S3C2440 S3C2440 193
3)修改目标板的arch和编译器路径
修改linux/2.6.30.4下的Makefile将
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
修改成
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/4.3.2/bin/arm-linux-
4)增加devfs文件管理器支持
修改fs/Kconfig,找到
menu “Pseudo filesystems”
添加
config DEVFS_FS
bool “/dev file system support (OBSOLETE)”
default y
config DEVFS_MOUNT
bool “Automatially mount at bool”
default
depends on DEVFS_FS
5)修改晶振频率
arch/arm/mach-s3c2440/mach-smdk2440.c
/*s3c24xx_init_clocks(16934400);*/ s3c24xx_init_clocks(12000000);
6)修改MTD分区,由于自己的uboot还没有完全做好,暂时用飞凌的boot的分区,
修改文件arch/arm/plat-s3c24xx/common-smdk.c
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "Boot",
.size = 0x00100000,
.offset = 0
},
[1] = {
.name = "MyApp",
.size = 0x003c0000,
.offset = 0x00140000,
},
[2] = {
.name = "Kernel",
.size = 0x00300000,
.offset = 0x00500000,
},
[3] = {
.name = "fs_yaffs",
.size = 0x03c00000, //60M
.offset = 0x00800000,
},
[4] = {
.name = "WINCE",
.size = 0x03c00000,
.offset = 0x04400000,
}
};
7)关闭ECC校验
文件drivers/mtd/nand/s3c2410.c
函数:s3c2410_nand_init_chip
/*chip->ecc.mode = NAND_ECC_SOFT; */ chip->ecc.mode = NAND_ECC_NONE;
这个有两个 软件校验和硬件校验都要关掉
8)修改nandflash驱动,修改drivers/mtd/nand下面的nand_bbt.c文件:
static struct nand_bbt_descr largepage_memorybased = {
.options = 0,
.offs = 0,
.len = 1, // 原数值为2,支持2K每页的flash修改为1。K9F1G08,K9F2G08是2k每页的flash
.pattern = scan_ff_pattern
};
static struct nand_bbt_descr largepage_flashbased = {
.options = NAND_BBT_SCAN2NDPAGE,
.offs = 0,
.len = 1, //原数值为2,支持2K每页的flash修改为1。K9F1G08,K9F2G08是2k每页的flash
.pattern = scan_ff_pattern
};
9)配置内核
make menuconfig
首先加载s3c24xx系列的通用配置,然后在此基础上修改
配置完后将配置文件保存为.config,这样方便下次make menuconfig时默认加载上次配置过的文件
交叉编译内核
make zImage
如果没有任何错误,编译出来的内核在arch/arm/boot/目录下,文件zImage即是。
基于busybox1.15.0的yaffs2文件系统移植TE2440II开发板
首先说一下各个知识点:
使用的busybox是1.15.0。什么是busybox呢,busybox是很多标准linux一个单个可执行实现,很多标准linux工具都可以共享很多共同的元素。例如,很多基于文件的元素(比如grep和find)都需要在文件中搜索文件的代码。当这些工具被合并到一个可执行程序中时,他们就可以共享这些相同的元素,这样可以产生更小的可执行程序。实际上,busybox可以将大约3.5M的工具包装成大约200KB大小。这就为引导盘和嵌入式linux设备提供了更多的工具。我们可以对2.4或2.6版本的linux内核使用这个工具。
几个常用的make选项:
make clean 清除源代码树
make distclean 彻底清除源代码树
make menuconfig N-curses(基于菜单的)配置工具
make defconfig 启用默认的(通用)配置
make config 基于菜单的配置工具
uClibc与glibc。CC的标准就是glibc这个库,里边有GCC各种标准函数的实现,使用uClibc,这是一个对大小进行优化过的C库,它为嵌入式系统开发。
根文件系统前面加一个“根”字,说明它是加载其他文件系统的根,既然是根,那么如果没有这个根,其他文件系统就没法加载。他包括系统引导和其他文件系统挂载所必须的文件,根文件系统包括Linux启动所必须的目录和关键性的文件,例如Linux启动时都需要有init目录下的相关文件,在Linux挂载分区时Linux一定会找到/etc/fstab这个挂载文件等,根文件系统还包括了应用程序bin目录等。
1)Jffs2
JFFS嵌入式系统文件系统最早是由瑞典 Axis Communications公司基于Linux2.0的内核为嵌入式系统开发的文件系统。JFFS2是RedHat公司基于JFFS开发的闪存文件系统,最初是针对RedHat公司的嵌入式产品eCos开发的嵌入式文件系统,所以JFFS也可以用于Linux,uCLinux中。
Jffs2:日志闪存嵌入式系统文件系统版本2(Journalling Flash FileSystem v2)主要用于NOR型闪存,基于MTD驱动层,特点是,可读写的,支持数据压缩的,基于哈希表的日志型文件系统,并提供了崩溃/掉电安全保护,提供“写平衡”支持等。缺点主要是当文件系统已经满或接近满时,因为垃圾收集的关系而使jffs2的运行速度大大放慢。
2)Yaffs Yet Another Flash File System
Yaffs/yaffs2是专门为嵌入式系统使用NAND型闪存而设计的一种日志型文件系统。与jffs2相比,它减少一些功能(例如不支持数据压缩),所以速度更快,挂载时间更短,对内存的占用较小。另外他是跨平台的文件系统,除了Linux和eCos,还支持WinCE,pSOS和ThreadX等。
Yaffs/yaffs自带NAND芯片驱动,并且为嵌入式提供了直接访问文件系统的API,用于可以不使用Linux中的MTD与VFS,直接对文件系统操作。
3)Cramfs
Cramfs是Linux的创始人Linux Torvalds参与开发的一种只读的压缩文件系统。他也基于MTD驱动程序。在cramfs文件系统中,每一页(4KB)被压缩,可以随机页访问,其压缩比高达2:1,为嵌入式系统节省了大量的Flash存储空间,使系统可通过更低容量的FLASH存储相同的文件,从而降低系统成本。Cramfs文件系统以压缩方式存储,在运行时解压缩。
4)NFS
NFS是由Sun开发并发展起来的一项不同机器,不同操作系统之间通过网络共享文件的技术
然后开始操作:
一.
给内核打上补丁,使内核对yaffs2文件系统支持。
下载最新的驱动http://www.aleph1.co.uk/cgi-bin/ ... fs2.tar.gz?view=tar
解压:
tar zxvf yaffs2.tar.gz
cd yaffs2
./patch-ker.sh c /home/hacker/linux-2.6.30.4
成功后打印信息:
1. Updating /file/fl/linux-2.6.33/fs/Kconfig
2. Updating /file/fl/linux-2.6.33/fs/Makefile
进入linux-2.6.30.4目录,把s3c2410的默认配置写入config文件。
1. make s3c2410_defconfig
配置文件系统选项
配置yaffs2文件系统
修改配置如下:
1. File systems --->
2.