创建项目:首先建一个文件夹,然后建立.s文件
File-new-名字-samsung-s3c2410A-否(自己写汇编程序)-target-source ..-add file .. -.s文件(查看-文件扩展名)-写汇编代码
交叉编译工具链 project-manage-con ..-folders-勾选GCC(Keil有自己的编译工具,自带可用)-设置GNN- TOOL-Prefix和GUN Tool Folder
导入linker脚本 Project – Options for target – linker – 设置Linker Script file为map.lds.
编译代码,调试代码
ARM主要有7个基本工作模式
User:非特权模式,大部分任务执行在这种模式
FIQ:当一个高优先级(fast)中断产生时将会进入这种模式
IRQ:当一个低优先级(normal)中断产生时将会进入这种模式
Supervisor:当复位或软中断指令执行时将会进入这种模式
Abort:当存取异常时将会进入这种模式
Undef:当执行未定义指令时会进入这种模式
System:使用和User模式相同寄存器集的特权模式
ARM有37个寄存器
1个用作PC(Program Counter)
1个用作CPSR(Current Program Status Register)
5个用作SPSR(Saves Program Status Registers)
30个通用寄存
CPSR寄存器
Mode位:处理器模式位
10000 User mode
10011 SVC mode
10010 IRQ
10001 FIQ mode
10111 Abort mode
11011 Undefined mode 11111 System mode
CPSR/SPSR操作指令
mrs r0,CPSR
msr CPSR,r0
条件位
N = Negative result from ALU
Z = Zero result from ALU
C = ALU operation Carried out or borrow
V = ALU operation oVerflowed
T位J位
T=0;J=0 处理器处于ARM状态
T=1;J=0 处理器处于Thumb状态
中断禁止位:
I
=1:禁止IRQ
F=1:禁止FIQ
if (a==0) x=0;
if (a>0) x=x+3;
cmp r0,#0
moveq r1,#0
addgt r1,r1,#3
伪指令ldr r1,=0x12345678(赋值)
bic r0,r0,#0x03 //清除r0中的0号位和1号位
tst r0,#0x20 //测试第六位是否为0,为0则z标志置1
使能中断和快速中断?
mrs r0,cpsr
bic r0,r0,#0xc0
msr cpsr,r0
判断当前工作状态是否是arm状态,是则切换到user工作模式
mrs r0,cpsr
tst r0,#0x20
andeq r0,r0,#ffffffe0
orreq r0,r0,#0x10
msreq cpsr,r0
/**********************************/
b main //跳转到标号为main地址代码处
bl func //保存下一条要执行的指令的位置到LR寄存器,跳转函数func
//当跳转代码结束后,用MOV PC,LR指令跳回来
beq addr //当CPSR寄存器中的Z条件码置位时,跳转到该地址处
bne addr //当不等时,跳转到地址addr
load/store架构规定,存储器之间不嫩直接拷贝,需通过寄存器做中转
ldr r0,[r1] (load)//r0=*r1 r1里存放的是地址,把该地址里存放的内容读入r0中
//LDRB(byte) LDRH (half word)
Ldr r0,[r1,#8] //r0=*(r1+8)存储器地址为r1+8的自数据读入寄存器0
Ldr pc,_irq //pc =*(_irq)将标号中的内容放入pc中
str r0,[r1] (store) //*r1 = r0 将寄存器r0中值写入到存储器地址为r1的空间中
str r0,[r1],#4 //r0=*r1,r1=r1+4 将r0中的字数据写入以r1为地址的内存中,并将新地址r1+4写入r1
str r0,[r1,#4] //r0=*(r1+4)将r0中的字数据写入以r1+4为地址的内存中
异常种类
中断 IRQ FIQ 外部硬件触发
软中断 Soft interrupt 系统调用
复位 Reset 如手机死机了,按power键
未定义指令 Underfined instruction
数据异常 Data abort 数据越界
Arm中最少有两个中断,处理中断的时候需要中断控制器。
GNU汇编伪指令
.text 将定义符开始的代码编译到代码段
.data 将定义符开始的代码编译到数据段
.end 文件结束
.equ GPG3C0N,0XE03001C0 定义宏(即用GPG3C0N代替0XE03001C0)
.byte 定义变量1字节
.byte 0x11,’a’,0定义字节数组
.word 定义word变量(4字节 32位机)
.word 0x12344578 0x33445566
.string 定义字符串 .string “adddd\0”
Ldr r0,=0xE0028008 载入大常数0xE0028008到r0中
.global _start 声明_start为全局符号
批量操作指令
批量操作指令 (ia-Increment After ib-Increment Before da-Dec Afrer db-Dec Before)
Ldmia r0!,{r3-r10}//r0里地址指向的内容批量,load到r3~r10寄存器中,r0里地址会自动加4
stmia r0!,{r3-r10} //把r3~r10寄存器中内容,store到r0里地址执行空间中,r0里地址会自动加4
堆栈操作指令
stmfd sp!,{r0-r12,lr}将寄存器r0~r12 lr中的值存入栈中 常用于中断保护现场,!表示会自动偏移
ldmfd sp!,{r0-r12,pc} 将栈中值逐个弹出到寄存器r0~r12 pc中,常用于中断恢复现场,~表示会恢复spsr到cpsr
软中断指令
swi 0x02 产生软中断,软中断号为2
异常种类
中断 IRQ FIQ 外部硬件触发
软中断 Soft interrupt 系统调用
复位 Reset 如手机死机了,按power键
未定义指令 Underfined instruction
数据异常 Data abort 数据越界
Arm中最少有两个中断,处理中断的时候需要中断控制器。
软件现在分为(应用,内核,硬件层)
异常是随机的。
裸机驱动的开发步骤:
1.看电路图
a.找到我要控制的设备
b.找到设备在CPU侧的控制管脚
2.看芯片手册(先看相关的中文文档,熟悉设备,再看手册)
a.搜索电路图里对应控制管脚的名称
b.看目录找到对应的控制模块
c.看该模块的overview了解该模块的大概功能
d.看控制寄存器
注:如果寄存器比较多怎么办?
看技术支持提供的例子程序,找到需要修改的寄存器
部分厂商会提供配置软件,通过界面去配置功能,我们只需使用配置好的寄存器值就可以了。
3.编程
a.定义要控制的寄存器的宏(与手册里的寄存器地址对应起来)
b.设备初始化(如设置GPIO为输出状态)
c.把功能分成最基本的小块,逐个实现,如点亮灯->在灭灯->加延时->闪烁->跑马灯
寄存器管理挺重要的(Registers Summary)主要在芯片手册上(6.2)
虚拟机-设置-选项-共享文件夹
Linux交叉开发环境就是在开发主机(host)上运行,编译生成二进制文件,然后传给目标机(target)去执行
串行通讯
单线
双线 uart(全双工 异步)i2c(半双工 同步) 三线 spi(全双工 同步,该方式是最快的)
并行通讯
多根数据线 地址线,如内存
功能:实现通过串口com2输出字符显示
1.看电路图找到cpu对应的控制引脚 GPA1_1,GPA1_0
2.看芯片手册,找到对应寄存器
a.配置管脚为串口模式
b.功能块设置
3.编程