I mentioned in Go Reference that MCU10 and eclipse come with a comfortable infrastructure: you add, remove, rename source files and set compiler options: managed make will take care and creates the make files for you. Make files are such a great thing because they allow you do to pretty much everything.
Classic CodeWarrior uses a different approach without make files. Exporting the project as make file did not really work, so make files were not something you could have used easily in classic. With the eclipse based MCU10 make files are the heart of the build system. In most cases using the managed make system is perfectly fine. But for a bare metal enthusiast it makes sense to use my own make file instead.
With a make file I can program my build. As with any programming language, it takes some time to master it. To learn more about make files have a look at GNU make documentation.
In the steps below, I’m going to create a make project for the Freescale HCS08 in the eclipse based CodeWarrior for MCU10.2. In contrast to the managed make, I will create my own make file and will have full control.
I start with using the File > New > Other menu:
I enable Show All Wizards and select the C Project (which is otherwise hidden), pressing Next.
The first time I create a C/C++ make project, a dialog will ask me to enable Generic C/C++ GNU Development. I’m OK with this.
Next I specify the project name, select an Empty Project under Makefile project with — Other Toolchain — and press Finish:
Now I have an empty project with nothing in it :-). Well, this is not completely true, as eclipse has created the .cproject and .project files in my project folder containing the project information.
What is missing in my project is to specify which make utility I want to use. CodeWarrior for MCU10.2 comes with the mingw32-make. For details about this implementation of make see the http://www.mingw.org/ web site. I want to use following command for make in my project settings:
${system:ECLIPSE_HOME}/../gnu/bin/mingw32-make -j6
Using Project > Properties I can specify the above as my Build Command:
For my S08 make file project I need 4 files:
- The startup file start08.c. I copy it from another project or use the one from <installation>\MCU\lib\hc08c\src\start08.c
- The linker file for my microcontroller. I use one from another project or one from the templates in <installation>\MCU\lib\hc08c\prm
- At least one source file, e.g. main.c with the main() function.
- And last but not least the makefile. I can create that makefile with the menu File > New General > File
I add a simple endless loop to my main.c:
void main(void) { Ā for(;;) { Ā Ā Ā /* not doing anything for now */ Ā } }
Next, I start add variables in my makefile:
ProjDirPathĀ Ā Ā Ā Ā Ā Ā Ā := C:/tmp/make_wsp/myProject CWInstallDirPathĀ Ā Ā := C:/Freescale/CW MCU v10.2 GnuInstallDirPathĀ Ā := $(CWInstallDirPath)/gnu/bin LL := "$(CWInstallDirPath)/MCU/prog/linker" LLFLAGS := CC := "$(CWInstallDirPath)/MCU/prog/chc08" CCFLAGS := -I"$(CWInstallDirPath)/MCU/lib/hc08c/include"
The variables point to my project directory (ProjDirPath), my CodeWarrior installation path (CWInstallDirPath) and the path where my gnu tools are located (GnuInstallDirPath). The variables LL and CC point to my linker and compiler, and CCFLAGS and LLFLAGS contain my compiler and linker options.
Next I add a rules to the make file. Rules in make files are in the form of
target: dependency list <tab>commands
In make file language, this says: “To build the target on the left hand side, the dependency list on the right hand side has to be built first. To create the target, the command(s) preceded by tabs have to be executed.”
With this in mind, I can write my rules as:
all: project.abs Ā Ā Ā @echo 'all done!' project.abs: project.prm main.o start08.o Ā Ā Ā $(LL) $(LLFLAGS) project.prm \ Ā Ā Ā -Add(main.o) \ Ā Ā Ā -Add(start08.o) \ Ā Ā Ā -O"project.abs" start08.o: start08.c Ā Ā Ā $(CC) $(CCFLAGS) start08.c main.o: main.c Ā Ā Ā $(CC) $(CCFLAGS) main.c
If I select now my project and do a Project > Build Project, I get in the Console View:
**** Build of configuration Default for project myProject **** C:\Freescale\CW MCU v10.2\gnu\bin\mingw32-make -j6 all "C:/Freescale/CW MCU v10.2/MCU/prog/chc08" -I"C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include" main.c "C:/Freescale/CW MCU v10.2/MCU/prog/chc08" -I"C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include" start08.c start08.c Command Line: '-I"C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include" start08.c' C:\tmp\make_wsp\myProject\start08.c Ā "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\start08.h" Ā "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\hidef.h" Ā Ā "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\stddef.h" Ā Ā "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\stdtypes.h" Ā "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\non_bank.sgm" Ā "C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include\non_bank.sgm" Object file: C:\tmp\make_wsp\myProject\start08.o, format ELF/DWARF 2.0 main.c Command Line: '-I"C:/Freescale/CW MCU v10.2/MCU/lib/hc08c/include" main.c' Code Size: 149 Global objects: 6, Data Size (RAM): 6 HC08 Compiler: *** 0 error(s), 0 warning(s), 0 information message(s) *** HC08 Compiler: *** Processing ok *** C:\tmp\make_wsp\myProject\main.c Object file: C:\tmp\make_wsp\myProject\main.o, format ELF/DWARF 2.0 Code Size: 2 Global objects: 1 HC08 Compiler: *** 0 error(s), 0 warning(s), 0 information message(s) *** HC08 Compiler: *** Processing ok *** "C:/Freescale/CW MCU v10.2/MCU/prog/linker"Ā project.prm \ -Add(main.o) \ -Add(start08.o) \ -O"project.abs" project.prm Command Line: 'project.prm -Add(main.o) -Add(start08.o) -O"project.abs"' Linking C:\tmp\make_wsp\myProject\project.prm Reading file 'C:\tmp\make_wsp\myProject\main.o' Reading file 'C:\tmp\make_wsp\myProject\start08.o' Generating Symbol table Generating DWARF data version 2.0 Code Size: 167 Generating MAP file 'C:\tmp\make_wsp\myProject\project.map' SmartLinker: *** 0 error(s), 0 warning(s), 0 information message(s) *** SmartLinker: *** Processing ok *** 'all done!'
If not, then something is wrong. One common error in make files is using spaces instead of tabs at the beginning of command lines. Using the Show Whitespace Characters is very useful in this context:
Another extremely helpful tool to spot errors in make files is using the Outline View:
While things are working well for now, adding new source files requires adding new rules.Ā Instead of:
start08.o: start08.c Ā Ā Ā $(CC) $(CCFLAGS) start08.c main.o: main.c Ā Ā Ā $(CC) $(CCFLAGS) main.c
I can use generic rules with:
# rule how to build an object file from a C file %.o: %.c Ā Ā Ā @echo 'Building file:
lt;' Ā Ā Ā $(CC) $(CCFLAGS)
lt;
Using rules for specific files still makes sense as for files which need some special treatment.
So far I’m using the ‘all’ make target as default make target. Why not adding a new make target to clean my project?
RM := "$(GnuInstallDirPath)/rm" -f clean: Ā Ā Ā $(RM) *.abs Ā Ā Ā $(RM) *.o Ā Ā Ā $(RM) *.map Ā Ā Ā $(RM) EDOUT
As I have now two make targets (‘all‘ and ‘clean‘), it makes sense to take advantage of the eclipse Make Target View. In that view I can add make targets using the ‘New Make Target’ button:
With this I can specify the ‘all’ and ‘clean’ target names:
With double clicking on a make target or using the toolbar icon it is now easy to execute a make target:
One thing remains: the source files and the object files are all in one folder. It would be better to use separate folders for source and object (and linked) files.
For this I add extra variables OBJ_PATH and SRC_PATH in my make file and change the options and rules to use it. Below is the extended make file:
ProjDirPathĀ Ā Ā Ā Ā Ā Ā Ā := C:/tmp/make_wsp/myProject CWInstallDirPathĀ Ā Ā := C:/Freescale/CW MCU v10.2 GnuInstallDirPathĀ Ā := $(CWInstallDirPath)/gnu/bin OBJ_PATH := obj SRC_PATH := src RM := "$(GnuInstallDirPath)/rm" -f LL := "$(CWInstallDirPath)/MCU/prog/linker" LLFLAGS := -EnvTEXTPATH=obj CC := "$(CWInstallDirPath)/MCU/prog/chc08" CCFLAGS := -I"$(CWInstallDirPath)/MCU/lib/hc08c/include" -ObjN="$(OBJ_PATH)/%%n.o" -EnvTEXTPATH=obj all: $(OBJ_PATH)/project.abs Ā Ā Ā @echo 'all done!' $(OBJ_PATH)/project.abs: $(SRC_PATH)/project.prm $(OBJ_PATH)/main.o $(OBJ_PATH)/start08.o Ā Ā Ā @echo 'Linking file:
lt;' Ā Ā Ā $(LL) $(LLFLAGS) $(SRC_PATH)/project.prm \ Ā Ā Ā -Add($(OBJ_PATH)/main.o) \ Ā Ā Ā -Add($(OBJ_PATH)/start08.o) \ Ā Ā Ā -O"$(OBJ_PATH)/project.abs" # rule how to build an object file from a C file $(OBJ_PATH)/%.o: $(SRC_PATH)/%.c Ā Ā Ā @echo 'Building file:
lt;' Ā Ā Ā $(CC) $(CCFLAGS)
lt; clean: Ā Ā Ā @echo 'Cleaning generated files...' Ā Ā Ā $(RM) $(OBJ_PATH)/*.abs Ā Ā Ā $(RM) $(OBJ_PATH)/*.o Ā Ā Ā $(RM) $(OBJ_PATH)/*.map Ā Ā Ā $(RM) EDOUT Ā Ā Ā $(RM) err.log
Now I can use different folders for the source and the output files in my make file project:
Uff, that was some work, but now I’m having complete control over my build.
Happy Making š
Pingback: No rule to make target | MCU on Eclipse
Pingback: Linting without a plugin | MCU on Eclipse
Pingback: DYI Free Toolchain for Kinetis: Part 1 – GNU ARM Build Tools | MCU on Eclipse
Hi, is very nice work!!! now how load a s19 whit linux terminal??
LikeLike
Thanks :-). I have not used it on Linux, but I’m able to download a file from the command line (https://mcuoneclipse.com/2012/08/03/codewarrior-flash-programming-from-a-dos-shell/). I don’t see a reason why this would not work on Linux?
LikeLiked by 1 person
I see this post. I not know Tcl script, I think that this can be done whit shell script in linux.
LikeLike
Hi Erich,
maybe a dumb beginners question: In my projects (HCS08) I am using only start08.c and main.c. Main.c consists only of calls of MCU_init() and asm_main() (because my knowledge of C is near zero, I am programming only in assembler). How do I have to add my asm and inc files to the make file? Or are they invoked automatically because of the call in main.c?
LikeLike
If C or assembly, this does not matter. All what is different in make files is that you need a rule to produce object files from *.asm instead of .c, and that you have dependencies to *.inc instead of .h. And that you call the assembler in the rule instead of the C compiler.
LikeLike
Pingback: Tutorial: Makefile Projects with Eclipse | MCU on Eclipse
Hello Erich,
Not sure if you are still active but I am trying to get the freeRTOS running on the TWR-S12G240. I read somewhere else that you did have it working with this board but for me the reset method in the “TickCntr” mentions it is not supported for the selected device but there is also no way to disable it. Did you ever come across this problem and if so how did you solve it?
I am using the classic codewarrior v5.1 and the FreeRTOS_2.203_31.01.2013 processor expert component
Sebastiaan
LikeLike
Hi Sebastiann,
yes, I’m still active :-). I have not used that board for a long while, so it could be that the FreeRTOS port sor S12 is out-of-date. I have to check the status and check if I can find a board.
Erich
LikeLike
I quickly tried it. I think you have not turned on the ‘Classic CodeWarrior’ option, see https://mcuoneclipse.com/2012/02/11/back-to-classic-freertos-for-freescale-s12x/ ?
LikeLike
Thank you for your quick response. Unfortunately I think I do have the option turned on.
Classic Codewarrior is set to “yes”.
The error already occurs before generating the code and is caused by
FRTOS1-> Ticks -> non-LDD Tick -> TickCntr -> Methods -> Reset.
It set to generate code but says “Method Reset not supported for the selected device”
But I have no way of turning off the code generation.
LikeLike
You should be able to right click on that Disable() method and turn it off.
LikeLike
I can unfortunately not turn it off by right clicking it only comes up with the options
“help on the method” and “copy error message to clipboard”. I see no other way of disabling it either.
I unfortunately can’t send an image or the project via this forum to show exactly what I mean.
LikeLike
You can use the email address on https://mcuoneclipse.com/about/
LikeLike