硬件平台: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启动。
如果是nor 启动, 2440会直接从nor flash 去读指令,如果是nand 启动,2440会把nand 前4K的内容拷贝到sram里面,从内部的sram去读取指令。
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读取数据,因此会偏慢一点。
上一篇:s3c2440学习之路-005 轮训模式读取key(按键)
下一篇:s3c2440学习之路-003 汇编给C传参数 点亮不同led灯
推荐阅读最新更新时间:2024-11-11 12:00
设计资源 培训 开发板 精华推荐
- 使用 LT1205 100MHz 带宽和 85dB、10MHz 抑制的 4 x 4 视频交叉点
- NU1680 5W无线接收端
- LT1787 连接到 LTC1404 ADC:双向电流至位转换器
- LT3470AHDDB 5V 降压转换器的典型应用电路
- LTC3630AMPDHC 4V 至 63V 输入至 -12V 输出、正负转换器的典型应用电路
- RDR-877 - 6 W 隔离式反激电源,使用 LinkSwitch-TNZ 无损生成交流过零信号
- LTC3891 的典型应用 - 低 IQ、60V 同步降压型控制器
- LTC2195IUKG、16 位、125Msps 低功耗双通道 ADC 的典型应用
- EVAL-ADT7X20EBZ,用于评估 ADT7320/ADT7420 温度传感器的评估板
- 使用 NXP Semiconductors 的 TDA3603 的参考设计