ardupilot/Tools/scripts/decode_watchdog.py

305 lines
9.6 KiB
Python
Executable File

#!/usr/bin/env python
'''
decode an watchdog message
/Tools/scripts/decode_watchdog.py "WDOG, 2641424, -3, 0, 0, 0, 0, 0, 0, 122, 3, 0, 181, 4196355, 135203219, SPI1"
'''
import re
import sys
import optparse
from collections import OrderedDict
import decode_ICSR
class DecodeWatchDog(object):
class Component(object):
def __init__(self, value):
self.value = value
def prefix(self):
m = re.match(".*Component([A-Z]+)", str(type(self)))
return m.group(1)
def decode(self):
return "?????"
def string_value(self):
return str(self.value)
def print_decoded(self):
print("%5s %25s: %12s: %s" % (
self.prefix(),
self.expansion(),
self.string_value(),
self.decode()
))
class ComponentT(Component):
def expansion(self):
return "Scheduler Task"
def decode(self):
if int(self.value) == -3:
return "Waiting for sample"
if int(self.value) == -1:
return "Pre-loop"
if int(self.value) == -2:
return "Fast loop"
return self.value
class ComponentSL(Component):
def expansion(self):
return "Semaphore Line"
def decode(self):
if int(self.value) == 0:
return "Not waiting on semaphore"
return self.value
class ComponentFL(Component):
def expansion(self):
return "Fault Line"
class ComponentFT(Component):
def expansion(self):
return "Fault Type"
def decode(self):
x = int(self.value)
# this list taken from AP_HAL_ChibiOS/system.cpp
fault_types = {
1: "Reset",
2: "NMI",
3: "HardFault",
4: "MemManage",
5: "BusFault",
6: "UsageFault",
}
if x in fault_types:
return fault_types[x]
return super(DecodeWatchDog.ComponentFT, self).decode()
class ComponentFA(Component):
def expansion(self):
return "Fault Address"
def string_value(self):
return hex(int(self.value, 16))
class ComponentFTP(Component):
def expansion(self):
return "Fault Thread Priority"
class ComponentFLR(Component):
def expansion(self):
return "Fault Long Return Address" # ?? FIXME: is this really what LR stands for?
def string_value(self):
return "0x" + self.value
class ComponentFICSR(Component):
def expansion(self):
return "Fault ICS Register" # ?? FIXME: expand further
def string_value(self):
return hex(int(self.value, 16))
def decode(self):
return "[Below]"
def print_decoded(self):
super(DecodeWatchDog.ComponentFICSR, self).print_decoded()
decoder = decode_ICSR.DecodeICSR()
text = decoder.string(int(self.value))
sys.stdout.write(re.sub("^", " ", text, flags=re.M))
class ComponentMM(Component):
def expansion(self):
return "MAVLink Message"
def decode(self):
if int(self.value) == 0:
return "[None]"
return super(DecodeWatchDog.ComponentMM, self).decode()
class ComponentMC(Component):
def expansion(self):
return "MAVLink Command"
def decode(self):
if int(self.value) == 0:
return "[None]"
return super(DecodeWatchDog.ComponentMC, self).decode()
class ComponentIE(Component):
def expansion(self):
return "Internal Error Mask"
class ComponentIEHex(ComponentIE):
def expansion(self):
return "Internal Error Mask"
def string_value(self):
return hex(int(self.value, 16))
class ComponentIEC(Component):
def expansion(self):
return "Internal Error Count"
def decode(self):
return self.value
class ComponentIEL(Component):
def expansion(self):
return "Internal Error Line"
def decode(self):
return self.value
class ComponentTN(Component):
def expansion(self):
return "Thread name"
def __init__(self):
self.components = OrderedDict()
self.components["T"] = DecodeWatchDog.ComponentT
self.components["SL"] = DecodeWatchDog.ComponentSL
self.components["FL"] = DecodeWatchDog.ComponentFL
self.components["FT"] = DecodeWatchDog.ComponentFT
self.components["FA"] = DecodeWatchDog.ComponentFA
self.components["FTP"] = DecodeWatchDog.ComponentFTP
self.components["FLR"] = DecodeWatchDog.ComponentFLR
self.components["FICSR"] = DecodeWatchDog.ComponentFICSR
self.components["MM"] = DecodeWatchDog.ComponentMM
self.components["MC"] = DecodeWatchDog.ComponentMC
self.components["IE"] = DecodeWatchDog.ComponentIEHex
self.components["IEC"] = DecodeWatchDog.ComponentIEC
self.components["TN"] = DecodeWatchDog.ComponentTN
self.df_components = {}
self.df_components["Task"] = DecodeWatchDog.ComponentT
self.df_components["Tsk"] = DecodeWatchDog.ComponentT
self.df_components["IErr"] = DecodeWatchDog.ComponentIE
self.df_components["IE"] = DecodeWatchDog.ComponentIE
self.df_components["IEC"] = DecodeWatchDog.ComponentIEC
self.df_components["IEL"] = DecodeWatchDog.ComponentIEL
self.df_components["MavMsg"] = DecodeWatchDog.ComponentMM
self.df_components["MvMsg"] = DecodeWatchDog.ComponentMM
self.df_components["MvCmd"] = DecodeWatchDog.ComponentMC
self.df_components["SemLine"] = DecodeWatchDog.ComponentSL
self.df_components["SmLn"] = DecodeWatchDog.ComponentSL
self.df_components["FL"] = DecodeWatchDog.ComponentFL
self.df_components["FT"] = DecodeWatchDog.ComponentFT
self.df_components["FA"] = DecodeWatchDog.ComponentFA
self.df_components["FP"] = DecodeWatchDog.ComponentFTP
self.df_components["LR"] = DecodeWatchDog.ComponentFLR
self.df_components["ICSR"] = DecodeWatchDog.ComponentFICSR
self.df_components["TN"] = DecodeWatchDog.ComponentTN
def run(self, text):
# see if the supplied string is a statustext message:
re_string = "(?:APM: )?WDG:"
for component in self.components.keys():
re_string += " %s(?P<%s>[^ ]+)" % (component, component)
# print("string: %s" % text)
# print("re_string: %s" % re_string)
wdg_re = re.compile(re_string)
m = wdg_re.match(text)
if m is not None:
comp = []
for group in m.groupdict():
comp.append(self.components[group](m.group(group)))
for c in comp:
c.print_decoded()
return
# not a statustext message; see if it a WDOG dataflash message
df_re = re.compile("WDOG {(.*)}")
m = df_re.match(text)
if m is not None:
pairs = m.group(1).split(",")
for pair in pairs:
(name, value) = pair.split(":")
name = name.strip()
if name == "TimeUS":
continue
value = value.strip()
# print("(%s)=(%s)" % (name, value))
if name in ["LR", "FICSR", "FA"]:
value = int(value, 10)
value = hex(value)
value = value[2:]
if name not in self.df_components:
raise KeyError(name)
self.df_components[name](value).print_decoded()
return
# not a statustext message and not a mavlogdump dump of a WDOG
# dataflash message. See if it is a .log-style CSV line
log_re = re.compile("WDOG, (\d+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), ([-\d]+), (\w+)")
column_names = "TimeUS,Tsk,IE,IEC,IEL,MvMsg,MvCmd,SmLn,FL,FT,FA,FP,ICSR,LR,TN"
cols = column_names.split(",")
m = log_re.match(text)
if m is not None:
for i in range(0,len(cols)):
name = cols[i]
if name == 'TimeUS':
continue
value = m.group(i+1)
# convert some things from base10 to hex:
if name in ["LR", "FICSR", "FA"]:
value = int(value, 10)
value = hex(value)
value = value[2:]
if name not in self.df_components:
raise KeyError(name)
self.df_components[name](value).print_decoded()
return
raise ValueError("Text not recognised")
# 2020-06-10 17:20:08.45: WDOG {TimeUS : 949568, Task : -2, IErr : 0, IErrCnt : 0, MavMsg : 0, MavCmd : 0, SemLine : 0, FL : 100, FT : 3, FA : 404947019, FP : 183, ICSR : 4196355}
# APM: WDG: T-3 SL0 FL122 FT3 FA0 FTP177 FLR80CBB35 FICSR4196355 MM0 MC0 IE67108864 IEC12353 TN:rcin
# FMT, 254, 47, WDOG, QbIHHHHHHHIBIIn, TimeUS,Tsk,IE,IEC,IEL,MvMsg,MvCmd,SmLn,FL,FT,FA,FP,ICSR,LR,TN
# WDOG, 2641424, -3, 0, 0, 0, 0, 0, 0, 122, 3, 0, 181, 4196355, 135203219, SPI1
if __name__ == '__main__':
parser = optparse.OptionParser(__file__)
opts, args = parser.parse_args()
if len(args) == 0:
print("Usage: %s" % parser.usage)
sys.exit(0)
text = args[0]
decoder = DecodeWatchDog()
decoder.run(text)