ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

六.项目的BSP工程管理

2022-01-01 02:02:30  阅读:238  来源: 互联网

标签:__ 文件 typedef led 工程 项目 BSP void bsp


随着我们的代码功能完善,在一个文件夹下放置所有文件已经不太合适了,针对我们上一章使用NXP提供的库来说,简简单单一个点亮LED的试验,目录结构就很乱了

 

 在做复杂功能项目的时候,需要对目录结构进行优化,这里引入一个新概念——BSP(Board Support Package 板级支持包),目录的结构先这样做

先按照下面结构建立目录

 

 其中,bsp用来放驱动文件,imx6u放和芯片有关的文件,obj编译以后生成的.o文件,project放C代码和汇编代码。先把前一章的几个头文件放在imx6u文件夹下,把start.s和main.c放在project里,然后有些代码,比方LED初始化,时钟初始化什么的,可以拆解出来写成独立的代码放在bsp根据功能不同可以放在bsp下几个按照功能建立的文件夹中。

这次的试验还和前面一样,点亮LED。

工程分解

为了以后的驱动开发方便,我们把各个功能模块分开放,

/bsp文件夹

bsp文件夹下放下面的文件

 

 

clk为时钟管理,delay为定时,led为led的驱动,代码直接放在下面

clk文件夹下文件:

#ifndef __BSP_CLK_H
#define __BSP_CLK_H
#include "imx6ul.h"

void clk_enable(void);
#endif
bsp_clk.h
#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

delay文件夹下文件

#ifndef __BSP_DELAY_H
#define __BSP_DELAY_H

#include "imx6ul.h"

void delay(volatile unsigned int n);

#endif
bsp_delay.h
#include "bsp_delay.h"
// 空操作,演示大约1ms
void delay_short(volatile unsigned int n)
{
    while(n--){}
}

void delay(volatile unsigned int n)
{
    while(n--){delay_short(0x7ff);}
}
bsp_delay.c

led文件夹下文件:

#ifndef __BSP_LED_H
#define __BSP_LED_H

#include "imx6ul.h"

#define LED0    0

void led_init(void);
void led_on(void);
void led_off(void);
void led_switch(int led, int status);


#endif
bsp_led.h
#include "bsp_led.h"

/*初始化LED*/
void led_init(void)
{   
    // 复用、电气属性寄存器初始化

    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0);
    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0x10B0);
    // GPIO1方向寄存器,
    GPIO1->GDIR = 0x8;
}


// 点亮LED
void led_on(void)
{
    GPIO1->DR &= ~(1<<3); //bit3清零
}


// 关闭LED
void led_off(void)
{
    GPIO1->DR |=(1<<3);  //bit3置一
}


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;
    }
}
bsp_led.c

/project文件夹

上面是基础的驱动,然后是project文件夹

 

 

里面是主函数和汇编的环境配置

.global _start

_start:
    MRS R0,CPSR
    BIC R0,R0,#0x1f
    ORR R0,R0,#0x13
    MSR CPSR,R0

    ldr sp,=0x80200000

    b main
start.s
#include "bsp_led.h"
#include "bsp_delay.h"
#include "bsp_clk.h"

int main(void)
{
    clk_enable();
    led_init();
    
    while(1)
    {
        led_switch(LED0,ON);
        delay(200);
        led_switch(LED0,OFF);
        delay(200);

    }
    return 0;
}
main.c

/imx6ul文件夹

imx6ul是芯片的库文件

 

 

 其中,cc.h是我们定义的数据类型,imx6ul.h是自己定义的头文件,这里定义这个头文件是简化了驱动库里导入头文件的方法,因为这里的几个库文件几乎在驱动的.h文件里几乎都要导入,定义了这个文件以后只用导入这个头文件就等于导入所有库文件了。

#ifndef __CC_H
#define __CC_H

#define __I     volatile
#define __O     volatile
#define __IO    volatile

#define ON      1
#define OFF     0

typedef signed char         int8_t;
typedef signed short        int16_t;
typedef signed int          int32_t;
typedef unsigned char       uint8_t;
typedef unsigned short      uint16_t;
typedef unsigned int        uint32_t;
typedef unsigned long long  uint64_t;

typedef signed char         s8;
typedef signed short        s16;
typedef signed int          s32;
typedef long long           s64;
typedef unsigned char       u8;
typedef unsigned short      u16;
typedef unsigned int        u32;
typedef unsigned long long  u64;
#endif
cc.h
#ifndef __IMX6UL_H
#define __IMX6UL_H

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

#endif
imx6ul.h

 

Makefile文件

