STM32F407VG Discovery - Unit test output not showing

Hello again!

I am progressing through my journey with STM32 using HAL, Platformio and C++ and I have stumbled on yet another problem.

When running Test project task I am either not able to see any printed results or I am stuck with an upload error, depending on setting a test_port or not. In platformio.ini you can see what I am talking about.

I am following STM32Cube HAL and Nucleo-F401RE: debugging and unit testing — PlatformIO latest documentation but with different dev board (STM32F407VG Discovery). Both boards have the same serial port connected to a ST-Link.

I have put some LEDs inside the code to see if it is running, and first three of them work perfectly, but the last one is never lit.

Is there any obvious mistake I am doing?

Test task output

> Executing task in folder stm32-synth: platformio test --environment disco_f407vg <

Verbose mode can be enabled via `-v, --verbose` option
Collected 1 items

Processing * in disco_f407vg environment
--------------------------------------------------------------------------------------
Building...
Uploading...
xPack OpenOCD, x86_64 Open On-Chip Debugger 0.10.0+dev-00378-ge5be992df (2020-06-26-09:27)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

srst_only separate srst_nogate srst_open_drain connect_deassert_srst

target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08002ea4 msp: 0x20020000
** 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)

main.cpp

#include "stm32f4xx_hal.h"

#include <unity.h>

void setUp(void) {}

void tearDown(void) {}

void test_sanityTestTrue(void) { TEST_ASSERT_EQUAL(true, true); }

void test_sanityTestFalse(void) { TEST_ASSERT_EQUAL(false, false); }

int main() {
  HAL_Init(); // initialize the HAL library

  HAL_Delay(2000); // service delay

  UNITY_BEGIN();

  RUN_TEST(test_sanityTestTrue);
  RUN_TEST(test_sanityTestFalse);

  UNITY_END(); // stop unit testing

  while (1) {
  }
}

void SysTick_Handler(void) { HAL_IncTick(); }

unittest_transport.h

#ifndef UNITEST_TRANSPORT_H
#define UNITEST_TRANSPORT_H

#ifdef __cplusplus
extern "C" {
#endif

void unittest_uart_begin();
void unittest_uart_putchar(char c);
void unittest_uart_flush();
void unittest_uart_end();

#ifdef __cplusplus
}
#endif

#endif // UNITEST_TRANSPORT_H

unittest_transport.c

#include "unittest_transport.h"
#include "stm32f4xx_hal.h"

#include "STM32HAL_BoardConfig.hpp"
#include "STM32HAL_Defines.hpp"

#define USARTx USART2
#define USARTx_CLK_ENABLE() __HAL_RCC_USART2_CLK_ENABLE()
#define USARTx_CLK_DISABLE() __HAL_RCC_USART2_CLK_DISABLE()
#define USARTx_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define USARTx_RX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()
#define USARTx_TX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()

#define USARTx_FORCE_RESET() __HAL_RCC_USART2_FORCE_RESET()
#define USARTx_RELEASE_RESET() __HAL_RCC_USART2_RELEASE_RESET()

#define USARTx_TX_PIN GPIO_PIN_2
#define USARTx_TX_GPIO_PORT GPIOA
#define USARTx_TX_AF GPIO_AF7_USART2
#define USARTx_RX_PIN GPIO_PIN_3
#define USARTx_RX_GPIO_PORT GPIOA
#define USARTx_RX_AF GPIO_AF7_USART2

static UART_HandleTypeDef UartHandle;

void unittest_uart_begin() {
  GPIO_InitTypeDef GPIO_InitStruct;

  USARTx_TX_GPIO_CLK_ENABLE();
  USARTx_RX_GPIO_CLK_ENABLE();

  USARTx_CLK_ENABLE();

  GPIO_InitStruct.Pin = USARTx_TX_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
  GPIO_InitStruct.Alternate = USARTx_TX_AF;

  HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = USARTx_RX_PIN;
  GPIO_InitStruct.Alternate = USARTx_RX_AF;

  HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
  UartHandle.Instance = USARTx;

  UartHandle.Init.BaudRate = 115200;
  UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
  UartHandle.Init.StopBits = UART_STOPBITS_1;
  UartHandle.Init.Parity = UART_PARITY_NONE;
  UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  UartHandle.Init.Mode = UART_MODE_TX_RX;
  UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

  MX_GPIO_Init(); // that's why we needed to #include "STM32HAL_BoardConfig.hpp"

  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_SET);

  if (HAL_UART_Init(&UartHandle) != HAL_OK) {
    while (1) {
      unittest_uart_putchar(0x63);
    }
  }
}

void unittest_uart_putchar(char c) {
  HAL_UART_Transmit(&UartHandle, (uint8_t *)(&c), 1, 1000);
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
}

void unittest_uart_flush() {
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
}

