Jump to content

    

maxntf

Участник
  • Content Count

    112
  • Joined

  • Last visited

Community Reputation

0 Обычный

About maxntf

  • Rank
    Частый гость

Recent Profile Visitors

1030 profile views
  1. У меня при таких действиях происходит следующее: Первый брекпоинт на 'B .' PC = текущему адресу, LR = 0xFFFFFFF1 Переставляю указатель на BX LR, делаю шаг в отладчике и получаю PC = 0х000010BC, LR = 0x00000F03. Это вообще похоже на системную память. Что я делаю не так?
  2. Вот полный пример кода исследования HatdFault. HardFaultHandler.s AREA OSKERNEL, CODE, READONLY, ALIGN=2 PRESERVE8 EXPORT HardFault_Handler IMPORT HardFaultHandler_c THUMB HardFault_Handler movs R0, #4 mov R1, LR tst R0, R1 ;// Check EXC_RETURN in Link register bit 2. bne Uses_PSP mrs R0, MSP ;// Stacking was using MSP. b Pass_StackPtr Uses_PSP mrs R0, PSP ;// Stacking was using PSP. Pass_StackPtr ALIGN ldr R2,=HardFaultHandler_c bx R2 ;// Stack pointer passed through R0. END HardFaultHandler_c.c // System Handler Control and State Register #define SYSHND_CTRL (*(volatile unsigned int*) (0xE000ED24u)) // Memory Management Fault Status Register #define NVIC_MFSR (*(volatile unsigned char*) (0xE000ED28u)) // Bus Fault Status Register #define NVIC_BFSR (*(volatile unsigned char*) (0xE000ED29u)) // Usage Fault Status Register #define NVIC_UFSR (*(volatile unsigned short*)(0xE000ED2Au)) // Hard Fault Status Register #define NVIC_HFSR (*(volatile unsigned int*) (0xE000ED2Cu)) // Debug Fault Status Register #define NVIC_DFSR (*(volatile unsigned int*) (0xE000ED30u)) // Bus Fault Manage Address Register #define NVIC_BFAR (*(volatile unsigned int*) (0xE000ED38u)) // Auxiliary Fault Status Register #define NVIC_AFSR (*(volatile unsigned int*) (0xE000ED3Cu)) static volatile unsigned int _Continue; // Set this variable to 1 to run further static struct { struct { volatile unsigned int r0; // Register R0 volatile unsigned int r1; // Register R1 volatile unsigned int r2; // Register R2 volatile unsigned int r3; // Register R3 volatile unsigned int r12; // Register R12 volatile unsigned int lr; // Link register volatile unsigned int pc; // Program counter union { volatile unsigned int byte; struct { unsigned int IPSR : 8; // Interrupt Program Status register (IPSR) unsigned int EPSR : 19; // Execution Program Status register (EPSR) unsigned int APSR : 5; // Application Program Status register (APSR) } bits; } psr; // Program status register. } SavedRegs; union { volatile unsigned int byte; struct { unsigned int MEMFAULTACT : 1; // Read as 1 if memory management fault // is active unsigned int BUSFAULTACT : 1; // Read as 1 if bus fault exception is active unsigned int UnusedBits1 : 1; unsigned int USGFAULTACT : 1; // Read as 1 if usage fault exception // is active unsigned int UnusedBits2 : 3; unsigned int SVCALLACT : 1; // Read as 1 if SVC exception is active unsigned int MONITORACT : 1; // Read as 1 if debug monitor exception // is active unsigned int UnusedBits3 : 1; unsigned int PENDSVACT : 1; // Read as 1 if PendSV exception is active unsigned int SYSTICKACT : 1; // Read as 1 if SYSTICK exception is active unsigned int USGFAULTPENDED : 1; // Usage fault pended; usage fault started // but was replaced by a higher-priority // exception unsigned int MEMFAULTPENDED : 1; // Memory management fault pended; memory // management fault started but was // replaced by a higher-priority exception unsigned int BUSFAULTPENDED : 1; // Bus fault pended; bus fault handler was // started but was replaced by a // higher-priority exception unsigned int SVCALLPENDED : 1; // SVC pended; SVC was started but was // replaced by a higher-priority exception unsigned int MEMFAULTENA : 1; // Memory management fault handler enable unsigned int BUSFAULTENA : 1; // Bus fault handler enable unsigned int USGFAULTENA : 1; // Usage fault handler enable } bits; } syshndctrl; // System Handler Control and State // Register (0xE000ED24) union { volatile unsigned char byte; struct { unsigned char IACCVIOL : 1; // Instruction access violation unsigned char DACCVIOL : 1; // Data access violation unsigned char UnusedBits : 1; unsigned char MUNSTKERR : 1; // Unstacking error unsigned char MSTKERR : 1; // Stacking error unsigned char UnusedBits2 : 2; unsigned char MMARVALID : 1; // Indicates the MMAR is valid } bits; } mfsr; // Memory Management Fault Status // Register (0xE000ED28) union { volatile unsigned int byte; struct { unsigned int IBUSERR : 1; // Instruction access violation unsigned int PRECISERR : 1; // Precise data access violation unsigned int IMPREISERR : 1; // Imprecise data access violation unsigned int UNSTKERR : 1; // Unstacking error unsigned int STKERR : 1; // Stacking error unsigned int UnusedBits : 2; unsigned int BFARVALID : 1; // Indicates BFAR is valid } bits; } bfsr; // Bus Fault Status Register (0xE000ED29) volatile unsigned int bfar; // Bus Fault Manage Address Register // (0xE000ED38) union { volatile unsigned short byte; struct { unsigned short UNDEFINSTR : 1; // Attempts to execute an undefined // instruction unsigned short INVSTATE : 1; // Attempts to switch to an invalid state // (e.g., ARM) unsigned short INVPC : 1; // Attempts to do an exception with a bad // value in the EXC_RETURN number unsigned short NOCP : 1; // Attempts to execute a coprocessor // instruction unsigned short UnusedBits : 4; unsigned short UNALIGNED : 1; // Indicates that an unaligned access fault // has taken place unsigned short DIVBYZERO : 1; // Indicates a divide by zero has taken // place (can be set only if DIV_0_TRP // is set) } bits; } ufsr; // Usage Fault Status Register (0xE000ED2A) union { volatile unsigned int byte; struct { unsigned int UnusedBits : 1; unsigned int VECTBL : 1; // Indicates hard fault is caused by failed // vector fetch unsigned int UnusedBits2 : 28; unsigned int FORCED : 1; // Indicates hard fault is taken because of // bus fault/memory management fault/usage // fault unsigned int DEBUGEVT : 1; // Indicates hard fault is triggered by // debug event } bits; } hfsr; // Hard Fault Status Register (0xE000ED2C) union { volatile unsigned int byte; struct { unsigned int HALTED : 1; // Halt requested in NVIC unsigned int BKPT : 1; // BKPT instruction executed unsigned int DWTTRAP : 1; // DWT match occurred unsigned int VCATCH : 1; // Vector fetch occurred unsigned int EXTERNAL : 1; // EDBGRQ signal asserted } bits; } dfsr; // Debug Fault Status Register (0xE000ED30) volatile unsigned int afsr; // Auxiliary Fault Status Register // (0xE000ED3C) Vendor controlled (optional) } HardFaultRegs; void HardFaultHandler_c(unsigned int* pStack); void HardFaultHandler_c(unsigned int* pStack) { if (NVIC_HFSR & (1uL << 31)) { NVIC_HFSR |= (1uL << 31); // Reset Hard Fault status *(pStack + 6u) += 2u; // PC is located on stack at SP + 24 bytes; // increment PC by 2 to skip break instruction. return; // Return to interrupted application } // // Read NVIC registers // HardFaultRegs.syshndctrl.byte = SYSHND_CTRL; // System Handler Control and // State Register HardFaultRegs.mfsr.byte = NVIC_MFSR; // Memory Fault Status Register HardFaultRegs.bfsr.byte = NVIC_BFSR; // Bus Fault Status Register HardFaultRegs.bfar = NVIC_BFAR; // Bus Fault Manage Address Register HardFaultRegs.ufsr.byte = NVIC_UFSR; // Usage Fault Status Register HardFaultRegs.hfsr.byte = NVIC_HFSR; // Hard Fault Status Register HardFaultRegs.dfsr.byte = NVIC_DFSR; // Debug Fault Status Register HardFaultRegs.afsr = NVIC_AFSR; // Auxiliary Fault Status Register // // Halt execution // If NVIC registers indicate readable memory, change the variable value // to != 0 to continue execution. // _Continue = 0u; while (_Continue == 0u); // // Read saved registers from the stack // HardFaultRegs.SavedRegs.r0 = pStack[0]; // Register R0 HardFaultRegs.SavedRegs.r1 = pStack[1]; // Register R1 HardFaultRegs.SavedRegs.r2 = pStack[2]; // Register R2 HardFaultRegs.SavedRegs.r3 = pStack[3]; // Register R3 HardFaultRegs.SavedRegs.r12 = pStack[4]; // Register R12 HardFaultRegs.SavedRegs.lr = pStack[5]; // Link register LR HardFaultRegs.SavedRegs.pc = pStack[6]; // Program counter PC HardFaultRegs.SavedRegs.psr.byte = pStack[7]; // Program status word PSR // // Halt execution // To step out of the HardFaultHandler, change the variable value to != 0. // _Continue = 0u; while (_Continue == 0u) { } } В общем после вылета в HardFault в режиме отладки проверяю структуру HardFaultRegs и там все значения 0. Где то ошибка в функции, как узнать причину?
  3. Прошу прощения, только создал сообщение и нашел ошибку. IMPORT HardFault_Handler Брал из готового примера. Неудобно когда похожие названия. В общем исправил, вроде все собралось, буду проверять. EXPORT HardFault_Handler IMPORT HardFaultHandler_с ... ldr R2,=HardFaultHandler_с И в main.c extern void HardFaultHandler_с(unsigned int* pStack); void HardFaultHandler_с(unsigned int* pStack){ }
  4. Хочу включить в проект на Keil исследование причины вылета в HardFault. Но в ассемблере никак не могу разобраться. Смысл я в общем понял в ассемблерном куске кода копируются данные регистров которые нужно проверить, а в Си функции уже их разбираемым. Есть startupxxx.s файл, в нем есть описание этой функции по умолчанию и там стоит атрибут WEAK. Посмотрел он указывает на то, что эта функция может быть переопределена в другом месте и будет иметь приоритет. В общем создаю новый asm файл, и компилятор начинает ругаться на то, что функция дублируется. Подскажите как правильно прикрутить asm файл с функцией HardFault, чтоб в main.c описать функцию void HardFaultHandler(unsigned int* pStack){...} ;---------------------------------------------------------------------- ;File : HardFaultHandler.S ;Purpose : HardFault exception handler for Keil assembler. ;-------- END-OF-HEADER --------------------------------------------- ;*/ AREA OSKERNEL, CODE, READONLY, ALIGN=2 PRESERVE8 EXPORT HardFault_Handler IMPORT HardFault_Handler THUMB HardFault_Handler ;// This version is for Cortex M0 movs R0, #4 mov R1, LR tst R0, R1 ;// Check EXC_RETURN in Link register bit 2. bne Uses_PSP mrs R0, MSP ;// Stacking was using MSP. b Pass_StackPtr Uses_PSP mrs R0, PSP ;// Stacking was using PSP. Pass_StackPtr ALIGN ldr R2,=HardFaultHandler bx R2 ;// Stack pointer passed through R0. END ;/****** End Of File *************************************************/ Или второй вариант. Пробую написать этот код в startup файле ; Dummy Exception Handlers (infinite loops which can be modified) NMI_Handler PROC EXPORT NMI_Handler [WEAK] B . ENDP HardFault_Handler\ PROC EXPORT HardFault_Handler [WEAK] ;// This version is for Cortex M0 movs R0, #4 mov R1, LR tst R0, R1 ;// Check EXC_RETURN in Link register bit 2. bne Uses_PSP mrs R0, MSP ;// Stacking was using MSP. b Pass_StackPtr Uses_PSP mrs R0, PSP ;// Stacking was using PSP. Pass_StackPtr ALIGN ldr R2,=HardFaultHandler bx R2 ;// Stack pointer passed through R0. B . ENDP SVC_Handler PROC ... А в main.c прописываю extern void HardFaultHandler(unsigned int* pStack); void HardFaultHandler(unsigned int* pStack){ ... } Тогда компилятор ругается что в startup файле символ HardFaultHandler не определен. Может его нужно как то определить в startup.s а не в main.c
  5. Спасибо! То, что нужно. FUNC void Setup (void) { SP = _RDWORD(0x08005000); // Setup Stack Pointer PC = _RDWORD(0x08005004); // Setup Program Counter XPSR = 0x01000000; // Set Thumb bit } Setup(); LOAD %L INCREMENTAL nocode // load debug info without performing reset FUNC void OnResetExec(void) { Setup(); }
  6. Это куда? Вот файлик debug.ini FUNC void Setup (void) { SP = _RDWORD(0x08005000); // Setup Stack Pointer PC = _RDWORD(0x08005004); // Setup Program Counter XPSR = 0x01000000; // Set Thumb bit } Setup(); LOAD %L INCREMENTAL nocode // load debug info without performing reset Там бы дописать что-то типа: IF(RESET) Setup(); Только возможно ли такое? У меня сейчас получается что при загрузке отладчика срабатывает функция Setup(), а когда я нажимаю в нем Reset то SP и PC сбрасываются. И получается что нужно перезагружать отладчик.
  7. Отлаживаю в Keil - ST-Link Debugger. Попробовал по совету x893 создал файл debug.ini. Похоже это то, что мне нужно. Только там получается что при запуске отладчика, он стартует с 0x08005004, а после reset(в отладчике) уже с 0x08000004. Помогите пожалуйста допилить этот ini.
  8. Подскажите как отладчику указать, чтоб он стартовал с определенного адреса? Читал, что вроде как нужно в скаттер файле определить точку входа через команду ENTRY. Только как это сделать я не знаю, что указывать в ее параметрах? Или это не то? Сам файл у меня тот, что предлагается стандартно (с измененной адресацией под бут) ; ************************************************************* ; *** Scatter-Loading Description File generated by uVision *** ; ************************************************************* LR_IROM1 0x08005000 0x0000B000 { ; load region size_region ER_IROM1 0x08005000 0x0000B000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x200000C0 0x00001F40 { ; RW data .ANY (+RW +ZI) } }
  9. Спасибо, понял в чем тут дело. Просто раньше работал только с 8 битными МК, там таких проблем нет. А у меня получилось, что буфер char - выравнивание у него по одному байту (без атрибута, начинаться может с любого адреса), а в качестве аргумента функции я передаю указатель на этот буфер с приведением типа до uint32.
  10. Всем привет, наткнулся на такой баг - объявил буфер в глобальных переменных. Передаю его адрес в аргументе функции. И когда обращаюсь в функции к этой переменной через указатель сразу вылетаю в HardFault_Handler. Пол дня парился, и в конце концов выяснил, что линковщик расположил ее по адресу не кратному 4. Проверил, действительно если передать в функцию указатель не кратный 4, то при чтении по этому адресу вылетаем в HardFault_Handler. И теперь не могу добиться, чтоб этот буфер разместился по корректному адресу. Добавляю перед ним или после него новые переменные, адреса смещаются, и у него все равно адрес не корректный. Что делать? P.S Keil V5.23.0.0
  11. Да как только отключил, все работает нормально.
  12. Понял. То есть даже если не включены прерывания по ошибкам, флаги все равно нужно сбрасывать при их установке?
  13. Народ подскажите, натолкнулся на такую штуку: Включен USART1 на прием и разрешен только один тип прерывания по приему байта. void USART1_IRQHandler(void){ char bt; if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET){ bt = (char)USART_ReceiveData(USART1); USART_ClearITPendingBit(USART1, USART_IT_RXNE); if(bt != 0){ bUartRx[cUartRx] = bt; if(cUartRx >= (BRXSIZE-2)) bUartRx[(BRXSIZE-1)] = 0, cUartRx = 0, fUartRxOver = 1; else cUartRx++, bUartRx[cUartRx] = 0; xSemaphoreGiveFromISR(xSemRxInBuf, NULL); } } } void UART_Init(void){ GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); USART_InitStruct.USART_BaudRate = 19200; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART1, &USART_InitStruct); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE); NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPriority = 0; NVIC_Init(&NVIC_InitStruct); Так вот, во время отладки при нажатии Stop или остановки по брекпоинту, если в этот момент что то принималось в UART, то после запуска отладчика все время висим в обработчике прерывания. Причем все флаги сброшены и больше не устанавливаются, даже если приходят данные. P.S. STM32F051R8T6 Keil v.5.23.0.0
  14. Меня интересует, нужна ли повторная инициализация startup в основной программе, или от нее нужно избавиться?