s3c2440 移值u-boot-2016.03 第2篇 支持Nand flash启动

2023-09-04  

 

1, 要求:在4K 的代码以内,完成 NOR NAND 类型判断,初始化 NAND 复制自身到 SDRAM ,重定向。

2, 在 /arch/arm/cpu/arm920t/ 文件夹里 添加一个 inic.c 的文件,要在这个文件里面做上面说的事情。
修改 /arch/arm/cpu/arm920t/Makefile 加入 inic.c 的 编译。
extra-y = start.o
obj-y += init.o
obj-y += cpu.o

init.c 最后有补丁文件

3, 在 start.S 中初始化 SP 后调用 init.c 中的 初始化 NAND FLASH 和 复制 u-boot 到 SDRAM 清BSS 等

ldr sp, =4096 #在 NOR 启动时定在这里是不能写的,sp 中通常是保存 入栈 出栈 , 局部变量等,因为函数中并没有用到,设不设这里都可以。
bl init_sdram
ldr sp, =0x34000000
bl nand_init_ll
/**
* 从 0 地址开始复制 到 SDRAM 中
* 在 smdk2440.h 中定义 #define CONFIG_SYS_TEXT_BASE
* u-boot 的加载地址
*/
mov r0,#0
ldr r1,=CONFIG_SYS_TEXT_BASE
ldr r2,=__bss_start
sub r2, r2, r1
bl copy_code_to_sdram
bl clear_bss #清不清都可以,因为重定向那里还要在清一次,为了以后去掉重定向这里也清。
#从片内 4K 跳到 SDRAM 中 bl 不行,要用 ldr pc
ldr pc,=_main

4, 启用流程
/arch/arm/cpu/arm920t/start.S
/arch/arm/lib/crt0.S
u-boot 第一阶段
/common/Board_f.c 中的 board_init_f() 函数
最后调用
jump_to_copy()
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
调用/arch/arm/librelocate.S relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
执行完毕后返回
crt0.S
bl board_init_f
下面直接执行第2阶段,也是因为执行了重定位,bl 跳不了
ldr pc, =board_init_r

5, 如何兼容 NOR FLASH NAND FLASH 启用?
不改动 原来的 重定位代码比较简单。
兼容 NOR FLASH NAND FLASH 的方法是,如果不想修改重定位的代码,就是先把 u-boot 复制到
SDRAM 的一个低地址,然后,它会从 这里在复制到 SDRAM 的高地址去。
NAND FLASH 启用要做的就是,在 4K 自动复制的代码里面,实现把u-boot 复制到 SDRAM 的低地址

6, 确定一个可用的链接地址
crt0.S
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
这里先把 sp 定在了最低端,因此不能使用 0x30000000
又因为u-boot 最终会被放到高地址也不能用 0x34000000
因为内存很大,放在10M 的位置吧。
在 smdk2440.h 中定义 #define CONFIG_SYS_TEXT_BASE 0x30a00000