void unittest_uart_end() {
  USARTx_CLK_DISABLE();
  USARTx_RX_GPIO_CLK_DISABLE();
  USARTx_TX_GPIO_CLK_DISABLE();
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
}

platformio.ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter, extra scripting
;   Upload options: custom port, speed and extra flags
;   Library options: dependencies, extra library storages
;
; Please visit documentation for the other options and examples
; http://docs.platformio.org/page/projectconf.html


[env:disco_f407vg]
platform = ststm32
board = disco_f407vg
framework = stm32cube

test_transport = custom
; test_port = /dev/stlinkv2_3 // wrong ioctl
; test_port = /dev/ttyACM0 // wrong ioctl
build_flags = -DF4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -u_printf_float
extra_scripts = config_script.py
test_speed = 115200

config_script.py

Import("env")


env.Append(CCFLAGS=[
    "-mfloat-abi=hard",
    "-mfpu=fpv4-sp-d16",
    "-u_printf_float"
])

env.Append(LINKFLAGS=[
    "-mfloat-abi=hard",
    "-mfpu=fpv4-sp-d16",
    "-u_printf_float"
])

print("Extra float config done!")

# def after_upload(source, target, env):
#     print ("Delay while uploading...")
#     import time
#     time.sleep(15)
#     print ("Done!")

# env.AddPostAction("upload", after_upload)

Please open a CLI and execute

pio test --without-testing

this will just build & flash the test firmware on the device.

Then, open a serial monitor, e.g. miniterm.py /dev/ttyACM0 115200 or hterm on the USB-serial adapter at 115200 baud and press the reset button on the board. Does any output appear, at all?

Thanks for the answer.

I am not able to locate any new tty device when running this code. /dev/ttyACM0 in platformio.ini was taken from me using USB_CDC class (another output source if you will, another IC on the dev board that requires a lot of code that I am not happy to be dependent on in unit tests).

Platformio serial monitor tries to connect with /dev/ttyS0 but connecting with this device using tio serial monitor from terminal results in no output at all. LEDs are still working though so the program is running.

Your simple test got me thinking. I was entirely sure that ST-Link is 100% connected to USART pins, but after reading the dev-board manual I now know that it’s completely opposite.

I will check that.

There isn’t supposed to be a new device showing up after uploading this as the firmware itself doesn’t create a new USB-serial device. As soon as you plug the Discovery board in, the on-board ST-Link provides the USB-UART interface (as one USB endpoint, the St-link flasher interface as another one). You can check that with sudo dmesg -w on the commandline, unplugging and replugging the Discovery board. There must be messages there regarding Linux registering a new TTY device, most likely /dev/ttyACM0. If that is not happening, something is wrong with the hardware or the ST-Link firmware (which can also be updated via ST tools).

I have done exactly that (dmesg -wH). There was nothing about registering new tty device.

I was able to get the test results with an external USB-UART converter.

dmesg results:

[maj31 21:09] usb 3-1.3: new full-speed USB device number 38 using xhci_hcd
[  +0,101330] usb 3-1.3: New USB device found, idVendor=0483, idProduct=3748, bcdDevice= 1.00
[  +0,000004] usb 3-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0,000003] usb 3-1.3: Product: STM32 STLink
[  +0,000002] usb 3-1.3: Manufacturer: STMicroelectronics
[  +0,000002] usb 3-1.3: SerialNumber: Pÿu\x06IwSUAY	\xc2\x87
[  +5,122678] usb 3-1.2: new full-speed USB device number 39 using xhci_hcd
[  +0,106398] usb 3-1.2: New USB device found, idVendor=0403, idProduct=6001, bcdDevice= 6.00
[  +0,000004] usb 3-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0,000003] usb 3-1.2: Product: FT232R USB UART
[  +0,000002] usb 3-1.2: Manufacturer: FTDI
[  +0,000002] usb 3-1.2: SerialNumber: AL01814Y
[  +0,008964] ftdi_sio 3-1.2:1.0: FTDI USB Serial Device converter detected
[  +0,000025] usb 3-1.2: Detected FT232RL
[  +0,000625] usb 3-1.2: FTDI USB Serial Device converter now attached to ttyUSB0

Hm interesting but it does see the STLink device / flasher. Just no virtual COM port (VCP).

I’d suggest you download STSW-LINK007 - ST-LINK, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 boards firmware upgrade - STMicroelectronics and execute that Java firmware upgrade program (sudo java -jar <file from archive>), it should allow you to select the version with “+ VCP”. I think otherwise it’s pretty uncomfortable to not have the onboard USB-UART working on a nice discovery board, which is supposed to be an all-in-one.

1 Like

Thank you very much, I’ll do that. As for now, we can consider this thread closed. :slight_smile: After all, I am able to get the tests results!