U-Boot-2009-03移植笔记(从Nandflash启动一)

发布时间:2024-09-04  

在U-Boot-2009-03移植笔记(点亮第一展灯)中,我们初始化好了sdram,点亮了第一盏灯。在本文中,我们将移植好nandflash启动的驱动代码。


对于S3C2440,有一个steppingston,在CPU上电的时候,由硬件将Nandflash的前4KB代码拷贝到片内的SRAM中,并且内部SRAM被映射到地址0x0,于是我们的代码才能被cpu执行。


但问题是我们的代码肯定不止4KB,所以我们必须自己写代码,把nandflash中的剩余代码拷贝到内存中,然后让CPU跳转到对应的内存地址执行。


设置堆栈指针,为C语言准备运行环境


1 /*设置堆栈*/

2 ldr sp, DW_STACK_START

3 mov fp,#0    

注意第二行引用了DW_STACK_START标号,我们定义在标号_start_armboot后面


1 _start_armboot:    .word start_armboot

2 DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

第二行的STACK_BASE和STACK_SIZE都定义在include/configs/xinna2440.h中


1 #define STACK_BASE  0x33f00000     //定义堆栈的地址

2 #define STACK_SIZE  0x8000         //堆栈的长度大小


设置好了堆栈指针,下面我们只需要初始化好Nandflash之后,就可以读取数据,存到sdram中了。


初始化NandFlash


我们在board/xinna2440/文件夹下,增加nand_op.c文件,然后修改board/xinna2440/Makefile,添加对nand_op.c的编译


1 COBJS        := xinna2440.o flash.o nand_op.o

编辑board/xinna2440/nand_op.c,添加以下文件,我们的板子上用的是K9F2G08U0A,2KB一页,共64MB大小。  1 /*


  2  * board/samsung/reille2440/nand_read.c

  3  *

  4  * (C) Copyright 2011

  5  * reille

  6  *

  7  * This program is free software; you can redistribute it and/or

  8  * modify it under the terms of the GNU General Public License as

  9  * published by the Free Software Foundation; either version 2 of

 10  * the License, or (at your option) any later version.

 11  *

 12  */

 13 #include

 14 #define NF_BASE   0x4E000000  //Nand Flash配置寄存器基地址

 15 #define __REGb(x) (*(volatile unsigned char *)(x))

 16 #define __REGi(x) (*(volatile unsigned int  *)(x))

 17 #if 0

 18 #define NFCONF __REGi(NF_BASE + 0x0 )  //通过偏移量还是得到配置寄存器基地址

 19 #define NFCONT __REGi(NF_BASE + 0x4 )  //通过偏移量得到控制寄存器基地址

 20 #define NFCMD  __REGb(NF_BASE + 0x8 )  //通过偏移量得到指令寄存器基地址

 21 #define NFADDR __REGb(NF_BASE + 0xC )  //通过偏移量得到地址寄存器基地址

 22 #define NFDATA __REGb(NF_BASE + 0x10)  //通过偏移量得到数据寄存器基地址

 23 #define NFSTAT __REGb(NF_BASE + 0x20)  //通过偏移量得到状态寄存器基地址

 24 #endif

 25 

 26 #define NFCONF (*(volatile unsigned int *)(NF_BASE + 0X0))

 27 #define NFCONT (*(volatile unsigned short *)(NF_BASE + 0x4))

 28 #define NFCMD  (*(volatile unsigned short *)(NF_BASE + 0X8))

 29 #define NFADDR (*(volatile unsigned short *)(NF_BASE + 0xc))

 30 #define NFDATA (*(volatile unsigned char *)(NF_BASE + 0x10))

 31 #define NFSTAT (*(volatile unsigned char *)(NF_BASE + 0x20))

 32 

 33 

 34 #define NAND_CHIP_ENABLE  (NFCONT &= ~(1<<1))  //Nand片选使能

 35 #define NAND_CHIP_DISABLE (NFCONT |= (1<<1))   //取消Nand片选

 36 #define NAND_CLEAR_RB     (NFSTAT |= (1<<2));

 37 #define NAND_DETECT_RB    { while(! (NFSTAT&(1<<2)) );}

 38 #define NAND_SECTOR_SIZE 2048

 39 #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)

 40 #if 0

 41 #define DEBUGN    printf

 42 #else

 43 #define DEBUGN(x, args ...) {}

 44 #endif

 45 

 46 /* low level nand read function */

 47 #define GPBCON  (*(volatile unsigned long *)0x56000010)

 48 #define GPBDAT  (*(volatile unsigned long *)0x56000014)

 49 

 50 #define GPACON    (*(volatile unsigned long *)0x56000000)

 51 

 52 void nand_wait_ll(void)

 53 {

 54     int k;

 55     while(!(NFSTAT & 1))

 56         for(k = 0; k < 20; k++);

 57     return;

 58 //    NAND_DETECT_RB

 59 }

 60 

 61 void nand_reset_ll(void)

 62 {

 63     NAND_CHIP_ENABLE; //选中Nand片选

 64 //    NAND_CLEAR_RB 

 65     NFCMD = 0xff;

 66     nand_wait_ll();

 67 //    NAND_CLEAR_RB 

 68     NAND_CHIP_DISABLE; //取消片选信号

 69 }

 70 

 71 

 72 unsigned char nand_read_id(unsigned char*mc,unsigned char *dc,unsigned char *pc)

 73 {

 74     int i=0;

 75     unsigned char res;

 76     NAND_CHIP_ENABLE; //选中Nand片选

 77     NFCMD = 0x90;

 78     for(i = 0;i < 100;i++);

 79     NFADDR = 0 & 0xFF;

 80     NFADDR = (0 >> 9) & 0xFF;

 81     NFADDR = (0 >> 17) & 0xFF;

 82     NFADDR = (0 >> 25) & 0xFF;

 83     for(i = 0;i < 100;i++);

 84     nand_wait_ll();

 85     *mc = NFDATA;

 86     *dc = NFDATA;

 87     res = NFDATA;

 88     *pc = NFDATA;

 89     NAND_CHIP_DISABLE; //取消片选信号

 90     return *mc;

 91 }

 92 

 93 void nand_init_ll(void)

 94 {

 95     int TACLS = 3;

 96     int TWRPH0 = 7;

 97     int TWRPH1 = 7;

 98     int i = 0;

 99     //配置gpio

100 //    GPACON = (GPACON &~(0x3f << 17)) | ( 0x3f << 17);

101     GPACON = GPACON | (0x3f << 17);

102     NFCONF = (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4) | (0 << 0);

103 

104     NFCONT = (0 << 13) | (0 << 12) | ( 0 << 10) | (0 << 9) | (0 << 8) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 1) | (1 << 0);

105 

106     nand_reset_ll();

107 }

108 

109 #if 0

110 int nand_write_ll(void)

111 {

112     int i = 0x90000;

113     unsigned char j = 0;

114     NAND_CHIP_ENABLE; //选中Nand片选

115     NFCMD = 0x80;

116 

117     NFADDR = 0x00;

118     NFADDR = 0x00;

119     NFADDR = i & 0xFF;

120     NFADDR = (i >> 8) & 0xFF;

121     NFADDR = (i >> 16) & 0xFF;

122     for(j = 0; j < 100;j++);

123 

124 

125     NFCMD = 0x10;

126     nand_wait_ll();

127 

128     for(j = 0 ; j < 100; j++)

129     {

130         NFDATA = j;

131     }

132     NFCMD = 0x10;

133     nand_wait_ll();

134 

135     NAND_CHIP_DISABLE; //取消片选信号

136     return 0;

137 }

138 #endif

139 

140 static void write_addr(unsigned int addr)

141 {

142     int col,page,i;

143     col = addr & NAND_BLOCK_MASK;

144     page = addr & NAND_SECTOR_SIZE;

145 

146     NFADDR = col & 0xff;

147     for(i = 0; i < 10; i++);

148     NFADDR = (col >> 8) & 0x0f;

149     for(i = 0; i < 10; i++);

150 

151 

152     NFADDR = page & 0xFF;

153     for(i = 0; i < 10; i++);

154     NFADDR = (page >> 8) & 0xFF;

155     for(i = 0; i < 10; i++);

156 

157     NFADDR = (page >> 16) & 0x01;

158     for(i = 0; i < 10; i++);

159 }

160 

161 static nand_read_page_ll(unsigned char *buf,unsigned long pageaddr)

