如何为你的硬件开发Simulink Toolbox(6)

如何为你的硬件开发Simulink Toolbox(6)_第1张图片
看过上一篇文章会知道,我们已经可以生成模型代码和主程序,但还没有进行编译,今天我们对Toolbox进行改造,在点击Build之后除了生成C文件,还将自动的编译生成bin文件。

在此之前,我已经为我的STM32硬件准备好一个完整的工程,把里面的主程序删除掉,剩下的是:

  • Startup,STM32的启动文件
  • Libraries,里面包含外设驱动头文件和STM32F10xR_V3.0.lib
  • Project,这里只放了一个sct文件

首先我们修改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'')';

经过以上修改后可以看到模型配置选项发生了变化。
如何为你的硬件开发Simulink Toolbox(6)_第2张图片在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(6)_第3张图片到这一步,Simulink Toolbox从模型配置到代码生成,再到自动化代码编译的主体流程已经串通,后面要做的就是要针对硬件开发各种外设的模块级S-Function和TLC,在调试过程中不断进行驱动工程的完善和调整。
如何为你的硬件开发Simulink Toolbox(6)_第4张图片

你可能感兴趣的:(Matlab/Simulink,simulink,stm32,matlab,单片机,编译器)