Skip to content

test: new prototypical semi-automatic test.#215

Open
csanchezdll wants to merge 4 commits intocandle-usb:masterfrom
csanchezdll:add_test_script
Open

test: new prototypical semi-automatic test.#215
csanchezdll wants to merge 4 commits intocandle-usb:masterfrom
csanchezdll:add_test_script

Conversation

@csanchezdll
Copy link
Contributor

This is the test script I used to detect (and check the fix) of #207 and #211.

The README.md should explain everything. Having to build "instrumented" versions of the FW is somewhat clumsy, but is the best way I found of forcing the runtime conditions I wanted to test. Using a breakpoint with and returning inside GDB would be another option, but it is more intrusive in terms of runtime timing.

If you run this before #209, it will fail right away, as the device will HardFault (trying to receive into a NULL buffer). If you run if on a branch without #212 (but with #209, otherwise the more frequent one hides the least frequent one) it will pass, usually, but running in a loop makes it eventually fail (in my system, it takes 100-200 iterations).

No failures running this on main up to 2500 iterations.

Copy link
Collaborator

@fenugrec fenugrec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some clever bash work in there.
Have not tested, just skimmed; with a few comments.

test/README.md Outdated

The script on this directory performs a limited test for
device functionality. It is meant to be run with a device
under test (DUT) connected thought USB and JTAG, and
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JTAG/SWD probably ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any way your GDB server of choice can connect, really, but yes as these are STM devices openocd and JTAG/SWD is correct. Changing.

test/README.md Outdated

The test is sligtly intrusive, because it temporarily
suspends the FW capability of sending frames to the host
thorugh USB. This is done by building a special "test"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*through

test/README.md Outdated
* GDB server (openocd, most likely) running

2. Start by building the special test version of the
code
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

" (append _test_fw suffix to your usual target name) "

candump_dut=$tmpdir/candump_dut
candump_aux=$tmpdir/candump_aux

mkfifo $gdb_in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a corresponding close/delete for this fifo ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is created inside $tmpdir which is removed at the end of the script, so no need for explicit removal (same as any other file).
One problem of the script as it is is when it timeouts (which is actually a common failure mode, as the DUT HardFaults) it hangs and when interrupting it it leaves a lot of slate subprocess and $tmpdir is silently kept. I am updating the script so it includes a timeout, removes subprocesses, and chimes about keeping the $tmpdir for examination on failures.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw: you can use trap to automatically execute a bash function on a signal, i.e. exit of the script.

trap_exit_handler() {
    echo 'insert cleanup stuff here'
}

trap 'trap_exit_handler' 0 1 15

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I know, that is what I am doing. This script started as a quick & dirty thing to catch the bug, that is why the "failing" exit was not so taken care of.

test/test.sh Outdated
fi

sudo ip link set $interface_aux down
sudo ip link set $interface_aux type can bitrate 500000
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would running at 1M help to trigger the bug faster ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not. The bug about the double buffer triggers right away, regardless of speed. And the bug about an IRQ interrupting "prepare" depends on the timing between the IRQ and main loop... which is affected by timing in general but not necessarily that way.
No harm on raising it, 1Mbps being the highest standard CAN speed. Let me check the bug reproduces, just in case, and I'll update.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the interrupted "prepare" bug (#211) seems to happen slightly less frequently at 1Mbps. Just chance, IMHO, but I have kept 500kbps by default and added a -b switch to select any desired bitrate.

Comment on lines 839 to 848
#ifdef USBD_TEST
volatile int skip_send = 0;
#endif
void USBD_GS_CAN_SendToHost(USBD_HandleTypeDef *pdev)
{
#ifdef USBD_TEST
if (skip_send)
return;
#endif

Copy link
Collaborator

@marckleinebudde marckleinebudde Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#ifdef USBD_TEST
volatile int skip_send = 0;
#endif
void USBD_GS_CAN_SendToHost(USBD_HandleTypeDef *pdev)
{
#ifdef USBD_TEST
if (skip_send)
return;
#endif
volatile int skip_send;
void USBD_GS_CAN_SendToHost(USBD_HandleTypeDef *pdev)
{
if (IS_ENABLED(USBD_TEST) && skip_send)
return;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing. Just thinking... if we are making skip_test not being ifdef'ed away on non-test FWs, then why using USBD_TEST at all? We could just predicate the early return on skip_test alone, as it is never set by normal code, and this way we could avoid having a separate "test" version of the binaries.
I did not want to do it right away to avoid "polluting" the FW with test features. What do you prefer?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grrr - my comment was here 2 times, then I deleted 1. Now it's gone :/ - here we go again:

No need to init as 0, as it's a global variable.
With the IS_ENABLED() helper, we can get rid of the ifdef.
Usually I'd make it static, but not sure, if the debugger can still find it.

Copy link
Collaborator

@marckleinebudde marckleinebudde Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing. Just thinking... if we are making skip_test not being ifdef'ed away on non-test FWs, then why using USBD_TEST at all?

If it's not ifdef'ed, the compiler will always compile the code, but the optimizer would remove it for the normal firmware. This has the benefit, that the syntax is always checked, even if the code is not in the resulting binary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure static does not affect visibility in GDB, but I am checking. About init, you are totally right. I'll use IS_ENABLED()... or should we just remove USBD_TEST altogether and avoid splitting the FW binaries?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with the extra binary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if the optimizer removing skip_test holds for volatile vars... but I do not think it is a big deal even if it is kept, and I agree with runtime checks being better than conditional compilation for syntax checking.

Copy link
Collaborator

@marckleinebudde marckleinebudde Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

candleLight_fw: mainline:

Memory region         Used Size  Region Size  %age Used
           FLASH:       17716 B       128 KB     13.52%
             RAM:        4512 B        16 KB     27.54%
create and sign dfu bin file: candleLight_fw
   text    data     bss     dec     hex filename
  17696      84    4448   22228    56d4 candleLight_fw

candleLight_fw: your branch + ifdef replaced by IS_ENABLED():

Memory region         Used Size  Region Size  %age Used
           FLASH:       17716 B       128 KB     13.52%
             RAM:        4516 B        16 KB     27.56%
create and sign dfu bin file: candleLight_fw
   text    data     bss     dec     hex filename
  17696      84    4452   22232    56d8 candleLight_fw

Text stays the same, but BSS grows.

You're right the variable is still in the BSS, but the code in USBD_GS_CAN_SendToHost() has been optimized out.

candleLight_test_fw: your branch + ifdef replaced by IS_ENABLED():

Memory region         Used Size  Region Size  %age Used
           FLASH:       17748 B       128 KB     13.54%
             RAM:        4516 B        16 KB     27.56%
create and sign dfu bin file: candleLight_test_fw
   text    data     bss     dec     hex filename
  17728      84    4452   22264    56f8 candleLight_test_fw

@csanchezdll
Copy link
Contributor Author

@marckleinebudde I think I addresses all your comments. I added separate commits for clarity, I can squash them before merging if you prefer a shorter git history.

then
printf "Keeping temporary directory in %s\n" $tmpdir
else
rm -rf $tmpdit
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tmpdir

@fenugrec
Copy link
Collaborator

In light of recent issues, maybe adding a few tests with cangen + cansequence would make sense ? if not in this script, maybe some other not too far.

@csanchezdll
Copy link
Contributor Author

I can add it :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments