I'm trying to develop a new feature for an embedded application and I'd like to do so using a test-driven approach.
The project is written in pure C and is being developed using IAR Embedded Workbench 6.60.1.5104. I'm targeting an LPC1788, which is a Cortex-M3 device, and all development is being done on a 64-bit Windows 7 machine. Right now I'm more in favour of getting unit tests to run on the PC rather than on the target hardware (RAM is quite limited).
I came across a useful book on the subject called Test Driven Development for Embedded C and that pointed me towards tools like Unity, CppUTest, Ceedling, etc. After looking into this stuff, I think my best choice is to configure Ceedling (which uses Unity) for my project. However, I'm not sure exactly what steps I need to take to configure Ceedling to work with my current IAR toolchain.
I've installed Ceedling and created the "blinky" example project and I'm trying to build and test it using the IAR toolchain. I've added iccarm.exe
to my path and edited blinky/project.yml
as given below:
---
# Notes:
# This is a fully tested project that demonstrates the use
# of a timer ISR to blink the on board LED of an Arduino UNO
:project:
:use_exceptions: FALSE
:use_test_preprocessor: TRUE
:use_auxiliary_dependencies: TRUE
:build_root: build
:release_build: TRUE
:test_file_prefix: test_
#You'll have to specify these
:environment:
- :mcu: atmega328p
- :f_cpu: 16000000UL
- :serial_port: COM8 #change this to the serial port you are using!!!
- :objcopy: avr-objcopy
# Uncomment these lines if you are using windows and don't have these tools in your path
# - :path:
# - C:\mingw\bin
# - C:\WinAVR-20100110\bin
# - C:\WinAVR-20100110\utils\bin
# - #{ENV['PATH']}
:extension:
:executable: .bin
:release_build:
:output: blinky
:paths:
:test:
- +:test/**
- -:test/support
:source:
- src/**
:support:
- test/support
:defines:
# in order to add common defines:
# 1) remove the trailing [] from the :common: section
# 2) add entries to the :common: section (e.g. :test: has TEST defined)
:commmon: &common_defines []
:test:
- *common_defines
- TEST
:test_preprocess:
- *common_defines
- TEST
:tools:
:release_compiler:
:executable: avr-gcc
:arguments:
- ${1}
- -DTARGET
- -DF_CPU=#{ENV['F_CPU']}
- -mmcu=#{ENV['MCU']}
- -Iinclude/
- -Wall
- -Os
- -c
- -o ${2}
:release_linker:
:executable: avr-gcc
:arguments:
- -mmcu=#{ENV['MCU']}
- ${1}
- -o ${2}.bin
:cmock:
:mock_prefix: mock_
:when_no_prototypes: :warn
:enforce_strict_ordering: TRUE
:plugins:
- :ignore
:treat_as:
uint8: HEX8
uint16: HEX16
uint32: UINT32
int8: INT8
bool: UINT8
:tools:
:test_file_preprocessor:
:executable: iccarm
:name: 'IAR test file preprocessor'
:test_includes_preprocessor:
:executable: iccarm
:name: 'IAR test includes preprocessor'
:test_compiler:
:executable: iccarm
:name: 'IAR test compiler'
:test_linker:
:executable: iccarm
:name: 'IAR test linker'
:release_compiler:
:executable: iccarm
:name: 'IAR release compiler'
:release_linker:
:executable: iccarm
:name: 'IAR release linker'
:plugins:
:load_paths:
- vendor/ceedling/plugins
:enabled:
- stdout_pretty_tests_report
- module_generator
...
The only difference between this and the default project.yml
is the content under the second :tools
section.
My guess is that I'm heading in the right direction, but I'm not sure whether iccarm.exe
is the correct executable to use for all these parts of the toolchain and what arguments I need to pass.
If I can configure Ceedling to build and test the blinky project using an IAR toolchain, I'm hoping I should be able to apply the same configuration for my actual project. If I try running rake
now, I get the following output:
$ rake
Test 'test_BlinkTask.c'
-----------------------
rake aborted!
Errno::ENOENT: No such file or directory @ rb_sysopen - build/test/preprocess/files/test_BlinkTask.c
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb:18:in `readlines'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb:18:in `extract_base_file_from_preprocessed_expansion'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb:14:in `preprocess_file'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator.rb:40:in `preprocess_file'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator.rb:12:in `block in setup'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb:33:in `preprocess_test_file'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator.rb:25:in `preprocess_test_and_invoke_test_mocks'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/test_invoker.rb:42:in `block in setup_and_invoke'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/test_invoker.rb:32:in `setup_and_invoke'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/tasks_tests.rake:11:in `block (2 levels) in <top (required)>'
Tasks: TOP => default => test:all
(See full trace by running task with --trace)
--------------------
OVERALL TEST SUMMARY
--------------------
No tests executed.
I assume this is because the test file preprocessor should be copying test files under the build/test/preprocess/files
directory, which currently doesn't happen.
After a bit of digging around I found this example configuration file for Unity that looks like it may be helpful. It's geared towards an IAR EW/Cortex M3 environment like the one I'm using. This may give some indication of what configuration options I need to specify in my Ceedling project.yml
:
If I can get Ceedling to build and test the blinky
project using an IAR toolchain, I'm hoping I can adapt it to work with my actual project. Any help would be appreciated.
It was a struggle but I believe I've managed to configure Ceedling to help test my project. Hopefully this will be useful to anyone else looking to use Ceedling within IAR projects.
The Ceedling CLI has a command (
ceedling new <proj_name>
) that allows you to create new projects with the structure Ceedling expects. You can also specify the name of an existing project in which case it only adds the necessary files to make it Ceedling-compatible, which is what I did with my project.For reference, my project structure looked something like this after performing this step:
After that, I looked over the reference manuals for the IAR tools and studied the output from IAR Embedded Workbench when building sample projects, as @user694733 suggested. I used this information to edit my
project.yml
as given below:This seems to be a suitable configuration for testing code designed to work on a Cortex-M3 device.
I also edited
rakefile.rb
to ensure that the generated test files are cleaned before each test run, as this was necessary to have the test results get printed consistently.I was then able to define and run unit tests. Below is an excerpt from
test_canDatabase.c
:I'm now able to run automated tests by invoking "ceedling" from a terminal (project root is the current working directory):