PageRenderTime 131ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/tos/chips/si446x/gdb_si446x.py

https://github.com/cire831/mm
Python | 305 lines | 253 code | 5 blank | 47 comment | 10 complexity | 3d29a1ab6446366a44ee10165f5d5aa9 MD5 | raw file
  1. from si446x.si446xdef import *
  2. from binascii import hexlify
  3. import operator
  4. # Setup required to use this module
  5. #
  6. # add the following python packages
  7. # sudo pip install future
  8. # sudo pip install construct==2.5.2
  9. #
  10. # copy gdb_si446x.py to <app>/.gdb_si446x.py
  11. # and add "source ../../.gdb_si446x.py" to the <app>/.gdbinit file.
  12. #
  13. # also copy si446xdef.py into the gdb data directory
  14. # "/usr/gcc-arm-none-eabi-4_9-2015q3/arm-none-eabi/share/gdb/python"
  15. # this install should happen on a TagNet tree install.
  16. # or add this copy into the mm/tools/00_gdb/copy_gdb which will check
  17. # for correct source and permissions.
  18. # convert byte array into hexlify'd string
  19. # with space between every two bytes (4 hex chars)
  20. #
  21. def get_spi_hex_helper(rb):
  22. """
  23. Return a printable string of hex array with
  24. spaces between every two hex digits
  25. """
  26. r_s = bytearray()
  27. x = 0
  28. i = 4
  29. r = 0
  30. buf = hexlify(rb)
  31. while (x < len(buf)):
  32. r = i if (x+i < len(buf)) else len(buf[x:])
  33. r_s += buf[x:x+r] + ' '
  34. x += r
  35. return r_s
  36. def get_cmd_structs(cmd):
  37. """
  38. Find the cmd in the struct enum list of si446x Radio
  39. commands and return information to use it.
  40. Returns a function to generate a Radio cmd msg along
  41. with the struct needed to interpret the response msg.
  42. Return (Cmd bytecode, (req msg, rsp struct))
  43. """
  44. for k,v in radio_config_cmd_ids.encoding.iteritems():
  45. if (v == cmd):
  46. try:
  47. cid = radio_config_cmd_ids.build(k)
  48. return radio_status_commands[cid]
  49. except:
  50. return (None, None)
  51. return (None, None)
  52. def get_buf_repr(b, l):
  53. """
  54. Convert the byte array input into a hex ascii string.
  55. Limited by length l and size of buffer b.
  56. Returns both a byte array of the input as well as a
  57. hex ascii string representation.
  58. """
  59. m = l if (l < b.type.sizeof) else b.type.sizeof
  60. x = 0
  61. b_s = bytearray()
  62. h_s = bytearray()
  63. for x in range(m):
  64. da = int(b[x])
  65. b_s.append(da)
  66. if (m): h_s = get_spi_hex_helper(b_s)
  67. return b_s, h_s
  68. def get_spi_trace_row_repr(i):
  69. """
  70. Get a row from the trace table using GDB parse_and_eval. Then
  71. format ascii string with results.
  72. Information presented:
  73. Radio SPI Operation
  74. Entry ID, timestamp, struct name, hexbytes, <container or decoded info>
  75. Example return values:
  76. SPI_REC_GET_REPLY
  77. 59 0x20e4237 fifo_info_rsp_s 1c40 Container({'rx_fifo_count': 28, 'tx_fifo_space': 64, 'cts': 255})
  78. 62 0x20e47ad SPI_REC_RX_FIFO 0x0 0x1c 70ff 2a04 bf04 490a 70ff 221a 5470 4725
  79. SPI_REC_READ_FRR
  80. 63 0x20e48b1 fast_frr_s 0800 0078 state: RX, rssi: 120
  81. """
  82. st = bytearray()
  83. row = 'g_radio_spi_trace[' + hex(i) + ']'
  84. rt = gdb.parse_and_eval(row) # get gdb object for the row in the trace array
  85. if (rt['timestamp'] == 0) or (rt['op'] == 0) or (rt['op'] >= 6):
  86. return st # nothing useful in the row object
  87. st += '{} '.format(str(i))
  88. rt_b, rt_h = get_buf_repr(rt['buf'], rt['length'])
  89. c_str, r_str = get_cmd_structs(rt['struct_id'])
  90. st += '{} '.format(str(rt['timestamp']))
  91. # print(rt['op'])
  92. if (rt['op'] == 2) and (c_str): # SEND_CMD
  93. try:
  94. st += '{} {}'.format(rt_h, radio_display_structs[r_str](r_str, rt_b))
  95. except:
  96. st += '{} {}'.format(rt['struct_id'], rt_h)
  97. return st
  98. if (rt['op'] == 3) and (r_str): # GET_REPLY
  99. st += "blen:slen {}:{}, ".format(len(rt_b), r_str.sizeof()-1)
  100. if (len(rt_b) == (r_str.sizeof() - 1)):
  101. st += '{} {} {}'.format(r_str.name, rt_h,
  102. radio_display_structs[r_str](r_str, bytearray('\xff') + rt_b))
  103. return st
  104. if (rt['op'] == 1): # READ_FRR
  105. r_str = fast_frr_s
  106. if (len(rt_b) > 1):
  107. tt = radio_display_structs[r_str](r_str, rt_b)
  108. else:
  109. tt = ''
  110. st += '{} {} {}'.format(r_str.name, rt_h, tt)
  111. return st
  112. ba = bytearray()
  113. ba.append(int(rt['struct_id']))
  114. try:
  115. bx = radio_config_cmd_ids.parse(ba)
  116. bxa = radio_config_commands[radio_config_cmd_ids.build(bx)][1].parse(rt_b)
  117. except:
  118. bx = hexlify(ba)
  119. bxa = ''
  120. st += '|| {} {} {} {} {}'.format(rt['op'], bx, rt['length'], rt_h, bxa)
  121. return st
  122. class RadioFSM (gdb.Command):
  123. """ Dump all radio device finite state machine transitions"""
  124. def __init__ (self):
  125. super (RadioFSM, self).__init__("radiofsm", gdb.COMMAND_DATA,
  126. gdb.COMPLETE_COMMAND)
  127. def invoke (self, args, from_tty):
  128. i_loop = 0
  129. i_this = int(gdb.parse_and_eval('Si446xDriverLayerP__fsm_tc'))
  130. i_prev = int(gdb.parse_and_eval('Si446xDriverLayerP__fsm_tp'))
  131. i_max = int(gdb.parse_and_eval('Si446xDriverLayerP__fsm_max'))
  132. i_count = int(gdb.parse_and_eval('Si446xDriverLayerP__fsm_count'))
  133. if (i_count < i_max): i_this = 0
  134. print i_this, i_prev, i_max
  135. while (i_loop < i_max):
  136. rd = gdb.parse_and_eval('Si446xDriverLayerP__fsm_trace_array[{}]'.format(hex(i_this)))
  137. start = int(rd['ts_start'])
  138. elapsed = int(rd['elapsed'])
  139. print '{:03d}: {:08x}/{:08x} ({:04x}) {:>18s} {:<12s} {:>18s} {:<12s}'.format(
  140. int(i_this), start, start + elapsed, elapsed,
  141. rd['ev'].__str__().replace('Si446xDriverLayerP__',''),
  142. rd['cs'].__str__().replace('Si446xDriverLayerP__',''),
  143. rd['ac'].__str__().replace('Si446xDriverLayerP__',''),
  144. rd['ns'].__str__().replace('Si446xDriverLayerP__',''))
  145. if (i_this == i_prev): break
  146. i_this += 1
  147. if (i_this >= i_max):
  148. i_this = 0
  149. i_loop += 1
  150. def GetArgs(args, count):
  151. alist = args.split()
  152. a_start = 0
  153. a_end = count
  154. if (len(alist) == 1):
  155. a_start = count - int(alist[0])
  156. elif (len(alist) == 2):
  157. a_start = count - int(alist[1])
  158. a_end = a_start + int(alist[0])
  159. return a_start, a_end, alist
  160. class RadioSPI (gdb.Command):
  161. """ Dump radio SPI transfer trace records"""
  162. def __init__ (self):
  163. super (RadioSPI, self).__init__("radiospi", gdb.COMMAND_DATA,
  164. gdb.COMPLETE_COMMAND)
  165. def invoke (self, args, from_tty):
  166. i_this = int(gdb.parse_and_eval('g_radio_spi_trace_next'))
  167. i_prev = int(gdb.parse_and_eval('g_radio_spi_trace_prev'))
  168. i_max = int(gdb.parse_and_eval('g_radio_spi_trace_max'))
  169. i_count = int(gdb.parse_and_eval('g_radio_spi_trace_count'))
  170. if (i_count < i_max): i_this = 0
  171. # print("queue: this:{}, prev:{}, max:{}, count:{}".format(i_this, i_prev, i_max, i_count))
  172. a_start, a_end, alist = GetArgs(args, i_count)
  173. # print('args({},{}): {}'.format(a_start, a_end, alist))
  174. for i_loop in range(i_count):
  175. ss = None
  176. if (i_loop > a_start) and (i_loop <= a_end):
  177. ss = get_spi_trace_row_repr(i_this)
  178. # else:
  179. # print("{}.{}.{}".format(a_start,i_loop,a_end))
  180. if (ss): print ss
  181. if (i_this == i_prev): break
  182. i_this += 1
  183. if (i_this >= i_max):
  184. i_this = 0
  185. class RadioGroups (gdb.Command):
  186. """
  187. Dump all radio device configuration and status groups
  188. If no arguments, then display all groups. Else display specific
  189. groups identified by arguments.
  190. """
  191. def __init__ (self):
  192. super (RadioGroups, self).__init__("radiogroups", gdb.COMMAND_DATA,
  193. gdb.COMPLETE_COMMAND)
  194. def invoke (self, args, from_tty):
  195. rd = gdb.parse_and_eval('g_radio_dump')
  196. for grp, __ in radio_config_group_ids.encoding.iteritems():
  197. if (args) and (grp not in args): continue
  198. bgrp = 'PAx' if (grp == 'PA') else grp
  199. str = radio_config_groups[radio_config_group_ids.build(grp)]
  200. r_a, r_s = get_buf_repr(rd[bgrp], str.sizeof())
  201. print grp, bgrp, str, r_s
  202. print radio_display_structs[str](str, r_a)
  203. class RadioStats (gdb.Command):
  204. """
  205. Dump out radio software stats, error counters etc.
  206. """
  207. def __init__ (self):
  208. super (RadioStats, self).__init__("radiostats", gdb.COMMAND_DATA,
  209. gdb.COMPLETE_COMMAND)
  210. def invoke (self, args, from_tty):
  211. rd = gdb.parse_and_eval('Si446xDriverLayerP__global_ioc')
  212. pRxMsg = gdb.parse_and_eval('Si446xDriverLayerP__pRxMsg')
  213. pTxMsg = gdb.parse_and_eval('Si446xDriverLayerP__pTxMsg')
  214. st = "pRxMsg:\t\t{}\tpTxMsg:\t\t{}".format(pRxMsg, pTxMsg)
  215. print st
  216. print "rc_readys:\t\t" + str(rd['rc_readys'])
  217. print "tx_packets:\t\t" + str(rd['tx_packets'])
  218. print "tx_reports:\t\t" + str(rd['tx_reports'])
  219. print "tx_timeouts:\t\t" + str(rd['tx_timeouts'])
  220. print "tx_underruns:\t\t" + str(rd['tx_underruns'])
  221. print
  222. print "rx_packets:\t\t" + str(rd['rx_packets'])
  223. print "rx_reports:\t\t" + str(rd['rx_reports'])
  224. print "rx_bad_crcs:\t\t" + str(rd['rx_bad_crcs'])
  225. print "rx_timeouts:\t\t" + str(rd['rx_timeouts'])
  226. print "rx_inv_syncs:\t\t" + str(rd['rx_inv_syncs'])
  227. print "rx_errors:\t\t" + str(rd['rx_errors'])
  228. print
  229. print "rx_overruns:\t\t" + str(rd['rx_overruns'])
  230. print "rx_active_overruns:\t" + str(rd['rx_active_overruns'])
  231. print "rx_crc_overruns:\t" + str(rd['rx_crc_overruns'])
  232. print "rx_crc_packet_rx:\t" + str(rd['rx_crc_packet_rx'])
  233. print "tx_send_wait_time:\t" + str(rd['send_wait_time'])
  234. print "tx_send_max_wait:\t" + str(rd['send_max_wait'])
  235. class RadioRaw (gdb.Command):
  236. """
  237. Dump out radio hardware context.
  238. """
  239. def __init__ (self):
  240. super (RadioRaw, self).__init__("radioraw", gdb.COMMAND_DATA,
  241. gdb.COMPLETE_COMMAND)
  242. def invoke (self, args, from_tty):
  243. arglist = gdb.string_to_argv(args.upper())
  244. print('args',arglist)
  245. if 'GROUPS' in arglist:
  246. print('GROUPS')
  247. rd = gdb.parse_and_eval('g_radio_dump')
  248. dg = {}
  249. group_order = sorted(radio_config_group_ids.encoding.items(),
  250. key=operator.itemgetter(1))
  251. for grp in radio_config_group_ids.encoding.keys():
  252. bgrp = 'PAx' if (grp == 'PA') else grp # fixup construct module bug
  253. buf = radio_config_groups[radio_config_group_ids.build(grp)]
  254. r_a, r_s = get_buf_repr(rd[bgrp], buf.sizeof)
  255. dg[radio_config_group_ids.build(grp)] = r_a
  256. print(grp, radio_config_group_ids.build(grp), r_s, r_a)
  257. print(dg)
  258. class RadioInfo (gdb.Command):
  259. """
  260. Dump out radio hardware context.
  261. """
  262. def __init__ (self):
  263. super (RadioInfo, self).__init__("radioinfo", gdb.COMMAND_DATA,
  264. gdb.COMPLETE_COMMAND)
  265. def invoke (self, args, from_tty):
  266. arglist = gdb.string_to_argv(args.upper())
  267. for cmd_id in ['part_info', 'func_info']:
  268. info_buf = gdb.parse_and_eval('g_radio_dump.' + cmd_id)
  269. print(info_buf)
  270. RadioGroups()
  271. RadioSPI()
  272. RadioFSM()
  273. RadioStats()
  274. RadioRaw()
  275. RadioInfo()