u-boot版本:1.1.6
交叉编译器:3.3.2
开发板:友善之臂mini2440
开发板配置:SoC s3c2440 、网卡 DM9000 、 Nor Flash AM29LV160DB (2M) 、NAND FLash (256M) 、SDRAM (64M)
以源文件已存在的 smdk2410项目为基础进行移植工作
1.移植准备工作
1).下载u-boot-1.1.6源码,并解压;
2).建立u-boot的source insight工程,方便查找及分析;
3).安装arm-Linux交叉编译器,版本3.3.2
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
arm920t:CPU型号
smdk2410:开发板名称
NULL: 开发者
s3c24x0: 片上系统
类比此项添加配置选项:
mini2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
1).找到 /board/smdk2410 目录,将此目录复制为 /board/mini2440 ,打开mini2440目录,将smdk2410.c文件重命名为mini2440.c。打开同目录下Makefile文件,修改代码
变更前: COBJS := smdk2410.o flash.o
#define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
4.修改CPU频率设置
1).将以上步骤建立的代码编译测试:
root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make mini2440_config
Configuring for mini2440 board...
root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make
生成u-boot.bin 下载至开发板运行,发现并未打印出任何信息。原因是2410和2440在频率设置方面有所不同。
2). 打开 /board/mini2440/mini2440.c ,屏蔽下列代码
#if 0
#define FCLK_SPEED 1
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#endif
#define USB_CLOCK 1
#if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#endif
int board_init (void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
clk_power->CLKDIVN = 0x05; /* 1 : 4 : 8 */
__asm__( "mrc p15,0,r1,c1,c0,0\n"
"orr r1,r1,#0xc0000000\n"
"mcr p15,0,r1,c1,c0,0\n"
:::"r1"
);//异步总线
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;
/* configure MPLL */
clk_power->MPLLCON = ((0x5c << 12) + (0x01 << 4) + 0x01); //400MHz
/* some delay between MPLL and UPLL */
delay (4000);
/* configure UPLL */
clk_power->UPLLCON = ((0x38 << 12) + (0x02 << 4) + 0x02); //48MHz
/* some delay between MPLL and UPLL */
delay (8000);
/* set up the I/O ports */
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;
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
icache_enable();
dcache_enable();
return 0;
}
改为
其他修改:
/* return HCLK frequency */
ulong get_HCLK(void)
{
return(get_FCLK()/4 );
}
/* return PCLK frequency */
ulong get_PCLK(void)
{
return(get_HCLK()/2 );
}
再次进行编译测试,出现打印信息:
U-Boot 1.1.6 (Jan 26 2017 - 17:10:05)
DRAM: 64 MB
Flash: 512 kB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
SMDK2410 #
5.支持Nor Flash AM29lv160DB
打开 mini2440.h 头文件,发现flash配置项只有CONFIG_AMD_LV400和CONFIG_AMD_LV800,没有本型号,因为AM29lv160DB符合CFI接口标准,故使用 /drivers/cfi_flash.c 中的接口函数。进行下列修改:
1).屏蔽代码
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#if 0
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
#endif
增加宏定义
#define CFG_FLASH_CFI_DRIVER 1
修改代码
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
#define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
#endif
#ifdef CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
#define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
#endif
为
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
#define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
#elif defined CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
#define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
#else
#define PHYS_FLASH_SIZE 0x00200000 /* 2MB */
#define CFG_MAX_FLASH_SECT (99) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x1F0000) /* addr of environment */
#endif
2) 在 /board/mini2440/makefile 中COBJS := mini2440.o flash.o去掉flash.o ,再次编译测试,出现错误:
cfi_flash.c:411: error: `CFG_MONITOR_BASE' undeclared (first use in this function)
在mini2440.h中加入宏定义
#define CFG_MONITOR_BASE 0
#define CFG_FLASH_CFI 1
再次编译,通过!烧写至开发板,打印出信息:
Flash: 2 MB
输入命令 flinfo
得到信息:
SMDK2410 # flinfo
Bank # 1: CFI conformant FLASH (16 x 16) Size: 2 MB in 35 Sectors
Erase timeout 8192 ms, write timeout 1 ms, buffer write timeout 1 ms, buffer size 1
Sector Start Addresses:
00000000 (RO) 00004000 (RO) 00006000 (RO) 00008000 (RO) 00010000 (RO)
00020000 00030000 00040000 00050000 00060000
00070000 00080000 00090000 000A0000 000B0000
000C0000 000D0000 000E0000 000F0000 00100000
00110000 00120000 00130000 00140000 00150000
00160000 00170000 00180000 00190000 001A0000
001B0000 001C0000 001D0000 001E0000 001F0000 (RO)
SMDK2410 #
至此nor flash支持移植成功。
6.支持DM9000网卡
smdk2410支持cs8900网卡,本开发板使用DM9000网卡,/drivers/dm9000x.c 是对应的网卡驱动。
1) 在mini2440.h中,将以下关于cs8900的宏注释掉,并添加DM9000宏定义:
/*
* 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
编译,出现错误提示:
dm9000x.c:374: error: `DM9000_IO' undeclared (first use in this function)
dm9000x.c:445: error: `DM9000_DATA' undeclared (first use in this function)
dm9000x.c:144: error: `CONFIG_DM9000_BASE' undeclared
以此继续增加宏定义:
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO 0x20000000
#define DM9000_DATA (DM9000_IO + 0x4)
#define CONFIG_DM9000_USE_16BIT 1
查看原理图可得本开发板网卡片选线接在BANK4,故基地址为0x20000000,IO为基地址,DATA与基地址偏移0x04,此外定义16BIT表示网卡使用16BIT模式。
2) 修改默认网络参数,mini2440.h 中修改代码:
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.31.111
#define CONFIG_SERVERIP 192.168.31.245
还有取消屏蔽:
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
再次编译,通过!下载至开发板,运行测试ping和tftp命令:发现ping无效,tftp可用。原因是未添加PING命令宏定义,故在mini2440.h中添加相关宏:
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
/*CFG_CMD_NAND |*/ \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I2C |*/ \
/*CFG_CMD_USB |*/ \
CFG_CMD_REGINFO | \
CFG_CMD_DATE | \
CFG_CMD_PING | \
再次测试,得到打印结果:
SMDK2410 # ping 192.168.31.245
dm9000 。。。。。
host 192.168.31.245 is alive
至此,dm9000支持移植成功。
7.支持NAND FLASH
nand的驱动代码在 /drivers/nand 目录下面,打开此目录下的nand.c文件,看到如下代码
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <nand.h>
所以判断使用nand驱动的宏开关为CFG_CMD_NAND。
1) 在mini2440.h中的CONFIG_COMMANDS中加入宏定义 CFG_CMD_NAND
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
CFG_CMD_NAND | \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I2C |*/ \
然后启动编译,错误如下:
nand.c:35: error: `CFG_MAX_NAND_DEVICE' undeclared here (not in a function)
nand.c:38: error: `CFG_NAND_BASE' undeclared here (not in a function)
home/book/Desktop/u-boot-1.1.6/include/linux/mtd/nand.h:412: error: `NAND_MAX_CHIPS' undeclared here (not in a function)
在mini2440.h中添加以上宏定义:
/*NAND FLASH*/
#define CFG_MAX_NAND_DEVICE 1
#define CFG_NAND_BASE 0x0
#define NAND_MAX_CHIPS 1
三者分别表示:
nand设备数量;
nand基地址,无实际意义,在board_nand_init函数中会被重新指定;
每个nand设备有1个nand芯片;
再次编译,出现错误为:
drivers/nand/libnand.a(nand.o)(.text+0x24): In function `nand_init':
/home/book/Desktop/u-boot-1.1.6/drivers/nand/nand.c:50: undefined reference to `board_nand_init'
意思是board_nand_init函数未定义。上电后nand的初始化过程为:start_armboot函数调用nand_init,nand_init函数在 /drivers/nand/nand.c中实现,nand_init函数调用同文件中nand_init_chip函数,nand_init_chip函数会首先调用board_nand_init函数来初始化nand设备。此函数是硬件相关,需要自己写。下一步实现此函数。
2) 实现board_nand_init函数。
在 /cpu/arm920t/s3c24x0/ 目录下建立文件nand_flash.c,文件内容为:
/*
* Nand flash interface of s3c2410/s3c2440
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <s3c2410.h>
#include <nand.h>
DECLARE_GLOBAL_DATA_PTR;
#define S3C2410_NFSTAT_READY (1<<0)
#define S3C2410_NFCONF_nFCE (1<<11)
#define S3C2440_NFSTAT_READY (1<<0)
#define S3C2440_NFCONT_nFCE (1<<1)
/* select chip, for s3c2410 */
static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
if (chip == -1) {
s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
} else {
s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
}
}
/* command and control functions, for s3c2410
*
* Note, these all use tglx's method of changing the IO_ADDR_W field
* to make the code simpler, and use the nand layer's code to issue the
* command and address sequences via the proper IO ports.
*
*/
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
struct nand_chip *chip = mtd->priv;
switch (cmd) {
case NAND_CTL_SETNCE:
case NAND_CTL_CLRNCE:
printf("%s: called for NCE\n", __FUNCTION__);
break;
case NAND_CTL_SETCLE:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
break;
case NAND_CTL_SETALE:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
break;
/* NAND_CTL_CLRCLE: */
/* NAND_CTL_CLRALE: */
default:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
break;
}
}
/* s3c2410_nand_devready()
*
* returns 0 if the nand is busy, 1 if it is ready
*/
static int s3c2410_nand_devready(struct mtd_info *mtd)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
}
/* select chip, for s3c2440 */
static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
if (chip == -1) {
s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
} else {
s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
}
}
/* command and control functions */
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
struct nand_chip *chip = mtd->priv;
switch (cmd) {
case NAND_CTL_SETNCE:
case NAND_CTL_CLRNCE:
printf("%s: called for NCE\n", __FUNCTION__);
break;
case NAND_CTL_SETCLE:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
break;
case NAND_CTL_SETALE:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
break;
/* NAND_CTL_CLRCLE: */
/* NAND_CTL_CLRALE: */
default:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
break;
}
}
/* s3c2440_nand_devready()
*
* returns 0 if the nand is busy, 1 if it is ready
*/
static int s3c2440_nand_devready(struct mtd_info *mtd)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
}
/*
* Nand flash hardware initialization:
* Set the timing, enable NAND flash controller
*/
static void s3c24x0_nand_inithw(void)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
if (0)
{
/* Enable NAND flash controller, Initialize ECC, enable chip select, Set flash memory timing */
s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
}
else
{
/* Set flash memory timing */
s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* Initialize ECC, enable chip select, NAND flash controller enable */
s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
}
}
/*
* Called by drivers/nand/nand.c, initialize the interface of nand flash
*/
void board_nand_init(struct nand_chip *chip)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
s3c24x0_nand_inithw();
if (0) {
chip->IO_ADDR_R = (void *)&s3c2410nand->NFDATA;
chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
chip->hwcontrol = s3c2410_nand_hwcontrol;
chip->dev_ready = s3c2410_nand_devready;
chip->select_chip = s3c2410_nand_select_chip;
chip->options = 0;
} else {
chip->IO_ADDR_R = (void *)&s3c2440nand->NFDATA;
chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
chip->hwcontrol = s3c2440_nand_hwcontrol;
chip->dev_ready = s3c2440_nand_devready;
chip->select_chip = s3c2440_nand_select_chip;
chip->options = 0;
}
chip->eccmode = NAND_ECC_SOFT;
}
#endif
还要在 /include/s3c24x0.h文件中增加本文件中使用到的S3C2440_NAND数据结构,在s3c2410_nand的下面,
/* NAND FLASH (see S3C2410 manual chapter 6) */
typedef struct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFECC;
} /*__attribute__((__packed__))*/ S3C2410_NAND;
增添2440nand的结构体:
typedef struct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCONT;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFMECCD0;
S3C24X0_REG32 NFMECCD1;
S3C24X0_REG32 NFSECCD;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFESTAT0;
S3C24X0_REG32 NFESTAT1;
S3C24X0_REG32 NFMECC0;
S3C24X0_REG32 NFMECC1;
S3C24X0_REG32 NFSECC;
S3C24X0_REG32 NFSBLK;
S3C24X0_REG32 NFEBLK;
} /*__attribute__((__packed__))*/ S3C2440_NAND;
然后打开同目录下的s3c2410.h,找到
static inline S3C2410_NAND * const S3C2410_GetBase_NAND(void)
{
return (S3C2410_NAND * const)S3C2410_NAND_BASE;
}
在其下面添加
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
{
return (S3C2440_NAND * const)S3C2410_NAND_BASE;
}
最后将新建的nand_flash.c文件编入u-boot之中。打开 /cpu/arm920t/s3c24x0/Makefile ,在COBJS中增加nand_flash.o:
COBJS = i2c.o interrupts.o serial.o speed.o \
usb_ohci.o nand_flash.o
编译,通过!下载至开发板运行,控制台打印出:NAND : 256MiB,输入命令nand info,打印信息:
NAND 256MiB 3.3V 8-bit, sector size 128 KiB
至此,NAND flash支持移植成功!
交叉编译器:3.3.2
开发板:友善之臂mini2440
开发板配置:SoC s3c2440 、网卡 DM9000 、 Nor Flash AM29LV160DB (2M) 、NAND FLash (256M) 、SDRAM (64M)
以源文件已存在的 smdk2410项目为基础进行移植工作
1.移植准备工作
1).下载u-boot-1.1.6源码,并解压;
2).建立u-boot的source insight工程,方便查找及分析;
3).安装arm-Linux交叉编译器,版本3.3.2
1).打开 /Makefile ,找到smdk2410板配置选项:
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
各项参数意义:
arm: CPU架构arm920t:CPU型号
smdk2410:开发板名称
NULL: 开发者
s3c24x0: 片上系统
类比此项添加配置选项:
mini2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
3.建立主代码
1).找到 /board/smdk2410 目录,将此目录复制为 /board/mini2440 ,打开mini2440目录,将smdk2410.c文件重命名为mini2440.c。打开同目录下Makefile文件,修改代码
变更前: COBJS := smdk2410.o flash.o
变更后: COBJS := mini2440.o flash.o
2).建立开发板配置头文件。将 /include/configs/smdk2410.h 复制为 /include/configs/mini2440.h ,打开此文件,添加
#define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
4.修改CPU频率设置
1).将以上步骤建立的代码编译测试:
root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make mini2440_config
Configuring for mini2440 board...
root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make
生成u-boot.bin 下载至开发板运行,发现并未打印出任何信息。原因是2410和2440在频率设置方面有所不同。
2). 打开 /board/mini2440/mini2440.c ,屏蔽下列代码
#if 0
#define FCLK_SPEED 1
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#endif
#define USB_CLOCK 1
#if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#endif
#endif
int board_init (void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
clk_power->CLKDIVN = 0x05; /* 1 : 4 : 8 */
__asm__( "mrc p15,0,r1,c1,c0,0\n"
"orr r1,r1,#0xc0000000\n"
"mcr p15,0,r1,c1,c0,0\n"
:::"r1"
);//异步总线
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;
/* configure MPLL */
clk_power->MPLLCON = ((0x5c << 12) + (0x01 << 4) + 0x01); //400MHz
/* some delay between MPLL and UPLL */
delay (4000);
/* configure UPLL */
clk_power->UPLLCON = ((0x38 << 12) + (0x02 << 4) + 0x02); //48MHz
/* some delay between MPLL and UPLL */
delay (8000);
/* set up the I/O ports */
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;
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
icache_enable();
dcache_enable();
return 0;
}
get_PLLCLK()
中
return((CONFIG_SYS_CLK_FREQ * m) / (p << s));改为
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
其他修改:
/* return HCLK frequency */
ulong get_HCLK(void)
{
return(get_FCLK()/4 );
}
/* return PCLK frequency */
ulong get_PCLK(void)
{
return(get_HCLK()/2 );
}
再次进行编译测试,出现打印信息:
U-Boot 1.1.6 (Jan 26 2017 - 17:10:05)
DRAM: 64 MB
Flash: 512 kB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
SMDK2410 #
5.支持Nor Flash AM29lv160DB
打开 mini2440.h 头文件,发现flash配置项只有CONFIG_AMD_LV400和CONFIG_AMD_LV800,没有本型号,因为AM29lv160DB符合CFI接口标准,故使用 /drivers/cfi_flash.c 中的接口函数。进行下列修改:
1).屏蔽代码
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#if 0
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
#endif
增加宏定义
#define CFG_FLASH_CFI_DRIVER 1
修改代码
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
#define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
#endif
#ifdef CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
#define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
#endif
为
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
#define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
#elif defined CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
#define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
#else
#define PHYS_FLASH_SIZE 0x00200000 /* 2MB */
#define CFG_MAX_FLASH_SECT (99) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x1F0000) /* addr of environment */
#endif
2) 在 /board/mini2440/makefile 中COBJS := mini2440.o flash.o去掉flash.o ,再次编译测试,出现错误:
cfi_flash.c:411: error: `CFG_MONITOR_BASE' undeclared (first use in this function)
在mini2440.h中加入宏定义
#define CFG_MONITOR_BASE 0
#define CFG_FLASH_CFI 1
再次编译,通过!烧写至开发板,打印出信息:
Flash: 2 MB
输入命令 flinfo
得到信息:
SMDK2410 # flinfo
Bank # 1: CFI conformant FLASH (16 x 16) Size: 2 MB in 35 Sectors
Erase timeout 8192 ms, write timeout 1 ms, buffer write timeout 1 ms, buffer size 1
Sector Start Addresses:
00000000 (RO) 00004000 (RO) 00006000 (RO) 00008000 (RO) 00010000 (RO)
00020000 00030000 00040000 00050000 00060000
00070000 00080000 00090000 000A0000 000B0000
000C0000 000D0000 000E0000 000F0000 00100000
00110000 00120000 00130000 00140000 00150000
00160000 00170000 00180000 00190000 001A0000
001B0000 001C0000 001D0000 001E0000 001F0000 (RO)
SMDK2410 #
至此nor flash支持移植成功。
6.支持DM9000网卡
smdk2410支持cs8900网卡,本开发板使用DM9000网卡,/drivers/dm9000x.c 是对应的网卡驱动。
1) 在mini2440.h中,将以下关于cs8900的宏注释掉,并添加DM9000宏定义:
/*
* 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
编译,出现错误提示:
dm9000x.c:374: error: `DM9000_IO' undeclared (first use in this function)
dm9000x.c:445: error: `DM9000_DATA' undeclared (first use in this function)
dm9000x.c:144: error: `CONFIG_DM9000_BASE' undeclared
以此继续增加宏定义:
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO 0x20000000
#define DM9000_DATA (DM9000_IO + 0x4)
#define CONFIG_DM9000_USE_16BIT 1
查看原理图可得本开发板网卡片选线接在BANK4,故基地址为0x20000000,IO为基地址,DATA与基地址偏移0x04,此外定义16BIT表示网卡使用16BIT模式。
2) 修改默认网络参数,mini2440.h 中修改代码:
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.31.111
#define CONFIG_SERVERIP 192.168.31.245
还有取消屏蔽:
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
再次编译,通过!下载至开发板,运行测试ping和tftp命令:发现ping无效,tftp可用。原因是未添加PING命令宏定义,故在mini2440.h中添加相关宏:
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
/*CFG_CMD_NAND |*/ \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I2C |*/ \
/*CFG_CMD_USB |*/ \
CFG_CMD_REGINFO | \
CFG_CMD_DATE | \
CFG_CMD_PING | \
再次测试,得到打印结果:
SMDK2410 # ping 192.168.31.245
dm9000 。。。。。
host 192.168.31.245 is alive
至此,dm9000支持移植成功。
7.支持NAND FLASH
nand的驱动代码在 /drivers/nand 目录下面,打开此目录下的nand.c文件,看到如下代码
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <nand.h>
所以判断使用nand驱动的宏开关为CFG_CMD_NAND。
1) 在mini2440.h中的CONFIG_COMMANDS中加入宏定义 CFG_CMD_NAND
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
CFG_CMD_NAND | \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I2C |*/ \
然后启动编译,错误如下:
nand.c:35: error: `CFG_MAX_NAND_DEVICE' undeclared here (not in a function)
nand.c:38: error: `CFG_NAND_BASE' undeclared here (not in a function)
home/book/Desktop/u-boot-1.1.6/include/linux/mtd/nand.h:412: error: `NAND_MAX_CHIPS' undeclared here (not in a function)
在mini2440.h中添加以上宏定义:
/*NAND FLASH*/
#define CFG_MAX_NAND_DEVICE 1
#define CFG_NAND_BASE 0x0
#define NAND_MAX_CHIPS 1
三者分别表示:
nand设备数量;
nand基地址,无实际意义,在board_nand_init函数中会被重新指定;
每个nand设备有1个nand芯片;
再次编译,出现错误为:
drivers/nand/libnand.a(nand.o)(.text+0x24): In function `nand_init':
/home/book/Desktop/u-boot-1.1.6/drivers/nand/nand.c:50: undefined reference to `board_nand_init'
意思是board_nand_init函数未定义。上电后nand的初始化过程为:start_armboot函数调用nand_init,nand_init函数在 /drivers/nand/nand.c中实现,nand_init函数调用同文件中nand_init_chip函数,nand_init_chip函数会首先调用board_nand_init函数来初始化nand设备。此函数是硬件相关,需要自己写。下一步实现此函数。
2) 实现board_nand_init函数。
在 /cpu/arm920t/s3c24x0/ 目录下建立文件nand_flash.c,文件内容为:
/*
* Nand flash interface of s3c2410/s3c2440
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <s3c2410.h>
#include <nand.h>
DECLARE_GLOBAL_DATA_PTR;
#define S3C2410_NFSTAT_READY (1<<0)
#define S3C2410_NFCONF_nFCE (1<<11)
#define S3C2440_NFSTAT_READY (1<<0)
#define S3C2440_NFCONT_nFCE (1<<1)
/* select chip, for s3c2410 */
static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
if (chip == -1) {
s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
} else {
s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
}
}
/* command and control functions, for s3c2410
*
* Note, these all use tglx's method of changing the IO_ADDR_W field
* to make the code simpler, and use the nand layer's code to issue the
* command and address sequences via the proper IO ports.
*
*/
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
struct nand_chip *chip = mtd->priv;
switch (cmd) {
case NAND_CTL_SETNCE:
case NAND_CTL_CLRNCE:
printf("%s: called for NCE\n", __FUNCTION__);
break;
case NAND_CTL_SETCLE:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
break;
case NAND_CTL_SETALE:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
break;
/* NAND_CTL_CLRCLE: */
/* NAND_CTL_CLRALE: */
default:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
break;
}
}
/* s3c2410_nand_devready()
*
* returns 0 if the nand is busy, 1 if it is ready
*/
static int s3c2410_nand_devready(struct mtd_info *mtd)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
}
/* select chip, for s3c2440 */
static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
if (chip == -1) {
s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
} else {
s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
}
}
/* command and control functions */
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
struct nand_chip *chip = mtd->priv;
switch (cmd) {
case NAND_CTL_SETNCE:
case NAND_CTL_CLRNCE:
printf("%s: called for NCE\n", __FUNCTION__);
break;
case NAND_CTL_SETCLE:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
break;
case NAND_CTL_SETALE:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
break;
/* NAND_CTL_CLRCLE: */
/* NAND_CTL_CLRALE: */
default:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
break;
}
}
/* s3c2440_nand_devready()
*
* returns 0 if the nand is busy, 1 if it is ready
*/
static int s3c2440_nand_devready(struct mtd_info *mtd)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
}
/*
* Nand flash hardware initialization:
* Set the timing, enable NAND flash controller
*/
static void s3c24x0_nand_inithw(void)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
if (0)
{
/* Enable NAND flash controller, Initialize ECC, enable chip select, Set flash memory timing */
s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
}
else
{
/* Set flash memory timing */
s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* Initialize ECC, enable chip select, NAND flash controller enable */
s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
}
}
/*
* Called by drivers/nand/nand.c, initialize the interface of nand flash
*/
void board_nand_init(struct nand_chip *chip)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
s3c24x0_nand_inithw();
if (0) {
chip->IO_ADDR_R = (void *)&s3c2410nand->NFDATA;
chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
chip->hwcontrol = s3c2410_nand_hwcontrol;
chip->dev_ready = s3c2410_nand_devready;
chip->select_chip = s3c2410_nand_select_chip;
chip->options = 0;
} else {
chip->IO_ADDR_R = (void *)&s3c2440nand->NFDATA;
chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
chip->hwcontrol = s3c2440_nand_hwcontrol;
chip->dev_ready = s3c2440_nand_devready;
chip->select_chip = s3c2440_nand_select_chip;
chip->options = 0;
}
chip->eccmode = NAND_ECC_SOFT;
}
#endif
还要在 /include/s3c24x0.h文件中增加本文件中使用到的S3C2440_NAND数据结构,在s3c2410_nand的下面,
/* NAND FLASH (see S3C2410 manual chapter 6) */
typedef struct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFECC;
} /*__attribute__((__packed__))*/ S3C2410_NAND;
增添2440nand的结构体:
typedef struct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCONT;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFMECCD0;
S3C24X0_REG32 NFMECCD1;
S3C24X0_REG32 NFSECCD;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFESTAT0;
S3C24X0_REG32 NFESTAT1;
S3C24X0_REG32 NFMECC0;
S3C24X0_REG32 NFMECC1;
S3C24X0_REG32 NFSECC;
S3C24X0_REG32 NFSBLK;
S3C24X0_REG32 NFEBLK;
} /*__attribute__((__packed__))*/ S3C2440_NAND;
然后打开同目录下的s3c2410.h,找到
static inline S3C2410_NAND * const S3C2410_GetBase_NAND(void)
{
return (S3C2410_NAND * const)S3C2410_NAND_BASE;
}
在其下面添加
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
{
return (S3C2440_NAND * const)S3C2410_NAND_BASE;
}
最后将新建的nand_flash.c文件编入u-boot之中。打开 /cpu/arm920t/s3c24x0/Makefile ,在COBJS中增加nand_flash.o:
COBJS = i2c.o interrupts.o serial.o speed.o \
usb_ohci.o nand_flash.o
编译,通过!下载至开发板运行,控制台打印出:NAND : 256MiB,输入命令nand info,打印信息:
NAND 256MiB 3.3V 8-bit, sector size 128 KiB
至此,NAND flash支持移植成功!