ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Вторник
23 апреля
893359
evgeniy1294 (03.01.2019 21:16, просмотров: 4790)
Что-то обленился я совсем. Давно хотел сделать умный обработчик для HardFault'a, тут наткнулся на решения segger'a, решил повторить функционал. Посмотрел я на их унылый ассемблер, загрустил и родил вот это: namespace core { struct archregs_t { 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. }; } void isr::HardFaultHandler() { uint32_t out = 0; // 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_t*)((&out)+1); // Halt execution // To step out of the HardFaultHandler, change the variable value to != 0. while(out == 0) { asm("nop"); } return; } Идея в том, что при вызове прерывания ядро пихает контекст, представленный archregs_t, в стек. Указатель стека при этом продавливается на следующую позицию, в которой создаётся переменная out, т.е поднявшись в стеке на 4 байта я получаю указатель на контекст. Указатель на контекст позволяет этот контекст править, тем самым я могу вернуться к точке вылета в hardfault, встать перед ней или после (или перейти в любое место программы), задав адрес вручную. Из минусов, потенциальная зависимость от компилятора и оптимизации. С выключенной оптимизацией clang отработал правильно, проверю на gcc и врублю оптимизацию. Работает на ядрах M3, M4 и M4F, на M0 и M0+ пока не проверял, на F7 и H7 может не работать.