看过上一篇文章会知道,我们已经可以生成模型代码和主程序,但还没有进行编译,今天我们对Toolbox进行改造,在点击Build之后除了生成C文件,还将自动的编译生成bin文件。
在此之前,我已经为我的STM32硬件准备好一个完整的工程,把里面的主程序删除掉,剩下的是:
首先我们修改mytarget.tlc这个系统tlc文件,增加设置代码生成路径、二进制文件输出路径和驱动代码路径的功能。
/%
BEGIN_RTW_OPTIONS
rtwoptions(1).prompt = 'MyTarget';
rtwoptions(1).type = 'Category';
rtwoptions(1).enable = 'on';
rtwoptions(1).default = 4;
rtwoptions(1).popupstrings = '';
rtwoptions(1).tlcvariable = '';
rtwoptions(1).tooltip = '';
rtwoptions(1).callback = '';
rtwoptions(1).makevariable = '';
rtwoptions(2).prompt = 'Code Generated Path:';
rtwoptions(2).type = 'Edit';
rtwoptions(2).enable = 'on';
rtwoptions(2).default = '';
rtwoptions(2).tlcvariable = 'tlc_code_output';
rtwoptions(2).makevariable = 'CODE_FILE_PATH';
rtwoptions(2).tooltip = 'The path where generated source code files will be put into';
rtwoptions(2).callback = '';
rtwoptions(3).prompt = 'Browser...';
rtwoptions(3).type = 'Pushbutton';
rtwoptions(3).enable = 'on';
rtwoptions(3).default = '';
rtwoptions(3).tooltip = 'Locate the path where the generated files will be put into';
rtwoptions(3).callback = 'pathbrowsercallback(hDlg,hSrc,''tlc_code_output'')';
rtwoptions(4).prompt = 'Binary Output Path:';
rtwoptions(4).type = 'Edit';
rtwoptions(4).enable = 'on';
rtwoptions(4).default = '';
rtwoptions(4).tlcvariable = 'tlc_bin_output';
rtwoptions(4).makevariable = 'BIN_FILE_PATH';
rtwoptions(4).tooltip = 'The path where binary files will be put into';
rtwoptions(4).callback = '';
rtwoptions(5).prompt = 'Browser...';
rtwoptions(5).type = 'Pushbutton';
rtwoptions(5).enable = 'on';
rtwoptions(5).default = '';
rtwoptions(5).tooltip = 'Locate the path where the binary files will be put into';
rtwoptions(5).callback = 'pathbrowsercallback(hDlg,hSrc,''tlc_bin_output'')';
rtwoptions(6).prompt = 'Driver Path:';
rtwoptions(6).type = 'Edit';
rtwoptions(6).enable = 'on';
rtwoptions(6).default = '';
rtwoptions(6).tlcvariable = 'tlc_driver_path';
rtwoptions(6).makevariable = 'DRIVER_PATH';
rtwoptions(6).tooltip = 'The path where driver project is';
rtwoptions(6).callback = '';
rtwoptions(7).prompt = 'Browser...';
rtwoptions(7).type = 'Pushbutton';
rtwoptions(7).enable = 'on';
rtwoptions(7).default = '';
rtwoptions(7).tooltip = 'Locate the path where the driver is';
rtwoptions(7).callback = 'pathbrowsercallback(hDlg,hSrc,''tlc_driver_path'')';
经过以上修改后可以看到模型配置选项发生了变化。
在tlc文件里的几个makevariable和makefile里的变量名是一样的,为了让代码和二进制文件能够生成到指定路径,并告知编译器使用我们模型生成的代码进行编译,tmf文件做了小幅修改,关键部分放在下面。
MAKE = C:\TDM-GCC-64\bin\make
KEIL_PATH = C:\Keil\ARM
ARMCC = $(KEIL_PATH)\BIN40\armcc
ARMASM = $(KEIL_PATH)\BIN40\armasm
ARMAR = $(KEIL_PATH)\BIN40\armar
ARMLINK = $(KEIL_PATH)\BIN40\armlink
FROMELF = $(KEIL_PATH)\BIN40\fromelf
MAKECMD = C:\TDM-GCC-64\bin\make
SHELL = cmd
HOST = PC
BUILD = yes
SYS_TARGET_FILE = mytarget.tlc
COMPILER_TOOL_CHAIN = armcc
CODE_FILE_PATH = |>CODE_FILE_PATH<|
BIN_FILE_PATH = |>BIN_FILE_PATH<|
DRIVER_PATH = |>DRIVER_PATH<|
CFLAGS := -c --cpu Cortex-M3 -D__MICROLIB -g -O0 --apcs=interwork
CMACRO := -DSTM32F10X_HD -DUSE_STDPERIPH_DRIVER
ASMFLAGS := --cpu Cortex-M3 -g --apcs=interwork --pd "__MICROLIB SETA 1"
LINKFLAGS := --cpu Cortex-M3 --library_type=microlib --strict
MAP := --autoat --summary_stderr --info summarysizes --map --xref --callgraph --symbols
INFO := --info sizes --info totals --info unused --info veneers
TARGET = $(BIN_FILE_PATH)\$(MODEL)
OBJMAP := $(BIN_FILE_PATH)\*.map
OBJHTM := $(BIN_FILE_PATH)\*.htm
OBJAXF := $(BIN_FILE_PATH)\*.axf
MODEL_SRC=$(wildcard $(CODE_FILE_PATH)/*.c)
MODEL_DIR=$(notdir $(MODEL_SRC))
OBJS=$(patsubst %.c,%.o,$(MODEL_DIR) )
OBJS +=$(DRIVER_PATH)\Startup\startup_stm32f10x_hd.o\
$(DRIVER_PATH)\Libraries\CMSIS\core_cm3.o\
$(DRIVER_PATH)\Libraries\CMSIS\system_stm32f10x.o\
$(DRIVER_PATH)\Libraries\CMSIS\stm32f10x_it.o
INC := -I$(CODE_FILE_PATH)
INC += -I$(KEIL_PATH)\RV31\INC
INC += -I$(KEIL_PATH)\CMSIS\Include
INC += -I$(KEIL_PATH)\INC\ST\STM32F10x
INC += -I$(DRIVER_PATH)\Libraries\CMSIS
INC += -I$(DRIVER_PATH)\Libraries\STM32F10x_StdPeriph_Driver\inc
%.o:%.c
$(ARMCC) $(CFLAGS) $(INC) $(CMACRO) $< -o $@
%.o:%.s
$(ARMASM) $(ASMFLAGS) $(INC) $< -o $@
mytarget:$(OBJS)
$(ARMLINK) $(LINKFLAGS) --libpath "$(KEIL_PATH)\RV31\LIB" --scatter=$(DRIVER_PATH)/Project/mytarget.sct $(MAP) $(INFO) --list $(TARGET).map $^ $(DRIVER_PATH)\Libraries\STM32F10xR_V3.0.lib --output=$(TARGET).axf
$(FROMELF) --bin -o $(TARGET).bin $(TARGET).axf
$(FROMELF) --i32 -o $(TARGET).hex $(TARGET).axf
del $(OBJHTM) $(OBJAXF) $(OBJS)
echo ### Created!
.PHONY : clean
clean:
del $(OBJS) *.map *.htm
还记得我们在实现自动配置模型参数的时候有这么一句吗?它是什么作用呢?
set_param(cs,‘PostCodeGenCommand’,‘mytarget_postgen(buildInfo)’);
这条语句设置了代码生成之后的回调函数,mytarget_postgen这个m语言的函数主要实现将模型生成的c文件拷贝到指定路径的功能,同时输出过程信息,如果指定的路径下已经有C文件,则先删除。
function mytarget_postgen(buildInfo)
disp('MyTarget postgen process!');
currentpath = pwd;
modelName = buildInfo.MODELNAME
cs = getActiveConfigSet(modelName);
% Get target path from model configuration
CodePath = get_param(cs,'tlc_code_output');
BinPath = get_param(cs,'tlc_bin_output');
cd(currentpath);
% Display work path
str = ['Current path is : ', currentpath];
disp(str);
str = ['Code will be generated to : ', CodePath];
disp(str);
str = ['Binary will be generated to : ', BinPath];
disp(str);
% Delete old files
cd(CodePath);
disp('Delete old files......');
oldcfiles =dir(fullfile(CodePath,'*.c'));
for i = 1:length(oldcfiles)
delete(oldcfiles(i).name);
str = ['Delete old source file : ',oldcfiles(i).name];
disp(str);
end
oldhfiles =dir(fullfile(CodePath,'*.h'));
for i = 1:length(oldhfiles)
delete(oldhfiles(i).name);
str = ['Delete old header file : ',oldhfiles(i).name];
disp(str);
end
cd(currentpath);
% Copy new files to code path
disp('Copy new files......');
cfiles = dir(fullfile(pwd,'*.c'));
hfiles = dir(fullfile(pwd,'*.h'));
for i = 1:length(cfiles)
copyfile(cfiles(i).name,CodePath);
str = ['Copy C source file : ',cfiles(i).name];
disp(str);
end
for i = 1:length(hfiles)
copyfile(hfiles(i).name,CodePath);
str = ['Copy C header file : ',hfiles(i).name];
disp(str);
end
end
OK,像上次一样,我们的模型里只放置一个进行模型配置的模块,我们点击Build按钮,稍等片刻会弹出代码生成的报告,和上次一样,这次我们再进一步,打开Diagnostic View,可以看到,除了生成了demo这个模型的c文件和makefile文件demo.mk,还如我们预期的进行了copy和编译的操作。
before tlc
### Invoking Target Language Compiler on demo.rtw
### Using System Target File: E:\Workspace\matlab\mytarget_toolbox\mytarget\mytarget.tlc
### Loading TLC function libraries
### Initial pass through model to cache user defined code
.
### Caching model source code
### Writing header file demo_types.h
### Writing header file demo.h
### Writing header file rtwtypes.h
.
### Writing source file demo.c
### Writing header file demo_private.h
### Writing header file rtmodel.h
### Writing source file main.c
### TLC code generation complete.
### Generating TLC interface API.
.
### Creating ASAP2 file: demo.a2l
### Indenting ASAP2 file.
after tlc
### Evaluating PostCodeGenCommand specified in the model
MyTarget postgen process!
modelName =
'demo'
Current path is : E:\Workspace\matlab\demo\demo_mytarget_rtw
Code will be generated to : E:\Workspace\matlab\code
Binary will be generated to : E:\Workspace\matlab\bin
Delete old files......
Delete old source file : demo.c
Delete old source file : main.c
Delete old header file : demo.h
Delete old header file : demo_private.h
Delete old header file : demo_types.h
Delete old header file : rtmodel.h
Delete old header file : rtwtypes.h
Copy new files......
Copy C source file : demo.c
Copy C source file : main.c
Copy C header file : demo.h
Copy C header file : demo_private.h
Copy C header file : demo_types.h
Copy C header file : rtmodel.h
Copy C header file : rtwtypes.h
before_make
.
### Processing Template Makefile: E:\Workspace\matlab\mytarget_toolbox\mytarget\mytarget.tmf
### Wrapping unrecognized make command (angle brackets added)
###
### in default batch file
### demo.mk which is generated from E:\Workspace\matlab\mytarget_toolbox\mytarget\mytarget.tmf is up to date
### Building demo: .\demo.bat
E:\Workspace\matlab\demo\demo_mytarget_rtw>set MATLAB=D:\Program Files\Matlab2017b
E:\Workspace\matlab\demo\demo_mytarget_rtw>C:\TDM-GCC-64\bin\make -f demo.mk GENERATE_ASAP2=1
C:\Keil\ARM\BIN40\armcc -c --cpu Cortex-M3 -D__MICROLIB -g -O0 --apcs=interwork -
------------这里省略各种编译输出信息-------------
E:\Workspace\matlab\mytarget_toolbox\src\Libraries\CMSIS\system_stm32f10x.o E:\Workspace\matlab\mytarget_toolbox\src\Libraries\CMSIS\stm32f10x_it.o
echo ### Created!
### Created!
after_make
Model demo Code genrattion complete for mytarget!
### Creating HTML report file demo_codegen_rpt.html
Build process completed successfully
打开设定的Binary文件输出路径,可以看到bin、hex和map文件已经生成到这里。
到这一步,Simulink Toolbox从模型配置到代码生成,再到自动化代码编译的主体流程已经串通,后面要做的就是要针对硬件开发各种外设的模块级S-Function和TLC,在调试过程中不断进行驱动工程的完善和调整。