学习内容:
- 什么是ARM
- 常用的汇编语言
- 裸机开发
什么是ARM
ARM处理器 外文名 Advanced RISC Machines
ARM处理器ARM处理器是英国Acorn有限公司设计的低功耗成本的第一款RISC微处理器。全称为Advanced RISC Machine。ARM处理器本身是32位设计,但也配备16位指令集,一般来讲比等价32位代码节省达35%,却能保留32位系统的所有优势。
定义
ARM的Jazelle技术使Java加速得到比基于软件的Java虚拟机(JVM)高得多的性能,和同等的非Java加速核相比功耗降低80%。CPU功能上增加DSP指令集提供增强的16位和32位算术运算能力,提高了性能和灵活性。ARM还提供两个前沿特性来辅助带深嵌入处理器的高集成SoC器件的调试,它们是嵌入式ICE-RT逻辑和嵌入式跟踪宏核(ETMS)系列。
特点介绍
ARM处理器的三大特点是:耗电少功能强、16位/32位双指令集和合作伙伴众多。
1、体积小、低功耗、低成本、高性能;
2、支持Thumb(16位)/ARM(32位)双指令集,能很好的兼容8位/16位器件;
3、大量使用寄存器,指令执行速度更快;
4、大多数数据操作都在寄存器中完成;
5、寻址方式灵活简单,执行效率高;
6、指令长度固定。
寄存器结构
ARM处理器共有37个寄存器,被分为若干个组(BANK),这些寄存器包括:
1 31个通用寄存器,包括程序计数器(PC指针),均为32位的寄存器。
2 6个状态寄存器,用以标识CPU的工作状态及程序的运行状态,均为32位,只使用了其中的一部分。
指令结构
ARM微处理器的在较新的体系结构中支持两种指令集:ARM指令集和Thumb指令集。其中,ARM指令为32位的长度,Thumb指令为16位长度。Thumb指令集为ARM指令集的功能子集,但与等价的ARM代码相比较,可节省30%~40%以上的存储空间,同时具备32位代码的所有优点。
常用的汇编语言
基于Linux的汇编语言
1、编写汇编文件{ .global _start _start: mov r1, #3 mov r2, #4 nop nop }
2、编译
arm-linux-gcc start.S -o start.o -c -g arm-linux-ld start.o -o strat.elf -Ttext=0x0
3、调试
窗口1:qemu-system-arm -machine xilinx-zynq-a9 -m 256M -serial stdio -kernel start.elf -S -s 窗口2:arm-none-linux-gnueabi-gdb start.elf target remote 127.0.0.1:1234 s/p/......
传输数据指令: MOV
{ mov r1, #3 /*r1 = 3*/ mov r1, r2 @ r1 = r2 }
算术运算指令: ADD,SUB,MUL
{ add r0, r1, #3 @ r0 = r1 + 3 adds r0, r1, #3 @ r0 = r1 + 3 操作:cpsr C adc r0, r1, #3 @ r0 = r1 + 3 + C 计算它们的和 : 0x1ffffffff 0x200000001 r0: 0x1 r1: 0xffffffff r2: 0x2 r3: 0x1 adds r1, r1, r3 adc r0, r0, r2 }
位操作指令: AND,ORR,EOR,BIC
{ and r0, r1, r2 @ r0 = r1 & r2 orr r0, r1, r2 @ r0 = r1 | r2 eor r0, r1, r2 @ r0 = r1 ^ r2 bic r0, r0, #3 r0 = 0xf ---> 1111 bic r0, r0, #3 ---> 0011 1100 r0 = 0xe ---> 1110 bic r0, r0, #5 ---> 0101 1010 and r0,r0,#0xa }
跳转指令: B,BL
{ b flag @ goto flag 2: mov r1, #3 bl 1f @跳转的同时 保存返回地址到lr bl 2b mov r2, #4 1: mov r3, #4 mov pc, lr }
比较指令: CMP
{ cmp r1, r3 @ 比较 moveq r1, #3 @ if(r1==r3) then r1 = 3 { void fun() { r1=0; } if(r0==0) fun(); fun: mov r1, #0 cmp r0, #0 bleq fun } { if((r0>4)&&(r0<10)) r1 = 0; cmp r0, #4 ble end cmpgt r0, #10 movlt r1, #0 end: nop } { if((r0>4)||(r0<10)) r1 = 0; cmp r0, #4 movgt r1, #0 bgt end cmp r0, #10 movlt r1, #0 end: nop } { if((r0>4)||(r2>10)) r1 = 0; cmp r0, #4 cmple r2, #10 movgt r1, #0 cmp r0, #4 movgt r1, #0 b end cmp r2, #10 movgt r1, #0 end: nop } }
加载/存储指令: LDR,STR
{ ldr r0, [r1] 内存读操作:r1值作为地址,取这个地址开始的4个字节的数据,放到r0里面 str r0, [r1] 内存写操作:把r0的值,写到 r1值作为地址的空间里面去 }
多寄存器语句传输指令: LDM/STM
空指令: NOP 伪指令 = MOV R0 R0
裸机开发
以串口设备的裸机驱动开发为例
{
1、明确需求: 谁(com2) 做什么(发送'S')
2、看原理图:
1)原理: XuTXD2 ---> 数据发送
2)控制芯片: XuTXD2 ---》 GPA1_1------》uart(串口)控制器
|
|------> GPIO控制器(设置成串口发送的专用脚)
3、芯片手册(寄存器)
【GPIO】
GPA1CON 0x11400020 [7:4] 0x2 = UART_2_TXD
GPA1CON 0x11400020 [3:0] 0x2 = UART_2_RXD
【uart】
1)通过目录找到控制器章节
28章节
2)看看子章节和需求相关的部分
概述看,需求功能相关看。
a)串口有5路,4路是标准的串口(com2)。每个串口发送和接收buf。
b)串口包含的内容: 波特率发生器, 发送接收单元, 停止位,校验位,数据位c)发送流程: data-->fifo --> shifter --> txpin
|----人-||-------uart控制器-----|
d)fifo: fifo:all bytes no fifo:1 byte (选择)
e)ULCONn: 设置数据位、校验位、停止位
f)clk:UBRDIVn UFRACVALn3)看寄存器
a)筛选寄存器(ctrl和config要,功能相关要,不确定的要)
ULCON: 设置停止位、数据位、校验位
UCON:全局控制
UTXH:发送的fifo
UBRDIV:波特率分频
UFRACVAL:分频???b)细看寄存器,怎么实现需求
ULCONn = 0x3;
UCONn [3:2] 01 tx poll mode [1:0] 01 rx poll mode
UTXHn: 把数据写入,就发送, 最多只能8位的数据
URXHn: 从里面读数据 ok 最多只能读8位数据
UBRDIVn: 整数
UFRACVALn: 小数*16}
实现代码main.c:
#define GPA1CON *(unsigned int volatile*)0x11400020 #define ULCON2 *(unsigned int volatile*)0x13820000 #define UCON2 *(unsigned int volatile*)0x13820004 #define UTXH2 *(unsigned int volatile*)0x13820020 #define UBRDIV2 *(unsigned int volatile*)0x13820028 #define UFRACVAL2 *(unsigned int volatile*)0x1382002c void delay() { int t = 0xfffff; while(t--); } void uart_init() { GPA1CON = GPA1CON & ~(0xf<<4) | (0x2<<4); ULCON2 = 0x3; UCON2 = UCON2 & ~0x3f | (0x1<<2); UBRDIV2 = 53; UFRACVAL2 = 4; } void uart_send(char c) { UTXH2 = c; } void main() { char c = 'S'; uart_init(); uart_send(c); while(1) { char c = uart_recv(); uart_send(c); } }
start.S:
.globl _start _start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq _undefined_instruction: .word _undefined_instruction _software_interrupt: .word _software_interrupt _prefetch_abort: .word _prefetch_abort _data_abort: .word _data_abort _not_used: .word _not_used _irq: .word _irq _fiq: .word _fiq reset: /* 设置cpu模式为SVC模式 */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr,r0 /* 设置异常向量表起始地址 */ ldr r0, =0x41000000 mcr p15, 0, r0, c12, c0, 0 @Set VBAR /*用户需要设置的初始化*/ ldr sp, stacktop /*设置svc sp*/ sub r6, sp , #64 /*计算user需要指向的栈顶地址*/ /*切换到用户模式*/ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0x10 msr cpsr,r0 mov sp, r6 /*设置user sp*/ /*跳转到应用程序*/ bl main stack: .space 64*8 stacktop: .word stack+64*8