ARM裸机:一步步点亮LED(汇编)

硬件工作原理及原理图查阅

  • LED物理特性介绍
    LED本身有2个接线点,一个是LED的正极,一个是LED的负极。LED这个硬件的功能就是点亮或者不亮,物理上想要点亮一颗LED只需要给他的正负极上加正电压即可,要熄灭一颗LED只需要去掉电压即可。

  • 查阅原理图了解板载LED硬件接法
    查阅原理图,发现开发板上一共有5颗LED。其中一颗D26的接法是:正极接5V,负极接地。因此这颗LED只要上电就会常亮。因此我们分析这颗LED是电源指示灯。
    剩下4颗LED的接法是:正极接3.3V,负极接了SoC上的一个引脚(GPIO),具体详细接法是:
    D22:GPJ0_3
    D23:GPJ0_4
    D24:GPJ0_5
    D25:PWMTOUT1(GPD0_1)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 分析如何点亮及熄灭LED(GPIO)
    分析:LED点亮的要求是:正极和负极之间有正向电压差。
    思考:在开发板上如何为LED制造这个电压差让它点亮呢?
    解答:因为正极已经定了(3.3V),而负极接在了SoC的引脚上,可以通过SoC中编程来控制负极的电压值,因此我们可以通过程序控制负极输出低电平(0V),这样在正负极上就有了压差,LED即可点亮。

数据手册查阅及相关寄存器浏览

  • GPIO概念的引入
    GPIO:general purpose input output 通用输入输出
    GPIO就是芯片的引脚(芯片上的引脚有些不是GPIO,只有一部分是),作为GPIO的这类引脚,他的功能和特点是可以被编程控制它的工作模式,也可以编程控制他的电压高低等。
    通过之前的分析我们知道,我们设计电路时就把LED接在了一个GPIO上,这样我们就可以通过编程控制GPIO的模式和输入输出值来操控LED亮还是灭;如果你当时设计电路时把LED接在非GPIO上那就不可能了。

  • 阅读数据手册中有关部分
    当我们想要通过编程操控GPIO来操作LED时,我们首先需要通读一下S5PV210的数据手册中有关于GPIO的部分,这部分在数据手册的Section2.2中。
    《S5PV210_UM_REV1.1.pdf》
    在这里插入图片描述

  • GPIO相关的寄存器介绍
    回忆下之前说过的,软件操作硬件的接口是:寄存器。
    我们当前要操作的硬件是LED,但是LED实际是通过GPIO来间接控制的,所以当前我们实际要操作的设备其实是SoC的GPIO。要操作这些GPIO,必须通过设置他们的寄存器。
    在这里插入图片描述

    查阅数据手册可知,GPJ0相关的寄存器有以下:
    GPJ0CON, (GPJ0 control)GPJ0控制寄存器,用来配置各引脚的工作模式
    GPJ0DAT, (GPJ0 data)当引脚配置为input/output模式时,寄存器的相应位和引脚的电平高低相对应。
    GPJ0PUD, (pull up down)控制引脚内部弱上拉、下拉
    GPJ0DRV, (driver)配置GPIO引脚的驱动能力
    GPJ0CONPDN,(记得是低功耗模式下的控制寄存器)
    GPJ0PUDPDN (记得是低功耗模式下的上下拉寄存器)
    注:在驱动LED点亮时,应该将GPIO配置为output模式。

    实际上真正操控LED的硬件,主要的有:GPJ0CON, GPJ0DAT 这么2个。
    如何点亮LED,编程的步骤是:
    1、操控GPJ0CON寄存器中,选中output模式
    2、操控GPJ0DAT寄存器,相应的位设置为0

开始手写汇编点亮LED

D22:GPJ0_3
D23:GPJ0_4
D24:GPJ0_5

在这里插入图片描述
在这里插入图片描述

GPJ0CON(0xE0200240)寄存器和GPJ0DAT(0xE0200244)寄存器

第一步:设置引脚模式为输出模式(向GPxCON寄存器写入0001)
第二步:写入控制的数据(向GPxDAT寄存器写入0输出低电平,LED亮;1输出高电平,LED灭)

文件目录:
在这里插入图片描述

led.S:

_start://把0x1111 1111 写入 GPJ0CON(0xE0200240)//这里 ldr 是Load Register(加载寄存器)的缩写,//用于从给定的地址加载数据到处理器寄存器r0。//=0x11111111是一个立即数常量,//表示存储在内存中的十六进制数值 11111111ldr r0, =0x11111111 //ldr伪指令,编译器判断立即数是否合法//将立即数 0xE0200240加载到寄存器r1中ldr r1, =0xE0200240//str是Store Register(存储寄存器)的缩写,//它将寄存器r0中的值存储到[r1]所指向的位置。//这里的[r1]是对另一个内存地址的操作符,//意味着将r0的内容放到r1当前内容指明的那个内存位置//将r0的值存储到r1指向的内存地址处str r0, [r1] //寄存器间接寻址去; //LED灭:将0xff放到GPJ0DAT(0xE0200244)寄存器; ldr r0, =0xff; ldr r1, =0xE0200244; str r0, [r1]//LED亮:将 0x0 放到GPJ0DAT(0xE0200244)寄存器ldr r0, =0x0ldr r1, =0xE0200244str r0, [r1]//结束死循环
falt:b falt //直到CPU断电关机

编译结果:
LED常亮

使用位运算实现复杂点亮要求

  • 如何只点亮中间1颗(两边是熄灭的)LED
    //LED亮:将 0xf7 放到GPJ0DAT(0xE0200244)寄存器 亮1颗
    中间一颗:0xEF
    最后一颗:0xdf

  • 常用位运算:与、或、非、移位
    位与(&) 位或(|) 位非(取反 ~) 移位(左移<< 右移>>)

  • 使用位运算实现功能
    1<<3 等于 0b1000
    1<<5 等于 0b100000
    (1<<3)|(1<<5) 等于 0b101000

  • 扩展一下:如何只熄灭中间1颗而点亮旁边2颗
    ldr r0, =((0<<3) | (1<<4) | (0<<5))

汇编编写延时函数并实现LED闪烁效果

延时就是编写一些没有目的的代码,占用CPU的时间。

//延时函数
delay:ldr r2, =0x900000ldr r3, =0x0
delay_loop:cmp r3, r2//比较r3 r2  会影响Z标志位  如果r2==r3 则Z=1 下一句当中的ne就会成立sub r2, r2, #1 //r2=r2-1bne delay_loop //如果r2==r3 就不会执行这句mov pc, lr //函数调用返回
#define  GPJ0CON  0xE0200240
#define  GPJ0DAT  0xE0200244
//3、添加链接属性添加
.globl _start //将-start 修改为外部链接属性,其他文件就能找到_start
_start://把0x1111 1111 写入 GPJ0CON(0xE0200240)//这里 ldr 是Load Register(加载寄存器)的缩写,//用于从给定的地址加载数据到处理器寄存器r0。//=0x11111111是一个立即数常量,//表示存储在内存中的十六进制数值 11111111ldr r0, =0x11111111 //ldr伪指令,编译器判断立即数是否合法//将立即数 0xE0200240加载到寄存器r1中ldr r1, =GPJ0CON//str是Store Register(存储寄存器)的缩写,//它将寄存器r0中的值存储到[r1]所指向的位置。//这里的[r1]是对另一个内存地址的操作符,//意味着将r0的内容放到r1当前内容指明的那个内存位置//将r0的值存储到r1指向的内存地址处str r0, [r1] //寄存器间接寻址delay_loop_ok://熄灭中间1颗而点亮旁边2颗ldr r0, =((0<<3) | (1<<4) | (0<<5))ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delayldr r0, =((1<<3) | (0<<4) | (1<<5))ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delay; bne delay_loop_okb delay_loop_ok //死循环

再难一点的流水灯效果

12321的点亮LED

#define  GPJ0CON  0xE0200240
#define  GPJ0DAT  0xE0200244
//3、添加链接属性添加
.globl _start //将-start 修改为外部链接属性,其他文件就能找到_start
_start://把0x1111 1111 写入 GPJ0CON(0xE0200240)//这里 ldr 是Load Register(加载寄存器)的缩写,//用于从给定的地址加载数据到处理器寄存器r0。//=0x11111111是一个立即数常量,//表示存储在内存中的十六进制数值 11111111ldr r0, =0x11111111 //ldr伪指令,编译器判断立即数是否合法//将立即数 0xE0200240加载到寄存器r1中ldr r1, =GPJ0CON//str是Store Register(存储寄存器)的缩写,//它将寄存器r0中的值存储到[r1]所指向的位置。//这里的[r1]是对另一个内存地址的操作符,//意味着将r0的内容放到r1当前内容指明的那个内存位置//将r0的值存储到r1指向的内存地址处str r0, [r1] //寄存器间接寻址delay_loop_ok:ldr r0, =((0<<3) | (1<<4) | (1<<5))ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delayldr r0, =((1<<3) | (0<<4) | (1<<5))ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delayldr r0, =((1<<3) | (1<<4) | (0<<5))ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delayldr r0, =((1<<3) | (0<<4) | (1<<5))ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delay; bne delay_loop_okb delay_loop_ok //死循环//结束死循环 2、高级点的死循环b .  //直到CPU断电关机 .:当前指令的地址//延时函数
delay:ldr r2, =0x900000ldr r3, =0x0
delay_loop:cmp r3, r2//比较r3 r2  会影响Z标志位  如果r2==r3 则Z=1 下一句当中的ne就会成立sub r2, r2, #1 //r2=r2-1bne delay_loop //如果r2==r3 就不会执行这句mov pc, lr //函数调用返回

位取反操作:

//1、使用宏定义
#define  GPJ0CON  0xE0200240
#define  GPJ0DAT  0xE0200244
//3、添加链接属性添加
.globl _start //将-start 修改为外部链接属性,其他文件就能找到_start
_start://把0x1111 1111 写入 GPJ0CON(0xE0200240)//这里 ldr 是Load Register(加载寄存器)的缩写,//用于从给定的地址加载数据到处理器寄存器r0。//=0x11111111是一个立即数常量,//表示存储在内存中的十六进制数值 11111111ldr r0, =0x11111111 //ldr伪指令,编译器判断立即数是否合法//将立即数 0xE0200240加载到寄存器r1中ldr r1, =GPJ0CON//str是Store Register(存储寄存器)的缩写,//它将寄存器r0中的值存储到[r1]所指向的位置。//这里的[r1]是对另一个内存地址的操作符,//意味着将r0的内容放到r1当前内容指明的那个内存位置//将r0的值存储到r1指向的内存地址处str r0, [r1] //寄存器间接寻址delay_loop_ok:ldr r0, =~(1<<3)ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delayldr r0, =~(1<<4)ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delayldr r0, =~(1<<5)ldr r1, =GPJ0DATstr r0, [r1]//延时一下:bl delay; bne delay_loop_okb delay_loop_ok //死循环//结束死循环 2、高级点的死循环b .  //直到CPU断电关机 .:当前指令的地址//延时函数
delay:ldr r2, =0x900000ldr r3, =0x0
delay_loop:cmp r3, r2//比较r3 r2  会影响Z标志位  如果r2==r3 则Z=1 下一句当中的ne就会成立sub r2, r2, #1 //r2=r2-1bne delay_loop //如果r2==r3 就不会执行这句mov pc, lr //函数调用返回

反汇编工具objdump的使用简介

反汇编的原理&为什么要反汇编
arm-linux-objdump -D led.elf > led_elf.dis
objdump是gcc工具链中的反汇编工具,作用是由编译链接好的elf格式的可执行程序反过来得到汇编源代码
-D表示反汇编 > 左边的是elf的可执行程序(反汇编时的原材料),>右边的是反汇编生成的反汇编程序

  • 反汇编的原因
    1、逆向破解
    2、调试,理解程序链接脚本、链接地址
    3、理解C语言和汇编语言的关系

(汇编 assembly 反汇编 Disassembly)
标号的实质是地址
指令被转换为机器码
地址池实现非法立即数
在这里插入图片描述

