栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【Linux学习】基础篇 2.1正点原子裸机 汇编LED驱动实验

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Linux学习】基础篇 2.1正点原子裸机 汇编LED驱动实验

汇编LED原理分析:

为什么要学习Cortex-A汇编?

        1.需要使用汇编初始化一些SOC外设

        2.使用汇编初始化DDR

        3.设置sp指针,一般指向DDR,设置好C语言运行环境

STM32 IO口初始化和I.MAX6ULL  IO口初始化区别?

STM32 IO口初始化流程:

        1.通过总线挂靠图找到对应总线进行时钟的开启RCC库函数

        2.设置IO复用,将其复用为GPIO

        3.配置GPIO的电气属性-输出方式、传输速率等

        4.使用GPIO,输出高低电平

I.MAX6ULL  IO口初始化流程:

           1.使能时钟,CCGR0-CCGR6这七个寄存器控制这6ULL所有外设时钟的使能,为了简单化,设置CCGR0-CCGR6这7个寄存器全部为0xFFFFFFFF ,相当于使能所有外设时钟

       2.IO复用,将寄存器的IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03的bit3-0设置为0101=5,此时GPIO_IO03配置为复用功能

           3.将寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03是设置GPIO_IO03的电气属性包括压摆率,速度,驱动能力,开漏,上下拉等。

             4.配置GPIO功能,设置输入输出,设置GPIO_GDIR寄存器bit3为1,即设置为输出模式

             5.设置GPIO1_DR寄存器的bit3,为1表示输出高电平,为0表示输出低电平

汇编简介:

        C 语言中的函数调用涉及到出栈入栈,出入栈需要对堆栈进行操作,堆栈实质是一段内存,该段内存由 SP 指针访问,SP 指针指向栈顶。因为 Cortex-A 芯片一上电 SP 指针还没初始化,C 环境还未准备 好,C代码无法运行,必须先用汇编语言设置好 C 环境,比如初始化 DDR、设置 SP 指针等等,C代码正常运行的前提条件是使用汇编代码配置好环境。以STM32F103 为例,启动文件 startup_stm32f10x_hd.s 就是汇编文件。

        汇编由一条条指令构成,指令涉及汇编指令。

        举例C语言与汇编实现变量值交换程序:

C语言程序:int a,b; a=b;

汇编程序:假设a的地址为0x20;b的地址为0x30 (在使用汇编最为常用的是LDR 和 STR指令)

        LDR R0, =0x30         //将数据地址0x30加载到R0中,即R0=0x30

        LDR R1,  [R0]            //读取地址0x30中的数据到R1寄存器

        LDR R0, =0x20        //将数据地址0x20加载到R0中,即R0=0x20

        STR R1, [R0]            //将R1中的值写入R0中所保存的地址

常用汇编指令:

1.存储器访问指令

        ARM 不能直接访问存储器,比如 RAM 中的数据,I.MX6UL 中的寄存器就是 RAM 类型 的,我们用汇编来配置 I.MX6UL 寄存器的时候需要借助存储器访问指令,一般先将要配置的值 写入到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器、

指令描述
LDR Rd, [Rn , #offset]从存储器 Rn+offset 的位置读取数据存放到 Rd 中。
STR Rd, [Rn, #offset]将 Rd 中的数据写入到存储器中的 Rn+offset 位置。

        LDR 主要用于从存储加载数据到寄存器 Rx 中,LDR 也可以将一个立即数加载到寄存器 Rx 中,LDR 加载立即数的时候要使用“=”,而不是“#”。在嵌入式开发中,LDR 最常用的就是读 取 CPU 的寄存器值。 

LDR R0, =0x0209C004 @将寄存器地址 0x0209C004 加载到 R0 中,即 R0=0x0209C004

LDR R1, [R0] @读取地址 0x0209C004 中的数据到 R1 寄存器中

LDR 是从存储器读取数据,STR 就是将数据写入到存储器中,LDR 和 STR 都是按照字进行读取和写入的,是操作的 32 位数据。

LDR R0, =0x0209C004 @将寄存器地址 0x0209C004 加载到 R0 中,即 R0=0x0209C004
LDR R1, =0x20000002 @R1 保存要写入到寄存器的值,即 R1=0x20000002
STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中

2.压栈和出栈指令

      A 函数中调用 B 函数,当 B 函数执行完以后再回到 A 函数继续执行。回到 A 函数代码能够接着正常运行要保证跳到 B 函数之前将当前处理器状态保存起来(就是保存 R0~R15 这些寄存器值),当 B 函数执行完成以后再用前面保存的寄存器值恢复 R0~R15 即可。保存 R0~R15 寄存器的操作就叫做现场保护,恢复 R0~R15 寄存器的操作就叫做 恢复现场。现场保护的时候需要进行压栈(入栈)操作,恢复现场就要进行出栈操作。

指令        描述
PUSH< reg list >将寄存器列表存入栈中。
POP < reg list >从栈中恢复寄存器列表。
PUSH {R0~R3, R12} @将 R0~R3 和 R12 压栈
PUSH {LR} @将 LR 进行压栈
POP {LR} @先恢复 LR
POP {R0~R3,R12} @在恢复 R0~R3,R12
3.算术运算指令
指令       计算公式备注
ADD Rd, Rn, RmRd = Rn + Rm加法运算,指令为 ADD
ADD Rd, Rn, #immedRd = Rn + #immed加法运算,指令为 ADD
ADC Rd, Rn, RmRd = Rn + Rm + 进位带进位的加法运算,指令为 ADC
ADC Rd, Rn, #immedRd = Rn + #immed +进位带进位的加法运算,指令为 ADC
SUB Rd, Rn, RmRd = Rn – Rm减法
SUB Rd, #immedRd = Rd - #immed减法
SUB Rd, Rn, #immedRd = Rn - #immed减法
SBC Rd, Rn, #immedRd = Rn - #immed – 借位带借位的减法
SBC Rd, Rn ,RmRd = Rn – Rm – 借位带借位的减法
MUL Rd, Rn, Rm  Rd = Rn * Rm乘法(32 位)
UDIV Rd, Rn, RmRd = Rn / Rm无符号除法
SDIV Rd, Rn, RmRd = Rn / Rm有符号除法
4.逻辑运算指令
指令计算公式备注
AND Rd, RnRd = Rd &Rn按位与
AND Rd, Rn, #immedRd = Rn &#immed按位与
AND Rd, Rn, RmRd = Rn & Rm按位与
ORR Rd, RnRd = Rd | Rn按位或
ORR Rd, Rn, #immedRd = Rn | #immed按位或
ORR Rd, Rn, RmRd = Rn | Rm按位或
BIC Rd, RnRd = Rd & (~Rn)位清除
BIC Rd, Rn, #immedRd = Rn & (~#immed)位清除
BIC Rd, Rn , RmRd = Rn & (~Rm)位清除
ORN Rd, Rn, #immedRd = Rn | (#immed)按位或非
ORN Rd, Rn, RmRd = Rn | (Rm)按位或非
EOR Rd, RnRd = Rd ^ Rn按位异或
EOR Rd, Rn, #immedRd = Rn ^ #immed按位异或
EOR Rd, Rn, RmRd = Rn ^ Rm按位异或

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/779579.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号