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();
}
如果本篇博客对您有帮助,或许可以在下方评论给我留个言。
启动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();
}
相关文章推荐
- 移植u-boot学习笔记5----- 修改代码之支持NAND启动
- u-boot-2012.04.01移植笔记——支持NAND启动
- u-boot-2012.04.01移植笔记——支持NAND启动
- u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动 .
- TQ2440 u-boot-2012.04.01移植二支持NAND启动
- 移植u-boot-2012.04----支持nand启动
- u-boot2010.03 移植篇(三)-----进一步修改start.S,smdk6410.h,支持nand启动及配置DM9000网卡
- 【Linux 移植 】——4、移植 u-boot-2012.04.01 之 支持NAND启动
- 移植u-boot-2012.04.01到jz2440开发板之修改代码支持NAND启动
- <2012 12 06> FL2440开发板的U-boot-2010.09版本移植(九)NAND Flash启动支持的一种新型方法,利用U-Boot自带nand_spl/nand_boot.c
- u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动
- TQ2440 u-boot-2012.10移植二支持NAND启动
- OK6410之uboot移植(4)——uboot启动代码植及支持nand flansh启动
- TQ2440 u-boot-2012.10移植二支持NAND启动
- u-boot-2009-11移植之stage1(支持从nand启动)
- 06-S3C2440学习之移植2012u-boot到S3C2440(移植过程二)支持NAND启动
- 移植u-boot2012.04.1 -》2440 (五)支持 nand nor 两种启动方式(完结)
- [s3c2416x移植u-boot-2015.10] 让u-boot-2015.10支持spl nand的启动
- u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动
- u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动