ARM学习笔记(四)

第四天的内容围绕裸机开发的编译流程、可执行文件结构和外设驱动展开,把核心点整理如下。

一、交叉编译工具链作用

裸机开发用的是arm-linux-gnueabihf工具链,四个核心工具各司其职:

gcc:编译器,把.c和.S源文件编译成.o目标文件,只做编译和汇编,不做链接。

ld:链接器,把多个.o目标文件拼接起来,指定程序运行的起始地址,生成elf可执行文件。

objcopy:格式转换工具,把elf文件转换成纯二进制的bin文件,去掉调试信息和段头,直接可以烧写到开发板运行。

objdump:反汇编工具,把elf文件反编译成汇编代码,用来调试和查看程序结构。

完整的编译链接流程:

bash

编译汇编启动文件

arm-linux-gnueabihf-gcc -g -c start.S -o start.o

编译C文件

arm-linux-gnueabihf-gcc -g -c main.c -o main.o

链接,指定代码段起始地址

arm-linux-gnueabihf-ld -Ttext 0x87800000 start.o main.o -o led.elf

转成二进制烧录文件

arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

反汇编查看

arm-linux-gnueabihf-objdump -D led.elf > led.dis

二、可执行文件的段区别

elf文件按内容分成不同的段,各有分工:

.text段:存放代码和指令,是只读可执行的,程序运行的入口就在这里。

.data段:存放已经初始化的全局变量和静态变量,可读可写。

.rodata段:存放只读常量,比如字符串常量、const修饰的变量。

.bss段:存放初始化为0的全局变量和静态变量,不占用bin文件空间,程序运行时自动清0。

.common段:存放未初始化的全局变量,链接时会合并到bss段。

三、Makefile与链接脚本

Makefile三要素

目标:最终要生成的文件

依赖:生成目标需要用到的源文件

规则:生成目标的具体命令

工程大了之后可以用Makefile统一管理编译,避免每次手动敲多条命令。编译时还可以用 -I 指定头文件路径, -L 指定库文件路径。

链接脚本

比 -Ttext 更灵活的地址指定方式,用特殊语法的lds文件规划内存布局。IMX6ULL的DDR3地址范围是0x80000000~0xA0000000,共512MB,我们一般把程序放到0x87800000起始的位置。

四、LED和蜂鸣器实现流程

裸机操作外设本质就是操作寄存器,步骤都是统一的:

  1. 开时钟:外设默认时钟关闭,先配置CCM寄存器打开对应时钟。

  2. 引脚复用:配置IOMUXC寄存器,把引脚设置为GPIO功能。

  3. 引脚电气属性:配置上下拉、摆率等电气参数。

  4. GPIO配置:设置GPIO方向为输出,然后写DR寄存器控制高低电平。

C语言操作寄存器的方式,直接通过地址指针访问:

// 定义寄存器地址

#define CCM_CCGR0 (*((volatile unsigned int *)0x020C4068))

// 打开所有时钟

CCM_CCGR0 = 0xFFFFFFFF;

这里必须加 volatile 关键字,作用是告诉编译器,对这个变量的访问不要做优化,每次都直接从内存读写。因为寄存器的值可能会被硬件改变,编译器优化掉的话会出问题。不仅变量前可以加,指针前加volatile表示指向的内存空间不被优化。

工程上一般会把外设驱动分层放到bsp目录,比如led.c、led.h,beep.c、beep.h,主函数只调用接口,结构更清晰。

补充

不同芯片的存储结构不一样,比如S3C2440用nor flash,地址从0x0开始,代码可以直接寻址;IMX6ULL用nand flash或者EMMC,不能直接寻址,程序要先搬到DDR里运行。

相关推荐
自不量力的A同学9 小时前
Goldfish Scheme v18.11.39 发布了:迈向现代宏系统与多核并发
笔记
qq_401700419 小时前
STM32 GPIO 精讲|推挽 / 开漏 / 上拉浮空,工程选型避坑
stm32·单片机·嵌入式硬件
海里的果9 小时前
论文阅读笔记-<Alpamayo-R1 >
论文阅读·笔记
凌云若寒9 小时前
BarTender提示#807错误:无法在拥有其他许可证的Licensing Service上激活节点锁定的 Professional 版许可证 的解决办法
运维·服务器·前端·学习·软件需求
创界工坊工作室9 小时前
19-基于单片机的宠物喂养控制系统设计
stm32·单片机·嵌入式硬件·proteus·宠物
Julien200410 小时前
管理 Ansible 配置文件
linux·运维·服务器·ssh·学习方法
深圳市恒锐丰科技杨生10 小时前
EG3116D 600V 单路半桥栅极驱动芯片|屹晶 EGmicro
嵌入式硬件·硬件工程
MicrosoftCloud10 小时前
性能排查 01|free 显示内存用了 90% 就是快满了吗?buff/cache 与 available 一次讲清
linux·运维·内存·free·buff/cache
浅念-10 小时前
动态规划专题:斐波那契数列模型 + 网格路径DP(LeetCode例题全解析)
笔记·算法·leetcode·面试·职场和发展·动态规划·推荐算法
爱吃苹果的日记本10 小时前
离散数学第七课
学习·离散数学