#!/usr/bin/env python ''' decode an stm32 ICSR register value AP_FLAKE8_CLEAN ''' import sys import optparse class DecodeICSR(object): # https://www.st.com/content/ccc/resource/technical/document/programming_manual/6c/3a/cb/e7/e4/ea/44/9b/DM00046982.pdf/files/DM00046982.pdf/jcr:content/translations/en.DM00046982.pdf # page 225 def __init__(self): # this ICSR-bit-assignment-table table also looks valid for M7 # - page 195 of # dm00237416-stm32f7-series-and-stm32h7-series-cortexm7-processor-programming-manual-stmicroelectronics.pdf self.M4_BITS = [ ("0-8", "VECTACTIVE", self.decoder_m4_vectactive), ("9-10", "RESERVED1", None), ("11", "RETOBASE", self.decoder_m4_retobase), ("12-18", "VECTPENDING", self.decoder_m4_vectpending), ("19-21", "RESERVED2", None), ("22", "ISRPENDING", self.decoder_m4_isrpending), ("23-24", "RESERVED3", None), ("25", "PENDSTCLR", self.decoder_m4_pendstclr), ("26", "PENDSTSET", self.decoder_m4_pendstset), ("27", "PENDSVCLR", self.decoder_m4_pendsvclr), ("28", "PENDSVSET", self.decoder_m4_pendstset), ("29-30", "RESERVED4", None), ("31", "NMIPENDSET", self.decoder_m4_nmipendset), ] self.longest_name_length = 0 for bit in self.M4_BITS: (bits, name, decoder) = bit length = len(name) if length > self.longest_name_length: self.longest_name_length = length def decoder_m4_vectactive(self, value): exceptions = { 0: "Thread mode", 1: "Reserved", 2: "NMI", 3: "Hard fault", 4: "Memory management fault", 5: "Bus fault", 6: "Usage fault", 7: "Reserved....", 10: "Reserved", 11: "SVCall", 12: "Reserved for Debug", 13: "Reserved", 14: "PendSV", 15: "SysTick", } if value in exceptions: exception = "%s" % str(exceptions[value]) else: exception = "IRQ%u" % (value - 16) return " (%s)" % exception def decoder_m4_retobase(self, value): if value: out = "no (or no more) active exceptions" else: out = "preempted active exceptions" return (" (%s)" % out) def decoder_m4_vectpending(self, value): return self.decoder_m4_vectactive(value) def decoder_m4_isrpending(self, value): if value: out = "Interrupt pending" else: out = "No pending interupt" return (" (%s)" % out) def decoder_m4_pendstclr(self, value): return (" (WO clears SysTick exception)") def decoder_m4_pendstset(self, value): if value: out = "SysTick pending" else: out = "SysTick not pending" return (" (%s)" % out) def decoder_m4_pendsvclr(self, value): return (" (WO clears pendsv exception)") def decoder_m4_pendsvset(self, value): if value: out = "PendSV pending" else: out = "PendSV not pending" return (" (%s)" % out) def decoder_m4_nmipendset(self, value): if value: out = "NMI pending" else: out = "NMI not pending" return (" (%s)" % out) def string(self, ICSR): ret = "" complete_mask = 0 for bit in self.M4_BITS: (bits, name, decoder) = bit if "-" in bits: (start_bit, stop_bit) = bits.split("-") start_bit = int(start_bit) stop_bit = int(stop_bit) else: start_bit = int(bits) stop_bit = int(bits) mask = 0 for i in range(start_bit, stop_bit+1): mask |= (1 << i) complete_mask |= mask value = (ICSR & mask) >> start_bit _format = "%%%us: %%3u " % (self.longest_name_length,) ret += (_format % (name, value)) if decoder is not None: ret += decoder(value) ret += "\n" return ret if complete_mask != 0b11111111111111111111111111111111: raise Exception("Mask incomplete") def run(self, ICSR): sys.stdout.write(self.string(ICSR)) if __name__ == '__main__': parser = optparse.OptionParser(__file__) opts, args = parser.parse_args() if len(args) == 0: print(parser.usage) sys.exit(0) def num(s): try: return int(s) except ValueError: return int(s, 16) ICSR = num(args[0]) decoder = DecodeICSR() decoder.run(ICSR)