正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.5, 汇编 led.s,第一次点亮LED灯

前言:

本文是根据哔哩哔哩网站上"正点原子[第二期]Linux之ARM(MX6U)裸机篇"视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。

引用:

正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》第 8.1 章

《正点原子资料_A盘/02开发板原理图/IMX6ULL_MINI_V2.2(Mini底板原理图).pdf》

正文:

本文是 "正点原子[第二期]Linux之ARM(MX6U)裸机篇--第6.5讲" 的读书笔记。

本文是根据正点原子可成Linux之ARM裸机开发的第6.4讲,第6.5 讲的内容,第一次在正点原子 I.MX6ULL Mini 开发板上,通过ARM汇编 led.s 程序第一次成功的点亮开发板上的LED灯。

也记录一下遇到的第一个裸机 ARM 的开发 led.s 遇到的 Bug。裸机 ARM 汇编开发的bug与C语言相比还是难以调试和找出Bug原因的,应为都是一个以寄存器,每一个寄存器的bit位反应的是对应物理 IO 接口的特性,不直观。

1. 视频 6.4讲和6.5讲 编写并编译汇编 led.s

根据正点原子视频 6.4讲和6.5讲 编写并编译汇编 led.s,然后进行编译,在第6.4 讲中说从汇编 led.s 源码编译出 led.elf,之后需要使用 objcopy 把 led.elf 文件从 ELF 格式转换为 .bin格式,然后.bin 格式还不能直接烧录到 SD 卡中。

第 6.5 讲详细的讲了 I.MX6U 芯片的从上电开始进行 BOOT 模式选择,和 BOOT Device 设备选择的配置,在 I.MX6U 的参数考手册里说明了 I.MX6U 上电之后通过 BOOT_MODE1, BOOT_MODE0 选择串口启动,还是芯片内部 boot Rom启动。如果是选择I.MX6U 芯片内部 boot ROM启动,参考手册又说明了如何根据 BOOT_CFG6[7:0], BOOT_CFG2[7:0], BOOT_CFG1[7:0] 通过GPIO来配置BOOT启动设备,通过不同的GPIO配置来选择 I.MX6U 上电启动之后 boot ROM 是从 SD, MMC, NAND Flash, NOR Flahs 这些那种外部存储设别中拷贝复制 .bin 文件到外部 DDR RAM中,然后到RAM中执行。

2. 视频6.5 讲接收了 I.MX6U 的 .bin 为什么要加上一个Header

从 led.s 汇编源码编译出来的 led.elf文件,然后使用 objecopy 把 led.elf 文件转换为 .bin 格式文件。然后 .bin 格式文件并不能直接烧录到SD卡中,然后让 I.MX6U 直接上电从SD卡中拷贝到DDR RAM中执行。I.MX6U 参考手册对于每一种 Boot Device 启动设备,都有要求 .bin 文件格式应该烧录到存储设备的哪个位置,在.bin文件的头部应该附加上哪些额外的header信息。

正点原子团队,根据NXP I.MX6U 的官方文档手册和NXP提供的 boot.bin 文件反推出了,烧录到不同的存储设备 SD卡,MMC, NAND Flash, NOR Flash中,需要附加的 header 信息有:

header = IVT + Boot Data + DCD

  • IVT: Image Vector Table
  • Boot Data: Boot Data
  • DCD: Device Config Data

并且 IVT, Boot Data, DCD 这些数据 NXP I.MX6U 芯片都规定定义了数据的格式,需要严格按照这些数据格式来填写数据header部分。

|--------------------------|------------------------------------------------------|
| 数据头 | 描述 |
| IVT | 固定地址的指针数组,记录了程序的入口地址 entry(绝对地址),DCD数据的绝对地址 |
| Boot Data | 记录了程序的起始地址,程序的长度 |
| DCD(Device Congfig Data) | 对外部DDR控制寄存器进行初始化所需的数据,主要是外部DDR控制寄存器的地址和对应寄存器地址需要写的值。 |

只有把需要的 IVT + Boot Data + DCD 组成的header部分添加到 led.bin,并且把重组之后的文件烧录到指定的 SD 某个起始偏移位置的扇区,才能在 I.MX6U 上电启动之后,芯片内部 boot ROM 从选择启动模式

3. 记录编写调试汇编 led.s 的一个Bug

在根据正点原子6.4讲,6.5讲,编写了汇编 led.s 程序,并烧录到SD卡启动之后,我编写的程序没有能正常点亮开发板的LED灯。

整个人懵逼了,问题出在哪里?因为是在ARM裸板上进行开发, 操作的都是寄存器的一个个bit位,操作bit位的结果是控制IO口的"复用特性","电气特性","GPIO的方向","GPIO的输出数据","外设时钟",这些东西都是从I.MX6U的芯片内部的东西,从ARM开发裸板上看不见莫不这,没有办法调试。

从这里也可以看出来,ARM逻辑开发设计到寄存器的设置的程序,如果程序出了bug真的很难调试,因为每一个寄存器都是32bit的,而寄存器的这32bit的每一个bit位都有它的物理(电气特性)含义,又涉及到多个寄存器,当出现了某个IO口没有按照程序预期输出对应的高电平或者低电平时,真的很难调试,你不清楚到底是哪一个寄存器写错了,是寄存器地址写错了?还是寄存器值的某一个bit位写错了?

还好,正点原子提供了 led.s 的示例源码。把正点原子的示例 led.s 源码编译烧写到 SD 卡上,上电启动开发板上 LED 灯正常亮起来。比对下正点原子提供了 led.s 实例源码,和我自己编写的 led.s 源码,很快就发现是我自己写的源码中 GPIO1_DR 寄存器的值写错了。正确的应该是 "GPIO1_DR=0x08",而我写成了 "GPIO1_DR=0x80",这样就没有正确的让对应的 GPIO1_IO03 bit 位输出低电平,LED灯也就不会亮起来了。

这个Bug还好有可以比对的正常执行的源码,才可以发现;如果没有可以比对的源码那?真的很难调试呀。

相关推荐
糖豆豆今天也要努力鸭14 分钟前
torch.__version__的torch版本和conda list的torch版本不一致
linux·pytorch·python·深度学习·conda·torch
烦躁的大鼻嘎22 分钟前
【Linux】深入理解GCC/G++编译流程及库文件管理
linux·运维·服务器
ac.char29 分钟前
在 Ubuntu 上安装 Yarn 环境
linux·运维·服务器·ubuntu
敲上瘾30 分钟前
操作系统的理解
linux·运维·服务器·c++·大模型·操作系统·aigc
EterNity_TiMe_1 小时前
【论文复现】(CLIP)文本也能和图像配对
python·学习·算法·性能优化·数据分析·clip
长弓聊编程1 小时前
Linux系统使用valgrind分析C++程序内存资源使用情况
linux·c++
sanguine__1 小时前
java学习-集合
学习
lxlyhwl1 小时前
【STK学习】part2-星座-目标可见性与覆盖性分析
学习
nbsaas-boot1 小时前
如何利用ChatGPT加速开发与学习:以BPMN编辑器为例
学习·chatgpt·编辑器
cherub.1 小时前
深入解析信号量:定义与环形队列生产消费模型剖析
linux·c++