21.05.2013, 17:02
|
|
Временная регистрация
Регистрация: 04.05.2008
Адрес: Ставрополь
Сообщений: 63
Сказал спасибо: 2
Сказали Спасибо 21 раз(а) в 17 сообщении(ях)
|
Программа уходит в HardFault (STM32)
Добрый день.
Прошу помощи по следующей проблеме.
Контроллер STM32F207
Программа крутится на freeRTOS. Используются очереди.
И периодически контроллер уходит на HardFault.
Обработчик прерывания таймер захвата, настроен на захват обеих фронтов, получает 2 значения вычисляет разницу между ними, записывает в очередь
PHP код:
|
void TimerSystemSensorIRQ(void)
{
__IO uint32_t ch_flag[Q_CH] = {0,0,0,0};
__IO uint32_t i;
static uint32_t ICReadValue[Q_CH][2];
portBASE_TYPE res = 0;
if(TIM4-›SR & TIM_IT_CC1)
{
TIM4-›SR = (uint16_t)~TIM_IT_CC1; //Clear flag interrupt
ICReadValue[CH11][CaptureNumber[CH11]] = TIM4-›CCR1;
ch_flag[CH11] = 1;
if(!CaptureNumber[0]) //первое измерение
{
CaptureNumber[0] = 1;
CapturePWValue[0] = 0;
}
else
{
CaptureNumber[0] = 0;
if(ICReadValue[CH11][1] ›= ICReadValue[CH11][0])
CapturePWValue[CH11] = ICReadValue[CH11][1] - ICReadValue[CH11][0];
else
CapturePWValue[CH11] = ((MAX_TIMER_VALUE - ICReadValue[CH11][0]) + ICReadValue[CH11][1]);
res = xQueueSendFromISR(CaptPWQueue[CH11], &CapturePWValue[CH11], 0);// send queue
}
}
TIM4-›SR = 0;
}
|
Задача читает значения из очереди пишет их в структуру генерирует события
PHP код:
|
void SSReadPW(LOOP_TypeDef ch, TYPE_SS_DEV type, unsigned char addr)
{
unsigned char i;
uint32_t event = 0;
uint32_t read_pw_val;
portBASE_TYPE time_end;
Ctrl_5V_On(ch); //switch On 5V
CaptureNumber[ch] = 0; //сброс количества замеров
TimerCaptureEnDis(ch, ENABLE); //start capture timer
for(i = 0; i ‹ Q_PW; i++)
{
Ctrl_24V_Off(ch); //switch off 24V
time_end = xQueueReceive(CaptPWQueue[ch], &read_pw_val, TIME_WAIT_QUEUE_CAPT); // interrupt queue
if(time_end == pdPASS)
{
if(read_pw_val › 0)
{
SS_Sensor[LOOP1][addr].PW[i] = read_pw_val; //write in struct cur PW value
SS_Sensor[LOOP1][addr].PW_Level[i] = (read_pw_val * 10) / SS_Sensor[LOOP1][addr].PW[0];
HandlePWs(ch, type, addr);// обработать полученные данные
}
}
else if(time_end == errQUEUE_FULL)
{
SS_Sensor[LOOP1][addr].OldState = SS_Sensor[LOOP1][addr].State;
break;
}
else
{
Ctrl_24V_On(ch);
}
vTaskDelay(DELAY_500_US); //delay 250 us
Ctrl_24V_On(ch); //switch on 24V
vTaskDelay(DELAY_250_US); //delay 250 us
}
vTaskDelay(DELAY_250_US); //delay 250 us
TimerCaptureEnDis(ch, DISABLE); //stop capture timer
vTaskDelay(TIME_WAIT_SOFT_RESET); //soft reset sensor
}
|
После запуска через случайное время вылетает в HardFault
если закомментировать вот эти строки
else if(time_end == errQUEUE_FULL)
{
SS_Sensor[LOOP1][addr].OldState = SS_Sensor[LOOP1][addr].State;
break;
}
else
{
Ctrl_24V_On(ch);
}
то все идет нормально.
Пробовал увеличивать размер стэка, приоритет задачи, приоритет прерывания ничего не помогает.
Обшарил все сайты что может быть?
|
|
|
|
23.05.2013, 14:58
|
|
Прохожий
Регистрация: 05.11.2006
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Программа уходит в HardFault (STM32)
1) Если в прерывании используете сервисы ОС, в конце обработчика вызывайте portEND_SWITCHING_ISR. Пример:
Код:
|
void SERIAL_UsartIRQ(SUsart *_usart)
{
long xHigherPriorityTaskWoken = pdFALSE;
...
xSemaphoreGiveFromISR(_usart-›TxSemaphore, &xHigherPriorityTaskWoken);
...
xQueueSendFromISR(_usart-›RxQueue, (void*) &byte, &xHigherPriorityTaskWoken);
...
xSemaphoreGiveFromISR(_usart-›RxSemaphore, &xHigherPriorityTaskWoken);
...
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
} |
2) Внимательно проверьте приоритеты прерываний. Приоритет пользовательского прерывания, которое использует сервисы ОС, должен быть ниже приоритета configMAX_SYSCALL_INTERRUPT_PRIORITY.
http://www.freertos.org/a00110.html#kernel_priority
3) Надеюсь, Вы не забыли включить
Код:
|
VIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); |
при старте системы
|
|
|
Сказали "Спасибо" InsolentS
|
|
|
23.05.2013, 15:09
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Программа уходит в HardFault (STM32)
За такой обработчик прерывания нужно бы наказывать как-то. Hard fault подойдет.
|
|
|
|
23.05.2013, 17:00
|
|
Временная регистрация
Регистрация: 04.05.2008
Адрес: Ставрополь
Сообщений: 63
Сказал спасибо: 2
Сказали Спасибо 21 раз(а) в 17 сообщении(ях)
|
Re: Программа уходит в HardFault (STM32)
2InsolentS
1 Добавил portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); не помогло
2 configMAX_SYSCALL_INTERRUPT_PRIORITY = 191
мое прерывание только Tim4_IRQ:
добавил:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
перед:
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
Попробовал предложенные Вами решения. Не помогло. Курю дальше.
2Easyrider83
Переписал обрботчик прерываний:
PHP код:
|
void TimerSystemSensorIRQ(void)
{
portBASE_TYPE res = 0;
long xHigherPriorityTaskWoken = pdFALSE;
if(TIM4-›SR & TIM_IT_CC1)
{
TIM4-›SR = (uint16_t)~TIM_IT_CC1; //Clear flag interrupt
if(CaptEnable[CH11])
{
xQueueSendFromISR(CaptPWQueue[CH11], &CaptPWValue[CH11], &xHigherPriorityTaskWoken);// send queue
}
}
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
|
Последний раз редактировалось valic; 23.05.2013 в 17:01.
Причина: исправление ошибок
|
|
|
|
24.05.2013, 08:53
|
|
Прохожий
Регистрация: 05.11.2006
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Программа уходит в HardFault (STM32)
Сообщение от valic
|
Код:
|
2 configMAX_SYSCALL_INTERRUPT_PRIORITY = 191
...
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 0; |
|
191 это decimal? это 0xBF hex - т.е. 13-ый приоритет, очень низкий.
А вот у таймера приоритет 0 - т.е. самый высокий.
Сделайте
Код:
|
configMAX_SYSCALL_INTERRUPT_PRIORITY = 0x10 или 0x20
...
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 3 .. 13; |
|
|
|
|
25.05.2013, 17:23
|
|
Временная регистрация
Регистрация: 04.05.2008
Адрес: Ставрополь
Сообщений: 63
Сказал спасибо: 2
Сказали Спасибо 21 раз(а) в 17 сообщении(ях)
|
Re: Программа уходит в HardFault (STM32)
Более подробное изучение вывело на место где происходит исключение.
При записи значения в очередь (при помощи FreeRTOS внутри обработчкиа prvCopyDataToQueue) вызывается функция memcpy, которая пытается писать данные в ячейки больше чем 0x20020000. У STM32F207 это конец оперативной памяти, поэтому возникает исключение BUS Fault, а так как оно не разрешено, вызывается HARD Fault.
Может есть какие-то настройки у FreeRTOS чтобы указать границы памяти?
По логике они указаны в stm32f2xx.h и она должна брать их оттуда.
Почему пытается писать данные за пределы?
|
|
|
|
25.05.2013, 17:53
|
|
Гуру портала
Регистрация: 20.11.2004
Сообщений: 10,015
Сказал спасибо: 936
Сказали Спасибо 2,269 раз(а) в 1,563 сообщении(ях)
|
Re: Программа уходит в HardFault (STM32)
Сообщение от valic
|
По логике они указаны в stm32f2xx.h и она должна брать их оттуда.
|
Вообще то это указывается в опциях линкера . Что за компиль ?
__________________
Осторожно , злой кот
|
|
|
|
25.05.2013, 18:02
|
|
Временная регистрация
Регистрация: 04.05.2008
Адрес: Ставрополь
Сообщений: 63
Сказал спасибо: 2
Сказали Спасибо 21 раз(а) в 17 сообщении(ях)
|
Re: Программа уходит в HardFault (STM32)
Компилятор Keil, да в линкере указано
IRAM start - 0x20000000 size - 0x20000
|
|
|
|
25.05.2013, 23:35
|
|
Прохожий
Регистрация: 05.11.2006
Сообщений: 3
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Программа уходит в HardFault (STM32)
Сообщение от valic
|
вызывается функция memcpy, которая пытается писать данные в ячейки больше чем 0x20020000.
|
У вас портится стек и отсюда ложные указатели. Вы сделали то, что я написал в сообщении #5 ?
|
|
|
|
26.05.2013, 09:15
|
|
Временная регистрация
Регистрация: 04.05.2008
Адрес: Ставрополь
Сообщений: 63
Сказал спасибо: 2
Сказали Спасибо 21 раз(а) в 17 сообщении(ях)
|
Re: Программа уходит в HardFault (STM32)
Да, сделал. Менял приоритеты, пробовал разные варианты, из указанных Вами.
Еще заметил такую особенность, в ОЗУ часть ячеек (около 500) заполнена одинаковыми данными 0xA5. и при остановке программы в некоторый момент времени я вижу эти значения регистрах общего назначения.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 19:20.
|
|