def dump_cfsr(cfsr: int) -> int: cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = cfsr cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) _LOG.info(cpu_state_info) return 0
def test_dump_with_cfsr(self): """Validate CPU state dump with CFSR bits set is formatted correctly.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = ( cortex_m_constants.PW_CORTEX_M_CFSR_PRECISERR_MASK | cortex_m_constants.PW_CORTEX_M_CFSR_BFARVALID_MASK) cpu_state_proto.pc = 0xd2603058 cpu_state_proto.bfar = 0xdeadbeef cpu_state_proto.mmfar = 0x8e4eb9a2 cpu_state_proto.r0 = 0xdb5e7168 cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) expected_dump = '\n'.join(( 'Exception caused by a bus fault at 0xdeadbeef.', '', 'Active Crash Fault Status Register (CFSR) fields:', 'PRECISERR Precise bus fault.', 'BFARVALID BFAR is valid.', '', 'All registers:', 'pc 0xd2603058', 'cfsr 0x00008200', 'mmfar 0x8e4eb9a2', 'bfar 0xdeadbeef', 'r0 0xdb5e7168', )) self.assertEqual(str(cpu_state_info), expected_dump)
def test_single_usage_fault_without_fields(self): """Ensure disabling show_active_cfsr_fields hides field names.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = cortex_m_constants.PW_CORTEX_M_CFSR_STKOF_MASK cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertEqual(cpu_state_info.exception_cause(False), 'usage fault')
def test_single_usage_fault(self): """Ensure usage faults are properly identified.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = cortex_m_constants.PW_CORTEX_M_CFSR_STKOF_MASK cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertEqual(cpu_state_info.exception_cause(), 'usage fault [STKOF]')
def test_unknown_exception(self): """Ensure CPU state with insufficient info has no known cause.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() # Set CFSR to a valid value. cpu_state_proto.cfsr = 0 cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertEqual(cpu_state_info.exception_cause(), 'unknown exception')
def test_icsr_fault(self): """Ensure a fault is active if ICSR says the handler is active.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.icsr = ( cortex_m_constants.PW_CORTEX_M_HARD_FAULT_ISR_NUM) cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertTrue(cpu_state_info.is_fault_active())
def test_cfsr_fault(self): """Ensure a fault is active if CFSR bits are set.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = ( cortex_m_constants.PW_CORTEX_M_CFSR_STKOF_MASK | cortex_m_constants.PW_CORTEX_M_CFSR_MUNSTKERR_MASK) cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertTrue(cpu_state_info.is_fault_active())
def test_imprecise_bus_fault(self): """Check that imprecise bus faults are identified correctly.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = ( cortex_m_constants.PW_CORTEX_M_CFSR_IMPRECISERR_MASK | cortex_m_constants.PW_CORTEX_M_CFSR_IBUSERR_MASK) cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertEqual(cpu_state_info.exception_cause(False), 'imprecise bus fault')
def test_mmfar_missing(self): """Ensure if mmfar is valid but missing it is handled safely.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = ( cortex_m_constants.PW_CORTEX_M_CFSR_MUNSTKERR_MASK | cortex_m_constants.PW_CORTEX_M_CFSR_MMARVALID_MASK) cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertEqual(cpu_state_info.exception_cause(False), 'memory management fault at ???')
def test_multiple_faults(self): """Ensure multiple CFSR bits are identified and reported.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = ( cortex_m_constants.PW_CORTEX_M_CFSR_STKOF_MASK | cortex_m_constants.PW_CORTEX_M_CFSR_UNSTKERR_MASK) cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertEqual(cpu_state_info.exception_cause(), 'usage fault, bus fault [UNSTKERR] [STKOF]')
def test_mmfar_valid(self): """Validate output format of valid MMFAR.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = ( cortex_m_constants.PW_CORTEX_M_CFSR_MUNSTKERR_MASK | cortex_m_constants.PW_CORTEX_M_CFSR_MMARVALID_MASK) cpu_state_proto.mmfar = 0x722470e4 cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertEqual(cpu_state_info.exception_cause(False), 'memory management fault at 0x722470e4')
def test_cfsr_fields(self): """Ensure correct fields are returned when CFSR bits are set.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.cfsr = ( cortex_m_constants.PW_CORTEX_M_CFSR_STKOF_MASK | cortex_m_constants.PW_CORTEX_M_CFSR_MUNSTKERR_MASK) cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) active_fields = [ field.name for field in cpu_state_info.active_cfsr_fields() ] self.assertEqual(len(active_fields), 2) self.assertIn('STKOF', active_fields) self.assertIn('MUNSTKERR', active_fields)
def test_registers(self): """Validate output of general register dumps.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.pc = 0xdfadd966 cpu_state_proto.mmfar = 0xaf2ea98a cpu_state_proto.r0 = 0xf3b235b1 cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) expected_dump = '\n'.join(( 'pc 0xdfadd966', 'mmfar 0xaf2ea98a', 'r0 0xf3b235b1', )) self.assertEqual(cpu_state_info.dump_registers(), expected_dump)
def test_dump_no_cfsr(self): """Validate basic CPU state dump.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_proto.pc = 0xd2603058 cpu_state_proto.mmfar = 0x8e4eb9a2 cpu_state_proto.r0 = 0xdb5e7168 cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) expected_dump = '\n'.join(( 'Exception caused by a unknown exception.', '', 'No active Crash Fault Status Register (CFSR) fields.', '', 'All registers:', 'pc 0xd2603058', 'mmfar 0x8e4eb9a2', 'r0 0xdb5e7168', )) self.assertEqual(str(cpu_state_info), expected_dump)
def test_empty_cpu_state(self): """Ensure empty CPU state has no known cause.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertEqual(cpu_state_info.exception_cause(), 'unknown exception')
def test_empty_state(self): """Ensure an empty CPU state proto doesn't indicate an active fault.""" cpu_state_proto = cpu_state_pb2.ArmV7mCpuState() cpu_state_info = exception_analyzer.CortexMExceptionAnalyzer( cpu_state_proto) self.assertFalse(cpu_state_info.is_fault_active())