evgeniy1294 (18.01.2020 00:04, просмотров: 349) ответил SciFi на Самое простое:
Если немного заморочиться, то можно легко найти проблему:
struct ArchRegs
{
uint32_t r0; //!< Register R0
uint32_t r1; //!< Register R1
uint32_t r2; //!< Register R2
uint32_t r3; //!< Register R3
uint32_t r12; //!< Register R12
uint32_t lr; //!< Link register
uint32_t pc; //!< Program counter
union
{
uint32_t all;
struct
{
unsigned IPSR: 8; //!< Interrupt Program Status register (IPSR)
unsigned EPSR: 19; //!< Execution Program Status register (EPSR)
unsigned APSR: 5; //!< Application Program Status register (APSR)
} bit;
} psr; //!< Program status register.
};
#ifdef __GNUC__
#ifdef __clang__
void mcu::isr::HardFault[[clang::optnone]]()
#else
void mcu::isr::HardFault[[gnu::optimize("-O0")]]()
#endif
#endif
{
volatile uint32_t out = 0;
volatile core::ArchRegs* archregs;
// Read fault information
shcsr.all = *(uint32_t*)(0xE000ED24);
hfsr.all = *(uint32_t*)(0xE000ED2c);
mfsr.all = *(uint8_t* )(0xE000ED28);
bfsr.all = *(uint8_t* )(0xE000ED29);
ufsr.all = *(uint16_t*)(0xE000ED2a);
mmar = *(uint32_t*)(0xE000ED34);
bfar = *(uint32_t*)(0xE000ED38);
// Halt execution
// If registers indicate readable memory, change the variable value to != 0 to continue execution.
while(out == 0)
{
asm("NOP");
}
out = 0;
// Get context pointer
archregs = (core::ArchRegs*)(__get_MSP()+8);
// Halt execution
// To step out of the HardFaultHandler, change the variable value to != 0.
while(out == 0)
{
asm("NOP");
}
return;
}
Ещё пример с валидацией указателя:
bool mcu::core::ValidatePointer(volatile uint8_t* pointer)
{
// Cortex-M3, Cortex-M4, Cortex-M4F, Cortex-M7 are supported
bool is_valid = true;
// Clear BFARVALID flag
SCB->CFSR |= SCB_CFSR_BFARVALID_Msk;
uint32_t mask = __get_FAULTMASK();
// Ignore BusFault by enabling BFHFNMIGN and disabling interrupts
__disable_fault_irq(); //__ASM volatile ("cpsid f" : : : "memory");
SCB->CCR |= SCB_CCR_BFHFNMIGN_Msk;
// probe pointer in question
*pointer;
// Check BFARVALID flag
if ((SCB->CFSR & SCB_CFSR_BFARVALID_Msk) != 0)
is_valid = false; // Bus Fault occured reading the address
// Reenable BusFault by clearing BFHFNMIGN
SCB->CCR &= ~SCB_CCR_BFHFNMIGN_Msk;
__set_FAULTMASK(mask);
return is_valid;
}