一. 简介
本文针对 IMX6ULL 的裸机开发的(即不带Linux操作系统的开发)。
主要分两部分的工作:
1. 配置 C语言运行环境
2. C 语言编写及运行
二. 配置C语言运行环境
配置 C 语言运行环境的工作分 三部分。如下:
1. 设置处理器模式
2. 设置 sp 指针
3. 跳转到 C 语言
接下来具体介绍配置 C 语言运行环境的工作。
1. 设置处理器模式
设置6ULL处于SVC模式下。
设置 CPSR 寄存器(即程序状态寄存器)的 bit[4-0],就是 M[4:0] 为10011=0X13。
读写状态寄存器需要用到 MRS 和 MSR 指令(即汇编指令)。
MRS 指令:
MRS 将 CPSR 寄存器数据读出到通用寄存器里面。
MSR 指令:
MSR 指令将通用寄存器的值写入到 CPSR 寄存器里面去。
2. 设置sp指针
sp 指针,即栈指针。C 语言运行需要入栈/出栈,入栈/出栈就需要 sp 指针。通过 sp 指针指定一段栈内存。
sp 可以指向内部 RAM,也可以指向 DDR,我们将其指向 DDR。
Sp设置到哪里?
512MB 的范围 0x80000000~0x9FFFFFFF。我们这里决定分配栈大小为 0x200000=2MB。处理器栈增长方式,对于 cortex-A7 而言,栈地址向下增长的。设置 sp 指向 0x80200000。
栈地址向下增长,如下图所示:
可以看出,首地址不能为 0x80000000,地址向下增长会在 0x7XXXXXXX 这样的地址。非法的内存地址,则代码运行就崩溃了。
注意:根据处理器的栈的增长方向,来设置 sp 指针,否则会出错。
3. 跳转到 C 语言
使用 b 指令,跳转到 C 语言函数,比如 main 函数。
三. 汇编实现
在做 嵌入式开发时,需要了解处理器的启动方式。恩智浦这款芯片 在 x.bin 文件中加的头信息对 DDR 进行了初始化。
如果使用其他处理器,一定要看处理器的启动方式。如果处理器没法初始化 DDR,那么就需要程序员手动初始化 DDR ,即在设置 sp 指针之前初始化 DDR,否则,无法将 sp 指针设置到 DDR 地址中。
配置 C 语言运行环境的汇编代码实现入下:
汇编语言文件命名为 start.s。代码如下:
.global _start /* 全局标号 */
/*
* 描述: _start函数,程序从此函数开始执行,此函数主要功能是设置C
* 运行环境。
*/
_start:
/* 进入SVC模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */
orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式 */
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */
ldr sp, =0X80200000 /* 设置栈指针 */
b main /* 跳转到main函数 */
以上汇编语言实现了配置 C 语言运行的环境。之后 即可再写 C 源码,然后,编译链接。烧录 SD 卡后即可在开发板运行了。
运行原理:以上的 汇编代码首先会执行,之后进入 C 语言的 main 函数执行 C 代码部分。