Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: WWDT у STM32
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
123kill12
К контроллеру подключены разные микросхемы.
В коде есть пара циклов которые могут зависнуть если эти микросхемы вдруг откажут. вероятность очень маленькая но есть. Простая перезагрузка не выход. так как перезагрузка контроллера может нарушить работу устройств которые с ним связаны ну вообще не желательно. так же хотелось бы чтоб устройство себя могло сдиагностировать.

пришел к выводу что IWDT не выход. у STM есть WWDT, который имеет свое прерывание и накладывание этого таймера на циклы которые могут повиснуть очень удобно.
Вот у меня возник вопрос как им пользоваться. ну как настроить и запустит тут все ясно.
Но вот повис цикл у меня. WWDT досчитал до 0 и вызвал прерывание. Что делать в прерывании чтоб выйти из повисшего цикла.

Думаю можно сделать какой нить глобальный регистр с битами. выставлять соотвествующий бит перед заходом в цикл и сбрасывать после выхода. В прерывании по этим битам определять какой цикл и изменяет значения так чтоб программа вывалилась из цикла.

но может есть проще путь?
maksimp
В прерывании WWDT выставить флаг (глобальной переменной типа unsigned char присвоить значение 1). В цикле его на каждой итерации проверять и как стал 1 то прекращать работу цикла. Перед началом цикла его установить в 0.
demiurg_spb
Можно и более жёскоsm.gif поступать (что-то на подобии исключений), ручками раскрутить/подправить стек так чтобы возврат из обработчика прерывания был совершён в точку вызова процедуры в которой возможно зависание, ну и конечно нужно чтобы код ошибки эта функция возвратила отличный от OK.
Таким макаром будут не нужны никакие маячащие в коде флаги лишь небольшой пролог-эпилог в виде:
Код
ENTER_EXCEPTION_BLOCK();
...
LEAVE_EXCEPTION_BLOCK();
Всё равно таймер нужно было где-то запускать и останавливать.

Остаётся вопрос как определить границы стекового фрейма функции. Может у кого есть идеи (в прологе фигачить что-то уникальное в стек)?

Я тоже заинтересован в подобного рода механизме. Предлагаю автору публиковать свои результаты, ну а мы по мере свободного времени тоже поучаствуем.
Flexz
А можно использовать ОС. Контрольный поток проверяет рабочие на зависания, при обнаружении оного рабочий поток просто перезапускается.
123kill12
Что то я не могу понять в WWDT.
Нажмите для просмотра прикрепленного файла

у него два режима. с компаратором и когда досчитывает до 3F.

3 регистра
в первом
WDGA - разрешения сброса или просто говоря включение таймера
T[6:0] - значение счетчика

в втором
EWI - написано как то необычно. это просто разрешение прерывания. причем тип RS тоесть могу читать и писать. но не могу записать туда 0. 0 там только после перезагрузки.
прерывание происходит когда значение опускается ниже 0x40h в T[6:0]
WDGTB[1:0] - делитель частоты. мы берем (PCLK1/4096)/(WDGTB+1)
W[6:0] - значение для сравнения

в третьем
EWIF - флаг что сработало прерывание.

EWIF как EWI все понятно, только смущает "Early wakeup"(раннее пробуждение) такое ощущение что он сбрасывает систему а потом после перезапуска срабатывает прерывание.
Когда я быстро просмотрел его, для того чтоб проверить подходит он мне или нет, у меня возникло впечетление что можно отключить ресет при помощи WDGA и компаратор будет просто генерировать прерывания. Но теперь мне кажется что это не так((( поэтому лезу в Application note AN3268.
(файл с фунциями http://dox.openpilot.org/Firmware/OpenPilo..._8c_source.html , а main и stm32f10x_it приложил)

/* NVIC configuration */
//++++++++++++++++++++++++++++
#define ena_WWDT NVIC_ISER_SETENA_0;
NVIC->ISER[0] |= ena_WWDT;
/* WWDG configuration */
/* Enable WWDG clock */
RCC->APB1ENR |= RCC_APB1ENR_WWDGEN;
/* WWDG clock counter */
WWDG->CFR |= WWDG_CFR_WDGTB0;
/* Set Window value to 65 */
WWDG->CFR |= 0x41;
/* Enable WWDG and set counter value to 127*/
WWDG->CR |= 0x7F;
/* Clear EWI flag */
WWDG->SR &=~WWDG_SR_EWIF;
/* Enable EW interrupt */
WWDG->CFR |=WWDG_CFR_EWI;
//++++++++++++++++++++++++++


void WWDG_IRQHandler(void){
/* Update WWDG counter */
WWDG->CR |= 0x7F;
/* Clear EWI flag */
WWDG->SR &=~WWDG_SR_EWIF;
//+++++++
//действие
//+++++++}

Ну вот мы его инизилизировали и включили. но как его выключить?

единственная мысль это сделать так.
void WWDT_ON(void)
{
/* Enable WWDG clock */
RCC->APB1ENR |= RCC_APB1ENR_WWDGEN;
/* Update WWDG counter */
WWDG->CR |= 0x7F;
/* Clear EWI flag */
WWDG->SR &=~WWDG_SR_EWIF;
}

void WWDT_OFF(void)
{
/* disable WWDG clock */
RCC->APB1ENR |= RCC_APB1ENR_WWDGRST;
}

кто знает лучше??? подскажите. Плз.

maksimp
Цитата(demiurg_spb @ Oct 26 2011, 08:38) *
Можно и более жёскоsm.gif поступать (что-то на подобии исключений), ручками раскрутить/подправить стек так чтобы возврат из обработчика прерывания был совершён в точку вызова процедуры в которой возможно зависание,

В стандартной библиотеке Си есть для этого функции setjmp и longjmp. И ещё ядру нужно сказать после этого, что программа уже не находится в обработчике прерывания.
demiurg_spb
Цитата(maksimp @ Oct 27 2011, 07:31) *
В стандартной библиотеке Си есть для этого функции setjmp и longjmp. И ещё ядру нужно сказать после этого, что программа уже не находится в обработчике прерывания.
Спасибо за hint! Попробую обязательно.
Ну а насчёт прерываний, может ничего и не придётся делать, нужно смотреть реализацию setjmp и longjmp.
ИМХО, они могут это учитывать.
Вот нашёл практически то, о чём говорил, правда без прерываний.
123kill12
вообще я спросил про то как остановить WWDT, но все равно спасибо за советы.

НУ И ЕЩЕ почему то прерывание не срабатывает((((((((

счетчик уменьшается.
demiurg_spb
Я всё о своём любимомsm.gif
Набрёл случайно на
http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html

модератору: Может чтобы не раздражать ТС разделить темы и создать тему типа "Си - exception handling своими руками"
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.