Enable STM32 Arduino CDC in a unit test?

My stm32 board uses the USB interface of the MCU to implement a serial over USB connection to the host, and with the -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC, -D USBCON, build flags I indeed see a com port on my PC and the program output (good).

However, when I try to run a unit test, the loaded binary doesn’t include the serial over USB functionality, I don’t see a com port on my PC, and platformio can’t get the results from the tested device.

Is there a way to cause the unit test binary to include also the serial over USB functionality?

platformio.ini

[env:stm32]
build_type = debug
debug_init_break = tbreak setup
platform = ststm32
board = genericSTM32F401CD
framework = arduino
debug_tool = stlink
upload_protocol = stlink
debug_build_flags = -O0 -ggdb3 -g3
build_flags =
  -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
  -D USBCON
  -Werror
  -fmax-errors=3
  -D SERIAL_TX_BUFFER_SIZE=4096
  -D SERIAL_RX_BUFFER_SIZE=4096

Unit test (empty)

#include <unity.h>

void setUp(void) {
    // set stuff up here
}

void tearDown(void) {
    // clean stuff up here
}

int main( int argc, char **argv) {
    UNITY_BEGIN();
    UNITY_END();
}

Test log:

 *  Executing task: C:\Users\user\.platformio\penv\Scripts\platformio.exe run --target upload 
Processing stm32 (platform: ststm32; board: genericSTM32F401CD; framework: arduino)
--------------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/ststm32/genericSTM32F401CD.html
PLATFORM: ST STM32 (15.6.0) > STM32F401CD (96k RAM. 384k Flash)
HARDWARE: STM32F401CDU6 84MHz, 96KB RAM, 384KB Flash
DEBUG: Current (stlink) External (blackmagic, jlink, stlink)   
PACKAGES:
 - framework-arduinoststm32 @ 4.20400.0 (2.4.0)
 - framework-cmsis @ 2.50700.210515 (5.7.0)
 - tool-dfuutil @ 1.11.0
 - tool-openocd @ 2.1100.211028 (11.0)
 - tool-stm32duino @ 1.0.2
 - toolchain-gccarmnoneeabi @ 1.90201.191206 (9.2.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 13 compatible libraries
Scanning dependencies...
No dependencies
Building in debug mode
Compiling .pio\build\stm32\src\main.cpp.o
Compiling .pio\build\stm32\src\packet_encoder.cpp.o
Linking .pio\build\stm32\firmware.elf
Checking size .pio\build\stm32\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=         ]  14.0% (used 13800 bytes from 98304 bytes)
Flash: [=         ]  14.8% (used 58204 bytes from 393216 bytes)
Configuring upload protocol...
AVAILABLE: blackmagic, dfu, jlink, serial, stlink
CURRENT: upload_protocol = stlink
Uploading .pio\build\stm32\firmware.elf
xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:19)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0800606c msp: 0x20018000
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked
================================================================ [SUCCESS] Took 14.40 seconds ================================================================ *  Terminal will be reused by tasks, press any key to close it. 

Will call into Serial.end() with the default unity_config.cpp

so that probably immediately closes the serial port again.

If you run the test cases and PlatformIO can connect to it it probably doesn’t hurt though.

Thanks @maxgerhardt. I tried to add an infinite loop to keep the com port alive and realized that nothing works. This blinking code works on my regular program but nothing in the test program. I run the test program with platformio/advanced/Verbose-Test, and it does compile my test program (e.g. it detects an intentional syntax error), and the uploading seems fine, but no blinking and no com port.

Any suggestion?

platformio.ini

[env:stm32]
build_type = debug
debug_test = *
test_build_src = true
debug_init_break = tbreak setup
platform = ststm32
board = genericSTM32F401CD
framework = arduino
debug_tool = stlink
upload_protocol = stlink
debug_build_flags = -O0 -ggdb3 -g3
build_flags =
  -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
	-D USBCON
  -Werror
  -fmax-errors=3
  -D SERIAL_TX_BUFFER_SIZE=4096
  -D SERIAL_RX_BUFFER_SIZE=4096

test/test_example.cpp:

#include <Arduino.h>
#include <unity.h>

void setUp(void) {
  // set stuff up here
}

void tearDown(void) {
  // clean stuff up here
}

#define LED PC13

int main(int argc, char **argv) {
  UNITY_BEGIN();

  // Serial.begin(115200);
  pinMode(LED, OUTPUT);

  for (;;) {
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
  }

  UNITY_END();
}

Log of verbose test, after a clean all: (side question, why the long doesn’t contain a verbose log of the build?)

 *  Executing task: C:\Users\user\.platformio\penv\Scripts\platformio.exe test --verbose --environment stm32 

Collected 1 tests (*)

Processing * in stm32 environment
-----------------------------------------------------------------------------------------------------------------------------------------------------------

Building & Uploading...
Library Manager: Installing throwtheswitch/Unity @ ^2.5.2
Unpacking  [####################################]  100%
Library Manager: Unity@2.5.2 has been installed!
xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:19)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08007d28 msp: 0x20018000
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **  
shutdown command invoked

