LPT26x-HSF-4MB-Hilink_14.2..../build/script/parse_tool/parse_freertos.py

464 lines
18 KiB
Python
Raw Normal View History

2025-05-13 22:00:58 +08:00
#!/usr/bin/env python
# coding:utf-8
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2023. All rights reserved.
import sys,string,re,os
from ctypes import *
from parse_basic import *
from auto_class import *
from config import *
OS_TASK_STATUS_UNUSED = 0x0001
OS_TASK_STATUS_SUSPEND = 0x0002
OS_TASK_STATUS_READY = 0x0004
OS_TASK_STATUS_PEND = 0x0008
OS_TASK_STATUS_RUNNING = 0x0010
OS_TASK_STATUS_DELAY = 0x0020
OS_TASK_STATUS_TIMEOUT = 0x0040
OS_TASK_STATUS_PEND_TIME = 0x0080
OS_TASK_FLAG_DETACHED = 0x0001
OS_TASK_FLAG_SYSTEM = 0x0002
OS_SWTMR_STATUS_UNUSED = 0
OS_SWTMR_STATUS_DELETING =1
OS_SWTMR_STATUS_CREATED=2
OS_SWTMR_STATUS_TICKING=3
queueQUEUE_TYPE_BASE=0
queueQUEUE_TYPE_SET=0
queueQUEUE_TYPE_MUTEX=1
queueQUEUE_TYPE_COUNTING_SEMAPHORE=2
queueQUEUE_TYPE_BINARY_SEMAPHORE=3
queueQUEUE_TYPE_RECURSIVE_MUTEX=4
CONTEXT_OFFSET=4 * 4 + 33 * 4
#ctypes.addressof(parameter) - ctypes.addressof(parent_structure)
def _los_List_get_all_node(list_addr):
node_list=[]
node=parse_memory_2_class(list_addr,LOS_DL_LIST,sizeof(LOS_DL_LIST))
while node.pstNext!=list_addr:
node_list.append(node.pstNext)
node = parse_memory_2_class(node.pstNext,LOS_DL_LIST,sizeof(LOS_DL_LIST))
return (DEFINE_SUCCESS,node_list)
def _addr_in_2_function_name(addr):
name=parse_addr_in_2_function_name(addr)
if name==None:
return hex(addr)
else:
return name
class _PhaseFreertosCtrl:
def __init__(self):
self.core=None
self.info_fd = sys.__stdout__
self.task_cnt=None
self.tcb_array = []
self.ext_task_list=[]
self.ext_taskstatus_list=[] ##freertos
self.heap_start = None
self.heap_end = None
self.heap_head = None
self.queue_cnt = configQUEUE_REGISTRY_SIZE
self.queue_array=[]
self.queue_ext_info=[]
self.timer_cnt = 0
self.timer_array=[]
self.timer_ext_info=[]
#self.sem_cnt=LOSCFG_BASE_IPC_SEM_LIMIT
#self.sem_array=[]
self.sem_ext_info=[]
self.excInfo=None
self.isr_ext_info=None
class _ExtPercpu:
def __init__(self):
self.handle_addr = None
self.per_cpu=None
self.g_tickCount=None
self.g_sysClock=None
self.g_tickPerSecond=None
self.g_cycle2NsScale=None
self.task_wait_addr=[]
self.timer_wait_addr=[]
self.g_intCount=None
class _ExtTaskInfo:
def __init__(self):
self.handle_addr=None
self.pend_addr=None
self.name='unknown'
self.buttom=0
self.peek_used=0
self.over=0
self.status_str=None
self.enter_name = 'unknown'
self.task_context = None
self.take_sem = None
class _ExtTaskStatus:
def __init__(self):
self.xHandle=None
self.pcTaskName='unknown'
self.xTaskNumber=0
self.eCurrentState=0
self.uxCurrentPriority=0
self.uxBasePriority=0
self.ulRunTimeCounter=0
self.pxStackBase = None
self.usStackHighWaterMark = 0
class _ExtTimerInfo:
def __init__(self):
self.handle_addr=None
self.func_name=None
class _ExtSemInfo:
def __init__(self):
self.handle_addr=None
self.pend_task_list=[]
class _ExtQueueInfo:
def __init__(self):
self.handle_addr=None
self.pend_read_task_list = []
self.pend_write_task_list =[]
class ExtIsrInfo:
def __init__(self):
self.isr_cnt = configHWI_MAX_VECTOR_CNT
self.pxAddr=None
self.pxHwiHandles_list = []
def make_isr_info(self):
self.isr_ext_info = self.ExtIsrInfo()
addr = parse_get_symbol_addr('pxHwiHandles')
self.isr_ext_info.pxAddr = parse_memory_2_class(addr,(uint32_t)*self.isr_ext_info.isr_cnt,sizeof((uint32_t)*self.isr_ext_info.isr_cnt))
for temp_addr in self.isr_ext_info.pxAddr:
if temp_addr!=0:
pxHwiHandles = parse_memory_2_class(temp_addr, HwiHandle_t, sizeof(HwiHandle_t))
self.isr_ext_info.pxHwiHandles_list.append(pxHwiHandles)
def print_isr_info(self):
print("\r\n---------------------content of 中断信息:---------------------",file=self.info_fd)
for hwi in self.isr_ext_info.pxHwiHandles_list:
if hwi.pxCb!=0 or hwi.xCounts!=0:
print("%s[0x%x][call_cnt=%d]"%(_addr_in_2_function_name(hwi.pxCb),hwi.pxCb,hwi.xCounts),file=self.info_fd)
print("",file=self.info_fd)
def _make_task_info(self,pxList):
pxCurrentTCB = parse_get_symbol_addr('pxCurrentTCB')
if pxList.uxNumberOfItems > 0:
num = 0
while num < pxList.uxNumberOfItems:
next_item = parse_memory_2_class(pxList.pxIndex, ListItem_t, sizeof(ListItem_t))
if not next_item:
break
pxList.pxIndex = next_item.pxNext
pxTCB = parse_memory_2_class(next_item.pvOwner, TCB_t, sizeof(TCB_t))
if pxTCB:
taskstatus = self._ExtTaskStatus()
taskstatus.xHandle = next_item.pvOwner
taskstatus.pcTaskName = pxTCB.pcTaskName
taskstatus.xTaskNumber = pxTCB.uxTCBNumber
if (next_item.pvOwner == pxCurrentTCB):
taskstatus.eCurrentState = 0
else:
taskstatus.eCurrentState = 1
taskstatus.uxCurrentPriority = pxTCB.uxPriority
taskstatus.uxBasePriority = pxTCB.uxBasePriority
#taskstatus.ulRunTimeCounter = pxTCB.ulRunTimeCounter
taskstatus.pxStackBase = pxTCB.pxStack
self.ext_taskstatus_list.append(taskstatus)
self.tcb_array.append(pxTCB)
num = num + 1
def make_all_task_info(self):
addr = parse_get_symbol_addr('uxCurrentNumberOfTasks')
obj=parse_memory_2_class(addr,c_uint,4)
self.task_cnt = obj.value
addr = parse_get_symbol_addr('pxReadyTasksLists')
pxReadyLists=parse_memory_2_class(addr, List_t*configMAX_PRIORITIES, sizeof(List_t)*configMAX_PRIORITIES)
for pxList in pxReadyLists:
self._make_task_info(pxList)
TaskListName = ['xDelayedTaskList1', 'xDelayedTaskList2', 'xPendingReadyList', 'xTasksWaitingTermination', 'xSuspendedTaskList']
for tasklist_name in TaskListName:
addr = parse_get_symbol_addr(tasklist_name)
pxList = parse_memory_2_class(addr, List_t, sizeof(List_t))
self._make_task_info(pxList)
def _task_status_2_string(self,status):
str=''
if (status&OS_TASK_STATUS_UNUSED):
str=str+"unused,"
if (status&OS_TASK_STATUS_RUNNING):
str=str+'runing,'
if (status&OS_TASK_STATUS_READY):
str=str+'ready,'
if (status&OS_TASK_STATUS_SUSPEND):
str=str+'suspend,'
if (status&OS_TASK_STATUS_PEND):
str=str+'pend,'
if (status&OS_TASK_STATUS_DELAY):
str=str+'delay,'
if (status&OS_TASK_STATUS_TIMEOUT):
str=str+'timeout,'
if (status&OS_TASK_STATUS_PEND_TIME):
str=str+'pendtime,'
return str
def _make_task_extra_info(self):
i=0
while i < self.task_cnt:
tcb = self.tcb_array[i]
ext_info=self.ext_task_list[i]
if tcb.taskStatus & OS_TASK_STATUS_UNUSED: #未使用任务返回
i=i+1
continue;
ext_info.buttom = tcb.topOfStack+tcb.stackSize #计算栈buttom
ext_info.status_str = self._task_status_2_string(tcb.taskStatus)
if tcb.taskSem!=0:
ext_info.take_sem = parse_memory_2_class(tcb.taskSem,LosSemCB,sizeof(LosSemCB))
#生成taskname
addr=tcb.taskName
str = parse_memory_2_string(addr,32)
if str!=None:
ext_info.name=str
#判断栈是否溢出
obj = parse_memory_2_class(tcb.topOfStack,c_uint,sizeof(c_uint))
if obj.value==0xCCCCCCCC:
ext_info.over=0
else:
ext_info.over=1
#计算栈峰值
addr = tcb.topOfStack+4
while addr < ext_info.buttom:
obj = parse_memory_2_class(addr,c_uint,sizeof(c_uint))
if obj.value != 0xCACACACA:
break
addr+=4
ext_info.peek_used = ext_info.buttom-addr
enter_name=parse_addr_2_function_name(tcb.taskEntry)
if enter_name!=None:
ext_info.enter_name = enter_name
ext_info.task_context=parse_memory_2_class(tcb.stackPointer,TaskContext,sizeof(TaskContext))
i=i+1
def print_task_short_info(self):
print("\r\n--------------------content of 任务信息摘要:--------------------",file=self.info_fd)
print('%4s|%20s|%4s|%10s|%10s|%s|%10s'%('xHandle','TaskName','xTaskNumber','eCurrentState','CurrentPriority','BasePriority','StackBase'),file=self.info_fd)
for taskstatus in self.ext_taskstatus_list:
print('0x%08x|%20s|%4d|%4d|0x%08x|0x%08x|0x%08x'
%(taskstatus.xHandle,taskstatus.pcTaskName,taskstatus.xTaskNumber,taskstatus.eCurrentState,taskstatus.uxCurrentPriority,taskstatus.uxBasePriority,taskstatus.pxStackBase),file=self.info_fd)
def print_task_detail_info(self):
print("\r\n--------------------content of 任务详细信息:--------------------",file=self.info_fd)
print("说明:tcb任务控制块信息,context:任务上下文的寄存器信息,backtrace 栈回溯",file=self.info_fd)
for tcb in self.tcb_array:
print('',file=self.info_fd)
uapi_print_ctypes_obj('tcb',tcb,self.info_fd)
ext_info = parse_memory_2_class(tcb.pxTopOfStack+CONTEXT_OFFSET,exc_context_freertos_t,sizeof(exc_context_freertos_t))
#打印寄存器信息
print("[TASK]%s 寄存器:"%(tcb.pcTaskName),file=self.info_fd)
uapi_print_ctypes_obj('context',ext_info,self.info_fd)
#打印back_trace
print("[TASK]%s back trace..."%(tcb.pcTaskName))
print("[TASK]%s 栈回溯:"%(tcb.pcTaskName),file=self.info_fd)
sp = tcb.pxTopOfStack+CONTEXT_OFFSET
self.stack_back_trace(tcb.pxStack, sp)
#print("[TASK]%s 其它状态:"%(ext_info.name),file=self.info_fd)
def make_queue_info(self):
addr = parse_get_symbol_addr('xQueueRegistry')
i=0
while i< self.queue_cnt:
obj=parse_memory_2_class(addr,QueueRegistryItem_t,sizeof(QueueRegistryItem_t))
if obj:
queue_item=parse_memory_2_class(obj.xHandle,Queue_t,sizeof(Queue_t))
self.queue_array.append(queue_item)
addr=addr+sizeof(QueueRegistryItem_t)
i=i+1
def print_queue_info(self):
print("\r\n--------------------content of 消息队列信息:--------------------",file=self.info_fd)
print("说明:queueName队列名字,queueHandle队列的内存空间, queueType队列类型, queueLen队列长度, queueItemSize每个节点大小queueUsed已用节点个数, queueAvailable剩余节点个数",file=self.info_fd)
i=0
for queue in self.queue_array:
if queue!=None:
if queue.ucQueueType == queueQUEUE_TYPE_BASE:
uapi_print_ctypes_obj('queue',queue,self.info_fd)
print("",file=self.info_fd)
i=i+1
print("",file=self.info_fd)
def make_timer_info(self):
pxaddr = parse_get_u32_symbol_val('pxCurrentTimerList')
addrList = parse_memory_2_class(pxaddr, uint32_t, sizeof(uint32_t))
if addrList:
pxList=parse_memory_2_class(addrList.value, List_t, sizeof(List_t))
if pxList != None:
if pxList.uxNumberOfItems > 0:
while self.timer_cnt < pxList.uxNumberOfItems:
next_item = parse_memory_2_class(pxList.pxIndex, ListItem_t, sizeof(ListItem_t))
pxList.pxIndex = next_item.pxNext
obj = parse_memory_2_class(next_item.pvOwner, Timer_t, sizeof(Timer_t))
self.timer_array.append(obj)
self.timer_cnt = self.timer_cnt + 1
def print_timer_info(self):
print("---------------------content of 定时器信息:---------------------",file=self.info_fd)
print("说明:SwTmr_Used定时器个数SwTmr_Total定时器个数上限timer_id定时器idpxCallbackFunction回调函数的地址xTimerPeriodInTicks调用周期ucStatus(1:ACTIVE 2:STATICALLY_ALLOCATED 3:AUTORELOAD)",file=self.info_fd)
print("SwTmr_Used=%d, SwTmr_Total=unlimited"%(self.timer_cnt),file=self.info_fd)
i=0
while i< self.timer_cnt:
timer=self.timer_array[i]
print("timer_id=%d %s[0x%x]"%(timer.pvTimerID,_addr_in_2_function_name(timer.pxCallbackFunction),timer.pxCallbackFunction),file=self.info_fd)
uapi_print_ctypes_obj('timer',timer,self.info_fd)
print('',file=self.info_fd)
i=i+1
print("",file=self.info_fd)
def _make_sem_extra_info(self):
i=0
while i< self.sem_cnt:
sem=self.sem_array[i]
ext_info=self.sem_ext_info[i]
if sem.semStat==1: #used
(ret,addr_list)=_los_List_get_all_node(ext_info.handle_addr + ctype_member_offset('semList',LosSemCB))
for node_addr in addr_list:
ext_info.pend_task_list.append(node_addr)
i=i+1
def make_sem_info(self):
addr = parse_get_u32_symbol_val('g_osAllSem')
i=0
while i< self.sem_cnt:
ext_info=self._ExtSemInfo()
obj=parse_memory_2_class(addr,LosSemCB,sizeof(LosSemCB))
ext_info.handle_addr=addr
self.sem_array.append(obj)
self.sem_ext_info.append(ext_info)
addr=addr+sizeof(LosSemCB)
i=i+1
self._make_sem_extra_info()
def get_pending_task(self,addr_list):
list=[]
for addr in addr_list:
i=0
while i < self.task_cnt:
ext_task = self.ext_task_list[i]
tcb = self.tcb_array[i]
if addr== ext_task.pend_addr:
list.append(tcb.taskId)
i=i+1
return list
def print_sem_info(self):
print("--------------------content of 信号量:--------------------",file=self.info_fd)
print("说明:SemName信号量名字,SemHandle信号量的地址, MaxCount信号量最大个数, Count已用个数",file=self.info_fd)
i=0
for queue in self.queue_array:
if queue!=None:
if queue.ucQueueType==queueQUEUE_TYPE_COUNTING_SEMAPHORE or queue.ucQueueType==queueQUEUE_TYPE_BINARY_SEMAPHORE or queue.ucQueueType==queueQUEUE_TYPE_RECURSIVE_MUTEX:
uapi_print_ctypes_obj('Sem',queue,self.info_fd)
print("",file=self.info_fd)
i=i+1
print("",file=self.info_fd)
def make_crash_info(self):
addr = parse_get_symbol_addr('g_exc_buff_addr')
self.excInfo = parse_memory_2_class(addr,exc_context_t,sizeof(exc_context_t))
def print_crash_info(self):
print("--------------------content of 死机信息:--------------------",file=self.info_fd)
uapi_print_ctypes_obj('g_exc_buff_addr',self.excInfo,self.info_fd)
self.stack_back_trace(self.excInfo.task_context.sp+sizeof(task_context_t),self.excInfo.task_context.sp+0x1000)
def stack_back_trace(self,start_addr,end_addr):
sp=start_addr
while sp < end_addr:
obj=parse_memory_2_class(sp,c_uint,sizeof(c_uint))
name = parse_addr_in_2_function_name(obj.value-4)
if name:
print("[BACK Trace][addr=0x%08x][val=0x%08x]%s"%(sp,obj.value,name),file=self.info_fd)
else:
pass
#print("[BACK Trace][addr=0x%08x][val=0x%08x]"%(sp,obj.value),file=self.info_fd)
sp=sp+4
_g_parse_freertos_ctrl=_PhaseFreertosCtrl()
def make_freertos_info():
try:
_g_parse_freertos_ctrl.make_all_task_info()
except:
print("[EXCEPTION]make_all_task_info fail.")
try:
_g_parse_freertos_ctrl.make_queue_info()
except:
print("[EXCEPTION]make_queue_info fail.")
try:
_g_parse_freertos_ctrl.make_timer_info()
except:
print("[EXCEPTION]make_timer_info fail.")
try:
_g_parse_freertos_ctrl.make_crash_info()
except:
print("[EXCEPTION]make_crash_info fail.")
try:
_g_parse_freertos_ctrl.make_isr_info()
except:
print("[EXCEPTION]make_isr_info fail.")
def print_freertos_info():
try:
_g_parse_freertos_ctrl.print_isr_info()
except:
print("[EXCEPTION]print_isr_info fail.")
try:
_g_parse_freertos_ctrl.print_queue_info()
except:
print("[EXCEPTION]print_queue_info fail.")
try:
_g_parse_freertos_ctrl.print_timer_info()
except:
print("[EXCEPTION]print_timer_info fail.")
try:
_g_parse_freertos_ctrl.print_sem_info()
except:
print("[EXCEPTION]print_sem_info fail.")
try:
_g_parse_freertos_ctrl.print_task_short_info()
except:
print("[EXCEPTION]print_task_short_info fail.")
try:
_g_parse_freertos_ctrl.print_task_detail_info()
except:
print("[EXCEPTION]print_task_detail_info fail.")
try:
_g_parse_freertos_ctrl.print_crash_info()
except:
print("[EXCEPTION]print_crash_info fail.")
def parse_freertos_info(log_fp):
_g_parse_freertos_ctrl.info_fd = log_fp
make_freertos_info()
print_freertos_info()
print("parse_freertos_info end!")