bin文件内部是机器码,机器码会有指定的指令地址,使用ld链接在一起

总结

1、知道LED点亮原理
2、查看原理图知道接线方式
3、查看数据手册知道寄存器地址
4、开始编程
5、编译可执行文件
6、下载到设备上
7、添加延时达到流水灯
8、位操作增加可读性,同时比较简略
9、反汇编工具objdump可以帮助理解程序

学习记录,侵权联系删除。
来源:朱老师物联网大课堂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3223633.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

2024 Q3 NAND闪存价格|企业级依然猛涨,消费级放缓

在企业领域持续投资于服务器基础设施&#xff0c;特别是在人工智能应用的推动下&#xff0c;企业级SSD需求增加的同时&#xff0c;消费电子市场却依旧疲软。加之NAND供应商在2024年下半年积极扩大生产&#xff0c;预计到2024年第三季度&#xff0c;NAND闪存供应充足率将上升至2…

jQuery 笔记

一、什么是jQuery 框架&#xff1a;半成品软件 Jquery就是封装好的js 本质上还是js jQuery是一个快速、简洁的JavaScript**框架**&#xff0c;是继Prototype之后又一个优秀的**JavaScript代码库**&#xff08;*或JavaScript框架*&#xff09;。 JQuery:封装好的代码库。有一…

程序设计——领域驱动设计

程序设计的所有原则和方法论都是追求一件事——简单——功能简单、依赖简单、修改简单、理解简单。因为只有简单才好用&#xff0c;简单才好维护。因此&#xff0c;不应该以评论艺术品的眼光来评价程序设计是否优秀&#xff0c;程序设计的艺术不在于有多复杂多深沉&#xff0c;…

JVM原理(二三):JVM虚拟机线程安全的实现方法

1. 互斥同步 互斥同步(MutualExclusion&Synchronization)是一种最常见也是最主要的并发正确性保障手段。同步是指在多个线程并发访问共享数据时&#xff0c;保证共享数据在同一个时刻只被一条(或者是一些&#xff0c;当使用信号量的时候)线程使用。而互斥是实现同步的一种…

3d模型墙模糊怎么回事?---模大狮模型网

在展览3D模型设计行业中&#xff0c;技术细节常常是设计师们需要面对和解决的关键问题之一。其中&#xff0c;3D模型墙模糊的现象可能会影响整个展览的视觉效果和观众的体验。本文将深入探讨这一问题的起因及解决方法&#xff0c;帮助设计师们更好地处理类似挑战。 一、问题的起…

MySQL架构优化及SQL优化

变更项目的整体架构是性能收益最大的方式。主要涉及两方面&#xff0c;一方面是从整个项目角度&#xff0c;引入一些中间件优化整体性能&#xff0c;另一方面是调整MySQL的部署架构&#xff0c;确保能承载更大的流量访问&#xff0c;提高数据层的整体吞吐。 1. 引入缓存中间件…

不用服务器 | 我搭建了一个属于自己的GPT聊天应用!!!

原文地址&#xff1a;aiutools.fun/archives/5118 平台限制部分内容未显示&#xff0c;详情请访问原文。 展示 不废话&#xff0c;直接上干货&#xff01; 我这里搭建的Lobe Chat 支持 聊天TTS & STT 语音会话文生图各种优秀的插件 下面搭建好的样子 前期准备 需要…

基于jeecgboot-vue3的Flowable流程-集成仿钉钉流程(四)支持json和xml的显示

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、相应的界面前端代码 <template><div class"formDesign"><FlowDesign :process"process" :fields"fields" :readOnly"readOnly&quo…

算法之工程化内容(2)—— Git常用命令

目录 1. git初始化配置 2. 新建仓库 3. 工作区——>暂存区——>本地仓库 4. git reset回退版本 5. 查看差异 git diff 6. 删除文件git rm 7. .gitignore 8. vscode操作git 9. git分支、合并和删除 10. 解决合并冲突 11. 回退和rebase 12. 添加远程仓库 参考链接&#xff…

【少儿编程Python:趣味编程,探索未来】第四章 面向对象编程,开启编程新境界 / 第二节 继承与多态的魔法探险

