一、硬件平台:
正点原子I.MX6U阿尔法开发板
二、SDK包简介
NXP 官方为 I.MX6ULL 编写了 SDK 包,在 SDK 包里面 NXP 已经编写好了寄存器定义文件, 所以我们可以直接移植 SDK 包里面的文件来用,SDK 在 NXP 官网下载
此处我们下载 Window 版本的,选择一处位置安装
三、SDK包移植
SDK 的移植我们只要关注其中的寄存器封装头文件就行,包含寄存器信息的文件位置如下:
fsl_common.h:位置:sdk目录devicesMCIMX6Y2driversfsl_common.h
fsl_iomuxc.h: 位置:sdk目录devicesMCIMX6Y2driversfsl_iomuxc.h
MCIMX6Y2.h: 位置:sdk目录devicesMCIMX6Y2MCIMX6YH2.h
我们复制这三个文件到工程目录下进行修改(修改需要参考正点原子例程示例文档),然后创建一个new_type.h的头文件,定义一些常用的关键字与声明,这里直接复制左神的代码
#ifndef __NEW_TYPE_H
#define __NEW_TYPE_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : cc.h
作者 : 左忠凯
版本 : V1.0
描述 : 有关变量类型的定义,NXP官方SDK的一些移植文件会用到。
其他 : 无
日志 : 初版V1.0 2019/1/3 左忠凯创建
***************************************************************/
/*
* 自定义一些数据类型供库文件使用
*/
#define __I volatile
#define __O volatile
#define __IO volatile
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef signed char s8;
typedef signed short int s16;
typedef signed int s32;
typedef signed long long int s64;
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
typedef unsigned long long int u64;
#endif
四、点灯程序编写
工程下面有了以上的文件之后,我们就可以进行调用开发了,先编写启动汇编文件,这里我直接使用上一节的启动代码和链接文件
下面编写 main 文件部分代码
头文件包含以及部分声明
#include 'fsl_common.h'
#include 'fsl_iomuxc.h'
#include 'MCIMX6Y2.h'
#include 'new_type.h'
#define LED_ON() (GPIO1->DR &= ~(1<<3))
#define LED_OFF() (GPIO1->DR |= (1<<3))
初始化时钟函数
void CLK_INIT(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)
{
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0x10b0);
GPIO1->GDIR |= (1 << 3);
GPIO1->DR &= ~(1 << 3);
}
延时函数
void delay(volatile unsigned int n)
{
while(n--)
{
volatile unsigned int i = 0x7ff;
while(i--);
}
}
主函数
int main(void)
{
CLK_INIT();
LED_INIT();
while (1)
{
/* code */
LED_ON();
delay(10000);
LED_OFF();
delay(10000);
}
return 0;
}
SDK开发与我们之前开发的最大区别就是提供了封装的寄存器地址以及操作函数,我们可以快速调用他进行开发,这里比较重要的两个函数
1. 复用设置函数:
static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t inputOnfield)
其参数功能如表:
参数 | 功能 |
---|---|
muxRegister | IO 的复用寄存器地址 |
muxMode | IO 复用值,也就是 ALT0~ALT8,对应数字 0~8,比如要将 GPIO1_IO03 设置 为 GPIO 功能的话此参数就要设置为 5 |
inputRegister | 外设输入 IO 选择寄存器地址,有些 IO 在设置为其他的复用功能以后还需要设置 IO 输入寄存器 |
inputDaisy | 寄存器 inputRegister 的值,比如 GPIO1_IO03 要作为 UART1_RX 引脚的话此 参数就是 1 |
configRegister | 未使用,函数 IOMUXC_SetPinConfig 会使用这个寄存器。 |
inputOnfield | IO 软件输入使 能 ,以 GPIO1_IO03 为例就是寄存器 SW_MUX_CTL_PAD_GPIO1_IO03 的 SION 位(bit4)。如果需要使能 GPIO1_IO03 的软件输入功能的话此参数应该为 1,否则的话就为 0。 |
复用功能有9种宏定义
IOMUXC_GPIO1_IO03_I2C1_SDA
IOMUXC_GPIO1_IO03_GPT1_COMPARE3
IOMUXC_GPIO1_IO03_USB_OTG2_OC
IOMUXC_GPIO1_IO03_USDHC1_CD_B
IOMUXC_GPIO1_IO03_GPIO1_IO03
IOMUXC_GPIO1_IO03_CCM_DI0_EXT_CLK
IOMUXC_GPIO1_IO03_SRC_TESTER_ACK
IOMUXC_GPIO1_IO03_UART1_RX
IOMUXC_GPIO1_IO03_UART1_TX
每个宏定义都包含了预先配置,比如 IOMUXC_GPIO1_IO03_GPIO1_IO03 本身集成了其配置,所以我们使用时只需要输入 IOMUXC_GPIO1_IO03_GPIO1_IO03 和输入使能参数就行
#define IOMUXC_GPIO1_IO03_GPIO1_IO03 0x020E0068U, 0x5U, 0x00000000U,0x0U, 0x020E02F4U
2. GPIO 口设置函数:
static inline void IOMUXC_SetPinConfig( uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t configValue)
此函数只使用了参数 configRegister 和 configValue,其参数功能如表:
参数 | 功能 |
---|---|
configRegister | IO 配置寄存器地址 |
configValue | 要写入到寄存器 configRegister 的值 |
代码编写完成后编写 Makefile文件代码
COMPILE ?= arm-linux-gnueabihf-
NAME ?= ledtest
CC := $(COMPILE)gcc
LD := $(COMPILE)ld
OBJCOPY := $(COMPILE)objcopy
OBJDUMP := $(COMPILE)objdump
OBJS := start.o main.o
$(NAME).bin:$(OBJS)
$(LD) -Timx6ul.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:%.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
此处 makefile 多用变量来代替常用的指令,具体可以查 makefile 手册,熟能生巧,之后用 imxdownload 工具下载到 sd 卡在 ARM 单片机上启动
详细下载细节可参考我之前的文章:ARM裸机开发:I.MX6UL 程序编译下载(SD卡)
五、实验现象
将SD卡插到开发板上启动,可以看到 LED 在周期性闪烁,这里就不插图了