ARM(IMX6U)BSP工程文件管理(分文件编程)

参考:Linux之ARM(IMX6U)BSP工程管理实验
作者:一只青木呀
发布时间: 2020-08-15 23:41:37
网址:https://blog.csdn.net/weixin_45309916/article/details/108028093

目录

  • 1、工程管理简介
    • 1.1、创建bsp、imx6ul、obj和project这四个文件夹
    • 1.2、文件分类
  • 2、实验程序编写
    • 2.1、创建 imx6ul.h 文件
    • 2.2、创建.vscode文件修改includePath(解决找不到头文件问题)
      • 2.2.1、修改includePath
    • 2.3、编写led驱动文件
      • 2.3.1、 bsp_led.h
      • 2.3.2、 bsp_led.c
    • 2.4、编写时钟驱动代码
      • 2.4.1、bsp_clk.h
      • 2.4.2、bsp_clk.c
    • 2.5、编写延时驱动代码
      • 2.5.1、bsp_delay.h
      • 2.5.2、bsp_delay.c
    • 2.6、修改main.c代码
      • 2.6.1、创建一个main.h文件,用来包含头文件
      • 2.6.2、main.c
  • 3、编译下载与验证
    • 3.1、编写链接文件
    • 3.2、编写Makefile文件
    • 3.3、编译下载

在我们写工程中,我们都是将所有的源码文件放到工程的根目录下,如果工程文件比较少的话这样做无可厚非, 但是如果工程源文件达到几十、甚至数百个的时候,这样一股脑全部放到根目录下就会使工程显得混乱不堪。所以我们必须对工程文件做管理,将不同功能的源码文件放到不同的目录中。另外我们也需要将源码文件中,所有完成同一个功能的代码提取出来放到一个单独的文件中,也就是对程序分功能管理。 本章我们就来学习一下如何对一个工程进行整理,使其美观、功能模块清晰、易于阅读

1、工程管理简介

在我们上一篇博客中(ARM(MX6U)裸机官方SDK移植)中,文件有:
在这里插入图片描述
我们将所有的源码文件都放到工程根目录下,即使这个工程只是完成了一个简单的流水灯的功能,但是其工程根目录下的源码文件就已经不少了。如果在添加一些其他的功能文件,那么文档就会更大,显得很混乱,所以我们需要对这个工程进行整理,将源码文件分模块、分功能整理。我们来看一个比较好的例程:
在这里插入图片描述
图 中的工程目录就很美观、不同的功能模块文件放到不同的文件夹中,比如驱动文件就放到bsp文件夹中, 官方库就放到 imx6ul文件夹中,编译产生的过程文件放到 OBJ 文件夹中

我们参考这个来整理一下(ARM(MX6U)裸机官方SDK移植)中的文件。

1.1、创建bsp、imx6ul、obj和project这四个文件夹

在这里插入图片描述

  • 其中 bsp 用来存放驱动文件
  • imx6ul 用来存放跟芯片有关的文件,比如 NXP 官方的 SDK库文件;
  • obj 用来存放编译生成的.o 文件
  • project 存放 start.S 和 main.c 文件,也就是应用文件;

1.2、文件分类

  • 将(ARM(MX6U)裸机官方SDK移植)实验中的 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 中提取出来做成一个独立的驱动文件 。

2、实验程序编写

使用 VScode 新建工程,工程名字为“ledc_bsp”。
在这里插入图片描述

2.1、创建 imx6ul.h 文件

#ifndef __IMX6UL_H
#define __IMX6UL_H#include "cc.h"
#include "MCIMX6Y2.h"
#include "fsl_common.h"
#include "fsl_iomuxc.h"#endif

文件 imx6ul.h 很简单,就是引用了一些头文件,以后我们就可以在其他文件中需要引用imx6ul.h 就可以了。

2.2、创建.vscode文件修改includePath(解决找不到头文件问题)

是为了vscode解决找不到工程的头文件的问题
在终端创建“ .vscode文件夹 ”,打开c_cpp_properties.json文件(自动创建出来的)。
在这里插入图片描述

2.2.1、修改includePath

把我们的头文件的文件夹路径添加进去
在这里插入图片描述
这样刷新一下,就可以包含所需的头文件了

2.3、编写led驱动文件

新建 bsp_led.h 和 bsp_led.c 两个文件,将这两个文件存放到 bsp/led 中,

2.3.1、 bsp_led.h

#ifndef __BSP_LED_H
#define __BSP_LED_H#include "imx6ul.h"#define LED0 0/*函数声明*/
void  led_on(void);
void led_off(void );
void led_init(void);
void led_switch(int led, int status);#endif /* __BSP_LED_H */

bsp_led.h 的内容很简单,就是一些函数声明和头文件的引用

2.3.2、 bsp_led.c

#include "bsp_led.h"/*打开LED灯*/
void  led_on(void)
{GPIO1->DR&= ~(1<<3); //bit3清零}
/*关闭LED灯*/
void led_off(void )
{GPIO1->DR |= (1<<3);  //bit3置1
}/*初始化LED灯*/
void led_init(void)
{IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0); /*复用为GPIO--IO03 */IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0x10B0);/*设置GPIO__IO03电器属性*/GPIO1->GDIR=0x8;//设置为输出GPIO1->DR=0x0; //设置为低电平,打开LED灯}/*LED 灯控制函数*/
void led_switch(int led, int status)
{switch(status){case  LED0:if(status == ON)GPIO1->DR |= (1<<3);  //bit3置1else if(status == OFF)GPIO1->DR&= ~(1<<3); //bit3清零break;}}

bsp_led.c 里面就两个函数 led_init 和 led_switch, led_init 函数用来初始化 LED 所使用的IO, led_switch 函数是控制 LED 灯的打开和关闭

2.4、编写时钟驱动代码

新建 bsp_clk.h 和 bsp_clk.c 两个文件,将这两个文件存放到 bsp/clk 中

2.4.1、bsp_clk.h

#ifndef __BSP_CLK_H
#define __BSP_CLK_H#include "imx6ul.h"void clk_enable(void);#endif // !__BSP_CLK_H

2.4.2、bsp_clk.c

#include "bsp_clk.h"/*使能外设时钟*/
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_clk.c 只有一个 clk_enable 函数,用来使能所有的外设时钟。

2.5、编写延时驱动代码

新建 bsp_delay.h 和 bsp_delay.c 两个文件,将这两个文件存放到 bsp/delay 中

2.5.1、bsp_delay.h

#ifndef __BSP_DELAY_H
#define __BSP_DELAY_H#include "imx6ul.h"void delay_short(volatile unsigned int n);
void delay(volatile unsigned int n);#endif // !__BSP_CLK_H

2.5.2、bsp_delay.c

#include "bsp_delay.h"/*短延时*/
void delay_short(volatile unsigned int n)
{while(n--){}}
/** 延时  一次循环大概是1ms 在主频396MHz* n:延时ms数
*/
void delay(volatile unsigned int n)
{while (n--){delay_short(0x7ff);}}

2.6、修改main.c代码

2.6.1、创建一个main.h文件,用来包含头文件

main.h

#ifndef __MAIN_H
#define __MAIN_H#include "imx6ul.h"
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"#endif // !__MAIN_H

2.6.2、main.c

#include "main.h"int main() 
{clk_enable();  //使能外设时钟led_init(); //初始化LEDwhile(1){led_off();  delay(1000);led_on();delay(1000);}return 0;
}

在 main.c 中我们仅仅留下了 main 函数,至此,本例程跟程序相关的内容就全部编写好了

3、编译下载与验证

3.1、编写链接文件


SECTIONS
{. = 0x87800000;.text :{obj/start.o*(.text)}.rodata ALIGN(4) : {*(.rodata*)}.data ALIGN(4) : {*(.data)}__bss_start = .;.bss ALIGN(4) : { *(.bss) *(COMMON)}__bss_end = .;
}

注意第 5 行设置的 start.o 文件路径

3.2、编写Makefile文件

CROSS_COMPILE 	?= arm-linux-gnueabihf-
TARGET		  	?= bspCC 				:= $(CROSS_COMPILE)gcc
LD				:= $(CROSS_COMPILE)ld
OBJCOPY 		:= $(CROSS_COMPILE)objcopy
OBJDUMP 		:= $(CROSS_COMPILE)objdumpINCDIRS 		:= 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 文件要比前面的实验复杂很多,因为这个Makefile 代码是一个通用 Makefile,我们以后所有的裸机例程都使用这个 Makefile。使用时候只要将所需要编译的源文件所在的目录添加到 Makefile 中即可

第 1~7 行定义了一些变量,除了第 2 行以外其它的都是跟编译器有关的,如果使用其它编译器的话只需要修改第 1 行即可。第 2 行的变量 TARGET 目标名字,不同的例程肯定名字不一一样。

第 9 行的变量 INCDIRS 包含整个工程的.h 头文件目录,文件中的所有头文件目录都要添加到变量INCDIRS中。比如本例程中包含.h头文件的目录有imx6ul、bsp/clk、bsp/delay和bsp/led,所以就需要在变量 INCDIRS 中添加这些目录,即:

INCDIRS := imx6ul bsp/clk bsp/led bsp/delay

仔细观察的话会发现第 9~11 行后面都会有一个符号“\”,这个相当于“换行符”,表示本行和下一行属于同一行,一般一行写不下的时候就用符号“\”来换行。在后面的裸机例程中我们会根据实际情况来在变量 INCDIRS 中添加头文件目录。

第 14 行是变量 SRCDIRS,和变量 INCDIRS 一样,只是 SRCDIRS 包含的是整个工程的所有.c 和.S 文件目录。比如本例程包含有.c 和.S 的目录有 bsp/clk、 bsp/delay、 bsp/led 和 project,即:

SRCDIRS := project bsp/clk bsp/led bsp/delay

同样的,后面的裸机例程中我们也要根据实际情况在变量 SRCDIRS 中添加相应的文件目录。

第 19 行的变量 INCLUDE 是用到了函数 patsubst,通过函数 patsubst 给变量 INCDIRS 添加一个“-I”,即:

INCLUDE := -I imx6ul -I bsp/clk -I bsp/led -I bsp/delay

加“-I”的目的是因为 Makefile 语法要求指明头文件目录的时候需要加上“-I”

第 21 行变量 SFILES 保存工程中所有的.s 汇编文件(包含绝对路径),变量 SRCDIRS 已经存放了工程中所有的.c 和.S 文件,所以我们只需要从里面挑出所有的.S 汇编文件即可,这里借助了函数 foreach 和函数 wildcard,最终 SFILES 如下:

SFILES := project/start.s

第 22 行变量 CFILES 和变量 SFILES 一样,只是 CFILES 保存工程中所有的.c 文件(包含绝对路径),最终 CFILES 如下:

CFILES = project/main.c bsp/clk/bsp_clk.c bsp/led/bsp_led.c bsp/delay/bsp_delay.c

第 24 和 25 行的变量 SFILENDIR 和 CFILENDIR 包含所有的.s 汇编文件和.c 文件,相比变量 SFILES 和 CFILES, SFILENDIR 和 CFILNDIR 只是文件名,不包含文件的绝对路径。使用函数 notdir 将 SFILES 和 CFILES 中的路径去掉即可, SFILENDIR 和 CFILENDIR 如下:

SFILENDIR = start.S
CFILENDIR = main.c bsp_clk.c bsp_led.c bsp_delay.c

第 27 和 28 行的变量 SOBJS 和 COBJS 是.S 和.c 文件编译以后对应的.o 文件目录,默认所有的文件编译出来的.o 文件和源文件在同一个目录中,这里我们将所有的.o 文件都放到 obj 文件夹下, SOBJS 和 COBJS 内容如下:

SOBJS = obj/start.o
COBJS = obj/main.o obj/bsp_clk.o obj/bsp_led.o obj/bsp_delay.o

第 29 行变量 OBJS 是变量 SOBJS 和 COBJS 的集合,如下:

OBJS = obj/start.o obj/main.o obj/bsp_clk.o obj/bsp_led.o obj/bsp_delay.o

编译完成以后所有的.o 文件就全部存放到了 obj 目录下
在这里插入图片描述
第 31 行的 VPATH 是指定搜索目录的,这里指定的搜素目录就是变量 SRCDIRS 所保存的目录,这样当编译的时候所需的.s 和.c 文件就会在 SRCDIRS 中指定的目录中查找。

第 33 行指定了一个伪目标 clean。

第 35~47 行就很熟悉了

3.3、编译下载

使用 Make 命令编译代码,编译成功以后使用软件 imxdownload 将编译完成的 bsp.bin 文件下载到 SD 卡中,命令如下:

chmod 777 imxdownload //给予 imxdownload 可执行权限,一次即可
./imxdownload bsp.bin /dev/sdd //烧写到 SD 卡中

烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板,如果代码运行正常的话 LED0 就会以 1000ms 的时间间隔亮灭

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php图片视频,PHP中使用php5-ffmpeg撷取视频图片实例

前几天在玩 FFmpeg 的时后&#xff0c;突然发现 Ubuntu 上多了 php5-ffmpeg 这个扩充套件&#xff0c;就想来玩玩看&#xff0c;看好不好用&#xff0c;有两个结论&#xff1a;读取影片取决于 FFmpeg 的支援性&#xff0c;如果想要什么格式都支援的话&#xff0c;建议自己重新编…

ARM(IMX6U)裸机C语言蜂鸣器驱动实验(BSP+SDK)

参考&#xff1a;Linux之ARM&#xff08;IMX6U&#xff09;裸机C语言蜂鸣器驱动实验–驱动编写,编译 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-16 14:47:23 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108032168 目录1、有源蜂鸣…

java金字塔的流程图,R中的金字塔图

Plotrix可能更容易&#xff0c;但可以反汇编ggplot图表&#xff0c;并将它们排列为金字塔图 . 使用 eipi10的数据(谢谢)&#xff0c;并调整drawing-pyramid-plot-using-r-and-ggplot2中的代码&#xff0c;我为"males"&#xff0c;"females"和"country…

ARM(IMX6U)裸机按键输入实验(BSP+SDK、GPIO输入与输出、按键消抖)

参考&#xff1a;Linux之ARM&#xff08;IMX6U&#xff09;裸机按键输入实验&#xff08;GPIO的输出与输入&#xff09; 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-17 21:43:37 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108057…

php 提取正文算法,PHP生成文章摘要算法_栈

之前网上复制了一个摘要算法&#xff0c;一直使用正常。最近写的一篇前500字里含有超链接&#xff0c;就导致摘要生成有误&#xff0c;从而影响了前端样式。所以后面打算自己写&#xff0c;想起大学编译原理匹配表达式的大致思想&#xff0c;就决定采用栈的思想试试。实现目标&…

设计模式 之 《组合模式》

GOOD&#xff1a;整体和部分可以被一致对待&#xff08;如WORD中复制一个文字、一段文字、一篇文章都是一样的操作&#xff09; #ifndef __COMPOSITE_MODEL__ #define __COMPOSITE_MODEL__ #include <iostream> #include <string> #include <vector> using n…

ARM(IMX6U)裸机主频和时钟

参考&#xff1a;Linux之ARM&#xff08;IMX6U&#xff09;裸机主频和时钟配置 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-28 10:39:17 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108237599 目录1、I.MX6U 时钟系统详解系统时钟…

关联矩阵古林法的matlab代码,[转载][原创]灰色关联分析及Matlab程序实现

灰色系统理论由我国著名学者邓聚龙教授于1982提出。灰色关联分析是灰色系统理论的一个分支&#xff0c;应用灰色关联分析方法对受多种因素影响的事物和现象从整体观念出发进行综合评价是一个被广为接受的方法。一、灰色关联分析法的建模过程灰色关联分析法的基本思想是根据各比…

C语言排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)

参考&#xff1a;C语言五大排序&#xff08;桶排序&#xff0c;冒泡排序&#xff0c;选择排序&#xff0c;插入排序&#xff0c;快速排序&#xff09;动态演示 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-09-09 20:18:43 网址&#xff1a;https://blog.csdn.net/we…

FIFO分枝_限界算法

问题&#xff1a; 检索4-皇后问题的状态空间树如下图的基本过程。&#xff08;4-皇后问题解空间的树结构&#xff0c;结点按深度优先检索编号&#xff09; 如果按序扩展这些结点&#xff0c;则下一个E-结点就是结点2。扩展结点2后生成结点3&#xff0c;8和13。利用限界函数(同行…

智能家居APP使用指南

参考&#xff1a;智能家居APP使用指南 作者&#xff1a;图触靓 发布时间&#xff1a; 2021-04-14 14:11:40 网址&#xff1a;https://blog.csdn.net/bhbhhyg/article/details/115694774 目录一、如何修改IP&#xff0c;端口号&#xff0c;以及发送的指令二、如何增加或者删除一…

python zlib字符串压缩

2019独角兽企业重金招聘Python工程师标准>>> 在做网络程序时,可以对字符串进行压缩来节省带宽 项目中用到 {"compress": <压缩标记>, "result":[[设备类型.设备ID, 设备名称, 单位ID, 设备功能], ...]} 只做了简单的压缩解压缩,也没crc3…

linux做一个客户端与WemosD1作为服务器的无线通信(局域网通信)

参考&#xff1a;linux做一个客户端与WemosD1作为服务器的无线通信&#xff08;局域网通信&#xff09; 作者&#xff1a;枕上 发布时间&#xff1a;2021-07-19 23:33:44 网址&#xff1a;https://blog.csdn.net/jinchi_boke/article/details/118916896?utm_sourceapp&app…

C语言学习书籍推荐《C语言程序设计 现代方法(第2版)》下载

下载地址&#xff1a;点我 C语言仍然是计算机领域的通用语言之一&#xff0c;但现在的C语言已经和当初的时候大不相同了。本书主要的一个目的就是通过一种“现代方法”来介绍C语言&#xff0c;书中强调标准C&#xff0c;强调软件工程&#xff0c;不再强调“手工优化”。这一版中…

wemosD1_WIFI模块 与 arduino

参考&#xff1a;wemosD1_WIFI模块 与 arduino 作者&#xff1a;枕上 发布时间&#xff1a;2021-07-19 21:49:55 网址&#xff1a;https://blog.csdn.net/jinchi_boke/article/details/118915142 目录作为设备接入wifi&#xff08;STA模式&#xff09;架设Wemos为ftp服务器ardu…

本机在合成图片经常提示内存不足

转载于:https://www.cnblogs.com/niyl/p/9988614.html

tp5 php7 报500,记一次TP单元测试报500错误的问题

记一次TP单元测试报500错误的问题一直听说好的单元测试能提高代码质量&#xff0c;昨天终于在下定决心弄懂单元测试&#xff0c;但第一步就把我干趴下了&#xff0c;我的问题在下面开始都没有什么问题&#xff0c;tp5单元测试的手册就那一点&#xff0c;通过看云上一位仁兄写的…

H3C配置

H3C交换机配置 1.查看设备版本,确定是否需要升级 <H3C>dis version 2.vlan及接口配置 注&#xff1a;正式配置前可以查看下现有的VLAN。命令如下 <H3C>dis vlan <H3C>sys                          //进入系统视图模式 [H3C]vlan …

创建自己的共用js库

直至昨晚为止&#xff0c;学习了一个多月的MVC与jQuery&#xff0c;从所做的练习中&#xff0c;发觉jQuery的代码也有跟C#语言一样可以重构&#xff0c;多页面有相同使用的方法函数&#xff0c;均可以放置于一个单独立的js文件或是自定义的js库中。在使用时&#xff0c;引用此库…

视频专辑:JAVA语言入门视频教程

为什么80%的码农都做不了架构师&#xff1f;>>> 专辑&#xff1a;JAVA语言入门视频教程 简介:该视频专辑是java的入门教程&#xff0c;适合初学者学习java&#xff0c;讲的也非常容易懂&#xff0c;希望能给想学习java的朋友一些帮助。 1 JAVASE 01 简介 2013-10…