加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

关于杨创YC2440uboot移植

发布时间:2020-12-15 06:20:16 所属栏目:百科 来源:网络整理
导读:? 欢迎大家有空可以看下我的http://ltdzhuwai.taobao.com ? U-Boot1.2.0移植YC2440 分类: U-BOOT 2010-12-22 19:48 185人阅读 评论(2) 收藏 举报 移植U-Boot-1.2.0到YC2440 首先,U-Boot-1.2.0还没有支持s3c2440,这次移植是用s3c2410的文件修改而成。本移
?

欢迎大家有空可以看下我的http://ltdzhuwai.taobao.com

?

U-Boot1.2.0移植YC2440

分类: U-BOOT 2010-12-22 19:48 185人阅读 评论(2) 收藏 举报

移植U-Boot-1.2.0到YC2440

首先,U-Boot-1.2.0还没有支持s3c2440,这次移植是用s3c2410的文件修改而成。本移植参考网上一位叫tekkaman网友完成。感谢他们无私奉献、共享。

链接:http://blog.chinaunix.net/u1/34474/showart_410294.html

U-Boot源码:ftp://ftp.denx.de/pub/u-boot/

红色为修改的地方,蓝色为运行指令、注释地方

?

一、在U-Boot中建立自己开发板类型,测试编译

1 进入U-Boot目录,修改Makefile

# tar –jxvf? u-boot-1.2.0.tar.bz2

# cd u-boot-1.2.0

# gedit Makefile

//为liao2440建立编译项

sbc2410x_config: unconfig

??? @$(MKCONFIG) $(@:_config=) arm arm920t sbc2410x NULL s3c24x0

liao2440_config : unconfig

??????? @$(MKCONFIG) $(@:_config=) arm arm920t liao2440 liao s3c24x0

说明:

arm: CPU的架构(ARCH)

arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。

liao2440: 开发板的型号(BOARD),对应于board/liao/liao2440目录。

liao: 开发者/或经销商(vender)。

s3c24x0: 片上系统(SOC)。

?

同时在“ifndef CROSS_COMPILE”之前? 加上自己交叉编译器的路径,比如我使用crosstool-0.43制作的基于2.6.24内核和gcc-4.1.1-glibc-2.3.2的ARM9TDMI交叉编译器,则:

?

CROSS_COMPILE=CROSS_COMPILE=/home/liao/crosstool/gcc-4.1.1-glibc-2.3.2/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-

?

2 /board子目录中建立自己开发板liao2440目录

?

由于上一步板子的开发者/或经销商(vender)中填了liao,所以开发板liao2440目录一定要建在/board子目录liao目录下 ,否则编译会出错。

?

# cd board

# mkdir liao liao/liao2440

# cp -arf sbc2410x/*?? liao/liao2440/

# cd liao/liao2440

# mv sbc2410x.c liao2440.c

?

修改自己开发板liao2440目录下Makefile文件

# gedit Makefile

COBJS := sbc2410x.o flash.o

?

COBJS := liao2440.o flash.o

?

3 建立配置头文件在include/configs/

# cd …/u-boot-1.2.0/include/configs

# cp include/configs/sbc2410x.h ?include/configs/liao2440.h

?

4 测试编译是否成功

# make liao2440_config

Configuring for liao2440 board…

(如果出现:

Makefile:1927: *** 遗漏分隔符 。 停止。

请在U-boot的根目录下的Makefile的

??????? @$(MKCONFIG) $(@:_config=) arm arm920t liao2440 liao)

前加上“Tab”键)

# make

?

??? Ok,到这里前期准备工作完成!!!!!!!

?

二、修改U-Boot中文件,根据开发板YC2440配置

1 修改/cpu/arm920t/start.S

1.1修改寄存器定义

/* turn off the watchdog */

# if defined(CONFIG_S3C2400)

# define pWTCON??????? 0x15300000

# define INTMSK??????? 0x14400008??? /* Interupt-Controller base addresses */

# define CLKDIVN??? 0x14800014??? /* clock divisor register */

# elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

# define pWTCON??????? 0x53000000

# define INTMSK??????? 0x4A000008??? /* Interupt-Controller base addresses */

# define INTSUBMSK??? 0x4A00001C

# define CLKDIVN??? 0x4C000014??? /* clock divisor register */

# define CLK_CTL_BASE??????? 0x4C000000

# if defined(CONFIG_S3C2440)

# define MDIV_405?????? 0x7f << 12

# define PSDIV_405?????? 0x21

# endif

# if defined(CONFIG_S3C2410)

# define MDIV_200??????? 0xa1 << 12

# define PSDIV_200??????? 0x31

# endif

/*这一段为后面修改时钟定义的一些参数*/

# endif

?

1.2修改中断禁止部分

# if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

??? ldr???? ?r0,=pWTCON

??? mov?? ?r1,#0x0

??? str???? ?r1,[r0]

?

???? /*

???? * mask all IRQs by setting all bits in the INTMR - default

???? */

??? mov??? r1,#0xffffffff

??? ldr?? ??r0,=INTMSK

??? str?? ??r1,[r0]

# if defined(CONFIG_S3C2410)

??? ldr??? r1,=0x7ff? ???//根据2410芯片手册,INTSUBMSK有11位可用,

?????????????????????? //vivi也是0x7ff,不知为什么U-Boot一直没改过来。

??? ldr??? r0,=INTSUBMSK

??? str??? r1,[r0]

# endif

# if? defined(CONFIG_S3C2440)

??? ldr??? r1,=0x7fff?? //根据2440芯片手册,INTSUBMSK有15位可用

??? ldr??? r0,[r0]

# endif

?

1.3 修改时钟设置

/*时钟控制逻辑单元能够产生s3c2440需要的时钟信号,包括CPU使用的主频FCLK,AHB总线使用的HCLK,APB总线设备使用的PCLK,2440里面的两个锁相环(PLL),其中一个对应FCLK、HCLK、PCLK,另外一个对应UCLK(48MHz)*/

/* FCLK:HCLK:PCLK = 1:4:8 */

??? ldr??? r0,=CLKDIVN

? ??mov??? r1,#5

??? str??? r1,[r0]

/*

下面协处理器指令是用来把CPU的模式设置成Asynchronous 模式,为什么要这样做?s3c2440的datasheet说得很清楚,具体可在datasheet中搜索R1_nF或R1_iA内容。至于R1_nF和R1_iA的值可以在vivi源码的s3c2440.h中得到。

单从指令上看,下面指令的作用把协处理器p15的寄存器c1的最高两位置1,仔细看过《arm 体系结构与编程》的朋友可能会发现个问题:《arm 体系结构与编程》里面说 p15 的bit30和bit31是保留的,那么下面的指令又怎么会有意义呢?其实《arm 体系结构与编程》里面说这两个bit是保留的是针对arm7的,对arm9的s3c2440并不适用。

*/

??? mrc??? p15,r1,c1,c0,0??????? /*read ctrl register?? liao*/

??? orr??? r1,#0xc0000000???????? /*Asynchronous? liao*/

??? mcr??? p15,0????? /*write ctrl register liao*/

?

# if defined(CONFIG_S3C2440)

??? /*now,CPU clock is 405.00 Mhz? */

??? mov??? r1,#CLK_CTL_BASE

??? mov??? r2,#MDIV_405?????????????????? /* mpll_405mhz??? liao*/

??? add??? r2,r2,#PSDIV_405???????????? /* mpll_405mhz??? liao*/

??? str??? r2,[r1,#0x04]?????????????? /* MPLLCON liao */

# endif

# if defined(CONFIG_S3C2410)

??? /*now,CPU clock is 202.8 Mhz?? liao*/

??? mov??? r1,#CLK_CTL_BASE??? /* liao*/

??? mov??? r2,#MDIV_200?????????????????? /* mpll_200mhz??? liao*/

??? add??? r2,#PSDIV_200???????????? /* mpll_200mhz??? liao*/

??? str??? r2,#0x04]?????????????? /* MPLLCON liao */

# endif

# endif??? /* CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 */

/*时钟设置参照vivi代码,主频405MHZ*/

?

1.4 将Flash启动改为从NAND Flash启动(2410与2440不同,参照vivi)

# if 0

# ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate:??????????????? ???/* relocate U-Boot to RAM???? ??*/

??? adr??? r0,_start??????? /* r0 <- current position of code?? */

??? ldr??? r1,_TEXT_BASE??????? /* test if we run from flash or RAM */

??? cmp???? r0,r1??????????????? /* don't reloc during debug???????? */

??? beq???? stack_setup

?

??? ldr??? r2,_armboot_start

??? ldr??? r3,_bss_start

??? sub??? r2,r3,r2??????? /* r2 <- size of armboot??????????? */

??? add??? r2,r0,r2??????? /* r2 <- source end address???????? */

?

copy_loop:

??? ldmia??? r0!,{r3-r10}??????? /* copy from source address [r0]??? */

??? stmia??? r1!,{r3-r10}??????? /* copy to?? target address [r1]??? */

??? cmp??? r0,r2??????????? /* until source end addreee [r2]??? */

??? ble? ??copy_loop

# endif??? /* CONFIG_SKIP_RELOCATE_UBOOT */

# endif

/*参照vivi代码,nandflash拷贝*/

# ifdef CONFIG_S3C2440_NAND_BOOT??

??? @ reset NAND

??? mov??? r1,#NAND_CTL_BASE

??? ldr??? r2,=( (7<<12)|(7<<8)|(7<<4)|(0<<0) )

??? str??? r2,#oNFCONF]??? ?/*这些宏在includes/configs/liao2440.h中定义*/

??? ldr??? r2,#oNFCONF]

?

??? ldr??? r2,=( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control

??? str??? r2,#oNFCONT]

??? ldr??? r2,#oNFCONT]

?

??? ldr??? r2,=(0x6)??????? @ RnB Clear

??? str??? r2,#oNFSTAT]

??? ldr??? r2,#oNFSTAT]

???

??? mov??? r2,#0xff??????? @ RESET command

??? strb??? r2,#oNFCMD]

?

? ??mov r3,#0?????????????????? @ wait

nand1:

? ??add? r3,#0x1

? ??cmp r3,#0xa

? ??blt?? nand1

?

nand2:

?? ?ldr?? r2,#oNFSTAT]????? @ wait ready

? ??tst??? r2,#0x4

? ??beq? nand2

?

?

??? ldr??? r2,#oNFCONT]

??? orr??? r2,#0x2??????? @ Flash Memory Chip Disable

??? str??? r2,#oNFCONT]

/*汇编调用C函数,初始化栈*/

@ 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

?? ?mov???? r1,#0x0

? mov ?r2,#0x20000

? ??bl??? nand_read_ll

/*nand_read_ll为uboot拷贝代码入口函数,r0,r1,r2为入口参数

tst? r0,#0x0中r0为函数返回值*/

?? ?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,#4

?? ?beq? stack_setup

?? ?bne? go_next

?

notmatch:

loop3:???? b???? loop3???????? @ infinite loop

?

#endif @ CONFIG_S3C2440_NAND_BOOT

?

1.5 调出start.S前,利用点灯大法查看程序运行位置

在 ldr? pc,_start_armboot 之前加入LED

mov??? r1,#GPIO_CTL_BASE

add??? r1,#oGPIO_F

ldr??? r2,=0x55aa

str??? r2,#oGPIO_CON]

mov??? r2,#0xff

str??? r2,#oGPIO_UP]

mov??? r2,#0xe0

str??? r2,#oGPIO_DAT]

/*YC2440开发板有4个LED,GPIO_F[4:7],点亮一个LED,下面函数进入第二阶段*/

ldr? pc,_start_armboot

_start_armboot:????? .word start_armboot

.align???? 2?????????????????

DW_STACK_START:? .word? STACK_BASE+STACK_SIZE-4

/*栈空间是从高地址向低地址增长,用于调用nand_read_ll函数时设置占空间,STACK_BASE STACK_SIZE定义在后面/include/configs/liao2440.h */

?

2 在board/liao/liao2440加入NAND Flash读函数文件,复制vivi中nand_read.c文件

#include <config.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 NFSTAT??????? __REGb(NF_BASE + 0x20)

?

//#define GPDAT??????? __REGi(GPIO_CTL_BASE+oGPIO_F+oGPIO_DAT)

?

#define NAND_CHIP_ENABLE? (NFCONT &= ~(1<<1))

#define NAND_CHIP_DISABLE (NFCONT |=? (1<<1))

#define NAND_CLEAR_RB????? (NFSTAT |=? (1<<2))

#define NAND_DETECT_RB????? { while(! (NFSTAT&(1<<2)) );}

?

#define BUSY 4

inline void wait_idle(void) {

??? while(!(NFSTAT & BUSY));

??? NFSTAT |= BUSY;

}

?

#define NAND_SECTOR_SIZE??? 512

#define NAND_BLOCK_MASK??????? (NAND_SECTOR_SIZE - 1)

?

/* low level nand read function */

int

nand_read_ll(unsigned char *buf,unsigned long start_addr,int size)

{

??? int i,j;

/*

下面if保证对flash的读操作是从某一页的页头开始的,也就是保证start_addr[0:8]位都为0,

本次flash的一页的大小位512-bytes,也就是从0x0到0x1ff */

??? if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {

??????? return -1;??? /* invalid alignment */

??? }

?

??? NAND_CHIP_ENABLE;

?

??? for(i=start_addr; i < (start_addr + size);) {

??????? /* READ0 */

??????? NAND_CLEAR_RB;???????

??????? NFCMD = 0;

?

??????? /* Write Address */

/*下面这个送地址的过程最难懂的一部分,为什么送进nand flash的地址忽略了bit8,纵观整个for(i) 循环,i并不是一个随机的地址,而应该是每一页的首地址。其实nand flash并不是忽略了bit8这个地址,而是bit8早就被定下来了,就是上面的NFCMD = 0;语句,(K9F1208U0B)支持从半页开始读取,从而它有两个读的命令,分别是0x00(从一页的上半页开始读) 和 0x01(从一页的下半页开始读),当取0x00时,bit8=0,当取0x01时 bit8=1*/

??????? NFADDR = i & 0xff;

??????? NFADDR = (i >> 9) & 0xff;

??????? NFADDR = (i >> 17) & 0xff;

??????? NFADDR = (i >> 25) & 0xff;

?

??????? NAND_DETECT_RB;

?

??????? for(j=0; j < NAND_SECTOR_SIZE; j++,i++) {

??????????? *buf = (NFDATA & 0xff);

??????????? buf++;

??????? }

??? }

??? NAND_CHIP_DISABLE;

??? return 0;

}

?

3.修改board/liao/liao2440/Makefile文件

......

OBJS := liao2440.o nand_read.o flash.o

......

?

4.修改include/configs/liao2440.h文件

在文件末尾添加定义

/*2410 2440 nand flash控制寄存器不同,不能混用*/

/*

?* Nandflash Boot

?*/

#define CONFIG_S3C2440_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 oNFCONT??????????? 0x04

#define oNFCMD??????????? 0x08

#define oNFADDR??? ????????0x0c

#define oNFDATA??????????? 0x10

#define oNFSTAT??????????? 0x20

#define oNFECC??????????? 0x2c

?

/* GPIO */

#define GPIO_CTL_BASE??????? 0x56000000

#define oGPIO_F??????????? 0x50

#define oGPIO_CON?????? 0x0?? /* R/W,Configures the pins of the port */

#define oGPIO_DAT??????? 0x4??? /* R/W,??? Data register for port */

#define oGPIO_UP??????? 0x8??? /* R/W,Pull-up disable register */

# endif??? /* __CONFIG_H */

?

5.修改board/liao/liao2440/lowlevel_init.S文件

依照开发板的内存区的配置情况,修改board/liao/liao2440/lowlevel_init.S文件

......

/* REFRESH parameter */

#define REFEN???????????? 0x1??? /* Refresh enable */

#define TREFMD???????????? 0x0??? /* CBR(CAS before RAS)/Auto refresh */

#define Trp???????????? 0x2??? /* 4clk */

#define Trc???????????? 0x3??? /* 7clk */

#define Tchr???????????? 0x2??? /* 3clk */

#define REFCNT???????????? 1012???

......

/*到这里第一阶段配置全部完成,下面就是C函数初始化配置*/

?

6 修改board/liao/liao2440/liao2440.c

修改其对GPIO和PLL的配置,参阅开发板硬件说明和2440芯片手册

......

#elif FCLK_SPEED==1??????? /* Fout = 405MHz */

//#define M_MDIV??? 0x5c

//#define M_PDIV??? 0x4

//#define M_SDIV??? 0x0

#define M_MDIV??? 0x7f

#define M_PDIV??? 0x2

#define M_SDIV??? 0x1

......

#elif USB_CLOCK==1

//#define U_M_MDIV??? 0x48

//#define U_M_PDIV??? 0x3

#define U_M_MDIV??? 0x38

#define U_M_PDIV??? 0x2

#define U_M_SDIV??? 0x2

......

?

/* set up the I/O ports */

gpio->GPACON = 0x007FFFFF;

……

// gpio->GPFCON = 0x000055AA;

gpio->GPFCON = 0x5500; /*for LED*/

......

/* arch number of S3C2440 -Board */

gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ;

/* adress of boot parameters */

gd->bd->bi_boot_params = 0x30000100;

icache_enable();

dcache_enable();

gpio->GPFDAT = 0xc0; /*for LED*/

?

return 0;

?

7. 实现NAND Flash的读写,再次修改/include/configs/liao2440.h

......

/*

?* High Level Configuration Options

?* (easy to change)

?*/

#define CONFIG_ARM920T??????? 1??? /* This is an ARM920T Core??? */

//#define CONFIG_S3C2410????? ??1??? /* in a SAMSUNG S3C2410 SoC???? */

//#define CONFIG_SBC2410X????? 1??? /* on a friendly-arm SBC-2410X Board? */

#define??? CONFIG_S3C2440????? 1??? /* in a SAMSUNG S3C2440 SoC???? */

#define CONFIG_liao2440??? ?1? ??/* on a SAMSUNG liao2440 Board? */

/*很多地方调用CONFIG_S3C2440,在这里定义

CONFIG_liao2440是针对本开发板配置的宏控制*/

......

/***********************************************************

?* Command definition

?***********************************************************/

#define CONFIG_COMMANDS /

??????????? (CONFIG_CMD_DFL???? | /

??????????? CFG_CMD_CACHE???? | /

??????????? CFG_CMD_NAND???? | /

??????????? CFG_CMD_NET???? | /

??????????? /*CFG_CMD_EEPROM |*/ /

??????????? /*CFG_CMD_I2C???? |*/ /

??????????? /*CFG_CMD_USB???? |*/ /

??????????? CFG_CMD_PING | /

???? ???????CFG_CMD_ENV | /

??????????? CFG_CMD_REGINFO? | /

??????????? CFG_CMD_DATE???? | /

??????????? CFG_CMD_DHCP???? | /

??????????? CFG_CMD_ELF)

?

/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */

#include <cmd_confdefs.h>

……

#define??? CFG_LONGHELP??????????????? /* undef to save memory??????? */

#define??? CFG_PROMPT?? "[liao2440]#"??????? /*Monitor Command Prompt? */

#define??? CFG_CBSIZE??????? 256???????????????? /* Console I/O Buffer Size??? */

……

#undef? CFG_CLKS_IN_HZ????????????? /* everything,incl board info,in Hz */

#define??? CFG_LOAD_ADDR???????????? 0x30008000??? /* default load address?? */

/*linux kernel放在这里执行*/

/* the PWM TImer 4 uses a counter of 15625 for 10 ms,so we need */

……

/* 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_FLASH??? 1

#define??? CFG_ENV_IS_IN_NAND??? 1

#define CFG_ENV_OFFSET? 0X20000

#define CFG_NAND_LEGACY

/*注意:网上很多地方都有关于CONFIG_CMD_NAND 、CFG_NAND_LEGACY、drivers/mtd/nand/nand.c中的nand_init()函数以及board/qljt/qljt2440/qljt2440.c中的nand_init()函数这四个东西的关系,请参考附录。*/

#define CFG_ENV_SIZE??? 0x10000?? /* Total Size of Environment Sector */

/*----------------------------------------------------------------------

?* NAND flash settings

?*/

#if (CONFIG_COMMANDS & CFG_CMD_NAND)

#define CFG_NAND_BASE 0x4E000000?? /* NandFlash控制器在SFR区起始寄存器地址 */

#define CFG_MAX_NAND_DEVICE 1

#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 NAND_WAIT_READY(nand) NF_WaitRB()

//#define NAND_DISABLE_CE(nand)? NF_SetCE(NFCE_HIGH)

//#define NAND_ENABLE_CE(nand)?? NF_SetCE(NFCE_LOW)

//#define WRITE_NAND_COMMAND(d,adr)??? NF_Cmd(d)

//#define WRITE_NAND_COMMANDW(d,adr) NF_CmdW(d)

//#define WRITE_NAND_ADDRESS(d,adr)????? NF_Addr(d)

//#define WRITE_NAND(d,adr)????????? NF_Write(d)

//#define READ_NAND(adr)?????????????? NF_Read()

?

#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) {rNFCONT |= (1<<1);}

#define NAND_ENABLE_CE(nand) {rNFCONT &= ~(1<<1);}

#define WRITE_NAND_COMMANDW(d,adr) NF_CmdW(d)

/* 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)

#define CONFIG_MTD_NAND_VERIFY_WRITE 1

……

#define rNFCONF (*(volatile unsigned int *)0x4e000000)

#define rNFCONT (*(volatile unsigned int *)0x4e000004)

#define rNFCMD (*(volatile unsigned char *)0x4e000008)

#define rNFADDR (*(volatile unsigned char *)0x4e00000c)

#define rNFDATA (*(volatile unsigned char *)0x4e000010)

#define rNFSTAT (*(volatile unsigned int *)0x4e000020)

#define rNFECC (*(volatile unsigned int *)0x4e00002c)

?

#endif???? /* __CONFIG_H */

?

8.在一些文件中添加CONFIG_S3C2440,使得原来s3c2410代码可以编译进来

8.1 /include/common.h文件的第454行:

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440)

?

8.2 /include/s3c24x0.h文件的第85、95、99、110、148、404行:

#if defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

?

8.3 /cpu/arm920t/s3c24x0/interrupts.c文件的第33、38行:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)

?

#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

?

8.4 /cpu/arm920t/s3c24x0/serial.c文件的第22、26行:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)

#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

void serial_setbrg (void)

{

???????? S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);

???????? int i;

???????? unsigned int reg = 0;

?

???????? /* value is calculated so : (int)(PCLK/16./baudrate) -1 */

???????? reg = get_PCLK() / (16 * gd->baudrate) - 1;

???????? /* FIFO enable,Tx/Rx FIFO clear */

???????? uart->UFCON = 0x00;

???????? uart->UMCON = 0x0;

???????? /* Normal,No parity,1 stop,8 bit */

???????? uart->ULCON = 0x3;

......

}

?

8.5 /cpu/arm920t/s3c24x0/speed.c文件的第33、37行:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)

#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

?

static ulong get_PLLCLK(int pllreg)

{

??? ......

?

??? m = ((r & 0xFF000) >> 12) + 8;

??? p = ((r & 0x003F0) >> 4) + 2;

??? s = r & 0x3;

#if defined(CONFIG_S3C2440)

?? ?if (pllreg == MPLL)

??? return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));

? ??else if (pllreg == UPLL)

#endif

??? return((CONFIG_SYS_CLK_FREQ * m) / (p << s));

}

?

/* return FCLK frequency */

ulong get_FCLK(void)

{

??? return(get_PLLCLK(MPLL));

}

?

/* return HCLK frequency */

ulong get_HCLK(void)

{

??? S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

?? ?if (clk_power->CLKDIVN & 0x6)???

??? {

?????? ?/*CAMDIVN 在12中定义*/

?? ? ?if ((clk_power->CLKDIVN & 0x6)==2)?????

????????????? return(get_FCLK()/2);

???? if ((clk_power->CLKDIVN & 0x6)==6)??????

????????????? return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 : get_FCLK()/3);????????

?????? ?if ((clk_power->CLKDIVN & 0x6)==4)???????

????????????? return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 : get_FCLK()/4);????????

?????? ?return(get_FCLK());

??? }

??? else??????

??? {

?????? ?????? return(get_FCLK());

??? }

??? //return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());

}

?

8.6 /cpu/arm920t/s3c24x0/usb_ohci.c文件的第45行:

#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

/*i2c没用到,文件还没修改*/

?

8.7 /rtc/s3c24x0_rtc.c文件的第35行:

#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

?

8.8 /cpu/arm920t/s3c24x0/interrupts.c文件的第181行:?

defined(CONFIG_VCMA9) || defined(CONFIG_liao2440)

/*添加defined(CONFIG_liao2440),使得原来sbc2410X的代码可以编译进来*/

?

9.在include/linux/mtd/nand_ids.h的结构体nand_flash_ids加入

static struct nand_flash_dev nand_flash_ids[] = {

......

??? {"Samsung KM29N16000",NAND_MFR_SAMSUNG,0x64,21,1,2,0x1000,0},

??? {"Samsung K9F1208U0B",? NAND_MFR_SAMSUNG,0x76,26,3,0x4000,

??? {"Samsung unknown 4Mb",0x6b,22,0x2000,

......

};

/*下面说说上面结构体的8个参数是怎么得出来的,以便日后再次移植的时候会更换nand flash*/

?

/*

1.“厂家 型号”:这个从nand flash的datasheet就可以直接找到了吧。

2. 生产商的编号:也就是datasheet里面的Maker code,它也同时被存放在nand flash里面的ID(nand flash应该有一个读ID命令的)信息里面)。

3. 本模块的编号:也就是datasheet里面的device code,跟Maker code一样它也被放到ID信息里面。

4. 总共容纳的地址位数:也就是有效的地址位数。针对于本flash(K9F1208U0M)可以参考它的datasheet第7页。

5. 一页所存储的字节数是否为256个:针对于本flash(K9F1208U0M)可以参考它的datasheet第7页。

6. 地址需要多少字节数减一(行列地址总共):举个例子可能更容易明白,第4点中可以知道本flash(K9F1208U0M)有26位,而对本flash地址的写入每次只能写8位,所以至少要写4次才能把26位地址写入本flash,4次的写入针对于编程来说就是[0:3],所以本falsh相对于该结构体的该变量的值是3.

7. 擦除1个block的大小:简单来说就是1个block的大小,本flash 1block=32 pages,1 page=512 bytes,所以 1 block=512x32=16 k-bytes,也就是0x4000。

8. 是否为16位总线:本flash地址和数据总线共用,都是8位的,所以上面值为0

*/

?

10.修改lib_arm/board.c

......

#include <common.h>

#include <command.h>

#include <malloc.h>

#include <devices.h>

#include <version.h>

#include <net.h>

#include <s3c2410.h>

......

static int display_banner (void)

{

?????? S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

??????? gpio->GPFDAT = 0x80;

/*在串口初始化和console初始化完成,串口输出信息之前,LED1、LED2、LED3会亮起*/

?????? 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",_bss_end);

#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);

}

……

void start_armboot (void)

{

???????? init_fnc_t **init_fnc_ptr;

???????? char *s;

#ifndef CFG_NO_FLASH

???????? ulong size;

#endif

?

#if defined(CONFIG_VFD) || defined(CONFIG_LCD)

???????? unsigned long addr;

#endif

?

???????? S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

......

?

?????? ??gpio->GPBDAT = 0x00;

/*在进入命令提示符之前,四个LED会同时亮起*/

???????? /* main_loop() can return to retry autoboot,if so just run it again. */

???????? for (;;) {

?????????????????? main_loop ();

???????? }

???????? /* NOTREACHED - no way out of command loop except booting */

}

?

11.修改common/env_nand.c

#ifdef CONFIG_INFERNO

#error CONFIG_INFERNO not supported yet

#endif

?

int nand_legacy_rw (struct nand_chip* nand,int cmd,

?????? ??? size_t start,size_t len,

?????? ??? size_t * retlen,u_char * buf);

extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];

extern int nand_legacy_erase(struct nand_chip *nand,size_t ofs,int clean);

?

/* info for NAND chips,defined in drivers/nand/nand.c */

extern nand_info_t nand_info[CFG_MAX_NAND_DEVICE];

……

#else /* ! CFG_ENV_OFFSET_REDUND */

int saveenv(void)

{

?????? ulong total;

?????? int ret = 0;

?

?????? puts ("Erasing Nand...");

?????? //if (nand_erase(&nand_info[0],CFG_ENV_OFFSET,CFG_ENV_SIZE))

?????? if (nand_legacy_erase(nand_dev_desc + 0,CFG_ENV_SIZE,0))??

????????????? return 1;

?

?????? puts ("Writing to Nand... ");

?????? total = CFG_ENV_SIZE;

?????? //ret = nand_write(&nand_info[0],&total,(u_char*)env_ptr);

?????? ret = nand_legacy_rw(nand_dev_desc + 0,

????????????? 0x00 | 0x02,

????????????? &total,(u_char*)env_ptr);

?

?????? if (ret || total != CFG_ENV_SIZE)

????????????? return 1;

?

?????? puts ("done/n");

?????? return ret;

}

……

#else /* ! CFG_ENV_OFFSET_REDUND */

/*

?* The legacy NAND code saved the environment in the first NAND device i.e.,

?* nand_dev_desc + 0. This is also the behaviour using the new NAND code.

?*/

void env_relocate_spec (void)

{

#if !defined(ENV_IS_EMBEDDED)

?????? ulong total;

?????? int ret;

?

?????? total = CFG_ENV_SIZE;

?????? //ret = nand_read(&nand_info[0],0x01 | 0x02,

????????????? CFG_ENV_SIZE,(u_char*)env_ptr);

? ??? if (ret || total != CFG_ENV_SIZE)

????????????? return use_default();

?

12. /board/liao/liao2440/liao2440.c文件末尾添加NAND Flash初始化函数

u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nand/nand.c中的nand_init();否则调用自己在board/liao/liao2440/liao2440.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_Cont(u16 cont)

{

?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

?????? nand->NFCONT = cont;

}

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->NFCONT &= ~(1<<1);

???????????????????? break;

?

????????????? case NFCE_HIGH:

???????????????????? nand->NFCONT |= (1<<1);

???????????????????? 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->NFCONT |= (1<<4);

}

static inline u32 NF_Read_ECC(void)

{

?????? S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

?????? return(nand->NFECC);

}????

#endif

?

#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((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4));

?????? NF_Cont((1<<6)|(1<<4)|(1<<1)|(1<<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

?

13. /include/s3c24x0.h加入2440 NAND Flash寄存器定义和CAMDIVN定义

......

typedef struct {

???????? S3C24X0_REG32?? LOCKTIME;

???????? S3C24X0_REG32?? MPLLCON;

???????? S3C24X0_REG32?? UPLLCON;

???????? S3C24X0_REG32?? CLKCON;

???????? S3C24X0_REG32?? CLKSLOW;

???????? S3C24X0_REG32?? CLKDIVN;

???????? S3C24X0_REG32?? CAMDIVN;

} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;

......

#if defined(CONFIG_S3C2410)

/* 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;

#endif

#if defined (CONFIG_S3C2440)

/* NAND FLASH (see S3C2440 manual chapter 6) */

typedef struct {

???????? S3C24X0_REG32?? NFCONF;

???????? S3C24X0_REG32?? NFCONT;

???????? S3C24X0_REG32?? NFCMD;

???????? S3C24X0_REG32?? NFADDR;

???????? S3C24X0_REG32?? NFDATA;

???????? S3C24X0_REG32?? NFMECC0;

???????? S3C24X0_REG32?? NFMECC1;

???????? S3C24X0_REG32?? NFSECC;

?? ??????S3C24X0_REG32?? NFSTAT;

???????? S3C24X0_REG32?? NFESTAT0;

???????? S3C24X0_REG32?? NFESTAT1;

???????? S3C24X0_REG32?? NFECC;

} /*__attribute__((__packed__))*/ S3C2410_NAND;

#endif

?

14.DM9000网卡移植

修改/include/configs/liao2440.h

/*

?* Hardware drivers

?*/

//#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 */

/* CONFIG_DM9000_BASE参数根据开发板设置*/

#define CONFIG_DRIVER_DM9000 1

#define CONFIG_DM9000_BASE 0x18000300

#define DM9000_IO CONFIG_DM9000_BASE

#define DM9000_DATA (CONFIG_DM9000_BASE+4)

#define CONFIG_DM9000_USE_16BIT

修正drivers/dm9000x.c中两个BUG

网卡MAC地址错误的解决方法

/* Initilize dm9000 board*/

int eth_init(bd_t * bd)

{

??? ......

??? /* Set Node address */

??? /* for (i = 0; i < 6; i++)

??????? ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);*/

??? char *tmp = getenv ("ethaddr");

??? char *end;

??? for (i=0; i<6; i++)

??? {

??????? bd->bi_enetaddr[i] = tmp ? simple_strtoul(tmp,&end,16) : 0;

?? ?????if (tmp)

??????????? tmp = (*end) ? end+1 : end;

??? }

/*屏蔽原有获取MAC地址的语句,替换成从U-Boot的参数区读取数据并存到bd->bi_enetaddr[i] */

??? printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x/n",bd->bi_enetaddr[0],

?????????? bd->bi_enetaddr[1],bd->bi_enetaddr[2],bd->bi_enetaddr[3],

?????????? bd->bi_enetaddr[4],bd->bi_enetaddr[5]);

......

/* Initilize dm9000 board*/

int eth_init(bd_t * bd)

{

??? ......

??? DM9000_iow(DM9000_RCR,RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);??? /* RX enable */

??? DM9000_iow(DM9000_IMR,IMR_PAR);??? /* Enable TX/RX interrupt mask */

#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;

??????? }

??????? printf(" link=%d/n",i);

??? }

?

??? /* see what we've got */

??? lnk = phy_read(17) >> 12;

??? printf("operating at ");

??? switch (lnk) {

??? case 1:

??????? printf("10M half duplex ");

??????? break;

??? case 2:

??????? printf("10M full duplex ");

??????? break;

??? case 4:

??????? printf("100M half duplex ");

??????? break;

??? case 8:

??????? printf("100M full duplex ");

??????? break;

??? default:

??????? printf("unknown: %d ",lnk);

??????? break;

??? }

??? printf("mode/n");

#endif

/*could not establish link提示和慢响应的解决方法*/

??? return 0;

}

YC2440的网卡是DM9000AEP,暂时还有点问题,后面继续研究。

?

三、交叉编译U-Boot

# cd u-boot

# make

如何利用已有U-Boot在SDRAM调试U-Boot

1 board/liao/liao2440/config.mk文件中修改TEXT_BASE=0x33000000,避免新的U-Boot与原来重复。

2 cpu/arm920t/start.S中屏蔽cpu_init_crit,此函数会将SDRAM清空一次,后果可想而知

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

@bl cpu_init_crit

#endif

3 在1.4节中加入一段代码,判断U-Boot是否在SDRAM,从而是否需要拷贝

@ 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

?

@ test uboot on sdram so decided whether need copy

? adr r0,_start

? ldr r1,_TEXT_BASE

? cmp r0,r1

? beq stack_setup

?

@ copy U-Boot to RAM

? ldr?? r0,=TEXT_BASE

? mov???? r1,#0x0

? mov r2,#0x20000

? bl??? nand_read_ll

? tst??? r0,#0x0

? beq? ok_nand_read

4 启动原来的U-Boot,调试新的

# tftp 33000000 u-boot.bin

# go 33000000

?

?

附录:

1.在u-boot-1.3.1前(不含u-boot-1.3.1)nand_init函数的调用关系,它的调用是被“CONFIG_COMMANDS&CFG_CMD_NAND”和“CFG_NAND_LEGACY”控制的,1:表示该值为真,0:表示该值为假

A :/drivers/mtd/nand/nand.c中的nand_init()函数

B :/board/liao/liao2440/liao2440.c中的nand_init()函数

CONFIG_COMMAND

&CFG_CMD_NAND

CFG_NAND_LEGACY

A

B

???????? 0

????????? 0

????? 0

?????? 0

???????? 0

????????? 1

????? 0

?????? 0

???????? 1

????????? 0

????? 1

?????? 1

???????? 1

??? ??????1

????? 0

?????? 1

2.在u-boot-1.3.1后(含u-boot-1.3.1)nand_init函数的调用关系,它的调用是被“CONFIG_CMD_NAND”和“CFG_NAND_LEGACY”控制的。

CONFIG_CMD_NAND

CFG_NAND_LEGACY

A

B

???????? 0

????????? 0

????? 0

?????? 0

???????? 0

????????? 1

????? 0

?????? 0

???????? 1

????? ????0

????? 1

?????? 1

???????? 1

????????? 1

????? 0

?????? 1

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读