apptrace_proc.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/env python
  2. #
  3. from __future__ import print_function
  4. import argparse
  5. import struct
  6. import sys
  7. class bcolors:
  8. HEADER = '\033[95m'
  9. OKBLUE = '\033[94m'
  10. OKGREEN = '\033[92m'
  11. WARNING = '\033[93m'
  12. FAIL = '\033[91m'
  13. ENDC = '\033[0m'
  14. BOLD = '\033[1m'
  15. UNDERLINE = '\033[4m'
  16. def main():
  17. ESP32_TRACE_BLOCK_HDR_SZ = 8
  18. ESP32_TRACE_BLOCK_TASK_IDX = 0
  19. ESP32_TRACE_BLOCK_TS_IDX = 1
  20. ESP32_TRACE_BLOCK_DATA_IDX = 2
  21. parser = argparse.ArgumentParser(description='ESP32 App Trace Parse Tool')
  22. parser.add_argument('file', help='Path to app trace file', type=str)
  23. parser.add_argument('--print-tasks', '-p', help='Print tasks', action='store_true')
  24. parser.add_argument('--print-details', '-d', help='Print detailed stats', action='store_true')
  25. parser.add_argument('--no-errors', '-n', help='Do not print errors', action='store_true')
  26. parser.add_argument('--block-len', '-b', help='Block length', type=int, default=1024)
  27. args = parser.parse_args()
  28. print("====================================================================")
  29. try:
  30. ftrc = open(args.file, 'rb')
  31. except IOError as e:
  32. print("Failed to open trace file (%s)!" % e)
  33. sys.exit(2)
  34. passed = True
  35. off = 0
  36. data_stats = {}
  37. last_ts = None
  38. tot_discont = 0
  39. while True:
  40. # ftrc.seek(off)
  41. task = None
  42. ts = 0
  43. trc_buf = ftrc.read(args.block_len)
  44. if len(trc_buf) == 0:
  45. # print('EOF')
  46. break
  47. trc_data = struct.unpack('<LL%sB' % (len(trc_buf) - ESP32_TRACE_BLOCK_HDR_SZ), trc_buf)
  48. if len(trc_data):
  49. # print("%x %x, len %d" % (trc_data[0], trc_data[1], len(trc_data) - 2))
  50. # print(trc_data[2:])
  51. # sys.exit(0)
  52. task = trc_data[ESP32_TRACE_BLOCK_TASK_IDX]
  53. ts = trc_data[ESP32_TRACE_BLOCK_TS_IDX]
  54. # print(ts)
  55. if last_ts and last_ts >= ts:
  56. # print("Global TS discontinuity %x -> %x, task %x, stamp %x at %x" % (last_ts, ts, task,
  57. # data_stats[task]['stamp'], off))
  58. if args.print_details:
  59. print("Global TS discontinuity %x -> %x, task %x at %x" % (last_ts, ts, task, off))
  60. # tot_discont += 1
  61. # passed = False
  62. last_ts = ts
  63. if task not in data_stats:
  64. print("%x: NEW TASK" % task)
  65. data_stats[task] = {'stamp': trc_data[ESP32_TRACE_BLOCK_DATA_IDX], 'last_ts': ts, 'count': 1, 'discont_offs': [], 'inv_stamps_offs': []}
  66. else:
  67. if data_stats[task]['last_ts'] == ts:
  68. print("Task TS discontinuity %x -> %x, task %x, stamp %x at %x" % (last_ts, ts, task, data_stats[task]['stamp'], off))
  69. data_stats[task]['discont_offs'].append(off)
  70. tot_discont += 1
  71. passed = False
  72. data_stats[task]['last_ts'] = ts
  73. data_stats[task]['count'] += 1
  74. if len(trc_data) > ESP32_TRACE_BLOCK_DATA_IDX:
  75. # print("DATA = %x %x %x %x" % (trc_data[-4], trc_data[-3], trc_data[-2], trc_data[-1]))
  76. if args.print_tasks:
  77. print("Task[%d] %x, ts %08x, stamp %x" % (off / args.block_len, task, ts, trc_data[ESP32_TRACE_BLOCK_DATA_IDX]))
  78. else:
  79. print("%x: NO DATA" % task)
  80. else:
  81. print("Failed to unpack data!")
  82. sys.exit(2)
  83. # check data
  84. for i in range(ESP32_TRACE_BLOCK_DATA_IDX, len(trc_data)):
  85. if trc_data[i] != data_stats[task]['stamp']:
  86. if not args.no_errors:
  87. print("Invalid stamp %x->%x at %x, task %x" % (data_stats[task]['stamp'], trc_data[i], off + ESP32_TRACE_BLOCK_HDR_SZ + i, task))
  88. passed = False
  89. data_stats[task]['stamp'] = trc_data[i]
  90. data_stats[task]['inv_stamps_offs'].append(off)
  91. # break
  92. if len(trc_buf) < args.block_len:
  93. print('Last block (not full)')
  94. break
  95. if data_stats[task]['stamp'] is not None:
  96. data_stats[task]['stamp'] = (data_stats[task]['stamp'] + 1) & 0xFF
  97. # print("stamp=%x" % data_stats[task][ESP32_TRACE_STAMP_IDX])
  98. off += args.block_len
  99. ftrc.close()
  100. print("====================================================================")
  101. print("Trace size %d bytes, discont %d\n" % (off, tot_discont))
  102. for t in data_stats:
  103. print("Task %x. Total count %d. Inv stamps %d. TS Discontinuities %d." % (t, data_stats[t]['count'],
  104. len(data_stats[t]['inv_stamps_offs']), len(data_stats[t]['discont_offs'])))
  105. if args.print_details:
  106. print('Invalid stamps offs: [{}]'.format(', '.join(hex(x) for x in data_stats[t]['inv_stamps_offs'])))
  107. print('TS Discontinuities offs: [{}]'.format(', '.join(hex(x) for x in data_stats[t]['discont_offs'])))
  108. print("\n")
  109. if passed:
  110. print("Data - OK")
  111. else:
  112. print("Data - FAILED!")
  113. if __name__ == '__main__':
  114. main()