I have been trying to integrate Unity Testing Framework into Keil version 5, naturally I faced a lot of issues and errors and was able to solve a lot of them, now I am facing an error that I would like to get your support with.
A brief summary:
This is my thesis project, which is Embedded software testing and the implementation teams are using Keil uvision 5 with code skeleton and configuration generated using STM32CubeMx for the development of a self-driving car project at my university.
The enviroment
OS: Windows 10
IDE-Version:
µVision V5.24.2.0
Tool Version Numbers:
Toolchain: MDK-ARM Professional Version: 5.24.1
Toolchain Path: C:\Keil_v5\ARM\ARMCC\Bin
C Compiler: Armcc.exe V5.06 update 5 (build 528)
Assembler: Armasm.exe V5.06 update 5 (build 528)
Linker/Locator: ArmLink.exe V5.06 update 5 (build 528)
Library Manager: ArmAr.exe V5.06 update 5 (build 528)
Hex Converter: FromElf.exe V5.06 update 5 (build 528)
CPU DLL: SARMCM3.DLL V5.24.1
Dialog DLL: DCM.DLL V1.16.0.0
Target DLL: STLink\ST-LINKIII-KEIL_SWO.dll V3.0.1.0
Dialog DLL: TCM.DLL V1.32.0.0
Practice board: STM32F446ZETx
The approach
I plan to integrate Unity FW by using a makefile to compile and run the tests in the pre-build option available withing Keil. for now I am trying to make the makefile work using commandline outside Keil, once it works, I believe it will easy to just run it with a make command from Keil pre-build option. I followed this tutorial to create the makefile http://www.throwtheswitch.org/build/make
I edited the makefile by adding the appropriate armcc and armlinker with the commandline options that were present in the keil configuration of the project and the arm compiler alternatives for what the tutorial was adding to their gcc as you will see in the makefile below
The structure
The following is sample structure of a Blinky project using TIM10 timer created using STM32CubeMx and Unity FW is added manually to the folder
--root
----Drivers
--------CMSIS --> "Drivers related files"
--------STM32F4xx_HAL-Driver --> "Drivers related files"
----Inc
---------gpio.h
---------main.h
---------stm32f4xx_hal_config.h
---------stm32f4xx_it.h
---------tim.h
----MDK-ARM
---------"Other STM32 related folders and files"
----Src
---------gpio.c
---------main.c
---------stm32f4xx_hal_msp.c
---------stm32f4xx_hal_config.c
---------stm32f4xx_it.c
---------tim.c
----Unity
---------build
-------------depends --> "autogenerated by makefile"
-------------objs --> "autogenerated by makefile"
-------------results --> "autogenerated by makefile"
-------------testing --> "autogenerated by makefile"
-------------TIM10_LED_1_Ceedling_try1.map
---------src
-------------stm32f4xx_hal.h
-------------unity_internals.h
-------------unity.c
-------------unity.h
---------test
-------------Testgpio.c
--.mxproject
--makefile
--mx.scratch
--TIM10_LED_1_Ceedling_try1.ioc
The makefile
ifeq ($(OS),Windows_NT)
ifeq ($(shell uname -s),) # not in a bash-like shell
CLEANUP = del /F /Q
MKDIR = mkdir
else # in a bash-like shell, like msys
CLEANUP = rm -f
MKDIR = mkdir -p
endif
TARGET_EXTENSION=exe
else
CLEANUP = rm -f
MKDIR = mkdir -p
TARGET_EXTENSION=out
endif
.PHONY: clean
.PHONY: test
PATHU = Unity/src/
PATHS = Src/
PATHI = Unity/src/
PATHI2 = Inc
PATHI3 = Drivers/STM32F4xx_HAL_Driver/Inc
PATHI4 = Drivers/STM32F4xx_HAL_Driver/Inc/Legacy
PATHI5 = Drivers/CMSIS/Device/ST/STM32F4xx/Include
PATHI6 = Drivers/CMSIS/Include
PATHT = Unity/test/
PATHB = Unity/build/testing/
PATHD = Unity/build/depends/
PATHO = Unity/build/objs/
PATHR = Unity/build/results/
BUILD_PATHS = $(PATHB) $(PATHD) $(PATHO) $(PATHR)
SRCT = $(wildcard $(PATHT)*.c)
COMPILE=armcc -c --cpu Cortex-M4.fp -D__MICROLIB -g -O3 --apcs=interwork --split_sections
LINK=armlink --library_type=microlib --libpath="C:\Keil_v5\ARM\ARMCC\lib" --strict --scatter "MDK-ARM\TIM10_LED_1_Ceedling_try1\TIM10_LED_1_Ceedling_try1.sct" --diag_suppress=L6329 --summary_stderr --info summarysizes --map --xref --callgraph --symbols --info sizes --info totals --info unused --info veneers --list "TIM10_LED_1_Ceedling_try1.map" -o "MDK-ARM\TIM10_LED_1_Ceedling_try1\TIM10_LED_1_Ceedling_try1.axf"
DEPEND=armcc --no_depend_system_headers --depend_dir=$(PATHD)
CFLAGS=-I. -I$(PATHU) -I$(PATHS) -I$(PATHI) -I$(PATHI2) -I$(PATHI3) -I$(PATHI4) -I$(PATHI5) -I$(PATHI6)
RESULTS = $(patsubst $(PATHT)Test%.c,$(PATHR)Test%.txt,$(SRCT) )
PASSED = `grep -s PASS $(PATHR)*.txt`
FAIL = `grep -s FAIL $(PATHR)*.txt`
IGNORE = `grep -s IGNORE $(PATHR)*.txt`
test: $(BUILD_PATHS) $(RESULTS)
@echo "-----------------------\nIGNORES:\n-----------------------"
@echo "$(IGNORE)"
@echo "-----------------------\nFAILURES:\n-----------------------"
@echo "$(FAIL)"
@echo "-----------------------\nPASSED:\n-----------------------"
@echo "$(PASSED)"
@echo "\nDONE"
$(PATHR)%.txt: $(PATHB)%.$(TARGET_EXTENSION)
-./$< > $@ 2>&1
$(PATHB)Test%.$(TARGET_EXTENSION): $(PATHO)Test%.o $(PATHO)%.o $(PATHU)unity.o $(PATHD)Test%.d
$(LINK) $@ $^
$(PATHO)%.o:: $(PATHT)%.c
$(COMPILE) $(CFLAGS) $< -o $@
$(PATHO)%.o:: $(PATHS)%.c
$(COMPILE) $(CFLAGS) $< -o $@
$(PATHO)%.o:: $(PATHU)%.c $(PATHU)%.h
$(COMPILE) $(CFLAGS) $< -o $@
$(PATHD)%.d:: $(PATHT)%.c
$(DEPEND) $@ $<
$(PATHB):
$(MKDIR) $(PATHB)
$(PATHD):
$(MKDIR) $(PATHD)
$(PATHO):
$(MKDIR) $(PATHO)
$(PATHR):
$(MKDIR) $(PATHR)
clean:
$(CLEANUP) $(PATHO)*.o
$(CLEANUP) $(PATHB)*.$(TARGET_EXTENSION)
$(CLEANUP) $(PATHR)*.txt
.PRECIOUS: $(PATHB)Test%.$(TARGET_EXTENSION)
.PRECIOUS: $(PATHD)%.d
.PRECIOUS: $(PATHO)%.o
.PRECIOUS: $(PATHR)%.txt
The current output and error
$ makecc -I. -IUnity/src/ -ISrc/ -IUnity/src/ -IInc -IDrivers/STM32F4xx_HAL_Driver/Inc -IDrivers/STM32F4xx_HAL_Driver/Inc/Legacy -IDrivers/CMSIS/Device/ST/STM32F4xx/Include -IDrivers/CMSIS/Include -c -o Unity/src/unity.o Unity/src/unity.c
armcc --no_depend_system_headers --depend_dir=Unity/build/depends/ Unity/build/depends/Testgpio.d Unity/test/Testgpio.c
Error: C4065E: type of input file 'Unity/build/depends/Testgpio.d' unknown
make: *** [makefile:74: Unity/build/depends/Testgpio.d] Error 1
rm Unity/src/unity.o
UPDATE -- simple makefile to test dependency error
SRC = $(wildcard *.c)
TAR = $(SRC:.c=.d)
DEPEND=armcc --no_depend_system_headers
all: $(TAR)
%.d: %.c
$(DEPEND) $@ $<
Unfortunately it returned armcc --no_depend_system_headers test.d test.c
Error: C4065E: type of input file 'test.d' unknow
but when changed the compiler and flags into
SRC = $(wildcard *.c)
TAR = $(SRC:.c=.d)
DEPEND=gcc -MM -MG -MF
all: $(TAR)
%.d: %.c
$(DEPEND) $@ $<
it worked and test.d is created from test.c -- all files are in the same folder
Update
I have managed to get the armcc to work, after checking the docs I updated my makefile as follows:
SRC = $(wildcard *.c)
TAR = $(SRC:.c=.d)
DEPEND=armcc --no_depend_system_headers --ignore_missing_headers --md --depend
all: $(TAR)
%.d: %.c
$(DEPEND) $@ $<
with makefile and the source file in the same folder it works fine.
Now, when returned to the main makefile and updated the DEPEND flags to the following
armcc --no_depend_system_headers --ignore_missing_headers --md --depend
It returned a different error, that has to do with armlink, I do not know how the process goes, what is fired first and which depends on the other, but the fact remains when I run make now it gives the following error:
$ make
cc -I. -IUnity/src/ -ISrc/ -IUnity/src/ -IInc -IDrivers/STM32F4xx_HAL_Driver/Inc -IDrivers/STM32F4xx_HAL_Driver/Inc/Legacy -IDrivers/CMSIS/Device/ST/STM32F4xx/Include -IDrivers/CMSIS/Include -c -o Unity/src/unity.o Unity/src/unity.c
armlink --library_type=microlib --libpath="C:\Keil_v5\ARM\ARMCC\lib" --strict --scatter "MDK-ARM\TIM10_LED_1_Ceedling_try1\TIM10_LED_1_Ceedling_try1.sct" --diag_suppress=L6329 --summary_stderr --info summarysizes --map --xref --callgraph --symbols --info sizes --info totals --info unused --info veneers --list "TIM10_LED_1_Ceedling_try1.map" -o "MDK-ARM\TIM10_LED_1_Ceedling_try1\TIM10_LED_1_Ceedling_try1.axf" Unity/build/testing/Testgpio.exe Unity/build/objs/Testgpio.o Unity/build/objs/gpio.o Unity/src/unity.o
Fatal error: L6002U: Could not open file Unity/build/testing/Testgpio.exe: No such file or directory
Finished: 0 information, 0 warning, 0 error and 1 fatal error messages.
make: *** [makefile:62: Unity/build/testing/Testgpio.exe] Error 1
rm Unity/src/unity.o
I will continue working on it, but if someone can help please do
great Update!
The previous error is gone and I am starting to see actual progress ! I commented out $(PATHD)Test%.d in the LINK step as it was commented out in the orignal file I got, when I included it, the error is gone and I am now facing syntax errors and warning from actual files :) please check below and advise
$ make
armcc --no_depend_system_headers --ignore_missing_headers --depend Unity/build/depends/Testgpio.d Unity/test/Testgpio.c
"Unity/test/Testgpio.c", line 13: Warning: #223-D: function "TEST_ASSERT_EQUAL" declared implicitly
TEST_ASSERT_EQUAL(2, AddFunction_ReturnCorrect(1, 1));
^
"Unity/test/Testgpio.c", line 13: Warning: #223-D: function "AddFunction_ReturnCorrect" declared implicitly
TEST_ASSERT_EQUAL(2, AddFunction_ReturnCorrect(1, 1));
^
"Unity/test/Testgpio.c", line 19: Warning: #223-D: function "UnityBegin" declared implicitly
UnityBegin("test/Testgpio.c");
^
"Unity/test/Testgpio.c", line 20: Warning: #223-D: function "RUN_TEST" declared implicitly
RUN_TEST(test_AddFunction_ReturnCorrect_ShouldReturnCorrectSum);
^
"Unity/test/Testgpio.c", line 22: Warning: #223-D: function "UnityEnd" declared implicitly
return (UnityEnd());
^
Unity/test/Testgpio.c: 5 warnings, 0 errors
Error: L6218E: Undefined symbol AddFunction_ReturnCorrect (referred from Testgpio.o).
Error: L6218E: Undefined symbol RUN_TEST (referred from Testgpio.o).
Error: L6218E: Undefined symbol TEST_ASSERT_EQUAL (referred from Testgpio.o).
Error: L6218E: Undefined symbol UnityBegin (referred from Testgpio.o).
Error: L6218E: Undefined symbol UnityEnd (referred from Testgpio.o).
Finished: 0 information, 0 warning and 5 error messages.
make: *** [makefile:74: Unity/build/depends/Testgpio.d] Error 1
Update
I am not what is happening here, after 3 4 makes the previous error returned
Update
OK so If I delete the build folder and run make, it gives the L6218E errors, if I run make again it gives the L6002U error. Also someone can explain why at the end of each make it runs rm Unity/src/unity.o
?