接着上一篇文章:(字体我就不改了)
4.添加u-boot对nand的读写功能
因为2442与2440差别不大,现参照2440的移植方法进行操作:
在driver/mtd/nand下添加s3c2440_nand.c文件,内容如下:
#include <common.h>
#if 0
#define DEBUGN printf
#else
#define DEBUGN(x, args ...) {}
#endif
#include <nand.h>
#include <asm/arch/s3c24x0_cpu.h>
#include <asm/io.h>
#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 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 NFECC0 __REGb(NF_BASE + 0x2c)
#define NFECC1 __REGb(NF_BASE + 0x2d)
#define NFECC2 __REGb(NF_BASE + 0x2e)
#define S3C2440_NFCONT_nCE (1<<1)
#define S3C2440_ADDR_NALE 0x0c
#define S3C2440_ADDR_NCLE 0x08
#define S3C2440_NFCONT_nFCE (1<<1)
#define S3C2440_NFCONT_EN (1<<0)
#define S3C2440_NFCONT_INITECC (1<<4)
#define S3C2440_NFCONT_MAINECCLOCK (1<<5)
#define S3C2440_NFCONF_TACLS(x) ((x)<<12)
#define S3C2440_NFCONF_TWRPH0(x) ((x)<<8)
#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4)
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;
else
NFCONT |= S3C2440_NFCONT_nCE;
}
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);
}
#ifdef CONFIG_S3C2440_NAND_HWECC //硬件ECC还没完成,只好用软件ECC
void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
DEBUGN("s3c2440_nand_enable_hwecc(%p, %d)/n", mtd, mode);
struct s3c2410_nand *nand = s3c2410_get_base_nand();
writel(readl(&nand->NFCONT) | S3C2440_NFCONT_INITECC, &nand->NFCONT);
}
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
{
ecc_code[0] = NFECC0;
ecc_code[1] = NFECC1;
ecc_code[2] = NFECC2;
DEBUGN("s3c2440_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x/n",
mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
return 0;
}
static int s3c2440_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
if (read_ecc[0] == calc_ecc[0] &&
read_ecc[1] == calc_ecc[1] &&
read_ecc[2] == calc_ecc[2])
return 0;
printf("s3c2440_nand_correct_data: not implemented/n");
return -1;
}
#endif
int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
struct s3c24x0_clock_power * const clk_power = s3c24x0_get_base_clock_power();
DEBUGN("board_nand_init()/n");
clk_power->CLKCON |= (1 << 4);
twrph0 = 4; twrph1 = 2; tacls = 0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
NFCONF = cfg;
cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;
/* 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;
nand->ecc.mode = NAND_ECC_SOFT; //采用软件ECC
return 0;
}
接下来在board2442.h中添加支持Nand的宏:
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_ARM920T 1 /* This is an ARM920T Core */
#define CONFIG_S3C24X0 1 /* in a SAMSUNG S3C24x0-type SoC */
#define CONFIG_S3C2410 1 /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_S3C2440 1
#define CONFIG_S3C2442b 1
/*
* Command line configuration.
*/
#define CONFIG_CMD_NAND
#define CONFIG_CMDLINE_EDITING
#ifdef CONFIG_CMDLINE_EDITING
#undef CONFIG_AUTO_COMPLETE
#else
#define CONFIG_AUTO_COMPLETE
#endif
/*Nand flash settings*/
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE 0x4E000000 //Nand配置寄存器基地址
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define CONFIG_NAND_S3C2440
#endif
接下来,在drivers/mtd/nand/Makefile文件中添加s3c2440_nand.c的编译项,如下:
COBJS-y += s3c2440_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
这部分与2440的移植相比基本上是一样的,唯一不同的是我参考了网上别人的博客,把ECC错误验证加上去了,这样就不会有烦人的“ECC_SNAND_ECC_NONE selected by board driver. This is not recommended !!”的提示。
记得以前看过网上说u-boot nand的ECC有bug,不过目前还没怎么发现,有待进一步观察。
现在启动后界面如下:

5.其他一些调整
修改board2442.h 注释掉储存环境变量到flash中的宏
//#define CONFIG_ENV_IS_IN_FLASH 1
//#define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
添加储存到nand中的宏
#define CONFIG_CMD_SAVEENV
#define CONFIG_ENV_IS_IN_NAND 1
#define CONFIG_ENV_OFFSET 0x40000
#define CONFIG_ENV_SIZE 0x20000
之后重新编译前需要make clean一下,不然最后链接时还会链接到env_flash.o文件,会使修改没有效果。
定义以下宏,才能让u-boot传递内核启动参数(如果编译出错就去掉这两个定义)
#define CONFIG_CMDLINE_TAG
#define CONFIG_SETUP_MEMORY_TAGS
修改arch/arm/lib 下board.c文件注释掉flash语句:
// display_flash_config (flash_init ());
在board.c文件中,u-boot是通过init_sequence[]结构体数组中调用env_init函数来进行环境变量的初始化。之后转到common/env_XXX.c文件执行。env_XXX.c文件中也包含了读取,存储环境变量的函数。XXX可以是flash,dataflash,eeprom,mmc,nand。由不同的存储介质编译相应的env_XXX文件。打开该目录下的Makefile,发现:
COBJS-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o
COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += env_eeprom.o
COBJS-$(CONFIG_ENV_IS_EMBEDDED) += env_embedded.o
COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += env_embedded.o
COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_embedded.o
COBJS-$(CONFIG_ENV_IS_IN_NVRAM) += env_embedded.o
COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
COBJS-$(CONFIG_ENV_IS_IN_MG_DISK) += env_mgdisk.o
COBJS-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
COBJS-$(CONFIG_ENV_IS_IN_NVRAM) += env_nvram.o
COBJS-$(CONFIG_ENV_IS_IN_ONENAND) += env_onenand.o
COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
由此可见,通过定义不同的宏,就能选择操作环境变量的不同存储介质。
common/env_common.c文件中有所有默认环境变量的设置。
6.ax88180以太网芯片的移植:
打开board/samsung/board2442/board2442.c
修改:
#ifdef CONFIG_CMD_NET
int board_eth_init(bd_t *bis)
{
int rc = 0;
#if 0
rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
rc = ax88180_initialize(bis);
return rc;
}
#endif
修改board2442.h, 注释掉cs8900的宏,添加ax88180的宏
/*
* Hardware drivers
*/
#define CONFIG_NET_MULTI
//#define CONFIG_CS8900 /* we have a CS8900 on-board */
//#define CONFIG_CS8900_BASE 0x19000300
//#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
#define CONFIG_DRIVER_AX88180
#define AX88180_BASE 0x28000000 //ax88180在bank5,所以地址是28000000
添加网络命令:
/*
* Command line configuration.
*/
#include <config_cmd_default.h>
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_SAVEENV
#define CONFIG_CMD_NAND
#define CONFIG_CMD_PING
#define CONFIG_CMD_NET
设置ip,网关,掩码,mac地址:
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.1.5 //开发板ip
#define CONFIG_SERVERIP 192.168.1.100 //主机ip
#define CONFIG_ETHADDR 08:00:3e:26:0a:5c //由于mac芯片没有接储存mac地址的eeprom,所以需要我们手动指定一个mac地址
除了修改这里,还要修改ax88180.c文件里,给相应变量赋值:
static void ax88180_read_mac_addr (struct eth_device *dev)
{
unsigned short macid0_val, macid1_val, macid2_val;
unsigned short tmp_regval;
unsigned short i;
/* Reload MAC address from EEPROM */
OUTW (dev, RELOAD_EEPROM, PROMCTRL);
/* Waiting for reload eeprom completion */
for (i = 0; i < 500; i++) {
tmp_regval = INW (dev, PROMCTRL);
if ((tmp_regval & RELOAD_EEPROM) == 0)
break;
udelay (1000);
}
#ifdef CONFIG_ETHADDR
/* Get MAC addresses */
dev->enetaddr[0] = 0x08;
dev->enetaddr[1] = 0x00;
dev->enetaddr[2] = 0x3e;
dev->enetaddr[3] = 0x26;
dev->enetaddr[4] = 0x0a;
dev->enetaddr[5] = 0x5c;
#else
/* Get MAC addresses */
macid0_val = INW (dev, MACID0);
macid1_val = INW (dev, MACID1);
macid2_val = INW (dev, MACID2);
if (((macid0_val | macid1_val | macid2_val) != 0) &&
((macid0_val & 0x01) == 0)) {
dev->enetaddr[0] = (unsigned char)macid0_val;
dev->enetaddr[1] = (unsigned char)(macid0_val >> 8);
dev->enetaddr[2] = (unsigned char)macid1_val;
dev->enetaddr[3] = (unsigned char)(macid1_val >> 8);
dev->enetaddr[4] = (unsigned char)macid2_val;
dev->enetaddr[5] = (unsigned char)(macid2_val >> 8);
}
#endif
}
再修改board/samsung/board2442/lowlevel_init.s中对内存控制寄存器的设置:
#define B1_BWSCON (DW32)
#define B2_BWSCON (DW16)
#define B3_BWSCON (DW16 + WAIT + UBLB)
#define B4_BWSCON (DW16)
#define B5_BWSCON (DW32 + WAIT + UBLB) //将对应片选的地址空间设成32位
#define B6_BWSCON (DW32)
#define B7_BWSCON (DW32)
下面这部分是修改时钟周期的,不修改应该也没问题
#define B5_Tacs 0x0 /* 0clk */
#define B5_Tcos 0x3 /* 0clk */
#define B5_Tacc 0x7 /* 14clk */
#define B5_Tcoh 0x1 /* 0clk */
#define B5_Tah 0x0 /* 0clk */
#define B5_Tacp 0x3
#define B5_PMC 0x0 /* normal */
修改内存刷新频率这部分要改:
#define REFCNT 0x4f4 /* period=7.8125us, HCLK=100Mhz, (2048+1-7.8125*100) */
另外,为了能使u-boot正常使用nfs协议,需修改net/nfs.c 文件
#define NFS_TIMEOUT (30*2000UL)
//把延迟由2000UL延长成成 30*2000UL,不然会有提示ERROR: Cannot unmount!
之后重新编译u-boot这时ax88180网口应该就能用了。
Ax88180现在应该已经可以用了,不过很难ping通,tftp传文件也不行。数据已经能从物理层通过网线发出来了,但是主机经常收不到包,估计是信号质量不高的原因。
本文介绍U-Boot在S3C2442平台上的NAND闪存支持移植过程及AX88180以太网控制器的驱动集成。详细讲述了如何添加NAND闪存读写功能、配置环境变量存储位置,并实现网络功能。
:nand读写和ax88180以太网支持&spm=1001.2101.3001.5002&articleId=6579515&d=1&t=3&u=b138af9ee96d4146a6aa767a45c41fe9)
4566

被折叠的 条评论
为什么被折叠?



