Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

DecodingBiosLogs

From Texas Instruments Wiki
Jump to: navigation, search

Decoding BIOS5 LOG Data outside of CCS

Introduction

In some systems it may be useful to acquire BIOS LOG data from the target, and upload it to a host PC, where it can be saved to a file and then viewed. Since data in the LOG buffers is not in a format that can be easily interpreted as is, it is helpful to have a program to decode the LOG data and print it out in a readable format. Here we will give an example of how to do this.

Getting the LOG Data from the Target

The log data for a given LOG is located at the address logname$buf, where logname is the name of the LOG in the configuration file. The size of the LOG data buffer is given by logname$size. You can look in the map file of your program to see the values of these symbols. For example, you might see the symbols, LOG_system$buf, LOG_system$size, trace$buf, and trace$size in your target program's map file. These symbols are not accessible from C code, though, so you would not be able to use them in target code. However, you can get the LOG object’s buffer address and size from C code, by looking at the fields of the LOG_Obj structure :

typedef struct LOG_Obj {
    Arg* bufend;
    Uns flag;
    Uns seqnum;
    LOG_Event* curptr;
    Uns lenmask;
    LOG_Event* bufbeg;
} LOG_Obj;

The field bufbeg contains the LOG’s buffer address. Since the actual length of the buffer is not stored in the LOG_Obj structure, you need to take the lenmask and add 1 to it. This will give you the length of the buffer in target MAUs.

As an example, this code will print out the address and size of the buffer for the trace LOG:

LOG_printf(&trace, "trace buffer address = 0x%x, size = 0x%x",
        trace.bufbeg, trace.lenmask + 1);

This works fine if you know the specific LOGs that you want to upload. However, you may want to write a more generic function that uploads buffers for all the LOGs on the target and works regardless of the LOG names. This is possible, since all LOG objects are stored in a table. The beginning of the table is at the address LOG_A_TABBBEG, and the number of LOG objects is given by LOG_A_TABLEN. The following C code will print out the location and size of the LOG_Obj table:

extern far Int LOG_A_TABBEG;
extern far Int LOG_A_TABLEN;
 
LOG_printf(&trace, "LOG_A_TABBEG = 0x%x, LOG_A_TABLEN = 0x%x",
        &LOG_A_TABBEG, &LOG_A_TABLEN);

The following C code will iterate through the LOG table, printing out the address and size of the LOG buffers:

extern far Int LOG_A_TABBEG;
extern far Int LOG_A_TABLEN;
 
/*
 *  ======== main ========
 */
Void main()
{
    Int     i;
    Int     logTabLen = (Int)&LOG_A_TABLEN;
    LOG_Obj *log;
 
    log = (LOG_Obj *)&LOG_A_TABBEG;
    for (i = 0; i < logTabLen; i++) {
        LOG_printf(&trace, "LOG buffer address: 0x%x, size: 0x%x",
                log->bufbeg, log->lenmask + 1);
        log++;
    }
}

For our LOG decoder example, we built the BIOS tsk example for the evm6478, and ran it on the C6748 simulator. We used a Code Composer Studio DS (Debug Server) script to upload the LOG data in the following format:

Format of LOG Data Sent to Host PC
Word Description
0 LOG index
size0 Size of LOG 0 in target MAUs
data[0] First word of LOG 0 data
... ...
data[size0 / 4 - 1] Last word of LOG 0 data
1 LOG index
size1 Size of LOG 1 in target MAUs
data[0] First word of LOG 1 data
... ...
data[size1 / 4 - 1] Last word of LOG 1 data
... ...
-1 LOG index of -1 and LOG size of 0 terminates data
0


The format that we choose to send the data to the host PC is arbitrary, as long as it agrees with the host program used to interpret the data. Since we are working with a C6000 target, we chose the size of each element in the table above to be 32 bits. We also chose to handle byte swapping in the DS script, although this could also have been done in the LOG decoder.

Note: We loaded the script in CCS v5 by opening the Scripting Console Window (Window -> Show View -> Scripting Console), and running loadJSFile(), passing the name of the script.

Decoding LOG Data on the Host PC

