基于mini2440 的 bootloader 设计 ---- 5、内存初始化

来源:互联网 发布:淘宝店铺行业怎么改 编辑:程序博客网 时间:2024/05/16 14:10
     

开发环境:

               电脑系统:RedHat Enterprise Linux6   kernel version : linux-2.6.32

               交叉工具链:arm-linux-xxx4.3.2 

               开发板版本:mini2440 S3C2440处理器  64M SDRAM   256M nand flash


     前一篇文章介绍了S3C2440 CPU的核心初始化,即:

      1、设置异常向量表
      2、设置cpu为svc32模式
      3、关闭看门狗
      4、关闭中断
      5、时钟初始化
      6、关闭MMU和caches

      至此,CPU已经可以正常工作并开始控制外设,但是外设的工作还得经过初始化的阶段,从这一篇文章开始我们的视线开始转向板载的外设资源。

      今天将介绍内存的初始化。事实上内存芯片是被CPU的存储控制器直接控制的,CPU核对外界的芯片“一无所知”,它只是给出地址或者数据,至于访问的是什么芯片,全部由存储控制器完成。比如CPU内核发出一个指令要求写数据到某某地址,它根本不知道目的地址是位于内存还是网卡或是其他芯片。他仅仅给出地址和数据,解析的工作由存储控制器完成。也就是说内存芯片的初始化是不存在的,内存初始化本质上就是初始化CPU 芯片里的存储控制器,而初始化CPU里的控制器无非就是初始化各种寄存器。这实际已经把代码的工作内存清晰的列了出来。但是在真正编码之前还是要对内存芯片进行一定的了解。

     一、背景知识:

    1、内存芯片内部存储结构介绍

        还是配图说明更清晰:


     上图是笔者开发板上内存芯片的内部存储结构,可以看出整个内存芯片是由4个Bank 组成,分别是Bank0~Bank3,每个Bank 的大小都是4M*16bit,因此整块内存芯片的容量就是:4M*16bit *4Bank = 256M bit = 32M Byte。每个Bank 的结构就如同一个矩阵,需要有行地址和列地址才能确定最终地址。因此可以看出内存芯片的访问是分三次进行的,首先给出bank 信号,然后给出Row(行)信号,最后给出Colum(列)信号,当地址信号接收完成以后内存芯片从数据端口给出数据。

注意:这里地址线共有13根,外加两根bank信号线。其中Row使用A0~A12、Colum 使用A0~A8作为地址线。笔者mini2440开发板的原理图如下:



     可以看到,S3C2440的地址线共有ADDR0~ADDR26 共27根(寻址128M),出去没使用到的ADDR26,还剩下26根地址线,但是内存芯片的地址线共有13根,外加bank选信号2根(共32M),怎么样都不可能正常连接。事实上,本人的开发板内存是64M的(两块32M的内存芯片组成),如下图,



      对比两个图可以看出,两块内存芯片的地址线都连接在CPU的ADDR2~ADDR14上,而Bank信号连接在ADDR24和ADDR25上,两块内存芯片共32根,一块内存芯片的数据线连在CPU数据线的低16位,另一块连在高16位,这样就组成了32位数据宽度的数据线。可以想象CPU读写数据的过程:CPU核读数据时,先给出地址,存储控制器分析该地址,如果是内存地址,则将该地址分解成bank信号、Row信号、Colum,先通过ADDR24、25给出bank信号,这样两个芯片都拿到一个bank选信号,然后是Row信号、Colum。当CPU(存储控制器发出)发出所有的地址信息后,两个内存芯片也拿到了一个完整的地址信息,然后每块内存芯片按照地址信息从地址中取出16位的数据,送到数据线上,当两片内存芯片都给出自己的数据后,CPU也就拿到了一个32位的数据,然后传给CPU核。写数据的过程大致一样,这里不再赘述。

      以上读写数据的过程只是笔者根据芯片的资料以及连线情况做出的假设,并未作出严格的考证。

     二、代码实现

         介绍完内存芯片的资料以及连线情况以后就可以进入编码初始化存储控制器的阶段,初始化存储控制器实际上就是要初始化各种寄存器,让存储控制器能够完美的运行起来。寄存器的情况在S3C2440手册上有详细的介绍,这里就不一一列举。下面是本人的初始化存储控制器的代码片段:


     

      以上就是今天的内容,初始化内存控制器。完整工程代码位于:点击打开链接




1 0