欢迎进入Python编程的奇幻世界!在这个课程中,我们将一起探索编程的乐趣,通过生动有趣的方式,培养孩子们的逻辑思维和创造力,让他们成为未来的科技小达人。 以下是我们课程的大纲: 【少儿编程Python:趣味编程,探索未来】 目录 1. 命名空间和作用域的探险之旅1.1 命名空间…

【通信协议】八、CDL(Caterpillar Data Link)协议解析

1、协议简介 CDL(Caterpillar Data Link)是caterpillar的通信协议,该品牌发动机ECM与各控制单元进行通信时,采用基于RS-485的物理层规范进行开发的CDL协议进行通信; 2、物理层 信号传输方式:差分信号(通过两条线的电压差识别逻辑0或逻辑1) 通信方式:半双工通信(只允…

Agent如何帮助大模型“增强记忆”?

Agent如何帮助大模型“增强记忆”&#xff1f; 原创 格林 神州问学 2024年07月08日 17:50 日本 记忆反馈 >规划&#xff1f; 来源|神州问学 引言 去年6月份&#xff0c;Lilian发布了关于LLM驱动的Agent的结构和组件&#xff0c;其中包括规划、行动、工具还有记忆&#xff…

电脑清理c盘内存空间怎么清理免费 怎么清理c盘的垃圾文件又不删除有用文件

在计算机使用过程中&#xff0c;随着时间的推移&#xff0c;C盘空间可能会被各种临时文件、缓存和无用的注册表项占用。这不仅会导致C盘空间不足&#xff0c;还可能影响计算机的性能。那么怎么样清理C盘内存空间&#xff0c;怎么样清理C盘的垃圾避开系统文件呢&#xff1f; 一…

用LangGraph、 Ollama,构建个人的 AI Agent

如果你还记得今年的 Google I/O大会&#xff0c;你肯定注意到了他们今年发布的 Astra&#xff0c;一个人工智能体&#xff08;AI Agent&#xff09;。事实上&#xff0c;目前最新的 GPT-4o 也是个 AI Agent。 现在各大科技公司正在投入巨额资金来创建人工智能体&#xff08;AI …

数据结构 实验 3

题目一&#xff1a;最短路径dijkstra算法 一、实验目的 熟练图的邻接矩阵和邻接表表示法掌握图的最短路径Dijkstra算法的基本思想用C语言实现Dijkstra算法 二、实验内容 从键盘输入的数据创建图&#xff08;图的存储结构采用邻接矩阵&#xff09;&#xff0c;设计Dijkstra算…

SCI二区TOP|蜘蛛黄蜂优化算法(SWO)原理及实现【免费获取Matlab代码】

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2023年&#xff0c;M Abdel-Basset受到蜘蛛黄蜂优化社会行为启发&#xff0c;提出了蜘蛛黄蜂优化算法&#xff08;Spider Wasp Optimizer, SWO&#xff09;。 2.算法原理 2.1算法思想 S…

git撤销/返回到某次提交(idea工具 + gitbush)

不多说废话&#xff0c;直接展示使用。 方法一&#xff1a;使用idea工具进行返回 准备某次过度提交 使用idea打开git log 找到要回去的版本 点击右键选到reset 模式选hard&#xff0c;强制回滚 这个时候本地代码已经回归你指定的版本了。 这个时候再进行强制推送&#xff0c…

Flutter Inno Setup 打包 Windows 程序

转载自&#xff1a;flutter桌面应用从开发配置到打包分发 - 掘金 (juejin.cn) 五.打包 1.创建 release 版本的应用 flutter build release 执行完成后&#xff0c; release包位置在项目的build->windows->runer文件夹中 2.应用程序分发 Windows 为 Windows 平台构建…

Linux 利用命名空间创建一个自己的“容器“

Linux 利用命名空间创建一个自己的"容器" 前置条件 创建一个目录存放容器mkdir /myapp准备静态编译busybox&#xff0c;操作系统自带的往往是依赖动态库的(本文使用的debian apt install busybox-static) 开始 使用unshare起一个独立命名空间.# 进入后/myapp目录…

【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …