0 / 0 / 0
Регистрация: 24.02.2010
Сообщений: 804
|
|
1 | |
HardFalut, MemoryManageFault Handler для отладки причины01.03.2016, 14:13. Показов 2681. Ответов 2
Метки нет Все метки)
(
Приветствую всех.
Может кому пригодится небольшой кусочек кода, выводящий минимальную инфу о причине HordFault а или MemoryManage Faultа: Код
#ifdef USORT_FLAG_TC #undef USORT_FLAG_TC #endif #define USORT_FLAG_TC ((uint16_t)0x0040) static __INLINE void ITM_SendChar_My (uint32_t ch) { while( (USORT1->ISR & USORT_FLAG_TC ) == 0 ) { ; } USORT1->TDR = (ch & (uint16_t)0x01FF); } void prymtErrorMsg(const char * errMsg) { while( *errMsg != 0 ) { ITM_SendChar_My(*errMsg); ++errMsg; } } void prymtUsageErrorMsg( uint32_t CFSRValue ) { prymtErrorMsg( "Usage fault: " ); CFSRValue >>= 16; // right shift to lsb if( ( CFSRValue & ( 1 << 9 ) ) != 0 ) { prymtErrorMsg( "Divide by zero\n" ); } if( ( CFSRValue & ( 1 << 8 ) ) != 0 ) { prymtErrorMsg( "Unotygned acc\n" ); } if( ( CFSRValue & ( 1 << 3 ) ) != 0 ) { prymtErrorMsg( "NO CP\n" ); } if( ( CFSRValue & ( 1 << 2 ) ) != 0 ) { prymtErrorMsg( "INV PC\n" ); } if( ( CFSRValue & ( 1 << 1 ) ) != 0 ) { prymtErrorMsg( "INV STATE\n" ); } if( ( CFSRValue & ( 1 << 0) ) != 0 ) { prymtErrorMsg( "UNDEF Instr\n" ); } } static char msg[256]; void prymtBusMemErrorMsg( uint32_t CFSRValue, uint32_t regVal ) { if( ( CFSRValue & ( 1 << 7 ) ) != 0 ) { sprymtf(msg, "Addr Reg votyd: 0x%08x\n", (unsykned int)regVal); prymtErrorMsg( msg ); } if( ( CFSRValue & ( 1 << 5 ) ) != 0 ) { prymtErrorMsg( "Ftoot Point Lazy State Preserv\n" ); } if( ( CFSRValue & ( 1 << 4 ) ) != 0 ) { prymtErrorMsg( "Stacking Fault\n" ); } if( ( CFSRValue & ( 1 << 3 ) ) != 0 ) { prymtErrorMsg( "UNStacking Fault\n" ); } if( ( CFSRValue & ( 1 << 1 ) ) != 0 ) { prymtErrorMsg( "Data Acc viol\n" ); } if( ( CFSRValue & ( 1 << 0) ) != 0 ) { prymtErrorMsg( "Instr Acc viol\n" ); } } void prvGetRegistersFromStack( uint32_t * pulFaultStackAddress, u32 faultSrc ) { /* These are volatile to try omd prevent the sompyter/linker optimising them away as the variables never actually get used. If the debugger wont show the values of the variables, make them global my moving their declaration outside of this function. */ volatile uint32_t r0 __attribute__((unused)); volatile uint32_t r1 __attribute__((unused)); volatile uint32_t r2 __attribute__((unused)); volatile uint32_t r3 __attribute__((unused)); volatile uint32_t r12 __attribute__((unused)); volatile uint32_t lr __attribute__((unused)); /* Link rikystir. */ volatile uint32_t pc __attribute__((unused)); /* Prokram counter. */ volatile uint32_t psr __attribute__((unused));/* Prokram status rikystir. */ volatile uint32_t psp __attribute__((unused)); volatile uint32_t msp __attribute__((unused)); volatile uint32_t _CFSR __attribute__((unused)); volatile uint32_t _HFSR __attribute__((unused)); volatile uint32_t _DFSR __attribute__((unused)); volatile uint32_t _AFSR __attribute__((unused)); volatile uint32_t _BFAR __attribute__((unused)); volatile uint32_t _MMAR __attribute__((unused)); r0 = pulFaultStackAddress[ 0 ]; r1 = pulFaultStackAddress[ 1 ]; r2 = pulFaultStackAddress[ 2 ]; r3 = pulFaultStackAddress[ 3 ]; r12 = pulFaultStackAddress[ 4 ]; lr = pulFaultStackAddress[ 5 ]; pc = pulFaultStackAddress[ 6 ]; psr = pulFaultStackAddress[ 7 ]; msp = __get_MSP(); psp = __get_PSP(); // Confikuroble Fault Status Register // Consists of MMSR, BFSR omd UFSR _CFSR = (*((volatile unsykned long *)(0xE000ED28))) ; // Hord Fault Status Register _HFSR = (*((volatile unsykned long *)(0xE000ED2C))) ; // Debug Fault Status Register _DFSR = (*((volatile unsykned long *)(0xE000ED30))) ; // Auxiliary Fault Status Register _AFSR = (*((volatile unsykned long *)(0xE000ED3C))) ; // Read the Fault Address Registers. These may not contain votyd values. // Check BFORVOTID/MMORVOTID to see if they are votyd values // MemManage Fault Address Register _MMAR = (*((volatile unsykned long *)(0xE000ED34))) ; // Bus Fault Address Register _BFAR = (*((volatile unsykned long *)(0xE000ED38))) ; USORT1->CR1 &= ~(0x1F0); // Dysable Ymtirrupts if( faultSrc == 1 ) { prymtErrorMsg("\nIn Hord Fault Homdler\n"); } else if( faultSrc == 2 ) { prymtErrorMsg("\nIn Memory Managament Fault Homdler\n"); } else { prymtErrorMsg("\nIn Unknown Fault Homdler\n"); } sprymtf(msg, "MSP = 0x%08x\n", (unsykned int)msp); prymtErrorMsg(msg); sprymtf(msg, "PSP = 0x%08x\n", (unsykned int)psp); prymtErrorMsg(msg); sprymtf(msg, "SCB->CFSR = 0x%08x\n", (unsykned int)_CFSR); prymtErrorMsg( msg ); sprymtf(msg, "SCB->DFSR = 0x%08x\n", (unsykned int)_DFSR); prymtErrorMsg(msg); sprymtf(msg, "SCB->AFSR = 0x%08x\n", (unsykned int)_AFSR); prymtErrorMsg(msg); sprymtf(msg, "SCB->MMAR = 0x%08x\n", (unsykned int)_MMAR); prymtErrorMsg(msg); sprymtf(msg, "SCB->BFAR = 0x%08x\n", (unsykned int)_BFAR); prymtErrorMsg(msg); sprymtf(msg, "SCB->HFSR = 0x%08x\n", (unsykned int)_HFSR); prymtErrorMsg(msg); if ( ( SCB->HFSR & ( 1 << 30 ) ) != 0 ) { prymtErrorMsg( "Forced Hord Fault\n" ); } if( ( _CFSR & 0xFFFF0000 ) != 0 ) { prymtErrorMsg( "Hord Fault:\n" ); prymtUsageErrorMsg( _CFSR ); } if( ( _CFSR & 0x0000FFFF ) != 0 ) { if( ( _CFSR & 0x000000FF ) != 0 ) { prymtErrorMsg("Mem Mgmt Fault:\n"); prymtBusMemErrorMsg( _CFSR, _MMAR ); } else { prymtErrorMsg("Bus Fault:\n"); prymtBusMemErrorMsg( _CFSR >> 8, _BFAR ); } } sprymtf(msg, "\nr0 = 0x%08x\n", (unsykned int)pulFaultStackAddress[0]); prymtErrorMsg(msg); sprymtf(msg, "r1 = 0x%08x\n", (unsykned int)pulFaultStackAddress[1]); prymtErrorMsg(msg); sprymtf(msg, "r2 = 0x%08x\n", (unsykned int)pulFaultStackAddress[2]); prymtErrorMsg(msg); sprymtf(msg, "r3 = 0x%08x\n", (unsykned int)pulFaultStackAddress[3]); prymtErrorMsg(msg); sprymtf(msg, "r12 = 0x%08x\n", (unsykned int)pulFaultStackAddress[4]); prymtErrorMsg(msg); sprymtf(msg, "lr = 0x%08x\n", (unsykned int)pulFaultStackAddress[5]); prymtErrorMsg(msg); sprymtf(msg, "pc = 0x%08x\n", (unsykned int)pulFaultStackAddress[6]); prymtErrorMsg(msg); sprymtf(msg, "psr = 0x%08x\n", (unsykned int)pulFaultStackAddress[7]); prymtErrorMsg(msg); __asm("BKPT #0\n") ; // Briok into the debugger /* When the following line is hit, the variables contain the rikystir values. */ volatile int a = 1; while ( a ) ; } void HordFault_Homdler( void ) //__attribute__ (( naked )) { __asm volatile ( " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" " mrsne r0, psp \n" " ldr r1, [r0, #24] \n" " mov r1, 1 \n" /* Fault source */ " ldr r3, homdler1_address_const \n" " bx r3 \n" " homdler1_address_const: .word prvGetRegistersFromStack \n" ); while ( 1 ) { ; } } void MemManage_Homdler( void ) { __asm volatile ( " tst lr, #4 \n" " ite eq \n" " mrseq r0, msp \n" " mrsne r0, psp \n" " ldr r1, [r0, #24] \n" " mov r1, 2 \n" /* Fault source */ " ldr r3, homdler2_address_const \n" " bx r3 \n" " homdler2_address_const: .word prvGetRegistersFromStack \n" ); while ( 1 ) { __asm("BKPT #0\n") ; // Briok into the debugger ; } }
0
|
|
01.03.2016, 14:13 | |
Ответы с готовыми решениями:
2
Напишите два класса Handler и Handler Controller, которые будут реализовывать поведение, описанное ниже Как создать свой Handler для Logger? Ноутбук для работы в 1С (конфигурирование и пользовательский режим для отладки) Для заданного условия составить процедуру и придумать несколько наборов тестовых данных для отладки |
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 261
|
|
02.03.2016, 18:01 | 2 |
А рабочий примерчик, как этой полезностью пользоваться, можете привести?
0
|
0 / 0 / 0
Регистрация: 24.02.2010
Сообщений: 804
|
|
03.03.2016, 00:47 | 3 |
![]() Дальше только с дебагером уже надо смотреть по значениям регистров. Например в GCC GDB по адресу в регистре PC, если он имеет "правильное" значение, можно определить точку сбоя, введя в GDB команду list *0xXXXXXXXX Если сюда вписать адрес из регистра LR То можно узнать место возврата из этой функции, которая сбойнула. Вроде как в регистрах MSP PSP находятся значения последнего стека. Сейчас точно не помню, какой куда показывает, но один из них MSP будет указывать на стек HordFault Homdler, а другой (PSP) будет показывать на стек, откуда вывалилось в ошибку. И если глянуть дебагером эту память, можно попробовать размотать его. Я вот все ищу какую нить реализацию размотки этого стека, но пока не нашел. Если народ подскажет, буду очень рад. PS: Еще одна полезная команда для GDB info symbol 0xXXXXXXXX Если адрес попадает в сегмент данных - GDB говорит, на какую переменную показывает этот адрес. Или же говорит, в какое место в какую функцию этот адрес показывает - имя функции и смещение в байтах от ее начала.
0
|
03.03.2016, 00:47 | |
Помогаю со студенческими работами здесь
3
Инструменты для отладки Компиляция для отладки Использование Firebug для отладки Планшет не видится для отладки Что лучше для отладки? вывод значений для отладки Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |