s3c2440学习之路-004 区分nand/nor 启动

  1. 原理分析
  2. 主要流程
  3. 源码

硬件平台:jz2440
软件平台:Ubuntu16.04 arm-linux-gcc-3.4.5
源码位置: https://github.com/lian494362816/C/tree/master/2440/005_leds/002

1.原理分析

1.1问题的由来

前面篇文章 https://blog.csdn.net/lian494362816/article/details/84642425 提到了SP的设置,但是当使用nand flash 和 nor flash启动时,2440内部的sram位置是不同的, SP的设置也不同。使用nor flash时,内部sram起始位置为0x40000000, 而使用nand flash时,内部sram起始位置为0x00000000。为了更好的使用,需要让代码区分nand 还是nor启动。总不能准备2份代码, 一份给nor使用,一份给nand使用吧。

在这里插入图片描述

在这里插入图片描述

1.2 解决方法

编程时,可以根据nor flash的特性和2440在使用nand flash启动时的特性来区分是nor 启动还是nand启动。

  1. 如果是nor 启动, 2440会直接从nor flash 去读指令,如果是nand 启动,2440会把nand 前4K的内容拷贝到sram里面,从内部的sram去读取指令。
  2. nor flash是可以随意读取数据的,但是如果需要往nor flash里面写数据,则需要先发送一些特殊的命令才可以,所以说nor flash是可以随意读但是不可以随意写。但是内部的sram是可以随意读写的。

2主要流程

根据前面提到的2点,可以在程序一开始往0地址写一个数据(特殊一点即可,这里写0),再读取0地址的数据。
如果是nor 启动,应该会写失败(写必须先发特定命令),所以再次读取0地址的数据不等于之前所写的数据。
如果是nand启动,因为程序是在内部的sram运行(2440自动把nand 数据拷贝到sram),所以写是会成功的,再次读取0地址的数据就等于之前所写的数据。
在这里插入图片描述

3源码

start.s

.global _start
_start:

    /* aoto switch nand or nor flash */
    /* write 0 to address[0] and read it
     * if address[0] is equal 0, it is nand
     * because nand can wirte easy, but nor need send
     * write-commond before wirte data, so write 0 to
     * nor address[0] will fail, and get nor address[0]
     * data is not equal 0
     */
    mov r1, #0
    ldr r0, [r1] /* r0=[0] store address[0] data*/
    str r1, [r1] /* 0->[0] */
    ldr r2, [r1] /* r2=[0] */
    cmp r1, r2
    ldr sp, =0x40000000 + 4096/* for nor */
    ldreq sp, =4096  /* for nand */
    streq r0, [r1] /* recover address[0] data */

    /* stop watch dog */
    ldr r0, =0x53000000
    mov r1, #0
    str r1, [r0]

    bl main

loop:
    b loop

汇编代码流程很简单
1)把R1赋值为0
2)将0地址数据保存到R0
3)往0地址写0
4)把0地址数据读到R2
5)SP先设置为0x40000000+ 4096
6)如果R2等于R1, 即R2=0,那么说明是nand启动, SP设置成4096
7)把R0的值写回0地址

这里不需要担心,万一程序一开始0地址的数据就是0,那么在往0地址写0再取出来,就会误被判定为成功。 程序最终会编译成机器码, 而机器码组成的指令有特定的格式,不会出现一条指令全是0组成。 通过反汇编可以知道,程序的第1条指令就是“ mov r1, #0”, 这条指令的机器码是e3a01000, 所以0地址的值,一开始不会等于0。

在这里插入图片描述

led_on.c

int main(void)
{
    int i = 0;
    /* clear mode */
    GPFCON &= ~((3 << 8) | (3 << 10) | (3 << 12));
    /* set to output mode */
    GPFCON |= ((1 << 8) | (1 << 10) | (1 << 12));
    /* all led off */
    GPFDAT |= (7 << 4);

    while (1)
    {
        GPFDAT |= (7 << 4);
        GPFDAT &= ~(i << 4);
        i++;

        if (8 == i)
        {
            i = 0;
        }
        delay(100000);
    }

    return 0;
}

main函数是写做一个流水灯的功能, 具体的细节不说,因为今天主要讲的是区分nand flash 和nor flash。把这份代码分别烧到nand 和 nor 都可以正常启动,并让流程灯跑起来,但是会发现流水灯的执行速度不一样。
烧到nand 会执行的更快一点, 因为使用nand时,程序是跑在内部的sram里面,而使用nor时,程序要从外部的nor flash读取数据,因此会偏慢一点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值