关于正点原子的alpha开发板的启动函数(汇编,自己的认识)
我傻逼了,这里的注释还是不要用;
全部换成
/* */
这里就分为两块,一部分是复位中断部分,第二部分就是IRQ部分(中断部分最重要)
我就围绕着两部分来展开我的认识
首先声明全局 .global_start
在 ARM 架构的程序中,_start 常常是 C 程序的 main 函数之前的汇编代码,它负责设置程序的初始状态,比如初始化堆栈指针、设置 BSS 段、调用 C/C++ 运行时初始化代码等,然后将控制权传递给 main 函数
不知道为什么视频里的清楚和设置bss段,后面的代码没有了
第一步:设置中断向量表
这里设置中断向量表的顺序是固定的,依照架构技术手册设置。
发生了哪个中断就把其地址加载给pc指针
;中断向量表ldr pc,=Reset_Handlerldr pc,=Undefined_Handlerldr pc,=SVC_Handlerldr pc,=PrefAbort_Handlerldr pc,=DataAbort_Handlerldr pc,=NotUsed_Handlerldr pc,=IRQ_Handlerldr pc,=FIQ_Handler
一共有8种中断类型,我们最关心的两种一个是系统复位中断,第二种是外设中断IRQ中断,其他的目前是不太关心。所以其实现也是一个死循环,如下
SVC_Handler:
ldr r0,=SVC_Handler
bx r0
第二步:实现复位中断函数和IRQ中断函数
关闭C1寄存器里的几个功能,主要是操作SCTLR寄存器


mrc p15,0,r0,c1,c0,0 /* 读取CP15的C1寄存器到R0中 */bic r0,r0,#(1<<12)/*清除C1寄存器的bit12位(I位),关闭I Cache */bic r0,r0,#(1<<11) /*清除C1寄存器的bit11(Z位),关闭分支预测 */bic r0,r0,#(1<<2)/*清除C1寄存器的bit2(C位),关闭D Cache */bic r0,r0,#(1<<1)/*清除C1寄存器的bit1(A位),关闭对齐 */bic r0,r0,#(1<<0)/*清除C1寄存器的bit0(M位),关闭MMU */mcr p15,0,r0,c1,c0,0 /* 将r0寄存器中的值写入到CP15的C1寄存器中*/
配置完该寄存器后就开始设置中断向量表基地址,这几个中断的偏移是在基地址为0x0的基础上的,但是我们存放其位置是在0x87800000
/* 中断向量表偏移*/ldr r0,=0x87800000dsbisbmcr p15,0,r0,c12,c0,0dsbisb
其中dsb和isb是为了保障操作完成。
mcr p15,0,r0,c12,c0,0
该段代码意思是从CP15协处理器c12存入这个偏移地址
而c12里的VBAR是一个用来存放中断向量偏移基地址的寄存器

初始化这八种中断情况下的pc堆栈指针了。
当然可以全部实现,也可以只实现我们需要的
/* 设置各个模式下的堆栈指针*//* IRQ模式*/mrs r0,spsr;bic r0,r0,#(0x1f)/*将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */orr r0,r0,#(0x12)/*r0或上0x12,表示使用IRQ模式 */msr cpsr,r0 /*将r0 的数据写入到cpsr_c中 */ldr sp,=0x80600000/* 设置IRQ模式下的栈首地址为0X80600000,大小为2MB*//* SYS模式*/mrs r0,spsr;bic r0,r0,#(0x1f) /*将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */orr r0,r0,#(0x1f)/* r0或上0x1f,表示使用SYS模式*/msr cpsr,r0/*将r0 的数据写入到cpsr_c中 */ldr sp,=0x80400000/* 设置IRQ模式下的栈首地址为0X80400000,大小为2MB*//* IRQ模式*/mrs r0,spsr;bic r0,r0,#(0x1f)/*将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */orr r0,r0,#(0x13)/* r0或上0x13,表示使用SVC模式*/msr cpsr,r0/*将r0 的数据写入到cpsr_c中 */ldr sp,=0x80200000/*设置SVC模式下的栈首地址为0X80200000,大小为2MB */
在 ARM 架构中,状态寄存器 `SPSR`(Saved Program Status Register)用于保存当前的程序状态信息,包括处理器模式。
以下是切换处理器模式的几种常见方法:
1. **使用 `CPS` 指令**:ARM 架构提供了 `CPS`(Change Processor State)指令,用于切换处理器模式。例如,`CPS #0x13` 将切换到 SVC(Supervisor)模式,其中 `0x13` 是模式值加上一个优先级级别。
2. **修改 `CPSR` 寄存器**:直接修改 `CPSR` 寄存器可以改变处理器模式,但这通常不是安全的编程实践,因为它可能影响当前的程序状态。
3. **使用 `MSR` 指令**:`MSR`(Move to Status Register)指令可以用来修改 `CPSR` 或 `SPSR` 的某些字段。例如,`MSR spsr_cxsf, r0` 可以将寄存器 `r0` 的值写入 `SPSR` 的控制和状态字段。
4. **异常和中断处理**:当异常或中断发生时,处理器会自动切换到相应的模式,并保存当前的 `CPSR` 到相应的 `SPSR`。处理完异常或中断后,处理器会从 `SPSR` 恢复 `CPSR` 的值,从而切换回原来的模式。
5. **使用 `BX` 指令**:在某些情况下,使用 `BX` 指令跳转到一个具有不同模式的代码位置也可以实现模式切换。被跳转的目标代码需要设置正确的模式。
`SPSR` 主要用于异常和中断处理中保存和恢复程序状态,而不是直接用来切换模式。在编写程序时,应该使用 `CPS` 指令或 `MSR` 指令来安全地切换处理器模式,并确保程序状态的正确性。直接修改 `SPSR` 可能会导致不可预测的行为,因为 `SPSR` 也包含了其他状态信息,如中断屏蔽位等。
SPSR寄存器用来改变状态的就是低5位,当然我们也可以直接用cps 加上那5位切换到对应模式
cps #0x13/*切换到SVC模式*/
ldr sp,=0x80600000/*设置堆栈指针*/
这样也许更简洁。
设置完堆栈指针就该跳转到 main函数了,但是前面的设置过程为保证安全会关闭全局中断,设置完后再打开,类似于freertos里的进入临界区
2.1 具体的复位函数实现
Reset_Handler:cpsid i /* 关闭全局中断*/mrc p15,0,r0,c1,c0,0 /* 读取CP15的C1寄存器到R0中 */bic r0,r0,#(1<<12)/*清除C1寄存器的bit12位(I位),关闭I Cache */bic r0,r0,#(1<<11) /*清除C1寄存器的bit11(Z位),关闭分支预测 */bic r0,r0,#(1<<2)/*清除C1寄存器的bit2(C位),关闭D Cache */bic r0,r0,#(1<<1)/*清除C1寄存器的bit1(A位),关闭对齐 */bic r0,r0,#(1<<0)/*清除C1寄存器的bit0(M位),关闭MMU */mcr p15,0,r0,c1,c0,0 /* 将r0寄存器中的值写入到CP15的C1寄存器中*//* 设置各个模式下的堆栈指针*//* IRQ模式*/mrs r0,spsr;bic r0,r0,#(0x1f)/*将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */orr r0,r0,#(0x12)/*r0或上0x12,表示使用IRQ模式 */msr cpsr,r0 /*将r0 的数据写入到cpsr_c中 */ldr sp,=0x80600000/* 设置IRQ模式下的栈首地址为0X80600000,大小为2MB*//* SYS模式*/mrs r0,spsr;bic r0,r0,#(0x1f) /*将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */orr r0,r0,#(0x1f)/* r0或上0x1f,表示使用SYS模式*/msr cpsr,r0/*将r0 的数据写入到cpsr_c中 */ldr sp,=0x80400000/* 设置IRQ模式下的栈首地址为0X80400000,大小为2MB*//* IRQ模式*/mrs r0,spsr;bic r0,r0,#(0x1f)/*将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */orr r0,r0,#(0x13)/* r0或上0x13,表示使用SVC模式*/msr cpsr,r0/*将r0 的数据写入到cpsr_c中 */ldr sp,=0x80200000/*设置SVC模式下的栈首地址为0X80200000,大小为2MB */cpsie i /*打开全局中断 */b main/*跳转到main函数 */
然后就是最重要的IRQ中断函数的编写
2.2 具体IRQ函数的实现
首先保存lr寄存器的值,也就是保存现场,也就是入栈操作,把寄存器中的值保存进内存中去。
入栈 r0-r3,r12,因为这几个寄存器不会自动保存,要手动保存
然后就使spsr状态寄存器,它也不会自动保存
好了这几个寄存器全部压入栈内了,等于中断前的现场已经保存完整
进入协处理器CP15的C15经过操作数4的选择后最终我们选择读取CBAR寄存器的值

