原子哥的视频笔记

一、BSP工程管理原理 
    BSP工程管理的目的就是为了模块化整理代码,同一个属性的文件存放在同一个目录里面。
    1、新建所需的文件夹,将同一属性的文件放到相应的文件夹中。
    2、修改clk、led、delay驱动,创建对应的驱动文件,然后放置到对应的目录中。
    3、根据编写的新驱动文件,修改main.c文件内容。

    设置VSCODE头文件路径。先创建.vscode目录,然后打开c/c++配置器,会在.vscode目录下生成一个叫做c_cpp_properties.json的文件
二、Makefile编写
    Makefile指定头文件路径,需要-I。我们编译源码的时候需要指定头文件路径。比如
bsp/clk/bsp_clk.h 变为-I bsp/clk/bsp_clk.h
    通过一堆的变量,将要编译的原材料准备好了。
    Makefile静态模式
<targets ...>: <target-pattern>: <prereq-patterns ...>
$(OBJS): obj/%.o : %.S 表示将所有的.S文件编译为.o并且存放到obj目录下去。

下面是我的笔记

./vscode/c_cpp_properties.json

ctrl + shift + p

搜C/C++:Ed

生成./vscode/.....json

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "${workspaceFolder}/bsp/clk",
                "${workspaceFolder}/bsp/delay",
                "${workspaceFolder}/bsp/led",
                "${workspaceFolder}/imx6ul",
                "${workspaceFolder}/obj",
                "${workspaceFolder}/project"            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}

makefile

CROSS_COMPILE 	?= arm-linux-gnueabihf-

TARGET		  	?= bsp



CC 				:= $(CROSS_COMPILE)gcc

LD				:= $(CROSS_COMPILE)ld

OBJCOPY 		:= $(CROSS_COMPILE)objcopy

OBJDUMP 		:= $(CROSS_COMPILE)objdump



INCDIRS 		:= imx6ul \

				   bsp/clk \

				   bsp/led \

				   bsp/delay 

				   			   

SRCDIRS			:= project \

				   bsp/clk \

				   bsp/led \

				   bsp/delay 

				   

				   

INCLUDE			:= $(patsubst %, -I %, $(INCDIRS))



SFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))

CFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))



SFILENDIR		:= $(notdir  $(SFILES))

CFILENDIR		:= $(notdir  $(CFILES))



SOBJS			:= $(patsubst %, obj/%, $(SFILENDIR:.S=.o))

COBJS			:= $(patsubst %, obj/%, $(CFILENDIR:.c=.o))

OBJS			:= $(SOBJS) $(COBJS)



VPATH			:= $(SRCDIRS)



.PHONY: clean

	

$(TARGET).bin : $(OBJS)

	$(LD) -Timx6ul.lds -o $(TARGET).elf $^

	$(OBJCOPY) -O binary -S $(TARGET).elf $@

	$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis



$(SOBJS) : obj/%.o : %.S

	$(CC) -Wall -nostdlib -c -O2  $(INCLUDE) -o $@ $<



$(COBJS) : obj/%.o : %.c

	$(CC) -Wall -nostdlib -c -O2  $(INCLUDE) -o $@ $<

	

clean:

	rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)



	

加注释版

# Makefile用于编译i.MX6UL嵌入式系统的基础板级支持包(BSP)

# 定义交叉编译工具链前缀
# ?= 条件赋值,如果CROSS_COMPILE未定义则使用arm-linux-gnueabihf-
CROSS_COMPILE 	?= arm-linux-gnueabihf-

# 目标程序名称,默认为"bsp"
TARGET		  	?= bsp

# 定义编译工具变量
CC 				:= $(CROSS_COMPILE)gcc      # C编译器
LD				:= $(CROSS_COMPILE)ld       # 链接器
OBJCOPY 		:= $(CROSS_COMPILE)objcopy  # 目标文件转换工具
OBJDUMP 		:= $(CROSS_COMPILE)objdump  # 反汇编工具

# 定义头文件搜索目录列表
# 包含处理器相关目录和各个驱动模块目录
INCDIRS 		:= imx6ul \              # i.MX6UL处理器相关头文件
				   bsp/clk \             # 时钟驱动头文件
				   bsp/led \             # LED驱动头文件
				   bsp/delay             # 延时驱动头文件

