开启辅助访问 切换到窄版

打印 上一主题 下一主题

Cortex-M3寄存器组&汇编与C的接口

[复制链接]
楼主
跳转到指定楼层
| 只看该作者 回帖奖励 |倒序浏览 |阅读模式
学uCOS的任务切换时涉及到汇编代码。为了能理解汇编代码,我在网上了解了Cortex-M3寄存器组、C与汇编的接口的知识,在这里分享给大家。

先来介绍Cortex-M3寄存器:



Cortex-M3拥有16个通用寄存器R0-R15。
R0-R12都是32位通用寄存器,用于数据操作。
R13是堆栈指针。在CM3处理器内核中共有两个堆栈指针,于是也就支持两个堆栈。当引用R13(SP)时,你引用到的是当前正在使用的那一个,另一个必须用特殊的指令来访问。两个堆栈分别是:
1、主堆栈指针(MSP):这是缺省的堆栈指针,它由OS内核、异常服务程序及需要特权访问的应用程序代码来使用。
2、进程堆栈指针(PSP):用于常规的应用程序代码。
R14是连接寄存器(LR)。在函数调用时存储返回的地址。
R15是程序计数器(PC)。指向当前程序的地址,如果修改它的值,就会改变程序的执行顺序(很多高级操作都在这)。



接下来介绍汇编与C的接口:


让C程序与汇编程序互相交互时,我们必须知道参数是如何传递的,以及值是如何返回的,这样才能在主调函数与子程序之间协调工作。这些交互机制在ARM中有明确的规定,由文档《ARM Architecture Procedure Call Standard(AAPCS,Ref5)》(我没有看过)给出。虽然没看官方的文档,我还是在百度上看了一下C与汇编混合编程,并做以下总结:1、发生函数调用时,入口参数依次通过R0-R3寄存器传递,其中R0传递第一个,R1传递第2个……,当超过4个参数时,其他参数通过栈传递。函数的返回值通过R0寄存器返回。在函数被调用前,R0-R3中的值会自动入栈。2、R4-R11为普通的通用寄存器,发生函数调用时,其中的数据不会自动入栈,如果被调函数需要使用这些寄存器,则需要由被调函数先将这些寄存器中数据入栈保存再使用这些寄存器。被调函数返回前,需要先将数据出栈回复R4-R11的值,然后再返回主调函数。3、R12(IP)可以记录对子程序的调用。R13-R15的作用在前一部分介绍过了,不再啰嗦


最后,我用C和汇编写了一个流水灯的程序,以此演示C语言调用汇编函数,其中LED亮灭的切换由汇编代码实现。以下附上部分代码:


/******************led.h*******************/
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"

voidLED_Init(void);//GPIO初始化
voidLED_Change(unsignedcharindex);//汇编函数在C语言头文件中的声明

#endif

/******************main.c*******************/
#include "delay.h"
#include "led.h"
intmain(void)
{
unsignedcharindex=1;
delay_init();
LED_Init();
while(1)
{
LED_Change(index);//调用汇编函数,传递一个参数
index=!index;
delay_ms(300);
}
}

/******************led.s*******************/
;全局函数
EXPORTLED_Change;该文件定义的函数
;常量
GPIOB_BASEEQU0x40010C00;GPIOB的基地址
GPIOB_BRREQUGPIOB_BASE+0x14;GPIOB_BRR寄存器的地址
GPIOB_BSRREQUGPIOB_BASE+0x10;GPIOB_BSRR寄存器的地址
GPIOE_BASEEQU0x40011800;GPIOE的基地址
GPIOE_BRREQUGPIOE_BASE+0x14;GPIOE_BRR寄存器的地址
GPIOE_BSRREQUGPIOE_BASE+0x10;GPIOE_BSRR寄存器的地址
LED_LIGHTEQU0x0020
;代码产生指令
PRESERVE8
THUMB

AREACODE,CODE,READONLY
;LED切换函数
LED_Change
CBZR0,LED1_Light;一个参数由R0传递,判断R0,如果值为0就跳转到LED1_Light

LED2_Light
;点亮LED2
LDRR1,=GPIOE_BRR;R1=GPIOE_BRR;//R1中存GPIOE_BRR寄存器的地址
LDRR2,=LED_LIGHT;R2=0x0020;
STRR2,[R1];*R1=R2;
;熄灭LED1
LDRR1,=GPIOB_BSRR
LDRR2,=LED_LIGHT
STRR2,[R1]
BXLR;函数返回

LED1_Light
;点亮LED1
LDRR1,=GPIOB_BRR
LDRR2,=LED_LIGHT
STRR2,[R1]
;熄灭LED2
LDRR1,=GPIOE_BSRR
LDRR2,=LED_LIGHT
STRR2,[R1]
BXLR;函数返回

NOP
END;汇编文件结束



效果如下:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表