[Linux]u-boot_2014移植(四)支持nand启动
[Linux]u-boot_2014移植(四)支持nand启动
艾恩凝
2021/6/5
个人认为支持nand启动是最难操作的 ,出现的问题比较多
修改链接
config.mk
在arch/arm/config.mk 里修改
1LDFLAGS_u-boot +=
2ALL-y += checkarmreloc
注释掉上面两个
u-boot.lds
在arch/arm/cpu/u-boot.lds 下增加如下两行
1 board/samsung/smdk2440/built-in.o(.text*)
2 arch/arm/cpu/built-in.o (.text*)
smdk2440.h
修改CONFIG_SYS_TEXT_BASE 的值
1#define CONFIG_SYS_TEXT_BASE 0x33f00000
init.c
在 arch/arm/cpu/arm920t 路径下添加 init.c,并且修改同目录下的Makefile
1
2/* NAND FLASH控制器 */
3#define NFCONF (*((volatile unsigned long *)0x4E000000))
4#define NFCONT (*((volatile unsigned long *)0x4E000004))
5#define NFCMMD (*((volatile unsigned char *)0x4E000008))
6#define NFADDR (*((volatile unsigned char *)0x4E00000C))
7#define NFDATA (*((volatile unsigned char *)0x4E000010))
8#define NFSTAT (*((volatile unsigned char *)0x4E000020))
9
10/* GPIO */
11#define GPHCON (*(volatile unsigned long *)0x56000070)
12#define GPHUP (*(volatile unsigned long *)0x56000078)
13
14/* UART registers*/
15#define ULCON0 (*(volatile unsigned long *)0x50000000)
16#define UCON0 (*(volatile unsigned long *)0x50000004)
17#define UFCON0 (*(volatile unsigned long *)0x50000008)
18#define UMCON0 (*(volatile unsigned long *)0x5000000c)
19#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
20#define UTXH0 (*(volatile unsigned char *)0x50000020)
21#define URXH0 (*(volatile unsigned char *)0x50000024)
22#define UBRDIV0 (*(volatile unsigned long *)0x50000028)
23
24#define TXD0READY (1<<2)
25
26
27void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);
28
29static int isBootFromNorFlash(void)
30{
31 volatile int *p = (volatile int *)0;
32 int val;
33
34 val = *p;
35 *p = 0x12345678;
36 if (*p == 0x12345678)
37 {
38 /* 写成功, 是nand启动 */
39 *p = val;
40 return 0;
41 }
42 else
43 {
44 /* NOR不能像内存一样写 */
45 return 1;
46 }
47}
48
49/*
50*src=0; dest=0x33f80000;len=0x73250
51**/
52void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
53{
54 int i = 0;
55
56 /* 如果是NOR启动 */
57 if (isBootFromNorFlash())
58 {
59 while (i < len)
60 {
61 dest[i] = src[i];
62 i++;
63 }
64 }
65 else
66 {
67 //nand_init();
68 nand_read_ll((unsigned int)src, dest, len);
69 }
70}
71
72void clear_bss(void)
73{
74 extern int __bss_start, __bss_end;
75 int *p = &__bss_start;
76
77 for (; p < &__bss_end; p++)
78 *p = 0;
79
80}
81
82void nand_init_ll(void)
83{
84#define TACLS 0
85#define TWRPH0 1
86#define TWRPH1 0
87 /* 设置时序 */
88 NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
89 /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
90 NFCONT = (1<<4)|(1<<1)|(1<<0);
91}
92
93static void nand_select(void)
94{
95 NFCONT &= ~(1<<1);
96}
97
98static void nand_deselect_ll(void)
99{
100 NFCONT |= (1<<1);
101}
102
103static void nand_cmd(unsigned char cmd)
104{
105 volatile int i;
106 NFCMMD = cmd;
107 for (i = 0; i < 10; i++);
108}
109
110static void nand_addr(unsigned int addr)
111{
112 unsigned int col = addr % 2048;
113 unsigned int page = addr / 2048;
114 volatile int i;
115
116 NFADDR = col & 0xff;
117 for (i = 0; i < 10; i++);
118 NFADDR = (col >> 8) & 0xff;
119 for (i = 0; i < 10; i++);
120
121 NFADDR = page & 0xff;
122 for (i = 0; i < 10; i++);
123 NFADDR = (page >> 8) & 0xff;
124 for (i = 0; i < 10; i++);
125 NFADDR = (page >> 16) & 0xff;
126 for (i = 0; i < 10; i++);
127}
128
129static void nand_wait_ready_ll(void)
130{
131 while (!(NFSTAT & 1));
132}
133
134static unsigned char nand_data(void)
135{
136 return NFDATA;
137}
138/*
139*src=0; dest=0x33f80000;len=0x73250
140*/
141void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)
142{
143 int col = addr % 2048;
144 int i = 0;
145
146 /* 1. 选中 */
147 nand_select();
148
149 while (i < len)
150 {
151 /* 2. 发出读命令00h */
152 nand_cmd(0x00);
153
154 /* 3. 发出地址(分5步发出) */
155 nand_addr(addr);
156
157 /* 4. 发出读命令30h */
158 nand_cmd(0x30);
159
160 /* 5. 判断状态 */
161 nand_wait_ready_ll();
162
163 /* 6. 读数据 */
164 for (; (col < 2048) && (i < len); col++)
165 {
166 buf[i] = nand_data();
167 i++;
168 addr++;
169 }
170
171 col = 0;
172 }
173
174 /* 7. 取消选中 */
175 nand_deselect_ll();
176}
177
178
board_init_f
在 arch/arm/lib/board.c 中 修改此函数,如下图
crt0.S
修改如下
1ENTRY(_main)
2
3
4
5
6 bl board_init_f
7
8#if ! defined(CONFIG_SPL_BUILD)
9
10/*
11 * Set up intermediate environment (new sp and gd) and call
12 * relocate_code(addr_moni). Trick here is that we'll return
13 * 'here' but relocated.
14 */
15
16 ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
17 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
18 ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
19 sub r9, r9, #GD_SIZE /* new GD is below bd */
20
21/* Set up final (full) environment */
22
23 bl c_runtime_cpu_setup /* we still call old routine here */
24
25
26 bl coloured_LED_init
27 bl red_led_on
28
29 /* call board_init_r(gd_t *id, ulong dest_addr) */
30 mov r0, r9 /* gd_t */
31 ldr r1, =CONFIG_SYS_TEXT_BASE /* dest_addr */
32 /* call board_init_r */
33 ldr pc, =board_init_r /* this is auto-relocated! */
34
35 /* we should not return here. */
36
37#endif
38
39ENDPROC(_main)
40
删除其他的
start.S
修改如下,在 bl cpu_init_crit 执行之后,加入
1 /*
2 * Set up initial C runtime environment and call board_init_f(0).
3 */
4
5#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
6 ldr sp, =(CONFIG_SPL_STACK)
7#else
8 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
9#endif
10 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
11 sub sp, sp, #GD_SIZE /* allocate one GD above SP */
12 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
13 mov r9, sp /* GD is above SP */
14 mov r0, #0
15
16
17
18 bl nand_init_ll
19 mov r0, #0
20 ldr r1, _TEXT_BASE /* =0x33f00000 */
21 ldr r2, _bss_start_ofs
22 bl copy_code_to_sdram
23 bl clear_bss
24
25 ldr pc,=_main
board_init_r
在 arch/arm/lib/board.c 中 修改此函数中的,如下图
end
至此,现在大概率可以正常在nand上启动u-boot了
u-boot移植系列目录
上一篇[Linux]u-boot_2014移植(三)设置时钟 修改内存
下一篇[Linux]u-boot_2014移植(五)支持NOR_Flash Nand_Flash
吾心信其可行,
则移山填海之难,
终有成功之日!
——孙文
则移山填海之难,
终有成功之日!
——孙文
评论
0 评论