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里运行。

相关推荐
东鹏特饮1 小时前
redhat9 配置yum 阿里云
linux·运维·redhat·yum
昌原的儿子LEO1 小时前
i.MX6ULL 裸机开发 C 语言驱动与 BSP 工程管理学习总结
linux·arm开发·学习
lqg_zone1 小时前
CentOS 7 虚拟机磁盘 I/O 卡顿排查实录:从 iostat 异常到虚拟盘后端故障的完整定位
linux·服务器·mysql·centos
kkkkkkkkkk_Z1 小时前
单片机|学习日记:单片机底层架构与寄存器操作全解析
linux·笔记·单片机·学习·51单片机
半导体憨包1 小时前
光伏组件级MLPE功率优化器DCDC:25年寿命+IP67+雷击,怎么设计才不“翻车“?
嵌入式硬件·硬件工程·dc-dc·半导体芯片
xiaoye-duck1 小时前
《Linux 网络编程》深入理解 IP 协议(一):网络层基础与 IP 协议头详解
linux·网络·ip
LCG元1 小时前
STM32F103 双ADC交错采样实战:DUALMOD寄存器拆解、DMA位宽陷阱与1.71MSPS有效采样率实测
stm32·单片机·嵌入式硬件
ao-weilai2 小时前
Linux网络编程:Linux Socket TCP
linux·服务器·网络
顶点多余2 小时前
9.16 面试总结
linux·面试·职场和发展