162 {

163     int i = 0;

164     NAND_CHIP_ENABLE; //选中Nand片选

165 

166     //发出READ0指令

167     NFCMD = 0;

168 

169     //对Nand进行寻址

170     NFADDR = 0x00;

171     NFADDR = 0x00;

172     NFADDR = pageaddr & 0xff;

173     NFADDR = (pageaddr >> 8) & 0xff;

174     NFADDR = (pageaddr >> 16) & 0xff;

175 

176     NFCMD = 0x30;

177     nand_wait_ll();

178         

179     for(i=0; i < NAND_SECTOR_SIZE; i++)

180         buf[i] = NFDATA;

181 

182     NAND_CHIP_DISABLE; //取消片选信号

183 }

184 

185 int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)

186 {

187     int pageaddr = 0;

188     for(pageaddr = 0; pageaddr < 100;pageaddr++)

189     {

190         nand_read_page_ll(buf,pageaddr);

191         buf += NAND_SECTOR_SIZE;

192     }

193     return 0;

194 }

195 


写好了nand_flash驱动之后,我们在start.S中调用,将u-boot自身,从nandflash读到sdram中。


 1     bl nand_init_ll     /*调用nandflash初始化函数*/

 2 

 3     ldr r0, =TEXT_BASE  /*指定uboot在内存中的地址,这个宏定义在board/xinna2440/config.mk中,默认是0x33f80000*/

 4     mov r1, #0x0  /*从nandflash的0地址读取*/

 5     mov r2, #0x30000  /*读取长度*/

 6 

 7     bl nand_read_ll    /*开始循环读取*/

 8     tst r0, #0x0  /*判断函数返回值*/

 9     beq ok_nand_read

10 

11 bad_nand_read:

12     loop2: b loop2  /*读取出错,死循环*/

13 

14 ok_nand_read:

15     mov r0,#0

16     ldr r1,=TEXT_BASE

17     mov r2,#0x400

18         /*读取成功,以下代码用于校验内存数据和sram中的数据是否一样*/

19 

20 go_next:

21     ldr r3, [r0], #4

22     ldr r4, [r1], #4

23     teq r3, r4

24     bne notmatch

25     subs r2, r2, #4

26     beq stack_setup

27     bne go_next

28 

29 notmatch:    /*数据不一致,死循环*/

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

相关文章

    机顶盒遥控接收头_数字电视与网络机顶盒应用的区别;遥控红外线接收头和机顶盒接收头其实没有很大的区别,现在很多的红外接收头都是在不同产品上可以通用的,只要红外接收头的工作电压、载波频率、波长一样,更主......
    机顶盒怎么选择?如何区分IPTV&OTT?;随着智能电视和机顶盒行业的发展,电视又重新回到了客厅娱乐的中心,我们不仅可以快进、暂停、点播选择自己喜欢的内容,还可以和家人一起玩智能游戏、购物......
    SC1281可用于卫星机顶盒,采样频率10Msps~3Gsps;卫星数字电视机顶盒是将卫星信号接收天线高频头送出的第一中频信号,进行信道解码和信源解码后,把数字信号还原至压缩前的形式,再经D/A转换......
    Trident Microsystems获得CEVA DSP内核授权;Trident Microsystems获得CEVA DSP内核授权,用于其机顶盒和数字电视产品线,全球......
    消费类应用机顶盒设计;机顶盒(调谐器盒)接收和转换电视广播信号,例如地面广播(数字和模拟)、有线电视广播和卫星广播,因此可以在传统的模拟电视机上观看。特别是,随着 2011 年终......
    九联科技发布搭载开源鸿蒙 OpenHarmony 3.1 的机顶盒;OpenHarmony 开源项目是开放原子开源基金会 (OpenAtom Foundation) 孵化......
    看智能电视 你选哪款APP?——视频播放软件大集合; 从前,电视播什么用户看什么,大家没有太多选择。但如今智能电视的出现,为大众带来有别于有限数字电视接收机(机顶盒)的、丰富......
    中兴通讯全系列机顶盒产品亮相巴西 Futurecom 通信展; 近日,一年一度的 Futurecom 通信展在南美最大城市圣保罗隆重举办。这是南美洲最大规模、最具权威性的电信展览会,汇聚......
    机顶盒嵌入式CPU;嵌入式CPU是机顶盒的心脏,当数据完成信道解码以后,首先要解复用,把传输流分成视频、音频,使视频、音频和数据分离开,在机顶盒专用的CPU中集成了32个以上可编程PID滤波器,其中......
    LoRa/UWB/GNSS协议。这些芯片天线结构紧凑、经济高效、开箱可用,符合RoHS指令,是安装在PCB上的SMT。这些天线非常适合用于IoT应用、医疗设备、机顶盒......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>