ARM(IMX6U)BSP工程文件管理(分文件编程)
參考:Linux之ARM(IMX6U)BSP工程管理實驗
作者:一只青木呀
發(fā)布時間: 2020-08-15 23:41:37
網(wǎng)址:https://blog.csdn.net/weixin_45309916/article/details/108028093
目錄
- 1、工程管理簡介
- 1.1、創(chuàng)建bsp、imx6ul、obj和project這四個文件夾
- 1.2、文件分類
- 2、實驗程序編寫
- 2.1、創(chuàng)建 imx6ul.h 文件
- 2.2、創(chuàng)建.vscode文件修改includePath(解決找不到頭文件問題)
- 2.2.1、修改includePath
- 2.3、編寫led驅(qū)動文件
- 2.3.1、 bsp_led.h
- 2.3.2、 bsp_led.c
- 2.4、編寫時鐘驅(qū)動代碼
- 2.4.1、bsp_clk.h
- 2.4.2、bsp_clk.c
- 2.5、編寫延時驅(qū)動代碼
- 2.5.1、bsp_delay.h
- 2.5.2、bsp_delay.c
- 2.6、修改main.c代碼
- 2.6.1、創(chuàng)建一個main.h文件,用來包含頭文件
- 2.6.2、main.c
- 3、編譯下載與驗證
- 3.1、編寫鏈接文件
- 3.2、編寫Makefile文件
- 3.3、編譯下載
在我們寫工程中,我們都是將所有的源碼文件放到工程的根目錄下,如果工程文件比較少的話這樣做無可厚非, 但是如果工程源文件達(dá)到幾十、甚至數(shù)百個的時候,這樣一股腦全部放到根目錄下就會使工程顯得混亂不堪。所以我們必須對工程文件做管理,將不同功能的源碼文件放到不同的目錄中。另外我們也需要將源碼文件中,所有完成同一個功能的代碼提取出來放到一個單獨(dú)的文件中,也就是對程序分功能管理。 本章我們就來學(xué)習(xí)一下如何對一個工程進(jìn)行整理,使其美觀、功能模塊清晰、易于閱讀。
1、工程管理簡介
在我們上一篇博客中(ARM(MX6U)裸機(jī)官方SDK移植)中,文件有:
我們將所有的源碼文件都放到工程根目錄下,即使這個工程只是完成了一個簡單的流水燈的功能,但是其工程根目錄下的源碼文件就已經(jīng)不少了。如果在添加一些其他的功能文件,那么文檔就會更大,顯得很混亂,所以我們需要對這個工程進(jìn)行整理,將源碼文件分模塊、分功能整理。我們來看一個比較好的例程:
圖 中的工程目錄就很美觀、不同的功能模塊文件放到不同的文件夾中,比如驅(qū)動文件就放到bsp文件夾中, 官方庫就放到 imx6ul文件夾中,編譯產(chǎn)生的過程文件放到 OBJ 文件夾中
我們參考這個來整理一下(ARM(MX6U)裸機(jī)官方SDK移植)中的文件。
1.1、創(chuàng)建bsp、imx6ul、obj和project這四個文件夾
- 其中 bsp 用來存放驅(qū)動文件;
- imx6ul 用來存放跟芯片有關(guān)的文件,比如 NXP 官方的 SDK庫文件;
- obj 用來存放編譯生成的.o 文件;
- project 存放 start.S 和 main.c 文件,也就是應(yīng)用文件;
1.2、文件分類
-
將(ARM(MX6U)裸機(jī)官方SDK移植)實驗中的 cc.h、fsl_common.h、 fsl_iomuxc.h 和 MCIMX6Y2.h 這四個文件拷貝到文件夾 imx6ul 中;
-
將 start.S 和 main.c 這兩個文件拷貝到文件夾 project 中。
-
我們前面的實驗中所有的驅(qū)動相關(guān)的函數(shù)都寫到了 main.c 文件中,比如函數(shù) clk_enable、 led_init 和 delay,這三個函數(shù)可以分為三類:時鐘驅(qū)動、 LED 驅(qū)動和延時驅(qū)動。因此我們可以在 bsp 文件夾下創(chuàng)建三個子文件夾: clk、 delay 和 led,分別用來存放時鐘驅(qū)動文件、延時驅(qū)動文件和 LED 驅(qū)動文件
這樣main.c 函數(shù)就會清爽很多,程序功能模塊清晰。工程文件夾都創(chuàng)建好了,接下來就是編寫代碼了,其實就是將時鐘驅(qū)動、 LED 驅(qū)動和延時驅(qū)動相關(guān)的函數(shù)從 main.c 中提取出來做成一個獨(dú)立的驅(qū)動文件 。
2、實驗程序編寫
使用 VScode 新建工程,工程名字為“l(fā)edc_bsp”。
2.1、創(chuàng)建 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、創(chuàng)建.vscode文件修改includePath(解決找不到頭文件問題)
是為了vscode解決找不到工程的頭文件的問題
在終端創(chuàng)建“ .vscode文件夾 ”,打開c_cpp_properties.json文件(自動創(chuàng)建出來的)。
2.2.1、修改includePath
把我們的頭文件的文件夾路徑添加進(jìn)去
這樣刷新一下,就可以包含所需的頭文件了
2.3、編寫led驅(qū)動文件
新建 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/*函數(shù)聲明*/ 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 的內(nèi)容很簡單,就是一些函數(shù)聲明和頭文件的引用
2.3.2、 bsp_led.c
#include "bsp_led.h"/*打開LED燈*/ void led_on(void) {GPIO1->DR&= ~(1<<3); //bit3清零} /*關(guān)閉LED燈*/ void led_off(void ) {GPIO1->DR |= (1<<3); //bit3置1 }/*初始化LED燈*/ void led_init(void) {IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0); /*復(fù)用為GPIO--IO03 */IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0x10B0);/*設(shè)置GPIO__IO03電器屬性*/GPIO1->GDIR=0x8;//設(shè)置為輸出GPIO1->DR=0x0; //設(shè)置為低電平,打開LED燈}/*LED 燈控制函數(shù)*/ 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 里面就兩個函數(shù) led_init 和 led_switch, led_init 函數(shù)用來初始化 LED 所使用的IO, led_switch 函數(shù)是控制 LED 燈的打開和關(guān)閉
2.4、編寫時鐘驅(qū)動代碼
新建 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_H2.4.2、bsp_clk.c
#include "bsp_clk.h"/*使能外設(shè)時鐘*/ 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 函數(shù),用來使能所有的外設(shè)時鐘。
2.5、編寫延時驅(qū)動代碼
新建 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_H2.5.2、bsp_delay.c
#include "bsp_delay.h"/*短延時*/ void delay_short(volatile unsigned int n) {while(n--){}} /** 延時 一次循環(huán)大概是1ms 在主頻396MHz* n:延時ms數(shù) */ void delay(volatile unsigned int n) {while (n--){delay_short(0x7ff);}}2.6、修改main.c代碼
2.6.1、創(chuàng)建一個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_H2.6.2、main.c
#include "main.h"int main() {clk_enable(); //使能外設(shè)時鐘led_init(); //初始化LEDwhile(1){led_off(); delay(1000);led_on();delay(1000);}return 0; }在 main.c 中我們僅僅留下了 main 函數(shù),至此,本例程跟程序相關(guān)的內(nèi)容就全部編寫好了
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 行設(shè)置的 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 文件要比前面的實驗復(fù)雜很多,因為這個Makefile 代碼是一個通用 Makefile,我們以后所有的裸機(jī)例程都使用這個 Makefile。使用時候只要將所需要編譯的源文件所在的目錄添加到 Makefile 中即可
第 1~7 行定義了一些變量,除了第 2 行以外其它的都是跟編譯器有關(guān)的,如果使用其它編譯器的話只需要修改第 1 行即可。第 2 行的變量 TARGET 目標(biāo)名字,不同的例程肯定名字不一一樣。
第 9 行的變量 INCDIRS 包含整個工程的.h 頭文件目錄,文件中的所有頭文件目錄都要添加到變量INCDIRS中。比如本例程中包含.h頭文件的目錄有imx6ul、bsp/clk、bsp/delay和bsp/led,所以就需要在變量 INCDIRS 中添加這些目錄,即:
INCDIRS := imx6ul bsp/clk bsp/led bsp/delay仔細(xì)觀察的話會發(fā)現(xiàn)第 9~11 行后面都會有一個符號“\”,這個相當(dāng)于“換行符”,表示本行和下一行屬于同一行,一般一行寫不下的時候就用符號“\”來換行。在后面的裸機(jī)例程中我們會根據(jù)實際情況來在變量 INCDIRS 中添加頭文件目錄。
第 14 行是變量 SRCDIRS,和變量 INCDIRS 一樣,只是 SRCDIRS 包含的是整個工程的所有.c 和.S 文件目錄。比如本例程包含有.c 和.S 的目錄有 bsp/clk、 bsp/delay、 bsp/led 和 project,即:
SRCDIRS := project bsp/clk bsp/led bsp/delay同樣的,后面的裸機(jī)例程中我們也要根據(jù)實際情況在變量 SRCDIRS 中添加相應(yīng)的文件目錄。
第 19 行的變量 INCLUDE 是用到了函數(shù) patsubst,通過函數(shù) patsubst 給變量 INCDIRS 添加一個“-I”,即:
INCLUDE := -I imx6ul -I bsp/clk -I bsp/led -I bsp/delay加“-I”的目的是因為 Makefile 語法要求指明頭文件目錄的時候需要加上“-I”。
第 21 行變量 SFILES 保存工程中所有的.s 匯編文件(包含絕對路徑),變量 SRCDIRS 已經(jīng)存放了工程中所有的.c 和.S 文件,所以我們只需要從里面挑出所有的.S 匯編文件即可,這里借助了函數(shù) foreach 和函數(shù) 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 只是文件名,不包含文件的絕對路徑。使用函數(shù) 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 文件編譯以后對應(yīng)的.o 文件目錄,默認(rèn)所有的文件編譯出來的.o 文件和源文件在同一個目錄中,這里我們將所有的.o 文件都放到 obj 文件夾下, SOBJS 和 COBJS 內(nèi)容如下:
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 所保存的目錄,這樣當(dāng)編譯的時候所需的.s 和.c 文件就會在 SRCDIRS 中指定的目錄中查找。
第 33 行指定了一個偽目標(biāo) clean。
第 35~47 行就很熟悉了
3.3、編譯下載
使用 Make 命令編譯代碼,編譯成功以后使用軟件 imxdownload 將編譯完成的 bsp.bin 文件下載到 SD 卡中,命令如下:
chmod 777 imxdownload //給予 imxdownload 可執(zhí)行權(quán)限,一次即可 ./imxdownload bsp.bin /dev/sdd //燒寫到 SD 卡中燒寫成功以后將 SD 卡插到開發(fā)板的 SD 卡槽中,然后復(fù)位開發(fā)板,如果代碼運(yùn)行正常的話 LED0 就會以 1000ms 的時間間隔亮滅
總結(jié)
以上是生活随笔為你收集整理的ARM(IMX6U)BSP工程文件管理(分文件编程)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: canvas简易人机五子棋
- 下一篇: VM虚拟机不能上网的问题解决