第一个ARM裸机程序

发布者:梦中的额吉最新更新时间:2020-04-11 来源: eefocus关键字:ARM  裸机程序  S3C2440A 手机看文章 扫描二维码
随时随地手机看文章

1.查看原理图和数据手册,设置IO口功能

提示:此处使用的芯片是三星的S3C2440A


1.1.LED1,连接到GPF4的IO口,从原理图看出是低电平点亮LED灯。

1.2查看数据手册,配置寄存器

寄存器的描述

查看这些寄存器的具体功能,直接定位到GPF这一组寄存器的端口

看GPF具体位的定义是什么?

配置好输出模式之后,设置GPF4的输出电平,写GPFDAT寄存器,具体描述如下:

小结:


控制GPF4需要设置两个寄存器,GPFCON,GPFDAT


1.设置GPF[9:8] = 0b01            --GPF4配置为输出


2.设置GPFDAT[4]= 0或者1;  --GPF4输出低/高电平


2.S3C2440框架和启动过程

2.1.基本框架


S3C2440是一个SOC,在一块芯片上面集成了有CPU、GPIO控制器、Nand控制器、Nor控制器、以及4K的SRAM

2.2.启动过程(大多数ARM芯片从0地址启动)


1.NoR启动,NoR Flash 基地址为0(片内RAM地址为:0x40000000),CPU读出NOR读出上的第一个指令(前四个字节)执行,CPU继续读出其他指令执行。


2.Nand启动,片内4K SRAM 基地之为0(Nor Falsh 不可访问),硬件2240把NAND前4K内容复制到片内内存SRAM中,然后CPU从0地址取出第一条指令(前四个字节)执行。


3.编写程序点亮LED灯思路

3.1.设置GPFCON寄存器的 【9:8】为 0 1 ,也就是网GOFCON这个地址(0x56000050)写值


使用寄存器助手看一下,设置的值为多少?设置的值为:0x100

即把值0x100写到地址:0x56000050 上


3.2.点亮或者熄灭LED灯


熄灭:设置GPFDAT寄存器的第4位为1,也就是网GOFDAT这个地址(0x56000054)写值,写的值为:0x10

点亮:设置GPFDAT寄存器的第4位为0,也就是网GOFDAT这个地址(0x56000054)写值,写的值为:0


注意:此方法会破坏寄存器原本的位,即改变这个寄存器所有的位,因为此时控制一个LED所以不管别的位。


4.一些汇编语言的知识


5.编写汇编代码

5.1.新建给汇编文件

5.1.使用source insight 打开文件,编辑文件,代码如下:


    /*

*点亮LED,GPF4

    */

 

.text

.global  _start

_start:

/*配置GPF4为输出引脚*/

/*0x100写到地址0x56000050*/

 

//使用伪指令,把GPFCON的地址赋值给R1

ldr r1,=0x56000050

//把0x100赋值给R0

mov r0,#0x100  /*ldr r0,=0x100*/

//把r0的值写到地址r1去

str r0,[r1]

/*配置GPF4输出低电平,点亮LED*/

/*把0写到地址0x56000054*/

 

//使用伪指令,把GPFDAT的地址赋值给R1

ldr r1,=0x56000054

//把0赋值给R0

mov r0,#0  /*ldr r0,=0*/

//把r0的值写到地址r1去

str r0,[r1]

/*死循环*/

halt:

b halt


6.编译文件

6.1.打开Linux的虚拟机,查看虚拟机的IP地址

6.2.在window系统使用远程登陆工具(filezilla Pro),登陆Linux账户,进行文件的传输

6.3.双击led1.S,文件自动进行传输;

6.4.进入Linux系统,进入work目录

开始编译:


使用命令:


预编译:arm-linux-gcc -c -o led1.o led1.S


链接   :arm-linux-ld -Ttext 0 led1.o -o led1.elf 


得到bin文件:arm-linux-objcopy -O binary -S led1.elf led1.bin


一次输入上面的命令得到,下面的编译文件:

提示:手动输入比较容易出错,所以在这里制作一个Makefile文件

使用NotePad打开,编辑如下:

上传Makefile到Linux系统上(使用filezilla Pro):

以后可以使用命令:


make clean     --清除编译文件

make               --编译

7.下载到开发版

7.1.把Linux系统编译好的led1.bin文件传回windows系统

7.2.使用oflash烧写bin文件到开发版


进入window命令行,跳转到bin文件所在目录,执行oflash led1.bin

选择eop烧写:

选择2440:

2440:

烧写到Nand Flash:

从0地址开始烧写:

烧写完成,拔掉开发板的eop烧写器,使开发板从Nand Flash启动,重启开发版。重启之后就可以在开开发版中看到连接到GPF4的LED被点亮了。


