【嵌入式系统原理与应用】南航嵌入式 第三章——嵌入式系统程序设计

第三章 嵌入式系统程序设计

学习目标
  • 了解ARM汇编相关知识
  • 掌握常用重点指令及伪指令
  • 掌握ARM汇编语言程序设计*
  • 了解BordLoader及启动文件
  • 了解CMSIS规范
  • 掌握嵌入式C程序设计*
重点内容
  • 1、ARM常用指令集(ARM\Thumb\Thumb-2)及特点
  • 2、ARM指令六种寻址方式
  • 3、熟悉常用指令:MOV,ADD, SUB,AND,ORR,CMP,B,LDR,STR及LDR伪指令
  • 4、熟悉条件域的使用
  • 5、子程序及子程序调用PROC/MOV PC,LR/ENDP/BL
  • 6、CMSIS层次结构
  • 7、启动文件的功能
  • 8、C中的常用运算符 << -> | & != ^ ~
  • 9、嵌入式系统的程序结构(包括OS与第9章结合)
  • 10、ARM汇编、寄存器、固件库对硬件的基本操作步骤

ARM指令分类及指令格式
ARM指令特点
  • (1)使用标准的、固定长度的32位指令格式
  • (2)所有指令都使用4位条件码来决定指令是否执行
  • (3)RISC结构,指令是加载/存储型的
ARM指令分类
  • 分支指令
  • 数据处理指令
  • 程序状态寄存器(CPSR)处理指令
  • 加载/存储指令
  • 协处理器指令和异常产生指令。
ARM指令格式

< o p c o d e > { < c o n d > } { S } < R d > , < R n > , < o p 2 > <opcode>\{<cond>\}\{S\} <Rd>,<Rn>,<op2> <opcode>{<cond>}{S}<Rd>,<Rn>,<op2>

image-20220525195756694

ARM指令的条件码

​ 当处理器工作在ARM状态时,几乎所有的指令均根据CSPR中条件码的状态和指令的条件域有条件地执行。

​ 每一条ARM指令包含4位的条件码,位于指令的最高4位[31:28]。

image-20220525195828379

image-20220525195832976

ARM指令中的操作数符号
  • # 立即数符号:32位立即数
  • 0x 十六进制符号
  • ! 更新基址寄存器符号
  • ^ 复制SPSR到CPSR符号
  • - 指示寄存器列表符号
ARM指令中的移位操作
移位操作符opsh操作含义示例示例说明
LSL逻辑左移MOV R0,R1, LSL#2将R1中的内容左移2位送R0中,低位用0填充
ASL算术左移MOV R0,R2, ASL#3将R2中的内容左移3位送R0中,LSL与ASL效果相同,可以互换
LSR逻辑右移MOV R0, R1, LSR#2将R1中的内容右移两位后传送到R0中,左端用零来填充
ASR算术右移MOV R0, R1, ASR#2将R1中的内容右移两位后传送到R0中,左端用第31位的值来填充
ROR循环右移MOV R0, R1, ROR#2将R1中的内容循环右移两位后传送到R0中
RRX扩展的循环右移MOV R0, R1, RRX#2将R1中的内容进行带扩展(C标志)的循环右移两位后传送到R0中

ARM指令的寻址方式
  • 7种常见的寻址方式
    • 1、立即寻址:ADD R0,R1,#10
    • 2、寄存器寻址:MOV R1,R2
    • 3、寄存器间接寻址:STR R0,[R1]
    • 4、基址加变址寻址:LDR R1,[R1,#4]
    • 5、相对寻址:BL SUB1
    • 6、堆栈寻址
    • 7、块拷贝(多寄存器)寻址:LDMIA R0,{R1-R5}

ARM 指令集
  • 数据处理指令 P60
  • 程序状态指令 P61
  • 分支指令 P62
  • 加载/存储指令 P63
  • 协处理器指令 P66
  • 异常中断指令 P67

Thumb 指令集
  • Thumb指令集指令编码长度为16位,但指令的操作数和指令地址仍是32位;
  • Thumb指令集是ARM指令系统的一个子集 ;
  • Thumb指令集在保留32代码优势的同时,大大的节省了系统的存储空间。
Thumb-2指令集
  • Thumb-2是一种新型混合指令集,融合了16位和32位指令,用于实现密度和性能的最佳平衡。

ARM 处理器支持的伪指令
  • ADR

    • 功能:将程序相对偏移地址或寄存器偏移地址加载到指定寄存器中。

    • Mloop	MOV R1,#0xf9
            	ADR	R0,mloop	;将mloop对应相对偏移地址传送到R0中	 
      
  • LDR

    • 功能:将32位常量或一个地址加载到到指定寄存器中 。(MOV不能加载32位的数)

    • LDR R1,=0x1234				   ;R1=0x1234
      Mloop	LDR R2,=0xABCDEF98      ;R2=0xABCDEF98
      	    LDR	R3,=mloop	   ;将mloop对应地址传送到R3中
      
  • NOP

    • 功能:空操作,产生所需的ARM无操作代码,用于简单延时,与MOV Rd,Rd等效 。

    • LDR R7,=1000
      LOOP    NOP		      ;作为延时主体
      	   SUB R7,R7,#1
      	   BNZ LOOP
      

ARM汇编语言程序设计
一些伪指令
汇编语言的程序结构
             AREA	Init,CODE,READONLY
             ENTRY
Start
             LDR  R0,=0x3FF5000
             MOV R1,#0xFF     ;或LDR R1,=0xFF
             STR   R1,[R0]
             LDR   R0,=0x3FF5008
             MOV  R1,#0x01		;或LDR R1,=0x01
             STR    R1,[R0]
            ┉┉
Handler1 PROC          	 ;子程序名Handler1
            :                      	 ;子程序主体
            ENDP	           	 ;子程序结束
            END	            ;整个汇编语言程序结束

子程序的调用

​ ARM汇编语言子程序都有一个子程序的名称,也有子程序的返回指令,采用MOV PC,LR返回。
​ 如果一个子程序不在调用的同一个文件中,则需要先用IMPORT声明是外部的,IMPORT声明可以放在AREA语句之前。
​ 在ARM汇编语言程序中,子程序的调用一般是通过BL指令来实现的。
​ BL 子程序名

子程序:
Label  PROC
	...
	MOV PC,LR
	ENDP

​ 子程序调用

BL  Label
image-20220525202529839
CMSIS 及其规范

​ CMSIS(Cortex Microcontroller Software Interface Standard)是ARM Cortex™ 微控制器软件接口标准,是 Cortex-M 处理器系列与供应商无关的硬件抽象层。使用CMSIS,可以为处理器和外设实现一致且简单的软件接口,从而简化软件的重用、缩短微控制器新开发人员的学习过程,并缩短新产品上市时间。

image-20220525202741725

  • (1)内核外设访问层(CPAL=Core Peripheral Access Layer) 。
    • 由ARM公司负责实现,包括对寄存器名称、地址的定义,对核寄存器、NVIC、调试子系统的访问接口定义等。
  • (2)中间件访问层(MWAL=Middleware Access Layer)。
    • 定义了访问中间件的一些通用API函数,该层也有ARM公司负责,但芯片厂家也要根据自己器件的设备特性更新。
  • (3)片上外设访问层(DPAL, Device Peripheral Access Layer)。
    • 由芯片厂商负责实现,其实现与CPAL类似,负责对硬件寄存器地址以及外设访问接口进行定义。该层可调用CPAL层提供的接口函数,同时根据设备特性对异常向量表进行扩展,以处理相应外设的中断请求。

BootLoard及启动文件

​ Boot Loader:是应用程序运行之前的引导加载程序,类似于PC的BIOS程序,目的是将PC指针引导到C语言程序main入口。

​ ARM处理器启动过程:

image-20220525202903348

​ 嵌入式系统的Boot Loader是在操作系统内核或用户应用程序运行之前运行的一段小程序,这段小程序可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态﹐以便为嵌入式系统准备好正确的环境。

image-20220525203115832

image-20220525203125542


嵌入式C程序设计
常用运算符举例
uint32_t  temp;//或u32 temp1:让temp的指定位n置位
	temp|=(1<<n);//n=0~312:让temp的指定位n清0
	temp&=~(1<<n);//n=0~313:让temp的指定位n取反
	temp^=(1<<n);//n=0~314:LED1闪烁(LED1为GPIO的PD2引脚)
	//法(1)
    #define LED1(x)   ((x) ? (GPIO_SetBits(GPIOD, GPIO_Pin_2)) : (GPIO_ResetBits(GPIOD, GPIO_Pin_2)));
	while(1) 
    { 
        LED1(0);
        Delay();	
        LED1(1);
        Delay();
    }
	//法(2)
     while(1)
     {
         GPIOD->ODR^=(1<<2);
         Delay();
     }
嵌入式程序设计过程

image-20220525203700605

嵌入式应用程序有4种基本的处理流程
  • (1)基于轮询的处理流程;
  • (2)基于中断驱动的处理流程;
  • (3)基于轮询与中断相结合的处理流程;
  • (4)基于处理并发任务的处理流程。

image-20220525203814980

image-20220525203819297

image-20220525203823765

混合编程

(1)汇编中调用C语言子程序

注意事项

  • 寄存器R0~R3以及R12和LR可能会被修改,若这些寄存器在调用后还要使用的话,必须在调用前将这些寄存器压入栈保护起来,调用完再弹出
  • SP的值应该是双字对齐
  • 确保输入参数的存储在正确的寄存器中尽管使用R0~R3
  • 返回值存于R0中

​ C语言部分:

int SumFourDataC(uint32_t data1,  uint32_t data2,  uint32_t data3,  uint32_t data4)
{
   uint32_t sum;
   sum = data1 + data2 + data3 + data4;
   return sum;
}

​ 汇编部分:

MOVS R0, #0x12
LDR R1, =#0x12345678
LDR R2,=#0xABCDEF10
LDR R3,=#0x87654321
IMPORT  SumFourDataC
BL  SumFourDataC

(2)C语言中调用汇编子程序

注意事项

  • 如果要改变寄存器R4~R11中的值,需要将原始数值保存到栈中,在返回到C代码前恢复这些原来的值。
  • 如果在汇编程序中调用另外一个汇编子程序,需要将LR的值保存在栈中,并且利用它执行返回操作。
  • 函数返回值存放在R0中

​ 汇编部分:

EXPORT SumFourDataASM
SumFourDataASM  PROC
                ADDS R0,R0,R1
			   ADDS R0,R0,R2
		   	   ADDS R0,R0,R3
			   BX LR
  			   ENDP

​ C语言部分:

extern int SumFourDataASM(uint32_t data1,  uint32_t data2,  uint32_t data3,  uint32_t data4)
uint32_t sum
sum = SumFourDataASM(1,2,3,4);

(3)C语言嵌入汇编程序

__asm  函数
{
	汇编语言程序段
	BX	LR;返回的值在R0中
}


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUAA_Peter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值