linux进阶-I.MX 6ULL

目录

启动模式(8引脚设置启动模式)

对应原理图

boot ROM程序

空偏移

映像向量表(Image vector table,IVT)

IVT结构体

Boot data

DCD(外设寄存器配置信息,初始化关键外设)

NXP官方I.MX 6ULL开发SDK


启动模式(8引脚设置启动模式)

三大模式:

熔丝:烧录一次,发布产品。

外部:USB、串口等。

内部:SD卡、EMMC、NAND。

设置方法BOOT_MODE0、BOOT_MODE1

内部介质设置方法BT_CFG1[4:7]

接口编号设置方法BT_CFG2[3]

介质属性设置方法:如SD、EMMC,位宽(BT_CFG2[5]

对应原理图

linux进阶-I.MX 6ULL_第1张图片

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在引导过程中使用的其他指针。

linux进阶-I.MX 6ULL_第2张图片

IVT结构体

linux进阶-I.MX 6ULL_第3张图片

Boot data

Boot data记录“镜像”在内存中的加载地址和大小。

linux进阶-I.MX 6ULL_第4张图片

DCD(外设寄存器配置信息,初始化关键外设)

复位后,芯片使用系统中所有外设的默认寄存器值。但是,这些默认值对于实现最佳系统性能来说并不理想,深圳有些外设在使用之前必须进行配置。DCD是包含在程序镜像中的配置信息,ROM对其解释以配置芯片上的各种外设。

例如,EIM默认配置允许核心在复位后立即连接到NOR闪存设备。这允许芯片与任何NOR闪存设备接口,但缺点是性能慢。此外,一些组件(如DDR)在准备使用之前需要一些寄存器编程作为配置的一部分。DCD可用于将EIM寄存器和MMDC寄存器编程到最佳配置。

ROM根据IVT的信息可确定DCD的位置。

linux进阶-I.MX 6ULL_第5张图片

NXP官方I.MX 6ULL开发SDK

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

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; iCCGR1 = 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

你可能感兴趣的:(linux进阶之路,单片机,嵌入式硬件)