реклама на сайте
подробности

 
 
> Watchdog @ SAM7X вешает AIC ?, Включение собаки убивает плату при интенсивной нагрузке
_dem
сообщение Jan 24 2008, 15:09
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



Ситуация такая :

Есть проект, на стадии конечной отладки. Все вроде проверено, оттестировано и работает. Но вот после очередной версии FW от тестеров стали приходить жалобы - платы самопроизвольно перезагружаются.
Разбор полетов и воспроизведение условий показало, что проблема в следующем :

Включение watchdog в прошивке приводит к тому, что под воздействием "DOS-атаки" UDP пакетами по ethernet плата через некоторое время (10-50 секунд) после старта перегружается по WD.

Atmel AT91SAM7X, PHY : RTL8201BL, micrium OS ( OS_VERSION = 283u ), IAR 4.41
tcp/ip стек от микриума.

Работа с WD организована следующим образом - в системном обработчике IdleTaskHook (Idle task имеет самый низкий приоритет) проверяется время, прошедшее с предыдущего сброса WD таймера. Если прошло более половины периода WD, он сбрасывается.

Код :

Код
    
void WD_Init( unsigned short period, unsigned char createTimer )
{
// enable clock
    AT91C_BASE_PMC->PMC_PCER   = (1 << AT91C_ID_SYS);                  

    if (!period)
    {
        AT91C_BASE_WDTC->WDTC_WDMR =  AT91C_WDTC_WDDIS;
        return;
    }
    
    // first, creating OS timer    
    if (createTimer)
    {
    unsigned char err;
    OS_TMR * WDTimer = OSTmrCreate(period / 3, period / 3, OS_TMR_OPT_PERIODIC, (OS_TMR_CALLBACK)WD_TimerCallback, 0, "Watchdog timer", &err );
    
    if ( (!period) || (err != OS_NO_ERR) || (!OSTmrStart( WDTimer, &err)) || (err != OS_NO_ERR) )
    {
         // disabling WD, we can't start timer
        AT91C_BASE_WDTC->WDTC_WDMR =  AT91C_WDTC_WDDIS;
        return;
    }
    }
    
    // timer started, configure WD
    // AT91C_BASE_WDTC->WDTC_WDCR
    __wd_period = period / 2;
    __wd_timestamp = OSTimeGet();
    
    period = period / 4;         // 4 msec per WD tick
    period = (period & 0x0FFF); // cut to 12 bit
                                      
    //AT91C_BASE_WDTC->WDTC_WDMR = ( AT91C_WDTC_WDDBGHLT | AT91C_WDTC_WDIDLEHLT | AT91C_WDTC_WDRSTEN | AT91C_WDTC_WDRPROC | (( period / 4 * 3) << 16) | (period) );
    AT91C_BASE_WDTC->WDTC_WDMR = ( AT91C_WDTC_WDDBGHLT | AT91C_WDTC_WDIDLEHLT | AT91C_WDTC_WDFIEN | (( period / 4 * 3) << 16) | (period) );
    // register IRQ handler
    BSP_Set_WDIRQHandler( __WD_IRQ_Handler );
}


Процедура, которая сбрасывает таймер :

Код
void WD_Tick( void )
{
    if (!__wd_period)
            return;
    if ( (OSTime - __wd_timestamp) > __wd_period)
    {
        AT91C_BASE_WDTC->WDTC_WDCR = 0xA5000001;
        __wd_timestamp = OSTime;
    }
}


Происходит интересная вещь - на каком-то этапе перестает работать AIC. Прерывания генерируются, но системный обработчик не запускается (используется protected mode), срабатывает он только от Watchdog.

зы. Грешил на приоритеты прерываний (думал, зависаю где-то в обработчике) - но только отключение собаки решило проблему.

Буду признателен beer.gif за любую информацию, кто работал с собакой на этом процессоре.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
_dem
сообщение Jan 25 2008, 10:52
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



У меня X256, ревизия A. Сейчас попробую решение, описанное в эррате - может, мне не повезло sad.gif

В IDLE таск я сбрасываю собаку, в таске ровно на 1-цу приоритетнее - мигаю диодом. Собака сама по себе работает, т.е. если по команде снаружи сделать while(1) {}, то проц сбрасывается и даже красиво оставляет лог сброса (id и имя зависшего таска, время сброса)

в момент сбоя AIC перестает обрабатывать прерывания. Единственное, что срабатывает - прерывание собаки.

ps. У меня AT91C_WDTC_WDRSTEN = 0, errata "не про нас"

=== UPDATE ===

Убрал в настройке собаки "окно срабатывания" (минимальный интервал сброса) -

т.е. вместо
AT91C_BASE_WDTC->WDTC_WDMR = ( AT91C_WDTC_WDDBGHLT | AT91C_WDTC_WDIDLEHLT | AT91C_WDTC_WDFIEN | (( period / 4 * 3) << 16) | (period) );

сделал

AT91C_BASE_WDTC->WDTC_WDMR = ( AT91C_WDTC_WDDBGHLT | AT91C_WDTC_WDIDLEHLT | AT91C_WDTC_WDFIEN | ( period) << 16) | (period) );

пока работает ( во всяком случае, ранее валилось на первых секундах, сейчас уже две минуты под тестом живетЪ

Имейте в виду на будущее smile.gif

Сообщение отредактировал _dem - Jan 25 2008, 10:53
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Jan 25 2008, 11:28
Сообщение #3


Дух погибшего транзистора
****

Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288



Цитата(_dem @ Jan 25 2008, 13:52) *
У меня X256, ревизия A.

ps. У меня AT91C_WDTC_WDRSTEN = 0, errata "не про нас"

Еще раз. Ошибка только в чипах серии S!


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th June 2025 - 10:21
Рейтинг@Mail.ru


Страница сгенерированна за 0.01396 секунд с 7
ELECTRONIX ©2004-2016