# 定义源文件搜索目录列表
# 包含主程序目录和各个驱动模块目录
SRCDIRS			:= project \             # 主项目源文件目录
				   bsp/clk \             # 时钟驱动源文件
				   bsp/led \             # LED驱动源文件
				   bsp/delay             # 延时驱动源文件

# 将INCDIRS中的每个目录前加上"-I ",生成编译器搜索路径
# patsubst: 模式替换函数,将每个目录前添加"-I "
INCLUDE			:= $(patsubst %, -I %, $(INCDIRS))

# 查找所有.S汇编文件(可预处理的汇编文件)
# foreach: 遍历SRCDIRS中的每个目录
# wildcard: 通配符查找函数,查找指定模式的文件
SFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))

# 查找所有.c源文件
CFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

# 提取文件名(去掉目录路径)
# notdir: 提取文件名,去掉路径部分
SFILENDIR		:= $(notdir  $(SFILES))
CFILENDIR		:= $(notdir  $(CFILES))

# 生成目标文件路径列表
# 将所有.S文件替换为.o文件,并添加obj/前缀
SOBJS			:= $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
# 将所有.c文件替换为.o文件,并添加obj/前缀
COBJS			:= $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
# 合并所有的目标文件
OBJS			:= $(SOBJS) $(COBJS)

# 指定搜索路径,当查找依赖文件时,会在这些目录中查找
VPATH			:= $(SRCDIRS)

# 声明clean为伪目标,防止存在名为clean的文件时规则不执行
.PHONY: clean

# 默认目标:生成最终的二进制文件
# 依赖所有的目标文件(.o文件)
$(TARGET).bin : $(OBJS)
	# 使用链接脚本imx6ul.lds链接所有目标文件,生成ELF文件
	$(LD) -Timx6ul.lds -o $(TARGET).elf $^
	
	# 从ELF文件中提取纯二进制镜像
	$(OBJCOPY) -O binary -S $(TARGET).elf $@
	
	# 生成反汇编文件用于调试和分析
	$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis

# 模式规则:编译.S汇编文件为目标文件
# 静态模式规则:指定特定的目标文件列表(SOBJS)使用此规则
# obj/%.o: 目标文件路径模式
# %.S: 源文件模式
$(SOBJS) : obj/%.o : %.S
	# 编译汇编文件,包含指定的头文件搜索路径
	$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<

# 模式规则:编译.c源文件为目标文件
$(COBJS) : obj/%.o : %.c
	# 编译C源文件,包含指定的头文件搜索路径
	$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<

# 清理目标:删除所有生成的文件
clean:
	# 删除ELF文件、反汇编文件、二进制文件和所有目标文件
	rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)

start.S

/***************************************************************

Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.

文件名	: 	 start.s

作者	   : 左忠凯

版本	   : V1.0

描述	   : ZERO-I.MX6UL/I.MX6ULL开发板启动文件,完成C环境初始化,

		 C环境初始化完成以后跳转到C代码。

其他	   : 无

论坛 	   : www.wtmembed.com

日志	   : 初版 2019/1/3 左忠凯修改

**************************************************************/



.global _start  		/* 全局标号 */



/*

 * 描述:	_start函数,程序从此函数开始执行,此函数主要功能是设置C

 *		 运行环境。

 */

_start:



	/* 进入SVC模式 */

	mrs r0, cpsr

	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 	*/

	orr r0, r0, #0x13 	/* r0或上0x13,表示使用SVC模式					*/

	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中 					*/



	/* 设置栈指针,

	 * 注意:IMX6UL的堆栈是向下增长的!

	 * 堆栈指针地址一定要是4字节地址对齐的!!!

	 * DDR范围:0X80000000~0X9FFFFFFF

	 */



	ldr sp,=0X80200000	/* 设置用户模式下的栈首地址为0X80200000,大小为2MB	  	   			*/

	b main				/* 跳转到main函数 										*/



main.c

/**************************************************************

Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.

文件名	: 	 mian.c

作者	   : 左忠凯

版本	   : V1.0

描述	   : I.MX6U开发板裸机实验5 BSP形式的LED驱动

其他	   : 本实验学习目的:

		 1、将各个不同的文件进行分类,学习如何整理工程、就

		 和学习STM32一样创建工程的各个文件夹分类,实现工程文件

		 的分类化和模块化,便于管理。

		 2、深入学习Makefile,学习Makefile的高级技巧,学习编写

		 通用Makefile。

论坛 	   : www.wtmembed.com

日志	   : 初版V1.0 2019/1/4 左忠凯创建

**************************************************************/