补丁文件:


  1 diff -urN u-boot-2016.03/arch/arm/cpu/arm920t/init.c u-boot-2016.03-ok/arch/arm/cpu/arm920t/init.c

  2 --- u-boot-2016.03/arch/arm/cpu/arm920t/init.c    1970-01-01 07:00:00.000000000 +0700

  3 +++ u-boot-2016.03-ok/arch/arm/cpu/arm920t/init.c    2016-05-17 06:48:31.635438931 +0800

  4 @@ -0,0 +1,196 @@

  5 +/* NAND FLASH控制器 */

  6 +#define NFCONF (*((volatile unsigned long *)0x4E000000))

  7 +#define NFCONT (*((volatile unsigned long *)0x4E000004))

  8 +#define NFCMMD (*((volatile unsigned char *)0x4E000008))

  9 +#define NFADDR (*((volatile unsigned char *)0x4E00000C))

 10 +#define NFDATA (*((volatile unsigned char *)0x4E000010))

 11 +#define NFSTAT (*((volatile unsigned char *)0x4E000020))

 12 +

 13 +/* CLK */

 14 +#define CLKDIVN  (*(volatile unsigned long *)0x4C000014)

 15 +#define MPLLCON  (*(volatile unsigned long *)0x4C000004) 

 16 +

 17 +/* SDRAM */

 18 +#define BWSCON    (*(volatile unsigned long *)0x48000000) 

 19 +#define BANKCON6  (*(volatile unsigned long *)0x4800001c) 

 20 +#define REFRESH   (*(volatile unsigned long *)0x48000024) 

 21 +#define BANKSIZE  (*(volatile unsigned long *)0x48000028) 

 22 +#define MRSRB6    (*(volatile unsigned long *)0x4800002c)

 23 +

 24 +void init_clock(void)

 25 +{

 26 +    //Mpll = 400M

 27 +    MPLLCON = (0x5c<<12) | (1<<4) | 1;

 28 +    //FCLK 400M HCLK 100M PCLK 50M

 29 +    CLKDIVN = 2<<1 | 1<<0;

 30 +    __asm__(

 31 +        "mrc  p15,0,r0,c1,c0,0n" 

 32 +        "orr  r0,r0,#0xc0000000n"

 33 +        "mcr  p15,0,r0,c1,c0,0n" 

 34 +    );

 35 +}

 36 +

 37 +void init_sdram(void)

 38 +{

 39 +    BWSCON   = 1<<25;

 40 +    BANKCON6 = 1<<16 | 1<<15 | 1;

 41 +    REFRESH  = (1<<23) + 1268;

 42 +    BANKSIZE = 1<<7 | 1<<4 | 1;

 43 +    MRSRB6   = 0x30;

 44 +}

 45 +

 46 +void clear_bss(void)

 47 +{

 48 +    extern int __bss_start, __bss_end;

 49 +    int *p = &__bss_start;

 50 +    

 51 +    for (; p < &__bss_end; p++)

 52 +    {    

 53 +        *p = 0;

 54 +    }

 55 +}

 56 +

 57 +static void nand_latency(void)

 58 +{

 59 +    int i=100;

 60 +    while(i--);

 61 +}

 62 +

 63 +static void nand_is_ready(void)

 64 +{

 65 +    //bit 0 : 1 不忙了

 66 +    while(! (NFSTAT & 1));

 67 +}

 68 +

 69 +static void nand_write_addr(unsigned int addr)

 70 +{

 71 +    int col, page;

 72 +    col = addr % 2048;

 73 +    page = addr / 2048;

 74 +    

 75 +    NFADDR = col & 0xff;            /* Column Address A0~A7 */

 76 +    nand_latency();        

 77 +    NFADDR = (col >> 8) & 0x0f;     /* Column Address A8~A11 */

 78 +    nand_latency();

 79 +    NFADDR = page & 0xff;            /* Row Address A12~A19 */

 80 +    nand_latency();

 81 +    NFADDR = (page >> 8) & 0xff;    /* Row Address A20~A27 */

 82 +    nand_latency();

 83 +    NFADDR = (page >> 16) & 0x03;    /* Row Address A28~A29 */

 84 +    nand_latency();

 85 +}

 86 +

 87 +static unsigned char nand_read_char(void)

 88 +{

 89 +    //只保留8个bit

 90 +    return NFDATA & 0xff;

 91 +}

 92 +

 93 +static void nand_cmd(unsigned char cmd)

 94 +{

 95 +    NFCMMD = cmd;

 96 +    nand_latency();

 97 +}

 98 +

 99 +static void nand_select_chip(void)

100 +{

101 +    //1bit : 0 选中

102 +    NFCONT &= ~(1<<1);

103 +}

104 +

105 +static void nand_deselect_chip(void)

106 +{

107 +    //1bit : 1 选中

108 +    NFCONT |= (1<<1);

109 +}

110 +