这里的Makefile文件是个重要点,因为在工程目录里所有的文件是按照路径管理的,在根目录下单Makefile就找不到需要编译的文件了。先把Makefile放下来

CROSS_COMPILE    ?= arm-linux-gnueabihf-
TARGET            ?= bsp

CC                := $(CROSS_COMPILE)gcc
LD                 := $(CROSS_COMPILE)ld
OBJCOPY            := $(CROSS_COMPILE)objcopy 
OBJDUMP            := $(CROSS_COMPILE)objdump 

INCLUDIRS        := imx6ul    \
                    bsp/clk    \
                    bsp/led \
                    bsp/delay

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

# 利用patsubst进行字符串修改,在INCLUDIRS每个路径前加-I \
$(patsubst <pattern>,<replacement>,<text>) \
名称:模式字符串替换函数——patsubst。\
功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符\
合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通\
配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>\
中的这个“%”将是<pattern>中的那个“%”所代表的字串。\
(可以用“\”来转义,以“\%”来表示真实含义的“%”字符)\
返回:函数返回被替换过后的字符串
INCLUDE            :=$(patsubst %, -I % ,$(INCLUDIRS))


#获取项目中.c、.s文件 \
foreach 类似BASH里的for循环,用法是 $(foreach <var>,<list>,<text>)    \
就是把list里的单词逐一取出放在变量var中,然后执行text的表达式内,每次text会返回一个字符串。            \
最后循环结束时,<text>返回值为每个字符串所组成的整个字符串,之间以空格分格,                \
wildcard为展开指定对象下文件集合
SFILES            := $(foreach dir ,$(SRCDIRS),$(wildcard $(dir)/*.s))
CFILES            := $(foreach dir ,$(SRCDIRS),$(wildcard $(dir)/*.c))

#获取不带路径的文件名,用来修改后缀生成.o文件的文件名
SFILENDIR        := $(notdir $(SFILES))        # 不带路径的文件名,
CFILENDIR        := $(notdir $(CFILES))        # 不带路径的文件名


# 将不带路径的文件名转换成.o后缀名,对应编译后文件名
SOBJS            := $(patsubst %, obj/%,$(SFILENDIR:.s=.o))    #.s=.o是把.s用.o替换
COBJS            := $(patsubst %, obj/%,$(CFILENDIR:.c=.o))      #.c=.o是把.c用.o替换

OBJS             := $(SOBJS) $(COBJS)

VPATH            := $(SRCDIRS)            

.PHONY: clean

$(TARGET).bin : $(OBJS)

    $(LD) -Timx6ul.lds -o $(TARGET).elf $^                   #将所有依赖文件链接,生成.elf文件
    $(OBJCOPY) -O binary -S $(TARGET).elf $@                #将elf转换为依赖的目标集合
    $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis        #将elf文件反汇编


# 静态模式 <Targets...>:<tatgets-pattern>:<prereq-patterns...>下面两天为自写
$(SOBJS) :    obj/%.o    :    %.s  #将所有的.s文件编译成.o文件放在obj文件夹内
    $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<

$(COBJS) : obj/%.o : %.c 
    $(CC) -Wall -nostdlib -c -O2  $(INCLUDE) -o $@ $<

clean:
    rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).dis $(OBJS)

print:
    @echo INCLUDE = $(INCLUDE)
    @echo OBJS = $(OBJS)

大体的说明我都注释出来了,就是用了好几种函数

包括但不限于替换字符串的patsubst,循环结构的foreach,静态模式等,这个Makefile文件就作为后期驱动开发用到的通用Makefile了。整个文件结构要比以前用到的Makefile复杂了好多,但是按照注释看应该好理解。调试的时候在一个地方卡了很久:

SOBJS            := $(patsubst %, obj/%,$(SFILENDIR:.s=.o))    #.s=.o是把.s用.o替换

patsubst后面第一个百分号后多了个空格,编译的时候一直报错

 

 并且后面用打印的伪目标调试也能打印出来对应的变量,一定要注意。

 链接脚本

注意看一下Makefile里的链接,我们使用了一个叫做链接脚本的文件来替换链接地址0x87800000。这个脚本就是根目录下单一个文件,拷贝在路径下就可以了,大致作用就是用于规定如何把输入文件内的section放入输出文件内, 并控制输出文件内各部分在程序地址空间内的布局. 但也可以用连接命令做一些其他事情,具体作用以后有机会再讲。

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

 

标签:__,文件,typedef,led,工程,项目,BSP,void,bsp
来源: https://www.cnblogs.com/yinsedeyinse/p/15747289.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有