小白参考了正点原子和行稳方能走远两位博主的资料
文章名字:ARM(IMX6U)裸机之I.MX6ULL启动头文件详解(内部BOOT ROM、IVT + Boot data + DCD + led.bin)
作者:行稳方能走远
原文地址:https://blog.csdn.net/zhuguanlin121/article/details/118915190
近几日学习来总结一下学习内容(强烈建议在vim编辑器下面进行程序的编写):
一、硬件启动要搭建软件环境前提就得先把硬件环境搭建好。
第一步:要先选择是内部启动还是外部启动。我现在只会SD卡启动这一方式,但是我觉得只要会如何选择启动设备、启动头文件,这些只是小问题。设置MODE1和MODE0是从内部BOOT启动的,也就是MODE1=1,MODE0=0。这个不用理解暂时,I.MX6ULL数据手册有资料可以查。选择了内部BOOT启动后,我们可以选择的启动设备就很多了,有:OR flash,oneNAND、NAND Flash、QSPI flash、SD/EMMC、EEPROM等等,我们最常用的就是NAND、SD、EMMC,QSPI(六线SPI)因为价格昂贵,使用率并不高。
第二步:启动头文件启动头文件:
1.让BOOT ROM使能Cache和MMU(cache是高速缓存,mmu是地址管理单元,将物理地址映射为虚拟地址),然后使能L1Cache L2cache MMU,目的就是为了加速启动。L1Cache打开时会下载镜像,然后L1Cache L2cache MMU全部打开来验证镜像。这个我也不太懂,我猜测可能是验证物理地址。+
2.将BOOT DATA 和 IVT(image vector table)数据块准备好! IVT 里面包含了一系列的地址信息,这些地址信息在ROM中按照固定的地址存放着。而Boot data,就是启动数据,包含了镜像要拷贝到哪个地址,拷贝的大小是多少等等。
3.将DCD(device configuration data)数据配置好,DCD是用来配置I.MX6ULL内部寄存器的。它主要是初始化外设,还有检查数据命令、NOP命令、解锁命令。这些其实也都属于DCD。
4.数据配置好之后,其实我也不知道该干什么。我只是了解到我们平时烧录给SD卡的数据是包括:IVT、BOOT DAT、DCD和.bin文件。他们加起来总共4KB大小,其中头部占3KB(IVT占32B、BOOT DATA占12B、DCD最大占1768B)。
5.正点原子的.imx文件load.imx 最前面的就是 IVT 和 Boot Data, IVT 包含了镜像程序的入口点、指向 DCD 的指针和一些用作其它用途的指针。内部 Boot ROM 要求 IVT 应该放到指定的位置,不同的启动设备位置不同。而 IVT 在整个 load.imx 的最前面,其实就相当于要求 load.imx 在烧写的时候应该烧写到存储设备的指定位置去。整个位置都是相对于存储设备的起始地址的偏移,偏移大概是4KB。
第三步:C语言运行环境的搭建1.设置处理器模式:将I.MX6ULL设置为SVC模式。设置CPSR寄存器的bit4-0,也就是M[4:0]为10011=0X13。
2.设置sp指针:Sp可以指向内部RAM,也可以指向DDR,我们将其指向DDR(DDR是外部ram),因为对于ARM-A7架构来说,处理器栈增长方式是向下增长,所以要设置sp指向0x80200000。(为什么要设置sp指针指向0x80200000我也没懂,以后知识层面扩大了会重新过来了解)
3.搭建完毕,跳转到C语言的主函数
.global _start @定义一个全局标号
_start:
mrs r0, cpsr @将CPSR的数据读入r0
bic r0, r0, #0x1f @r0=r0&0x1f
orr r0, r0, #0x13 @r0=r0|0x13
msr cpsr, r0 @将r0的数据写入CPSR
ldr sp, =0x80200000 @设置栈指针
b main @跳转到main函数
第四步:软件编写
1.先写出main.c的头文件
#ifndef __MAIN_H
#define __MAIN_H
/*
* CCM相关寄存器地址
*/
#define CCM_CCGR0 *((volatile unsigned int *)0X020C4068)
#define CCM_CCGR1 *((volatile unsigned int *)0X020C406C)
#define CCM_CCGR2 *((volatile unsigned int *)0X020C4070)
#define CCM_CCGR3 *((volatile unsigned int *)0X020C4074)
#define CCM_CCGR4 *((volatile unsigned int *)0X020C4078)
#define CCM_CCGR5 *((volatile unsigned int *)0X020C407C)
#define CCM_CCGR6 *((volatile unsigned int *)0X020C4080)
/*
* IOMUX相关寄存器地址
*/
#define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068)
#define SW_PAD_GPIO1_IO03 *((volatile unsigned int *)0X020E02F4)
/*
* GPIO1相关寄存器地址
*/
#define GPIO1_DR *((volatile unsigned int *)0X0209C000)
#define GPIO1_GDIR *((volatile unsigned int *)0X0209C004)
#define GPIO1_PSR *((volatile unsigned int *)0X0209C008)
#define GPIO1_ICR1 *((volatile unsigned int *)0X0209C00C)
#define GPIO1_ICR2 *((volatile unsigned int *)0X0209C010)
#define GPIO1_IMR *((volatile unsigned int *)0X0209C014)
#define GPIO1_ISR *((volatile unsigned int *)0X0209C018)
#define GPIO1_EDGE_SEL *((volatile unsigned int *)0X0209C01C)
#endif
2.编写源文件
#include "main.h"
/* 使能外设时钟 */
void clk_enable(void)
{
CCM_CCGR0 = 0xFFFFFFFF;
CCM_CCGR1 = 0xFFFFFFFF;
CCM_CCGR2 = 0xFFFFFFFF;
CCM_CCGR3 = 0xFFFFFFFF;
CCM_CCGR4 = 0xFFFFFFFF;
CCM_CCGR5 = 0xFFFFFFFF;
CCM_CCGR6 = 0xFFFFFFFF;
}
/* 初始化LED */
void led_init(void)
{
SW_MUX_GPIO1_IO03 = 0x5; //复用为GPIO1_IO03
SW_PAD_GPIO1_IO03 = 0x10B0; //设置GPIO1_IO03电气属性
/* GPIO初始化 */
GPIO1_GDIR = 0x8; //设置为输出
GPIO1_DR = 0x0; //打开LED灯
}
int main(void)
{
clk_enable();
//初始化LED
led_init();
while(1);
return 0;
}
代码编写完毕后,按原步骤将这些文件烧录给SD卡,然后将SD卡插进I.MX6ULL,将I.MX6ULL拨码开关选择为SD卡启动就ok了!
第四步:Makefile的编写arm-linux-gnueabihf-gcc -g -c led.s -o led.o
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.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
objs := start.o main.o
ledc.bin:$(objs)
arm-linux-gnueabihf-ld -Ttext 87800000 $^ -o ledc.elf
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
%.o:%.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
%.o:%.S
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
clean:
rm -rf *.o ledc.bin ledc.elf ledc.dis
download:
./imxdownload ledc.bin /dev/sdb
这里尝试使用了自动化变量,发现还是理解不了。下次还是一步一步来吧。
总结:学裸机开发,因为我有很多的STM32开发经验,所以这方面学起来事半功倍,而且能在这里能有32熟悉感,很亲切。很多地方还有不懂,但我相信经过我的深入学习,这些问题都会被我解决的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)