In order to decode the LOG data obtained from the target, we need to know the format of the data and the meaning of the system LOG event Ids. In addition, we need to know if the LOGs are of the “time-stamped” type, where LOG events consist of eight words instead of four words.

The following table describes how the 4 words of a LOG event (8 words for time-stamped logging) should be interpreted for system, printf, and raw LOGs. For system LOGs, the interpretation should also take into account the type of system event, ie, a thread event, such as SWI_post, a system tick event (eg, PRD_TICK), or a USER event (resulting from LOG_message() or LOG_error()).
Note: This table is valid for 32-bit targets only, such as C6000.

LOG Record Format
LOG type
system printf raw
USER event eg,
LOG_message
Thread event
eg, SWI_post
System tick
eg, PRD_tick
word 0 seqNum /* Sequence number - increments by 2 */
word 1 arg0 arg0 ticks arg0 arg0
word 2 format handle arg0 /* not used */ arg1 arg1
word 2 eventId format arg2
word 4 pad0 arg2 arg3
word 5 pad1 arg3 arg4
word 6 lowTimeStamp   /* Low 32 bits of timestamp */
word 6 highTimeStamp /* High 32 bits of timestamp */


Event Ids for system LOGs are defined in the table below. (The names of the events are intended to match the names in the logdecode.c file attached).

System LOG Event Ids
Event Id Event Name Args Description Event Type
0 _LOG_PRDBEGIN handle = prd, arg0 = unused Thread
1 _LOG_PRDEND handle = 0, arg0 = unused Thread
2 _LOG_SWIPOST handle = swi, arg0 = unused Thread
3 _LOG_SWIBEGIN handle = swi, arg0 = unused Thread
4 _LOG_SWIEND handle = swi, arg0 = unused Thread
5 _LOG_PRDTICK tick = PRD_D_tick, arg0 = unused System tick
6 _LOG_CLKINT tick = CLK_R_time, arg0 = unused System tick
7 _LOG_HWIBEGIN handle = hwi, arg0 = unused Thread
8 _LOG_USRMSG format, arg0 User
9 _LOG_USRERR format, arg0 User
10 _LOG_TSKBLOCKED handle = tsk, arg0 = unused Thread
11 _LOG_TSKDONE handle = tsk, arg0 = unused Thread
12 _LOG_TSKRUNNING handle = tsk, arg0 = unused Thread
13 _LOG_TSKREADY handle = tsk, arg0 = unused Thread
14 _LOG_SEMPOST handle = sem, arg0 = sem count Thread
15 _LOG_TSKYIELD handle = tsk, arg0 = unused Thread
16 _LOG_PWRMRSRCCHNG arg0 = id, arg1 = 0 (off) or 1 (on) ---


The LOG Decode Program

The example LOG decode program takes a COFF file and the binary file of LOG data as arguments. The COFF file is parsed to get information about the LOGs needed to output the data, such as whether or not they are time-stamped, and the name and type of each LOG (system, printf, or raw). The ".const" section is also read, since it contains the format strings of printf LOGs. All code necessary to build the program on a Linux PC is attached in a zip file.

To build the program on a Linux PC, unzip the attached file to a directory on the PC. Edit the makefile to set the path to the Linux codegen tools. Then run 'gmake'.

To run the program on the sample data provided, type

 ./bin/logdecode.x86U prog.out prog.dat

or

 ./bin/logdecode.x86U prog8.out prog8.dat

List of Example Files

  • logdecode.c - The main decode program.
  • cof.c, cof.h, _cof.h, cof_std.c, cof_syms.c - COFF parsing functions and header files.
  • std.h - A header file containing standard types.
  • makefile - A Linux makefile to build the program.
  • prog8.out, prog8.dat - Sample COFF file and LOG data file with timestamped LOGs.
  • prog.out, prog.dat - Sample COFF file and LOG data file with non-timestamped LOGs.
  • log.txt, log8.txt - Sample output for the non-timestamped and timestamped examples.

Example Download

The example Code Composer Studio DS script for dumping LOG data into a binary file can be downloaded here: File:DSPBIOS LogDecodeExample LogDump.zip The example Linux application for decoding the LOG data can be downloaded here: File:DSPBIOS LogDecodeExample LogDecode.zip