[Linux]u-boot_2014移植(四)支持nand启动

[Linux]u-boot_2014移植(四)支持nand启动

个人博客https://aeneag.xyz/

艾恩凝

2021/6/5

个人认为支持nand启动是最难操作的 ,出现的问题比较多

修改链接

config.mk

arch/arm/config.mk 里修改

1LDFLAGS_u-boot +=
2ALL-y += checkarmreloc

注释掉上面两个

u-boot.lds

ubootlds.png

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

init.png

  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 中 修改此函数,如下图

boardinit.png

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

nandstart.png

board_init_r

arch/arm/lib/board.c 中 修改此函数中的,如下图

hang.png

end

至此,现在大概率可以正常在nand上启动u-boot了

u-boot移植系列目录

上一篇[Linux]u-boot_2014移植(三)设置时钟 修改内存

下一篇[Linux]u-boot_2014移植(五)支持NOR_Flash Nand_Flash


    


公众号'艾恩凝'
个人公众号
个人微信
个人微信
    吾心信其可行,
          则移山填海之难,
                  终有成功之日!
                                  ——孙文
    评论
    0 评论
avatar

取消