搜索
bottom↓
回复: 15

TQ2440裸奔程序1-跑马灯

[复制链接]

出0入0汤圆

发表于 2011-1-16 16:35:12 | 显示全部楼层 |阅读模式
最近,把半个多月来学习ARM的笔记进行了整理,主要是想让自己养成一个良好的学习习惯,加深对汇编语言的理解,见证自己学习过程中的体会和感悟,同时感谢在论坛上给予我帮助的人,你们的帮助是我继续研究下去的动力。故将自己的笔记整理发布,仅供像我这样的初学者参考。
                        第一章 GPIO端口操作
S3C2440有117个I/O端口,共分为A-H组,可以通过设置寄存器来确定某个引脚用于输入、输出或其他特殊功能。对端口的操作主要通过以下三个寄存器来进行。
1.        GPxCON,用于配置/选择引脚的功能。
2.        GPxDAT,用于引脚读写,当引脚被设为输入时,可以读此寄存器得到引脚输入,当引脚为输出时,写此寄存器相应位可令此引脚输出高电平或低电平。
3.        GPxUP,用于设置内部上拉电阻,为0时,相应引脚使用上拉电阻,为1时不使用(当引脚处于高阻状态时,它的电平由上拉、下拉电阻确定)
因此对端口的操作实际上就是通过对这三个寄存器进行读写。代码如下:
Ldr r0,=GPxCON   配置某端口功能
Ldr r1,=0x?     
Str r1,[r0]

Ldr r0,=GPxDAT   读取端口数据
Ldr r1,=0x?
Str r1,[r0]      ;向端口写入数据
Ldr r1,[r0]      ;读取端口数据
1、        TQ2440LED跑马灯程序
硬件说明:TQ2440中,LED1-LED4接GPB5-GPB8,其中1灯灭,0灯亮
          GPBCON地址为0x56000010,GPBDAT地址为0x56000014
          GPBCON每两位控制一个端口,其中00为输入端,01为输出端,取
值11保留,10为其它定义

   软件说明:
             设置GPB5-GPB8为输出端(0x01<<10)+ (0x01<<12)+ (0x01<<14)+ (0x01<<16)=0x15400

首先,我们初始化程序主要工作为:
关闭看门狗电路
      关闭子中断源
      关闭中断
      设置系统模式并关闭中断
      设置堆栈指针
      调用TestMain应用程序
程序:
Start
        ldr        r0,=WTCON       ;watch dog disable
        ldr        r1,=0x0
        str        r1,[r0]

        ldr        r0,=INTMSK
        ldr        r1,=0xffffffff  ;all interrupt disable
        str        r1,[r0]

        ldr        r0,=SUBINTMSK
        ldr        r1,=0x7fff                ;all sub interrupt disable
        str        r1,[r0]
               
        msr cpsr_c,#0xdf            ;系统模式并关闭IQR中断
        ldr sp,=4096
        
        b   TestMain

需要说明的是,我们在调用外部汇编程序时,需要用IMPORT TestMain引入该程序,同理,需要用EXPORT TestMain导出该函数定义。
在LED.S文件中
ldr r0,=GPBCON
ldr r1,=(0x01<<10)+(0x01<<12)+(0x01<<14)+(0x01<<16)
str r1,[r0]
用来设置GPBCON端口中GPB5-GPB8四个引脚功能为输出端。

ldr r0,=GPBDAT
    ldr r1,=(0xe<<5)        ;led1
str r1,[r0]
向GPB端口输出数据        (111000000)点亮LED1灯,其他同理

ldr r2,=0x20000
loop1
    sub r2,r2,#1
    cmp r2,#0
    bne loop1
用来延时,需要说明的是,在我们的初始化程序中,由于没有对时钟频率进行设置,TQ2440外接频率为FIN=12M,故程序运转正常。当我们将其用7命令下载到SDRAM中运行时,你会觉得四个LED灯全亮。原因何在,这是因为TQ2440中U_BOOT程序已将CPU时钟设置为400MHz,运行速度加快给你造成的错觉(这个问题,曾让我困惑,以为下载到NAND中不运行)。
将此程序下载到NANDFLASH或SDRAM中运行,我们自然产生一个问题,从NAND启动后,CPU自动将前4K数据拷贝到内部RAM中运行,地址为0x00000000而下载到SDRAM中时,其地址为0x30000000,两个地址不一样,程序是如何都能运行的呢?它是如何处理地址的呢?
让我们看看汇编后的代码:
               ldr r0,=WTCON       ;watch dog disable
[0xe3a00453]   mov      r0,#0x53000000
               ldr        r1,=0x0   
[0xe3a01000]   mov      r1,#0
               str        r1,[r0]
