SDK 移植及BSP工程管理

NXP 官方为 I.MX6ULL 编写了 SDK 包,在 SDK 包里面 NXP 已经编写好了寄存器定义文件,
所以我们可以直接移植 SDK 包里面的文件来用
1 I.MX6ULL 官方 SDK 包简介
NXP 针对 I.MX6ULL 编写了一个 SDK 包,这个 SDK 包就类似于 STM32 STD 库或者
HAL 库,这个 SDK 包提供了 Windows Linux 两种版本,分别针对主机系统是 Windows 和 Linux。
NXP 的 定位里面,I.MX6ULL 就是一个 Cotex-A 内核的高端单片机,定位类似 ST STM32H7。I.MX6ULL SDK 包在 NXP 官网下载,下载界面如图
双击 SDK_2.2_MCIM6ULL_RFP_Win.exe 安装 SDK 包,
安装的时候需要设置好安装位置,安装完成以后的 SDK 包如图
我们重点是需要 SDK 包里面与寄存器定义相关的文件,一共需要如下三个文件:
fsl_common.h:位置SDK_2.2_MCIM6ULL\devices\MCIMX6Y2\drivers\fsl_common.h
fsl_iomuxc.h: 位置为 SDK_2.2_MCIM6ULL\devices\MCIMX6Y2\drivers\fsl_iomuxc.h
MCIMX6Y2.h: 位置为 SDK_2.2_MCIM6ULL\devices\MCIMX6Y2\MCIMX6YH2.h
整个 SDK 包我们就需要上面这三个文件,把这三个文件准备好,我们后面移植要用。

SDK 文件移植

使用 VSCode 新建工程,将 fsl_common.h fsl_iomuxc.h MCIMX6Y2.h 这三个文件拷贝
到工程中,这三个文件直接编译的话肯定会出错的!需要对其做删减,因为这三个文件里面的 代码都比较大,所以就不详细列出这三个文件删减以后的内容了
创建 cc.h 文件
新建一个名为 cc.h 的头文件, cc.h 里面存放一些 SDK 库文件需要使用到的数据类型,在
cc.h 里面输入如下代码:
1 #ifndef __CC_H
2 #define __CC_H

14 * 自定义一些数据类型供库文件使用
15 */
16 #define __I volatile
17 #define __O volatile
18 #define __IO volatile
19
20 #define ON 1
21 #define OFF 0
22
23 typedef signed char int8_t;
24 typedef signed short int int16_t;
25 typedef signed int int32_t;
26 typedef unsigned char uint8_t;
27 typedef unsigned short int uint16_t;
28 typedef unsigned int uint32_t;
29 typedef unsigned long long uint64_t;
30 typedef signed char s8; 
31 typedef signed short int s16;
32 typedef signed int s32;
33 typedef signed long long int s64;
34 typedef unsigned char u8;
35 typedef unsigned short int u16;
36 typedef unsigned int u32;
37 typedef unsigned long long int u64;
38
39 #endif
编写实验代码
新建 start.S main.c 这两个文件,start.S 文件的内容和上一章一样,直接复制过来就可以, 创建完成以后工程目录如图 main.c 中输入如下所示代码:
1 #include "fsl_common.h"
2 #include "fsl_iomuxc.h"
3 #include "MCIMX6Y2.h"
4 
5 /*
6 * @description : 使能 I.MX6U 所有外设时钟
7 * @param : 无
8 * @return : 无
9 */
10 void clk_enable(void)
11 {
12 CCM->CCGR0 = 0XFFFFFFFF;
13 CCM->CCGR1 = 0XFFFFFFFF;
14 
15 CCM->CCGR2 = 0XFFFFFFFF;
16 CCM->CCGR3 = 0XFFFFFFFF;
17 CCM->CCGR4 = 0XFFFFFFFF;
18 CCM->CCGR5 = 0XFFFFFFFF;
19 CCM->CCGR6 = 0XFFFFFFFF;
20
21 }
22 
23 /*
24 * @description : 初始化 LED 对应的 GPIO
25 * @param : 无
26 * @return : 无
27 */
28 void led_init(void)
29 {
30 /* 1、初始化 IO 复用 */
31 IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0);
32 
33 /* 2、、配置 GPIO1_IO03 的 IO 属性 
34 *bit 16:0 HYS 关闭
35 *bit [15:14]: 00 默认下拉
36 *bit [13]: 0 kepper 功能
37 *bit [12]: 1 pull/keeper 使能
38 *bit [11]: 0 关闭开路输出
39 *bit [7:6]: 10 速度 100Mhz
40 *bit [5:3]: 110 R0/6 驱动能力
41 *bit [0]: 0 低转换率
42 */
43 IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0X10B0);
44 
45 /* 3、初始化 GPIO,设置 GPIO1_IO03 设置为输出 */
46 GPIO1->GDIR |= (1 << 3); 
47 
48 /* 4、设置 GPIO1_IO03 输出低电平,打开 LED0 */
49 GPIO1->DR &= ~(1 << 3); 
50 }
51 
52 /*
53 * @description : 打开 LED 灯
54 * @param : 无
55 * @return : 无
56 */
57 void led_on(void)
58 {
59 /* 将 GPIO1_DR 的 bit3 清零 */
60 GPIO1->DR &= ~(1<<3);
61 }
62 
63 /*
64 * @description : 关闭 LED 灯
65 * @param : 无
66 * @return : 无
67 */
68 void led_off(void)
69 {
70 /* 将 GPIO1_DR 的 bit3 置 1 */
71 GPIO1->DR |= (1<<3);
72 }
73 
74 /*
75 * @description : 短时间延时函数
76 * @param - n : 要延时循环次数(空操作循环次数,模式延时)
77 * @return : 无
78 */
79 void delay_short(volatile unsigned int n)
80 {
81 while(n--){}
82 }
83 
84 /*
85 * @description : 延时函数,在 396Mhz 的主频下
86 * 延时时间大约为 1ms
87 * @param - n : 要延时的 ms 数
88 * @return : 无
89 */
90 void delay(volatile unsigned int n)
91 {
92 while(n--)
93 {
94 delay_short(0x7ff);
95 }
96 }
97 
98 /*
99 * @description : main 函数
100 * @param : 无
101 * @return : 无
102 */
103 int main(void)
104 {
105 clk_enable(); /* 使能所有的时钟 */
106 led_init(); /* 初始化 led */
107
108 while(1) /* 死循环 */
109 { 
110 led_off(); /* 关闭 LED */
111 delay(500); /* 延时 500ms */
112
113 led_on(); /* 打开 LED */
114 delay(500); /* 延时 500ms */
115 }
116
117 return 0;
118 }
编译下载验证
编写 Makefile 和链接脚本
Makefile 文件内容如下:
1 CROSS_COMPILE ?= arm-linux-gnueabihf-
2 NAME ?= ledc
3 
4 CC := $(CROSS_COMPILE)gcc
5 LD := $(CROSS_COMPILE)ld
6 OBJCOPY := $(CROSS_COMPILE)objcopy
7 OBJDUMP := $(CROSS_COMPILE)objdump
8 
9 OBJS := start.o main.o
10
11 $(NAME).bin:$(OBJS)
12 $(LD) -Timx6ul.lds -o $(NAME).elf $^
13 $(OBJCOPY) -O binary -S $(NAME).elf $@
14 $(OBJDUMP) -D -m arm $(NAME).elf > $(NAME).dis
15
16 %.o:%.s
17 $(CC) -Wall -nostdlib -c -O2 -o $@ $<
18 
19 %.o:%.S
20 $(CC) -Wall -nostdlib -c -O2 -o $@ $<
21 
22 %.o:%.c
23 $(CC) -Wall -nostdlib -c -O2 -o $@ $<
24 
25 clean:
26 rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis
编译下载
使用 Make 命令编译代码,编译成功以后使用软件 imxdownload 将编译完成的 ledc.bin
件下载到 SD 卡中,命令如下:
烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板,如果代码运行正常的
LED0 就会以 500ms 的时间间隔亮灭,实验现象和上一章一样

BSP工程管理原理

目的就是为了模块化整理代码,同一个属性的文件存放在同一个目录里面

1.修建所需的文件夹,将同一属性的文件放到相应的文件夹中

2.修改clk,led,delay驱动,创建对应的驱动文件,然后放置到对应的目录中

3.根据编写的驱动新文件。修改main.c文件内容

设置vs code头文件路径。先创建.vscode目录,然后打开C/C++配置器,会在.vscode目录下生成一个叫做c_cpp_properties.json的文件

新建名为“ 5_ledc_bsp ”的文件夹,在里面新建 bsp imx6ul obj project 4 个文件夹,
完成以后如图
其中 bsp 用来存放驱动文件; imx6ul 用来存放跟芯片有关的文件,比如 NXP 官方的 SDK
库文件; obj 用来存放编译生成的 .o 文件; project 存放 start.S main.c 文件,也就是应用文件; 将十二章实验中的 cc.h fsl_common.h fsl_iomuxc.h MCIMX6Y2.h 这四个文件拷贝到文件 夹 imx6ul 中;将 start.S main.c 这两个文件拷贝到文件夹 project 中。我们前面的实验中所有 的驱动相关的函数都写到了 main.c 文件中,比如函数 clk_enable led_init delay ,这三个函数 可以分为三类:时钟驱动、LED 驱动和延时驱动。因此我们可以在 bsp 文件夹下创建三个子文 件夹:clk delay led ,分别用来存放时钟驱动文件、延时驱动文件和 LED 驱动文件,这样 main.c 函数就会清爽很多,程序功能模块清晰。工程文件夹都创建好了,接下来就是编写代码 了,其实就是将时钟驱动、LED 驱动和延时驱动相关的函数从 main.c 中提取出来做成一个独立 的驱动文件 。
实验程序编写
创建 imx6ul.h 文件
新建文件 imx6ul.h ,然后保存到文件夹 imx6ul 中,在 imx6ul.h 中输入如下内容:
#ifndef __IMX6UL_H
#define __IMX6UL_H

 #include "cc.h"
 #include "MCIMX6Y2.h"
 #include "fsl_common.h"
 #include "fsl_iomuxc.h"

 #endif
编写 led 驱动代码
新建 bsp_led.h bsp_led.c 两个文件,将这两个文件存放到 bsp/led 中,在 bsp_led.h 中输入 输入如下内容:
1 #ifndef __BSP_LED_H
2 #define __BSP_LED_H
3 #include "imx6ul.h"
15 #define LED0 0
16
17 /* 函数声明 */
18 void led_init(void);
19 void led_switch(int led, int status);
20 #endif
bsp_led.h 的内容很简单,就是一些函数声明,在 bsp_led.c 中输入如下内容:
1 #include "bsp_led.h"
18 void led_init(void)
19 {
20 /* 1、初始化 IO 复用 */
21 IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0); 
22 
23 /* 2、、配置 GPIO1_IO03 的 IO 属性 */
24 IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0X10B0);
25 
26 /* 3、初始化 GPIO,GPIO1_IO03 设置为输出*/
27 GPIO1->GDIR |= (1 << 3); 
28
29 /* 4、设置 GPIO1_IO03 输出低电平,打开 LED0*/
30 GPIO1->DR &= ~(1 << 3); 
31 }
33 /*
34 * @description : LED 控制函数,控制 LED 打开还是关闭
35 * @param - led : 要控制的 LED 灯编号
36 * @param - status : 0,关闭 LED0,1 打开 LED0
37 * @return : 无
38 */
39 void led_switch(int led, int status)
40 { 
41 switch(led)
42 {
43 case LED0:
44 if(status == ON)
45 GPIO1->DR &= ~(1<<3); /* 打开 LED0 */
46 else if(status == OFF)
47 GPIO1->DR |= (1<<3); /* 关闭 LED0 */
48 break;
49 }
50 }
bsp_led.c 里面就两个函数 led_init led_switch led_init 函数用来初始化 LED 所使用的
IO led_switch 函数是控制 LED 灯的打开和关闭,这两个函数都很简单。
编写时钟驱动代码
新建 bsp_clk.h bsp_clk.c 两个文件,将这两个文件存放到 bsp/clk 中,在 bsp_clk.h 中输入 输入如下内容:
1 #ifndef __BSP_CLK_H
2 #define __BSP_CLK_H


