Esempio n. 1
0
static void _FaultShow(const NANO_ESF *esf, int fault)
{
	PR_EXC("Fault! EXC #%d\n", fault);

#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
	PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
	       SCB_MMFSR, SCB_BFSR, SCB_UFSR);
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
	PR_EXC("SFSR: 0x%x\n", SAU->SFSR);
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */
}
Esempio n. 2
0
/**
 *
 * @brief Dump bus fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _BusFault(const NANO_ESF *esf, int fromHardFault)
{
	PR_EXC("***** BUS FAULT *****\n");

	_FaultThreadShow(esf);

	if (_ScbBusFaultIsStacking()) {
		PR_EXC("  Stacking error\n");
	} else if (_ScbBusFaultIsUnstacking()) {
		PR_EXC("  Unstacking error\n");
	} else if (_ScbBusFaultIsPrecise()) {
		PR_EXC("  Precise data bus error\n");
		if (_ScbBusFaultIsBfarValid()) {
			PR_EXC("  Address: 0x%x\n", _ScbBusFaultAddrGet());
			if (fromHardFault) {
				_ScbBusFaultBfarReset();
			}
		}
		/* it's possible to have both a precise and imprecise fault */
		if (_ScbBusFaultIsImprecise()) {
			PR_EXC("  Imprecise data bus error\n");
		}
	} else if (_ScbBusFaultIsImprecise()) {
		PR_EXC("  Imprecise data bus error\n");
	} else if (_ScbBusFaultIsInstrBusErr()) {
		PR_EXC("  Instruction bus error\n");
	}
}
Esempio n. 3
0
/**
 *
 * @brief Dump hard fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _HardFault(const NANO_ESF *esf)
{
	PR_EXC("***** HARD FAULT *****\n");
	if (_ScbHardFaultIsBusErrOnVectorRead()) {
		PR_EXC("  Bus fault on vector table read\n");
	} else if (_ScbHardFaultIsForced()) {
		PR_EXC("  Fault escalation (see below)\n");
		if (_ScbIsMemFault()) {
			_MpuFault(esf, 1);
		} else if (_ScbIsBusFault()) {
			_BusFault(esf, 1);
		} else if (_ScbIsUsageFault()) {
			_UsageFault(esf);
		}
	}
}
Esempio n. 4
0
/**
 *
 * @brief Dump thread information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _FaultThreadShow(const NANO_ESF *esf)
{
	PR_EXC("  Executing thread ID (thread): 0x%x\n"
	       "  Faulting instruction address:  0x%x\n",
	       sys_thread_self_get(),
	       esf->pc);
}
Esempio n. 5
0
/**
 *
 * @brief Dump usage fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _UsageFault(const NANO_ESF *esf)
{
	PR_EXC("***** USAGE FAULT *****\n");

	_FaultThreadShow(esf);

	/* bits are sticky: they stack and must be reset */
	if (_ScbUsageFaultIsDivByZero()) {
		PR_EXC("  Division by zero\n");
	}
	if (_ScbUsageFaultIsUnaligned()) {
		PR_EXC("  Unaligned memory access\n");
	}
	if (_ScbUsageFaultIsNoCp()) {
		PR_EXC("  No coprocessor instructions\n");
	}
	if (_ScbUsageFaultIsInvalidPcLoad()) {
		PR_EXC("  Illegal load of EXC_RETURN into PC\n");
	}
	if (_ScbUsageFaultIsInvalidState()) {
		PR_EXC("  Illegal use of the EPSR\n");
	}
	if (_ScbUsageFaultIsUndefinedInstr()) {
		PR_EXC("  Attempt to execute undefined instruction\n");
	}

	_ScbUsageFaultAllFaultsReset();
}
Esempio n. 6
0
/**
 *
 * @brief Dump information regarding fault (FAULT_DUMP == 1)
 *
 * Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 1
 * (short form).
 *
 * eg. (precise bus error escalated to hard fault):
 *
 * Fault! EXC #3, Thread: 0x200000dc, instr: 0x000011d3
 * HARD FAULT: Escalation (see below)!
 * MMFSR: 0x00000000, BFSR: 0x00000082, UFSR: 0x00000000
 * BFAR: 0xff001234
 *
 * @return N/A
 */
void _FaultDump(const NANO_ESF *esf, int fault)
{
	int escalation = 0;

	PR_EXC("Fault! EXC #%d, Thread: %x, instr @ %x\n",
	       fault,
	       sys_thread_self_get(),
	       esf->pc);

	if (3 == fault) { /* hard fault */
		escalation = _ScbHardFaultIsForced();
		PR_EXC("HARD FAULT: %s\n",
		       escalation ? "Escalation (see below)!"
				  : "Bus fault on vector table read\n");
	}

	PR_EXC("MMFSR: %x, BFSR: %x, UFSR: %x\n",
	       __scs.scb.cfsr.byte.mmfsr.val,
	       __scs.scb.cfsr.byte.bfsr.val,
	       __scs.scb.cfsr.byte.ufsr.val);

	if (_ScbMemFaultIsMmfarValid()) {
		PR_EXC("MMFAR: %x\n", _ScbMemFaultAddrGet());
		if (escalation) {
			_ScbMemFaultMmfarReset();
		}
	}
	if (_ScbBusFaultIsBfarValid()) {
		PR_EXC("BFAR: %x\n", _ScbBusFaultAddrGet());
		if (escalation) {
			_ScbBusFaultBfarReset();
		}
	}

	/* clear USFR sticky bits */
	_ScbUsageFaultAllFaultsReset();
}
Esempio n. 7
0
/**
 *
 * @brief Dump bus fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static int _BusFault(NANO_ESF *esf, int fromHardFault)
{
	PR_FAULT_INFO("***** BUS FAULT *****\n");

	if (SCB->CFSR & SCB_CFSR_STKERR_Msk) {
		PR_FAULT_INFO("  Stacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_UNSTKERR_Msk) {
		PR_FAULT_INFO("  Unstacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_PRECISERR_Msk) {
		PR_FAULT_INFO("  Precise data bus error\n");
		/* In a fault handler, to determine the true faulting address:
		 * 1. Read and save the BFAR value.
		 * 2. Read the BFARVALID bit in the BFSR.
		 * The BFAR address is valid only if this bit is 1.
		 *
		 * Software must follow this sequence because another
		 * higher priority exception might change the BFAR value.
		 */
		STORE_xFAR(bfar, SCB->BFAR);

		if (SCB->CFSR & SCB_CFSR_BFARVALID_Msk) {
			PR_EXC("  BFAR Address: 0x%x\n", bfar);
			if (fromHardFault) {
				/* clear SCB_CFSR_BFAR[VALID] to reset */
				SCB->CFSR &= ~SCB_CFSR_BFARVALID_Msk;
			}
		}
		/* it's possible to have both a precise and imprecise fault */
		if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
			PR_FAULT_INFO("  Imprecise data bus error\n");
		}
	} else if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
		PR_FAULT_INFO("  Imprecise data bus error\n");
	} else if (SCB->CFSR & SCB_CFSR_IBUSERR_Msk) {
		PR_FAULT_INFO("  Instruction bus error\n");
#if !defined(CONFIG_ARMV7_M_ARMV8_M_FP)
	}
#else
	} else if (SCB->CFSR & SCB_CFSR_LSPERR_Msk) {
Esempio n. 8
0
/**
 *
 * @brief Dump MPU fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _MpuFault(const NANO_ESF *esf, int fromHardFault)
{
	PR_EXC("***** MPU FAULT *****\n");

	_FaultThreadShow(esf);

	if (_ScbMemFaultIsStacking()) {
		PR_EXC("  Stacking error\n");
	} else if (_ScbMemFaultIsUnstacking()) {
		PR_EXC("  Unstacking error\n");
	} else if (_ScbMemFaultIsDataAccessViolation()) {
		PR_EXC("  Data Access Violation\n");
		if (_ScbMemFaultIsMmfarValid()) {
			PR_EXC("  Address: 0x%x\n", _ScbMemFaultAddrGet());
			if (fromHardFault) {
				_ScbMemFaultMmfarReset();
			}
		}
	} else if (_ScbMemFaultIsInstrAccessViolation()) {
		PR_EXC("  Instruction Access Violation\n");
	}
}
Esempio n. 9
0
/**
 *
 * @brief Dump MPU fault information
 *
 * See _FaultDump() for example.
 *
 * @return error code to identify the fatal error reason
 */
static u32_t _MpuFault(NANO_ESF *esf, int fromHardFault)
{
	u32_t reason = _NANO_ERR_HW_EXCEPTION;

	PR_FAULT_INFO("***** MPU FAULT *****\n");

	if (SCB->CFSR & SCB_CFSR_MSTKERR_Msk) {
		PR_FAULT_INFO("  Stacking error\n");
	}
	if (SCB->CFSR & SCB_CFSR_MUNSTKERR_Msk) {
		PR_FAULT_INFO("  Unstacking error\n");
	}
	if (SCB->CFSR & SCB_CFSR_DACCVIOL_Msk) {
		PR_FAULT_INFO("  Data Access Violation\n");
		/* In a fault handler, to determine the true faulting address:
		 * 1. Read and save the MMFAR value.
		 * 2. Read the MMARVALID bit in the MMFSR.
		 * The MMFAR address is valid only if this bit is 1.
		 *
		 * Software must follow this sequence because another higher
		 * priority exception might change the MMFAR value.
		 */
		u32_t mmfar = SCB->MMFAR;

		if (SCB->CFSR & SCB_CFSR_MMARVALID_Msk) {
			PR_EXC("  MMFAR Address: 0x%x\n", mmfar);
			if (fromHardFault) {
				/* clear SCB_MMAR[VALID] to reset */
				SCB->CFSR &= ~SCB_CFSR_MMARVALID_Msk;
			}
#if defined(CONFIG_HW_STACK_PROTECTION)
			/* When stack protection is enabled, we need to see
			 * if the memory violation error is a stack corruption.
			 * For that we investigate the address fail.
			 */
			struct k_thread *thread = _current;
			u32_t guard_start;
			if (thread != NULL) {
#if defined(CONFIG_USERSPACE)
				guard_start =
					thread->arch.priv_stack_start ?
					(u32_t)thread->arch.priv_stack_start :
					(u32_t)thread->stack_obj;
#else
				guard_start = thread->stack_info.start;
#endif
				if (mmfar >= guard_start &&
					mmfar < guard_start +
					MPU_GUARD_ALIGN_AND_SIZE) {
					/* Thread stack corruption */
					reason = _NANO_ERR_STACK_CHK_FAIL;
				}
			}
#else
		(void)mmfar;
#endif /* CONFIG_HW_STACK_PROTECTION */
		}
	}
	if (SCB->CFSR & SCB_CFSR_IACCVIOL_Msk) {
		PR_FAULT_INFO("  Instruction Access Violation\n");
	}
#if defined(CONFIG_ARMV7_M_ARMV8_M_FP)
	if (SCB->CFSR & SCB_CFSR_MLSPERR_Msk) {
		PR_FAULT_INFO(
			"  Floating-point lazy state preservation error\n");
	}
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */

	/* Assess whether system shall ignore/recover from this MPU fault. */
	if (_MemoryFaultIsRecoverable(esf)) {
		reason = _NANO_ERR_RECOVERABLE;
	}

	return reason;
}
Esempio n. 10
0
/**
 *
 * @brief Dump reserved exception information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _ReservedException(const NANO_ESF *esf, int fault)
{
	PR_EXC("***** %s %d) *****\n",
	       fault < 16 ? "Reserved Exception (" : "Spurious interrupt (IRQ ",
	       fault - 16);
}
Esempio n. 11
0
/**
 *
 * @brief Dump debug monitor exception information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _DebugMonitor(const NANO_ESF *esf)
{
	PR_EXC("***** Debug monitor exception (not implemented) *****\n");
}