PIO test doesn't run properly when upload using serial port

Hi ,
I was doing a test scrip using the PIO test for our device testing .I’m still a newbie using pio test …I use the following test scrip to use as a pilot scrip for PIO test .

#include <Arduino.h>
#include <unity.h>
void do_test() {
    TEST_ASSERT_EQUAL_INT(1, 1);
    }

void setup()
{

    UNITY_BEGIN();
    RUN_TEST(do_test);
   UNITY_END();
}
void loop() {

    delay(500);
}

initially i used mbed method which I define .ini as follows ,

[env:nucleo_f429zi]
platform = ststm32
board = nucleo_f429zi
framework = arduino
upload_protocol = mbed
upload_port = E:
test_port = COM12
monitor_port = COM12

which i used on board STLINK and the drive letter ,and the virtual COM port as test port and monitor port. The test output was successful.

Since our end product doesn’t have the STLINK and we are planning to use serial boot loader i re define the .ini as follows

[env:nucleo_f429zi]
platform = ststm32
board = nucleo_f429zi
framework = arduino
upload_protocol = serial
upload_port = COM8
test_port = COM8
monitor_port = COM8

Where the COM8 is a USB to UART adaptor attached to serial boot loader .

When I run the same test scrip it build and upload the scrip to the board ,but it stuck there after with the below message shown in the picture .

even when I press the reset button nothing happening.
Not sure if I’m missing something .appreciate if someone car help .

Thanks,
Samson.

So, if you are flashing the device via its serial bootloader, you must have put the BOOT0 pin jumper in the position that boots the device into bootloader mode on reset.

Do you remove that jumper again after it’s uploaded and before you reset the board?

After you execute pio test and the test firmware is supposed to be on the board, can you open a serial monitor program (like hterm) and press reset and see if there’s any output?

Hi Max ,

I test the serial bootloader before by running another script where i use a println msg to display on the serial monitor .Once flashed it will automatically resets and show the msg on the serial monitor .It was successful.

As you can see previously when I ran the same script ( the scipt that i used for pio test) on mbed it ran the test and shows passed .But when I use serial method it doesn’t .

Thanks ,
Samson.

Well if you upload and test via the STLink, the STLink is connecting to a different USART peripheral and pins than the serial bootloader though?

I’ve tested the following in my Nucleo F103RB.

First, the Serial object writes to PA2/3 (USART2), which is connected to the STLink (COM12)
The serial bootloader, to which a USB-UART converter (COM3) is connected, is on PA9/PA10 for USART1 since that’s where the bootloader is listening for my chip (source).

So, I configure my platformio.ini for serial upload on COM3, and further enable the Arduino core to enable the hardware 1 object for USART1 access.

[env:nucleo_f103rb]
platform = ststm32
board = nucleo_f103rb
upload_protocol = serial
framework = arduino
test_transport = custom
test_port = COM3
build_flags = 
    -D HAVE_HWSERIAL1

I then copy your test\cool_test\test.cpp into the same path into my project, but add a delay(2000); in setup(). Since both the serial bootloader and the test interface will be using the same serial, I need to make sure that enough time passes after the serial upload program is finished and control of the serial object is given back to PlatformIO to read the output. The firmware shouldn’t execute so fast that it sends the data to the serial uploader program, which swallows it.

Additionally, according to docs, I need to implement my own test transfer layer, since the unit test use Serial (=Serial2) by default in the Arduino framework, but my USB-UART converter sits on Serial1, thus the testing serial wouldn’t get any output. Thus I add the file test\unittest_transport.h and fill it with

#ifndef UNITTEST_TRANSPORT_H
#define UNITTEST_TRANSPORT_H

#include <Arduino.h>

#define TESTING_SERIAL Serial1

void unittest_uart_begin() {
    TESTING_SERIAL.begin(115200); /* default test_speed value */
    TESTING_SERIAL.setRx(PA10);
    TESTING_SERIAL.setTx(PA9);
}

void unittest_uart_putchar(char c) {
    TESTING_SERIAL.print(c);
}

void unittest_uart_flush() {
    TESTING_SERIAL.flush();
}

void unittest_uart_end() {

}

#endif

I then start the “Test” project task and…

After the firmware is uploaded via the serial bootloader, without me needing to press reset or anything, it just works.

Note that the USART peripherals and pins may be different for your setup.

Hi Max,

Thank you so much for your time on this .I tried the method you explain before ,the UART pins are i’m using for the bootloader is PB10 (TX)/PB11(RX) which correspond to serial3. Then I define the .ini as follows ,

[env:nucleo_f429zi]
platform = ststm32
board = nucleo_f429zi
framework = arduino
upload_protocol = serial
    -D HAVE_HWSERIAL3

create the header file as follows ,

#ifndef UNITTEST_TRANSPORT_H
#define UNITTEST_TRANSPORT_H
#include <Arduino.h>
#define TESTING_SERIAL Serial3

void unittest_uart_begin() {
    TESTING_SERIAL.begin(115200); /* default test_speed value */
    TESTING_SERIAL.setRx(PB11);
    TESTING_SERIAL.setTx(PB10);
 }

void unittest_uart_putchar(char c) {
    TESTING_SERIAL.print(c);
}

void unittest_uart_flush() {
    TESTING_SERIAL.flush();
}

void unittest_uart_end() {

}
#endif

put the header file in to the test folder , ran the test.cpp still it wasn’t successful .Not sure why may be I should re- try .

Thanks again !
Samson.

Thish cannot be correct, is missing build_flags = as a previous line.

Have you verified that if you write a normal firmware that uses Serial3, you do see output on the COM port that is connected to the bootloader, and which is also supposed to capture the unit testing output later?

Hi Max ,

you’re right i forgot to add build_flags here, but i did add to .ini.I used a basic serial monitor script and flash to see if the serial bootloader is working .

#include <Arduino.h>

HardwareSerial Serial1(USART1);

void setup() {

    Serial1.setRx(PB11); // using pin name PY_n
   Serial1.setTx(PB10);
   Serial1.begin(9600);
}

void loop() {

  Serial1.println("Hello");
  delay(5000);
 }

.ini define as ,
[env:nucleo_f429zi]
platform = ststm32
board = nucleo_f429zi
framework = arduino
upload_protocol = serial
upload_port = COM8

The program uploaded and print it in the command line .

I ran the test code changing the Serial3 to serial1 and still no output .

.ini is ,
[env:nucleo_f429zi]
platform = ststm32
board = nucleo_f429zi
framework = arduino
upload_protocol = serial
upload_port =COM8
test_transport = custom
test_port = COM8
build_flags =
-D HAVE_HWSERIAL1

transport header file;

#ifndef UNITTEST_TRANSPORT_H
#define UNITTEST_TRANSPORT_H
#include <Arduino.h>
#define TESTING_SERIAL Serial1

void unittest_uart_begin() {

    TESTING_SERIAL.begin(115200); /* default test_speed value */
    TESTING_SERIAL.setRx(PB11);
    TESTING_SERIAL.setTx(PB10);
    }

    void unittest_uart_putchar(char c) {

       TESTING_SERIAL.print(c);
  }

void unittest_uart_flush() {

    TESTING_SERIAL.flush();
}

void unittest_uart_end() {

}
#endif

test code,

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

void do_test() {

    TEST_ASSERT_EQUAL_INT(1, 1);
    }

void setup()
{

     delay(2000);
    UNITY_BEGIN();
    RUN_TEST(do_test);
    UNITY_END();
}

void loop() {
    delay(500);
}

One thing I did was when I remove the the upload_port = COM8 ( as per your example) on .ini it gives an error ,

I believe since I have multiple COM ports available I have to specify in the .ini

Thanks,
samson.

Hi Max ,

Finally i manage to get it work with the following settings,
change the unittest_transport.h as follows ,

#ifndef UNITTEST_TRANSPORT_H
#define UNITTEST_TRANSPORT_H
#include <Arduino.h>
#define TESTING_SERIAL Serial1

HardwareSerial Serial1(USART3);

void unittest_uart_begin() {
     /* default test_speed value */
    TESTING_SERIAL.setRx(PB11);
    TESTING_SERIAL.setTx(PB10);
    TESTING_SERIAL.begin(115200);
}

void unittest_uart_putchar(char c) {
       TESTING_SERIAL.print(c);

        }

void unittest_uart_flush() {

        TESTING_SERIAL.flush();
    }

void unittest_uart_end() {

}

   #endif

.ini config,

[env:nucleo_f429zi]
platform = ststm32
board = nucleo_f429zi
framework = arduino
upload_protocol = serial
upload_port= COM5
test_port = COM5
test_transport = custom

Here in your example there is no upload_ port define. But in my case since I have multiple COM port,so that I have to define the upload_port (if not gives an error "Failed to init device ") which leads to another issue where as I need to use the PIO CLI in the future to upload the test script and run on multiple devices sequentially .
The issue is in PIO CLI if I use : pio test --test-port COM5 it gives an error since it doesn’t know which port to upload .So if i type pio test --upload-port COM5 ,it upload the test scrip to the device and doesn’t show any output (That is obvious since i haven’t define test-port COM5.
So I think i cannot use both arguments ( test_port and upload_port )at once with pio test.

Is there another method i can use the arguments test-port and upload-port both on CLI or is there any special command for that ?

Thank you,
Samson.

Just append both arguments. pio test --upload-port X --test-port Y.

>pio test --help
Usage: pio test [OPTIONS]

Options:
  -e, --environment <environment>
  -f, --filter <pattern>          Filter tests by a pattern
  -i, --ignore <pattern>          Ignore tests by a pattern
  --upload-port TEXT
  --test-port TEXT
  -d, --project-dir DIRECTORY
  -c, --project-conf FILE
  --without-building
  --without-uploading
  --without-testing
  --no-reset
  --monitor-rts INTEGER RANGE     Set initial RTS line state for Serial
                                  Monitor

  --monitor-dtr INTEGER RANGE     Set initial DTR line state for Serial
                                  Monitor

  -v, --verbose
  -h, --help                      Show this message and exit.

But if you’ve set both of these options in the platformio.ini then they should be respected if just running pio test. That is not the case?

Hi Max ,

Yes it does work thank you ! .The reason why I want to use cli instead of define in .ini is to use a script to flash multiple devices ( I think it will be inconvenient to use the .ini to define the upload_port and test_port for each an every device )

Thanks again !
Samson.

1 Like