目录
启动模式(8引脚设置启动模式)
三大模式:
熔丝:烧录一次,发布产品。
外部:USB、串口等。
内部:SD卡、EMMC、NAND。
设置方法:BOOT_MODE0、BOOT_MODE1。
内部介质设置方法:BT_CFG1[4:7]
接口编号设置方法:BT_CFG2[3]
介质属性设置方法:如SD、EMMC,位宽(BT_CFG2[5])
对应原理图
boot ROM程序
选择内部启动方式,启动boot ROM程序
初始化时钟、外部DDR3
从外部存储介质加载代码
镜像空偏移,由芯片厂商设定。
Image vector table(IVT),关键数据位置。
Boot data,启动数据。镜像加载地址、大小。
Device configuration data(DCD),关键外设的寄存器配置信息(时钟、DDR3相关)。
bin文件,真正程序文件。
空偏移
镜像不是从存储介质头部开始存储的,不同介质分别对应一段偏移地址。
映像向量表(Image vector table,IVT)
映像向量表是ROM从提供程序映像的引导设备中读取的数据结构,该程序映像包含成功启动所需的数据组件。
IVT包含程序映像入口点、指向设备配置数据(DCD)的指针和ROM在引导过程中使用的其他指针。
IVT结构体
Boot data
Boot data记录“镜像”在内存中的加载地址和大小。
DCD(外设寄存器配置信息,初始化关键外设)
复位后,芯片使用系统中所有外设的默认寄存器值。但是,这些默认值对于实现最佳系统性能来说并不理想,深圳有些外设在使用之前必须进行配置。DCD是包含在程序镜像中的配置信息,ROM对其解释以配置芯片上的各种外设。
例如,EIM默认配置允许核心在复位后立即连接到NOR闪存设备。这允许芯片与任何NOR闪存设备接口,但缺点是性能慢。此外,一些组件(如DDR)在准备使用之前需要一些寄存器编程作为配置的一部分。DCD可用于将EIM寄存器和MMDC寄存器编程到最佳配置。
ROM根据IVT的信息可确定DCD的位置。
NXP官方I.MX 6ULL开发SDK
下载SDK2.2_iMX6ULL_LINUX。下载完成后名字为:SDK_2.2_MCIM6ULL_RFP_Linux.run
虚拟机通过共享文件夹得到。并运行。
./SDK_2.2_MCIM6ULL_RFP_Linux.run
运行完成,会在\opt\生成SDK_2.2_MCIM6ULL文件夹。
在\opt\SDK_2.2_MCIM6ULL\tools\imgutil\readme.txt附有说明文档。
1、复制.bin文件到imgutil\evkmcimx6ull文件下,并重命名为sdk20-app.bin。
2、在imgutil\evkmcimx6ull文件下,终端中运行mkimage.sh命令,获取可启动的镜像文件sdk20-app.imag。
如果镜像是用RAM链接文件构成的,使用“mkimage.sh ram”命令制作可启动镜像。
如果镜像是用Flash链接文件构成的,使用“mkimage.sh flash”命令制作可启动的XIP镜像。
如果镜像是用RAM链接文件构成的,并希望从MicroSD卡启动,使用“mkimage.sh sd”命令制作可启动镜像。
根据mkimage.sh和dcd.config文件,dcdgen.bin生成DCD表,imgutil.bin生成img可烧录镜像。
VSCode
下载deb_x64文件,存于虚拟机linux中。
安装:sudo dpkg -i xxx.deb
启动:code
使用特点:
无需新建项目,直接打开文件夹。
不同目录下的文件夹,可保存在工作区。
默认预览模式。不需要可在Setting中输入“preview”,取消勾选:Workbench > Editor:Enable Preview
推荐插件:
c/c++:函数跳转、自动补全。
Chinese:中文。
material theme:UI。
CodeSpell Checker:拼写检查。
rainbow-highlighter:变量彩虹高光。
shift+alt+z:变量彩虹高光。
shift+alt+a:取消变量彩虹高光。
ARM:汇编插件。
高效工作:
移动光标到行首:home
移动光标到行尾:end
跳转文档头部:ctrl+home
跳转文档尾部:ctrl+end
花括号跳转:ctrl+shift+\
文件跳转:ctrl+p
行跳转:ctrl+g
批量修改:F2
GPIO
数量:五组GPIO(GPIO1~GPIO5),每组最多32个,共124个。
GPIO1_IO0~GPIO1_IO31
GPIO2_IO0~GPIO2_IO21
GPIO3_IO0~GPIO3_IO28
GPIO4_IO0~GPIO4_IO28
GPIO5_IO0~GPIO5_IO11
clock controller module(CCM模块)用于配置芯片的各种外设时钟。跟GPIO相关的时钟主要有CCM_CCGR(0~3)寄存器。
//经典汇编led.s
.global _start
_start:
@使能GPIO时钟
ldr r0,=0x20c406c @将0x20c406c加载到寄存器r0
ldr r1,=0xffffffff @将0xffffffff加载到寄存器r1
str r1,[r0] @将寄存器r1的值存储到r0寄存器指向的地址
@设置引脚复用为GPIO
ldr r0,=0x20e006c
ldr r1,=5
str r1,[r0]
@设置引脚属性(上下拉、速率、驱动能力)
ldr r0,=0x20e02f8
ldr r1,=0x10b0
str r1,[r0]
@控制GPIO引脚输出高低电平
ldr r0,=0x209c004
ldr r1,=16
str r1,[r0]
ldr r0,=0x209c000
ldr r1,=0
str r1,[r0]
1、下载裸机的gcc编译器:sudo apt-get install gcc-arm-none-eabi
2、编译汇编文件为可重定位文件led.o:arm-none-eabi-gcc -c led.s -o led.o
3、把重定位文件链接起来,得到可执行程序(elf文件):arm-none-eabi-ld -Ttext 0x80000000 led.o -o led.elf
4、把elf文件去掉冗余的段和elf头,得到纯净的bin文件:arm-none-eabi-objcopy -O binary led.elf led.bin
5、给bin文件添加6ull特殊的头部信息(IVT + boot data + DCD),并烧录到sd卡:./mkimage.sh xxx.bin
使用官方SDK
引入SDK头文件目的:解决寄存器地址难查、难设置。
devices/MCIMX6Y2/MCIMX6Y2.h:记录外设寄存器及其相关操作。
devices/MCIMX6Y2/drivers/fsl_iomuxc.h:记录引脚复用及其相关操作。
devices/MCIMX6Y2/MCIMX6Y2.h:
注释:
#include "core_ca7.h"
#include "system_MCIMX6Y2.h"
添加:
#define __O volatile
#define __IO volatile
#define __I volatile const
#define uint32_t unsigned int
#define uint16_t unsigned short
#define uint8_t unsigned char
bin文件组成(段是程序的基本组成元素):
.text段:代码文本
.rodata段:只读变量,如const修饰的变量
.data段:非零的全局变量、静态变量。
.bss段:值为0的全局变量、静态变量。
.comment段:存放注释。
链接脚本引入
目的:指定链接地址、起始代码在text段的位置,其他段的位置。
SECTIONS{
. = xxx //链接起始地址
.段名
{
xxx
*(.段名)
}
...
}
led.s
.global _start
_start:
@设置栈地址为64M,0x80000000~0xA0000000,512MB
ldr sp,=0x84000000
@跳转main函数
b main
led.c
#include "../include/MCIMX6Y2.h"
#include "../include/fsl_iomuxc.h"
/* 简单延时函数 */
void delay(uint32_t count)
{
volatile uint32_t i=0;
for(i=0; i<count; i++)
{
__asm("NOP"); /* 调用nop空指令 */
}
}
int main()
{
/* 使能GPIO1时钟 */
CCM->CCGR1 = 0Xffffffff;
/* 设置 红灯引脚的复用以及属性 */
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO04, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO04, 0x10b0);
/* 设置 GPIO1_04为输出模式 */
GPIO1->GDIR |= (1<<4);
/* 设置 GPIO1_04输出电平为高电平 */
GPIO1->DR |= (1<<4);
while(1)
{
GPIO1->DR &= ~(1<<4); //红灯亮
delay(0xfffff);
GPIO1->DR |= 1<<4; //红灯灭
delay(0xfffff);
}
return 0;
}
script.lds
SECTIONS{
.=0x80000000;
.text ALIGN(4):
{
build/start.o
*(.text)
}
.rodata ALIGN(4):
{
*(.rodata)
}
.data ALIGN(4):
{
*(.data)
}
__bss_start=.;
.bss ALIGN(4):
{
*(.bss)
*(COMMON)
}
__bss_end=.;
}
Makefile
ifeq ($(ARCH),x86)
CC=gcc
else
CC=arm-none-eabi-gcc
LD=arm-none-eabi-ld
OBJCOPY=arm-none-eabi-objcopy
endif
TARGET=led
BUILD_DIR=build
SRC_DIR=sources
INC_DIR=include
CFLAGS=$(patsubst %,-I %,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))
SOURCE_c=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
SOURCE_s=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.s))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCE_c)))
OBJS+=$(patsubst %.s,$(BUILD_DIR)/%.o,$(notdir $(SOURCE_s)))
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET).bin:$(OBJS)
$(LD) -Tscript.lds -o $(BUILD_DIR)/$(TARGET).elf $^
$(OBJCOPY) -O binary $(BUILD_DIR)/$(TARGET).elf $@
$(BUILD_DIR)/%.o:%.c $(INCLUDE) | create_build
$(CC) -c $< -o $@ $(CFLAGS)
$(BUILD_DIR)/%.o:%.s $(INCLUDE) | create_build
$(CC) -c $< -o $@ $(CFLAGS)
.PHONY:clean create_build burn
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)
burn:
cp $(BUILD_DIR)/$(TARGET).bin /home/couvrir/make_testfile1
cd /home/couvrir/make_testfile1 && ./mkimage.sh $(TARGET).bin