NXP官方为I.MX6ULL编写了SDK包(I.MX6UL也可使用),其中有NXP已经编写好的寄存器定义文件。
I.MX6ULL的SDK包在NXP官网下载
在安装好的文件中,我们只需要fsl_common.h、fsl_iomuxc.h、MCIMX6Y2.h这三个文件。
同时需要一个新头文件,用于存放一些SDK库文件需要使用到的数据类型
cc.h
#ifndef __CC_H
#define __CC_H
#define __I volatile
#define __O volatile
#define __IO volatile
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
#endif
汇编文件
start.S
.global _start /* 全局标量 */
.global _bss_start
_bss_start:
.word __bss_start
.global _bss_end
_bss_end:
.word __bss_end
/*
描述: _start函数,程序从此函数开始执行,此函数主要功能是设置C运行环境
*/
_start:
/* 进入SVC模式 */
mrs r0, cpsr // 读取cpsr的数据到r0
bic r0, r0, #0X1F // 将r0的低五位清零,即cpsr的M0-M4
orr r0, r0, #0X13 // r0或上0x13,表示使用SVC模式
msr cpsr, r0 // 将r0的数据写入到cpsr_c中
/* 清除BSS段 */
ldr r0, _bss_start
ldr r1, _bss_end
mov r2, #0
bss_loop:
stmia r0!, {r2}
cmp r0, r1 //比较r0和r1里面的数值
ble bss_loop //如果r0地址小于等于r1,继续清除bss段
ldr sp, = 0X80200000 // 设置栈指针
b main // 跳转到C语言main函数
驱动文件:
main.c
#include "fsl_common.h"
#include "fsl_iomuxc.h"
#include "MCIMX6Y2.h"
/**********************************
* 函数名称: void clk_enable(void)
* 函数功能: 使能外设时钟
* 输入 : 无
* 输出 : 无
***********************************/
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;
}
/**********************************
* 函数名称: void LED_Init(void)
* 函数功能: 初始化LED
* 输入 : 无
* 输出 : 无
***********************************/
void LED_Init(void)
{
/* 初始化IO复用,复用为GPIO1_IO03 */
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0);
/* 设置GPIO1——IO3 电气属性 */
/***************************
*bit 16:0 HYS关闭
*bit [15:14]: 00 默认下拉
*bit [13]: 0 kepper功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 R0/6驱动能力
*bit [0]: 0 低转换率
****************************/
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0X10B0);
/* 初始化GPIO,GPIO1_IO3设置为输出 */
GPIO1 -> GDIR = 0X00000008;
/* 设置GPIO1_IO3输出低电平,打开LED灯 */
GPIO1 -> DR = 0X0;
}
/**********************************
* 函数名称: void delay_short(volatile unsigned int n)
* 函数功能: 短延时
* 输入 : volatile unsigned int n
* 输出 : 无
***********************************/
void delay_short(volatile unsigned int n)
{
while(n--);
}
/**********************************
* 函数名称: void delay(volatile unsigned int n)
* 函数功能: 延时,在396Mhz主频下约1ms
* 输入 : volatile unsigned int n
* 输出 : 无
***********************************/
void delay(volatile unsigned int n)
{
while(n--)
delay_short(0X7FF);
}
/**********************************
* 函数名称: void LED_On(void)
* 函数功能: 打开LED灯
* 输入 : 无
* 输出 : 无
***********************************/
void LED_On(void)
{
GPIO1 -> DR &= ~(1 << 3); /* bit3清零 */
/* 1 << 3:
* 1左移3位 0000 0001 --> 0000 1000
* ~(1 << 3):
* ~(0000 1000) --> 1111 0111
* GPIO1_DR &= ~(1 << 3) 即 将bit3清零
*/
}
/**********************************
* 函数名称: void LED_Off(void)
* 函数功能: 关闭LED灯
* 输入 : 无
* 输出 : 无
***********************************/
void LED_Off(void)
{
GPIO1 -> DR |= (1 << 3); /* bit3置1 */
}
int main(void)
{
clk_enable(); /* 使能外设时钟 */
LED_Init(); /* 初始化LED */
while(1)
{
LED_On();
delay(500);
LED_Off();
delay(500);
}
return 0;
}
Makefile:
CROSS_COMPILE ?= arm-linux-gnueabihf-
NAME ?= ledc
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
OBJS := start.o main.o
$(NAME).bin : $(OBJS)
$(LD) -Timx6ull.lds -o $(NAME).elf $^
$(OBJCOPY) -O binary -S $(NAME).elf $@
$(OBJDUMP) -D -m arm $(NAME).elf > $(NAME).dis
%.o:%.S
$(CC) -Wall -nostdlib -c -O2 -o $@ $<
%.o:%.c
$(CC) -Wall -nostdlib -c -O2 -o $@ $<
clean:
rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis
链接脚本:
imx6ull.lds
SECTIONS{
. = 0X87800000;
.text :
{
start.o
*(.text)
}
.rodata ALIGN(4) : {*(.rodata*)}
.data ALIGN(4) : { *(.data) }
__bss_start = .;
.bss ALIGN(4) : { *(.bss) *(COMMON) }
__bss_end = .;
}
fsl_iomuxc.h中有两个用于设置IO的函数
IOMUXC_SetPinMux(uint32_t muxRegister, //0x020E0068U
uint32_t muxMode, //0x5U 用于设定MUX_MODE
uint32_t inputRegister, //0x00000000U
uint32_t inputDaisy, //0x0U
uint32_t configRegister, //0x020E02F4U
//前五个用了一个宏(如IOMUXC_GPIO1_IO03_GPIO1_IO03)代替
//即 #define IOMUXC_GPIO1_IO03_GPIO1_IO03 0x020E0068U,0x5U,0x00000000U,0x0U,0x020E02F4U
uint32_t inputOnfield) //0
IOMUXC_SetPinConfig(uint32_t muxRegister, //0x020E0068U
uint32_t muxMode, //0x5U
uint32_t inputRegister, //0x00000000U
uint32_t inputDaisy, //0x0U
uint32_t configRegister, //0x020E02F4U
//前五个用了一个宏(如IOMUXC_GPIO1_IO03_GPIO1_IO03)代替
//即 #define IOMUXC_GPIO1_IO03_GPIO1_IO03 0x020E0068U,0x5U,0x00000000U,0x0U,0x020E02F4U
uint32_t configValue) //0x10B0 用于设置电气属性