[0xe5801000]   str      r1,[r0,#0]
               ldr        r0,=INTMSK
[0xe59f001c]   ldr      r0,0x30000030 ; = #0x4a000008
               ldr        r1,=0xffffffff  ;all interrupt disable
[0xe3e01000]   mvn      r1,#0
               str r1,[r0]

从汇编后代码我们可以看到,因为WTCON地址0x53000000是一个合法的立即数,故ldr r0,=WTCON被处理成mov r0,#0x53000000指令,与地址无关。而INTMSK的地址为0x4a000008不是合法立即数,故 ldr r0,=INTMSK指令被汇编成一条
ldr r0,0x30000030 ; = #0x4a000008即从地址为0x30000030处读取0x4a000008,我们知道,编译器会在每段的未尾放一缺省的文字池,用来存放不是合法立即数的常数,当用伪指令LDR时,根据操作数的情况,或汇编成MOV指令,或用LDR读取指令。从上面我们可以看出,当程序在SDRAM(0x30000000)运行时,程序能根据地址读取正确的数,而程序写入NAND并运行时,它的开始地址为0x00000000,同理,数据0x4a000008的地址应该变为0x00000030,如图:
SDRAM运行,其地址如下:
0x30000000        ldr r0,=GPBCON        
……               
0x3000000c        ldr  r0,0x30000030 ; = #0x4a000008        0xe59f001c(二进制代码)
……               
0x30000030        0x4a000008        
那么当从NAND中运行时,其地址空间如下:
0x00000000        ldr r0,=GPBCON        
……               
0x0000000c        ldr  r0,0x30000030 ; = #0x4a000008        0xe59f001c(二进制代码)
……               
0x00000030        0x4a000008        
那么,ldr指令是如何保证从SDRAM或NAND中运行得到正确的地址的呢,这是因为ldr指令的地址是基于PC+8+偏移地址,我们看其二进代码0xe59f001c(二进制代码),偏移值为1c,其值计算如下:0x3000000c+8+1c=0x30000030(SDRAM)
                              0x0000000c+8+1c=0x00000030(NAND)
同理,我们再看看b TestMain指令情况:
其汇编为:
               b   TestMain   0x3000002c
[0xea000002]   b   TestMain
而TestMain代码的第一条指令地址为  0x3000003c
而转移指令的地址计算方法如下:后24位向左移动2位后再与PC+8相加的值就是程序转移的地址:
               (SDRAM)   0x3000002c+8+000002*4(左移2位)=0x3000003c
             (NADND)      0x0000002c+8+000002*4(左移2位)=0x0000003c

测试实验:
如果我们将b   TestMain指令改为ldr pc,=TestMain会有什么效果呢?
指定RO地址为0x30000000时,在SDRAM中能正常运行(增加延长次数),而下载到NAND后不能运行
指定RO地址为0x00000000时,在SDRAM中不能正常运行,而下载到NAND中能运行。

新手,请多关照

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2011-1-27 12:47:28 | 显示全部楼层
正在学ARM,写得不错,早点看到的话,光点亮灯就不用花了快一个小时了

出0入0汤圆

发表于 2011-1-27 13:50:23 | 显示全部楼层
頂,不錯,學習中!

出0入0汤圆

发表于 2011-1-27 14:56:49 | 显示全部楼层
SDRAM运行,其地址如下:
0x30000000        ldr r0,=GPBCON         
……                 
0x3000000c        ldr  r0,0x30000030 ; = #0x4a000008        0xe59f001c(二进制代码)
……                 
0x30000030        0x4a000008         
那么当从NAND中运行时,其地址空间如下:
0x00000000        ldr r0,=GPBCON         
……                 
0x0000000c        ldr  r0,0x30000030 ; = #0x4a000008        0xe59f001c(二进制代码)
……                 
0x00000030        0x4a000008      

是有不是有错???

出0入0汤圆

发表于 2011-1-27 20:58:27 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-1-28 00:09:19 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-1-28 06:30:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-28 21:51:32 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-2-11 16:41:26 | 显示全部楼层
不错学习啦

出0入0汤圆

发表于 2011-8-3 11:40:11 | 显示全部楼层
MARK, 居然是汇编的。

出0入0汤圆

发表于 2011-8-4 17:12:49 | 显示全部楼层
楼主,我刚接触arm,问下如果要实现这个功能需要神马软件呢

出0入0汤圆

发表于 2011-11-1 17:22:45 | 显示全部楼层
汇编的....有木有C语言的程序,有木有学习裸奔资料

出0入0汤圆

发表于 2011-11-11 08:39:10 | 显示全部楼层
用汇编写,厉害,佩服

出0入0汤圆

发表于 2012-2-18 15:24:01 | 显示全部楼层
写得太好了!坚持啊!

出0入0汤圆

发表于 2012-4-26 15:34:15 | 显示全部楼层
请楼主把完整的该代码上传学习如何?

出0入0汤圆

发表于 2012-4-27 15:54:26 | 显示全部楼层
顶一下,思考最后的那个测试实验。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 10:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表