8.查看伪指令解析后的汇编指令

8.1.修改Makefile 把 .elf文件反汇编,查看真正的汇编指令


使用指令:arm-linux-objdump -D led1.elf > led1.dis


修改后入下:


all:

arm-linux-gcc -c -o led1.o led1.S

arm-linux-ld -Ttext 0 led1.o -o led1.elf

arm-linux-objcopy -O binary -S led1.elf led1.bin

arm-linux-objdump -D led1.elf > led1.dis

 

clean:

rm *.bin *.o *.elf

使用远程登陆工具(filezilla Pro)上传Makefile文件到Linux虚拟机(因为已经上传过一次,所以此处应该为覆盖文件)

8.2.回到Linux虚拟机,使用make命令进行编译

机,使用make命令进行编译

生成的 led1.dis文件传回到windows

使用Notepad打开这个文件

想要看懂汇编语言语句,需要对ARM寄存器有所了解:

注意:ARM的指令的运行采用的是流水线型,当指令地址A的指令时,CPU已经对地址A+4的指令进行译码,同时已经在读取地址A+8的指令。所以pc的值是当前的地址+8;


8.3汇编代码指令解析:


第一句指令:ldr    r1, [pc, #20]

第二句指令:mov    r0, #256


解析:把0x100的值赋值给寄存器r0


第三句指令:str    r0, [r1]


解析:把ro的值(0x100)写到r1对应的内存,即把值0x100写入到内存:【0x56000050】


第四句指令:ldr    r1, [pc, #12]

第五句指令:mov    r0, #0


解析:把0赋值给r0寄存器


第六五句指令:str    r0, [r1]


解析:把ro的值(0x0)写到r1对应的内存,即把值0x0写入到内存:【0x56000054】


小结:


在CPU的角度来看,GPFCON、GPFDAT他们没有本质的区别,都当作内存来用。


8.4.编译器的功能


编译过程,我们的编译器会把汇编码转换成机器码,而机器码就是bin文件(二进制文件)的内容


把Linux编译好的 .bin文件从Linux拉出来,用Hex工具打开和.dis文件的机器码进行比较


可以看出他们是一样的。

练习1:修改led1.S驱动LED2

修改led1.S文件驱动连接GPF5的LED灯


1.由原理图可知,需要操作的的是GPF5

通过查看寄存器GPFCON的描述可知,需要设置GPFCON[11:10] = 0b01


即:网0x56000050地址写 0x400

2.修改led1.S文件


代码如下:


.text

.global  _start

_start:

/*配置GPF5为输出引脚*/

/*0x400写到地址0x56000050*/

 

//使用伪指令,把GPFCON的地址赋值给R1

ldr r1,=0x56000050

//把0x100赋值给R0

mov r0,#0x400  /*ldr r0,=0x400*/

//把r0的值写到地址r1去

str r0,[r1]

/*配置GPF5输出低电平,点亮LED1*/

/*把0写到地址0x56000054*/

 

//使用伪指令,把GPFDAT的地址赋值给R1

ldr r1,=0x56000054

//把0赋值给R0

mov r0,#0  /*ldr r0,=0*/

//把r0的值写到地址r1去

str r0,[r1]

/*死循环*/

halt:

b halt


3.上传到Linux进行编译:

4.传回windows 烧录到开发版

5.使用oflash 烧录到Nand Flash中,重启开发版,LED2被点亮。


附加:查看反编译的机器码是什么,下个练习用到

既然机器码是真正写到硬件的二进制代码,理论上我们通过修改二进制代码就可以修改他们的功能了。所以我们需要去查看RAM架构手册中对于 mov指令的描述,它每一个位的含义是什么?


MOV指令机器码如下所示:

当使用命令:mov r0 ,#1024  --把0x400赋值给r0的时候(也就是点亮LED2的时候)的机器码是:0xe3a00b01


把该值赋值到寄存器查看助手,查看一下哪一个位被设置了

如果想通过修改机器码去修改程序的执行结果,就是要修改mov指令机器码的立即数【11:0】的值

计算一下0x400的立即数是什么是否和上面的解释的一样

所以我们就可以通过改变机器码里边的立即数来改变最终程序的执行结果了。这样子的话,只要我们知道了我们需要设置的立即数,我们就可以推算出机器码,然后把这个机器码写入到硬件里面,程序就可以按我们的想法执行了。


具体看练习2的例子。


练习2:修改bin文件点亮LED3

1.由原理图可知,需要操作的的是GPF6

如果是使用汇编语言的话,那么和练习1的句子应该只有一句不同,只需要将上面的GPFCON[13:12]=0b01

使用寄存器助手看一下需要设置的值,设置为0x1000

可以看出这个程序的立即数是:0x1000,那么这个立即数 对应的机器码是什么?


0x1000可以转化成二进制可以表示为: 19个0加上1000000000000,用机器码表示成:1右移20位得到的数


那么机器码的rotate就是:20/2=10;  immed_8=1;


那么整个机器码我们可以表示为:e3a00a01

直接复制练习1的例子中的bin文件,把e3a00b01 改成  e3a00a01 

烧录修改后的bin文件到开发版中,烧录重启后,可以看到开发版的LED3亮灯。


9.用c语言控制LED灯

9.1.编写思路


通过查数据手册,知道了寄存器GPFCON和GPFDAT的数值,它们是32位的地址,其实本质来说也是内存,不过我们修改了这个内存的值就会使程序的运行结果发生变化,如果能根据数据手册的要求去改变这个寄存器所在地址的数值的话就能控制对应IO了。

在C语言中可以定义一个指针变量来存放这两个32位的地址,然后在程序中改变这个32位地址的(改变寄存器)值。


9.2.编写c代码


新建一个.c文件,很简单几条语句


int main()

{

unsigned int *pGPFCON=(unsigned int *)0x56000050;

unsigned int *pGPFDAT=(unsigned int *)0x56000054;

/*配置GPF4的引脚为输出引脚*/

 

*pGPFCON=0x100;

 

/*配置GPF4的引脚输出低电平(点亮LED)*/

*pGPFDAT=0;

 

return ;

}

问题:


1.编写的main函数谁来调用


2.main函数定义的变量保存在内存中,内存地址是多少


答:写一个汇编代码,给main函数设置使用的内存,调用main函数。


9.3.编写汇编代码


新建一个启动文件,命名为start.S,具体内容如下:


.text

.global _start

 

_start:

 

/*c语言中局部变量保存在栈中,栈对应的是一块内存*/

/*设置内存 :sp 栈*/

ldr sp ,=4096; //Nand Flash 启动

 

/*对于2440来说,当设置为Nand启动,从0开始的4k空间

  对应的是片内内存,把栈设置在内存的顶部*/

 

   // ldr sp ,=0x40000000+4096; //Nand Flash 启动

/*对于2440来说,当设置为Nor启动,片内4k内存的地址是0x40000000

  对应的是片内内存,把栈设置在内存的顶部*/

/*调用main函数,跳转到main函数*/

bl main

halt:

b halt

9.4.编写一个Makefile,方便对于汇编文件的编译,内容如下:


all:

arm-linux-gcc -c -o led.o led.c

arm-linux-gcc -c -o start.o start.S

arm-linux-ld -Ttext 0 start.o led.o -o led.elf

arm-linux-objcopy -O binary -S led.elf led.bin

arm-linux-objdump -D led.elf > led.dis

 

clean:

rm *.bin *.o *.elf *.dis


9.5.上传到Linux系统进行编译

在Linux系统进入源文件所在目录进行编译

9.6.把Linux系统编译好的文件传回window,然后烧写led.bin文件到开发版,可以看到GPF4对应的led灯亮了,这样这个c语言代码就便宜完成了。

关键字:ARM  裸机程序  S3C2440A 引用地址:第一个ARM裸机程序

上一篇:S3C2440—3.用点亮LED来熟悉裸机开发的详细流程
下一篇:S3C2440之裸机之汇编点亮LED灯

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

ARM7学习---按键测试程序(LPC2103 IO0PIN)
今天一直在学习按键测试程序,看上去很简单,按键嘛谁都会用,很多种单片机里都是用过了,但是今天还是遇到了一个问题,而且花了我半天的时间调试和找问题。刚开始我不会用LPC2103的GPIO,后来查了数据手册,知道了读取IO口的方法是读取IOPIN寄存器,LPC2103使用的是IO0PIN。我程序写好,把按键通过串口反馈信息。但是我一直测试没按键的时候输入按键口状态不稳定,有按键的时候还是很稳定的。我以为程序出错了,一直在修改程序,但是还是一样的情况。后来静下心来想了下,是否IO配置错了?但是检查了好多遍,IO是配置为输入,没什么问题的。后来终于想起来了,我没在按键的IO口加上拉电阻,以前我在51 STC AVR单片机的按键口都不加上拉电
[单片机]
ARM程序优化及其在嵌入式TCP/IP协议实现中的应用介绍
随着嵌入式技术的发展,人们对系统的智能化、小型化的要求也越来越高。基于ARM结构的微处理器以其高性能、低功耗、低价格等方面的优势被广泛应用于各种电子产品,特别是一些高端的嵌入式控制应用中,例如移动电话、工业控制、网络通信等方面。ARM技术具有很好的性能和功效,其合作伙伴包括许多世界顶级的半导体公司。可以说ARM技术几乎无处不在。 TCP/IP互联网协议族在全世界范围内已经成为开放系统互联的协议,它提供了很好的交互操作能力,可兼容多种网络技术。嵌入式技术与TCP/IP技术的结合已经展现出强劲的发展势头和巨大的市场潜力。如何开发面向 ARM的高效代码,尤其是提高类似于TCP/IP协议栈等基础性的软件模块的执行效率已成为每个从事
[单片机]
<font color='red'>ARM</font><font color='red'>程序</font>优化及其在嵌入式TCP/IP协议实现中的应用介绍
MCU,DSP,ARM学习方法经验分享
  很多初学者,甚至是混了好几年的老手,都在抱怨,电子这行怎么竞争这么大啊? 颓废,这完全在抹杀自己的激情,没了激情,搞电子,完全就是在浪费生命。其实,竞争真的大吗??对比一下,难道做业务的竞争不大,做管理的竞争不大,现在这个社会,哪个领域,哪个行业,竞争都大,所以,假如你想逃避竞争,那你就不用活了,当然,你本身家庭很好,父辈好有米的话,那另当别论!所以, 不管什么行业,竞争大不大的问题,都不用问了。答案都是:竞争大,但是必须面对,我们要自己面对的竞争越小,那么你的技术能力应该是越牛X。搞电子的人要跟得上时代,但是人的脑袋会随着年龄的增大而迟钝,所以这就造成了电子人才(特别是搞电子软件)的一种生老病死的自然规律。也就是说,一般40
[单片机]
S3C2440裸机------SPI_程序框架使用GPIO实现SPI协议操作OLED
1.oledfont.h #ifndef __OLEDFONT_H #define __OLEDFONT_H const unsigned char oled_asc2_8x16 = { {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// 0 {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00},//!1 {0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,
[单片机]
记录一种数据的传送方式,ARM7传送数据到GPIO
/*********************************************************************** * 名称:AD9850_SendToGPIO() * 功能:发送数据到GPIO * 入口参数:DataTemp:发送的数据 * 出口参数:无 ***********************************************************************/ void AD9850_SendToGPIO(uint8 DataTemp) { int8u GPIO = {D0,D1,D2,D3,D4,D5,D6,D7}; //D0~D7分别为IO口
[单片机]
Intel 10nm代工 LG两款ARM芯片现身
苹果最新推出的A11芯片再次证明,只有自主把控芯片才能让设备发挥最大的价值。而除了苹果之外,三星,华为等也在研发自家的芯片,很多人对此可能并不陌生,但可能有些读者可能不曾了解的是,LG也拥有自家的芯片——NUCLUN,尽管最终以失败告终。 现据最新消息,LG似乎正在研发两款全新的处理器。 根据欧盟知识产权局的申请文件,LG提交了两份商标申请文件,分别是“LG KROMAX Processor" 和 "LG EPIK Processor”。LG称它们指的是“芯片 ,多处理器芯片”。 当然,目前还并没有充分的证据表明这两款芯片会运用于智能手机,它们也有可能用于物联网设备。 不过联系到去年Recode的报道,Intel证实他们将为LG
[半导体设计/制造]
快速学Arm(38)--定时器和计数器(2)
我们再来看看定时器/计数器的结构 我们再对照上图看一下下面的例子: 这个例子实现了这样匹配的功能:定时0.1s,定时到,定时器复位并产生中断,外部匹配输出0上的电平翻转. 下面一个例子实现了捕获功能: 这个例子实现了这样的功能:捕获通道0上的下降沿信号触发捕获事件并产生捕获中断. 下面这个例子实现了用定时器测量脉冲宽度的功能
[单片机]
快速学<font color='red'>Arm</font>(38)--定时器和计数器(2)
处理器双雄争霸ARM将击败Intel?
ARM与英特尔( Intel )之间在处理器架构与生态系统方面的战争,正以多种形式重塑这个产业;预期将产生变化的,包括运算装置外观设计(form factor)、编程模型(programming model) 、成本(costs)、功耗预算(power budget)…等等。 举例来说,有两家ARM核心处理器供应商──AMD与Nvidia──已经开始提供各自的伺服器平台,因此有部分伺服器厂商可能就会透过垂直整合来差异化产品,有的则是与特定SoC供应商合作开发客制化解决方案;笔者猜想,英特尔未来也会依循其中一种方式,或以上两种方式都采用。 伺服器领域的发展情势可能远超过人们所预期、不仅仅是一场战争,而且会带来非常深远的影
[手机便携]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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