Search code examples
pythonpython-3.xtrace32lauterbach

How to print variable from Multi core Trace32 with Python command


I want to get both static variables and local variable from a function in trace32 with python script. I have got some useful reference from trace32 site with python script. with below documents, I have written some script to control the trace32 with python remote API's.

https://www2.lauterbach.com/pdf/app_python.pdf

https://www2.lauterbach.com/pdf/general_ref_s.pdf

Now in my environment, I have two core. One is master and other is slave. The slave is configured as Intercom. Below is the script I have written with the help of the above docs.

Code example:

Static int totalcount = 15U;

static void test_main (void)
{
   int temp = 0U;
   temp = get_result(); /* it will return some values*/
   totalcount = totalcount + temp;
}

Script:

import time
import ctypes # module for C data types
from ctypes import c_void_p
import enum # module for enumeration support

# Load TRACE32 Remote API DLL
t32api = ctypes.cdll.LoadLibrary('D:/demo/api/python/t32api64.dll')
# TRACE32 Debugger or TRACE32 Instruction Set Simulator as debug device
T32_DEV = 1

# Configure communication channel to the TRACE32 device
# use b for byte encoding of strings
t32api.T32_Config(b"NODE=",b"localhost")
t32api.T32_Config(b"PORT=",b"20000")
t32api.T32_Config(b"PACKLEN=",b"1024")

# Establish communication channel
rc = t32api.T32_Init()
rc = t32api.T32_Attach(T32_DEV)
# Ping to master core
rc = t32api.T32_Ping()
time.sleep(2)

# Break the slave core -> Name is mycore
rc = t32api.T32_Cmd(b"InterCom mycore Break")
time.sleep(3)
rc = t32api.T32_Cmd(b"InterCom mycore Go")
time.sleep(2)
rc = t32api.T32_Cmd(b"InterCom mycore break.Set test_main")
time.sleep(2)

#Print the variable 
error =  ctypes.c_int32(0)
result =  ctypes.c_int32(0)

t32api.T32_Cmd (b"InterCom mycore Var totalcount")
error = t32api.T32_EvalGet(ctypes.byref(result));
if (error == 0):
    print("OK");
    print (result.value)
else:
    print("Nok error")


# Release communication channel
rc = t32api.T32_Exit()
print ("Exit") 

I can able to communicate with slave using the python API t32api.T32_Cmd and it was successful. But the problem here, I didn't get the actual value of the static variable. It is printing like below

output:

$ python test.py
Ok
c_long(0)
Exit

Here I am getting result as c_long(0). If I am converting to result.value also, then value is 0.

Seems like t32api is not getting the variable output using t32api.T32_EvalGet()function. t32api still in the master core only.

I would like to know how to get the actual values of the variable using Python API. Can anybody suggest the solution ?


Solution

  • T32_EvalGet() returns the value as the EVAL() function would do. For it to work you first must load the value by using Eval <expression>, or if you want to query another GUI InterCom.Evaluate <instance> <expression>. To get the value of an integer variable you can use Var.VALUE(<hll_expression>).

    So your code would change to

    error = ctypes.c_int32(0)
    result = ctypes.c_int32(0)
    t32api.T32_Cmd(b"InterCom.Evaluate mycore Var.VALUE(totalcount)")
    error = t32api.T32_EvalGet(ctypes.byref(result));
    

    Note that you are doing all operations through the first GUI. It's also possible to query the second GUI directly using the Remote API.

    You can open another channel to the other GUI by changing your code to

    // create channel for master GUI
    channel_master = ctypes.c_void_p(0)
    t32api.T32_RequestChannelNetAssist(ctypes.byref(channel_master))
    t32api.T32_SetChannel(channel_master)
    
    t32api.T32_Config(b"NODE=", b"localhost")
    t32api.T32_Config(b"PORT=", b"20000")
    t32api.T32_Config(b"PACKLEN=", b"1024")
    
    rc = t32api.T32_Init()
    rc = t32api.T32_Attach(T32_DEV)
    
    // create channel for slave GUI
    channel_slave = ctypes.c_void_p(0)
    t32api.T32_RequestChannelNetAssist(ctypes.byref(channel_slave))
    t32api.T32_SetChannel(channel_slave)
    
    t32api.T32_Config(b"NODE=", b"localhost")
    t32api.T32_Config(b"PORT=", b"20001")  // note the 20001 here
    t32api.T32_Config(b"PACKLEN=", b"1024")
    
    rc = t32api.T32_Init()
    rc = t32api.T32_Attach(T32_DEV)
    

    The query would then change to

    t32api.T32_SetChannel(channel_slave)
    
    error = ctypes.c_int32(0)
    result = ctypes.c_int32(0)
    t32api.T32_Cmd(b"Eval Var.VALUE(totalcount)")
    error = t32api.T32_EvalGet(ctypes.byref(result));
    

    Assuming the GUI has port 20001. T32_SetChannel() is used to switch between the channels.


    I'd also like to draw your attention to the pyrcl package, which removes the need to work with ctypes. For example working with multiple GUIs, the code for reading totalcount both from master and slave would be:

    import lauterbach.trace32.rcl as t32
    
    dbg_master = t32.connect(port=20000)
    dbg_slave = t32.connect(port=20001)
    
    totalcount_master = dbg_master.fnc("Var.VALUE(totalcount)")
    totalcount_slave = dbg_slave.fnc("Var.VALUE(totalcount)")