22lib_logging: Debug Printing
33###########################
44
5+ |newpage |
6+
57************
68Introduction
79************
@@ -27,13 +29,17 @@ To use this module, include ``lib_logging`` in the application's
2729Debug units
2830***********
2931
30- A source file can be added to a debug unit by defining the ``DEBUG_UNIT `` macro before inclusion of ``debug_print.h ``. For example::
32+ A source file can be added to a debug unit by defining the ``DEBUG_UNIT `` macro before inclusion of ``debug_print.h ``. For example,
33+
34+ .. code-block :: c
3135
3236 #define DEBUG_UNIT ETHERNET_MODULE
3337 #include "debug_print.h"
3438
3539 To include all source files in a module in a particular debug unit, it is
36- convenient to do it in the ``lib_build_info.cmake `` file of the module e.g.::
40+ convenient to do it in the ``lib_build_info.cmake `` file of the module e.g.
41+
42+ .. code-block :: cmake
3743
3844 set(LIB_COMPILER_FLAGS ... -DDEBUG_UNIT=ETHERNET_MODULE ...)
3945
@@ -47,7 +53,9 @@ By default, debug printing is turned *off*. To enable printing you
4753need to pass the correct command line option to compilation. The
4854following defines can be set by using the ``-D `` option to the
4955compiler. For example, the following in your application ``CMakeLists.txt ``
50- will enable debug printing::
56+ will enable debug printing
57+
58+ .. code-block :: cmake
5159
5260 set(APP_COMPILER_FLAGS ... -DDEBUG_PRINT_ENABLE=1 ...)
5361
@@ -66,3 +74,246 @@ DEBUG_PRINT_DISABLE_[debug unit]
6674 debug unit. If set to 1, this will override the default set by
6775 ``DEBUG_PRINT_ENABLE ``.
6876
77+
78+ *******
79+ Example
80+ *******
81+
82+ This included example shows how to use the logging library. It covers the
83+ difference between the logging library (``debug_printf() ``) and the system library
84+ printing function (``printf() ``).
85+
86+ It also covers the difference between JTAG and xSCOPE to perform the I/O to the
87+ host, including approximate values for resource usage and performance of each approach.
88+
89+ *****************************
90+ Example logging library usage
91+ *****************************
92+
93+ The CMakeLists.txt file
94+ =======================
95+
96+ To start using the XMOS logging library, you need to add ``lib_logging `` to the
97+ dependent module list in the ``CMakeLists.txt `` file
98+
99+ .. code-block :: cmake
100+
101+ set(APP_DEPENDENT_MODULES "lib_logging")
102+
103+ The dependencies for this example are specified by ``deps.cmake `` in the ``examples ``
104+ directory and are included in the application ``CMakeLists.txt `` file.
105+
106+ Also, ``debug_printf() `` calls are only active if you enable
107+ them in your ``CMakeLists.txt `` file. This is done by by setting ``DEBUG_PRINT_ENABLE ``
108+ to 1 in the ``APP_COMPILER_FLAGS ``.
109+
110+ .. code-block :: cmake
111+
112+ set(APP_COMPILER_FLAGS ... -DDEBUG_PRINT_ENABLE=1 ...)
113+
114+ Include
115+ =======
116+
117+ The function prototypes are declared in a single header file which must
118+ be included from your source file.
119+
120+ .. code-block :: c
121+
122+ #include "debug_print.h"
123+
124+ Example application output
125+ ==========================
126+
127+ The example application outputs "Hello world".
128+
129+ .. literalinclude :: ../../examples/app_debug_unit/src/main.xc
130+ :language: c
131+ :start-at: main(
132+ :end-at: debug_printf(
133+
134+ Building and Running the application using the command line
135+ ===========================================================
136+
137+ First open a command prompt/terminal window with the tools environment setup.
138+ A setup batch/script file is provided in the XTC package to do this for you.
139+
140+ To configure the build run the following from an XTC command prompt.
141+
142+ .. code-block :: console
143+
144+ cd examples
145+ cd app_debug_unit
146+ cmake -B build -G "Unix Makefiles"
147+
148+ Finally, the application binaries can be built using ``xmake ``.
149+
150+ .. code-block :: console
151+
152+ xmake -C build
153+
154+ Running the application is then done using the command.
155+
156+ .. code-block :: console
157+
158+ xrun --xscope bin/app_debug_unit.xe
159+
160+ Debug units by example
161+ ======================
162+
163+ Applications can be created with different *units * whose debug output is independently
164+ controlled. The example application also calls a function in another unit:
165+
166+ .. literalinclude :: ../../examples/app_debug_unit/src/main.xc
167+ :language: c
168+ :start-at: unit_function(
169+ :end-at: unit_function(
170+
171+ That file has put its debug messages as a separate debug unit by doing:
172+
173+ .. literalinclude :: ../../examples/app_debug_unit/src/unit.xc
174+ :language: c
175+ :start-at: define
176+ :end-at: include
177+
178+ And by default these debug messages are not enabled, so running the program
179+ will only produce the following output.
180+
181+ .. code-block :: console
182+
183+ $ xrun --xscope bin/app_debug_unit.xe
184+ Hello world
185+
186+ In order to enable the debug_print messages in ``unit.xc `` it is necessary to
187+ add to the list of compiler flags in the ``CMakeLists.txt `` file.
188+
189+ .. code-block :: cmake
190+
191+ set(APP_COMPILER_FLAGS ... -DDEBUG_PRINT_ENABLE_unit=1 ...)
192+
193+ After rebuilding the application it will now produce.
194+
195+ .. code-block :: console
196+
197+ $ xrun --xscope bin/app_debug_unit.xe
198+ Hello world
199+ Unit print
200+
201+ xSCOPE printing
202+ ===============
203+
204+ On the xCORE platform it is possible to have I/O messages sent to the
205+ console using either JTAG or xSCOPE. The default is for JTAG to be used. However,
206+ when doing I/O over JTAG all cores on the xCORE are stopped and hence
207+ real-time functionality is no longer maintained. As a result xSCOPE I/O should
208+ be preferred.
209+
210+ xSCOPE I/O is enabled by creating a ``config.xscope `` file. This file can be
211+ created in the same folder as the ``CMakeLists.txt `` or with the source files. When
212+ ``config.xscope `` exists, it controls whether I/O messages are enabled, and
213+ whether they use xSCOPE or JTAG. When xSCOPE is enabled it uses a link to
214+ communicate with the xTAG. The link is specified in the target's ``XN `` file.
215+ A basic file which enables I/O over xSCOPE contains:
216+
217+ .. code-block :: console
218+
219+ <xSCOPEconfig ioMode="basic" enabled="true">
220+ </xSCOPEconfig>
221+
222+ |newpage |
223+
224+ *****
225+ Notes
226+ *****
227+
228+ Resource usage
229+ ==============
230+
231+ The following table shows the memory and cycle requirements for doing
232+ a simple print of "Hello world %d\\ n", using either ``printf() `` or ``debug_printf() ``,
233+ and using either JTAG or xSCOPE as the transport to the host.
234+
235+ .. list-table :: Resource usage
236+ :header-rows: 1
237+
238+ * - Function
239+ - Transport
240+ - Program Memory (kB)
241+ - Time (us)
242+ - Channel Ends
243+ * - None
244+ - N/A
245+ - 0.9
246+ - 0.0
247+ - 0
248+ * - debug_printf()
249+ - JTAG
250+ - 1.86
251+ - 72000
252+ - 0
253+ * - debug_printf()
254+ - xSCOPE
255+ - 2.88
256+ - 8.5
257+ - 1 per tile
258+ * - printf()
259+ - JTAG
260+ - 9.02
261+ - 72000
262+ - 0
263+ * - printf()
264+ - xSCOPE
265+ - 9.99
266+ - 18.6
267+ - 1 per tile
268+
269+ .. note :: The JTAG timings are approximate and will depend on a number of factors
270+ including the host machine being used.
271+
272+ Lossless vs lossy
273+ =================
274+
275+ The advantage of using xSCOPE instead of JTAG should be clear from the performance
276+ figures above. However, it is important to understand that xSCOPE is a lossy
277+ transport and as such if too much I/O is created then messages can be lost.
278+
279+ Ordering
280+ ========
281+
282+ It is also essential to understand that messages produced by different
283+ logical cores are interleaved on the host console. There is no guarantee of the
284+ order in which they will be printed.
285+
286+ print.h
287+ =======
288+
289+ The tools provide extremely lightweight printing functions in ``print.h ``. For
290+ example it is possible to do.
291+
292+ .. code-block :: c
293+
294+ #include <print.h>
295+ ...
296+ printstr("The number ");
297+ printint(10);
298+ printstrln(" should be 10");
299+
300+ But each of these print fragments can arrive mixed with messages from
301+ other logical cores. Whereas,
302+
303+ .. code-block :: c
304+
305+ debug_printf("The number %d should be 10\n", 10);
306+
307+ will be printed as a single line.
308+
309+ ***************
310+ Further Reading
311+ ***************
312+
313+ * `XMOS XTC Tools Installation Guide <https://xmos.com/xtc-install-guide >`_
314+
315+ * `XMOS XTC Tools User Guide <https://www.xmos.com/view/Tools-15-Documentation >`_
316+
317+ * `XMOS application build and dependency management system; xcommon-cmake <https://www.xmos.com/file/xcommon-cmake-documentation/?version=latest >`_
318+
319+ * `XMOS Libraries <https://www.xmos.com/libraries >`_
0 commit comments