初始化片外RAM,让程序有更大内存空间

发布者:chaohuangmeitao最新更新时间:2021-10-14 来源: eefocus关键字:TQ2440  初始化  片外RAM  内存空间 手机看文章 扫描二维码
随时随地手机看文章

到目前为止,我们的程序只能使用S3C2440的片内4KB的RAM。这么小的内存空间,显然不能应付实际的应用。是时候使用片外的RAM了,本文将详细介绍片外RAM的初始化过程。


0 ROM,RAM,SRAM,DRAM,SDRAM傻傻分不清

作为软件出身的软男,很难从根本上弄清楚ROM,RAM,SDRAM,SRAM等等的原理,这里我们只要了解基本的特性就可以了。


ROM,NorFlash: 只读内存,掉电不丢失。只读指的是不能通过正常的写入接口写入数据,但是可以通过特殊的烧写逻辑写入。这就意味之,我们的程序可以直接在ROM中执行,但是程序执行时无法在ROM中保存数据。测试表明,写入操作可以执行,但是没有任何效果。TQ2440搭配了2MB的NorFlash ROM,我们的程序烧入ROM后能直接执行,但是由于不能写内存,所以程序功能收到很大限制。为此实验环境选择了从Nandflash启动,应为S3C2440硬件直接会把Nandflash的头4KB数据拷贝到片内的SRAM执行。


SRAM:(Static RAM)可读写,掉电丢失数据,但是无需定期电路刷新。这种东西非常昂贵,集成度不高,性能也相当好。多用于CPU的cache等关键场合。S3C2440A片内集成了4KB的SRAM,已经相当不错了。到目前为止,我们的实验程序都是运行在这块SRAM上的。


DRAM:(Dynamic RAM)可读写,掉电丢失数据,而且必须定期充电刷新。这种RAM相对便宜,集成度高,性能较SRAM差点,但是也相当不错了。


SDRAM:(Synchronous DRAM)同步DRAM。首先它是DRAM,只是额外需要同步时钟才能正常工作。这也是TQ2440板子上搭配的主要内存。核心板子上配备了2块,一共64MB。本文的目的就是配置使用着64MB的SDRAM。


1 内存地址的转换全过程

对内存的操作是所有程序的最基本需求,而对内存进行寻址是所有内存操作的前提。高级编程语言里,一般会使用各种符号名来代表内存地址,例如如下C语言代码:


int main()

{

   int a=10;

   printf("hellon");

}


main,a,printf都是符号,它在编译后会被实际的内存地址取代。C语言提供了直接操作内存地址的强大工具—指针,这也是C语言能在底层开发领域统治多年的法宝。


int *pa = &a;

int *p = (int*)0x00001010;


C语言不仅允许我们获得变量的内存地址,而且允许直接使用内存地址。那么这里的0x00001010地址数据到底是如何对应到内存芯片上的实际物理存储单元的呢?这种对应需要2个步骤:


1.1 从虚拟地址到物理地址

上面代码中的内存地址数据 0x00001010是核心CPU看到的地址,被称作虚拟地址。对于低端的单片机,这个虚拟地址直接作为物理地址发送到地址总线。而现代高级CPU内部一般都集成了一个被称作MMU的内存管理单元,CPU核心发出的虚拟地址首先进入MMU,MMU负责把虚拟地址转换为地址总线上的物理地址,然后发送到地址总线。


虚拟地址—(MMU)—物理地址


MMU是Windows,Linux等操作系统运行的基础,也是多进程实现的基础。S3C2440A的ARM核心也继承了MMU,只是默认MMU是不启动的,这就意味着虚拟地址和物理地址完全一样。我们的实验程序也没有启动MMU,所以在程序中使用的内存地址可以直接理解成物理地址。


1.2 从物理地址到内存存储单元的行列地址和片选信号

物理地址是一个线性地址,一般不能够直接用来寻址内存单元。中间需要通过内存控制器来把物理地址转换成内存单元的行列地址以及片选信号。


物理地址—(内存控制器)—行列地址及片选信号


总之,只要不同的物理地址最终被映射到不同的内存单元就满足硬件设计的要求,而不管CPU地址总线,CPU引脚,RAM芯片引脚到底是如何组合的。如何组合是硬件设计师的工作,我们软件工程师只要使用就可以了。


2 TQ2440的SDRAM硬件配置

2.1 S3C2440内存硬件设计

内存地址相关的引脚共有35个,其中行列地址引脚A26,A25,…A0共27个,片选信号引脚nGCS0,nGCS1,…,nGCS7共8个。可见外部引脚最大寻址空间为8*2^27,正好是1GB。1GB以上的空间仅供CPU内部寄存器使用。


S3C2440把每一个片选信号对应的空间称作一个BANK,每个BANK大小128M。


2.2 TQ2440开发板SDRAM搭配硬件设计

TQ2440搭配了2片32MB的SDRM,共64MB。这两片内存并联成32位数据宽度供CPU使用。

这里写图片描述

图中看出,每个内存芯片的行列地址有13位,数据宽度为2个字节,这样可寻址:2^13*2 = 64KB。啥?不是每个芯片32MB吗?这里的玄机在于对于SDRAM来说,行列地址共用一组引脚,首先通过A0-A12读取行地址并暂存起来,然后下一个周期还是通过A0-A12读取列地址,然后把行列地址拼装起来成为最后的行列地址。


RAM芯片上还有BA1,BA0两个引脚,这也是单元地址的一部分,叫做LogicalBank,注意这里的Bank和S3C2440的内存空间BANK没有什么关系。内存控制器要只有把物理地址转换为【(BA1,BA0),(A0-A12),片选信号】,并且产生正确的时序才能完成内存单元的寻址。


开发板上SDRAM芯片信号为:LogicalBank大小为4M,共有4个LogicalBank,内存单元大小为16位(2字节),所以单片容量为:4 x 4 x 2 = 32MB。然后两个内存芯片并联后接入BANK6。


如何把物理地址转换为行列地址是内存控制器的工作,这也是初始化SDRAM的重要步骤。


3 S3C2440片外内存初始化方法

从前面的分析,我们知道程序内存地址到SDRAM内存单元地址的整个转换过程为:


虚拟地址---(MMU)---物理地址(内存控制器)---LogicalBank,行列地址,片选信号


目前我们没有启用MMU,也无需配置。现在要做的就是配置内存控制器,使其能够正确地把物理地址转换为行列地址和片选信号。

S3C2440片内集成了完整的内存控制器,我们只需要向相应的控制寄存器写入合适的数值即可完成配置。


2.1 与SDRAM有关的控制寄存器

BWSCON

BANKCON6

REFRESH

BANKSIZE

MRSR6


其中有些时间周期参数的设置依赖于HCLK的值,故需要记住在设置MPLL时产生的HCLK。上篇博文中我们设置的HCLK=200MHz,这个数值太大无法满足设置REFRESH中Tsrc的要求,所以本文实验时同时把HCLK修改成了100MHz,PCLK设置成了50MHz。由于此时FCLK:HCLK不再是1:1而是1:2,所以需要设置CPU的总线模式为异步模式,增加了相关设置代码。


在我们的试验中,FCLK=200MHz,HCLK=100MHz,也就是周期是10ns。


上述寄存器需要设置的值都在源码中了,在此贴出完整的设置代码:


2.2 配置源码

.equ WTCON,     0x53000000

.equ INTMSK,    0x4a000008


/* Fin=12MHz, FCLK=200MHz */

.equ MPLLCON,   0x4c000004

.equ M_MDIV,    92

.equ M_PDIV,    4

.equ M_SDIV,    1


/* Fin=12MHz, UPLLCLK = 48MHz */

.equ UPLLCON,   0x4c000008

.equ U_MDIV,    56

.equ U_PDIV,    2

.equ U_SDIV,    2


/* HCLK=FCLK/2=100MHz, PCLK=HCLK/2=50MHz, UCLK=UPLLCLK=48MHz */

.equ CLKDIVN,   0x4c000014

/*

  if If HDIVN is not 0 and the CPU bus mode is the fast bus mode,

  the CPU will operate by the HCLK

*/

.equ HDIVN,     1

.equ DIVN_UPLL, 0

.equ PDIVN,     1


/* SDRAM */

.equ BWSCON,    0x48000000

.equ BANKCON6,  0x4800001c

.equ REFRESH,   0x48000024

.equ BANKSIZE,  0x48000028

.equ MRSRB6,    0x4800002c

/* BWSCON */

.equ BWSCON_WS6, 0  /* wait status: disable */

.equ BWSCON_DW6, 2  /* data width : 32 */


/* BANKCON6 */

.equ B6_MT,     3   /* memory type: SDRAM */

.equ B6_Trcd,   0   /* Row to Col delay: 2 clocks,(min: 20ns)*/

.equ B6_SCAN,   1   /* Column address number */


/* BANKSIZE */

.equ BANKSIZE_VAL,  0xB1    /* 64MB for BANK7,6 */


