cortex m4与matlab连接,从零搭建Cortex-M4工程

考察一个嵌入式工程师能力的重要指标就是,是否具备架构大型工程的能力。作为一个合格的嵌入式工程师,在职业生涯中一定有需要架构一个全新的工程。

废话不多说,接下来我们以一款Cortex-M4的MUC为例,给大家展示如何搭建一个的嵌入式系统的工程框架。

1. 环境

(1) 硬件:STM32F407核心板,只有基础的供电和晶振电路,没有外围器件;

选择这块板子作为例子有三个重要的原因:

其一,意法的MCU应用很广泛,比较具有代表性;

其二,官网支持比较好,开发资料很容易找;

其三,也是最重要的,我手里刚好有一块;

(2) 工具链:gcc-arm-none-eabi

我用过很多嵌入式开发环境,ADS、keil、IAR等等,但开发32位单片机最喜欢的还是GNU的这套工具链,而且使用这套工具链还有一个重要的原因,相比其他开发环境,由于GNU与脚本可以紧密结合,使得搭建持续集成服务器会容易得多。

(3) 第三方库:STM32Cube_FW_F4_V1.14.0

意法官网提供的驱动包:

注:启动代码一定要使用gcc目录下的:

Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\gcc\startup_stm32f407xx.s

2. 目录划分

根据嵌入式系统层次顶层划分了五个目录:

|– apps # 应用层程序路径

|– boot # 启动代码路径

|– build # 编译根目录

|– bin # bin文件输出路径

|– objs # obj文件输出路径

|– drivers # 驱动层程序路径

|– libs # 第三方库(在本例中存放意法官网的驱动库文件)

|– inc 库的头文件

|– src 库的源文件

最终工程目录划分如下图所示:

.

├── apps

│   ├── main.c

│   └── Makefile

├── boot

│   ├── Makefile

│   └── startup.s

├── build

│   ├── bin

│   ├── Makefile

│   ├── objs

│   └── stm32f407vet6.ld

├── drivers

│   ├── inc

│   ├── Makefile

│   └── src

├── libs

│   ├── inc

│   ├── Makefile

│   └── src

└── Makefile

3. 编写Makefile

对于多文件夹的工程,不仅需要在根目录编写Makefile,而且需要为每个子文件夹单独编写Makefile文件,并在根目录的文件夹中遍历所有子文件夹并调用其中的Makefile。

(1) 根目录Makefile

对于循环调用子文件夹中的Makefile,一个简单的办法是利用awk命令和make命令的-C参数:

SUBDIRS =$(shell ls -l | grep ^d | awk ‘{if($$9 != “build”) print $$9}’)

$(SUBDIRS):ECHO

make -C $@

ECHO:

@echo $(SUBDIRS)

其中:

“grep ^d”表示ls -l命令后首行以‘d’字母开头,既文件夹;

“$$9”表示第九列的值

由于我们需要在build文件夹中进行最后的链接工作,所以在遍历子目录的时候排除‘build’文件夹。

除此之外,我们还需要记录几个固定的目录:

ROOT_DIR=$(shell pwd)

OBJS_DIR=build/obj

BIN_DIR =build/bin

头文件路径:

INCS+=-I$(ROOT_DIR)/stm32f407_lib/inc

INCS+=-I$(ROOT_DIR)/drivers/inc

编译选项:

CFLAGS+= -mcpu=cortex-m4 -mthumb -Wall

CFLAGS+= -mfloat-abi=hard -mfpu=fpv4-sp-d16

CFLAGS+= -Os

CFLAGS+= -ffunction-sections -fdata-sections

链接选项:

LFLAGS+= -mcpu=cortex-m4 -mthumb

LFLAGS+= -mfloat-abi=hard -mfpu=fpv4-sp-d16

LFLAGS+= -Wl,–gc-sections

最终将这些宏导出,以供子目录编译时使用:

export BIN OBJS_DIR BIN_DIR ROOT_DIR DEFS INCS CFLAGS LFLAGS

(2) 子目录Makefile

子目录中Makefile文件的编写通常需要使用到三个十分常用的Makefile函数:wildcard、notdir和patsubst。

其中:

wildcard:用于搜索路径中的文件,并以空格间隔每个文件从而形成列表的形式返回

例如,本工程drives路径下的src目录中有两个C文件,那么编写如下Makefile:

CUR_SOURCE=$(wildcard *.c ./src/*.c)

all: $(CUR_SOURCE)

@echo $(CUR_SOURCE)

执行后输出结果为:

./src/key.c ./src/led.c

notdir:用于去掉列表中的文件夹路径

还以上面的Makefile为例,如果再增加一行:

CUR_SOURCE=$(wildcard *.c ./src/*.c)

NOT_SOURCE=$(notdir $(CUR_SOURCE))

all: $(CUR_SOURCE)

@echo $(CUR_SOURCE)

@echo $(NOT_SOURCE)

执行后输出结果为:

./src/key.c ./src/led.c

key.c led.c

patsubst:用于匹配替换

在上文的Makefile中继续增加一行:

CUR_SOURCE=$(wildcard *.c ./src/*.c)

NOT_SOURCE=$(notdir $(CUR_SOURCE))

PAT_SOURCE=$(patsubst %.c, %.o, $(NOT_SOURCE))

all: $(CUR_SOURCE)

@echo $(CUR_SOURCE)

@echo $(NOT_SOURCE)

@echo $(PAT_SOURCE)

最终输出结果为:

./src/key.c ./src/led.c

key.c led.c

key.o led.o

对于子目录中不存在下级目录的情况,我们可以简单地编写Makefile文件如下:

CUR_SOURCE =$(wildcard *.c)

CUR_OBJS =$(patsubst %.c, %.o, $(CUR_SOURCE))

all:$(CUR_OBJS)

$(CUR_OBJS):%.o:%.c

@echo $^

@$(CC) $(CFLAGS) $(DEFS) $(INCS) -c $^ -o $(ROOT_DIR)/$(OBJS_DIR)/$@

而对于子目录中还有下级src路径的情况,可以简单地编写Makefile如下:

CUR_SOURCE=$(wildcard ./src/*.c)

CUR_OBJS=$(patsubst %.c, %.o, $(notdir $(CUR_SOURCE)))

all:$(CUR_OBJS)

$(CUR_OBJS):%.o:$(DIR_SRC)/%.c

@echo $^

@$(CC) $(CFLAGS) $(DEFS) $(INCS) -c $^ -o $(ROOT_DIR)/$(OBJS_DIR)/$@

(3) build目录Makefile

最终所有子目录中的程序都编译为.o文件后,需要在build文件夹中进行链接,链接的过程分为两步:

生成elf格式的文件:

$(ROOT_DIR)/$(BIN_DIR)/$(OBJ_ELF):$(OBJS)

@$(CC) $(LFLAGS) -Tstm32.ld -o $@ $^

转为可以直接烧写到Flash中的bin文件:

$(ROOT_DIR)/$(BIN_DIR)/$(BIN):$(ROOT_DIR)/$(BIN_DIR)/$(OBJ_ELF)

@arm-none-eabi-objcopy -O binary -S $< $@

4. 链接脚本

意法的官方库中提供了链接脚本的样例,但在具体的工程中需要根据不同的MCU以及RAM、Flash划分进行改写,例如,本例中使用的STM32F407后缀名为‘VET6’具有512K Flash,192K RAM,则修改:

/* Highest address of the user mode stack */

_estack = 0x20020000;    /* end of RAM */

/* Specify the memory areas */

MEMORY

{

FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 512K

RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K

CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值