14 #include "imx6ul.h"
15
16 /* 函数声明 */
17 void clk_enable(void);
18
19 #endif
bsp_clk.h 很简单,在 bsp_clk.c 中输入内容:
1 #include "bsp_clk.h"
14 /*
15 * @description : 使能 I.MX6U 所有外设时钟
16 * @param : 无
17 * @return : 无
18 */
19 void clk_enable(void)
20 {
21 CCM->CCGR0 = 0XFFFFFFFF;
22 CCM->CCGR1 = 0XFFFFFFFF;
23 CCM->CCGR2 = 0XFFFFFFFF;
24 CCM->CCGR3 = 0XFFFFFFFF;
25 CCM->CCGR4 = 0XFFFFFFFF;
26 CCM->CCGR5 = 0XFFFFFFFF;
27 CCM->CCGR6 = 0XFFFFFFFF;
28 }
bsp_clk.c 只有一个 clk_enable 函数,用来使能所有的外设时钟。
编写延时驱动代码
新建 bsp_delay.h bsp_delay.c 两个文件,将这两个文件存放到 bsp/delay 中,在 bsp_delay.h 中输入输入如下内容:
1 #ifndef __BSP_DELAY_H
2 #define __BSP_DELAY_H
13 #include "imx6ul.h"
14
15 /* 函数声明 */
16 void delay(volatile unsigned int n);
17
18 #endif
bsp_delay.c 中输入内容:
1 #include "bsp_delay.h"
2 
3 /*
4 * @description : 短时间延时函数
5 * @param - n : 要延时循环次数(空操作循环次数,模式延时)
6 * @return : 无
7 */
8 void delay_short(volatile unsigned int n)
9 {
10 while(n--){}
11 }
12
13 /*
14 * @description : 延时函数,在 396Mhz 的主频下
15 * 延时时间大约为 1ms
16 * @param - n : 要延时的 ms 数
17 * @return : 无
18 */
19 void delay(volatile unsigned int n)
20 {
21 while(n--)
22 {
23 delay_short(0x7ff);
24 }
25 }
修改 main.c 文件
1 #include "bsp_clk.h"
2 #include "bsp_delay.h"
3 #include "bsp_led.h"
4 
5 /*
6 * @description : main 函数
7 * @param : 无
8 * @return : 无
9 */
10 int main(void)
11 {
12 clk_enable(); /* 使能所有的时钟 */
13 led_init(); /* 初始化 led */
14
15 while(1)
16 { 
17 /* 打开 LED0 */
18 led_switch(LED0,ON); 
19 delay(500);
20
21 /* 关闭 LED0 */
22 led_switch(LED0,OFF); 
23 delay(500);
24 }
25
26 return 0;
27 }
编译下载验证
编写 Makefile 和链接脚本
在工程根目录下新建 Makefile 和 imx6ul.lds 这两个文件,创建完成以后的工程如图
在文件 Makefile 中输入如下所示内容:
1 CROSS_COMPILE ?= arm-linux-gnueabihf-
2 TARGET ?= bsp
3 
4 CC := $(CROSS_COMPILE)gcc
5 LD := $(CROSS_COMPILE)ld
6 OBJCOPY := $(CROSS_COMPILE)objcopy
7 OBJDUMP := $(CROSS_COMPILE)objdump
8 
9 INCDIRS := imx6ul \
10 bsp/clk \
11 bsp/led \
12 bsp/delay 
13 
14 SRCDIRS := project \
15 bsp/clk \
16 bsp/led \
17 bsp/delay 
18 
19 INCLUDE := $(patsubst %, -I %, $(INCDIRS))
20
21 SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
22 CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
23
24 SFILENDIR := $(notdir $(SFILES))
25 CFILENDIR := $(notdir $(CFILES))
26
27 SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
28 COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
29 OBJS := $(SOBJS) $(COBJS)
30
31 VPATH := $(SRCDIRS)
32
33 .PHONY: clean
34 
35 $(TARGET).bin : $(OBJS)
36 $(LD) -Timx6ul.lds -o $(TARGET).elf $^
37 $(OBJCOPY) -O binary -S $(TARGET).elf $@
38 $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
39
40 $(SOBJS) : obj/%.o : %.S
41 $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
42
43 $(COBJS) : obj/%.o : %.c
44 $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
45 
46 clean:
47 rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)
链接脚本 imx6ul.lds 的内容基本和上一章一样,主要是 start.o 文件路径不同,本章所使用
imx6ul.lds 链接脚本内容如下所示:
1 SECTIONS{
2 . = 0X87800000;
3 .text :
4 {
5 obj/start.o 
6 *(.text)
7 }
8 .rodata ALIGN(4) : {*(.rodata*)} 
9 .data ALIGN(4) : { *(.data) } 
10 __bss_start = .; 
11 .bss ALIGN(4) : { *(.bss) *(COMMON) } 
12 __bss_end = .;
13 }
编译下载
使用 Make 命令编译代码,编译成功以后使用软件 imxdownload 将编译完成的 bsp.bin 文件
下载到 SD 卡中,命令如下:
烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板,如果代码运行正常的
LED0 就会以 500ms 的时间间隔亮灭

wink成功

 

  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值