LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

通过Python+CRemoteAPI控制Trace32进行调试

关键词:Python、C Remote API、Trace32等等。

当需要对Trace32调试进行自动化,或者提高效率时,可以通过Remote Control API进行。

基本的调试流程如下:

Python、C等语言可以通过调用C Remote API库文件,和Trace32 PowerView基于Socket通信,进行Trace32调试工作。模拟了Trace32 PowerView下的操作。

1 配置Trace32支持Socket Remote Control

1. 修改C:\T32\config.t32文件,增加两个空白行

2. 在Trace32 Start中找到一个连接,选择PowerView Instance->Advanced Settings->Interfaces->API Port->Use Port选择Yes。

3. 在T32的temp指定目录里,查看T32_xxxxxx.t32,出现了API访问相关配置:

参考《API for Remote Control and JTAG Access》的Preparing Trace32 Software。

2 Remote Control API

2.1 API内容

API包含两个C文件,一个头文件:

  • hlinknet.c-处理跟Trace32调试软件的Socket接口工作。
  • hremote.c-API接口函数的实现。
  • t32.h-API文件件。

2.2 编写基于Remote Control API接口的C程序

包含头文件t32.h,将库连接到可执行文件中即可。

如果需要记录API函数调用轨迹,在编译时需要打开ENABLE_APILOG,增加

-DENABLE_APILOG

在运行时,增加环境变量:

set T32APILOGFILE=C:\temp\t32apilog.txt

则会将调用函数轨迹输出到log文件中。

更多参考:C:\T32\demo\api\capi\test。

2.3 API列表

t32.h中包含了所有API函数:

T32EXTERN int  T32_Errno;
T32EXTERN int  T32_Config(const char *String1, const char *String2);
T32EXTERN int  T32_Init(void);
T32EXTERN int  T32_Attach(int DeviceSpecifier);
T32EXTERN int  T32_Terminate(int ShellReturnValue);
T32EXTERN int  T32_Exit(void);
T32EXTERN int  T32_Ping(void);
T32EXTERN int  T32_Nop(void);
T32EXTERN int  T32_NopEx(int length, int options);
T32EXTERN int  T32_NopFail(void);
T32EXTERN int  T32_Cmd(const char *Command);
T32EXTERN int  T32_Cmd_f(const char *command, ...) ATTRIBUTE_PRINTF(1, 2);
T32EXTERN int  T32_CmdWin(uint32_t WindowHandle, const char *Command);
T32EXTERN int  T32_Printf(const char *str, ...) ATTRIBUTE_PRINTF(1, 2);
T32EXTERN int  T32_Stop(void);
T32EXTERN int  T32_GetPracticeState(int *pPracticeState);
T32EXTERN int  T32_EvalGet(uint32_t *pEvaluationResult);
T32EXTERN int  T32_EvalGetString(char *EvaluationString);
T32EXTERN int  T32_GetMessage(char *AreaMessage, uint16_t *pMessageType);
T32EXTERN int  T32_GetTriggerMessage(char *TriggerMessage);
T32EXTERN int  T32_GetChannelSize(void);
T32EXTERN void T32_GetChannelDefaults(void *ParametersOut);
T32EXTERN void T32_SetChannel(void *ParametersIn);
T32EXTERN int  T32_APILock(int nTimeoutMS);                                                                                               /* preliminary*/
T32EXTERN int  T32_APIUnlock(void);
T32EXTERN int  T32_GetApiRevision(uint32_t* pRevNum);
T32EXTERN void T32_GetSocketHandle(int *t32soc);

T32EXTERN int  T32_Go(void);
T32EXTERN int  T32_Break(void);
T32EXTERN int  T32_Step(void);
T32EXTERN int  T32_StepMode(int Mode);
T32EXTERN int  T32_ResetCPU(void);
T32EXTERN int  T32_SetMode(int Mode);
T32EXTERN int  T32_GetCpuInfo(char **pCPUString, uint16_t *pFPUType, uint16_t *pEndianess, uint16_t *pReserved);
T32EXTERN int  T32_GetState(int *pSystemState);
T32EXTERN int  T32_ReadMemory     (uint32_t Address, int Access, uint8_t *pBuffer, int Size);
T32EXTERN int  T32_WriteMemory    (uint32_t Address, int Access, const uint8_t *pBuffer, int Size);
T32EXTERN int  T32_WriteMemoryPipe(uint32_t Address, int Access, const uint8_t *pBuffer, int Size);
T32EXTERN int  T32_ReadMemoryEx   (uint32_t Address, int Segment, int Access, int Attribute, uint8_t *pBuffer, int Size);                 /*undocumented*/
T32EXTERN int  T32_WriteMemoryEx  (uint32_t Address, int Segment, int Access, int Attribute, uint8_t *pBuffer, int Size);                 /*undocumented*/
T32EXTERN int  T32_SetMemoryAccessClass(const char* Access);
T32EXTERN int  T32_GetRam(uint32_t *pStartAddress, uint32_t *pEndAddress, uint16_t *pAccess);
T32EXTERN int  T32_GetSource(uint32_t Address, char *SourceFile, uint32_t *pSourceLine);
T32EXTERN int  T32_GetSelectedSource(          char *SourceFile, uint32_t *pSourceLine);
T32EXTERN int  T32_GetSymbol(const char *SymbolName, uint32_t *pAddress, uint32_t *pSize, uint32_t *pAccess);
T32EXTERN int  T32_GetSymbolFromAddress (char* SymbolName, uint32_t Address, int StringLength);
T32EXTERN int  T32_ReadVariableString(const char *VariableName, char *StringFromNumeric, int StringLength);
T32EXTERN int  T32_ReadVariableValue (const char *VariableName, uint32_t *pValueLower32Bit, uint32_t *pValueUpper32Bit);
T32EXTERN int  T32_WriteVariableValue (const char *VariableName, uint32_t ValueLower32Bit, uint32_t ValueUpper32Bit);
T32EXTERN int  T32_GetWindowContent(const char *command, char * buffer, uint32_t requested, uint32_t offset, uint32_t print_code);
T32EXTERN int  T32_ReadRegisterByName (const char *RegisterName, uint32_t *pValueLower32Bit, uint32_t *pValueUpper32Bit);
T32EXTERN int  T32_WriteRegisterByName(const char *RegisterName, uint32_t ValueLower32Bit, uint32_t ValueUpper32Bit);
T32EXTERN int  T32_ReadPP(uint32_t *pProgramCounter);
T32EXTERN int  T32_ReadRegister (uint32_t MaskLower32Bit, uint32_t MaskUpper32Bit, uint32_t *pBuffer);
T32EXTERN int  T32_WriteRegister(uint32_t MaskLower32Bit, uint32_t MaskUpper32Bit, uint32_t *pBuffer);
T32EXTERN int  T32_ReadBreakpoint (uint32_t Address, int Access, uint16_t *pBPConfiguration, int Size);
T32EXTERN int  T32_WriteBreakpoint(uint32_t Address, int Access, int        BPConfiguration, int Size);
T32EXTERN int  T32_GetBreakpointList(int *pNumberFetched, T32_Breakpoint *pBPSettings, int FetchLimit);
T32EXTERN int  T32_GetTraceState(int TraceType, int *pTraceState, int32_t *pTraceTotalRecords, int32_t *pCurrentRecordMin, int32_t *pCurrentRecordMax);
T32EXTERN int  T32_ReadTrace    (int TraceType, int32_t StartRecord, int NumberOfRecords, uint32_t Mask, uint8_t *pBuffer);
T32EXTERN int  T32_GetLastErrorMessage(char *ErrorMessage, uint32_t* pLastError, uint32_t* pInternal);
# ifdef ENABLE_NOTIFICATION
typedef void (*T32_NotificationCallback_t)();
T32EXTERN int T32_NotifyStateEnable(int EventNumber, T32_NotificationCallback_t pFunction);
T32EXTERN int T32_NotifyEventEnable(const char* event, T32_NotificationCallback_t pFunction);
T32EXTERN int T32_CheckStateNotify(unsigned ParameterOfCallbackFunction);

参考:API Functions,包括错误码、每个函数描述以及和多个Trace32联调。

3 Python+t32api.so/t32api.dll进行调试

在C:\T32\demo\api\python中提供了Python所需要使用的库,以及Python脚本。

其中库:

  • t32api.dll - 32/64位Windows适用。
  • t32api64.dll - 64位Windows适用。
  • t32api.so - 32/64位Linux适用。
  • t32api64.so - 64位Linux使用。

Python脚本:

  • t32api.py - 简单的使用Remote Control演示。
  • t32apicmd.py - 使用T32_Cmd()和T32_GetMessage()执行命令获取结果。
  • t32remotedo.py - 执行一个PRACTICE脚本。
  • t32apimenu.py -  较丰富的Remote Control API演示。

以最简单的t32api.py为例:

#!/usr/bin/python
# -*- coding: latin-1 -*-
import platform--获取操作系统细信息。
import ctypes--提供了与C语言兼容的数据类型,允许调用DLL/SO共享库中的函数。

# auto-detect the correct library
if (platform.system()=='Windows') or (platform.system()[0:6]=='CYGWIN') :--获取操作系统类型,根据操作系统类型加载不同的C Remote Control库。
  if ctypes.sizeof(ctypes.c_voidp)==4:
    # WINDOWS 32bit
    t32api = ctypes.CDLL("./t32api.dll")
    # alternative using windows DLL search order:
#   t32api = ctypes.cdll.t32api
  else:
    # WINDOWS 64bit
    t32api = ctypes.CDLL("./t32api64.dll")
    # alternative using windows DLL search order:
#   t32api = ctypes.cdll.t32api64
elif platform.system()=='Darwin' :
  # Mac OS X
  t32api = ctypes.CDLL("./t32api.dylib")
else :
  if ctypes.sizeof(ctypes.c_voidp)==4:
    # Linux 32bit
    t32api = ctypes.CDLL("./t32api.so")
  else:
    # Linux 64bit
    t32api = ctypes.CDLL("./t32api64.so")

t32api.T32_Config(b"NODE=",b"localhost")--调用C库中T32_Config对连接进行配置。
t32api.T32_Config(b"PORT=",b"20000")
t32api.T32_Config(b"PACKLEN=",b"1024")

t32api.T32_Init()--初始化,并建立和Trace32 PowerView的Socket连接。
t32api.T32_Attach(1)--附着到Trace32,一般选择T32_DEC_ICD支持的命令更丰富。
t32api.T32_Ping()--测试和Trace32的连通。

t32api.T32_Cmd(b"AREA")--执行一个Trace32命令。

t32api.T32_Exit()--断开和Trace32的连接。

4 连接多个Trace32 PowerView

API没有Socket通信通道的参数,这里提供了几个函数用于切换到不同的Socket:

  • T32_GetChannelSize():获取一个Channel结构体大小,用于后续创建Channel。
  • T32_GetChannelDefaults():获取默认Channel参数。
  • T32_SetChannel():设置活跃Channel。

首先T32_GetChannelSize()获取Channel结构体大小,分配内存;然后T32_GetChannelDefaults()填充默认Channel参数;T32_SetChannel()设置活跃参数,之后调用API建立Socket连接,发送命令进行处理。

示例:

void* channel_1 = malloc (T32_GetChannelSize());
void* channel_2 = malloc (T32_GetChannelSize());
T32_GetChannelDefaults (channel_1);
T32_GetChannelDefaults (channel_2);
T32_SetChannel (channel_1);
T32_Config ("PORT=", "20000");--设置channel_1对应的Socket连接。此后发送的命令都会通过端口20000发送。
T32_Init ();
T32_Attach (T32_DEV_ICE);
T32_SetChannel (channel_2);
T32_Config (
"PORT=", "20002");--设置channel_2对应的Socket连接。此后发送的命令都会通过端口20002发送。
T32_Init ();
T32_Attach (T32_DEV_ICE);

posted on 2023-03-18 23:59  ArnoldLu  阅读(842)  评论(0编辑  收藏  举报

导航