I.MX6U点灯(c语言)
Cortex-A7的九种运行模式
模式 | 描述 |
---|---|
User(USR) | 用户模式,非特权模式,大部分程序运行的时候就处于此模式。 |
FIQ | 快速中断模式,进入 FIQ 中断异常 |
IRQ | 一般中断模式。 |
Supervisor(SVC) | 超级管理员模式,特权模式,供操作系统使用。 |
Monitor(MON) | 监视模式?这个模式用于安全扩展模式。 |
Abort(ABT) | 数据访问终止模式,用于虚拟存储以及存储保护。 |
Hyp(HYP) | 超级监视模式?用于虚拟化扩展。 |
Undef(UND) | 未定义指令终止模式。 |
System(SYS) | 系统模式,用于运行特权级的操作系统任务 |
CPSR 寄存器
- M[4:0]: 处理器模式控制位
M[4:0] | 处理器模式 |
---|---|
10000 | User 模式 |
10001 | FIQ 模式 |
10010 | IRQ 模式 |
10011 | Supervisor(SVC)模式 |
10110 | Monitor(MON)模式 |
10111 | Abort(ABT)模式 |
11010 | Hyp(HYP)模式 |
11011 | Undef(UND)模式 |
11111 | System(SYS)模式 |
堆栈的上下增长方式
-
向上增长
低地址向高地址增长
-
向下增长
高地址向低地址增长
初始化c语言环境
-
进入SVC模式
将bit4-bit0配置为10011
-
设置栈指针
设置sp指针为0x80200000,ddr3的地址在0x80000000,栈的空间大小为0x200000=2M
-
跳转到main函数
点灯代码
start.s 初始化c语言环境
1 | .global _start |
main.h 定义相关寄存器
1 |
|
main.c 点灯程序
1 |
|
Makefile 自动编译文件
1 | objs := start.o main.o |
-
第一行:objs变量 包含生成ledc.bin的依赖文件。
-
第三行:生成文件ledc.bin,依赖start.o和main.o。
-
第四行:使用arm-linux-gnueabihf-ld链接,起始地址为0x87800000,“$^”表示所有依赖文件的集合,要把start.o放在最前面,因为需要汇编代码在最前面进行初始化。等同于:
arm-linux-gnueabihf-ld -Ttext 0x87800000 -o ledc.elf start.o main.o
-
第五行:使用arm-linux-gnueabihf-objcopy将ledc.elf文件转为ledc.bin文件,“$@”表示目标集合,等同于:
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf ledc.bin
-
第六行:使用arm-linux-gnueabihf-objdump反汇编,生成ledc.dis
-
后面是用arm-linux-gnueabihf-gcc把.s、.c、.S文件生成对应的.o文件,就是把start.s生成start.o,把main.c生成main.o
计算机基础之text段、data段、bss段和stack、 heap
-
text段
就是****放程序代码****的,编译时确定,只读;
程序代码段,在AT91库中是表示程序段的大小,它是由编译器在编译连接时自动计算的,当你在链接定位文件中将该符号放置在代码段后,那么该符号表示的值就是代码段大小,编译连接时,该符号所代表的值会自动代入到源程序中。
-
data段
存放在编译阶段(而非运行时)就能确定的数据,可读可写。也就是通常所说的静态存储区,赋了****初值的全局变量*和*赋初值的静态变量****存放在这个区域,常量也存放在这个区域;
静态初始化的数据,所以有初值的全局变量和static变量在data区。段的起始位置也是由连接定位文件所确定,大小在编译连接时自动分配,它和你的程序大小没有关系,但和程序使用到的全局变量,常量数量相关。
-
bss段
定义而****没有赋初值的全局变量和静态变量****,放在这个区域;
通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0。BSS段属于静态内存分配。它的初始值也是由用户自己定义的连接定位文件所确定,用户应该将它定义在可读写的RAM区内,源程序中使用malloc分配的内存就是这一块,它不是根据data大小确定,主要由程序中同时分配内存最大值所确定,不过如果超出了范围,也就是分配失败,可以等空间释放之后再分配。
-
栈区(stack)
由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
保存函数的局部变量和参数。是一种“后进先出”(Last In First Out,LIFO)的数据结构,这意味着最后放到栈上的数据,将会是第一个从栈上移走的数据。对于哪些暂时存贮的信息,和不需要长时间保存的信息来说,LIFO这种数据结构非常理想。在调用函数或过程后,系统通常会清除栈上保存的局部变量、函数调用信息及其它的信息。栈另外一个重要的特征是,它的地址空间“向下减少”,即当栈上保存的数据越多,栈的地址就越低。栈(stack)的顶部在可读写的RAM区的最后。
-
堆区(heap)
一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事。
保存函数内部动态分配内存,是另外一种用来保存程序信息的数据结构,更准确的说是保存程序的动态变量。堆是“先进先出”(First In first Out,FIFO)数据结构。它只允许在堆的一端插入数据,在另一端移走数据。堆的地址空间“向上增加”,即当堆上保存的数据越多,堆的地址就越高。
imx6ul.lds 链接文件
1 | SECTIONS{ |
总结
- 汇编初始化c语言环境
- 配置模式
- 配置sp指针
- 配置跳转函数
- h文件定义需要操作的寄存器
- CCM寄存器
- IOMUX 相关寄存器
- GPIO1 相关寄存器
- c文件配置寄存器以及逻辑代码
- 初始化时钟
- 初始化led灯(GPIO的配置)
- 延时函数
- Makefile文件
- o文件的生成
- bin文件的生成
- 链接起始地址 生成.elf
- .elf文件生成.bin文件