#include "bsp_clk.h"

#include "bsp_delay.h"

#include "bsp_led.h"



/*

 * @description	: mian函数

 * @param 		: 无

 * @return 		: 无

 */

int main(void)

{

	clk_enable();		/* 使能所有的时钟 			*/

	led_init();			/* 初始化led 			*/



	while(1)			

	{	

		/* 打开LED0 */

		led_switch(LED0,ON);		

		delay(500);



		/* 关闭LED0 */

		led_switch(LED0,OFF);	

		delay(500);

	}



	return 0;

}

clk/bsp_clk.h

#ifndef __BSP_CLK_H
#define __BSP_CLK_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 bsp_clk.h
作者	   : 左忠凯
版本	   : V1.0
描述	   : 系统时钟驱动头文件。
其他	   : 无
论坛 	   : www.wtmembed.com
日志	   : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/

#include "imx6ul.h"

/* 函数声明 */
void clk_enable(void);

#endif

clk/bsp_clk.c

#include "bsp_clk.h"

/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 bsp_clk.c
作者	   : 左忠凯
版本	   : V1.0
描述	   : 系统时钟驱动。
其他	   : 无
论坛 	   : www.wtmembed.com
日志	   : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/

/*
 * @description	: 使能I.MX6U所有外设时钟
 * @param 		: 无
 * @return 		: 无
 */
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;
}

bsp/delay.h

#ifndef __BSP_DELAY_H
#define __BSP_DELAY_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 bsp_delay.h
作者	   : 左忠凯
版本	   : V1.0
描述	   : 延时头文件。
其他	   : 无
论坛 	   : www.wtmembed.com
日志	   : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "imx6ul.h"


/* 函数声明 */
void delay(volatile unsigned int n);

#endif

bsp/delay.c

/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 bsp_delay.c
作者	   : 左忠凯
版本	   : V1.0
描述	   : 延时文件。
其他	   : 无
论坛 	   : www.wtmembed.com
日志	   : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "bsp_delay.h"

/*
 * @description	: 短时间延时函数
 * @param - n	: 要延时循环次数(空操作循环次数,模式延时)
 * @return 		: 无
 */
void delay_short(volatile unsigned int n)
{
	while(n--){}
}

/*
 * @description	: 延时函数,在396Mhz的主频下
 * 			  	  延时时间大约为1ms
 * @param - n	: 要延时的ms数
 * @return 		: 无
 */
void delay(volatile unsigned int n)
{
	while(n--)
	{
		delay_short(0x7ff);
	}
}


led/bsp_led.h

#ifndef __BSP_LED_H
#define __BSP_LED_H
#include "imx6ul.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 bsp_led.h
作者	   : 左忠凯
版本	   : V1.0
描述	   : LED驱动头文件。
其他	   : 无
论坛 	   : www.wtmembed.com
日志	   : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/

#define LED0	0

/* 函数声明 */
void led_init(void);
void led_switch(int led, int status);
#endif

led/bsp_led.c

#include "bsp_led.h"
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 bsp_led.c
作者	   : 左忠凯
版本	   : V1.0
描述	   : LED驱动文件。
其他	   : 无
论坛 	   : www.wtmembed.com
日志	   : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/

/*
 * @description	: 初始化LED对应的GPIO
 * @param 		: 无
 * @return 		: 无
 */
void led_init(void)
{
	/* 1、初始化IO复用 */
	IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0);		/* 复用为GPIO1_IO03 */
	
	
	/* 2、、配置GPIO1_IO03的IO属性	
	 *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);
	
	/* 3、初始化GPIO,GPIO1_IO03设置为输出*/
	GPIO1->GDIR |= (1 << 3);	 

	/* 4、设置GPIO1_IO03输出低电平,打开LED0*/
	GPIO1->DR &= ~(1 << 3);		
}


/*
 * @description		: LED控制函数,控制LED打开还是关闭
 * @param - led		: 要控制的LED灯编号
 * @param - status	: 0,关闭LED0,1 打开LED0
 * @return 			: 无
 */
void led_switch(int led, int status)
{	
	switch(led)
	{
		case LED0:
			if(status == ON)
				GPIO1->DR &= ~(1<<3);	/* 打开LED0 */
			else if(status == OFF)
				GPIO1->DR |= (1<<3);	/* 关闭LED0 */
			break;
	}
}

imx6ul文件夹的略库文件,太大太长写不下

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