Testing...
If you don't see any output for the first 10 secs, please reset board (press reset button)

TimeoutError: Could not automatically find serial port based on the known UART bridges
Please specify `test_port` for environment or use global `--test-port` option.
---------------------------------------------------------- stm32:* [ERRORED] Took 43.29 seconds ---------------------------------------------------------- 

========================================================================= SUMMARY =========================================================================Environment    Test    Status    Duration
-------------  ------  --------  ------------
stm32          *       ERRORED   00:00:43.293
======================================================== 1 test cases: 0 succeeded in 00:00:43.293 ========================================================
 *  The terminal process "C:\Users\user\.platformio\penv\Scripts\platformio.exe 'test', '--verbose', '--environment', 'stm32'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

Oh, you’re overwriting the main() function in an Arduino based on-target unit test? That’s not good, you still have to adhere to setup() and loop() like in the example.

Thanks @maxgerhardt , this is very useful. I copied the test blindly from here Unit Testing with PlatformIO: Part 1. The Basics | PlatformIO Labs.

With the new test, It passes -when I click on alien-icon/Advanced/Verbose-test but not when I click on the hourglass icon at the bottom of the screen. What is the difference between the two? Can I make the hourglass to work as well?

platformio.ini

[env:stm32]
build_type = debug
; debug_test = *
; test_build_src = true
debug_init_break = tbreak setup
platform = ststm32
board = genericSTM32F401CD
framework = arduino
debug_tool = stlink
upload_protocol = stlink
debug_build_flags = -O0 -ggdb3 -g3
build_flags =
  -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
	-D USBCON
  -Werror
  -fmax-errors=3
  -D CONFIG_MAX_PACKET_DATA_LEN=100
  -D CONFIG_MAX_PENDING_COMMANDS=5
  -D SERIAL_TX_BUFFER_SIZE=4096
  -D SERIAL_RX_BUFFER_SIZE=4096

test/test_example.cpp (3 ok tests, one should fail):


#include <Arduino.h>
#include <unity.h>

#define LED PC13

void setUp(void) {
  // set stuff up here
}

void tearDown(void) {
  // clean stuff up here
}

void test_calculator_addition(void) {
  // TEST_ASSERT_EQUAL(32, calc.add(25, 7));
}

void test_calculator_subtraction(void) {
  // TEST_ASSERT_EQUAL(20, calc.sub(23, 3));
}

void test_calculator_multiplication(void) {
  // TEST_ASSERT_EQUAL(50, calc.mul(25, 2));
     TEST_ASSERT_EQUAL(1, 2);

}

void test_calculator_division(void) {
  // TEST_ASSERT_EQUAL(32, calc.div(100, 3));
}

void setup() {
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);

  // NOTE!!! Wait for >2 secs
  // if board doesn't support software reset via Serial.DTR/RTS
  delay(2000);

  UNITY_BEGIN();
  RUN_TEST(test_calculator_addition);
  RUN_TEST(test_calculator_subtraction);
  RUN_TEST(test_calculator_multiplication);
  RUN_TEST(test_calculator_division);
  UNITY_END();
}

void loop() {
  digitalWrite(LED, HIGH);
  delay(100);
  digitalWrite(LED, LOW);
  delay(500);
}

Log with alien/Advanced/Verbose-test (good):

  *  Executing task: C:\Users\user\.platformio\penv\Scripts\platformio.exe test --verbose --environment stm32 

Collected 1 tests (*)

Processing * in stm32 environment
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Building & Uploading...
xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:19)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08007364 msp: 0x20018000
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **  
shutdown command invoked

Testing...
If you don't see any output for the first 10 secs, please reset board (press reset button)

test\test_example.cpp:42:test_calculator_addition:PASS
test\test_example.cpp:43:test_calculator_subtraction:PASS
test\test_example.cpp:25:test_calculator_multiplication:FAIL: Expected 1 Was 2
test\test_example.cpp:45:test_calculator_division:PASS

-----------------------
4 Tests 1 Failures 0 Ignored
FAIL

------------------------------------------------------------------ stm32:* [FAILED] Took 12.63 seconds ------------------------------------------------------------------
================================================================================ SUMMARY ================================================================================Environment    Test    Status    Duration
-------------  ------  --------  ------------
stm32          *       FAILED    00:00:12.629

________________________________________________________________________________ stm32:* ________________________________________________________________________________test\test_example.cpp:25:test_calculator_multiplication:FAIL: Expected 1 Was 2

========================================================== 4 test cases: 1 failed, 3 succeeded in 00:00:12.629 ==========================================================
 *  The terminal process "C:\Users\user\.platformio\penv\Scripts\platformio.exe 'test', '--verbose', '--environment', 'stm32'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

Log when clicking on the hourglass icon at the bottom (bad, it does changes however the blinking rate if I change the duration so the program is uploaded):

*  Executing task: C:\Users\user\.platformio\penv\Scripts\platformio.exe test --upload-port COM3 --test-port COM3 

Verbosity level can be increased via `-v, -vv, or -vvv` option
Collected 1 tests

Processing * in stm32 environment
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------Building & Uploading...
xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:19)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08007368 msp: 0x20018000
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **  
shutdown command invoked
Testing...
If you don't see any output for the first 10 secs, please reset board (press reset button)

could not open port 'COM3': FileNotFoundError(2, 'The system cannot find the file specified.', None, 2)
------------------------------------------------------------------ stm32:* [PASSED] Took 8.56 seconds ------------------------------------------------------------------ 

=============================================================== 0 test cases: 0 succeeded in 00:00:08.565 =============================================================== *  Terminal will be reused by tasks, press any key to close it. 

So this invocation works

While this one doesn’t. Do you have COM3 hardcoded somewhere in the platformio.ini?

Not in platformio.ini but in the status bar. I changed it to auto and it works now. Thanks @maxgerhardt!

The unit testing is very useful. For now I use for simple libraries but will try also actual communication using a loopback. Will see how it will got.

image

@maxgerhardt, last quick question, the Verbose Test function doesn’t print any of the build log (as I would expect), just ‘hangs’ while the build is done in the background. Does it worth filing a feature request or is it working as intended?

  *  Executing task: C:\Users\user\.platformio\penv\Scripts\platformio.exe test --verbose --environment stm32 

Collected 1 tests (*)

Processing * in stm32 environment
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Building & Uploading...
xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:19)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08007364 msp: 0x20018000
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **  
shutdown command invoked

Testing...
If you don't see any output for the first 10 secs, please reset board (press reset button)

test\test_example.cpp:42:test_calculator_addition:PASS
test\test_example.cpp:43:test_calculator_subtraction:PASS
test\test_example.cpp:25:test_calculator_multiplication:FAIL: Expected 1 Was 2
test\test_example.cpp:45:test_calculator_division:PASS

-----------------------
4 Tests 1 Failures 0 Ignored
FAIL

------------------------------------------------------------------ stm32:* [FAILED] Took 12.63 seconds ------------------------------------------------------------------
================================================================================ SUMMARY ================================================================================Environment    Test    Status    Duration
-------------  ------  --------  ------------
stm32          *       FAILED    00:00:12.629

________________________________________________________________________________ stm32:* ________________________________________________________________________________test\test_example.cpp:25:test_calculator_multiplication:FAIL: Expected 1 Was 2

========================================================== 4 test cases: 1 failed, 3 succeeded in 00:00:12.629 ==========================================================
 *  The terminal process "C:\Users\user\.platformio\penv\Scripts\platformio.exe 'test', '--verbose', '--environment', 'stm32'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

I think that’s a concious design decision because pio test -v does show the build log and pio test -vvv shows every compiler invocation. pio test shows none of it, very compact and silent.

With ‘pio test -v’ I don’t get build log, just ‘Building & Uploading…’ and then silent for 10-20 seconds until it starts to upload. Is this the intended behavior?

PS C:\Users\user\projects\serial_packets_arduino\repo\platformio> pio test -v
Collected 2 tests (test_packet_crc, test_packet_data)

Processing test_packet_crc in stm32 environment
----------------------------------------------------------------------------------------------------------------------------------------------------------

Building & Uploading...
xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:19)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08007418 msp: 0x20018000
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **  
shutdown command invoked

Testing...
If you don't see any output for the first 10 secs, please reset board (press reset button)

test\test_packet_crc\test_packet_crc.cpp:43:test_empty_data:PASS
test\test_packet_crc\test_packet_crc.cpp:44:test_data1:PASS
test\test_packet_crc\test_packet_crc.cpp:45:test_data2:PASS

-----------------------
3 Tests 0 Failures 0 Ignored

--------------------------------------------------- stm32:test_packet_crc [PASSED] Took 40.21 seconds ---------------------------------------------------

Processing test_packet_data in stm32 environment
----------------------------------------------------------------------------------------------------------------------------------------------------------
Building & Uploading...
xPack OpenOCD x86_64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:19)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08007418 msp: 0x20018000
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked

Testing...
If you don't see any output for the first 10 secs, please reset board (press reset button)

test\test_packet_data\test_packet_data.cpp:54:test_constructor:PASS
test\test_packet_data\test_packet_data.cpp:55:test_write_uint8:PASS

-----------------------
2 Tests 0 Failures 0 Ignored
OK

--------------------------------------------------- stm32:test_packet_data [PASSED] Took 14.10 seconds ---------------------------------------------------
======================================================================== SUMMARY ======================================================================== 
Environment    Test              Status    Duration
-------------  ----------------  --------  ------------
stm32          test_packet_crc   PASSED    00:00:40.206
stm32          test_packet_data  PASSED    00:00:14.101
======================================================= 5 test cases: 5 succeeded in 00:00:54.307 ======================================================= 
PS C:\Users\user\projects\serial_packets_arduino\repo\platformio>