/* REFRESH */

.equ REFRESH_ENABLE, 1

.equ REFRESH_MODE,  0

.equ REFRESH_Trp,   0

.equ REFRESH_Tsrc,  1

.equ REFRESH_COUNT, 1268


/* MRSRB6 */

.equ MRSRB6_VAL, 0x30       /* CL: 3 clock (min: 2.5ns )*/


.text

.global ResetEntry

/* interrupt vector */

ResetEntry:

    b ResetHandler

    b ResetHandler

    b ResetHandler

    b ResetHandler

    b ResetHandler

    b ResetHandler

    b ResetHandler

    b ResetHandler


/* The first instruction to run */

ResetHandler:

    /* ----------- disable watch dog-------- */

    ldr r0, =WTCON

    ldr r1, =0x0

    str r1, [r0]


    /* ------- disable all interrupts------- */

    ldr r0, =INTMSK

    ldr r1, =0xffffffff

    str r1, [r0]


    /* -----------set clock---------------  */

    ldr r0, =CLKDIVN

    ldr r1, =(DIVN_UPLL<<3) + (HDIVN<<1) + PDIVN

    str r1, [r0]

    /*switch to asynchronous bus mode*/

.if HDIVN>1

    mrc p15, 0, r0, c1, c0, 0

    orr r0, r0, #0xc0000000

    mcr p15, 0, r0, c1, c0, 0


.endif

    /* set up upll */

 ldr r0, =UPLLCON

    ldr r1, =(U_MDIV<<12) + (U_PDIV<<4) + U_SDIV

    str r1, [r0]

    nop

    nop

    nop

    nop

    nop

    nop

    nop


    /* set up mpll */

    ldr r0, =MPLLCON

    ldr r1, =(M_MDIV<<12) + (M_PDIV<<4) + M_SDIV

    str r1, [r0]


    /* ----------------- set sdram -------------*/

    ldr r0, =BWSCON

    ldr r1, [r0]

    ldr r2, =(1<<26 | 3<<24)

    bic r1, r1, r2

    ldr r2, =((BWSCON_WS6<<26) | (BWSCON_DW6<<24))

    orr r1, r1, r2

    str r1, [r0]


    ldr r0, =BANKCON6

    ldr r1, [r0]

    ldr r2, =((1<<16) | (1<<15) | 0xF)

    bic r1, r1, r2

    ldr r2, =(B6_MT<<15 | B6_Trcd<<2 | B6_SCAN)

    orr r1, r1, r2

    str r1, [r0]


    ldr r0, =REFRESH

    ldr r1, [r0]

    ldr r2, =(1<<23 | 1<<22 | 3<<20 | 3<<18 | 0x7FF)

    bic r1, r1, r2

    ldr r2, =(REFRESH_ENABLE<<23 | REFRESH_MODE<<22 | REFRESH_Trp<<20 | REFRESH_COUNT)

    orr r1, r1, r2

    str r1, [r0]


    ldr r0, =BANKSIZE

    ldr r1, =BANKSIZE_VAL

    str r1, [r0]


    ldr r0, =MRSRB6

    ldr r1, =MRSRB6_VAL

    str r1, [r0]


    /* --------------set statck----------------- */

    ldr sp, =0x34000000  /* must be aligned by 4 bytes */


    /* call C function */

    b Main


.end


4 开始使用片外内存

现在已经可以使用64MB的SDRAM了,这相对于片内的4KB SRAM来说已经相当大了,而且足以可以运行大型软件了。虽然目前我们的程序本身被加载到片内SRAM上运行,但是我们在代码中是可以使用[0x30000000,0x34000000)这个范围的SDRAM内存了。

首先我们可以把堆栈指针SP指向SDRAM中,这样C语言的函数参数和局部变量就自动被放到SDRAM里了。

其次我们可以直接通过C指针直接操作SDRAM的。


3.1 把堆栈设置到片外内存上

ldr sp, =0x34000000


就是这么简单的一条命令,就可以让C程序的堆栈搬迁到SDRAM中。


3.2 在片外内存上读写数据

void Main(void)

{

    led_init();

    int a = 10;

    /* 测试栈是否在SDRAM上 */

    if(((unsigned)&a) > 0x30000000) {

        led_on(2);

    }else{

        led_off(2);

    }

    /* 在SDRAM上直接读写内存*/

    int *pInt = (int*)0x30000000;

    *pInt = 99;

    if(*pInt == 99){

        led_on(1);

    }else{

        led_off(1);

    }

    while(1){

        ;

    }

}


5 下一步:把程序加载到SDRAM中

尽管目前我们可以直接操作SDRAM,但是程序代码本身并没有在SDRAM中运行。为此我们需要写一个loader,把程序加载到SDRAM中。loader可以和程序混合成一个程序,也可以两者分开。如果混合在一起那就是一个完整的能独立启动的程序,例如U-Boot。如果将两者分开,那么必须首先安装loader到NandFlash中,然后启动,通过命令加指定的程序到SDRAM执行。


下一步,将实验NANDFLASH读写操作,从而为代码搬迁做好准备。

关键字:TQ2440  初始化  片外RAM  内存空间 引用地址: 初始化片外RAM,让程序有更大内存空间

上一篇:TQ2440开发板学习纪实(9)--- 利用Undefined异常模拟BLX指令
下一篇:TQ2440开发板学习纪实(3)--- 设置时钟频率,让CPU运行的更快

推荐阅读最新更新时间:2024-11-11 10:21

基于MSP430F5438A的SPI通信来进行SD卡初始化
最近需要做一个数据存储,发现SD卡这一块还不太好弄 现在的单片机有相当一部分还不支持SDIO,比如MSP430(据我所知,如果有支持的型号了还请及时告诉我~),所以只好用SPI通信来进行SD卡的操作,虽然后续涉及到更为复杂的FAT等等,但是首先需要解决的仍然是建立通信的问题。 采用的单片机型号为MSP430F5438A,用了一个开发板。 SPI通信基本例程 例程及解释如下: 鉴于CSDN的Markdown代码高亮做的实在是……唉,这里贴一个容易看的吧: SPI通信代码 SD卡通信方式 以上是给出的例程,SD卡有自己的一套通信方法: 这里引述了: http://elm-chan.org/docs/mmc/mmc_
[单片机]
基于MSP430F5438A的SPI通信来进行SD卡<font color='red'>初始化</font>
U-boot1.1.6移植到TQ2440开发板(下)
这两天在移植u-boot,花了两天完全是因为卡在nandflash里了,关于nandflash下次再写吧,这次记录一下刚刚遇到的一个问题吧。。。呵呵。 u-boot在引导linux启动,需要传递环境变量等配置 设置一些宏定义,在include/configs文件下的配置文件里添加 #define CONFIG_SETUP_MEMORY_TAGS 1 #define CONFIG_CMDLINE_TAG 1 #define CONFIG_INITRD_TAG 1 #defineCONFIG_BOOTARGS noinitrd root=/dev/mtdblock2 init=/linuxrc consol
[单片机]
stm32标准库dma初始化详解
STM32的DMA有三种类型的传输 1.M-M(内存到内存) 2.M-P(内存到外设) 3.P-M(外设到内存) STM32的标准库函数提供了一个STM32的初始化结构体如下; typedef struct { uint32_t DMA_PeripheralBaseAddr;//外设地址 uint32_t DMA_MemoryBaseAddr; //内存地址 uint32_t DMA_DIR; //传输方向 uint32_t DMA_BufferSize; //传输的数据多少 uint32_t DMA_PeripheralInc; //外设地址是否递增 uint32_t DMA
[单片机]
STM32 IO口初始化流程
首先初始化时钟APB2 1.配置输入输出模式和引脚速度(GPIOx_CRL或GPIOx_CRH) 2.读取或写入IO口数据 2.1读取IO口数据(GPIOx_IDR) 2.2写入IO口数据(GPIOx_ODR、GPIOx_BSRR、GPIOx_BRR) 3.锁定IO口数据,直到下次复位(GPIOx_LCKR)
[单片机]
TIMER之pwm应用
TIMER之pwm应用 //TIM3 PWM部分初始化 //PWM输出初始化 //arr:自动重装值 //psc:时钟预分频数 //PB5,TIMER3_CH2 void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; //GPIO 结构体初始化 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //基本定时器结构体初始化 TIM_OCInitTypeDef TIM_OCInitStructure; //output compare 结构体初始化
[单片机]
STM32F107VC 锁相环初始化
AHB与APB的地位相当于PC中的南北桥,是两道独立的片内总线。 AHB:advanced high-performance bus;APB: advanced peripherals bus。 static void SetSysClockTo72(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration --------------------------- SYSCLK 由PLL时钟,外部高速时钟,内部高速时钟获得,最大为72MHz HCLK
[单片机]
关于stm32(cotex-m3)向量表初始化的总结笔记
最近学习lm3s811的时候,看到启动代码发现跟STM32的启动代码有不少区别,然后就开始详细的看启动代码,最后总结出如下几个点,其实并没有本质 上的区别,由于用lm3s811是为了最近的比赛,所以快速的用库进行了开发,就没有对具体TI公司怎么来设计进行细看,所以就以STM32来说。 1,首先STM32启动代码里面 AREA RESET, DATA, READONLY ;由于是Readonly,所以其实是放到了CODE区__Vectors应该就是0了,因为编译器本身分配是从头开始的。 2,而软件仿真时添加__Vectors到Watch1里面观察是x20000688,但是由于其不是变量,所以数值是不可预测的, 这里应
[单片机]
TQ2440国嵌学院gboot-栈的初始化
栈:后进先出的方式 满栈:SP指针指向最后一个入栈的数据 空栈:SP指针指向即将入栈数据的空位置 ARM采用满栈的方式 升栈:SP指针从低地址到高地址 降栈:SP指针从高地址到低地址 ARM采用降栈 ARM采用的是满降栈 栈的主要作为是:保存局部变量 由于我们这里是TQ2440的开发板,开发板的SDRAM为64M,有ARM是降栈的方式,采用最高地址是栈的初始地址,TQ2440的内存的地址是0X30000000,然后加上64M就是最高的内存地址,也就是SP指针指向0X34000000, 代码如下 init_stack: ldr sp,=0x34000000 mov
[单片机]

推荐帖子

GPS原理与应用
介绍卫星导航概念、坐标系、GPS组成、卫星信号、接收机、干扰等内容,给出了许多工程实践知识。领域可能有点偏。GPS原理与应用
linjingui 汽车电子
我是新来的,求大侠指导~
我是一个新手,有c基础,汇编以前也学过,现在想做嵌入式开发,不知道应该学那些东西,希望高手老师们能给我指点具体的学习里程,比如看什么书,先看什么后看什么,谢谢感谢你`~我是新来的,求大侠指导~看操作系统,具体的WINCE/LINUX这些东西上的驱动开发,应用开发吧呵呵光看书是不解决问题的OJT有问题请先GOOGLE,BAIDU有点难度哦以后需再关注,现在先帮你顶一下要做好工程师,必须动手。呵呵呵。引用8楼gooogleman的回复:要做好工程师,必须动手。
lixiyuan999 嵌入式系统
我要为几天之后的电子设计大赛设计滤波器,频率比较高
论坛中的朋友们大家好,为了几天之后的电子设计大赛,我要设计一个矩形性质比较好的,较高频率的带通滤波器。老师提示我用L,C元件和集成运算放大器来设计,但是我接触到的资料都是RC有源滤波器,频率带宽等等条件不太满足,希望能得到各位的帮助。我要为几天之后的电子设计大赛设计滤波器,频率比较高参差放大器!它可以很好地满足所需。
张乡夫 模拟电子
LED无线通信技术 "光照上网"或将实现,中国也参与研究了?
在英国爱丁堡大学任教的德国物理学家哈拉尔德·哈斯13日晚为公众作了一场报告,名为“我的Li-Fi革命”。他说,Li-Fi光照上网利用LED(发光二极管)照明灯以极高频率闪烁形成的脉冲来传输数据,最近的实验表明,单色5毫瓦LED照明灯和接收设备在1米和10米的距离上,数据传输速率可分别达到3.5Gbps和1.1Gbps(1bps为每秒1比特),用不同颜色的光还可以成倍提高数据传输速率。1.哪些因素影响传输速率?接收距离、光的颜色、光线强度2.光照上网有哪些优点?不
qwqwqw2088 LED专区
CC4008 四位二进制超前进位全加器
本文很详细的说明了CC4008四位二进制超前进位全加器的原理和过程CC4008四位二进制超前进位全加器
rain 模拟电子
赵厚麟:运营商如何把握知识产权的运用
IT时代周刊  在中国电信市场上,3G对整个电信市场格局从由“语音时代”向“信息多媒体时代”转换的影响是非常巨大的。运营商需要重新培育自己在业务、服务、综合运营方面的能力,同时也不能忽略在转型过程中所面临的潜在的知识产权问题。  一位参与通信标准制定的专利专家形象地比喻说:“在知识产权方面,现在我们仅仅感受到了在铺设3G道路时‘怎么修路’和‘怎么造车’的专利问题,而对于在这条信息高速公路上运营时‘交通管理’和‘有效配载货物’所涉及到的专利问题,我们还来不及关注,这方面的知识产权问题,对于我
mdreamj RF/无线
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved