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

时间:2021-01-03 21:54:46

你好!这里是风筝的博客,欢迎和我一起交流。

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


启动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文件:

  1. /* NAND FLASH控制器 */  
  2. #define NFCONF (*((volatile unsigned long *)0x4E000000))  
  3. #define NFCONT (*((volatile unsigned long *)0x4E000004))  
  4. #define NFCMMD (*((volatile unsigned char *)0x4E000008))  
  5. #define NFADDR (*((volatile unsigned char *)0x4E00000C))  
  6. #define NFDATA (*((volatile unsigned char *)0x4E000010))  
  7. #define NFSTAT (*((volatile unsigned char *)0x4E000020))  
  8.   
  9. /* GPIO */  
  10. #define GPHCON              (*(volatile unsigned long *)0x56000070)  
  11. #define GPHUP               (*(volatile unsigned long *)0x56000078)  
  12.   
  13. /* UART registers*/  
  14. #define ULCON0              (*(volatile unsigned long *)0x50000000)  
  15. #define UCON0               (*(volatile unsigned long *)0x50000004)  
  16. #define UFCON0              (*(volatile unsigned long *)0x50000008)  
  17. #define UMCON0              (*(volatile unsigned long *)0x5000000c)  
  18. #define UTRSTAT0            (*(volatile unsigned long *)0x50000010)  
  19. #define UTXH0               (*(volatile unsigned char *)0x50000020)  
  20. #define URXH0               (*(volatile unsigned char *)0x50000024)  
  21. #define UBRDIV0             (*(volatile unsigned long *)0x50000028)  
  22.   
  23. #define TXD0READY   (1<<2)  
  24.   
  25. void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);  
  26.   
  27. static int isBootFromNorFlash(void)  
  28. {  
  29. volatile int *p = (volatile int *)0;  
  30. int val;  
  31. val = *p;  
  32. *p = 0x12345678;  
  33. if (*p == 0x12345678)  
  34. {  
  35. /* 写成功, 是nand启动 */  
  36. *p = val;  
  37. return 0;  
  38. }  
  39. else  
  40. {  
  41. /* NOR不能像内存一样写 */  
  42. return 1;  
  43. }  
  44. }  
  45.   
  46. void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)  
  47. {   
  48. int i = 0;  
  49.   
  50. /* 如果是NOR启动 */  
  51. if (isBootFromNorFlash())  
  52. {  
  53. while (i < len)  
  54. {  
  55. dest[i] = src[i];  
  56. i++;  
  57. }  
  58. }  
  59. else  
  60. {  
  61. //nand_init();  
  62. nand_read_ll((unsigned int)src, dest, len);  
  63. }  
  64. }  
  65.   
  66. void clear_bss(void)  
  67. {  
  68. extern int __bss_start, __bss_end;  
  69. int *p = &__bss_start;  
  70.   
  71. for (; p < &__bss_end; p++)  
  72. *p = 0;  
  73. }  
  74.   
  75. void nand_init_ll(void)  
  76. {  
  77. #define TACLS   0  
  78. #define TWRPH0  1  
  79. #define TWRPH1  0  
  80. /* 设置时序 */  
  81. NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);  
  82. /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */  
  83. NFCONT = (1<<4)|(1<<1)|(1<<0);  
  84. }  
  85.   
  86. static void nand_select(void)  
  87. {  
  88. NFCONT &= ~(1<<1);  
  89. }  
  90.   
  91. static void nand_deselect(void)  
  92. {  
  93. NFCONT |= (1<<1);  
  94. }  
  95.   
  96. static void nand_cmd(unsigned char cmd)  
  97. {  
  98. volatile int i;  
  99. NFCMMD = cmd;  
  100. for (i = 0; i < 10; i++);  
  101. }  
  102.   
  103. static void nand_addr(unsigned int addr)  
  104. {  
  105. unsigned int col  = addr % 2048;  
  106. unsigned int page = addr / 2048;  
  107. volatile int i;  
  108. NFADDR = col & 0xff;  
  109. for (i = 0; i < 10; i++);  
  110. NFADDR = (col >> 8) & 0xff;  
  111. for (i = 0; i < 10; i++);  
  112. NFADDR  = page & 0xff;  
  113. for (i = 0; i < 10; i++);  
  114. NFADDR  = (page >> 8) & 0xff;  
  115. for (i = 0; i < 10; i++);  
  116. NFADDR  = (page >> 16) & 0xff;  
  117. for (i = 0; i < 10; i++);  
  118. }  
  119.   
  120. static void nand_wait_ready(void)  
  121. {  
  122. while (!(NFSTAT & 1));  
  123. }  
  124.   
  125. static unsigned char nand_data(void)  
  126. {  
  127. return NFDATA;  
  128. }  
  129.   
  130. void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)  
  131. {  
  132. int col = addr % 2048;  
  133. int i = 0;  
  134.   
  135. /* 1. 选中 */  
  136. nand_select();  
  137.   
  138. while (i < len)  
  139. {  
  140. /* 2. 发出读命令00h */  
  141. nand_cmd(0x00);  
  142.   
  143. /* 3. 发出地址(分5步发出) */  
  144. nand_addr(addr);  
  145.   
  146. /* 4. 发出读命令30h */  
  147. nand_cmd(0x30);  
  148.   
  149. /* 5. 判断状态 */  
  150. nand_wait_ready();  
  151.   
  152. /* 6. 读数据 */  
  153. for (; (col < 2048) && (i < len); col++)  
  154. {  
  155. buf[i] = nand_data();  
  156. i++;  
  157. addr++;  
  158. }  
  159.   
  160. col = 0;  
  161. }  
  162.   
  163. /* 7. 取消选中 */   
  164. nand_deselect();  
  165. }