Multiple Target and Minimal Disturbance Debugger Features This chapter describes the Apex Multiple Target and Minimal Disturbance debugger features. This is a feature that is ONLY available to Ericsson MACS PowerPC hardware. It is not available for any other Apex Embedded targets. In addition, to use the Minimal Disturbance features, the user will need to configure TDM and the kernel to use the realtime debug task.
The following sections are included in this chapter.
Multiple Target DebuggingUsers can debug multiple targets using only one debugger engine. For multiple target debugging, users must use the program_file debugger invocation option and specify the information for each target that will be in the debug session.
Additional information on multiprogram debugging can be found in Using the Apex Debugger.
Program File Option
Enable the multiple target feature of the debugger using one of the following:
GUI Command Command Line
Multiprogram debugging: toggle and text field in the File > Run or File > Debug dialogs apex_debug -program_file <full pathname of program file>
Either of these causes the debugger to read the program file, which specifies which targets to debug.
Program File
To debug multiple targets from one debug session, a program file must first be created. This file contains the information the debugger needs for a multiple target session and may be located in any directory accessible to the debugger.
The file has the following format:
Example contents of a program file:
# lines beginning with # are comments # # target 1: program executable: /path/to/the/first/executable executable_args: -arg1 arg2 -arg3 extra_executable: /path/to/exe/net.vox /path/to/exe/helper.vox target: vulcan dbiface: /usr/blah/blah/host_daemon tdm_service: tdm2 rdt_service: rdt1 kernel: /proj/x5/bsp/krn/krn.vox # target 2: program executable: /path/to/the/second/executable executable_args: -arg1 arg2 -arg3 target: varpa dbiface: /usr/blah/blah/host_daemon tdm_service: tdm2 rdt_service: rdt1 kernel: /proj/x5/bsp/krn/krn.vox
Synchronized Target Hardware
In some multiple target systems, there is a hardware or software synchronization between the targets in the system. This synchronization is characterized by one-stop/all-stop and one-go/all-go target activity and requires TDM support.
For example, a debug session could consist of four synchronized targets, each target loaded with a user application. When the user starts one application (and target) from the debugger with the continue or run command, all four targets will execute as a result of the TDM extensions. Then, when one application (and target) stops for any reason, the other three targets will also stop, also due to the TDM extensions.
The debugger supports debugging this one-stop-all/stop and one-start/all-start hardware configuration. However, all targets in the target system must have the same characteristics; either all targets are synchronized or none of the targets are synchronized.
In addition to the one-start/all-start characteristic, the target system often supports a mechanism for only starting one target in the target system. Users must configure TDM to add this extra support. The one-start/all-start mechanism is referred to as global_go and the single target execution is referred to as local_go in this discussion.
Special Considerations for Synchronized Targets
There are special considerations for the synchronized target systems that support local_go and global_go. These are described below.
Single Stepping
Stepping in a synchronized target system can be configured by the user. The debugger has a special set command that gives the user control over the step behavior:
set step_cmd <cmd> [local_go|global_go]
where cmd = s, si, o, oi and global_go refers to running all targets in the target system and local_go refers to running only the current target in the target system.
User Procedure Calls
User procedure calls are always executed on the current target only, i.e., using local_go.
p procedure_call()
Catching Exceptions
When the user chooses to catch a specific or a set of exceptions, the catch exception command is used. To catch any exception, the debugger sets a breakpoint at the location in the RTS where all exceptions are handled. Each time a handled exception occurs, the application stops at the RTS breakpoint and the debugger reads memory to determine if this exception is one that the user wants to catch. If it is, then the debugger announces the exception to the user and waits for the user's next command. If it is not, the debugger continues execution of the application without notifying the user that the application had stopped.
In the one-stop-all-stop scenario, this means that each time any of the applications in the debug session goes through the exception handling in the RTS, (i.e., has an exception) all of the applications in the debug session will stop. Then, if the exception is not one that the user requested via the catch command, all of the targets will be restarted without the user's knowledge.
As an alternative approach for catching exceptions, instead of using the debugger feature catch foo, you can set breakpoints in your application code - specifically in your exception handlers.
This will avoid stopping the application when exceptions other than the one you want to catch are raised.
Continuing After Breakpoints
When one application in the debug session stops at a breakpoint or at an exception, all of the other applications in the debug session will also be stopped. The user can continue execution from any target in the debug session, not only the target that stopped at the event.
Minimal Disturbance Debugging (Realtime Mode)This Apex debugger feature enables users to debug one or more embedded targets with minimal disturbance. The debugger is asynchronous, allowing the user to debug the application while it is running. The implementation uses a runtime support package, Realtime Debug Task (RDT), which is linked with the user's application. This runtime support package handles the debugger commands while the user's application is running, since TDM can only handle debugger commands when the user's application is stopped.
The architecture of the debugger is described in Figure 10 .
Figure 10 Architecture Of the Debugger
The Minimal Disturbance extensions provide users with special debugging support for debugging running user applications. That is, the Minimal Disturbance debugger allows users to debug running applications in the following manner:
- reading/writing memory
- setting/deleting breakpoints
- executing user defined pass through commands
- detach a running application from the debug session
- passthru command
Usage
To utilize the Minimal Disturbance feature of the debugger, users must set the environment variable described in the next section and invoke the debugger using one of the realtime options
Environment variables
Two environment variables control the behavior of the RDT. These are described in Table 2.
The value of APEX_RDT_SERVICE must match the value of the port compiled into the target RDT configuration.
Options
The following options are provided specifically for multiple target debugging.
- Enable the realtime debug mode
GUI Command Command Line
Realtime: -realtime button and text field in File > Run or File > Debug dialogs apex_debug -realtime <executable_name>
- Attach to a running target without stopping it
GUI Command Command Line
Realtime: -realtime_attach button and text field in File > Run or File > Debug dialogs apex_debug -realtime_attach <executable_name>
Note that -realtime_attach also implies -realtime.
- Attach to a running target without stopping and set the breakpoints necessary to catch unhandled exceptions
GUI Command Command Line
Realtime: -realtime_attach_with_exceptions button and text field in File > Run or File > Debug dialogs apex_debug -realtime_attach_with_exceptions <executable_name>
Note that -realtime_attach_with_exceptions also implies -realtime and
-realtime_attach.Permitted/Not Permitted Debugger Commands
When debugging in realtime mode (by invoking the debugger with one of the -realtime options), only a limited set of debugger commands are permitted when the application is running. These commands are:
- Read/write memory commands (static data that's not stored in registers). For example:
GUI Command Command Line
Debug > Show p global_var
Memory Window p address:m
Debug > Modify Data global_var := new_value
- Breakpoint commands (including exception handling). For example:
GUI Command Command Line
Debug > Break Instruction bi
Debug > Break b line/procedure
Debug > Catch catch program_error
- Browsing/host-only commands (set commands). For example:
GUI Command Command Line
Navigate > Visit v file
v procedure
View > Options set OBASE 16
- Detach user application from the debugger. For example:
GUI Command Command Line
Programs > Detach detach program program_number
- Passthru to RDT. For example:
GUI Command Command Line
Debug > Command pass "string_for_RDT"
Commands that involve communication with the TDM are not permitted when the application is running.
- Register manipulation. For example:
GUI Command Command Line
Debug > Show p $pc
Debug > Modify Register $r1 := 100
Windows > Registers reg
- Task display/manipulation. For example:
GUI Command Command Line
Windows > Tasks lt
- Call stack. For example:
GUI Command Command Line
Windows > Stack cs
Warning: Although disassembling is allowed while the user application is running, the debugger must read memory from the target to present the actual code. This typically results in multiple realtime reads which will disturb the running application more than a typical read/write memory command.
Configuration for Minimal Disturbance
The debugger's Minimal Disturbance features are configurable. The sections below provide instructions on how to configure these features.
The Realtime Debug Task
The Realtime Debug Task is designed to run in the application idle time to minimize the disturbance of the application's realtime performance. Therefore, it is important to understand that if the application does not have enough idle cycles, the RDT will not be able to respond to debugger requests. The remainder of this section describes how to configure your system to meet these requirements.
RDT priority vs. APEX_RDT_TIMEOUT
The priority of the RDT is configured in the Board Support Package (BSP). When the RDT has a low priority, allowing it only a small amount of CPU time, the response time for a realtime command might exceed the value of the environment variable APEX_RDT_TIMEOUT. In this case, a realtime operation may result in a time-out, causing an error message to be displayed.
There are two ways to prevent this:
- 1 . Increase the Value Of APEX_RDT_TIMEOUT
- 2 . Increase the RDT Priority
Increase the Value Of APEX_RDT_TIMEOUT
A higher APEX_RDT_TIMEOUT value gives the RDT more time to respond to realtime operations. One drawback is that the user will have to wait longer for the debugger to report a timeout on the target. See Table 2 for default values.
A typical case where the value should be increased is when the user is debugging an application that uses most of the target CPU time. This will cause the debugger to wait longer before timing out, increasing the changes of the RDT to respond to the debugger requests.
Increase the RDT Priority
By increasing the priority of the RDT to a priority higher than some "work task" of the application, the RDT is allowed to interrupt the application to perform realtime debug operations. In general the priority should not be greater than the priority of the time-critical application tasks. Also note that the priority of the RDT should be lower than the priority of the TCP/IP network program. TCP/IP networking is described in the Using EneT with Rational Exec Guide.
Configuration of the RDT priority is described in section Runtime Support Configuration.
Realtime Passthru Command
The RDT includes a customized passthru command, which allows a parser to be installed on the target side. The passthru command passes a string directly to the RDT. For example:
- pass "echo a text string"
Echoes text on the diagnostics console of the target.
- pass "get prio"
Returns the priority of the RDT.
- pass "set prio value"
Sets the priority of the RDT and returns the old priority. This can be handy when tuning its priority level.
The return value (status) of the passthru commands are echoed by the debugger. This can be used by a user-customized passthru routine to feed information back to the user. For example, the get prio passthru command returns the priority value of the RDT and this number is printed by the debugger.
Detach the Running Application
When debugging in realtime mode, the user can detach the running application from the debug session using the detach command. The debugger will not kill the application as it is detached from the debug session; instead the application will continue running.
Before the detach command can be issued, all breakpoints from the application must be deleted and all exception catching must be turned off.
Detaching from and attaching to a running target can be used to sample and tune the target with only minimal disturbance. For instance, if the application executing on the target has global parameters that control execution, these can be examined and modified using this technique.
Realtime Debugging Considerations
Debugging in realtime mode presents special issues for users. The purpose of this feature is to allow users to debug running applications and only minimally disturb the running applications. However some debugger commands have "hidden", or unexpected consequences. Therefore, special care must be taken when using the realtime mode debugger commands.
Catch and Propagate Exceptions in Realtime Mode
When catch or propagate commands are in effect, the debugger must stop the application at every exception raise to determine whether the exception should be announced. This process can disturb the application on the order of seconds. Therefore, these features should not be used in realtime mode.
As an alternative approach for catching exceptions, instead of using the debugger feature catch foo, you can set breakpoints in your application code - specifically in your exception handlers.
This will avoid stopping the application when exceptions other than the one you want to catch are raised.
Displaying Data
For simple data types, the debugger can display the data with one (1) realtime operation. However, when displaying data of more complex types, the debugger may issue multiple realtime operations. For example, to display records, array, and access types, the debugger needs to retrieve address information from the target before being able to locate and read the actual data.
When minimal disturbance is essential, use memory display commands to dump the data. This will guarantee that only one read operation is used (unless more than 4961 bytes are displayed).
Disassembly
Users are permitted to display disassembled source while the applications are running. However, the debugger must perform multiple realtime memory reads to present this information to the user.
When minimal disturbance is essential, displaying disassembled source is not recommended.
Runtime Support Configuration
The configuration of the RDT is modeled on the same principles as the configuration of the TDM and the kernel. See the Configuring Rational Exec Guide for detailed information on configuring the kernel and TDM.
Configure the RDT using the following steps. This requires the network driver to be shared between TDM and TCP/IP:
- 1 . Determine the address where the shared session data between the TDM and RDT can be stored - this area is less than 64 bytes. You can use the check_config program to locate unallocated memory between the TDM, kernel, networking and the application.
- 2 . Edit Board_Common.sw in your board_common.ss view to define the value of RDT_SESSION_DATA. Example:
Board_Common.sw: SERIAL_TDM_START: 000008000 NETWORK_TDM_START: 000020000 KERNEL_START: 000050000 USER_LINK_BLOCK: 000200000 TDM_IFACE_BLOCK: 00006FFC0 NET_START: 000070000 RDT_SESSION_DATA: 00001FF00
- 3 . Since RDT is used, initialize a_tdm_session_data in v_net_conf.2.ada. To do this, edit v_net_conf.2.ada in net_conf.ss/<your tdm view> by uncommenting the address clause for tdm_session_data as show below:
v_net_conf.2.ada: Tdm_Session_Data : Tdm_Session.Tdm_Session_Data_T; pragma Import (Ada, Tdm_Session_Data, "RDT_SESSION_DATA");
- 4 . Verify the EneT configuration in v_net_conf.2.ada found in the net_conf.ss subsystem in the your "tcp_ip" view:
v_net_conf.2.ada: config_table := ( ... a_tdm_session_data => null, ... );
- 5 . Enter the port that RDT will use to communicate by editing v_rdt_conf.2.ada in the rdt_conf.ss subsystem as shown in the example below. In the example we set the port to 7654 (which is the default value which the debugger will use to connect to the RDT):
v_rdt_conf.2.ada: ... procedure init is begin config_table.a_tdm_session_data:= tdm_session.to_a_tdm_session_data_t(tdm_session_data'address); config_table.rdt_udp_port := 7654; config_table.rdt_initial_priority := system.priority'(5); end init; ...- 6 . Edit the package body realtime_debug_task to register a proper "passthru" handler routine. An example handler is supplied in realtime_debug_task.2.ada in the rdt_conf.ss view. Model your own passthru handlers after this example implementation. The passthru handler is registered in the elaboration code in the package.:
realtime_debug_task.2.ada: begin -- register pass_thru handler rdt_debug_task.register_passthru_callback (act'address); end realtime_debug_task;
- 7 . Compile TDM, TCP/IP and RDT.
- 8 . Link TDM and TCP/IP.
- 9 . Add an import to the rdt_conf.ss subsystem to your application library.
- 10 . Edit the main procedure of your application to include the RDT-support:
main_program.2.ada: with realtime_debug_task; -- include RDT procedure main_program is ... begin ... end;
- 11 . Compile and link your application.
Programmatic interface to the Real-time Debug Task
An application linked with the Realtime_Debug_Task can call the following routines to control the behavior of the RDT:
package Realtime_Debug_Task is -- Get the RDT priority -- function Get_Priority return System.Priority; -- Set the RDT priority -- procedure Set_Priority (Prio : System.Priority); -- Stop the real-time debug task -- procedure Stop; end Realtime_Debug_Task;
Since the RDT runs as a separate task that never terminates, the stop routine must be called if you want your application to terminate.
Troubleshooting
This section describes some problems that may occur when debugging using the minimal disturbance features of the debugger and suggestions on remedying the problems.
Start-up Time
Networking must be operational for realtime mode commands to function. Users must allow the target sufficient start-up time for the networking to initialize before issuing any realtime mode commands. In normal circumstances, users only need to wait a couple of seconds for the networking to initialize. In many cases, the networking is configured to print out a text message informing users that it is initialized. Once this message has been displayed, it is safe to start using the realtime mode debugging commands.
If networking is not running on the target, the realtime operations issued by the debugger will timeout. See the Enet Guide for more information on networking.
RDT Initialization Time-out Error Message
If a debugger operation in realtime mode times out, you may see a message like this:
=> Could not read address 0x2090c4 using RDT Reason: RDT timed out or dbiface could not connect to RDT === Could only read 0 out of 4 bytes from 02090c4 => Cannot read 4 bytes at addr: 02090c4 => trying to read 32-bit integer of type natural
There are a number of reasons to why this might happen, including:
- the application is not linked with realtime debug support
- the wrong communications port is used for the RDT traffic
- TCP/IP networking not running on the target
To determine the exact cause of the timeout, perform the following actions:
- 1 . If the application can be stopped, issue a user interrupt command and list the tasks with the lt command. Look for the Realtime_Debug_Task. If missing, the application needs to be relinked with the RDT to enable realtime debugging. See section Runtime Support Configuration for details.
- 2 . If the RDT is running, the most likely cause is a misconfiguration of the RDT port number. Check the value of APEX_RDT_SERVICE and compare it with the port number in v_rdt_conf.2.ada, located in the rdt_conf.ss subsystem.
- 3 . Check that you have configured the target for TCP/IP networking and also that you have downloaded the networking program. Fir information on networking, refer to the Using Enet with Rational Exec Guide
.Runtime Support Configuration
The configuration of the RDT is modeled on the same principles as the configuration of the TDM and the kernel. See the Configuring Rational Exec Guide for detailed information on configuring the kernel and TDM.
Configure the RDT using the following steps. This requires the network driver to be shared between TDM and TCP/IP:
1 This is the current implementation limit. It may change in future implementations.
- 1 . Determine the address where the shared session data between the TDM and RDT can be stored - this area is less than 64 bytes. You can use the check_config program to locate unallocated memory between the TDM, kernel, networking and the application.
- 2 . Since RDT is used, initialize a_tdm_session_data in v_net_conf.a. Do this by editing v_net_conf.2.ada as shown in the example below:
v_net_conf.2.ada: tdm_session_data: tdm_session.tdm_session_data_t; for tdm_session_data use at system.memory_address(16#1_FF00#); ... a_tdm_session_data => tdm_session.to_a_tdm_session_data_t( tdm_session_data'address ),- 3 . Edit the RDT configuration in rdt_conf.ss v_rdt_conf.2.ada to share the tdm_session_data at the same address as you used in v_net_conf.2.ada.
- 4 . Edit the TCP/IP application configuration in v_net_conf.2.ada found in the net_conf.ss subsystem:
a_tdm_session_data => null
- 5 . Enter the port that RDT will use to communicate by editing v_rdt_conf.2.ada in the rdt_conf.ss subsystem as shown in the example below. In the example we set the port to 7654 (which is the default value which the debugger will use to connect to the RDT):
v_rdt_conf.2.ada: procedure init is begin config_table.a_tdm_session_data:= tdm_session. to_a_tdm_session_data_t (system."+" (16#1_FF00#)); config_table.rdt_udp_port := 7654; config_table.rdt_initial_priority := system.priority'(5); end init;- 6 . Edit the package body realtime_debug_task to register a proper "passthru" handler routine. An example handler is supplied in realtime_debug_task.2.ada. Model your own passthru handlers after this example implementation. The passthru handler is registered in the elaboration code in the package.:
realtime_debug_task.2.ada: elaboration_part -- register pass_thru handler
- 7 . Compile TDM, TCP/IP and RDT.
- 8 . Link TDM and TCP/IP.
- 9 . Add an import to the rdt_conf.ss subsystem to your application library.
- 10 . Edit the main procedure of your application to include the RDT-support:
main_program.a: with realtime_debug_task; -- include RDT procedure main_program is ... begin ... end;
- 11 . Compile and link your application.
Rational Software Corporation http://www.rational.com support@rational.com techpubs@rational.com Copyright © 1993-2002, Rational Software Corporation. All rights reserved. |