ROV Module Writers Guide/Processing Data

From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  offline version generated on 18-Nov-2017 00:11 UTC  

ROV Module Writers Guide/Processing Data

Retrieving and processing target data


Retrieving Other Target Data

The state object passed to the view functions only contains the data in the structure; ROV does not automatically follow any pointers when decoding the structure. Any references to data outside the structure, such as arrays, strings, or pointers to other structures, will be represented simply by their address.

Retrieving the actual data associated with these pointers is done using special functions provided by ROV through the xdc.rov.Program module.

Below are the Program APIs. The return types 'Instance_View' and 'Module_View' are not actual types, these are just used to indicate that the API returns an instance view structure or a module view structure.

xdc.rov.Program interface
Object fetchStruct(FetchDesc desc, Ptr addr);
Array fetchArray(FetchDesc desc, Ptr addr, Int len);
String fetchString(Ptr addr);
Instance_View[] scanInstanceView(String modName, String tabName);
Module_View scanModuleView(String modName, String tabName); 
RawView scanRawView(String modName);
Instance_View scanHandleView(String modName, Ptr instAddr, String tabName);
Instance_View scanObjectView(String modName, Any obj, String tabName);

There are two classes of xdc.rov.Program APIs which retrieve data from the target. 'scan' APIs such as scanInstanceView() and scanModuleView() run view initialization code and return view structures. 'fetch' APIs such as fetchStruct() and fetchArray() retrieve arbitrary data from the target.

Documentation for these APIs can be found with xdc.rov.Program, and examples can be found in part two of this guide.

'fetch' Functions - Fetching raw data

In order to fetch data from the target, ROV must know the data's type in order to know how many bytes to read as well as how to properly decode the raw data. As a result, the Program.fetchStruct() and Program.fetchArray() functions take as their first parameter a 'FetchDescriptor' object which gives ROV information about the type of the data to be fetched.

A fetch descriptor object is automatically generated for every reference-type field in a module's state structures. These generated objects hang off the state objects passed to the view functions and always have a name of the form fieldName$fetchDesc.

For example, an instance state structure with the fields declared below will have the generated fields 'obj.arr$fetchDesc' and 'obj.sptr$fetchDesc'.

Instance_State structure example
struct Instance_State {
    Char      arr[ ]; // An array
    MyStruct *sptr;   // A pointer to a structure.

These generated fields can be used in their respective fetch functions as follows:

Instance_State usage example
function viewInitBasic(obj, view) {
    var arr = Program.fetchArray(obj.arr$fetchDesc, obj.arr, len);
    var myStruct = Program.fetchStruct(obj.sptr$fetchDesc, obj.sptr);

'scan' Functions - Using data from other modules or instances

The data displayed in one module's view will often depend on data from another module. View init code may access the raw state of other modules, or it may access the views of other modules. Accessing the raw state of another module is discouraged since this does not provide any support for data validation and internal implementation changes in this module will likely break your interpretation of its state. To be safe, retrieve data from other modules only using their views.

Retrieving a particular view from a module is done using one of four 'scan' APIs that are a part of the Program module. The scan APIs are:

scan APIs
Instance_View[] scanInstanceView(String modName, String tabName);
Module_View scanModuleView(String modName, String tabName); 
Instance_View scanHandleView(String modName, Ptr instAddr, String tabName);
Instance_View scanObjectView(String modName, Any obj, String tabName);

These APIs are documented in the Program module. 'scanModuleView' is used to scan a module-level view, and 'scanInstanceView' is used to scan an instance-level view. Calling scanInstanceView will process the requested view for every instance of that module, and return an array of views. In contrast, 'scanHandleView' takes a handle to an instance, and scans only that instance.

The fourth API, 'scanObjectView' has a more advanced use case. It is used to scan an instance that is embedded within another object. That is, it is used when a state structure doesn't contain a handle to another instance but actually has the other instance allocated within it.

Calling Program.scanObjectView will not read any additional data from the target, since the state structure was already read as part of reading its parent structure.

There is an additional scan API for retrieving the raw state of another module, 'scanRawView'.

RawView scanRawView(String modName);

The scanRawView returns a structure defined in xdc.rov.Program which contains the module state as well as an array of instance state structures.

Sharing data across views

Modules may have data which needs to be referenced by multiple views supported by the module. This can be accomplished using the Program.getPrivateData() API, which returns an arbitrary JavaScript object. Any data can be attached to this object and shared across views. There is one of these objects per module, and the objects are reset whenever the ROV model is reset (such as every time the target is run and halted).

Module private data example
var data = Program.getPrivateData("ModA");
if (data.sharedData === undefined) {
    data.sharedData = ... // retrieve the data from the target
// Go on to use the shared data...

Data Validation and Reporting Errors

If while processing a view you discover that some of the target data is corrupted and holds incorrect or impossible values, you can report this to the ROV user as an error message.

ROV allows you to associate an error string with each individual field in a view. In the ROV GUI, if a field has an error string associated with it, that field will have its background set to red, and the error string will appear as a tooltip message if the user hovers their mouse over the field.

To specify an error string, use the Program.displayError API, passing it the view structure, the name of the field to display the error in, and the error message to display. If there is a problem with a view structure field named 'priority', for example:

error string example
Program.displayError(view, "priority", "Corrupted state: The value of 'priority' is greater than 'maxPriority'.");

Writing Robust View Code

When retrieving data from the target, it is important to appreciate that there may be problems with the data due to a target's corrupted state. Since ROV is often used as a debugging tool on a corrupted system, it is important that ROV handle errors as gracefully as possible, while still providing helpful information to the ROV user.

All of the 'Program.fetch...' and 'Program.scan...' APIs will intentionally throw an exception if they encounter a problem. The purpose of throwing these exceptions is so that bad data will not be operated on in the view code. This way, if the exception is not caught, the view function will exit before operating on the bad data.

The 'Program.fetch...' APIs will throw an exception if there was a problem reading memory, such as a bad address. The 'Program.scan...' APIs will throw an exception if there are any errors reported in the $status fields for the returned view. All other Program APIs should not throw any exceptions.

It is important, then, to surround all calls to 'fetch' and 'scan' APIs with try / catch blocks, so that any errors can be handled and reported intelligently. ROV will not crash if these exceptions are not caught, but the user will have less information to work with.

When an exception is caught, it is recommended that you report an error with the field you were processing to the user, and include the message from the exception.

For example, when scanning a Handle to an instance:

try/catch example
try {
    var inst = Program.scanHandle('Task', pendElem.task, 'Basic');
catch (e) {
    Program.displayError(view, "taskLabel", e);

See also

xdc.rov.Program Client documentation for xdc.rov.Program
xdc.rov.ViewInfo Client documentation for xdc.rov.ViewInfo

Personal tools
package reference