全部博文(17)
分类: LINUX
2008-03-23 14:31:53





























#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCMD __REGb(NF_BASE + 0x4)
#define NFADDR __REGb(NF_BASE + 0x8)
#define NFDATA __REGb(NF_BASE + 0xc)
#define NFSTAT __REGb(NF_BASE + 0x10)
#define BUSY 1
inline void wait_idle(void) {
int i;
while(!(NFSTAT & BUSY))
for(i=0; i<10; i++);
}
/* 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 */
NFCONF &= ~0x800;
for(i=0; i<10; i++);
for(i=start_addr; i < (start_addr + size);) {
/* READ0 */
NFCMD = 0;
/* Write Address */
NFADDR = i & 0xff;
NFADDR = (i >> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff;
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
*buf = (NFDATA & 0xff);
buf++;
}
}
/* chip Disable */
NFCONF |= 0x800; /* chip disable */
return 0;
}
3 修改board/tekkaman/tekkaman2410/Makefile文件
......
OBJS := tekkaman2410.o nand_read.o
......
4 修改include/configs/tekkaman2410.h文件,添加如下内容:
......
/*
* Nandflash Boot
*/
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
//#define UBOOT_RAM_BASE 0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE 0x4E000000
#define bINT_CTL(Nb) __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
#endif /* __CONFIG_H */
5 修改board/tekkaman/tekkaman2410/lowlevel_init.S文件
依照开发箱的内存区的配置情况, 修改board/tekkaman/tekkaman2410/lowlevel_init.S文件,我利用博创提供的vivi源码里的信息做了如下更改:
......
#define B1_BWSCON (DW16) /*@tekkaman*/
#define B2_BWSCON (DW16)
#define B3_BWSCON (DW16) /*@tekkaman*/
#define B4_BWSCON (DW16)
#define B5_BWSCON (DW16)
#define B6_BWSCON (DW32)
#define B7_BWSCON (DW32)
......
#define B3_Tacs 0x0 /* 0clk */
#define B3_Tcos 0x0 /* 0clk @tekkaman*/
#define B3_Tacc 0x7 /* 14clk */
#define B3_Tcoh 0x0 /* 0clk @tekkaman*/
#define B3_Tah 0x0 /* 0clk */
#define B3_Tacp 0x0 /*@tekkaman*/
#define B3_PMC 0x0 /* normal */
......
注:之所以Bank3的改动较大,是因为smdk2410的网卡CS8900是在Bank3,而博创2410-S的AX88796是在Bank2。
......
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0xb2 /*@tekkaman*/
.word 0x30
.word 0x30
6 修改/board/tekkaman/tekkaman2410/tekkaman2410.c
因为博创2410-S和smdk2410的GPIO连接有所不同,我依旧利用博创配的vivi,修改其对GPIO的配置(具体原因我并未深究,请参阅博创2410-S的硬件说明和2410芯片手册):
......
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000051aa; //0x000055AA; tekkaman
gpio->GPFUP = 0x000000ef; //0x000000FF; tekkaman
gpio->GPGCON = 0xfd95ffba; //0xFF95FFBA; tekkaman
gpio->GPGUP = 0x0000efff; //0x0000FFFF; tekkaman
gpio->GPHCON = 0x0016faaa; //0x002AFAAA; tekkaman
gpio->GPHUP = 0x000007FF;
......
7 为了实现NAND Flash的读写,再次修改
//具体内容请参阅对《U-BOOT下使用bootm引导内核方法》的补充说明
......
#define CFG_LONGHELP
/* undef to save memory */
#define CFG_PROMPT "[Tekkaman2410]#"
/*Monitor Command Prompt */
#define CFG_CBSIZE 256
/* Console I/O Buffer Size */
......
#define CFG_LOAD_ADDR 0x30008000
/* default load address */
......
//#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */
//#define CFG_FLASH_BASE PHYS_FLASH_1
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CFG_NO_FLASH 1
#if 0
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
//#if 0 ///删掉这行
#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
#endif
//#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
......
/* timeout values are in ticks */
//#define CFG_FLASH_ERASE_TOUT (5*CFG_HZ)
/* Timeout for Flash Erase */
//#define CFG_FLASH_WRITE_TOUT (5*CFG_HZ)
/* Timeout for Flash Write */
#define CFG_ENV_IS_IN_NAND 1 ///第一次改没有改好NAND
#define CFG_ENV_OFFSET 0X20000
//#define ENV_IS_EMBEDDED 1
#define CFG_NAND_LEGACY
#define CFG_ENV_SIZE 0x10000
/* Total Size of Environment Sector */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_NAND_BASE 0x4E000000
/* NandFlash控制器在SFR区起始寄存器地址 */
#define CFG_MAX_NAND_DEVICE 1
/* 支持的最在Nand Flash数据 */
#define SECTORSIZE 512
/* 1页的大小 */
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_BLOCK_MASK 511
/* 页掩码 */
#define ADDR_COLUMN 1
/* 一个字节的Column地址 */
#define ADDR_PAGE 3
/* 3字节的页块地址!!!!!*/
#define ADDR_COLUMN_PAGE 4
/* 总共4字节的页块地址!!!!! */
#define NAND_ChipID_UNKNOWN 0x00
/* 未知芯片的ID号 */
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
/* Nand Flash命令层底层接口函数 */
#define WRITE_NAND_COMMAND(d, adr) {rNFCMD = d;}
#define WRITE_NAND_ADDRESS(d, adr) {rNFADDR = d;}
#define WRITE_NAND(d, adr) {rNFDATA = d;}
#define READ_NAND(adr) (rNFDATA)
#define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));}
#define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);}
#define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);}
/* the following functions are NOP's because S3C24X0 handles this in hardware 一定要加上 */
#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
/* 允许Nand Flash写校验 */
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
*
* Nandflash Boot
*/
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
//#define UBOOT_RAM_BASE 0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE 0x4E000000
#define bINT_CTL(Nb) __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
#define rNFCONF (*(volatile unsigned int *)0x4e000000)
#define rNFCMD (*(volatile unsigned char *)0x4e000004)
#define rNFADDR (*(volatile unsigned char *)0x4e000008)
#define rNFDATA (*(volatile unsigned char *)0x4e00000c)
#define rNFSTAT (*(volatile unsigned int *)0x4e000010)
#define rNFECC (*(volatile unsigned int *)0x4e000014)
#define rNFECC0 (*(volatile unsigned char *)0x4e000014)
#define rNFECC1 (*(volatile unsigned char *)0x4e000015)
#define rNFECC2 (*(volatile unsigned char *)0x4e000016)
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND*/
#endif /* __CONFIG_H */
8
static struct nand_flash_dev nand_flash_ids[] = {
......{NULL,}
};
9 修改/lib_arm中的board.c。
static int display_banner (void)
{
printf ("\n\n%s\n\n", version_string);
debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
_armboot_start, _bss_start, _bss_end);
printf ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", //tekkaman
_armboot_start, _bss_start, _bss_end); //tekkaman
#ifdef CONFIG_MODEM_SUPPORT
debug ("Modem Support enabled\n");
#endif
#ifdef CONFIG_USE_IRQ
debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
#endif
return (0);
}
ret = nand_legacy_rw(nand_dev_desc + 0,
0x00 | 0x02, CFG_ENV_OFFSET, CFG_ENV_SIZE,
&total, (u_char*)env_ptr);
u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。Nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nnd/nand.c中的nand_init();否则调用自己在board/smdk2410/smdk2410.c中的nand_init()函数。这里我选择第二种方式。
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE;
static inline void NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF = conf;
}
static inline void NF_Cmd(u8 cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCMD = cmd;
}
static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
}
static inline void NF_Addr(u8 addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFADDR = addr;
}
static inline void NF_SetCE(NFCE_STATE s)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1<<11);
break;
case NFCE_HIGH:
nand->NFCONF |= (1<<11);
break;
}
}
static inline void NF_WaitRB(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
while (!(nand->NFSTAT & (1<<0)));
}
static inline void NF_Write(u8 data)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFDATA = data;
}
static inline u8 NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFDATA);
}
static inline void NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF |= (1<<12);
}
static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFECC);
}
#endif
/** NAND flash initialization.
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong nand_probe(ulong physadr);
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}
static inline void NF_Init(void)
{
#if 0 /* a little bit too optimistic */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif
NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
/*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */
NF_Reset();
}
void
nand_init(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
#endif
printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
}
#endif
12 修正U-Boot的NE2000驱动的低级错误
将drivers/ne2000.h第45行:
at */
改为:
at
真是TNND汗死
!!!!
13 因为没有Nor Flash芯片,所以注释掉/common/cmd_bootm.c中关于imls命令的程序段和/common/cmd_flash.c中的程序。不然,按上面的修改,编译会出错。
/common/cmd_bootm.c第91行:(“0”后面一定要换行!!!不然还会错!!!)
#if 0
(CONFIG_COMMANDS & CFG_CMD_IMLS)
#include
extern flash_info_t flash_info[]; /* info for FLASH chips */
static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#endif
/common/cmd_bootm.c第1237行:(“0”后面一定要换行!!!不然还会错!!!)
#if 0
(CONFIG_COMMANDS & CFG_CMD_IMLS)
/*-----------------------------------------------------------------------
* List all images found in flash.
*/
int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
flash_info_t *info;
int i, j;
image_header_t *hdr;
ulong data, len, checksum;
for (i=0, info=&flash_info[0]; i
......
......
#if 0
(CONFIG_COMMANDS & CFG_CMD_FLASH)
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
#include
......
三、交叉编译U-Boot。
在U-Boot的根目录下
$make
一阵English飘过~~~~~~~~~~~~~~~~~~~~~~~
严格按上面的修改,应该是会成功的。因为我本着认真负责的态度,按上面的步骤又做了一遍,改了一遍,且编译成功。
如果你还遇到错误,可以找我讨论 QQ:78027228。
不过我建议:在看懂U-Boot的基础上移植,不然当有错误时你会狂郁闷,不知如何下手!
网友评论 、、、这个也给转过来了o(∩_∩)o...哈哈 Blog作者的回复: Blog作者的回复: Blog作者的回复: Blog作者的回复: Blog作者的回复:


![]()
网友: flylonglong
时间:2007-11-24 17:12:01 IP地址:202.115.65.★
为什么完全照着你的做的
在
一、在U-Boot中建立自己的开发板类型,并测试编译。
中的第四小步
4 测试编译能否成功
$make tekkaman2410_config
执行以上命令之后 出现以下提示:
Configuring for tekkaman2410 board...
ln:正在创建连至'asm-arm'的符号连接'asm':不允许的操作
make:***[ebest2410-config] Error 1
我昨天在编译内核的时候也出现了
ln:正在创建连至'asm-arm'的符号连接'asm':不允许的操作
这条错误
不知道怎么回事情
使用chmod命令也修改不了'asm-arm'文件的属性(它的属性是不可读写的)
不知道该怎么办了 不知道楼主知道否?????
PS:我开发环境是 vmware+redhat9.0




![]()
网友: flylonglong
时间:2007-11-24 18:04:06 IP地址:202.115.65.★
上面问题好象是解决了
不过还是在$make tekkaman2410_config 通过之后
在执行 $make 的时候
一堆英文过后
最后一行提示 make:*** [uboot] Error 1
诶 可能是我的开发环境和博主的不同吧
但是又实在找不出错在哪
真苦闷啊
flylonglong 您好!上面的问题我还从来没碰过。我猜想可能的原因有两个:1、你的编译器没有制作好。2、你的开发系可能老了点。我建议你自己制作一个编译器看看 ,第一个问题的可能性比较大。




![]()
网友: jscorps
时间:2007-12-28 18:14:38 IP地址:211.23.177.★
很冒昧的請問一下 , 在u-boot 1.2.0中, 原本就有sbc2410x的board 設定. 它如果用在friendly -arm上的sbc2410x , 是不是就可以從NAND FLASH上面啟動呢? 還是u-boot 1.2.0 中的sbc2410x 本來就沒有支援NAND flash boot up.
Thanks
sbc2410x源码不支持NAND启动,也要通过类似2410-S的一些修改来实现。




![]()
网友: jscorps
时间:2007-12-31 16:16:13 IP地址:210.202.45.★
我了解了 , 謝謝您的回覆.....
有問題 , 再跟您請教...^_^




![]()
网友: heufkk
时间:2007-12-31 16:18:08 IP地址:218.7.43.★
你好,参照你的文章我移植1.1.5,遇到如下问题
/root/u-boot-1.1.5/include/configs/fk2410.h:220:1: warning: this is the location of the previous definition
/root/bin/arm-uclinux-tool/bin/arm-uclinux-gcc -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000 -I/root/u-boot-1.1.5/include -fno-builtin -ffreestanding -nostdinc -isystem /root/bin/arm-uclinux-tool/lib/gcc/arm-uclinux/3.4.0/include -pipe -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -Wall -Wstrict-prototypes -c -o env_dataflash.o env_dataflash.c
/root/bin/arm-uclinux-tool/bin/arm-uclinux-gcc -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000 -I/root/u-boot-1.1.5/include -fno-builtin -ffreestanding -nostdinc -isystem /root/bin/arm-uclinux-tool/lib/gcc/arm-uclinux/3.4.0/include -pipe -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -Wall -Wstrict-prototypes -c -o env_flash.o env_flash.c
env_flash.c:70: error: `CFG_FLASH_BASE' undeclared here (not in a function)
env_flash.c: In function `saveenv':
env_flash.c:330: warning: implicit declaration of function `flash_sect_protect'
env_flash.c:334: warning: implicit declaration of function `flash_sect_erase'
env_flash.c:338: warning: implicit declaration of function `flash_write'
make[1]: *** [env_flash.o] 错误 1
make[1]: Leaving directory `/root/u-boot-1.1.5/common'
make: *** [common/libcommon.a] 错误 2
你前面把CFG_FLASH_BASE'注释掉了,那么我遇见这样的问题是怎么回事?
感谢你的回答
env_flash 是使用nor flash。2410-S没有nor flash ,所以我移植时,将一些关于nor flash 的源码删除或是不去理会。可能是这里出了问题,你要参考一下有关nor flash 移植的资料。




![]()
网友: freeubuntu
时间:2008-01-08 12:04:50 IP地址:58.60.126.★
我完全按照你的方法修改uboot1.2.0,gpio和内存地址分配参考开发商提供的bootloader
编译时保错,主要原因是在修改中删除了很多define,很多东西都没有定义了
flash.c: In function 'flash_init':
flash.c:64: error: 'CFG_MAX_FLASH_BANKS' undeclared (first use in this function)
flash.c:64: error: (Each undeclared identifier is reported only once
flash.c:64: error: for each function it appears in.)
flash.c:67: error: 'flash_info' undeclared (first use in this function)
flash.c:75:2: error: #error "Unknown flash configured"
flash.c:77: error: 'PHYS_FLASH_SIZE' undeclared (first use in this function)
flash.c:78: error: 'CFG_MAX_FLASH_SECT' undeclared (first use in this function)
flash.c:81: error: 'PHYS_FLASH_1' undeclared (first use in this function)
flash.c:113: warning: implicit declaration of function 'flash_protect'
flash.c:113: error: 'FLAG_PROTECT_SET' undeclared (first use in this function)
flash.c:114: error: 'CFG_FLASH_BASE' undeclared (first use in this function)
flash.c:119: error: 'CFG_ENV_ADDR' undeclared (first use in this function)
flash.c: At top level:
flash.c:127: error: expected ')' before '*' token
flash.c:172: error: expected ')' before '*' token
flash.c:293: error: expected ')' before '*' token
flash.c:371: error: expected ')' before '*' token
你有碰到过这些问题吗?
出现这种情况的原因很可能是nor flash 的驱动造成的。如果你的板上有nor flash ,请参考我移植SBC2440V4的文章,那个板子有nor flash ,而且在nor flash方面两个芯片的基本代码一样。
如果你不使用nor flash ,那就是你没有将nor flash的驱动清干净,比如:修改/include/configs/tekkaman2410.h时漏了什么。
最后出现
flash.c:127: error: expected ')' before '*' token
flash.c:172: error: expected ')' before '*' token
flash.c:293: error: expected ')' before '*' token
flash.c:371: error: expected ')' before '*' token
有可能是语法错误,可能是你手误,多删或少删了什么,比如“;”或“)”等等。
移植到2410的那篇文章我复查过应该不会有问题。




![]()
网友: freeubuntu
时间:2008-01-09 16:37:35 IP地址:58.60.126.★
上个问题解决了,可还是有错误,报错如下:
common/libcommon.a(env_nand.o): In function `saveenv':
/home/freedom/Desktop/uboot/u-boot-1.2.0/common/env_nand.c:212: undefined reference to `nand_info'
make: *** [u-boot] Error 1
看了上面的解答,知道应该是nor flash的问题,nor flash删除了一些什么内容呢?我再看一下
可能是你在:
10 修改common/env_nand.c时,漏了extern nand_info_t nand_info[CFG_MAX_NAND_DEVICE];
你仔细看看10 修改common/env_nand.c这部分,看看有没有漏改了什么。
在实现这个驱动前,我用U-Boot就是这么痛苦。
以下介绍驱动的移植和U-Boot下网卡驱动移植、编写的一般方法。
......
DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP);
DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */
DP_OUT(base, DP_RCR, DP_RCR_AB); /* Accept broadcast, no errors, no multicast */
DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
dp->running = true;
}
......
static void
dp83902a_send(unsigned short *data, int total_len, unsigned long key)
{
......
DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
{
/* Dummy read. The manual sez something slightly different, */
/* but the code is extended a bit to do what Hitachi's monitor */
/* does (i.e., also read data). */
/* //屏蔽无用的语句
cyg_uint16 tmp;
int len = 1;
DP_OUT(base, DP_RSAL, 0x100-len);
DP_OUT(base, DP_RSAH, (start_page-1) & 0xff);
DP_OUT(base, DP_RBCL, len);
DP_OUT(base, DP_RBCH, 0);
DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);
DP_IN_DATA(dp->data, tmp);
*/ }
......
#if DEBUG & 4
printf(" sg buf %08lx len %08x\n ", (unsigned long) data, len);
dx = 0;
#endif
while (len > 1) {
#if DEBUG & 4
printf(" %04x", *data);
if (0 == (++dx % 16)) printf("\n ");
#endif
DP_OUT_DATA(dp->data, *data++);
len-=2;
}
#if DEBUG & 4
if (len==1) printf(" %04x", (*data)&0xff);
printf("\n");
#endif
if (len==1) {DP_OUT_DATA(dp->data, (*data++)&0xff); total_len++; }
if (total_len < pkt_len) {
#if DEBUG & 4
printf(" + %d bytes of padding\n", pkt_len - total_len);
#endif
/* Padding to 802.3 length was required */
for (i = total_len; i < pkt_len;) {
i+=2;
DP_OUT_DATA(dp->data, 0);
}
}
......
}
/*
This function is called when a packet has been received. It's job is
to prepare to unload the packet from the hardware. Once the length of
the packet is known, the upper layer of the driver can be told. When
the upper layer is ready to unload the packet, the internal function
'dp83902a_recv' will be called to actually fetch it from the hardware.
*/
static void
dp83902a_RxEvent(void)
{
struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
cyg_uint8 *base = dp->base;
unsigned char rsr;
unsigned short rcv_hdr[2];
int i, len, pkt, cur;
......
DP_OUT(base, DP_RBCL, 4);
DP_OUT(base, DP_RBCH, 0);
DP_OUT(base, DP_RSAL, 0);
DP_OUT(base, DP_RSAH, pkt);
if (dp->rx_next == pkt) {
if (cur == dp->rx_buf_start)
DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
else
DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */
return;
}
dp->rx_next = pkt;
DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
CYGACC_CALL_IF_DELAY_US(10);
#endif
for (i = 0; i < sizeof(rcv_hdr);) {
DP_IN_DATA(dp->data, rcv_hdr[i++]);
}
#if DEBUG & 5
printf("rx hdr %04x %04x \n",
rcv_hdr[0], rcv_hdr[1]);
#endif
len = rcv_hdr[1] - 4;
uboot_push_packet_len(len);
if (((rcv_hdr[0] >>8)&0xff) == dp->rx_buf_start)
DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
else
DP_OUT(base, DP_BNDRY, ((rcv_hdr[0] >>8)&0xff)-1); /* Update pointer */
}
}
/*
This function is called as a result of the "eth_drv_recv()" call above.
It's job is to actually fetch data for a packet from the hardware once
memory buffers have been allocated for the packet. Note that the buffers
may come in pieces, using a scatter-gather list. This allows for more
efficient processing in the upper layers of the stack.
*/
static void
dp83902a_recv(unsigned short *data, int len)
{
......
/* Read incoming packet data */
DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
DP_OUT(base, DP_RBCL, len & 0xFF);
DP_OUT(base, DP_RBCH, (len >> 8)& 0xFF);
DP_OUT(base, DP_RSAL, 4); /* Past header */
DP_OUT(base, DP_RSAH, dp->rx_next);
DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
CYGACC_CALL_IF_DELAY_US(10);
#endif
saved = false;
for (i = 0; i < 1; i++) {
if (data) {
mlen = len;
#if DEBUG & 4
printf(" sg buf %08lx len %08x \n", (unsigned long) data, mlen);
dx = 0;
#endif
while (0 < mlen) {
/* Saved byte from previous loop? */
if (saved) {
*data++ = saved_char;
mlen--;
saved = false;
continue;
}
{
cyg_uint16 tmp;
DP_IN_DATA(dp->data, tmp);
#if DEBUG & 4
printf(" %04x", tmp);
if (0 == (++dx % 16)) printf("\n ");
#endif
*data++ = tmp;
mlen-=2;
if (mlen==1) {
DP_IN_DATA(dp->data, tmp);
tmp = tmp & 0xff;
#if DEBUG & 4
printf(" %04x", tmp);
#endif
*data++ = tmp;
mlen--;
}
}
}
#if DEBUG & 4
printf("\n");
#endif
}
}
}
......
//添加自定义的AX88796硬件信息,在这里定义了如果网卡的MAC地址的前三个为
//0x08, 0x08, 0x08,那就是AX88796。如果你要修改MAC地址 ,
//最好前三个要和这三个一样,不然驱动会认不到网卡。
static hw_info_t hw_info[] = {
......
{ /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
{ /* AX88796 */ 0x0ff0, 0x08, 0x08, 0x08, 0 },
{ /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
......
};
......
static void pcnet_reset_8390(void)
{
int i, r;
PRINTK("nic base is %lx\n", nic_base);
#if 1
n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD);
PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
#endif
n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET);
//低级错误,严重的BUG,没有修改无法实现网卡的热复位,晕死。
for (i = 0; i < 100; i++) {
if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0)
break;
PRINTK("got %x in reset\n", r);
my_udelay(100);
}
n2k_outb(0xff, EN0_ISR); /* Ack intr. */
if (i == 100)
printf("pcnet_reset_8390() did not complete.\n");
} /* pcnet_reset_8390 */
static hw_info_t * get_prom(void ) {
unsigned char prom[32];
char ethaddr[20]; //tekkaman
int i, j, tekkaman; //tekkaman
unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0};//tekkaman
......
pcnet_reset_8390();
mdelay(10);
for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
n2k_outb(program_seq[i].value, program_seq[i].offset);
tekkaman=ne2000_read_mac_addr(prom);
if (tekkaman) {
printf("ethaddr in nand is not found ,loading ne_defethaddr:");
for (i = 0; i < 12; i++) {
prom[i] = ne_defethaddr[i/2];
printf(" %02x", prom[i]);
}
}
prom[28] = prom[30] = 0x57;
PRINTK("\n");
for (i = 0; i < NR_INFO; i++) {
if ((prom[0] == hw_info[i].a0) &&
(prom[2] == hw_info[i].a1) &&
(prom[4] == hw_info[i].a2)) {
PRINTK("matched board %d\n", i);
break;
}
}
if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
for (j = 0; j < 6; j++)
dev_addr[j] = prom[j<<1];
PRINTK("on exit i is %d/%ld\n", i, NR_INFO);
PRINTK("MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n",
dev_addr[0],dev_addr[1],dev_addr[2],dev_addr[3],dev_addr[4],dev_addr[5]);
return (i < NR_INFO) ? hw_info+i : &default_info;
if (tekkaman) {
sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
dev_addr[0], dev_addr[1],
dev_addr[2], dev_addr[3],
dev_addr[4], dev_addr[5]) ;
printf("Set environment from HW MAC addr = \"%s\"\n", ethaddr);
setenv ("ethaddr", ethaddr);
}
}
return NULL;
}
/* U-boot specific routines */
#define NB 5
static unsigned short *pbuf = NULL;
static int plen[NB];
static int nrx = 0;
static int pkey = -1;
void uboot_push_packet_len(int len) {
PRINTK("pushed len = %d, nrx = %d\n", len, nrx);
if (len>=2000) {
printf("NE2000: packet too big\n");
return;
}
if (nrx >= NB) {
printf("losing packets in rx\n");
return;
}
plen[nrx] = len;
dp83902a_recv(&pbuf[nrx*1000], len);
nrx++;
}
void uboot_push_tx_done(int key, int val) {
PRINTK("pushed key = %d\n", key);
pkey = key;
}
int eth_init(bd_t *bd) {
static hw_info_t * r;
// char ethaddr[20];
PRINTK("### eth_init\n");
if (!pbuf) {
pbuf = malloc(NB*1000);
if (!pbuf) {
printf("Cannot allocate rx buffers\n");
return -1;
}
}
#ifdef CONFIG_DRIVER_NE2000_CCR
{
volatile unsigned char *p = (volatile unsigned char *) CONFIG_DRIVER_NE2000_CCR;
PRINTK("CCR before is %x\n", *p);
*p = CONFIG_DRIVER_NE2000_VAL;
PRINTK("CCR after is %x\n", *p);
}
#endif
nic_base = CONFIG_DRIVER_NE2000_BASE;
nic.base = (cyg_uint8 *) CONFIG_DRIVER_NE2000_BASE;
r = get_prom();
if (!r)
return -1;
/*//屏蔽无用的语句
sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
dev_addr[0], dev_addr[1],
dev_addr[2], dev_addr[3],
dev_addr[4], dev_addr[5]) ;
PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr);
setenv ("ethaddr", ethaddr);
*/
#define DP_DATA 0x10
nic.data = (unsigned short *) (nic.base + DP_DATA);
nic.tx_buf1 = 0x40;
nic.tx_buf2 = 0x46;
nic.rx_buf_start = 0x4C;
nic.rx_buf_end = 0x80;
dp83902a_start(dev_addr);
if (dp83902a_init() == false)
return -1;
return 0;
}
void eth_halt() {
PRINTK("### eth_halt\n");
dp83902a_stop();
}
int eth_rx() {
int j, tmo;
volatile uchar * inpkt
PRINTK("### eth_rx\n");
tmo = get_timer (0) + TOUT * CFG_HZ;
while(1) {
dp83902a_poll();
if (nrx > 0) {
for(j=0; j
NetReceive(inpkt, plen[j]);//这句的作用就是将接收到的数据
//送到MAC层以上的协议层
}
nrx = 0;
return 1;
}
if (get_timer (0) >= tmo) {
printf("timeout during rx\n");
return 0;
}
}
return 0;
}
int eth_send(volatile void *packet, int length) {
int tmo;
PRINTK("### eth_send\n");
pkey = -1;
dp83902a_send((unsigned short *) packet, length, 666);
tmo = get_timer (0) + TOUT * CFG_HZ;
while(1) {
dp83902a_poll();
if (pkey != -1) {
PRINTK("Packet sucesfully sent\n");
return 0;
}
if (get_timer (0) >= tmo) {
printf("transmission error (timoeut)\n");
return 0;
}
}
return 0;
}
#endif
ne2000.c修改完毕
NE2000驱动的低级错误
将第45行:
at */
改为:
at
就是去掉“*/” , 真是TNND汗死
!!!!
......
#define DP_IN(_b_, _o_, _d_) (_d_) = *( (volatile unsigned char *) ((_b_)+(_o_)))
#define DP_OUT(_b_, _o_, _d_) *( (volatile unsigned char *) ((_b_)+(_o_))) = ((unsigned char) (_d_))
#define DP_IN_DATA(_b_, _d_) (_d_) = *( (volatile unsigned short *) ((_b_)))
#define DP_OUT_DATA(_b_, _d_) *( (volatile unsigned short *) ((_b_))) = ((unsigned short) (_d_))
/* here is all the data */
#define cyg_uint8 unsigned char
#define cyg_uint16 unsigned short
#define bool int
#define false 0
#define true 1
#define CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 1
#define CYGACC_CALL_IF_DELAY_US(X) my_udelay(X)
typedef struct dp83902a_priv_data {
cyg_uint8* base;
cyg_uint16* data;
cyg_uint8* reset;
int tx_next; /* First free Tx page */
int tx_int; /* Expecting interrupt from this buffer */
int rx_next; /* First free Rx page */
int tx1, tx2; /* Page numbers for Tx buffers */
unsigned long tx1_key, tx2_key; /* Used to ack when packet sent */
int tx1_len, tx2_len;
bool tx_started, running, hardwired_esa;
cyg_uint8 esa[6];
void* plf_priv;
/* Buffer allocation */
int tx_buf1, tx_buf2;
int rx_buf_start, rx_buf_end;
} dp83902a_priv_data_t;
......
(3)修改8390.h
......
/*
* Only generate indirect loads given a machine that needs them.
* - removed AMIGA_PCMCIA from this list, handled as ISA io now
*/
#define n2k_inb(port) (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)))
#define n2k_outb(val,port) (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)) = ((unsigned char) val))
#define EI_SHIFT(x) (x)
......
网卡驱动程序的修改到此结束,以下是总线参数的修改:
修改/board/tekkaman/tekkaman2410/lowlevel_init.S文件(参数都是参考 刘淼 的书):
#define B1_BWSCON (DW16)
#define B2_BWSCON (DW16 + UBLB)
#define B3_BWSCON (DW16)
......
#define B2_Tacs 0x3 /* 4clk tekkaman*/
#define B2_Tcos 0x3 /* 4clk tekkaman*/
#define B2_Tacc 0x7 /* 14clk */
#define B2_Tcoh 0x3 /* 4clk tekkaman*/
#define B2_Tah 0x3 /* 4clk tekkaman*/
#define B2_Tacp 0x3 /* 6clk tekkaman*/
#define B2_PMC 0x0 /* normal */
......
U-Boot 1.2.0 (Sep 25 2007 - 14:59:27)
U-Boot code: 33F80000 -> 33F98BC0 BSS: -> 33F9D3C0
DRAM: 64 MB
NAND: 64 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
[Tekkaman2410]# printenv
bootdelay=3
baudrate=115200
ethaddr=08:08:08:08:12:27
netmask=255.255.255.0
bootfile=zImage.img
loadaddr=0x30008000
bootargs=root=/dev/nfs rw nfsroot=192.168.1.22:/home/tekkaman/working/rootfs ip=192.168.1.2:192.168.1.22::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M
bootcmd=tftp;bootm
ipaddr=192.168.1.2
serverip=192.168.1.22
stdin=serial
stdout=serial
stderr=serial
Environment size: 382/65532 bytes
U-Boot 1.2.0 (Sep 25 2007 - 14:59:27)
U-Boot code: 33F80000 -> 33F98BC0 BSS: -> 33F9D3C0
DRAM: 64 MB
NAND: 64 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
### eth_init
matched board 31
AX88796 - tekkmana ESA: 08:08:08:08:12:27
TFTP from server 192.168.1.22; our IP address is 192.168.1.2
Filename 'zImage.img'.
Load address: 0x30008000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#############
done
Bytes transferred = 1727136 (1a5aa0 hex)
## Booting image at 30008000 ...
Image Name: tekkamanninja
Created: 2007-09-25 9:28:11 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1727072 Bytes = 1.6 MB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
Starting kernel ...
Uncompressing Linux................................................................................................................ done, booting the kernel.
Linux version 2.6.22.2 () (gcc version 4.1.0) #5 Tue Sep 25 15:43:11 CST 2007
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
Machine: Tekkaman2410
Memory policy: ECC disabled, Data cache writeback
CPU S3C2410A (id 0x32410002)
S3C2410: core 202.800 MHz, memory 101.400 MHz, peripheral 50.700 MHz
S3C24XX Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists. Total pages: 16256
Kernel command line: root=/dev/nfs rw nfsroot=192.168.1.22:/home/tekkaman/working/rootfs ip=192.168.1.2:192.168.1.22::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M
irq: clearing pending ext status 00000100
irq: clearing subpending status 00000002
(以下略)