S3C2440 开发板实战(2):start.S初认识 + SDRAM配置 + 重定位

发布者:蓝天飞行最新更新时间:2022-07-18 来源: csdn关键字:S3C2440  start  重定位 手机看文章 扫描二维码
随时随地手机看文章

1、看门狗部分

废话不多说,直接开始配置,首先就是要关闭暂时不使用的看门狗,找到看门狗的寄存器:WTCON,将其第0位置0,即禁用看门狗,即:


# define pWTCON    0x53000000    //WTCON地址

 

ldr    r0,    =pWTCON

mov    r1,    #0x0

str    r1,    [r0]    //关闭看门狗


2、时钟部分

在S3C2440中有三种时钟频率,分别为FCLK, HCLK, PCLK,分别控制不同种类的外设,在时钟树中可以进行查找,这里不做过多赘述,在以后的博客中有应用。


从芯片手册中查找FCLK, HCLK, PCLK 的最高频率,在范围内我们选择设置FCLK = 400MHZ, HCLK = 100MHZ, PCLK = 50MHZ (TF : TH : TP = 1 : 4 : 8)为例进行设置初始化时钟,看芯片手册的时钟树如下图所示:

OSC可以理解为我们的晶振频率,从开发板的原理图上可以看出为12MHZ。


时钟信号通过OM[3 : 2]( 外接引脚 GND )进行时钟源选择,即设置OM[3, 2] = [0, 0],此时刚上电时FCLK频率等于晶振频率,然后进入lock time,此时,CPU暂停工作,在lock time (该段时间是为稳定输出新的FCLK)过后CPU继续工作,CPU时钟的主频率为设置的FCLK。


为保证CPU能够在启动后一定能发送设置的FCLK信号,所以将FCLK设置为最大值:


# define LOCKTIME    0x4C000000 

 

ldr    r0,    =LOCKTIME

ldr    r1,    =0xffffffff

str    r1,    [r0]

先不看控制USB部分(UPLL)直接看MPLL部分。时钟树中时间信号通过锁相环(PLL)生成400MHZ的FCLK。其中关于MPLL寄存器设置方法如下:

然后通过查找数值表(也可以手算,在手册中有公式),由Input Frequency = 12MHZ,Output Frequency  = 400MHZ得到MDIV, PDIV, SDIV的参数值,并写入寄存器中:


# define MPLLCON    0x4C000004    //MPLLCON地址

 

ldr    r0,    =MPLLCON

ldr    r1,    = ((92 << 12) | (1 << 4) | (1 << 0))    // MDIV = 92  PDIV =1  SDIV = 1

str    r1,    [r0]                //写入寄存器

时钟树通过参数HDIVN, PDIVN对FCLK进行分频操作得到可操作进行外设操作的时钟HCLK, PCLK,设置分频系数的寄存器为CLKDIVN: 


# define CLKDIVN    0x4C000014 

ldr    r0,    =CLKDIVN    

ldr    r1,    =((10 << 1) | (1 << 0))    // HCLK = FCLK / 4

                                         // PCLK = HCLK / 2

最后一步由于设置的HDIVN寄存器不等于0,所以需要设置CPU处于异步状态,这里涉及到协处理器的命令(我也不懂哈哈哈),就按照手册中的来编(chao)写就行了。


3、代码重定位

这里先要讲一讲,由于nor flash在运行程序时,是可读不可写的,所以如果程序中有变量储存在 .bin文件中时,该变量不可被改变,即使在程序中对其进行修改。所以我们需要对代码进行重定位到SDRAM中,然后才能对其全局变量进行修改。所以首先应该讲下关于SDRAM的初始化配置:


3.1. SDRAM

由于在start,S程序中只要对SDRAM进行初始化配置,这样就能够对代码进行重定位,所以本章节博客只对SDRANM的初始化程序进行编写以及一些基本操作。


S3C2440中可以支持很多的存储单元,是通过地址对其进行区分的:

内存控制器通过识别不同的地址发出不同的片选信号(0信号低电平有效)。现针对SDRAM分析,2440外设置的是64M的SDRAM,需要对其进行设置寄存器,其SDRAM可以理解为3维的存储空间,bank * row * col,所以大体过程是由CUP发出地址,经过内存控制器转换成row, col, bank信号(为减少pin)


------------------------------------------------------------------------------------------------------------------------------------------------------


既然使用SDRAM就要和CPU说清楚这是个啥类型SDRAM,毕竟人家也是按需办事,所以配置寄存器BWSCON!

ST6:首先来看看芯片手册这么一句话:“nBE[3:0] is the 'AND' signal nWBE[3:0] and nOE”,即nBE是nWBE和nOE的“与”信号,所以nBE是字节选通信号(读+写),nWBE是读字节选通信号。


由于在进行SDRAM操作的时候只需要在写入的时候需要选择比如说32位中的前4位,输出时候把全部的输出(这是韦老师讲的,这块我也不了解,以后填坑把),所以置0.


WS6:wait的使用时因为有些质量比较差的储存芯片的反映速度没那么快,你叫他半天不理你和痴呆似的,需要等待他就秒,就是这个道理。开发板上的SDRAM比较好所以不等待。置0


SW6:由JZ2440是由两片SDRAM组成起来的32位SDRAM,所以应该选择10


一般会把CS7设置成CS6(也是SDRAM)但是没有使用它。


所以设置BWSCON = 0x22000000;


------------------------------------------------------------------------------------------------------------------------------------------------------


接着设置寄存器BANKCONn,和BWSCON一样,同时设置CS6和CS7。

可以看出[4 : 14]位都不需要我们设置!而且MT很清楚就知道应该置“11”,接着就是[0 : 3]位的配置。


Trcd的值是芯片的参数,根据HY57V561620F(L)T(P) 芯片手册:

为了和时钟频率对应,取20ns。即2 CLOCKs,将[3 : 2]置"00"


继续查看芯片手册:


明显Column address number  = 9,所以设置[1 : 0]为“01”。


所以设置寄存器


BANKCON6 = 0X18001;

BANKCON7 = 0X18001;

------------------------------------------------------------------------------------------------------------------------------------------------------


在2440芯片手册往下拉继续配置寄存器(我也觉得麻烦,没办法继续走)。


接着就是REFRESH寄存器,这个寄存器作用就是使SDRAM自动刷新,这是一个内部的自动操作。由于SDRAM要不断进行刷新(Refresh)才能保留住数据(储存体中电容的有效保存期有限),因此它是SDRAM最重要的操作。这么重要的参数,咋们肯定去SDRAM芯片手册中进行查找啦(保有),首先看看寄存器是怎么配置的:


REFEN:使能没得跑置“1”。


TREFMD:选择自刷新(SR)和自动刷新(AR)。对于AR,SDRAM内部有一个行地址生成器(也称刷新计数器)用来自动的依次生成行地址。由于刷新是针对一行中的所有存储体进行,所以无需列寻址。对于SR,在发出AR命令时,将CKE置于无效状态,就进入了SR模式。此时不再依靠系统时钟工作,而是根据内部的时钟进行刷新操作。在SR期间除了CKE之外的所有外部信号都是无效的(无需外部提供刷新指令),只有重新使CKE有效才能退出自刷新模式并进入正常操作状态。


所以我们选择AR模式对其进行数据的刷新。置“0”默认值。


Trp: 废话不多说直接查芯片手册

老道理,取整 2倍CLOCK。[21 : 20]为“00”


Tsrc:这个就比较特殊了。芯片手册没有嘿嘿。再看看描述中的式子。Trc = Tsrc + Trp.那这么说找到Trc就是我们的目标!那又回到最初的起点,开查芯片手册!就在Trp的上边。取整取70ns,大一点没坏处!Tsrc = 70 - 20 = 5*CLOCK ---> [19 : 18] 置“01”。


Refresh Counter :这个就是最重要的刷新频率了。这参数就放在SDRAM芯片手册的前面几面。

果然找到Refresh period = 64 / 8192 ms,带入公式中得到

  frac{64}{8192} * 10^{-3}=frac{left ( 2^{11}-RC+1 right )}{10^{8}}

由于时钟周期为7.8us,且时钟周期为HCLK = 1000MHZ,Refresh = 1269;


综上所述,REFRESH = 0x8404f5。


------------------------------------------------------------------------------------------------------------------------------------------------------


第四个寄存器BANKSIZE,上图!(半夜两点的我已经不知疲倦)

BK76MAP:这个简单,开发板配套的SDRAM容量为256Mb,注意这里是小b,所以容量大小为256/8 = 32MB,由于外设搭载两片SDRAM,所以容量为64MB。置[2 : 0] ="001"


SCKE_EN:断电模式启用 (以后填坑,先开先)


SCLK_EN:推荐值(以后填坑,先开先)


BURST_EN :  启用突发操作。(以后填坑,先开先)


所以BANKSIZE = 0x000000b1


-----------------------------------------------------------------------------------------------------------------------------------------------------------


最后一个寄存器,MRSRBn 

这个寄存器特点:简单!有fixed值就选fixed值!


唯一需要选择的是CL值,一看诶。芯片手册上边查就行了,这个值的意思是由于在读SDRAM时需要发出:bank row col地址,所以需要等一会儿才有数据发回来。所以在芯片手册中可以查到CL=2或者3,这个值设置后回发送至SDRAM中的MR寄存器,以后在2或者3clock时刻返回数据。所以我们设置为2clock 即  =》“010”


所以MRSRB6 = 0x20; MRSRB7 = 0x20; 


-----------------------------------------------------------------------------------------------------------------------------------------------------------


综上所述,对于SDRAM的初始化函数程序如下所示


#include "s3c2440_soc.h"

 

void sdram_init(void)

{   

   BWSCON = 0x22000000;

   BANKCON6 = 0x18001;

   BANKCON7 = 0x18001;

   REFRESH  = 0x8404f5;

   BANKSIZE = 0xb1;

   MRSRB6   = 0x20;

   MRSRB7   = 0x20;

}


3.2. 判断设置是nor flash启动还是nand flash启动

这一段代码主要是基于NOR flash 可读不可写,然而NAND flash是可读可写的特性,所以可以通过对某一地址进行写数据对其进行判断,但如果是NAND falsh启动的话则会破坏内存,所以还需要保护数据


mov    r1,    #0   

ldr    r0,    [r1]    // 保存数据

str    r1,    [r1]    // 写入数据

ldr    r2,    [r1]    // 读出数据

cmp    r1,    r2      // 如果相等 Z = 1

ldr    sp,    =0x40000000 + 4096   //NOR启动

moceq  sp,    #4096   // NAND启动

streq    r0,    [r1]    //恢复数据

但是对于NOR flash启动的u-boot,他就没有管那么多了。反正他要使用NOR启动,在Start.S文件中使用以下代码,区别就是破坏了NAND flash部分代码


ldr sp, =4092

ldr r0, =0x12345678

str r0, [sp]

ldr r1, [sp]

cmp r0, r1

ldrne sp, =0x40000000+4096

bl clock_init


3.3. 代码重定位

首先用XXH查看dis文件(返回编码文件)。(该文件的程序里面包括了初始化的全局变量和未初始化的全局变量。


用VIM打开dis文件,/搜索关键词:Disassembly of section 查找到程序数据类型包括:


.text、.rodata、.data、,bss、.comment等等


其中看源文件的文件大小可以知道 .bss段是不在bin文件的内容中的这个段包括了未初始化的全局变量,.data段是在bin文件范围中包括了已经初始化的全局变量。这里有两种转移代码的方式:①把需要改变的部分移至SDRAM,②把全部程序移至SDRAM。我们选择第二种进行移动(链接脚本比较简洁)。所以应该把.data的部分进行拷贝。


所以这个时候就要使用链接脚本 *.lds文件,通过查阅Using ld The GNU linker有一下源代码格式:


SECTIONS {

...

secname start BLOCK(align)(NOLOAD) : AT (ldadr)

{ contents } >region:phdr =fill

...

}

start: 起始地址


runtime addr:运行时的地址


relocate addr:重定位的地址


AT(ldadr) Load Addr:加载地址  可以省略不写


LoadAddr = runtime addr 如果没有加AT,它的的加载地址就等于链接时的起始地址


以实例来进行说明:


sdram.lds

 

SECTIONS

{

    . = 0x30000000;              //设置当前地址为SDRAM首地址

 

    . = ALIGN(4);                //向四取整

    .text      :

    {

      *(.text)                   //Load Addr = Routime Addr

    }

    . = ALIGN(4);                // 紧接着.text文件排放              

    .rodata : { *(.rodata) }

    . = ALIGN(4);

    .data : { *(.data) }

    . = ALIGN(4);

    __bss_start = .;

    .bss : { *(.bss) *(.COMMON) }

    _end = .;

}

/* 重定位text, rodata, data段整个程序 */

    mov r1, #0

    ldr r2, =_start         /* 第1条指令运行时的地址 */

    ldr r3, =__bss_start    /* bss段的起始地址 */

 

cpy:

    ldr r4, [r1]             //r1 --> r2

    str r4, [r2]

    add r1, r1, #4           //循环4次 (16byte/4byte)

    add r2, r2, #4

    cmp r2, r3

    ble cpy

 

 

    /* 清除BSS段 */

    ldr r1, =__bss_start

    ldr r2, =_end

    mov r3, #0

clean:

    str r3, [r1]

    add r1, r1, #4

    cmp r1, r2

    ble clean

注:


* ldr: 这里我们可以进行ldrb(1byte)或者使用ldr (4byte),由于sdram是16byte的,所以使用ldr函数能够极大的减少访问SDRA的次数:、


①原来:读ldrb执行16次指令,并且访问16次SDRAM;写strb执行16次,并访问16次SDRAM


②现在:读ldr执行4次指令,并且访问8次(我也很迷惑),写str执行4次,并访问4次SDRAM(每次读出四字节)


*写程序:在写程序中会发出地址加上DPM,把感兴趣的对应写入,对应的是SDRAM配置中的写使能


*.bss段:由于bss段数据都是未初始化,都是0,但是转移后的位置可能存的不是0数据,所以应该对其进行初始化置“0”


* 向四取整:由于ldr的操作是四个字节的赋值,但是我们的地址并不是四字节对齐,所以会进行向四取整


实例:


命令存放地址     3 0 0 0 0 0 0 2 ( 2 < 4)


真实存放地址     3 0 0 0 0 0 0 0 


所以应对方法也是对当前地址进行向四取整即:


. = ALIGN(4);

这样命令存放的地址就变为:


实例:


命令存放地址     3 0 0 0 0 0 0 4 ( 4 >= 4)


真实存放地址     3 0 0 0 0 0 0 4


这就是start文件初认识了!


关键字:S3C2440  start  重定位 引用地址:S3C2440 开发板实战(2):start.S初认识 + SDRAM配置 + 重定位

上一篇:S3C2440 开发板实战(3):编译概念 + LED点亮闪烁
下一篇:JZ2440开发板几种烧写程序的方法

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

S3C2440⑥ | UART实验
实验 —— UART数据收发实验 1. 看原理图确定UART硬件如何连接 由原理图可以看出,JZ2440开发板上将三个串口全部引出,其中UART0设置了板载的USB转串口电路,只需连接板上的USB口就可以,所以接下来我们使用UART0进行数据收发实验。 2. 看芯片手册设置引脚复用功能(GPHCON)、开启片内上拉(GPHUP) 由原理图可以看出,UART0的引脚是: GPH2:TXD0 GPH3:RXD0 这两个引脚都是普通的GPIO口,所以需要设置引脚复用功能,作为串口UART0的引脚: 在【嵌入式系统通信协议②】EIA RS-232C串口总线标准(https://blog.csdn.net/Mculover6
[单片机]
<font color='red'>S3C2440</font>⑥ | UART实验
从0开始学Keil下的S3C2440裸机开发-2使用外部SDRAM
和使用内部RAM一样,关键设置分散加载文件,同时设置JLINK初始化配置文件。 1、新增工程配置组。 2设置分散加载组 3设置ini文件 Ext_Ram内容: FUNC void SetupForStart (void) { // o Program Entry Point PC = 0x30000000; } FUNC void Init (void) { _WDWORD(0x4A000008, 0xFFFFFFFF); // Disable All Interrupts _WDWORD(0x53000000, 0x00000000); // Disable Watchdog Timer
[单片机]
从0开始学Keil下的<font color='red'>S3C2440</font>裸机开发-2使用外部<font color='red'>SDRAM</font>
S3C2440 Linux驱动移植——NAND驱动
1. 修改分区表 打开文件arch/arm/plat-s3c24xx/common-smdk.c,修改mtd_partition结构体数组。 修改后如下: view plain copy static struct mtd_partition smdk_default_nand_part = { = { .name = Uboot , .size = 0x00040000, .offset = 0x00000000, }, = { .name = K
[单片机]
<font color='red'>S3C2440</font> Linux驱动移植——NAND驱动
S3C2440 存储器控制器分析
首先说一下,S3C2440 存储器空间并不包括NAND FLASH ,NAND FLASH只是一个外设而已。 S3C2440存储器控制器的寻址范围是0~0x3fff ffff,共1G。这1G空间分为8个BANK,BANK0~BANK7。 在产品开发阶段,一般使用BANK0控制NOR FLASH,BANK6控制SDRAM;对于成品,则会去掉NOR FLASH,而将固件放在NAND FLASH上,SDRAM不变。 对于代码存储,如NOR FLASH,是没有必要访问到具体字节;而对于SDRAM,因为可能保存有字节变量,必须得支持访问到字节。这里就说一下,在32位总线宽度下,存储器控制器是如何访问SDR
[单片机]
STM8S103F3实现串口中断接,中断发功能
一、首先进行UART1初始化 /*USART1 config*/ void USART1_Init(void) { /*Uart1*/ UART1_CR1=0x00; UART1_CR2=0x00; UART1_CR3=0x00; // 设置波特率,必须注意以下几点: // (1) 必须先写BRR2 // (2) BRR1存放的是分频系数的第11位到第4位, // (3) BRR2存放的是分频系数的第15位到第12位,和第3位到第0位 // 例如对于波特率位9600时,分频系数=2000000/9600=208 // 对应的十六进制数为00D0,BBR1=0D,BBR2
[单片机]
对LCD的操作(S3C2440
先简单介绍下LCD的操作原理。 如下图的LCD示意图,里面的每个点就是一个像素点。 想象有一个电子枪,一边移动,一边发出各种颜色的光。这里有很多细节问题,我们一个一个的梳理。 电子枪是如何移动的? 答:有一条CLK时钟线与LCD相连,每发出一次CLK(高低电平),电子枪就移动一个像素。 颜色如何确定? 答:由连接LCD的三组线:R(Red)、G(Green)、B(Blue)确定。 电子枪如何得知应跳到下一行? 答:有一条HSYNC信号线与LCD相连,每发出一次脉冲(高低电平),电子枪就跳到下一行。 电子枪如何得知应跳到原点? 答:有一条VSYNC信号线与LCD相连,每发出一次脉冲(高低电平),电子枪就跳到原点。
[单片机]
三星S21被曝全系换成Exynos 1000:内建AMD GPU
三星是当下为数不多可以自研移动SoC芯片的手机厂商,Exynos已经成熟迭代很多年的时间。虽然三星也自持全网通基带技术,可其用于美版、国行等旗舰Galaxy往往会选择高通骁龙平台。   不过,有国外爆料人透露,他得到消息,三星计划在Galaxy S21/30这一代产品上全系换装Exynos 1000系列处理器。   只是提到的原因说来也有些尴尬,即骁龙875过于昂贵,使用Exynos 1000可以减少成本,在保持售价和前代不变甚至小幅下调的前提下,争取利润。   还有一点是,骁龙875性能也太强了,过溢……   消息还得到另一位国外爆料人的肯定,据悉,Exynos 1000系列将基于5nm工艺打造,GPU来自三星与AMD R
[手机便携]
三星全球最薄平板S2图片曝光!传仅5.5mm、6月亮相
    南韩三星电子(Samsung Electronics)要在平板电脑市场挑战苹果 (Apple)霸权的举动越来越积极,,传出也将在6月份发表新款旗舰级平板电脑产品「Galaxy Tab S2」,而据爆料新星@OnLeaks透露,Tab S2厚度仅有5.5mm,将成为全球最薄的平板产品。 日本网站Gadget通信报导,@OnLeaks 10日透过Twitter公布了据称是9.7吋版Tab S2的渲染图片( 图片按此 ),且据@OnLeaks指出,Tab S2采用Galaxy S6风格的外框设计,尺寸为237.17x169.58 x5.5mm。@OnLeaks表示,上述Tab S2尺寸并不是最终版规格,因此Tab S2最终
[手机便携]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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