How do I create an optimal, customizable Ceedling configuration for STM32 unit testing?

I’m working on an STM32 project using the stm32f407g-disc1 and want to set up Ceedling for unit testing. It is important for me to maintain the standard folder structure typically used in STM32 projects (such as in STM32CubeMX or STM32CubeIDE), while also having a robust and customizable Ceedling configuration.

I’ve already tried creating the project.yml file myself, but I’m not sure if I’ve implemented all the necessary steps correctly. My goal is to find a good Ceedling configuration that can be easily adapted to different STM32 projects. Are there any best practices or examples for setting up Ceedling optimally for STM32 unit testing, so that the configuration is flexible and sustainable?”

The STM32 Project


:project:
  :use_exceptions: FALSE
  :use_test_preprocessor: :all
  :use_auxiliary_dependencies: TRUE
  :build_root: build
  :release_build: TRUE
  :test_file_prefix: test_
  :which_ceedling: gem
  :ceedling_version: 0.31.1
  :default_tasks:
    - test:all

#:test_build:
# :use_assembly: TRUE

:release_build:
  :output: stmBase
  :use_assembly: TRUE
  :artifacts:
    - stmBase.map

# :output: MyApp.out
# :use_assembly: FALSE

:environment:

:extension:
  :executable: .elf

:paths:
  :test:
    - +:test/**
    - -:test/support
  :source:
    - Core/Inc/**
    - Core/Src/**
  :include:
    - Core/Inc/
    - Drivers/CMSIS/Device/ST/STM32F4xx/Include/
    - Drivers/CMSIS/Include/
    - Drivers/STM32F4xx_HAL_Driver/Inc/
  :toolchain_include:
    - USB_HOST/App
    - USB_HOST/Target
    - Core/Inc
    - build/vendor/unity/src
    - Drivers/STM32F4xx_HAL_Driver/Inc
    - Drivers/STM32F4xx_HAL_Driver/Inc/Legacy
    - Middlewares/ST/STM32_USB_Host_Library/Core/Inc
    - Middlewares/ST/STM32_USB_Host_Library/Class/CDC/Inc
    - Drivers/CMSIS/Device/ST/STM32F4xx/Include
    - Drivers/CMSIS/Include
  :support:
    - test/support

  :libraries: []

# :exclude_files:
#   - CoreSrcmain.c

:defines:
  :common: &common_defines
    - STM32F407xx 
    - USE_HAL_DRIVER 
  :test:
    - *common_defines
    - TEST
  :test_preprocess:
    - *common_defines
    - TEST

:cmock:
  :mock_prefix: mock_
  :when_no_prototypes: :warn
  :enforce_strict_ordering: TRUE
  :plugins:
    - :ignore
    - :callback
  :treat_as:
    uint8: HEX8
    uint16: HEX16
    uint32: UINT32
    int8: INT8
    bool: UINT8
  # TODO: herausfinden, ob das richtig ist.
  :includes:
    - <stdbool.h>
    - <stdint.h>
  :treat_externs: :include


:gcov:
  :reports:
    - HtmlDetailed
  :gcovr:
    :html_medium_threshold: 75
    :html_high_threshold: 90

:tools:
  :test_compiler:
    :executable: arm-none-eabi-gcc
    :arguments:
      - ${1}
      - -mcpu=cortex-m4
      - -std=gnu11
      - -g3
      - -DDEBUG
      - -DUSE_HAL_DRIVER
      - -DSTM32F407xx
      - -c
      - -I"$": COLLECTION_PATHS_TOOLCHAIN_INCLUDE
      - -O0
      - -ffunction-sections
      - -fdata-sections
      - -Wall
      - -fstack-usage
      - -fcyclomatic-complexity
      - -MMD
      - -MP
      - -MF"${2}.d"
      - -MT"${2}.o"
      - --specs=nano.specs
      - -mfpu=fpv4-sp-d16
      - -mfloat-abi=hard
      - -mthumb
      - -o ${2}

  :test_linker:
    :executable: arm-none-eabi-gcc
    :arguments:

      - ${1}
      - -DTARGET
      - -Isrc/ 
      - -I"$": COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE 
      - -mcpu=cortex-m4 
      - -mthumb 
      - -mfpu=fpv4-sp-d16 
      - -mfloat-abi=hard 
      - -Wl,-Map="${2}.map" 
      - -g 
      - -T"STM32F407VGTX_FLASH.ld" 
      - --specs=nosys.specs 
      - -Wl,--gc-sections 
      - -static 
      - --specs=nano.specs 
      - -Wl,--start-group -lc -lm -Wl,--end-group 
      - -o ${2}.elf 


:libraries:
  :placement: :end

  :flag: "-l${1}"

  :path_flag: "-L ${1}"

  :system: [] 

  :test: []

  :release: []

:plugins:
  :load_paths: []
  :enabled: []

New contributor

HEIM_MAG is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

4

Here’s an example of a working setup for a project for an STM32L4P5. Since you are using an STM32F407 you’ll obviously have to change some include paths and defines as appropriate.

First a note on directory structure. Here I have a top-level git repository. Within are two directories containing my application/driver specific code (in MyApp and MyDrivers). You probably want to choose better names, I’ve renamed these from project-specific names just as an example. These directories contain the code that will be unit tested. You might only have one such directory, or more than two, depending on your project.

Then there is the STM32 project (created with STM32CubeIDE or STM32CubeMX, for example). I did not add any of my code into this directory. I changed main.c to call out my project-specific app_main() function.

Lastly there is the unit_test directory, where you will construct the unit-test framework.

It looks like this:

repo_root/
├─ MpApp/
│  ├─ Src/
│  │  ├─ app_file.c
│  ├─ Inc/
│  │  ├─ app_file.h
├─ MyDrivers/
│  ├─ Src/
│  │  ├─ foo_driver.c
│  ├─ Inc/
│  │  ├─ foo_driver.h
├─ STMProject/
│  ├─ Core/
│  ├─ Drivers/
│  ├─ ...etc.../
├─ unit_test/
│  ├─ build/
│  ├─ test/
│  │  ├─ test_app_file.c
│  │  ├─ test_foo_driver.c
│  │  ├─ support/
│  ├─ project.yml

You’ll see that the project contains two files that will be unit tested: app_file.c and foo_driver.c. Hence there are only two files in the unit_test/test directory, one for each file to test.

The unit_test directory contains a build directory, which is where build artifacts will be placed during the test process.

Here is the project.yml file that lives in unit_test:

---

# Notes:
# Sample project C code is not presently written to produce a release artifact.
# As such, release build options are disabled.
# This sample, therefore, only demonstrates running a collection of unit tests.

:project:
  :use_exceptions: TRUE
  :use_test_preprocessor: TRUE
  :use_auxiliary_dependencies: TRUE
  :build_root: build
#  :release_build: TRUE
  :test_file_prefix: test_
  :which_ceedling: gem
  :ceedling_version: 0.31.1
  :default_tasks:
    - test:all

:test_build:
  :use_assembly: FALSE

#:release_build:
#  :output: MyApp.out
#  :use_assembly: FALSE

:environment:

:extension:
  :executable: .out

:paths:
  :test:
    - +:test/**
    - -:test/support
  :source:
    - ../STMProject/Core/Inc/
    - ../MyApp/Src/
    - ../MyApp/Inc/
    - ../MyDrivers/Src/
    - ../MyDrivers/Inc
    - ../STMProject/Drivers/STM32L4xx_HAL_Driver/Inc
    - ../STMProject/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/
    - ../STMProject/Drivers/CMSIS/Device/ST/STM32L4xx/Include/
    - ../STMProject/Drivers/CMSIS/Include
  :support:
    - test/support
  :libraries: []

: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)
  :common: &common_defines
    - STM32L4P5xx
    - USE_HAL_DRIVER
    - TEST
    - CMOCK_MEM_DYNAMIC
  :test:
    - *common_defines
  :test_preprocess:
    - *common_defines

:flags:
  :test:
    :compile:
      :*:
        - -Wno-int-to-pointer-cast
        - -Wno-pointer-to-int-cast
#        - -O0
#        - -g

:cmock:
  :mock_prefix: mock_
  :when_no_prototypes: :warn
  :enforce_strict_ordering: TRUE
  :plugins:
    - :ignore
    - :callback
    - :expect_any_args
    - :ignore_arg
  :includes:
    - stm32l4xx_hal.h
  :includes_h_pre_orig_header:
    - stm32l4xx_hal.h
  :includes_c_pre_header:
    - stm32l4xx_hal.h
  :treat_as:
    uint8:    HEX8
    uint16:   HEX16
    uint32:   UINT32
    int8:     INT8
    bool:     UINT8
  :strippables:
    - '__NO_RETURN'

# Add -gcov to the plugins list to make sure of the gcov plugin
# You will need to have gcov and gcovr both installed to make it work.
# For more information on these options, see docs in plugins/gcov
:gcov:
  :reports:
    - HtmlDetailed
    - Text
  :gcovr:
    :html_medium_threshold: 75
    :html_high_threshold: 90
    :print_summary: true

#:tools:
# Ceedling defaults to using gcc for compiling, linking, etc.
# As [:tools] is blank, gcc will be used (so long as it's in your system path)
# See documentation to configure a given toolchain for use


# LIBRARIES
# These libraries are automatically injected into the build process. Those specified as
# common will be used in all types of builds. Otherwise, libraries can be injected in just
# tests or releases. These options are MERGED with the options in supplemental yaml files.
:libraries:
  :placement: :end
  :flag: "-l${1}"
  :path_flag: "-L ${1}"
  :system: []    # for example, you might list 'm' to grab the math library
  :test: []
  :release: []

:plugins:
  :load_paths:
    - "#{Ceedling.load_path}"
  :enabled:
    - stdout_pretty_tests_report
    - module_generator
    - gcov
...

I’m not sure I can give a line-by-line breakdown of what all that means, this was made over time as a collective effort until it worked.

The interesting part, probably, is the :paths:source: directive. This has to include all the directories that contain source code to be tested, and directories containing header files that can be mocked. Don’t include paths to source code that you don’t want to test.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật