nand flash相关

2023-06-13  

关于nandflash的说明,请参考其他。


现在先贴出来韦东山先生的代码,作我学习之用。


 1 @************************************************

 2 @ File:head.s

 3 @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行

 4 @************************************************  

 5   

 6 .text

 7 .global _start

 8 _start:

 9            @函数disable_watch_dog, memsetup, init_nand,      nand_read_ll在init.c中定义

10             ldr     sp, =4096               @设置堆栈 

11             bl      disable_watch_dog       @关WATCH DOG

12             bl      memsetup                @初始化SDRAM

13             bl      nand_init               @初始化NAND Flash

14 

15             @将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM中

16                                             @nand_read_ll函数需要3个参数:

17             ldr     r0,     =0x30000000         @1. 目标地址=0x30000000,这是SDRAM的起始地址

18             mov     r1,     #4096           @2.  源地址   = 4096,连接的时候,main.c中的代码都存在NAND Flash地址4096开始处

19             mov     r2,     #2048           @3.  复制长度= 2048(bytes),对于本实验的main.c,这是足够了

20             bl      nand_read               @调用C函数nand_read

21 

22             ldr     sp, =0x34000000         @设置栈

23             ldr     lr, =halt_loop          @设置返回地址

24             ldr     pc, =main               @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转

25 

26 halt_loop:

27             b       halt_loop

28  


上面的代码的作用很明显,现在主要说明地址相关的东西;


ldr     sp, =4096               @设置堆栈   首先上电后4k代码会自动拷贝到steppingstone里面,disable_watch_dog,memsetup等函数都是在这4k范围里面。


后面的链接脚本如下:


1 SECTIONS { 

2   firtst      0x00000000 : { head.o init.o nand.o}     @在nand flash里面地址为0x0000_0000初存放head.o,init.o,nand.o等

3   second     0x30000000 : AT(4096) { main.o }          @在4096处,注意此时是4k以外,这个代码就是指出当代码大小大于4k时的处理方法。

4 }                                @可以看到main.o的运行地址是0x3000_0000,说明运行4k以后的代码需要复制到sdram里面执行。


5  


上面说明main函数是在刚才提到的4k范围以外。所以head文件里面会有将4096(4k)的main函数编译出来的东西拷贝到3000_0000也就是sdram的地方。


这个在以后程序比较大的时候基本是比较通用的函数,所以一定得花时间搞明白。上面简单的说明来地址映射方面的问题。


再看init.c,这个文件只是关闭看门狗和初始化sdram:


 1 /* WOTCH DOG register */

 2 #define     WTCON                (*(volatile unsigned long *)0x53000000)

 3 

 4 /* SDRAM regisers */

 5 #define     MEM_CTL_BASE        0x48000000      //定义寄存器的方法

 6  

 7 void disable_watch_dog();

 8 void memsetup();

 9 

10 /*上电后,WATCH DOG默认是开着的,要把它关掉 */

11 void disable_watch_dog()

12 {

13     WTCON    = 0;

14 }

15 

16 /* 设置控制SDRAM的13个寄存器 */

17 void memsetup()

18 {

19     int     i = 0;

20     unsigned long *p = (unsigned long *)MEM_CTL_BASE;

21 

22     /* SDRAM 13个寄存器的值 */

23     unsigned long  const    mem_cfg_val[]={ 0x22011110,     //BWSCON

24                                             0x00000700,     //BANKCON0

25                                             0x00000700,     //BANKCON1

26                                             0x00000700,     //BANKCON2

27                                             0x00000700,     //BANKCON3  

28                                             0x00000700,     //BANKCON4

29                                             0x00000700,     //BANKCON5

30                                             0x00018005,     //BANKCON6

31                                             0x00018005,     //BANKCON7

32                                             0x008C07A3,     //REFRESH

33                                             0x000000B1,     //BANKSIZE

34                                             0x00000030,     //MRSRB6

35                                             0x00000030,     //MRSRB7

36                                     };

37 

38     for(; i < 13; i++)

39         p[i] = mem_cfg_val[i];

40 }


 上面设置sdram寄存器的方法是用c语言,现在贴出汇编的方法来比较;


 1 memsetup:

 2     @ 设置存储控制器以便使用SDRAM等外设

 3 

 4     mov r1,     #MEM_CTL_BASE       @ 存储控制器的13个寄存器的开始地址

 5     adrl    r2, mem_cfg_val         @ 这13个值的起始存储地址

 6     add r3,     r1, #52             @ 13*4 = 54

 7 1:  

 8     ldr r4,     [r2], #4            @ 读取设置值,并让r2加4

 9     str r4,     [r1], #4            @ 将此值写入寄存器,并让r1加4

10     cmp r1,     r3                  @ 判断是否设置完所有13个寄存器

11     bne 1b                          @ 若没有写成,继续

12     mov pc,     lr                  @ 返回

13 

14 

15 .align 4

16 mem_cfg_val:

17     @ 存储控制器13个寄存器的设置值

18     .long   0x22011110      @ BWSCON

19     .long   0x00000700      @ BANKCON0

20     .long   0x00000700      @ BANKCON1

21     .long   0x00000700      @ BANKCON2

22     .long   0x00000700      @ BANKCON3  

23     .long   0x00000700      @ BANKCON4

24     .long   0x00000700      @ BANKCON5

25     .long   0x00018005      @ BANKCON6

26     .long   0x00018005      @ BANKCON7

27     .long   0x008C07A3      @ REFRESH

28     .long   0x000000B1      @ BANKSIZE

29     .long   0x00000030      @ MRSRB6

30     .long   0x00000030      @ MRSRB7


同样是往这13个寄存器写值。


而main函数只是led的亮灭,这里就不贴出来了


现在主要看nand.c文件。


先贴出来如下:


//===================================我是分解线=============================


//@nand.c


  1 #define LARGER_NAND_PAGE

  2 

  3 #define GSTATUS1        (*(volatile unsigned int *)0x560000B0)

  4 #define BUSY            1

  5 

  6 #define NAND_SECTOR_SIZE    512              @小页

  7 #define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE - 1)     511  0b1_1111_1111

  8 

  9 #define NAND_SECTOR_SIZE_LP    2048         @2k   大页

 10 #define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)    @2047  0b111_1111_1111

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