1# README Codec2 STM32 Unit Test
2Don Reid 2018/2019
3
4This is the unittest system for the stm32 implementation of
5codec2/FreeDV which runs on Linux systems. It requires a STM32F4xx
6processor development board connected to/having a ST-LINK, e.g. a
7STM32F4 Discovery board.
8
9## Quickstart
10
11Requirements:
12* python3/numpy
13* arm-none-eabi-gdb install and in your path (see codec2/stm32/README.md)
14* STM32F4xx_DSP_StdPeriph_Lib_V1.8.0 (see codec2/stm32/README.md)
15* build openocd from source and have it in your path (see below)
16
17Build codec2 for x86 Linux and run the ctests.  This generates several artifacts required for the stm32 tests:
18
19```
20$ cd ~/codec2
21$ mkdir build_linux && cd build_linux && cmake .. && make && ctest
22```
23
24Now build for the stm32, and run the stm32 ctests:
25```
26$ cd ~/codec2/stm32 && mkdir build_stm32 && cd build_stm32
27$ cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/STM32_Toolchain.cmake -DPERIPHLIBDIR=~/Downloads/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0 ..
28$ make
29$ sudo apt install python3-numpy libncurses5
30$ ctest -V
31```
32
33You should see tests executing (and passing). They are slow to execute
34(30 to 180 seconds each), due to the speed of the semihosting system.
35
36## If a Test fails
37
38Explore the files in ```codec2/stm32/unittest/test_run/name_of_test```
39
40When each test runs, a directory is created, and several log files generated.
41
42## Running the stm32 Unit Tests
43
441. Tests can be run using the ctest utility (part of cmake)
45   ```
46   $ cd ~/codec2/stm32/build_stm32
47   $ ctest
48   ```
49   You can pass -V to see more output:
50   ```
51   $ ctest -V
52   ```
53   You can pass -R <pattern> to run test matching <pattern>. Please note,
54   that some test have dependencies and will have to run other tests before
55   being executed
56   ```
57   $ ctest -R ofdm
58   ```
59   To list the available ctests:
60   ```
61   $ ctest -N
62   ```
631. To run a single test.  This test exercises the entire 700D receive side,
64   and measures CPU load and memory:
65   ```
66   $ cd ~/codec2/stm32/unittest
67   $ ./scripts/run_stm32_tst tst_ofdm_api_demod 700D_AWGN_codec
68   ```
69   In general:
70   ```
71   $ ./scripts/run_stm32_test <name_of_test> <test_option>
72   ```
73
741. To run a test set (example):
75   ```
76   $ cd ~/codec2/stm32/unittest
77   $ ./scripts/run_all_ldpc_tests
78   ```
79   In general: (codec2, ofdm, ldpc):
80   ```
81   $ ./scripts/run_all_<set_name>_tests
82   ```
83
84## When tests fail
85
861. If a test fails, explore the files in the ```test_run``` directory for that test.
871. Try building with ALLOC_DEBUG can be helpful with heap issues:
88   ```
89   $ CFLAGS=-DEBUG_ALLOC cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/STM32_Toolchain.cmake \
90     -DPERIPHLIBDIR=~/Downloads/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0 ..
91   ```
92
93## Sequence of a Test
94
95Consider the example:
96```
97build_stm32$ ctest -R tst_ldpc_dec_noise
98```
99
1001. The test is kicked off based on `src/CMakeLists.txt`, which calls `scipts/run_stm32_tst`
1011. `run_stm32_tst` calls the test setup script, e.g. `tst_ldpc_dec_setup`.  Typically, this will run a host version to generate a reference.
1021. `run_stm32_tst` runs the stm32 executable on the Discovery, e.g. `tst_ldpc_dec`, the source is in `src/tst_ldpc_dec.c`
1031. The steup and check scripts can handle many sub cases, e.g. `ideal` and `noise`.
1041. `run_stm32_tst` calls the test check script, e.g. `tst_ldpc_dec_check` which typically compares the host generated reference to the output from the stm32.
1051. As the test runs, various files are generated in `test_run/tst_ldpc_dec_noise`
1061. When debugging it's useful to run the ctest with the verbose option:
107   ```
108   $ ctest -V -R tst_ldpc_dec_noise
109   ```
110   Set the `-x` at the top of the scripts to trace execution:
111   ```
112   #!/bin/bash -x
113   #
114   # tst_ldpc_enc_check
115
116   ```
117
118## Directory Structure
119
120   | Path | Description |
121   | --- | --- |
122   | `scripts`   | Scripts for unittest system
123   | `src`       | stm32 C sources
124   | `\src\CMakeLists.txt` | ctests are defined here
125   | `lib/python`| Python library files
126   | `lib/octave`| Octave library files
127   | `test_run`  | Files created by each test as it runs
128
129
130## Running the tests remotely
131
132If the stm32 hardware is connected on a different pc with linux, the tests can be run remotely.
133Test will run slower, roughly 3 times.
134
1351. You have to build OpenOCD on the remote machine with the STM32 board. It must be built from
136   (https://github.com/db4ple/openocd.git).
1371. You don't need OpenOCD installed on your build pc.
1381. You have to be able to run ssh with public key authentication using ssh-agent so that
139   you can ssh into the remote machine without entering a password.
1401. You have to call ctest with the proper UT_SSH_PARAMS settings, e.g.
141```
142UT_SSH_PARAMS="-p 22 -q remoteuser@remotemachine" ctest -V
143```
144
145## Debug and Semihosting
146
147These tests required a connection from the arm-none-eabi-gdb debugger
148to the stm32 hardware. For this we use a recent version of
149OpenOCD. Running tests with the stm32 hardware connected to a remote
150machine via ssh is possible. This works only with a patched (fixed)
151OpenOCD, see below.
152
153## OpenOCD
154
155We recommend OpenOCD instead of stlink.
156
157Most linux distributions use old packages for openocd, so you should
158build it from the git source. If your test runs fail with error
159messages regarding SYS_FLEN not support (see openocd_stderr.log in the
160test_run directories), your openocd is too old. Make sure to have the
161right openocd first in the PATH if you have multiple openocd
162installed!
163
164It is strongly recommended to build OpenOCD from sources, see below.
165
166## Building OpenOCD
167
168OpenOCD needs to be built from the source.
169
170If you want to use openocd remotely via SSH, you have to use currently the patched
171source from (https://github.com/db4ple/openocd.git) instead of the official repository.
172
1731.
174    The executable is placed in /usr/local/bin ! Make sure to have no
175    other openocd installed (check output of `which openocd` to be
176    /usr/local/bin)
177
178	```Bash
179      sudo apt install libusb-1.0-0-dev libtool pkg-config autoconf automake texinfo
180      git clone https://git.code.sf.net/p/openocd/code openocd-code
181      cd openocd-code
182      ./bootstrap
183      ./configure
184      sudo make install
185      which openocd
186
187      sudo cp contrib/60-openocd.rules /etc/udev/rules.d/
188      sudo udevadm control --reload-rules
189      {un plug/plug-in stm32 Discovery}
190	```
191
1922. Plug in a stm32 development board and test:
193
194```
195   $ openocd -f board/stm32f4discovery.cfg
196
197   Open On-Chip Debugger 0.10.0+dev-00796-ga4ac5615 (2019-04-12-21:58)
198   Licensed under GNU GPL v2
199   For bug reports, read
200   http://openocd.org/doc/doxygen/bugs.html
201   Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
202   adapter speed: 2000 kHz
203   adapter_nsrst_delay: 100
204   none separate
205   srst_only separate srst_nogate srst_open_drain connect_deassert_srst
206   Info : Listening on port 6666 for tcl connections
207   Info : Listening on port 4444 for telnet connections
208   Info : clock speed 2000 kHz
209   Info : STLINK V2J33S0 (API v2) VID:PID 0483:3748
210   Info : Target voltage: 2.871855
211   Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
212   Info : Listening on port 3333 for gdb connections
213```
214
215## st-util (deprecated)
216
217Most distributions don't have stutil included. Easiest way is to build it from
218the github sources.
219
220The source can be downloaded from:
221
222       (https://github.com/texane/stlink)
223
224After compiling it can be installed anywhere, as long as it is in the PATH.  The program is in
225`build/Release/src/gdbserver/st-util`.
226
227The newlib stdio functions (open, fread, fwrite, flush, fclose, etc.) send
228some requests that this tool does not recognize and those messages will appear
229in the output of st-util.  They can be ignored.
230
2311. Build from github
232
233```Bash
234  git clone https://github.com/texane/stlink
235  cd stlink
236  make
237  sudo cp ./etc/udev/rules.d/49-stlinkv2.rules /etc/udev/rules.d/
238  sudo udevadm control --reload-rules
239```
2403. Add the st-util util to your $PATH, if not installed in the default location ( /usr/local/bin )
241
2424. Plug in a stm32 development board and test:
243
244```
245  $ st-util
246
247  st-util 1.4.0-47-gae717b9
248  2018-12-29T06:52:16 INFO usb.c: -- exit_dfu_mode
249  2018-12-29T06:52:16 INFO common.c: Loading device parameters....
250  2018-12-29T06:52:16 INFO common.c: Device connected is: F4 device, id 0x10016413
251  2018-12-29T06:52:16 INFO common.c: SRAM size: 0x30000 bytes (192 KiB), Flash: 0x100000 bytes (1024 KiB) in pages of 16384 bytes
252  2018-12-29T06:52:16 INFO gdb-server.c: Chip ID is 00000413, Core ID is  2ba01477.G
253  2018-12-29T06:52:16 INFO gdb-server.c: Listening at *:4242...
254```
255
256
257
258
259# vi:set ts=3 et sts=3:
260