这个寄存器全名叫做配置基地址寄存器
我们为什么要得到该寄存器的值呢,因为我们要进一步得到GIC控制器的基地址。GIC的基地址存在CBAR里,这点是最重要的。没有CBAR的读取就找不到GIC的基地址
通过找到GIC的基地址,再经过偏移0x2000我们就得到GIC-CPU接口的基地址再偏移0xc我们得到了GIC-IAR寄存器的地址。这个GIC-IAR寄存器就是我们干这麽久最关键的地方。如果是知道这个偏移,那我们这样就更便捷,但是可读性就差了一些。
add r1,r1,#(0x200C);
找到IAR寄存器后读取寄存器里的值我们就得到了CPUID和中断号,他们被存入r0寄存器
得到中断号后我们的目的就得到了,就能找到对应的中断函数地址了。入栈r0,r1,把中断号和GIC-CPU接口的地址保存下来
切换到SVC模式,保存当前模式下的lr寄存器
r0,r1都用了,根据system_irqhandler得到入口地址存到r2寄存器内
blx跳到对应函数。
出栈SVC模式下的lr寄存器,切换到IRQ模式。出栈r0,r1。在不同的处理模式下出入栈lr都是成对的,它们拥有不完全公用的堆栈空间。这里的出栈入栈都是针对内存而言的,出栈就是内存到寄存器,入栈就使寄存器到内存。此刻r0存的是中断号,r1存的是GIC-CPU的基地址。把中断号存入GIC-CPU的基地址偏移0x10处的寄存器内表示中断执行完成,写EOIR 出栈r0恢复状态寄存器也就是
当前堆栈里还存有r0,r0-r3,r12的值,其中第一个r0存的是spsr寄存器的值
pop {r0}
msr spsr, r0
这个与那个应该是等价的,都是接受栈内原本存入的spsr寄存器的值
然后恢复现场,还IRQ中断发生前的r0-r3,r12寄存器的内容
弹出lr-4的值给pc
这里我开始困惑的地方就是为什么没有-8,后来我才知道运行那段会被强制执行完,所以-4就可以了。
IRQ_Handler:push {lr} /*保存当前运行地址 */push {r0-r3, r12} /* 其他寄存器会自动保存,这几个要手动*/mrs r0 ,spsr /*读取状态寄存器 */push {r0} /*保存 */mrc p15,4,r1,c15,c0,0 /*读取CP15的CBAR寄存器 */add r1,r1,#(0x2000) /*基地址偏移0x2000得到GIC-CPU接口的基地址 */ldr r0,[r1,#(0xc)] /* 将GIC-CPU基地址再偏移0xc得到GICC-IAR寄存器的基地址,取该地址的值*//*得到中断号及CPUID */push {r0,r1}cps #(0x13) /* 切换到SVC模式*/push {lr} /*保存svc模式下的lr寄存器 */ldr r2,=system_irqhandler /* 加载C语言的IRQ中断处理函数*/blx r2 /*跳转到对应的IRQ中断函数 */pop {lr}cps #0x12 /* 进入IRQ模式*/pop {r0,r1}str r0,[r1,#(0x10)] /*将其中断ID号写入r0保存的地址中,也就是IAR基地址 */pop {r0}msr spsr_cxsf, r0 /*恢复状态寄存器 */pop {r0-r3,r12}pop {lr}subs pc,lr,#4
经过我的测试,把中断向量基地址的偏移放在 _start:下也是没有问题的。
相关文章:
关于正点原子的alpha开发板的启动函数(汇编,自己的认识)
我傻逼了,这里的注释还是不要用; 全部换成 /* */ 这里就分为两块,一部分是复位中断部分,第二部分就是IRQ部分(中断部分最重要) 我就围绕着两部分来展开我的认识 首先声明全局 .global_start 在 ARM 架…...
Deep Layer Aggregation【方法部分解读】
摘要: 视觉识别需要跨越从低到高的层次、从小到大的尺度以及从精细到粗略的分辨率的丰富表示。即使卷积网络的特征层次很深,单独的一层信息也不足够:复合和聚合这些表示可以改进对“是什么”和“在哪里”的推断。架构上的努力正在探索网络骨干的许多维度,设计更深或更宽的架…...
大数据面试SQL题-笔记01【运算符、条件查询、语法顺序、表连接】
大数据面试SQL题复习思路一网打尽!(文档见评论区)_哔哩哔哩_bilibiliHive SQL 大厂必考常用窗口函数及相关面试题 大数据面试SQL题-笔记01【运算符、条件查询、语法顺序、表连接】大数据面试SQL题-笔记02【...】 目录 01、力扣网-sql题 1、高频SQL50题(…...
零基础自学爬虫技术该从哪里开始入手?
零基础自学爬虫技术可以从以下几个方面入手: 一、学习基础编程语言 Python 是爬虫开发的首选语言,因此首先需要学习 Python 编程语言的基础知识。这包括: 语法基础:学习 Python 的基本语法,如变量定义、数据类型、控…...
CV11_模型部署pytorch转ONNX
如果自己的模型中的一些算子,ONNX内部没有,那么需要自己去实现。 1.1 配置环境 安装ONNX pip install onnx -i https://pypi.tuna.tsinghua.edu.cn/simple 安装推理引擎ONNX Runtime pip install onnxruntime -i https://pypi.tuna.tsinghua.edu.cn/si…...
Redis的使用(四)常见使用场景-缓存使用技巧
1.绪论 redis本质上就是一个缓存框架,所以我们需要研究如何使用redis来缓存数据,并且如何解决缓存中的常见问题,缓存穿透,缓存击穿,缓存雪崩,以及如何来解决缓存一致性问题。 2.缓存的优缺点 2.1 缓存的…...
BERT架构的深入解析
BERT(Bidirectional Encoder Representations from Transformers)是由Google在2018年提出的一种基于Transformer架构的预训练模型,迅速成为自然语言处理(NLP)领域的一个里程碑。BERT通过双向编码器表示和预训练策略&am…...
数字孪生技术如何助力低空经济飞跃式发展?
一、什么是低空经济? 低空经济,是一个以通用航空产业为主导的经济形态,它涵盖了低空飞行、航空旅游、航空物流、应急救援等多个领域。它以垂直起降型飞机和无人驾驶航空器为载体,通过载人、载货及其他作业等多场景低空飞行活动&a…...
HTTP背后的故事:理解现代网络如何工作的关键(二)
一.认识请求方法(method) 1.GET方法 请求体中的首行包括:方法,URL,版本号 方法描述的是这次请求,是具体去做什么 GET方法: 1.GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源。 2.在浏览器中直接输入 UR…...
数据流通环节如何规避安全风险
由于参与数据流通与交易的数据要素资源通常是经过组织加工的高质量数据集,甚至可能涉及国家核心战略利益,一旦发生针对数据流通环节的恶意事件,将造成较大负面影响,对数据要素市场的价值激活造成潜在威胁。具体来说,数…...
部署k8s 1.28.9版本
继上篇通过vagrant与virtualBox实现虚拟机的安装。笔者已经将原有的vmware版本的虚拟机卸载掉了。这个场景下,需要重新安装k8s 相关组件。由于之前写的一篇文章本身也没有截图。只有命令。所以趁着现在。写一篇,完整版带截图的步骤。现在行业这么卷。离…...
实验二:图像灰度修正
目录 一、实验目的 二、实验原理 三、实验内容 四、源程序和结果 源程序(python): 结果: 五、结果分析 一、实验目的 掌握常用的图像灰度级修正方法,包括图象的线性和非线性灰度点运算和直方图均衡化法,加深对灰度直方图的理解。掌握对比度增强、直方图增强的原理,…...
bash: ip: command not found
输入: ip addr 报错: bash: ip: command not found 报错解释: 这个错误表明在Docker容器中尝试执行ip addr命令时,找不到ip命令。这通常意味着iproute2包没有在容器的Linux发行版中安装或者没有正确地设置在容器的环境变量PA…...
全开源TikTok跨境商城源码/TikTok内嵌商城/前端uniapp+后端+搭建教程
多语言跨境电商外贸商城 TikTok内嵌商城,商家入驻一键铺货一键提货 全开源完美运营 海外版抖音TikTok商城系统源码,TikToK内嵌商城,跨境商城系统源码 接在tiktok里面的商城。tiktok内嵌,也可单独分开出来当独立站运营 二十一种…...
云原生、Serverless、微服务概念
云原生(Cloud Native) 云原生是一种设计和构建应用程序的方法,旨在充分利用云计算的优势。云原生应用程序通常具有以下特征: 容器化:应用程序和其依赖项被打包在容器中,确保一致的运行环境。常用的容器技…...
Windows上LabVIEW编译生成可执行程序
LabVIEW项目浏览器(Project Explorer)中的"Build Specifications"就是用来配置项目发布方法的。在"Build Specifications"右键菜单中选取"New",可以看到程序有几种不同的发布方法:Application(EXE)、Installer、.Net Inte…...
ref 和 reactive 区别
在Vue 3中,ref和reactive都是用于创建响应式数据的API,但它们之间存在一些关键的区别。以下是ref和reactive的主要区别: 1. 数据类型处理 ref:主要用于定义基本类型的数据(如字符串、数字、布尔值等)以及…...
深度学习计算机视觉中, 多尺度特征和上下文特征的区别是?
在深度学习和计算机视觉中,多尺度特征和上下文特征都是用来捕捉和理解图像中复杂模式和关系的重要概念,但它们的侧重点有所不同。 多尺度特征 (Multi-scale Features) 多尺度特征是指在不同尺度上对图像进行特征提取,以捕捉不同尺度的物体特…...
Facebook未来展望:数字社交平台的进化之路
在信息技术日新月异的时代,社交媒体平台不仅是人们交流沟通的重要工具,更是推动社会进步和变革的重要力量。作为全球最大的社交媒体平台之一,Facebook在过去十多年里,不断创新和发展,改变了数十亿用户的社交方式。展望…...
uniapp-vue3-vite 搭建小程序、H5 项目模板
uniapp-vue3-vite 搭建小程序、H5 项目模板 特色准备拉取默认UniApp模板安装依赖启动项目测试结果 配置自动化导入安装依赖在vite.config.js中配置 引入 prerttier eslint stylelint.editorconfig.prettierrc.cjs.eslintrc.cjs.stylelintrc.cjs 引入 husky lint-staged com…...
PyTorch RMSprop优化器报错怎么办?教你一招避坑
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 PyTorch RMSprop优化器报错深度解析:一招解决常见陷阱目录PyTorch RMSprop优化器报错深度解析:一招解决常…...
挖 SRC 必备 25 个漏洞平台 零基础入门到实战全汇总
【值得收藏】程序员必看:网络安全漏洞挖掘平台大全,附高额奖励攻略 本文详细介绍了30网络安全应急响应中心(SRC)平台,包括腾讯、360、华为、京东等企业官方漏洞平台,以及补天、Seebug等第三方平台。这些平台允许白帽黑客提交企业…...
python政府集中采购管理系统设计与实现
目录同行可拿货,招校园代理 ,本人源头供货商项目背景核心功能模块技术实现要点应用价值项目技术支持获取博主联系方式 源码获取详细视频演示 :同行可合作点击我获取源码->获取博主联系方式->进我个人主页-->同行可拿货,招校园代理 ,本人源头供货商 项目背…...
构建全志Tina Linux Docker编译镜像:从环境配置到CI/CD实践
1. 项目概述:为什么我们需要一个专属的Docker编译镜像?如果你和我一样,长期在嵌入式Linux开发领域摸爬滚打,那么“环境搭建”这四个字,大概率是你开发周期里最耗时、也最令人头疼的环节之一。尤其是当我们面对像全志Ti…...
Linux下BepInEx Mod部署原理与实战指南
1. 为什么Linux玩家总在Mod部署上卡住?——BepInEx不是“装上就能用”的玩具 BepInEx、Unity、Linux、Mod框架——这四个词凑在一起,对很多刚从Windows转战Linux的玩家或Mod开发者来说,几乎等于一道默认关闭的门。我第一次在Ubuntu 22.04上尝…...
别再硬编码IP了!用LabVIEW类+队列实现仪器参数动态管理(附网口类实战代码)
告别硬编码:LabVIEW面向对象编程在仪器参数管理中的实战应用 在工业自动化和测试测量领域,工程师们经常面临一个共同的挑战:如何高效管理各类仪器的配置参数。传统开发方式中,IP地址、端口号等关键参数往往直接硬编码在程序里&…...
如何识别并拒绝AI领域虚假技术信息
我不能按照该标题生成相关内容。原因如下:标题中“TAI #181”指向一份外部出版物(疑似The AI Index Report或某AI行业通讯),但未提供任何可验证的原始内容、上下文、数据来源或事实依据;“DeepSeek’s V3.2 ‘Speciale…...
Kettle的优势
Kettle说具有非常强大的数据处理功能,没有做不到只有你想不到或者你还没有学会使用,如果确实做不到的情况下你还可以开发插件来进行数据处理,其中Kettle也提供了广泛的数据处理和转换功能,包括数据抽取、清洗、转换、合并、过滤等…...
3步彻底告别重复GUI操作:零代码AI助手如何让你每天节省2小时
3步彻底告别重复GUI操作:零代码AI助手如何让你每天节省2小时 【免费下载链接】UI-TARS-desktop The Open-Source Multimodal AI Agent Stack: Connecting Cutting-Edge AI Models and Agent Infra 项目地址: https://gitcode.com/GitHub_Trending/ui/UI-TARS-desk…...
5个理由让你立即尝试ImStudio:实时GUI布局设计器
5个理由让你立即尝试ImStudio:实时GUI布局设计器 【免费下载链接】ImStudio GUI layout designer for Dear ImGui 项目地址: https://gitcode.com/gh_mirrors/im/ImStudio ImStudio是一个基于Dear ImGui的实时GUI布局设计器,专为游戏开发者和应用…...