111 +static void nand_reset(void)

112 +{

113 +    nand_select_chip();

114 +    nand_cmd(0xff);

115 +    nand_deselect_chip();

116 +}

117 +

118 +void nand_init_ll(void)

119 +{    

120 +    //TACLS 3.3v 时 12ns

121 +    #define TACLS   0

122 +    //12ns

123 +    #define TWRPH0  1

124 +    //5ns

125 +    #define TWRPH1  0

126 +    NFCONF = TACLS<<12 | TWRPH0<<8 |  TWRPH1<<4;

127 +    /* 4 ECC

128 +     * 1 CE 先不选中,用的时候在选中

129 +     * 0 启动 flash controller

130 +     */

131 +    NFCONT = 1<<4 | 1<<1 | 1;

132 +    nand_reset();

133 +}

134 +

135 +static void nand_read(unsigned int addr, unsigned char *buf, int len)

136 +{

137 +    //选中

138 +    nand_select_chip();

139 +    //j 地址可能不是从0对齐开始读的

140 +    unsigned int i = addr,j = addr % 2048;

141 +    for(; i142 +    {

143 +        //读命令

144 +        nand_cmd(0x00);

145 +        nand_is_ready();

146 +        

147 +        //发送地址

148 +        nand_write_addr(i);

149 +        nand_is_ready();

150 +    

151 +        //在次发出读命令

152 +        nand_cmd(0x30);

153 +        nand_is_ready();

154 +        //读2K

155 +        for(; j<2048; j++)

156 +        {

157 +            *buf = nand_read_char();

158 +            buf++;

159 +            i++;

160 +        }

161 +        j=0;

162 +        nand_latency();

163 +    }

164 +    //取消选中

165 +    nand_deselect_chip();

166 +}

167 +

168 +static int boot_is_nor()

169 +{

170 +    //利用 NOR 不能写的特点判断

171 +    volatile unsigned int *p = (volatile unsigned int *)0;

172 +    unsigned int val;

173 +    val = *p;

174 +    *p = 0x12345678;

175 +    if(0x12345678 == *p)

176 +    {

177 +        *p = val;

178 +        return 0;

179 +    }

180 +    return 1;

181 +}

182 +

183 +//片内4K 的程序要复制到链接SDRAM中去

184 +void copy_code_to_sdram(unsigned char *src,unsigned char *dst,int len)

185 +{

186 +    int i = 0;

187 +    if(boot_is_nor())

188 +    {

189 +        while(i < len)

190 +        {

191 +            dst[i] = src[i];

192 +            i++;

193 +        }

194 +    }

195 +    else

196 +    {

197 +        nand_read((int)src, dst, len);

198 +    }

199 +}

200 +

201 diff -urN u-boot-2016.03/arch/arm/cpu/arm920t/Makefile u-boot-2016.03-ok/arch/arm/cpu/arm920t/Makefile

202 --- u-boot-2016.03/arch/arm/cpu/arm920t/Makefile    2016-03-14 22:20:21.000000000 +0800

203 +++ u-boot-2016.03-ok/arch/arm/cpu/arm920t/Makefile    2016-05-17 06:48:31.767626866 +0800

204 @@ -8,6 +8,7 @@

205  extra-y    = start.o

206  

207  obj-y    += cpu.o

208 +obj-y    += init.o

209  obj-$(CONFIG_USE_IRQ)    += interrupts.o

210  

211  obj-$(CONFIG_EP93XX) += ep93xx/

212 diff -urN u-boot-2016.03/arch/arm/cpu/arm920t/start.S u-boot-2016.03-ok/arch/arm/cpu/arm920t/start.S

213 --- u-boot-2016.03/arch/arm/cpu/arm920t/start.S    2016-03-14 22:20:21.000000000 +0800

214 +++ u-boot-2016.03-ok/arch/arm/cpu/arm920t/start.S    2016-05-17 06:48:31.782641369 +0800

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。