news 2026/4/18 3:42:40

ARM裸机开发入门:从环境搭建到外设驱动

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ARM裸机开发入门:从环境搭建到外设驱动

ARM 裸机开发学习知识体系

第一阶段:环境搭建与工具链认知
  1. 交叉编译工具链安装与配置
    • 安装gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf
    • 配置环境变量(修改.bashrc文件)。
    • 验证安装(arm-linux-gnueabihf-gcc -v)。
  2. 代码传输与烧录
    • 在 Ubuntu 上配置 FTP 服务 (vsftpd)。
    • 使用 Windows 下的FileZilla Client工具上传代码到 Ubuntu 开发机。
    • 使用imxdownload工具将生成的.bin文件烧录到 SD 卡 (/dev/sdb)。
  3. 开发板启动方式
    • 了解 i.MX6ULL-Mini 开发板的多种启动模式(SD卡、eMMC、NAND Flash、USB)。
    • 通过拨码开关选择从 SD 卡启动。
  4. GNU 工具链详解
    • 编译器 (arm-linux-gnueabihf-gcc): 将源代码(.S,.c)编译成目标文件(.o)。
    • 链接器 (arm-linux-gnueabihf-ld): 将一个或多个目标文件链接成可执行文件(.elf),并根据链接脚本分配地址。
    • 格式转换器 (arm-linux-gnueabihf-objcopy): 将.elf文件转换为纯二进制格式(.bin),用于烧录。
    • 反汇编器 (arm-linux-gnueabihf-objdump): 将.elf文件反汇编成人类可读的汇编代码,用于调试和分析。
  5. Makefile 自动化构建
    • 理解 Makefile 的三要素:目标、依赖、规则。
    • 编写规则来自动化执行编译、链接、格式转换、反汇编等步骤。
    • 使用变量(如CC,LD)简化和优化 Makefile。
    • 定义伪目标(如clean,load)来执行清理和烧录操作。
第二阶段:ARM 汇编语言基础
  1. 汇编程序结构与伪操作
    • AREA: 定义代码段或数据段。
    • CODE32/THUMB: 指定指令集(32位 ARM 或 16位 Thumb)。
    • ENTRY: 定义程序入口点。
    • END: 标记汇编源文件结束。
    • .global _start: 声明全局符号_start,作为程序入口。
  2. 核心数据处理指令
    • MOV: 数据传送指令。理解立即数(12位立即数的判断标准)、寄存器寻址、移位操作(LSL, LSR, ASR, ROR, RRX)。
    • ADD/SUB: 加法/减法指令。
    • MVN: 按位取反传送指令。
    • BIC: 位清零指令(AND NOT)。
    • ORR: 逻辑或指令(用于置位)。
  3. 内存访问指令 (Load/Store)
    • LDR: 从内存加载数据到寄存器。掌握多种寻址方式(立即数偏移、寄存器偏移、前/后索引等)。
    • STR: 将寄存器数据存储到内存。
  4. 程序状态寄存器 (CPSR) 与条件执行
    • CPSR 标志位:
      • N(Negative): 结果为负。
      • Z(Zero): 结果为零。
      • C(Carry): 无符号运算产生进位或借位。
      • V(oVerflow): 有符号运算溢出。
    • CMP: 比较指令(实质是做减法但不保存结果,只更新 CPSR 标志位)。
    • 利用条件码(如EQ,NE,GT,LT等)实现条件执行。
  5. 程序流控制指令
    • B: 无条件或条件分支跳转。
    • BL: 带返回的分支跳转(将下一条指令地址存入LR)。
    • BX: 间接跳转,并可切换指令集状态(ARM/Thumb)。
  6. ARM 处理器工作模式
    • 7 种基本模式: User, FIQ, IRQ, Supervisor (SVC), Abort, Undef, System。
    • Cortex-A 特有模式: Monitor (安全扩展)。
    • 模式切换: 通过修改 CPSR 寄存器的 M[4:0] 位域。
      • MRS: 读取 CPSR 到通用寄存器。
      • MSR: 将通用寄存器的值写入 CPSR。
    • CPS 指令: 快速开关中断和切换模式(如cpsid i,cpsie i,cps #mode)。
  7. 异常向量表
    • 处理器复位后从固定地址(通常是0x0)开始执行。
    • 异常向量表包含各种异常(复位、未定义指令、SWI、预取中止、数据中止、IRQ、FIQ)的入口地址。
    • 软中断 (SWI): 用于在用户模式下请求内核服务(系统调用)。
第三阶段:函数调用与栈管理
  1. 函数调用机制
    • PC 与 LR:BL指令将返回地址存入LR(R14),函数通过BX LRMOV PC, LR返回。
    • 寄存器传参: ARM AAPCS 规约规定,前 4 个参数通过R0-R3传递,返回值通过R0返回。
  2. 栈 (Stack) 的概念与类型
    • 满栈 (Full Stack): 栈指针指向最后一个有效数据项。
    • 空栈 (Empty Stack): 栈指针指向下一个要放入数据的位置。
    • 增栈 (Ascending): 栈向高地址增长。
    • 减栈 (Descending): 栈向低地址增长。
    • ARM 采用:满减栈 (Full Descending Stack)
  3. 栈指针初始化
    • 使用LDR SP, =0x40001000初始化栈顶指针(SP, R13)。
  4. 保护与恢复现场 (压栈/弹栈)
    • STMFD (Store Multiple Full Descending):STMFD SP!, {寄存器列表}。将寄存器列表中的值压入栈,并更新 SP。
    • LDMFD (Load Multiple Full Descending):LDMFD SP!, {寄存器列表}。从栈中弹出值到寄存器列表,并更新 SP。
    • 主调函数职责: 在调用子函数前后,负责保存和恢复自己需要使用的寄存器(包括LR)。
  5. 栈对齐问题
    • PRES8 伪指令: 确保栈指针在函数调用时保持 8 字节对齐,以满足某些 ABI 要求,避免链接错误。
  6. 混合编程 (C 与汇编互调)
    • 汇编调用 C 函数:
      1. 在汇编中使用IMPORT c_func_name声明。
      2. 按规约准备参数(R0-R3)。
      3. 使用BL c_func_name调用。
      4. R0获取返回值。
    • C 调用汇编函数:
      1. 在汇编中使用EXPORT asm_func_name导出函数。
      2. 在 C 中使用extern声明该函数原型。
      3. 像调用普通 C 函数一样调用它。
第四阶段:启动代码与 C 语言运行环境搭建
  1. 启动代码的核心任务
    • 初始化异常向量表。
    • 为各处理器模式(SVC, IRQ, FIQ, ABT, UND)设置独立的栈指针。
    • 初始化.bssCOMMON段(清零)。
    • (可选)关闭看门狗、初始化时钟、DDR 等。
    • 设置处理器为UserSVC模式。
    • 跳转到 C 语言的main()函数。
  2. 链接脚本 (Linker Script)
    • 作用: 为链接器提供内存布局蓝图,精确控制各段(.text,.rodata,.data,.bss)在内存中的位置。
    • 关键语法:
      • SECTIONS { ... }: 定义输出段。
      • . = 0x87800000;: 设置当前链接地址(Location Counter)。
      • *(.text): 收集所有输入文件的.text段。
      • *(.rodata*): 使用通配符收集所有以.rodata开头的段(如.rodata.str1.1)。
      • __bss_start = .; ... __bss_end = .;: 定义符号,标记.bss段的起始和结束地址,供启动代码用于清零。
  3. 内存段 (Memory Segments) 详解
    • .text: 代码段,存放程序的机器指令。
    • .rodata: 只读数据段。存放字符串常量、const全局变量、跳转表等。运行时不可写。
    • .data: 已初始化数据段。存放初始化为非零值的全局/静态变量。程序镜像中包含其初始值。
    • .bss: 未初始化数据段。存放初始化为0或未显式初始化的静态/全局变量。程序镜像中不占空间,运行时由启动代码清零。
    • COMMON: 未初始化的非静态全局变量。在链接时才确定大小和位置,最终通常与.bss合并。
第五阶段:i.MX6ULL 裸机外设驱动开发
  1. 硬件抽象与寄存器访问
    • volatile关键字: 告诉编译器不要优化对该变量的访问,因为其值可能被硬件异步修改。
    • 直接地址映射:#define GPIO1_DR *((volatile unsigned int *)0x0209C000)
    • 结构体映射: 将外设寄存器组定义为结构体,提高代码可读性和可维护性。c

      编辑

      struct GPIO_t { unsigned int DR; unsigned int GDIR; // ... other registers }; #define GPIO1 (*((struct GPIO_t *)0x0209C000))
  2. SDK (Software Development Kit) 的使用
    • 主要利用 NXP 提供的头文件(如MCIMX6Y2.h,fsl_common.h,fsl_iomuxc.h)。
    • 使用 SDK 封装好的 API(如IOMUXC_SetPinMux,IOMUXC_SetPinConfig)进行引脚复用和电气属性配置。
  3. GPIO 驱动开发流程 (以 LED 为例)
    • 时钟使能: 配置CCM(Clock Control Module) 寄存器,打开对应外设的时钟门控。
    • 引脚复用 (IOMUX): 配置IOMUXC_SW_MUX_CTL_PAD_xxx寄存器,将引脚功能设置为 GPIO。
    • 电气属性配置: 配置IOMUXC_SW_PAD_CTL_PAD_xxx寄存器,设置驱动能力、上下拉等。
    • GPIO 方向设置: 配置GPIOx_GDIR寄存器,设置为输出模式。
    • GPIO 数据操作: 通过GPIOx_DR寄存器进行置位(开灯)、清零(关灯)或异或(翻转)操作。
  4. BSP (Board Support Package) 工程管理
    • 分层架构:
      • project/: 存放main.c,start.S等主程序文件。
      • imx6ull/: 存放 SoC 相关的官方头文件。
      • bsp/: 存放板级外设驱动模块(如led.c/h,beep.c/h)。
    • 优点: 模块化、可重用、易于维护。
  5. 蜂鸣器 (BEEP) 驱动
    • 原理:通过 GPIO 控制 PNP 三极管(如 S8550)的基极,从而控制蜂鸣器的通断。高电平导通,蜂鸣器响。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 21:21:40

短视频配音笑声检测,用SenseVoiceSmall轻松标记事件

短视频配音笑声检测,用SenseVoiceSmall轻松标记事件 1. 为什么短视频需要智能语音分析? 你有没有遇到过这种情况:剪辑一段搞笑短视频时,背景里的笑声总是来得不合时宜?或者你想在某个“笑点”位置加个特效&#xff0…

作者头像 李华
网站建设 2026/4/17 1:07:24

计算机毕业设计springboot大学生就医服务移动应用 基于SpringBoot的校园智慧医疗助手小程序 SpringBoot+Android高校学生在线诊疗平台

计算机毕业设计springboot大学生就医服务移动应用(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。移动互联网把校医院装进口袋,却让“排队两小时、看病五分钟”仍是大…

作者头像 李华
网站建设 2026/4/17 1:18:54

做了十年DBA,我为什么对“AI优化SQL”从警惕变为认同?

推荐阅读把DBA的经验写成程序:我如何用LLMKGML实现了SQL智能优化?END数据驱动,成就未来,云和恩墨,不负所托!云和恩墨创立于2011年,是业界领先的“智能的数据技术提供商”。公司以“数据驱动&…

作者头像 李华
网站建设 2026/4/16 12:55:14

如何用好VibeThinker-1.5B?系统提示词设置最佳实践教程

如何用好VibeThinker-1.5B?系统提示词设置最佳实践教程 1. VibeThinker-1.5B 是什么?轻量模型,强大推理 你有没有遇到过这样的情况:想跑一个AI模型做编程题或数学题,结果发现动辄几十亿参数的模型太吃资源,…

作者头像 李华
网站建设 2026/4/16 14:26:47

短视频创作者福音,AI自动识别音频中的笑点

短视频创作者福音,AI自动识别音频中的笑点 你有没有过这样的经历:剪辑一条3分钟的脱口秀音频,反复听十几遍,就为了找出那几个“观众爆笑”的瞬间?手动标记笑声位置、截取高光片段、配上字幕和特效——一上午就没了。更…

作者头像 李华
网站建设 2026/4/16 16:45:23

零基础手把手教用YOLOv13镜像,快速上手不踩坑

零基础手把手教用YOLOv13镜像,快速上手不踩坑 你是不是也经历过这样的场景:好不容易找到一个目标检测项目,兴冲冲地准备跑起来,结果卡在环境配置上——依赖冲突、CUDA版本不对、PyTorch编译出错……折腾半天,代码还没…

作者头像 李华