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可以帮助理解程序
学习记录,侵权联系删除。
来源:朱老师物联网大课堂
相关文章:
ARM裸机:一步步点亮LED(汇编)
硬件工作原理及原理图查阅 LED物理特性介绍 LED本身有2个接线点,一个是LED的正极,一个是LED的负极。LED这个硬件的功能就是点亮或者不亮,物理上想要点亮一颗LED只需要给他的正负极上加正电压即可,要熄灭一颗LED只需要去掉电压即可…...
【单链表】05 有一个带头结点的单链表L,设计一个算法使其元素递增有序。
🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux算法题上机准备 😘欢迎 ❤️关注 👍点赞 🙌收藏 ✍️留言 题目 有一个带头结点的单链表L,设计一个算法使其元素递增有序。 算法思路 解决办法有很多&…...
C语言入门基础题:奇偶 ASCII 值判断(C语言版)和ASCII码表,什么是ASCII码,它的特点和应用?
1.题目描述: 任意输入一个字符,判断其 ASCII 是否是奇数,若是,输出 YES ,否则,输出 NO例如,字符 A 的 ASCI 值是 65 ,则输出 YES ,若输入字符 B(ASCII 值是 66)ÿ…...
Numpy的广播机制(用于自动处理不同形状的数组)
NumPy 广播是一种强大的机制,允许 NumPy 在执行元素级运算时自动处理不同形状的数组。广播的规则使得无需显式地创建匹配形状的数组,直接进行运算,大大简化了代码并提高了效率。 基本概念 广播的基本思想是让较小的数组在需要的维度上进行扩…...
计算机图形学入门24:材质与外观
1.前言 想要得到一个漂亮准确的场景渲染效果,不只需要物理正确的全局照明算法,也要了解现实中各种物体的表面外观和在图形学中的模拟方式。而物体的外观和材质其实就是同一个意思,不同的材质在光照下就会表现出不同的外观,所以外观…...
FTP、http 、tcp
HTTP VS FTP HTTP :HyperText Transfer Protocol 超文本传输协议,是基于TCP协议 FTP: File Transfer Protocol 文件传输协议, 基于TCP协议, 基于UDP协议的FTP 叫做 TFTP HTTP 协议 通过一个SOCKET连接传输依次会话数…...
【虚幻引擎】UE4初学者系列教程开发进阶实战篇——生存游戏案例
一、课程体系 1 学前必读 2 Character类相关基础 -人物移动控制 -动画蓝图 3 常见游戏机制基础 -碰撞器、触发器 -物体使用接口 -视角切换 4其他相关设计 -背包系统 -锻造系统 -物体破碎效果 -简易种植系统 -互动物体动画 5课程结语 二、UI部分 思维导图部分 实操部分 …...
认识并理解webSocket
今天逛牛客,看到有大佬分享说前端面试的时候遇到了关于webSocket的问题,一看自己都没见过这个知识点,赶紧学习一下,在此记录! WebSocket 是一种网络通信协议,提供了全双工通信渠道,即客户端和服…...
Scissor算法-从含有表型的bulkRNA数据中提取信息进而鉴别单细胞亚群
在做基础实验的时候,研究者都希望能够改变各种条件来进行对比分析,从而探索自己所感兴趣的方向。 在做数据分析的时候也是一样的,我们希望有一个数据集能够附加了很多临床信息/表型,然后二次分析者们就可以进一步挖掘。 然而现实…...
Linux-磁盘空间不足的清理步骤(详细版本)
当 Linux 服务器出现 “no space left on device” 错误时,意味着磁盘空间已满,需要采取一些措施来清理磁盘,可以根据下面步骤依次清理: 1. 检查磁盘使用情况 首先,使用 df 和 du 命令检查磁盘使用情况,找出哪些目录占用了大量空间。 可以通过如下命令来查询 df -h举例…...
go-redis源码解析:连接池原理
1. 执行命令的入口方法 redis也是通过hook执行命令,initHooks时,会将redis的hook放在第一个 通过hook调用到process方法,process方法内部再调用_process 2. 线程池初始化 redis在新建单客户端、sentinel客户端、cluster客户端等,…...
蓝桥杯备赛攻略(怒刷5个月拿省一)
十五届蓝桥杯结束,up也在这次比赛中获得了不错的成绩,为了帮助大家在25年蓝桥杯上获得好的成绩,我将根据今年的经验写一份蓝桥杯的备赛攻略,希望能帮到大家。 参赛准备 蓝桥杯算法赛必须指定一个编程语言赛道报名,也就…...
springboot项目jar包修改数据库配置运行时异常
一、背景 我将软件成功打好jar包了,到部署的时候发现jar包中数据库配置写的有问题,不想再重新打包了,打算直接修改配置文件,结果修改配置后,再通过java -jar运行时就报错了。 二、问题描述 本地项目是springBoot项目…...
倒计时 2 周!CommunityOverCode Asia 2024 IoT Community 专题部分
CommunityOverCode 是 Apache 软件基金会(ASF)的官方全球系列大会,其前身为 ApacheCon。自 1998 年以来,在 ASF 成立之前,ApacheCon 已经吸引了各个层次的参与者,在 300 多个 Apache 项目及其不同的社区中探…...
使用OpenCV在按下Enter键时截图并保存到指定文件夹
使用OpenCV在按下Enter键时截图并保存到指定文件夹 在这篇博客中,我们将介绍如何使用OpenCV库来实现一个简单的功能:在按下Enter键时从摄像头截图并保存到指定的文件夹中。这个功能可以用于各种应用,例如监控系统、视频捕捉等。 前置条件 …...
汇川伺服 (4)FFT、机械特性、闭环、惯量、刚性、抑制振动
一、参数解释 二、FFT 三、机械特性分析 四、多级配方与对象字典 对机组网配方 对象字典 五、InoServoShop 主要是用于调试620P620N将压缩报解压后不需要安装就可以直接使用 六、InoDriveWorkShop 主要是调试660 670 810 520 等系列 惯量识别 Etune Stune 惯量比调试 大惯…...
Unity3D中使用并行的Job完成筛选类任务详解
在Unity3D开发中,处理大量数据或执行复杂计算时,性能往往成为制约因素。为了提升游戏或应用的性能,Unity提供了强大的Job System,它允许开发者利用多线程和并行计算来优化数据处理过程。本文将详细介绍如何在Unity中使用并行的Job…...
汽车信息安全--欧盟汽车法规
目录 General regulation 信息安全法规 R155《网络安全及网络安全管理系统》解析 R156《软件升级与软件升级管理系统》解析 General regulation 欧洲的汽车行业受到一系列法律法规的约束,包括 各个方面包括: 1.安全要求:《通用安全条例&a…...
@SpringBootApplication 注解
什么是 SpringBootApplication SpringBootApplication 是 Spring Boot 提供的一个核心注解,它是一个组合注解,用于简化 Spring Boot 应用程序的配置。这个注解通常标注在主类上,用于标识一个 Spring Boot 应用的入口。通过这个注解ÿ…...
java项目总结4
目录 1.正则表达式 2.爬虫 3.时间 4.包装类 5.工具类之Arrays 6.Lambda 1.正则表达式 用于验证字符串是否满足自己所需要的规则。方法:matches 注意:\在Java中有特殊涵义,是将其它的意思本来化,假设"是用来引…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
