|
Прерывания Cortex-M3, HardFault_Handler |
|
|
|
Mar 15 2012, 07:28
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 19-02-07
Пользователь №: 25 487

|
Цитата(rat @ Mar 15 2012, 14:12)  void RTC_IRQHandler(void); Наверное проблема в ; Улетает прерывание в HardFault_Handler.
|
|
|
|
|
Mar 15 2012, 07:46
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 19-02-07
Пользователь №: 25 487

|
; для начала убрать надо
|
|
|
|
|
Mar 15 2012, 07:54
|

Местный
  
Группа: Свой
Сообщений: 497
Регистрация: 9-06-05
Из: Новосибирск
Пользователь №: 5 852

|
Цитата(Mareng @ Mar 15 2012, 14:46)  ; для начала убрать надо При попытке убрать ; появляется Error[Pe065]: expected a ";" Цитата(rat @ Mar 15 2012, 14:49)  При попытке убрать ; появляется Error[Pe065]: expected a ";" Поправил. Ошибка ; исчезла, но попрежнему HardFault_Handler при попытке войти в прерывание
|
|
|
|
|
Mar 15 2012, 08:03
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 19-02-07
Пользователь №: 25 487

|
Цитата(rat @ Mar 15 2012, 14:54)  Поправил. Ошибка ; исчезла, но попрежнему HardFault_Handler при попытке войти в прерывание Теперь осталось выяснить адрес какой функции записан в векторе обработчика RTC. Обычно это в startup*.s написано
|
|
|
|
|
Mar 15 2012, 08:16
|

Местный
  
Группа: Свой
Сообщений: 497
Регистрация: 9-06-05
Из: Новосибирск
Пользователь №: 5 852

|
Цитата(Сергей Борщ @ Mar 15 2012, 14:56)  Значит ошибка где-то чуть раньше, вероятно в конце предыдущей функции забыли "}". Ибо с ";" это не функция обрабочика прерывания, а объявление функции и не связанный с ним кусок кода. Это да, поправил. В дизассемблере ошибка выглядит так: сразу после выполнения RTC->CTRL |= RTC_CTRL_EN; следует POP R4, PC вот после этого шага и происходит трабл, загорается "красная рука" (как при F5) и при остановке перечисляется куча фаультных хандлеров. Цитата(Mareng @ Mar 15 2012, 15:03)  Теперь осталось выяснить адрес какой функции записан в векторе обработчика RTC. Обычно это в startup*.s написано В startup_EFM32tg.s написано: PUBWEAK RTC_IRQHandler SECTION .text:CODE:REORDER(1) RTC_IRQHandler B RTC_IRQHandler
|
|
|
|
|
Mar 15 2012, 08:22
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 19-02-07
Пользователь №: 25 487

|
Можно посмотреть в пдф-е на проц точный адрес вектора RTC, посмотреть реальный адрес функции-обработчика, а потом убедиться(просмотром памяти), что в адресе вектора записан адрес именно этой функции. Тогда уже верняк.
|
|
|
|
|
Mar 19 2012, 08:00
|
Частый гость
 
Группа: Участник
Сообщений: 89
Регистрация: 3-01-11
Пользователь №: 61 997

|
Помогите разобраться с приоритетами прерываний. У меня реализован модбас чере зперрывания от юсарт и считывание внешнего ацп через exti(сигнал готовности данных). Но когда на входе ацп 0, то модбас работает прекрасно. а когда напряжение на вхоже повышается то модбас отвечает через раз. CODE { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = IRQChannel; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ITConfig(USART,USART_IT_ERR,ENABLE); } NVIC_SetPriority(USART2_IRQn,0); //!! USART_ITConfig(USARTx,USART_IT_TC,ENABLE); USART_ITConfig(USARTx,USART_IT_RXNE,ENABLE);
/*=============================================================================== ===============================*/ void ADCRDYInterruptConfig (void) { EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Trigger =EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_InitStructure.EXTI_Line = EXTI_Line1|EXTI_Line13; EXTI_Init(&EXTI_InitStructure); } /*=============================================================================== ===============================*/ void ADCNVIC_Conf (void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /*=============================================================================== ===============================*/ void ADC2NVIC_Conf (void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } и еще, возможно ли такое, что когда выполняется бесконечный цикл while, прерывания не срабатывают? потому что запись команд и чтение АЦп сделано через spi и очень часто когда виснет программа я ее останавливаю и останавливается на строчке while (!(SPIx->SR & SPI_SR_RXNE)); Код uint8_t WriteSPI(SPI_TypeDef * SPIx,uint8_t val) { SPIx->DR = val; while (!(SPIx->SR & SPI_SR_RXNE));//while(!(SPI1->SR & 0x01)); return SPIx->DR; }
Сообщение отредактировал IgorKossak - Mar 19 2012, 10:17
Причина редактирования: [codebox] для длинных кодов!!!
|
|
|
|
|
Mar 20 2012, 08:40
|
Частый гость
 
Группа: Участник
Сообщений: 89
Регистрация: 3-01-11
Пользователь №: 61 997

|
CODE void EXTI1_IRQHandler(void) { static uint8_t ADC1_Channel=1; static unsigned char Command=ReadChannelData_0; static unsigned char Channel; static uint32_t temp=0; static uint32_t temp1=0; static uint8_t lenght=0; static uint32_t mul=0; static float k=0; static float b=0; static uint8_t ADCBuf_ind; static uint8_t HR_ind; static uint8_t adcMode;
if (EXTI->PR&(1<<1)) // Прерывание от EXTI1 { EXTI_ClearITPendingBit(EXTI_Line1); k=(float)ReadFromFlash(HR_ADDRESS+F_K_ADC*2)/100000; b=(float)ReadFromFlash(HR_ADDRESS+F_B_ADC*2)/100000;
if (IfValid(ADC_MODE_REG,ReadFromFlash(HR_ADDRESS+F_ADC_MODE_REG*2))) adcMode=ReadFromFlash(HR_ADDRESS+F_ADC_MODE_REG*2); else adcMode=0x40; if ((adcMode==0x20)||(adcMode==0x40)) { if ((adcMode>>1)&0x01) { lenght=3; mul=0x10000; } else { lenght=2; mul=0x100; } switch (ADC1_Channel) { case 1: { Channel=ReadChannelData_0; Command=WriteToModeChannel_2; HR_ind=ADC_CODE_1; ADCBuf_ind=0; ADC1_Channel++; } break; case 2: { Channel=ReadChannelData_1; Command=WriteToModeChannel_3; HR_ind=ADC_CODE_2; ADCBuf_ind=1; ADC1_Channel++; } break; case 3: { Channel=ReadChannelData_2; Command=WriteToModeChannel_4; HR_ind=ADC_CODE_3; ADCBuf_ind=2; ADC1_Channel++; } break; case 4: { Channel=ReadChannelData_3; Command=WriteToModeChannel_1; HR_ind=ADC_CODE_4; ADCBuf_ind=3; ADC1_Channel=1; } break; } temp=WriteToADC(SPI_1,Channel,8,SPI1); while (lenght) { temp1=WriteToADC(SPI_1,0x00,8,SPI1); temp=temp+temp1*mul; mul=mul/0x100; lenght--; } HoldingRegister[HR_ind]=temp; //код ацп ADCBuffer[ADCBuf_ind]=(float)temp*k+b; temp=WriteToADC(SPI_1,Command,8,SPI1); temp=WriteToADC(SPI_1,adcMode,8,SPI1); //16bit resolution } } } uint8_t WriteToADC(uint8_t type,uint8_t firstParam, uint8_t secondParam, SPI_TypeDef * thirdParam) { uint8_t temp=0;
if (type==SPI_1) temp=WriteSPI(thirdParam,firstParam); else temp=WriteSoftSPI(firstParam,secondParam); return temp; } uint8_t WriteSPI(SPI_TypeDef * SPIx,uint8_t val) { SPIx->DR = val; while (!(SPIx->SR & SPI_SR_RXNE));//while(!(SPI1->SR & 0x01)); return SPIx->DR; } uint8_t WriteSoftSPI(uint8_t val, uint8_t data_lenght) { uint8_t c;
for(c = 0; c < data_lenght; c++) { // ADC_Delay(ADC_TIM); CLR_SCK_ADC1();
if(val & 0x80) SET_SDI_ADC1(); else CLR_SDI_ADC1();
// ADC_Delay(ADC_TIM); SET_SCK_ADC1(); // ADC_Delay(ADC_TIM); val <<= 1; if(SDO_ADC1()) val |= 0x01; }
return val; } /*=============================================================================== =====*/ void ADC_Delay (TIM_TypeDef* TIMx) { TIMx->CR1|=0x01; while(!TIMx->SR&TIM_FLAG_Update) {} TIMx->CR1&=~0x01; } Вот и получается, что первый АЦП опрашивается через аппаратный эспиай МК и подвисает на while while (!(SPIx->SR & SPI_SR_RXNE)), а второй АЦП опрашивается программно реализованным эспиай и подвисает на функции задержки на while(!TIMx->SR&TIM_FLAG_Update) {}.
Сообщение отредактировал batisto4ka - Mar 20 2012, 08:41
|
|
|
|
|
Mar 20 2012, 13:08
|
Частый гость
 
Группа: Участник
Сообщений: 89
Регистрация: 3-01-11
Пользователь №: 61 997

|
они не зависают,а подвисают..если сделать функцию опроса АЦП не по гвотовности данных по внешнему прерыванию, а просто функция в фоне которая опрашивает АЦП, товсе работает, а если сделать через прерывания - то модбас отвечает через раз, и бывает такое, что опрос АЦП подвисает, потмоу что нет ответа от АЦП, по SPI не считываются данные и соотвественно след канала АЦП не опрашивается и виснет программа, либо (в случае программной реализации АЦп) подвисает таймер ..или бывает такое, что АЦП может не ответить, как тогда в таком случае можно организовать опрос через SPI, чтоб если вдруг АЦП не ответит, не висло прерывание или фон?
Сообщение отредактировал batisto4ka - Mar 20 2012, 13:12
|
|
|
|
|
Apr 1 2012, 15:38
|

Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094

|
Здравствуйте. Есть такой код: CODE #define STM32F10X_MD_VL #include "stm32f10x.h"
uint8_t change = 0;
void __EXTI0_IRQHandler (void) { if (change == 0) { change = 1; GPIOC->BSRR = GPIO_BSRR_BS8 | GPIO_BSRR_BR9; } else { change = 0; GPIOC->BSRR = GPIO_BSRR_BR8 | GPIO_BSRR_BS9; }; EXTI->PR = EXTI_PR_PR0; };
static __INLINE void system_init (void) { RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR & RCC_CR_HSERDY)) {}; RCC->CFGR |= RCC_CFGR_PLLMULL_0 | RCC_CFGR_PLLSRC; RCC->CR |= RCC_CR_PLLON; while (!(RCC->CR & RCC_CR_PLLRDY)) {}; RCC->CFGR |= RCC_CFGR_SW_1; while (!(RCC->CFGR & RCC_CFGR_SWS_PLL)) {}; RCC->APB2ENR |= (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_AFIOEN); };
int __main (void) { system_init (); GPIOC->CRH &= ~GPIO_CRH_CNF8 & ~GPIO_CRH_CNF9 & ~GPIO_CRH_MODE8 & ~GPIO_CRH_MODE9; GPIOC->CRH |= GPIO_CRH_MODE8_0 | GPIO_CRH_MODE8_1 | GPIO_CRH_MODE9_0 | GPIO_CRH_MODE9_1;
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PA; EXTI->FTSR |= EXTI_RTSR_TR0; EXTI->RTSR |= EXTI_RTSR_TR0; EXTI->IMR |= EXTI_IMR_MR0; NVIC_SetPriority (EXTI0_IRQn, 15); NVIC_EnableIRQ (EXTI0_IRQn); __enable_irq ();
GPIOC->BSRR = GPIO_BSRR_BR8 | GPIO_BSRR_BS9; while (1) { }; }; При этом содержимое *.s файла такое: CODE sram_base EQU 0x20000000 sram_size EQU 0x2000 stack_top EQU (sram_base + sram_size) ;------------------------------------------------ AREA reset, DATA, READONLY DCD stack_top DCD RESET_Handler DCD 0;NMI_Handler ; NMI Handler DCD 0;HardFault_Handler ; Hard Fault Handler DCD 0;MemManage_Handler ; MPU Fault Handler DCD 0;BusFault_Handler ; Bus Fault Handler DCD 0;UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0;SVC_Handler ; SVCall Handler DCD 0;DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD 0;PendSV_Handler ; PendSV Handler DCD 0;SysTick_Handler ; SysTick Handler ; External Interrupts DCD 0;WWDG_IRQHandler ; Window Watchdog DCD 0;PVD_IRQHandler ; PVD through EXTI Line detect DCD 0;TAMPER_IRQHandler ; Tamper DCD 0;RTC_IRQHandler ; RTC DCD 0;FLASH_IRQHandler ; Flash DCD 0;RCC_IRQHandler ; RCC DCD EXTI0_IRQHandler ; EXTI Line 0 DCD 0;EXTI1_IRQHandler ; EXTI Line 1 DCD 0;EXTI2_IRQHandler ; EXTI Line 2 DCD 0;EXTI3_IRQHandler ; EXTI Line 3 DCD 0;EXTI4_IRQHandler ; EXTI Line 4 DCD 0;DMA1_Channel1_IRQHandler ; DMA1 Channel 1 DCD 0;DMA1_Channel2_IRQHandler ; DMA1 Channel 2 DCD 0;DMA1_Channel3_IRQHandler ; DMA1 Channel 3 DCD 0;DMA1_Channel4_IRQHandler ; DMA1 Channel 4 DCD 0;DMA1_Channel5_IRQHandler ; DMA1 Channel 5 DCD 0;DMA1_Channel6_IRQHandler ; DMA1 Channel 6 DCD 0;DMA1_Channel7_IRQHandler ; DMA1 Channel 7 DCD 0;ADC1_IRQHandler ; ADC1 DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0;EXTI9_5_IRQHandler ; EXTI Line 9..5 DCD 0;TIM1_BRK_TIM15_IRQHandler ; TIM1 Break and TIM15 DCD 0;TIM1_UP_TIM16_IRQHandler ; TIM1 Update and TIM16 DCD 0;TIM1_TRG_COM_TIM17_IRQHandler ; TIM1 Trigger and Commutation and TIM17 DCD 0;TIM1_CC_IRQHandler ; TIM1 Capture Compare DCD 0;TIM2_IRQHandler ; TIM2 DCD 0;TIM3_IRQHandler ; TIM3 DCD 0 ; Reserved DCD 0;I2C1_EV_IRQHandler ; I2C1 Event DCD 0;I2C1_ER_IRQHandler ; I2C1 Error DCD 0;0 ; Reserved DCD 0 ; Reserved DCD 0;SPI1_IRQHandler ; SPI1 DCD 0 ; Reserved DCD 0;USART1_IRQHandler ; USART1 DCD 0;USART2_IRQHandler ; USART2 DCD 0 ; Reserved DCD 0;EXTI15_10_IRQHandler ; EXTI Line 15..10 DCD 0;RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line DCD 0;CEC_IRQHandler ; HDMI-CEC DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0;TIM6_DAC_IRQHandler ; TIM6 and DAC underrun DCD 0;TIM7_IRQHandler ; TIM7 ;------------------------------------------------ AREA main_code, CODE, READONLY RESET_Handler PROC ENTRY IMPORT __main LDR R0, =__main BX R0 ENDP
EXTI0_IRQHandler\ PROC IMPORT __EXTI0_IRQHandler ENDP ;------------------------------------------------ AREA stack, DATA, READWRITE SPACE 0x1000 ;------------------------------------------------ END Прогоняю его в отладчике, при нажатии на кнопку устанавливается бит PR0 регистра EXTI_PR, но перехода к обработчику прерывания не происходит, программа так и крутится в бесконечном цикле. Никак не могу понять, что я делаю не так?
Сообщение отредактировал IgorKossak - Apr 1 2012, 17:03
Причина редактирования: [codebox] для длинного кода!!!
|
|
|
|
|
Apr 2 2012, 13:44
|

Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094

|
Решил проблему, мой косяк был. Надо было делать не так: Код EXTI0_IRQHandler\ PROC IMPORT __EXTI0_IRQHandler ENDP , а так: Код EXTI0_IRQHandler\ PROC EXPORT EXTI0_IRQHandler [WEAK] ENDP Причем как я понял, в отладчике кейла перехода к обработчику не происходит в любом случае, то ли так задумано, то ли я чего не так делаю. А вот в железе изначально происходило зависание при возникновении прерывания, т.е. мк переходил по неизвестно какому адресу. Теперь с этим все ок, правда возникла другая трабла, но это в отдельной теме. p.s. - про "кодбокс" не знал, спасибо, буду использовать.
|
|
|
|
|
Apr 3 2012, 17:44
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 27-10-08
Пользователь №: 41 225

|
to batisto4ka:
1. По зависанию SPI в цикле ожидания передачи: если Вы кладете данные в аппаратный SPI и не дожидаясь окончания передачи остановите ядро (по точке останова, или просто кнопкой отладчика) то передача по SPI накроется медным тазом, и флаг окончания передачи никогда не поднимется, сам с таким сталкивался. Так что возможно Ваша проблема связана не с зависанием SPI или АЦП.
2. На мой взгляд, писать такой огромный кусок кода в прерывание, а тем более вызывать из него кучу ветвящихся процедур не очень красиво. Вполне возможно ваши проблемы возникают тогда, когда обработчик прерывания EXTI ушел в какую-нибудь функцию, а в это время возникает прерывание от USART. Я бы сделал немного по другому, в основном цикле я бы реализовал конечный автомат обработки MODBUS и опроса АЦП, а в прерываниях оставил бы лишь генерацию входов для этого автомата.
3. Если уж хотите обезопасить себя от зависания в циклах, вводите счетчики итераций - хорошая практика, к примеру:
uint8_t counter = 20;
while ((/*Ваше условие*/) && (counter--) ) { /*Ваши действия*/ }
if (!counter) {/*Обработка ошибки*/};
Таким образом из любого, потенциально опасного цикла Ваша программа выйдет либо по нормальному условию, либо через четко заданное количество итераций, а следующий за циклом if обработает аварийную ситуацию.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|