ARM 汇编启动代码详解:从中断向量表到中断处理
ARM 汇编启动代码详解:从中断向量表到中断处理
引言
在嵌入式系统开发中,ARM 处理器(如 Cortex-A 系列)的启动代码是系统初始化和运行的基础。启动代码通常包括中断向量表的创建、初始化硬件状态(如关闭缓存和 MMU)、设置栈指针以及处理各种中断(如 IRQ、FIQ 等)。本文将详细解析一段典型的 ARM 汇编启动代码,涵盖 _start 函数、中断向量表、复位处理程序(Reset_Handler)以及 IRQ 中断处理程序(IRQ_Handler)。代码参考了 ARM Cortex-A(armV7)编程手册和 Cortex-A7 技术参考手册,确保内容准确且实用。
1. 代码概述
以下是完整代码的结构:
.global _start /* 全局标号 *//** 描述:_start函数,首先是中断向量表的创建* 参考文档:ARM Cortex-A(armV7)编程手册V4.0.pdf P42,3 ARM Processor Modes and Registers(ARM处理器模型和寄存器)* ARM Cortex-A(armV7)编程手册V4.0.pdf P165 11.1.1 Exception priorities(异常)*/
_start:ldr pc, =Reset_Handler /* 复位中断 */ ldr pc, =Undefined_Handler /* 未定义中断 */ ldr pc, =SVC_Handler /* SVC(Supervisor)中断 */ ldr pc, =PrefAbort_Handler /* 预取终止中断 */ ldr pc, =DataAbort_Handler /* 数据终止中断 */ ldr pc, =NotUsed_Handler /* 未使用中断 */ ldr pc, =IRQ_Handler /* IRQ中断 */ ldr pc, =FIQ_Handler /* FIQ(快速中断)未定义中断 *//* 复位中断 */
Reset_Handler:cpsid i /* 关闭全局中断 *//* 关闭 I、D Cache 和 MMU */mrc p15, 0, r0, c1, c0, 0 /* 读取 CP15 的 C1 寄存器到 R0 中 */ bic r0, r0, #(0x1 << 12) /* 清除 C1 寄存器的 bit12 位 (I 位),关闭 I Cache */ bic r0, r0, #(0x1 << 2) /* 清除 C1 寄存器的 bit2 (C 位),关闭 D Cache */ bic r0, r0, #0x2 /* 清除 C1 寄存器的 bit1 (A 位),关闭对齐 */ bic r0, r0, #(0x1 << 11) /* 清除 C1 寄存器的 bit11 (Z 位),关闭分支预测 */ bic r0, r0, #0x1 /* 清除 C1 寄存器的 bit0 (M 位),关闭 MMU */ mcr p15, 0, r0, c1, c0, 0 /* 将 r0 寄存器中的值写入到 CP15 的 C1 寄存器中 */#if 0/* 汇编版本设置中断向量表偏移 */ldr r0, =0X87800000dsbisbmcr p15, 0, r0, c12, c0, 0dsbisb
#endif/* 设置各个模式下的栈指针 *//* 进入 IRQ 模式 */mrs r0, cpsrbic 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, cpsrbic r0, r0, #0x1f /* 将 r0 寄存器中的低 5 位清零 */ orr r0, r0, #0x1f /* r0 或上 0x1f, 表示使用 SYS 模式 */ msr cpsr, r0 /* 将 r0 的数据写入到 cpsr_c 中 */ ldr sp, =0x80400000 /* 设置 SYS 模式下的栈首地址为 0X80400000, 大小为 2MB *//* 进入 SVC 模式 */mrs r0, cpsrbic r0, r0, #0x1f /* 将 r0 寄存器中的低 5 位清零 */ orr r0, r0, #0x13 /* r0 或上 0x13, 表示使用 SVC 模式 */ msr cpsr, r0 /* 将 r0 的数据写入到 cpsr_c 中 */ ldr sp, =0X80200000 /* 设置 SVC 模式下的栈首地址为 0X80200000, 大小为 2MB */cpsie i /* 打开全局中断 */#if 0/* 使能 IRQ 中断 */mrs r0, cpsr /* 读取 cpsr 寄存器值到 r0 中 */ bic r0, r0, #0x80 /* 将 r0 寄存器中 bit7 清零,也就是 CPSR 中的 I 位清零,表示允许 IRQ 中断 */ msr cpsr, r0 /* 将 r0 重新写入到 cpsr 中 */
#endifb main /* 跳转到 main 函数 *//* 未定义中断 */
Undefined_Handler:ldr r0, =Undefined_Handlerbx r0/* SVC 中断 */
SVC_Handler:ldr r0, =SVC_Handlerbx r0/* 预取终止中断 */
PrefAbort_Handler:ldr r0, =PrefAbort_Handler bx r0/* 数据终止中断 */
DataAbort_Handler:ldr r0, =DataAbort_Handlerbx r0/* 未使用的中断 */
NotUsed_Handler:ldr r0, =NotUsed_Handlerbx r0/* IRQ 中断!重点!!!!! */
IRQ_Handler:push {lr} /* 保存 lr 地址 */ push {r0-r3, r12} /* 保存 r0-r3,r12 寄存器 */mrs r0, spsr /* 读取 spsr 寄存器 */ push {r0} /* 保存 spsr 寄存器 */mrc p15, 4, r1, c15, c0, 0 /* 从 CP15 的 C0 寄存器内的值到 R1 寄存器中 */ add r1, r1, #0X2000 /* GIC 基地址加 0X2000,也就是 GIC 的 CPU 接口端基地址 */ ldr r0, [r1, #0XC] /* GIC 的 CPU 接口端基地址加 0X0C 就是 GICC_IAR 寄存器 */ push {r0, r1} /* 保存 r0, r1 */cps #0x13 /* 进入 SVC 模式,允许其他中断再次进去 */push {lr} /* 保存 SVC 模式的 lr 寄存器 */ ldr r2, =system_irqhandler /* 加载 C 语言中断处理函数到 r2 寄存器中 */ blx r2 /* 运行 C 语言中断处理函数,带有一个参数,保存在 R0 寄存器中 */pop {lr} /* 执行完 C 语言中断服务函数,lr 出栈 */ cps #0x12 /* 进入 IRQ 模式 */ pop {r0, r1} str r0, [r1, #0X10] /* 中断执行完成,写 EOIR */pop {r0} msr spsr_cxsf, r0 /* 恢复 spsr */pop {r0-r3, r12} /* r0-r3, r12 出栈 */ pop {lr} /* lr 出栈 */ subs pc, lr, #4 /* 将 lr-4 赋给 pc *//* FIQ 中断 */
FIQ_Handler:ldr r0, =FIQ_Handler bx r0
2. 代码功能详解
2.1 _start:程序入口和中断向量表
_start 是程序的入口点,它首先创建中断向量表。ARM 处理器在启动或发生异常时会根据向量表跳转到对应的处理程序。向量表包含 8 个条目,每个条目对应一种异常或中断:
- 复位中断(Reset):系统上电或复位后执行。
- 未定义中断(Undefined):执行了未定义的指令。
- SVC 中断(Supervisor Call):软件触发系统调用。
- 预取终止中断(Prefetch Abort):指令预取失败。
- 数据终止中断(Data Abort):数据访问失败。
- 未使用中断(Not Used):保留,未定义。
- IRQ 中断(Interrupt Request):外部设备请求的中断。
- FIQ 中断(Fast Interrupt Request):快速中断,通常用于高优先级任务。
代码使用 ldr pc, =handler 将每个处理程序的地址加载到程序计数器 pc,实现跳转。例如:
ldr pc, =Reset_Handler /* 复位中断 */
这表示当发生复位时,处理器会跳转到 Reset_Handler 执行。
2.2 Reset_Handler:复位处理程序
Reset_Handler 是系统启动后的第一个执行函数,负责初始化硬件状态。以下是其主要步骤:
(1) 关闭全局中断
cpsid i /* 关闭全局中断 */
- 使用
cpsid i关闭所有 IRQ 中断,确保初始化过程中不受干扰。
(2) 关闭缓存和 MMU
mrc p15, 0, r0, c1, c0, 0 /* 读取 CP15 的 C1 寄存器到 R0 */
bic r0, r0, #(0x1 << 12) /* 关闭 I Cache */
bic r0, r0, #(0x1 << 2) /* 关闭 D Cache */
bic r0, r0, #0x2 /* 关闭对齐 */
bic r0, r0, #(0x1 << 11) /* 关闭分支预测 */
bic r0, r0, #0x1 /* 关闭 MMU */
mcr p15, 0, r0, c1, c0, 0 /* 将修改写入 CP15 C1 */
- CP15 协处理器:CP15 负责系统配置,这里读取其控制寄存器 C1。
- 位操作:使用
bic清除特定位,分别关闭指令缓存(I Cache)、数据缓存(D Cache)、内存管理单元(MMU)等功能。这是“读-改-写”模式,确保初始状态干净。
(3) 设置中断向量表偏移(可选)
#if 0
ldr r0, =0X87800000
dsb
isb
mcr p15, 0, r0, c12, c0, 0
dsb
isb
#endif
- 这部分被禁用(
#if 0),用于将中断向量表基址设置为0x87800000,常见于需要调整向量表位置的场景(如从 Flash 移动到 SRAM)。dsb和isb确保操作同步。
(4) 设置不同模式的栈指针
ARM 处理器有多种工作模式(如 IRQ、SVC、SYS),每个模式需要独立的栈。代码为 IRQ、SYS 和 SVC 模式设置栈指针:
/* 进入 IRQ 模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 清零模式位 */
orr r0, r0, #0x12 /* 设置为 IRQ 模式 */
msr cpsr, r0
ldr sp, =0x80600000 /* 设置栈顶为 0x80600000,大小 2MB *//* 进入 SYS 模式 */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x1f /* 设置为 SYS 模式 */
msr cpsr, r0
ldr sp, =0x80400000 /* 设置栈顶为 0x80400000 *//* 进入 SVC 模式 */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x13 /* 设置为 SVC 模式 */
msr cpsr, r0
ldr sp, =0x80200000 /* 设置栈顶为 0x80200000 */
- 模式切换:使用
mrs读取当前程序状态寄存器(CPSR),bic清零模式位(低 5 位),orr设置新模式,msr写入回 CPSR。 - 栈设置:栈指针
sp指向内存区域(这里是 DDR 范围 0x80000000~0x9FFFFFFF),栈向下增长,必须 4 字节对齐。
(5) 打开全局中断并跳转
cpsie i /* 打开全局中断 */
b main /* 跳转到 main 函数 */
cpsie i重新启用中断。b main跳转到 C 语言的main函数,标志着初始化完成。
2.3 其他中断处理程序
除了 Reset_Handler,代码还定义了其他中断处理程序,但大多数只是简单地进入死循环:
Undefined_Handler:ldr r0, =Undefined_Handlerbx r0SVC_Handler:ldr r0, =SVC_Handlerbx r0PrefAbort_Handler:ldr r0, =PrefAbort_Handler bx r0DataAbort_Handler:ldr r0, =DataAbort_Handlerbx r0NotUsed_Handler:ldr r0, =NotUsed_Handlerbx r0FIQ_Handler:ldr r0, =FIQ_Handler bx r0
- 这些处理程序使用
ldr加载自身地址到r0,然后bx r0跳转回去,形成死循环。这是一种简单处理方式,实际应用中可能需要更复杂的逻辑。
2.4 IRQ_Handler:IRQ 中断处理
IRQ_Handler 是代码中的重点,负责处理外部设备的中断。以下是详细解析:
(1) 保存上下文
push {lr} /* 保存返回地址 */
push {r0-r3, r12} /* 保存通用寄存器 */
- 保存中断前的
lr(返回地址)和r0-r3, r12(可能被使用的寄存器)。
(2) 保存状态
mrs r0, spsr /* 读取 spsr */
push {r0} /* 保存 spsr */
spsr存储中断前的处理器状态,需保存以便返回。
(3) 获取 GIC 中断号
mrc p15, 4, r1, c15, c0, 0 /* 从 CP15 读取 GIC 基址 */
add r1, r1, #0X2000 /* 计算 GIC CPU 接口地址 */
ldr r0, [r1, #0XC] /* 从 GICC_IAR 读取中断号 */
push {r0, r1} /* 保存中断号和基址 */
- 通过 CP15 获取 GIC 基址,偏移
0x2000得到 CPU 接口地址,从GICC_IAR寄存器读取当前中断号。
(4) 模式切换和调用 C 函数
cps #0x13 /* 切换到 SVC 模式 */
push {lr} /* 保存 SVC 模式下的 lr */
ldr r2, =system_irqhandler /* 加载 C 函数地址 */
blx r2 /* 调用 C 中断处理函数 */
- 切换到 SVC 模式,调用 C 语言的
system_irqhandler函数,r0作为参数传递中断号。
(5) 清理和返回
pop {lr} /* 恢复 SVC 模式 lr */
cps #0x12 /* 切换回 IRQ 模式 */
pop {r0, r1}
str r0, [r1, #0X10] /* 写 EOIR 标记中断结束 */
pop {r0}
msr spsr_cxsf, r0 /* 恢复 spsr */
pop {r0-r3, r12} /* 恢复寄存器 */
pop {lr} /* 恢复 lr */
subs pc, lr, #4 /* 返回 */
- 恢复所有状态,通知 GIC 中断处理完成(写
GICC_EOIR),返回到中断前的位置。
3. 总结与应用
3.1 关键点回顾
- 中断向量表:定义了 8 种异常的入口,启动时跳转到
Reset_Handler。 - 复位初始化:关闭中断、缓存和 MMU,设置栈指针,跳转到
main。 - IRQ 处理:通过 GIC 获取中断号,调用 C 函数处理,恢复现场返回。
3.2 应用场景
这段代码适用于嵌入式系统(如基于 Cortex-A7 的开发板),用于启动操作系统或裸机程序。理解这些内容有助于调试硬件初始化问题、优化中断响应以及开发低级驱动。
3.3 扩展阅读
- 参考文档:ARM Cortex-A(armV7)编程手册、Cortex-A7 技术参考手册。
- 相关知识:CP15 协处理器、GIC 中断控制器、ARM 模式切换。
4. 附录:常见问题解答
- 为什么关闭缓存和 MMU? 为了确保启动时硬件状态干净,避免缓存或虚拟内存的残留影响。
- 栈指针为何向下增长? ARM 栈通常向下增长,方便压栈和出栈操作。
- GIC 是什么? 通用中断控制器,管理多个设备的中断请求。
相关文章:
ARM 汇编启动代码详解:从中断向量表到中断处理
ARM 汇编启动代码详解:从中断向量表到中断处理 引言 在嵌入式系统开发中,ARM 处理器(如 Cortex-A 系列)的启动代码是系统初始化和运行的基础。启动代码通常包括中断向量表的创建、初始化硬件状态(如关闭缓存和 MMU&a…...
LTSPICE仿真电路:(二十六)跨阻放大器简单仿真
1.前言 由于有个机会刚好了解了下跨阻,简单做个这个仿真,实际上跨阻放大器应该要复杂的多,由于跨阻放大器实际上是将电流转换为电压,最需要注意的参数肯定是运放的偏置电流 2.跨阻放大器仿真 这篇是纯记录 这是一个将0-50uA电流…...
特辣的海藻!15
题 1.迷宫 - 蓝桥云课 2.外卖店优先级 - 蓝桥云课 3.后缀表达式 - 蓝桥云课 题 1.迷宫 - 蓝桥云课 import java.util.*;public class Main {static class Node {int x;int y;String str;public Node(int x, int y, String str) {this.x x;this.y y;this.str str;} …...
RISCV GCC 后端 -- 依赖(Dependence)简析
在命令式语言,如C/C中,其依赖关系及分类如下: 依赖(Dependence) -- Control Dependence -- Data Dependence (Reads and Writes of the same location, registers / Memories etc) -- True Dependence (Write then Rea…...
算法-- js排序
汇总 注:以下log n 是 O(log2n) 注:快速排序实际应用中通常最优,但需避免最坏情况。 1 快速排序 [快速排序的思路] 分区:从数组中任意选择一个“基准”,所有比基准小的元素放在基准前面,比基准大的元素…...
FfreeRTOS有阻塞作用的API
在 FreeRTOS 中,阻塞 API 是指那些会导致调用任务进入阻塞状态(Blocked State)的函数,即任务会暂时让出 CPU,直到某个条件满足(如超时、信号量可用、队列数据到达等)。以下是常见的阻塞 API 分类及示例: 1. 任务延迟(延时) vTaskDelay() 使任务阻塞指定的时间(以系统…...
【棒垒球规则】全国幼儿软式棒垒球比赛规则(三)·棒球1号位
棒垒球球队的组成 3.01球队的组成 球队由教练员及工作人员 2 名至 4 名、队员 9 至 12 名组成。 球衣背号不大于两位数,背号不小于 15 厘米。 上场队员名单应填写上场选手和替补选手。 3.02防守位置及名称(参照图四) a.9 名队…...
stm32week10
stm32学习 七.CAN 7.STM32 CAN外设 标识符过滤器: 每个过滤器的核心由两个32位寄存器组成:R1[31:0]和R2[31:0] FSCx:位宽设置,置0为16位,置1为32位 FBMx:模式设置,置0为屏蔽模式,…...
Linux上历史命令显示时间,修改时间戳
今天分享一个生产环境避免背锅的小技巧:设置历史命令执行的具体时间。还可以快速定位问题出现的时间点并恢复误操作导致的系统问题,用于追踪溯源。 在Linux系统中,默认情况下,history命令只会显示命令的编号和命令内容࿰…...
看雪 get_pwn3(2016 CCTF 中的 pwn3)
get_pwn3(2016 CCTF 中的 pwn3) 格式化字符串漏洞 get_pwn3(2016 CCTF 中的 pwn3) (1) motalymotaly-VMware-Virtual-Platform:~/桌面$ file pwn3 pwn3: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, …...
python全栈-JavaScript
python全栈-js 文章目录 js基础变量与常量JavaScript引入到HTML文件中JavaScript注释与常见输出方式 数据类型typeof 显示数据类型算数运算符之加法运算符运算符之算术运算符运算符之赋值运算符运算符之比较运算符运算符之布尔运算符运算符之位运算符运算符优先级类型转换 控制…...
操作系统概述(3)
批处理系统 1.单道批处理系统 单道批处理系统是成批地处理作用,并且始终只有一道作业在内存中的系统。优点:提高系统资源的利用率和系统吞吐量。缺点:系统中的资源得不到充分利用。 2.多道批处理系统 引入多道程序设计技术,是…...
SolidWorks2025三维计算机辅助设计(3D CAD)软件超详细图文安装教程(2025最新版保姆级教程)
目录 前言 一、SolidWorks下载 二、SolidWorks安装 三、启动SolidWorks 前言 SolidWorks 是一款由法国达索系统(Dassault Systmes)公司开发的三维计算机辅助设计(3D CAD)软件,广泛用于机械设计、工程仿真和产品开…...
powershell绑定按钮事件的两种方式
写一个powershell的简单GUI做本地任务,试验出2个方法: 方法1: function btn1_click {write-host $text1.Text -ForegroundColor Green -BackgroundColor Black }$btn1.Add_Click({btn1_click})方法2: $btn2_click {write-host $…...
JBDC Java数据库连接(1)
目录 JDBC概述 定义 JDBC API 实例 JDBC搭建 建立与数据库连接: 形式: 实例 获得Satement执行sql语句 Satement中的方法: 实例 实例 JDBC概述 定义 JDBC(Java DataBase Connectivity)java数据库连接是一种用于执行SQL…...
Spring Boot 3.x 集成 MongoDB 的 默认配置项及默认值,以及 常用需要修改的配置项 的详细说明
以下是 Spring Boot 3.x 集成 MongoDB 的 默认配置项及默认值,以及 常用需要修改的配置项 的详细说明: 一、默认配置项及默认值 Spring Boot 对 MongoDB 的默认配置基于 spring.data.mongodb 前缀,以下是核心配置项: 配置项默认…...
git rebase复杂场景验证
经常面临复杂的分支管理,这里对几种场景的行为做一些验证。 结论总结 git rebase br_name:等价与新建br_name分支,然后找到当前分支与br_name分支的分叉点。然后把分叉点以后的提交(当前分支)一个一个的cherry-pick过…...
【Introduction to Reinforcement Learning】翻译解读2
2.2 马尔可夫决策过程(MDPs) 马尔可夫决策过程(MDP)为顺序决策提供了框架,其中动作不仅影响即时奖励,还会影响未来结果。与多臂老虎机问题不同,MDP中的即时奖励与延迟奖励相平衡。在多臂老虎机…...
大数据(5)Spark部署核弹级避坑指南:从高并发集群调优到源码级安全加固(附万亿级日志分析实战+智能运维巡检系统)
目录 背景一、Spark核心架构拆解1. 分布式计算五层模型 二、五步军工级部署阶段1:环境核弹级校验阶段2:集群拓扑构建阶段3:黄金配置模板阶段4:高可用启停阶段5:安全加固方案 三、万亿级日志分析实战1. 案例背景&#x…...
Linux内核中TCP协议栈的实现:tcp_close函数的深度剖析
引言 TCP(传输控制协议)作为互联网协议族中的核心协议之一,负责在不可靠的网络层之上提供可靠的、面向连接的字节流服务。Linux内核中的TCP协议栈实现了TCP协议的全部功能,包括连接建立、数据传输、流量控制、拥塞控制以及连接关闭等。本文将深入分析Linux内核中tcp_close…...
从搜索丝滑过渡到动态规划的学习指南
搜索&动态规划 前言砝码称重满分代码及思路solution 1(动态规划)solution 2(BFS) 跳跃满分代码及思路solution 1(动态规划)solution 2 (BFS) 积木画满分代码及思路动态规划思路讲解solution 前言 本文主要是通过一些竞赛真题…...
(一)栈结构、队列结构
01-线性结构-数组-栈结构 线性结构(Linear List)是由n(n>0)个数据元素(结点) a[0], a[1], a[2], a[3],...,a[n-1]组成的有限序列 数组 通常数组的内存是连续的,所以在知道数组下标的情况下,访问效率是…...
AWS SNS深度解析:构建高可用、可扩展的云原生消息通信解决方案
引言 在云原生架构中,高效的消息通信是系统解耦、实时响应的核心需求。AWS Simple Notification Service(SNS)作为一款全托管的发布/订阅(Pub/Sub)服务,为开发者提供了灵活、可靠的消息分发能力。本文将从…...
MySQL基础 [五] - 表的增删查改
目录 Create(insert) Retrieve(select) where条件 编辑 NULL的查询 结果排序(order by) 筛选分页结果 (limit) Update Delete 删除表 截断表(truncate) 插入查询结果(insertselect&…...
4.7学习总结 可变参数+集合工具类Collections+不可变集合
可变参数: 示例: public class test {public static void main(String[] args) {int sumgetSum(1,2,3,4,5,6,7,8,9,10);System.out.println(sum);}public static int getSum(int...arr){int sum0;for(int i:arr){sumi;}return sum;} } 细节:…...
OpenGL学习笔记(简介、三角形、着色器、纹理、坐标系统、摄像机)
目录 简介核心模式与立即渲染模式状态机对象GLFW和GLAD Hello OpenGLTriangle 三角形顶点缓冲对象 VBO顶点数组对象 VAO元素缓冲对象 EBO/ 索引缓冲对象 IEO 着色器GLSL数据类型输入输出Uniform 纹理纹理过滤Mipmap 多级渐远纹理实际使用方式纹理单元 坐标系统裁剪空间 摄像机自…...
vmware虚拟机上Ubuntu或者其他系统无法联网的解决方法
一、检查虚拟机是否开启了网络服务 打开方式:控制面板->-管理工具--->服务 查找 VMware DHCP Service 和VMware NAT Service ,确保这两个服务已经启动。如下图,没有启动就点击启动。 二、设置网络类型 我们一般使用前两种多一些&…...
OpenVLA-OFT——微调VLA时加快推理的三大关键设计:支持动作分块的并行解码、连续动作表示以及L1回归(含输入灵活化及对指令遵循的加强)
前言 25年3.26日,这是一个值得纪念的日子,这一天,我司「七月在线」的定位正式升级为了:具身智能的场景落地与定制开发商 ,后续则从定制开发 逐步过渡到 标准产品化 比如25年q2起,在定制开发之外࿰…...
Linux脚本基础详解
一、基础知识 Linux 脚本主要是指在 Linux 系统中编写的用于自动化执行任务的脚本程序,其中最常用的便是 Bash 脚本。下面我们将从语法、使用方法和示例三个方面详细讲解 Linux 脚本。 1. 脚本简介 定义:Linux 脚本是一系列命令的集合,可以…...
LabVIEW 油井动液面在线监测系统
项目背景 传统油井动液面测量依赖人工现场操作,面临成本高、效率低、安全风险大等问题。尤其在偏远地区或复杂工况下,测量准确性与时效性难以保障。本系统通过LabVIEW虚拟仪器技术实现硬件与软件深度融合,为油田智能化转型提供实时连续监测解…...
