您的位置:首页 > 其它

2440超详细uboot移植笔记(八)------支持NAND启动

2017-05-04 14:19 197 查看
你好!这里是风筝的博客,欢迎和我一起交流。

如果本篇博客对您有帮助,或许可以在下方评论给我留个言。

启动u-boot后发现提示“NAND:  0 MiB”,说明uboot现在还不能识别出NAND FLASH,所以现在我们来修改代码:

a.在smdk2440.h(路径为:include\configs\smdk2440.h)文件中,将

#define CONFIG_SYS_TEXT_BASE 0x0

修改为:

#define CONFIG_SYS_TEXT_BASE0x33f80000

因为nand flash地址为30000000~34000000,所以这里为uboot留出512k的空间

b.
注释掉:

jump_to_copy

这是跳转函数,先注释掉,这里由我们自己实现。

c.添加init.c(这个文件待会我会上传)文件到board/samsung/smdk2440文件夹下

d.
修改board/samsung/smdk2440下的Makefile文件,把

obj-y:= smdk2440.o

修改为:

obj-y:= init.o smdk2440.o

这里涉及到Makefile的语法,意为编译init和smdk2440文件。

e.在arch/arm/cpu目录下修改u-boot.lds文件下,在:

CPUDIR/start.o(.text*)

这一行语句下添加一句:

board/samsung/smdk2440/built-in.o (.text)

f.在文件:arch/arm/lib/crt0.s的include之后添加如下代码:

.globl _TEXT_BASE

_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE

其中,_TEXT_BASE作为此刻代码段的位置,把代码从NAND FLASH复制到SDRAM时要用到

g.在汇编函数_main(路径:arch/arm/lib/crt0.s)里,找到这句代码:

bicsp, sp, #7/*
8-byte alignment for ABI compliance */

这条是8字节对齐指令,而且在这个_main函数里,设置了堆栈指针,所以我们现在可以调用C函数了。

所以在#endif之后添加如下代码:

bl nand_init_ll
mov r0, #0
ldr r1, _TEXT_BASE

ldr r2, =__bss_start
sub r2, r2, r1

bl copy_code_to_sdram
bl clear_bss
ldr pc, =call_board_init_f

call_board_init_f:

h.在c函数reserve_uboot(路径:common/board_f)里,把:

gd->relocaddr -= gd->mon_len;

gd->relocaddr &= ~(4096 - 1);

这两句和重定位有关,先注释掉,并且在:
gd->start_addr_sp = gd->relocaddr;

这一句代码之前添加一句:
gd->relocaddr = CONFIG_SYS_TEXT_BASE;

这里由我们自己定位地址。

i.至此,NAND也可以启动uboot了.

附上init.c文件:

/* NAND FLASH控制器 */  

#define NFCONF (*((volatile unsigned long *)0x4E000000))  

#define NFCONT (*((volatile unsigned long *)0x4E000004))  

#define NFCMMD (*((volatile unsigned char *)0x4E000008))  

#define NFADDR (*((volatile unsigned char *)0x4E00000C))  

#define NFDATA (*((volatile unsigned char *)0x4E000010))  

#define NFSTAT (*((volatile unsigned char *)0x4E000020))  

  

/* GPIO */  

#define GPHCON              (*(volatile unsigned long *)0x56000070)  

#define GPHUP               (*(volatile unsigned long *)0x56000078)  

  

/* UART registers*/  

#define ULCON0              (*(volatile unsigned long *)0x50000000)  

#define UCON0               (*(volatile unsigned long *)0x50000004)  

#define UFCON0              (*(volatile unsigned long *)0x50000008)  

#define UMCON0              (*(volatile unsigned long *)0x5000000c)  

#define UTRSTAT0            (*(volatile unsigned long *)0x50000010)  

#define UTXH0               (*(volatile unsigned char *)0x50000020)  

#define URXH0               (*(volatile unsigned char *)0x50000024)  

#define UBRDIV0             (*(volatile unsigned long *)0x50000028)  

  

#define TXD0READY   (1<<2)  

  

void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);  

  

static int isBootFromNorFlash(void)  

{  

volatile int *p = (volatile int *)0;  

int val;  

val = *p;  

*p = 0x12345678;  

if (*p == 0x12345678)  

{  

/* 写成功, 是nand启动 */  

*p = val;  

return 0;  

}  

else  

{  

/* NOR不能像内存一样写 */  

return 1;  

}  

}  

  

void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)  

{   

int i = 0;  

  

/* 如果是NOR启动 */  

if (isBootFromNorFlash())  

{  

while (i < len)  

{  

dest[i] = src[i];  

i++;  

}  

}  

else  

{  

//nand_init();  

nand_read_ll((unsigned int)src, dest, len);  

}  

}  

  

void clear_bss(void)  

{  

extern int __bss_start, __bss_end;  

int *p = &__bss_start;  

  

for (; p < &__bss_end; p++)  

*p = 0;  

}  

  

void nand_init_ll(void)  

{  

#define TACLS   0  

#define TWRPH0  1  

#define TWRPH1  0  

/* 设置时序 */  

NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);  

/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */  

NFCONT = (1<<4)|(1<<1)|(1<<0);  

}  

  

static void nand_select(void)  

{  

NFCONT &= ~(1<<1);  

}  

  

static void nand_deselect(void)  

{  

NFCONT |= (1<<1);  

}  

  

static void nand_cmd(unsigned char cmd)  

{  

volatile int i;  

NFCMMD = cmd;  

for (i = 0; i < 10; i++);  

}  

  

static void nand_addr(unsigned int addr)  

{  

unsigned int col  = addr % 2048;  

unsigned int page = addr / 2048;  

volatile int i;  

NFADDR = col & 0xff;  

for (i = 0; i < 10; i++);  

NFADDR = (col >> 8) & 0xff;  

for (i = 0; i < 10; i++);  

NFADDR  = page & 0xff;  

for (i = 0; i < 10; i++);  

NFADDR  = (page >> 8) & 0xff;  

for (i = 0; i < 10; i++);  

NFADDR  = (page >> 16) & 0xff;  

for (i = 0; i < 10; i++);  

}  

  

static void nand_wait_ready(void)  

{  

while (!(NFSTAT & 1));  

}  

  

static unsigned char nand_data(void)  

{  

return NFDATA;  

}  

  

void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)  

{  

int col = addr % 2048;  

int i = 0;  

  

/* 1. 选中 */  

nand_select();  

  

while (i < len)  

{  

/* 2. 发出读命令00h */  

nand_cmd(0x00);  

  

/* 3. 发出地址(分5步发出) */  

nand_addr(addr);  

  

/* 4. 发出读命令30h */  

nand_cmd(0x30);  

  

/* 5. 判断状态 */  

nand_wait_ready();  

  

/* 6. 读数据 */  

for (; (col < 2048) && (i < len); col++)  

{  

buf[i] = nand_data();  

i++;  

addr++;  

}  

  

col = 0;  

}  

  

/* 7. 取消选中 */   

nand_deselect();  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: