📄 programming-concepts-techniques.sgml
字号:
<CHAPTER id="debugging-techniques"><TITLE>Debugging Techniques</TITLE><PARA><productname>eCos</productname> applications and components can be debugged in traditional ways, with printing statements and debugger single-stepping, but there are situations in which these techniques cannot be used. One example of this is when a program is getting data at a high rate from a real-time source, and cannot be slowed down or interrupted.</PARA><PARA><productname>eCos</productname>’s infrastructure module provides a <EMPHASIS>tracing</EMPHASIS> formalism, allowing the kernel’s tracing macros to be configured in many useful ways. <productname>eCos</productname>’s kernel provides <FIRSTTERM>instrumentation buffers</FIRSTTERM> which also collect specific (configurable) data about the system’s history and performance.</PARA><SECT1 id="tracing"><TITLE>Tracing</TITLE><PARA>To use <productname>eCos</productname>’s tracing facilities you must first configure your system to use <FIRSTTERM>tracing</FIRSTTERM>. You should enable the Asserts and Tracing component (<OPTION>CYGPKG_INFRA_DEBUG</OPTION>) and the <OPTION>Use tracing</OPTION> component within it (<OPTION>CYGDBG_USE_TRACING</OPTION>). These options can be enabled with the <APPLICATION>Configuration Tool</APPLICATION> or by editing the file <FILENAME><REPLACEABLE>BUILD_DIR</REPLACEABLE>/pkgconf/infra.h </FILENAME> manually.</PARA><PARA>You should then examine all the tracing-related options inthe <citetitle>Package: Infrastructure</citetitle> chapter of the <citetitle><PRODUCTNAME>eCos</PRODUCTNAME> ReferenceManual</citetitle>. One useful set of configuration options are: <literal>CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS</literal> and <literal>CYGDBG_INFRA_DEBUG_TRACE_MESSAGE</literal>,which are both enabled by default when tracing is enabled.</PARA><PARA>The following “Hello world with tracing” showsthe output from running the hello world program (from <xref linkend="ecos-hello-world">) that wasbuilt with tracing enabled: </PARA><EXAMPLE><TITLE>Hello world with tracing</TITLE><SCREEN>$ mips-tx39-elf-run --board=jmr3904 helloHello, eCos world!ASSERT FAIL: <2>cyg_trac.h [ 623] Cyg_TraceFunction_Report_::set_exitvoid() exitvoid used in typed functionTRACE: <1>mlqueue.cxx [ 395] Cyg_ThreadQueue_Implementation::enqueue() {{enterTRACE: <1>mlqueue.cxx [ 395] Cyg_ThreadQueue_Implementation::enqueue() }}RETURNING UNSET!TRACE: <1>mlqueue.cxx [ 126] Cyg_Scheduler_Implementation::add_thread() }}RETURNING UNSET!TRACE: <1>thread.cxx [ 654] Cyg_Thread::resume() }}return voidTRACE: <1>cstartup.cxx [ 160] cyg_iso_c_start() }}return voidTRACE: <1>startup.cxx [ 142] cyg_package_start() }}return voidTRACE: <1>startup.cxx [ 150] cyg_user_start() {{enterTRACE: <1>startup.cxx [ 150] cyg_user_start() (((void)))TRACE: <1>startup.cxx [ 153] cyg_user_start() 'This is the system default cyg_user_start()'TRACE: <1>startup.cxx [ 157] cyg_user_start() }}return voidTRACE: <1>sched.cxx [ 212] Cyg_Scheduler::start() {{enterTRACE: <1>mlqueue.cxx [ 102] Cyg_Scheduler_Implementation::schedule() {{enterTRACE: <1>mlqueue.cxx [ 437] Cyg_ThreadQueue_Implementation::highpri() {{enterTRACE: <1>mlqueue.cxx [ 437] Cyg_ThreadQueue_Implementation::highpri() }}RETURNING UNSET!TRACE: <1>mlqueue.cxx [ 102] Cyg_Scheduler_Implementation::schedule() }}RETURNING UNSET!TRACE: <2>intr.cxx [ 450] Cyg_Interrupt::enable_interrupts() {{enterTRACE: <2>intr.cxx [ 450] Cyg_Interrupt::enable_interrupts() }}RETURNING UNSET!TRACE: <2>thread.cxx [ 69] Cyg_HardwareThread::thread_entry() {{enterTRACE: <2>cstartup.cxx [ 127] invoke_main() {{enterTRACE: <2>cstartup.cxx [ 127] invoke_main() ((argument is ignored))TRACE: <2>dummyxxmain.cxx [ 60] __main() {{enterTRACE: <2>dummyxxmain.cxx [ 60] __main() (((void)))TRACE: <2>dummyxxmain.cxx [ 63] __main() 'This is the system default __main()'TRACE: <2>dummyxxmain.cxx [ 67] __main() }}return voidTRACE: <2>memcpy.c [ 112] _memcpy() {{enterTRACE: <2>memcpy.c [ 112] _memcpy() ((dst=80002804, src=BFC14E58, n=19))TRACE: <2>memcpy.c [ 164] _memcpy() }}returning 80002804TRACE: <2>cstartup.cxx [ 137] invoke_main() 'main() has returned with code 0. Calling exit()'TRACE: <2>exit.cxx [ 71] __libc_exit() {{enterTRACE: <2>exit.cxx [ 71] __libc_exit() ((status=0 ))TRACE: <2>atexit.cxx [ 84] cyg_libc_invoke_atexit_handlers() {{enterTRACE: <2>atexit.cxx [ 84] cyg_libc_invoke_atexit_handlers() (((void)))Scheduler:Lock: 0Current Thread: <null>Threads:Idle Thread pri = 31 state = R id = 1 stack base = 800021F0 ptr = 80002510 size = 00000400 sleep reason NONE wake reason NONE queue = 80000C54 wait info = 00000000<null> pri = 0 state = R id = 2 stack base = 80002A48 ptr = 8000A968 size = 00008000 sleep reason NONE wake reason NONE queue = 80000BD8 wait info = 00000000 </SCREEN></EXAMPLE></SECT1><SECT1 id="kernel-instrumentation"><TITLE>Kernel Instrumentation</TITLE><PARA><FIRSTTERM>Instrument buffers</FIRSTTERM> can be used to find out how many events of a given type happened in the kernel during execution of a program.</PARA><PARA>You can monitor a class of several types of events, or you can just look at individual events. </PARA><PARA>Examples of <FIRSTTERM>events</FIRSTTERM> that can be monitored are: </PARA><ITEMIZEDLIST><LISTITEM><PARA>scheduler events </PARA></LISTITEM><LISTITEM><PARA>thread operations</PARA></LISTITEM><LISTITEM><PARA>interrupts </PARA></LISTITEM><LISTITEM><PARA>mutex operations </PARA></LISTITEM><LISTITEM><PARA>binary semaphore operations </PARA></LISTITEM><LISTITEM><PARA>counting semaphore operations </PARA></LISTITEM><LISTITEM><PARA>clock ticks and interrupts </PARA></LISTITEM></ITEMIZEDLIST><PARA>Examples of fine-grained scheduler event types are: </PARA><ITEMIZEDLIST><LISTITEM><PARA>scheduler lock</PARA></LISTITEM><LISTITEM><PARA>scheduler unlock</PARA></LISTITEM><LISTITEM><PARA>rescheduling</PARA></LISTITEM><LISTITEM><PARA>time slicing </PARA></LISTITEM></ITEMIZEDLIST><PARA>Information about the events is stored in an <FIRSTTERM>event record</FIRSTTERM>. The structure that defines this record has type <type>struct Instrument_Record</type>:</PARA><PARA>The list of records is stored in an array called <TYPE>instrument_buffer</TYPE>which you can let the kernel provide or you can provide yourselfby setting the configuration option <literal>CYGVAR_KERNEL_INSTRUMENT_EXTERNAL_BUFFER</literal>. </PARA><PARA>To write a program that examines the instrumentation buffers: </PARA><ORDEREDLIST><LISTITEM><PARA>Enable instrumentation buffers in the <productname>eCos</productname> kernel configuration.The component macro is <literal>CYGPKG_KERNEL_INSTRUMENT</literal>.</PARA></LISTITEM><LISTITEM><PARA>To allocate the buffers yourself, enable the configurationoption <literal>CYGVAR_KERNEL_INSTRUMENT_EXTERNAL_BUFFER</literal>. </PARA></LISTITEM><LISTITEM><PARA>Include the header file <FILENAME>cyg/kernel/instrmnt.h</FILENAME>. <PROGRAMLISTING>#include <cyg/kernel/instrmnt.h></PROGRAMLISTING></PARA></LISTITEM><LISTITEM><PARA>The <STRUCTNAME>Instrumentation_Record</STRUCTNAME> structureis not published in the kernel header file. In the future therewill be a cleaner mechanism to access it, but for now you shouldpaste into your code in the following lines: </para><PROGRAMLISTING>struct Instrument_Record{ CYG_WORD16 type; // record type CYG_WORD16 thread; // current thread id CYG_WORD timestamp; // 32 bit timestamp CYG_WORD arg1; // first arg CYG_WORD arg2; // second arg};</PROGRAMLISTING></LISTITEM><LISTITEM><PARA>Enable the events you want to record using <FUNCTION>cyg_instrument_enable()</FUNCTION>, and disable them later. Look at <filename>cyg/kernel/instrmnt.h</filename> and the examples below to see what events can be enabled. </PARA></LISTITEM><LISTITEM><PARA>Place the code you want to debug between the matchingfunctions <FUNCTION>cyg_instrument_enable()</FUNCTION> and <FUNCTION>cyg_instrument_disable()</FUNCTION>. </PARA></LISTITEM><LISTITEM><PARA>Examine the buffer. For now you need to look at the datain there (the example program below shows how to do that), and futureversions of <productname>eCos</productname> will include a host-side tool to help you understandthe data. </PARA></LISTITEM></ORDEREDLIST><EXAMPLE><TITLE>Using instrument buffers</TITLE><PARA>This program is also provided in the <FILENAME>examples</FILENAME> directory. </PARA><PROGRAMLISTING>/* this is a program which uses <productname>eCos</productname> instrumentation buffers; it needs to be linked with a kernel which was compiled with support for instrumentation */#include <stdio.h>#include <pkgconf/kernel.h>#include <cyg/kernel/instrmnt.h>#include <cyg/kernel/kapi.h>#ifndef CYGVAR_KERNEL_INSTRUMENT_EXTERNAL_BUFFER# error You must configure eCos with CYGVAR_KERNEL_INSTRUMENT_EXTERNAL_BUFFER#endifstruct Instrument_Record{ CYG_WORD16 type; // record type CYG_WORD16 thread; // current thread id CYG_WORD timestamp; // 32 bit timestamp CYG_WORD arg1; // first arg CYG_WORD arg2; // second arg};struct Instrument_Record instrument_buffer[20];cyg_uint32 instrument_buffer_size = 20;int main(void){ int i; cyg_instrument_enable(CYG_INSTRUMENT_CLASS_CLOCK, 0); cyg_instrument_enable(CYG_INSTRUMENT_CLASS_THREAD, 0); cyg_instrument_enable(CYG_INSTRUMENT_CLASS_ALARM, 0); printf("Program to play with instrumentation buffer\n"); cyg_thread_delay(2); cyg_instrument_disable(CYG_INSTRUMENT_CLASS_CLOCK, 0); cyg_instrument_disable(CYG_INSTRUMENT_CLASS_THREAD, 0); cyg_instrument_disable(CYG_INSTRUMENT_CLASS_ALARM, 0); for (i = 0; i < instrument_buffer_size; ++i) { printf("Record %02d: type 0x%04x, thread %d, ", i, instrument_buffer[i].type, instrument_buffer[i].thread); printf("time %5d, arg1 0x%08x, arg2 0x%08x\n", instrument_buffer[i].timestamp, instrument_buffer[i].arg1, instrument_buffer[i].arg2); } return 0;}</PROGRAMLISTING></EXAMPLE><PARA>Here is how you could compile and run this program in the <filename>examples</filename> directory,using (for example) the MN10300 simulator target: </PARA><SCREEN>$ make XCC=mn10300-elf-gcc INSTALL_DIR=/tmp/ecos-work-mn10300/install instrument-testmn10300-elf-gcc -c -o instrument-test.o -g -Wall -I/tmp/ecos-work-mn10300/install/include \ -ffunction-sections -fdata-sections instrument-test.cmn10300-elf-gcc -nostartfiles -L/tmp/ecos-work-mn10300/install/lib -W1,--gc-sections -o \ instrument-test instrument-test.o -Ttarget.ld -nostdlib$ mn10300-elf-run --board=stdeval1 instrument-test</SCREEN><EXAMPLE><TITLE>Instrument buffer output</TITLE><PARA>Here is the output of the <COMMAND>instrument-test</COMMAND> program. Notice that in little over 2 seconds, and with very little activity, and with few event types enabled, it gathered 17 records. In larger programs it will be necessary to select very few event types for debugging. </PARA><PROGRAMLISTING>Program to play with instrumentation bufferRecord 00: type 0x0207, thread 2, time 6057, arg1 0x48001cd8, arg2 0x00000002Record 01: type 0x0202, thread 2, time 6153, arg1 0x48001cd8, arg2 0x00000000Record 02: type 0x0904, thread 2, time 6358, arg1 0x48001d24, arg2 0x00000000Record 03: type 0x0905, thread 2, time 6424, arg1 0x00000002, arg2 0x00000000Record 04: type 0x0906, thread 2, time 6490, arg1 0x00000000, arg2 0x00000000Record 05: type 0x0901, thread 2, time 6608, arg1 0x48009d74, arg2 0x48001d24Record 06: type 0x0201, thread 2, time 6804, arg1 0x48001cd8, arg2 0x480013e0Record 07: type 0x0803, thread 1, time 94, arg1 0x00000000, arg2 0x00000000Record 08: type 0x0801, thread 1, time 361, arg1 0x00000000, arg2 0x00000000Record 09: type 0x0802, thread 1, time 548, arg1 0x00000001, arg2 0x00000000Record 10: type 0x0803, thread 1, time 94, arg1 0x00000000, arg2 0x00000000Record 11: type 0x0801, thread 1, time 361, arg1 0x00000001, arg2 0x00000000Record 12: type 0x0903, thread 1, time 513, arg1 0x48009d74, arg2 0x48001d24Record 13: type 0x0208, thread 1, time 588, arg1 0x00000000, arg2 0x00000000Record 14: type 0x0203, thread 1, time 697, arg1 0x48001cd8, arg2 0x480013e0Record 15: type 0x0802, thread 1, time 946, arg1 0x00000002, arg2 0x00000000Record 16: type 0x0201, thread 1, time 1083, arg1 0x480013e0, arg2 0x48001cd8Record 17: type 0x0000, thread 0, time 0, arg1 0x00000000, arg2 0x00000000Record 18: type 0x0000, thread 0, time 0, arg1 0x00000000, arg2 0x00000000Record 19: type 0x0000, thread 0, time 0, arg1 0x00000000, arg2 0x00000000</PROGRAMLISTING></EXAMPLE></SECT1></CHAPTER></PART><!-- Keep this comment at the end of the fileLocal variables:mode: sgmlsgml-omittag:nilsgml-shorttag:tsgml-namecase-general:tsgml-general-insert-case:lowersgml-minimize-attributes:nilsgml-always-quote-attributes:tsgml-indent-step:2sgml-indent-data:tsgml-parent-document:("user-guide.sgml" "book" "part")sgml-exposed-tags:nilsgml-local-catalogs:nilsgml-local-ecat-files:nilEnd:-->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -