好文档 - 专业文书写作范文服务资料分享网站

我的arm - linux移植笔记

天下 分享 时间: 加入收藏 我要投稿 点赞

strb r2, [r1, #oNFCMD]

mov r3, #0 @ wait 就是一下段延时 nand1:

add r3, r3, #0x1 cmp r3, #0xa blt nand1 nand2:

ldr r2, [r1, #oNFSTAT] @ wait ready tst r2, #0x4 beq nand2

ldr r2, [r1, #oNFCONT]

orr r2, r2, #0x2 @ Flash Memory Chip Disable str r2, [r1, #oNFCONT]

@ 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初始化frame的起始位置

@ copy U-Boot to RAM

ldr r0, =TEXT_BASE 设置第1个参数: UBOOT在RAM中的起始地址 mov r1, #0x0 设置第2个参数:Nand Flash的起始地址 mov r2, #0x20000 设置第3个参数: UBOOT的长度(128KB)

bl nand_read_ll 在board/tekkaman/tekkaman2440/nand_read.c我会解析这个函数的作用

tst r0, #0x0 如果函数的返回值为0,表示执行成功.

beq ok_nand_read 执行内存比较,比较什么呢?他比较搬运到内存中的代码和在内部ram的前4kb是否一样

bad_nand_read:

loop2: b loop2 @ infinite loop

ok_nand_read: @ verify

mov r0, #0 内部RAM的起始地址

ldr r1, =TEXT_BASE UBOOT在RAM中的起始地址 mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes go_next: ldr r3, [r0], #4 ldr r4, [r1], #4

6

teq r3, r4 进行比较 bne notmatch subs r2, r2, #4 beq stack_setup bne go_next

notmatch:

内存中的代码和在内部ram的前4kb如果不一样,就无限的循环在这了,如果你不努力的去

体会每一句,你的功力就像他一样了,哈哈! loop3: b loop3 @ infinite loop

#endif @CONFIG_S3C2440_NAND_BOOT @tekkaman@@

在 “ _start_armboot: .word start_armboot ” 后加入: .align 2 二的平方 也就是字对齐了存储了

DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

9.在board/tekkaman/tekkaman2440加入NAND Flash读函数文件,拷贝vivi中的nand_read.c文件到此文件夹即可:

#include

#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));等待是否nand忙于上次的操作 NFSTAT |= BUSY; }

7

#define NAND_SECTOR_SIZE 512 一页大小,我们的nand是这样分的 1设备(Device) = 4096 块(Blocks)

1块(Block) = 32页/行(Pages/rows) ;页与行是相同的意思,叫法不一样 1(Page) = 528字节(Bytes) = 数据块大小(512Bytes) + OOB块大小(16Bytes)

在每一页中,最后16个字节(又称OOB)用于Nand Flash命令执行完后设置状态用,剩余512个字节又 分为前半部分和后半部分。可以通过Nand Flash命令00h/01h/50h分别对前半部、后半部、OOB进行定位,通过OOB部分的第六字节(即517字节)标志是否是坏块,OOB第六字节外,通常至少把OOB的前3个字节存放Nand Flash硬件ECC码,这个我就不多说了,你要想真正看懂这些代码,必须了解nand的架构啊Nand Flash内置的指针指向各自的首地址。

#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 ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { return -1; /* invalid alignment */检验开始地址和程序大小是否为512的整数 }

NAND_CHIP_ENABLE; 允许NAND

for(i=start_addr; i < (start_addr + size);) {直到读取整个uboot代码为止 /* READ0 */

NAND_CLEAR_RB; NFCMD = 0;

Nand Flash 片内寻址采用26位地址形式。从第0位开始分四次通过I/O0-I/O7进行 传送,并进行片内寻址。具体含义如下:

0-7位:字节在上半部、下半部及OOB内的偏移地址 8位:值为0代表对一页内前256个字节进行寻址 值为1代表对一页内后256个字节进行寻址 9-13位:对页进行寻址 14-25位:对块进行寻址 当传送地址时,从位0开始 /* Write Address */ NFADDR = i & 0xff;

NFADDR = (i >> 9) & 0xff; NFADDR = (i >> 17) & 0xff; NFADDR = (i >> 25) & 0xff;

NAND_DETECT_RB; /* 读出一页(512字节) */

8

for(j=0; j < NAND_SECTOR_SIZE; j++, i++) { *buf = (NFDATA & 0xff); buf++; } }

NAND_CHIP_DISABLE;禁止片选 return 0; }

注意:s3c2410与s3c2440的Nand Flash控制器寄存器不同,不能混用!!

10. 修改board/tekkaman/tekkaman2440/Makefile文件 OBJS := tekkaman2440.o nand_read.o flash.o

11. 修改include/configs/tekkaman2440.h文件,添加如下内容(注意:s3c2410与s3c2440的Nand Flash控制器寄存器不同,不能混用!!): ...... /*

* Nandflash Boot */

#define CONFIG_S3C2440_NAND_BOOT 1 这处告诉从nand启动 #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_B 0x10

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

12. 修改board/tekkaman/tekkaman2440/lowlevel_init.S文件 ......

/* REFRESH parameter */

9

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

注:参数的值按照SKY提供的对应文件的参数修改过来。 13. 修改/board/tekkaman/tekkaman2440/tekkaman2440.c

因为SKY2440和smdk2410的GPIO连接有所不同,修改其对GPIO和PLL的配置(请参阅SKY2440的硬件说明、2440芯片手册和提供的uboot相对应的文件):这个函数我想不用我解释了吧!其实有些IO口在驱动里可以重新设置,但有时没有必要单单写一个IO驱动,例如串口的端口设置需要将他设置为rx或tx用那就可以直接改这了。 ......

#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->GPBCON = 0x00044556; gpio->GPBCON = 0x00055556; ......

/* arch number of S3C2440 -Board */

gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ;

机码ID号必须和内核的机码对上,我们的是168,你找到他不要另加一个,因为我就犯过这个错误,他本身里面就有一个,你得覆盖他,要不然他还会认他以前的那个号,别忘了他的配置文件,是按照行读的,一旦读到匹配的参数就会跳出循环,导致你在后面加的根本就没起上作用。 /* adress of boot parameters */

gd->bd->bi_boot_params = 0x30000100;

10

我的arm - linux移植笔记

strbr2,[r1,#oNFCMD]movr3,#0@wait就是一下段延时nand1:addr3,r3,#0x1cmpr3,#0xabltnand1nand2:ldrr2,[r1,#oNFSTAT]@
推荐度:
点击下载文档文档为doc格式
3q3ea97wu606i7k4fy2m
领取福利

微信扫码领取福利

微信扫码分享