你好!这里是风筝的博客,欢迎和我一起交流。
如果本篇博客对您有帮助,或许可以在下方评论给我留个言。
启动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
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();
- }