前言
ARM 处理器是英国Acorn有限公司设计的低功耗低成本的一款RISC微处理器
ARM 全称为 Acorn RISC Machine
目前市面上的CPU有两大类别
- RISC: 精简指令集计算机
- CISC: 复杂指令集计算机
关于两者的差别网上有很多资料,这里简要列出几点
DIFF | CISC | RISC |
---|---|---|
理念 | 让每条指令能够完成比较复杂的功能 | 让每条指令只实现最基本的功能 |
指令数目 | 多(>200) | 少(<100) |
指令字长 | 不固定 | 固定(16/32) |
指令使用频率 | 相差大(20/80) | 相差小 |
各种指令执行时间 | 相差很大 | 相差不大(因为等长,绝大多数在一个周期内完成) |
优化编译实现 | 难 | 易 |
功耗 | 大 | 小 |
CPU设计难度 | 大 | 小 |
应用代码量 | 小 | 大 |
应用开发时间 | 短 | 长 |
CISC的典型代表就是 Intel 和 AMD 系列芯片,RISC 的代表有IBM 的 Power(Power Optimization With Enhanced RISC),SUN 的SPARC,HP 的 PA-RISC 还有ARM
从两种架构的市场变化情况来看(鄙人愚见,欢迎拍砖)
DIFF | CISC | RISC |
---|---|---|
以前 | 电子消费领域(PC) | 服务器领域(各种小型机,大型机) |
现在 | 服务器领域(PC服务器) | 电子消费领域(手机,游戏机,嵌入式) |
未来 | 取决于能源成本和储能比(成正比) | 取决于能源成本和储能比(成反比) |
ARM 处理器本身是32位设计,但也配备16位指令集,一般来讲比等价32位代码节省达35%(也就是代码密度更高),却能保留32位系统的绝大部分优势
因为价格与能耗上的明显优势,在手持设备与嵌入式领域大放异彩,可以说目前的绝大部分便携或手持电子消费品都是用的ARM芯片
Tip: 当然还有更弱的终端由单片机(PC51一类的)来实现,ARM具备更复杂和强劲的控制与处理能力,价格也相对更贵
概要
平台环境与工具
应用的开发无法脱离具体的平台与环境,即便声称为跨平台的框架,在现实情况中,同样一套代码,在不同的平台与环境中也不一定会获得相同的效果
Note: 对于嵌入式来说,尤为如此,因为硬件配置不同,极大可能根本无法正常运行
这里使用如下平台与开发环境
- Windows 7 32位旗舰版
- 天嵌2440V2开发板
- 三星 ARM920T 芯片
- H-JTAG v2.1
- Keil uVision4.10
Tip: 都不是最新的,但能用,原理相通
Windows 7 32位旗舰版
天嵌2440V2开发板
三星 ARM920T 芯片
H-JTAG v2.1
Keil uVision4.10
按键控制 LED 灯
要求
- 使用ARM板的按键控制LED灯
KEY电路原理图
LED电路原理图
创建项目
创建项目的总体过程就
- 新建文件夹
- 创建项目文件
- 项目中添加入源代码
只有以下几个方式稍微注意一下
选择三星 S3C2440A芯片
Device 选项卡中确保是正确的设备选型(和头文件相关,寄存器的正确地址决定于此)
设定时钟频率和栈大小
Target 选项卡中确保时钟频率和板载一致
正确设定内存(只读栈和读写栈,也就是代码区与数据区的大小)
选择H-JTAG ARM 模式
选择正确的模式
使用外部工具
代码示例
asm_key_led.s
;;;
;LED电路原理图
;LED1-GPB5
;LED2-GPB6
;LED3-GPB7
;LED4-GPB8
;0-On,1-Off
;芯片针脚配置寄存器
;GPBCON-0x56000010
;GPBDAT-0x56000014
;GPBUP -0x56000018
;KEY电路原理图
;K1-EINT1/GPF1
;K2-EINT4/GPF4
;K3-EINT2/GPF2
;K4-EINT0/GPF0
;DOWN-0,UP-1
;芯片针脚配置寄存器
;GPFCON-0x56000050
;GPFDAT-0x56000054
;GPFUP -0x56000058
AREA RESET, CODE, READONLY ;定义一个名为RESET的只读代码段
CODE32 ;CODE32伪指令指示汇编编译器后面的指令为32位的ARM指令
ENTRY ;ENTRY伪指令用于指定程序的入口点,一个程序(可以包含多个源文件)中至少要有一个ENTRY,可以有多个ENTRY,但一个源文件中最多只有一个ENTRY
START ;不是关键词,只是一个标号,可以修改
;关看门狗相关配置
LDR R0, =0x53000000 ;0x53000000是看门狗定时器的控制寄存器地址,LDR是将这个地址加载到R0寄存器中
LDR R1, =0 ;LDR将0这个立即数,加载到R1寄存器中
STR R1, [R0] ;STR将R1寄存器中的值(0)存到R0寄存器中地址所指代的寄存器中,在这里,总体来讲就是关闭了看门狗
;配置与按键相连接的IO端口为输入GPF{1,4,2,0},00代表输入
LDR R0, =0x56000050 ;0x56000050是GPF的控制寄存器地址,LDR是将这个地址加载到R0寄存器中
LDR R1, =0 ;LDR将0这个立即数,加载到R1寄存器中
STR R1, [R0] ;STR将R1寄存器中的值(0)存到R0寄存器中地址所指代的寄存器中,在这里,总体来讲就是将所有的GPF针脚都设定成了输入模式,00代表输入
;配置与LED相连接的IO端口为输出GPB{5,6,7,8},01代表输出
LDR R2, =0x56000010 ;0x56000010是GPB的控制寄存器地址,LDR是将这个地址加载到R2寄存器中
LDR R3, =0x00015400 ;LDR将0x00015400这个数,加载到R3寄存器中,0x00015400代表0001 0101 0100 0000 0000,[17-10]分别为01010101,代表GPB{5,6,7,8}设定为输出,01代表输出
STR R3, [R2] ;STR将R3寄存器中的值(0x00015400)存到R2寄存器中地址所指代的寄存器中,在这里,总体来讲就是将GPB{5,6,7,8}设定为输出,01代表输出
;熄灭全部LED灯
LDR R2, =0x56000014 ;0x56000014是GPB的数据寄存器地址,LDR是将这个地址加载到R2寄存器中
LDR R3, =0x000001E0 ;LDR将0x000001E0这个数加载到R3寄存器中,0x000001E0代表0001 1110 0000,代表GPB{5,6,7,8}的位置为高电位
STR R3, [R2] ;STR将R3寄存器中的值(0x000001E0)存到R2寄存器中地址所指代的寄存器中,在这里,总体来讲就是将GPB{5,6,7,8}设定为高电位,高电位LED灯就灭了
LOOP
;读取按键状态
LDR R0, =0x56000054 ;0x56000054是GPFDAT寄存器的地址,LDR将0x56000054这个地址加载到R0寄存器中
LDR R1, [R0] ;LDR将R0寄存器中地址所指代的寄存器中的值加载到R1
;LED初始状态为熄灭
LDR R3, =0x000001E0 ;LDR将0x000001E0(0001 1110 0000)加载到R3中
;判断K1是否按下
TST R1, #0x00000002 ;TST指令将寄存器R1的值与0x00000002(0000 0010)的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,此操作类似于 if((GPFDAT & 0x00000002) == 0){},TST指令与ANDS指令的区别在于TST指令不保存运算结果,TST指令通常与EQ/NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效
BICEQ R3, #0x00000020 ;如果上一步的结果为EQ,则此步的操作就是将R3寄存器中值的第5位(从0位开始数)值清零,BIC指令将寄存器R3的值与0x00000020(0010 0000)的反码(1101 1111)作逻辑“与”操作,结果保存到R3寄存器中;GPB5
;判断K2是否按下
TST R1, #0x00000010 ;TST指令将寄存器R1的值与0x00000010(0001 0000)的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,此操作类似于 if((GPFDAT & 0x00000010) == 0){},TST指令与ANDS指令的区别在于TST指令不保存运算结果,TST指令通常与EQ/NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效
BICEQ R3, #0x00000040 ;如果上一步的结果为EQ,则此步的操作就是将R3寄存器中值的第6位(从0位开始数)值清零,BIC指令将寄存器R3的值与0x00000040(0100 0000)的反码(1011 1111)作逻辑“与”操作,结果保存到R3寄存器中;GPB6
;判断K3是否按下
TST R1, #0x00000004 ;TST指令将寄存器R1的值与0x00000004(0000 0100)的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,此操作类似于 if((GPFDAT & 0x00000004) == 0){},TST指令与ANDS指令的区别在于TST指令不保存运算结果,TST指令通常与EQ/NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效
BICEQ R3, #0x00000080 ;如果上一步的结果为EQ,则此步的操作就是将R3寄存器中值的第7位(从0位开始数)值清零,BIC指令将寄存器R3的值与0x00000080(1000 0000)的反码(0111 1111)作逻辑“与”操作,结果保存到R3寄存器中;GPB7
;判断K4是否按下
TST R1, #0x00000001 ;TST指令将寄存器R1的值与0x00000001(0000 0001)的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,此操作类似于 if((GPFDAT & 0x00000001) == 0){},TST指令与ANDS指令的区别在于TST指令不保存运算结果,TST指令通常与EQ/NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效
BICEQ R3, #0x00000100 ;如果上一步的结果为EQ,则此步的操作就是将R3寄存器中值的第8位(从0位开始数)值清零,BIC指令将寄存器R3的值与0x00000100(0001 0000 0000)的反码(1110 1111 1111)作逻辑“与”操作,结果保存到R3寄存器中;GPB8
;控制LED显示
STR R3, [R2] ;STR将R3寄存器中的值存到R2寄存器中地址所指代的寄存器中,在这里,总体来讲就是将GPB{5,6,7,8}设定为相应电位,高电位LED灯就灭了,低电位灯就亮了
B LOOP ;不断循环
END ;汇编结束
编译执行
[Build]->[Debug]->[Run]
编译执行过程中没有报错,从结果来看,符合预期
依次按下K1 到 K4 ,相应的 LED1 到 LED4 灯也被点亮
原文地址http://soft.dog/2017/03/15/arm-02-key-led/