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

xiaoxiao2021-02-27  309

你好!这里是风筝的博客,

欢迎和我一起交流。


启动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();  }  

 

 

 

 

 

 

转载请注明原文地址: https://www.6miu.com/read-3530.html

最新回复(0)