evgeniy1294 (08.07.2019 08:28 - 08:31, просмотров: 253) ответил mrVladimir на Я, можно сказать, начинающий. Не могли бы Вы вкратце пояснить как организовать ловушку на прерывание hardfault.
Для ARM все довольно просто(Cortex-M):
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 isr::HardFault[[clang::optnone]]()
#else
void isr::HardFault[[gnu::optimize("-O0")]]()
#endif
#endif
{
volatile uint32_t out = 0;
volatile core::ArchRegs* archregs;
// Read fault information
shcsr.all = *(uint32_t*)(0xe000'ed24);
hfsr.all = *(uint32_t*)(0xe000'ed2c);
mfsr.all = *(uint8_t* )(0xe000'ed28);
bfsr.all = *(uint8_t* )(0xe000'ed29);
ufsr.all = *(uint16_t*)(0xe000'ed2a);
mmar = *(uint32_t*)(0xe000'ed34);
bfar = *(uint32_t*)(0xe000'ed38);
// 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;
}
Подробно описано в мануале на ядро. Если выйти из прерывания, то вернешься в точку вылета, если править контекст, то можно попасть в любую точку программы - например, в повторную инициализацию.