由于书上的介绍与板子上不大一样,遇到很多问题,将查找到的资料综合一下,以便使用!
1)开发环境
1.开发板:勤研2440,
nor flash:没移植改变nor flash前,显示Amd29LV400BB 512K,但实际是:
Bank # 1: MXIC MX29LV160B FLASH (16 x 16) Size: 2 MB in 35 Sectors
AMD Standard command set, Manufacturer ID: 0xC2, Device ID: 0x2249
Erase timeout: 30000 ms, write timeout: 100 ms
第0扇区大小为8K,第1、2为4K,第3为16K,后面31扇区为32K。前面4个扇区加起来刚好是主要扇区的大小 = 32K
Sector Start Addresses:
00000000 (RO) 00002000 (RO) 00003000 (RO) 00004000 (RO) 00008000 (RO)
00010000 (RO) 00018000 00020000 00028000 00030000
00038000 00040000 00048000 00050000 00058000
00060000 00068000 00070000 00078000 00080000 (RO,放参数)
00088000 (RO) 00090000 00098000 000A0000 000A8000
000B0000 000B8000 000C0000 000C8000 000D0000
000D8000 000E0000 000E8000 000F0000 000F8000
2.软件环境:ubantu9.0(韦东山一期光盘)
3. linux版本:linux-2.6.22.6 (/work/system/linux-2.6.22.6)补丁:linux-2.6.22.6_jz2440.patch
4.u-boot:uboot-1.1.6 补丁:u-boot-1.1.6_jz2440.patch
5.自己的u-boot目录/work/system/u-boot-jimmy/u-boot-1.1.6
参考:http://blog.csdn.net/johnmcu/article/details/6561311
2)具体步骤
A)解压U-BOOT-1.1.6,进入U-BOOT目录,修改Makefile:
在smdk2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
加上
myjz2440_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t myjz2440 NULL s3c24x0
修改完Makefile后,在board目录下,新建自己的开发板目录myjz2440,把smdk2410目录下的所有文件拷到myjz2440,把smdk2410.c改为myjz2440.c。修改该目录下的Makefile,把smdk2410.o改为myjz2440.o。
COBJS :=myjz2440.o flash.o
include/configs目录下创建板子的配置头文件,拷贝smdk2410.h为myjz2440.h
测试能否编译成功:
执行makemyjz2440_config
B).修改SDRAM配置,在board/myjz2440/lowlevel_init.S(内存控制器初始化)中,检查
#define B6_BWSCON (DW32)位宽为32
把B1_BWSCON改为(DW16) B5_BWSCON改为(DW8),如下:
#define B1_BWSCON (DW16)
#define B2_BWSCON (DW16)
//#define B3_BWSCON (DW16 + WAIT + UBLB)
#define B3_BWSCON (DW16 + UBLB)
#define B4_BWSCON (DW16 + WAIT + UBLB)
#define B5_BWSCON (DW8)
#define B6_BWSCON (DW32)
#define B7_BWSCON (DW32)
根据HCLK设置SDRAM 的刷新参数,主要是REFCNT寄存器,开发板HCLK为100M
将
#define REFCNT 0x1113 改为 #define REFCNT 0x4f4 /* period=7.8125us, HCLK=100Mhz, (2048+1-7.8125*100) */
增加对S3C2440的支持,2440的时钟计算公式、NAND操作和2410不太一样。
对于2440开发板,将FCLK设为400MHz,分频比为FCLK:HCLK:PCLK=1:4:8。
修改board/myjz2440/myjz2440.c中的board_init函数(为了方便,可以再 vi include/s3c24x0.h,加入:
#define isS3C2410 ((rGSTATUS1 & 0xffff0000) == 0x32410000)
):
DECLARE_GLOBAL_DATA_PTR;
#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
/*参考链接是#define S3C2440_MPLL_400MHZ ((0x7f<<12)|(0x02<<4)|(0x01)) ,不过没什么影响*/
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
#define S3C2440_MPLL_100MHZ ((0x5c<<12)|(0x01<<4)|(0x03))
#define S3C2440_UPLL_96MHZ ((0x38<<12)|(0x02<<4)|(0x01))
#define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02)) //usb有关
#define S3C2440_CLKDIV (0x05) // | (1<<3)) /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */
#define S3C2440_CLKDIV188 0x04 /* FCLK:HCLK:PCLK = 1:8:8 */
#define S3C2440_CAMDIVN188 ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */
/* Fin = 16.9344MHz */
#define S3C2440_MPLL_399MHz_Fin16MHz ((0x6e<<12)|(0x03<<4)|(0x01))
#define S3C2440_UPLL_48MHZ_Fin16MHz ((60<<12)|(4<<4)|(2))
int board_init (void)
{
S3C24X0_CLOCK_POWER *clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
gpio->GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555;
gpio->GPBUP = 0x000007FF;
gpio->GPCCON = 0xAAAAAAAA;
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA;
gpio->GPHUP = 0x000007FF;
/* FCLK:HCLK:PCLK = 1:4:8 */
clk_power->CLKDIVN = S3C2440_CLKDIV;
/* change to asynchronous bus mod */
__asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */
"orr r1, r1, #0xc0000000\n" /* Asynchronous */
"mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */
:::"r1"
);
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFFFF;
clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
delay (4000);
/* configure MPLL */
clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
/* some delay between MPLL and UPLL */
/* configure UPLL */
/* some delay between MPLL and UPLL */
delay (8000);
gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
gd->bd->bi_boot_params = 0x30000100;
icache_enable();
dcache_enable();
return 0;
}
在cpu/arm920t/s3c24X0/speed.c中修改:
在程序开头增加一行DECLARE_GLOBAL_DATA_PTR;,这样才可以使用gd变量:
DECLARE_GLOBAL_DATA_PTR;
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;
/* support both of S3C2410 and S3C2440 */
if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
else
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); /* S3C2440 */
}
/* return FCLK frequency */
ulong get_FCLK(void)
{
return(get_PLLCLK(MPLL));
}
// jimm add for jz2440
#define S3C2440_CLKDIVN_PDIVN (1<<0)
#define S3C2440_CLKDIVN_HDIVN_MASK (3<<1)
#define S3C2440_CLKDIVN_HDIVN_1 (0<<1)
#define S3C2440_CLKDIVN_HDIVN_2 (1<<1)
#define S3C2440_CLKDIVN_HDIVN_4_8 (2<<1)
#define S3C2440_CLKDIVN_HDIVN_3_6 (3<<1)
#define S3C2440_CLKDIVN_UCLK (1<<3)
#define S3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)
#define S3C2440_CAMDIVN_CAMCLK_SEL (1<<4)
#define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)
#define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)
#define S3C2440_CAMDIVN_DVSEN (1<<12)
/* return HCLK frequency */
ulong get_HCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
unsigned long clkdiv;
unsigned long camdiv;
int hdiv = 1;
if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
else
{
clkdiv = clk_power->CLKDIVN;
camdiv = clk_power->CAMDIVN;
/* work out clock scalings */
switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
case S3C2440_CLKDIVN_HDIVN_1:
hdiv = 1;
break;
case S3C2440_CLKDIVN_HDIVN_2:
hdiv = 2;
break;
case S3C2440_CLKDIVN_HDIVN_4_8:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
break;
case S3C2440_CLKDIVN_HDIVN_3_6:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
break;
}
return get_FCLK() / hdiv;
}
}
ulong get_PCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
unsigned long clkdiv;
unsigned long camdiv;
int hdiv = 1;
/* support both of S3C2410 and S3C2440 */
if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());
else
{
clkdiv = clk_power->CLKDIVN;
camdiv = clk_power->CAMDIVN;
/* work out clock scalings */
switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
case S3C2440_CLKDIVN_HDIVN_1:
hdiv = 1;
break;
case S3C2440_CLKDIVN_HDIVN_2:
hdiv = 2;
break;
case S3C2440_CLKDIVN_HDIVN_4_8:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
break;
case S3C2440_CLKDIVN_HDIVN_3_6:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
break;
}
return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
}
}
/* return UCLK frequency */
ulong get_UCLK(void)
{
return(get_PLLCLK(UPLL));
}
重新执行make myjz2440_config ;make all生成u-boot.bin,由于还没有增加NAND Flash的支持,所以可烧入NOR Flash中运行
在make all时会出现错误:没有CAMDIVN
这个要在include/s3c24x0.h中定义, 在129行S3C24X0_CLOCK_POWER结构体中增加:
S3C24X0_REG32 CAMDIVN; /* for s3c2440*/
成功后,控制台显示:
U-Boot 1.1.6 (Jul 20 2013 - 09:53:57)
DRAM: 64 MB
Flash: 512 kB(nor flash ,实际有2M)
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
myjz2440 # printenv
bootdelay=3
baudrate=115200
ipaddr=10.140.1.253
serverip=10.140.1.250
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial
myjz2440 # ping 10.140.1.250
CS8900 Ethernet chip not found?!
以上转自:http://blog.csdn.net/conjimmy/article/details/9491197
(注:原文上面实验成功,但原文下面网卡移植存在一定问题!)
U-Boot移植DM9000网卡
——西伯利亚的风
根据书《嵌入式Linux应用开发完全手册》移植网卡驱动,对于Jz2440开发板好像并不适用,Jz2440开发板使用的是DM9000网卡,已经不是书上讲的CS8900网卡了。DM9000网卡与CS8900网卡接口方式不一样,经过几天的折腾,终于移植成功,现将笔记整理如下。
一、移植环境
1.u-boot版本1.1.6
2.开发板Jz2440(ARM9 S3C2440
NAND K9F2G08
SDRAM K4S561632 * 2
网卡 DM9000)
3.Linux: ubuntu 9.10
二、移植思路
查看u-boot-1.1.6源码发现,u-boot中已经包含dm9000的驱动文件dm9000x.c,所以我们只需要设置u-boot支持网卡就行。总体思路主要完成以下几件事情:
1.设置存储控制器,也就是设置S3C2440的BANK以使用DM9000;
2.配置u-boot使用DM9000网卡;
3.设置IP、serverIP等。
三、设置存储控制器
根据Jz2440开发板的原理图可知,DM9000网卡 使用的是BANK4
由图可知,DM9000网卡使用的片选信号是nGCS 4,也就说明DM9000使用了BANK4。修改lowlevel_init.S(路径:board/smdk2410/lowlevel_init.S)。
/* BWSCON */
#define DW8 (0x0)
#define DW16 (0x1)
#define DW32 (0x2)
#define WAIT (0x1<<2)
#define UBLB (0x1<<3)
#define B1_BWSCON (DW32)
#define B2_BWSCON (DW16)
#if 0
#define B3_BWSCON (DW16 + WAIT + UBLB)
#endif
#define B3_BWSCON (DW16 + UBLB)
#define B4_BWSCON (DW16 + WAIT + UBLB)
#define B5_BWSCON (DW16)
#define B6_BWSCON (DW32)
#define B7_BWSCON (DW32)
修改前BANK3外接的CS8900网卡,将BANK3注释掉,修改数据宽度为16位,设置BANK4数据宽度16位,使用WAIT和nBE信号。
#define B4_Tacs 0x0 /*0clk */
#define B4_Tcos 0x3 /*4clk */
#define B4_Tacc 0x7 /* 14clk */
#define B4_Tcoh 0x1 /*1clk */
#define B4_Tah 0x3 /*4clk */
#define B4_Tacp 0x6 /*6clk */
#define B4_PMC 0x0 /* normal */
根据DM9000数据手册设置时序,具体见DM9000数据手册。
四、配置u-boot使用DM9000网卡
修改配置文件smdk2410.h(路径:include/configs/smdk2410.h)。
/** Hardware drivers*/
#if 0
#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 */
#endif
#define CONFIG_DRIVER_DM9000 1 /* we have a DM9000 on-board */
#define CONFIG_DM9000_USE_16BIT 1
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_DATA 0x20000004
#define DM9000_IO 0x20000000
注释掉CS8900的信息,添加DM9000的配置信息。
宏定义CONFIG_DRIVER_DM9000为1表示配置使用DM9000网卡,u-boot编译时会将DM9000相关的驱动编译进去。其中0x20000000是DM9000的基址(BANK4),由于DM9000只有一条地址线CMD(LADDR2,见图3.1)用于区别是数据还是地址(CMD为低时数据总线上传输的是地址信号,CMD为高时传输的是数据信号),所以DM9000_DATA为0x20000004,DM9000_IO为0x20000000。
五、设置IP、serverIP
在配置文件smdk2410.h(路径:include/configs/smdk2410.h)中根据实际情况修改开发板的IP地址,serverIP。
修改前:
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 10.0.0.110
#define CONFIG_SERVERIP 10.0.0.1
修改后:
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.1.6
#define CONFIG_SERVERIP 192.168.1.2
我的PC和开发板使用路由器相连,PC IP地址为192.168.1.2,开发板设置为192.168.1.6,保证在同一个网段就行。
增加ping命令:
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL| \
CFG_CMD_CACHE| \
/*CFG_CMD_NAND|*/ \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I2C|*/ \
/*CFG_CMD_USB|*/ \
FG_CMD_REGINFO| \
CFG_CMD_PING| \
CFG_CMD_DATE| \
CFG_CMD_ELF)
仿照CMD命令格式,我们使用CFG_CMD_PING增加对ping的支持。
六、遇到问题vs解决方案
以上任务完成,在u-boot根目录下编译,编译成功!
使用OpenJtag将编译完成的u-boot.bin烧入开发板运行。u-boot启动后,使用print命令查看u-boot的参数:
Jz2440 # print
bootdelay=3
baudrate=115200
ethaddr=08:00:3e:26:0a:5b
ipaddr=192.168.1.6
serverip=192.168.1.2
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial
看到开发板的IP、serverIP已经修改成功。我们使用ping命令ping一下PC 192.168.1.2。
Jz2440 # ping 192.168.1.2
dm9000 i/o: 0x20000000, id: 0x90000a46
MAC: 50:50:50:50:50:50
could not establish link
ping failed; host 192.168.1.2 is not alive
host is not alive ,ping不通,看来存在问题!
上网搜索了很久,网上的都是教你屏蔽这一段代码,屏蔽那一段代码,然后就可以了,都没有详细的分析,看不大明白。后来,通过研究高版本的u-boot,发现了问题所在。
打开高版本u-boot,u-boot-1.3.4中的dm9000x.c,可以看到如下更新说明:
06/03/2008 Remy Bohmer <[url=mailto[email protected]][email protected][/url]>
-Fixed the driver to work with DM9000A.
发现DM9000驱动在后续版本中更新了,老版本的(u-boot-1.1.6)对DM9000支持可能存在问题。
发现了问题,马上更新试试看,复制u-boot-1.3.4中的dm9000x.c到u-boot-1.1.6中,覆盖掉原来的dm9000x.c,然后编译。
出现了错误!
drivers/dm9000x.c:480: undefined reference to `is_zero_ether_addr‘
/drivers/dm9000x.c:480: undefined reference to `is_multicast_ether_addr‘
make: *** [u-boot] Error 1
很明显,缺少两个函数定义。网上搜索也没有找到,干脆对u-boot-1.3.4建立SourceInsight工程搜索这两个函数。发现这两个函数都存在于net.h中(路径:include/net.h)。
复制这两个函数,到自己的u-boot(目前为u-boot-1.1.6)的net.h中(路径:include/net.h)
/*
*
* is_zero_ether_addr - Determine if give Ethernet address is all zeros.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Return true if the address is all zeroes.
*/
static inline int is_zero_ether_addr(const u8 *addr)
{
return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
}
/*
*
* is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Return true if the address is a multicast address.
* By definition the broadcast address is also a multicast address.
*/
static inline int is_multicast_ether_addr(const u8 *addr)
{
return (0x01 & addr[0]);
}
然后编译,通过!
烧写到开发板,ping主机192.168.1.2:
Jz2440 # ping 192.168.1.2
ERROR: resetting DM9000 -> not responding
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:5b
could not establish link
host 192.168.1.2 is alive
“host 192.168.1.2 is alive”, ping通了,DM9000移植OK!
七、网络测试
1.测试tftp
通过tftp传输一个程序到内存中运行试试看。在主机上打开tftp软件,将leds.bin(运行地址在0x30000000)放在tftp软件目录中,在u-boot界面,输入命令:
Jz2440 # tftp 0x30000000 leds.bin
ERROR: resetting DM9000 -> not responding
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:5b
could not establish link
TFTP from server 192.168.1.2; our IP address is 192.168.1.6
Filename ‘leds.bin‘.
Load address: 0x30000000
Loading: #
done
Bytes transferred = 168 (a8 hex)
传输成功,在u-boot界面使用go命令运行程序
Jz2440 # go 0x30000000
## Starting application at 0x30000000 ...
可以看到Jz2440开发板上led已经在循环闪烁了。
2.测试nfs
由于虚拟机Linux上开启了nfs服务,虚拟机Linux IP为192.168.1.3,需要先更改serverIP。
Jz2440 # setenv serverip 192.168.1.3
Jz2440 # saveenv
然后将leds.bin放在nfs目录,/work/nfs_root/,在u-boot界面使用nfs传输文件
Jz2440 # nfs 0x30000000 192.168.1.3:/work/nfs_root/leds.bin
ERROR: resetting DM9000 -> not responding
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:5b
could not establish link
File transfer via NFS from server 192.168.1.3; our IP address is 192.168.1.6
Filename ‘/work/nfs_root/leds.bin‘.
Load address: 0x30000000
Loading: #
done
Bytes transferred = 168 (a8 hex)
传输成功,在u-boot界面使用go命令运行程序
Jz2440 # go 0x30000000
## Starting application at 0x30000000 ...
可以看到Jz2440开发板上led已经在循环闪烁了。
至此,DM9000网卡移植成功!
以上转自:http://blog.csdn.net/cxsys/article/details/7375662