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

 
 
> Важно ! uC-TCPIP bug @ SAM7X port, Некорректная обработка пакетов
_dem
сообщение Dec 27 2007, 18:47
Сообщение #1


Местный
***

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



uCOS/II v 2.85
ucTCPIP v 1.86
MCU - AT91SAM7X256 @ 43Mhz + RTL8201BL, порт ucTCPIP от micrium.com - свежий по состоянию на 27.12.2007

Долго отлавливал следующий баг в порте uTCP-IP на SAM7X -
в случае, если на плату приходит пара пакетов из Ethernet с малым расстоянием между ними (менее 1 мс), возможно "зависание" стека до получения следующего пакета из сети.

Картина выглядит так - приходит подряд два пакета, на каждый из которых плата должна ответить.
Плата отвечает на первый пакет, потом сетевая подсистема "зависает" (API работает, но обмена нет) до прихода еще одного пакета (неважно какого, например ARP).

Вместо
Код
---------- time ------------------------------->
[ request1 ][ request2 ] [ reply1][ reply2 ] --<time>------[ request3 ][ reply3 ]
имеем
Код
---------- time ------------------------------->
[ request1 ][ request2 ] [ reply1] ----<time>------[ any ethernet packet ][ reply2 ]


Если подряд принимаются три или более пакетов, проблема не возникает, т.к. прерывание по третьему пакету обрабатывает второй и третий.

Проблема связана с тем, что за время обработки пакета в прерывании успевает придти еще один пакет, повторно же обработка не запускается (прерывание срабатывает, но флаги EMAC_RSR корректно не установлены, т.к. были сброшены при выходе из прерывания на прошлом пакете) - код не в определяет причину прерывания.
Код
---------- time ------------------------------->
[ packet1 ][ packet 2]
[irq1]-----[irq2]-------
[-----irq1_processing:packet ready-----][----irq2_processing:reason unknown----]


Проблема решается следующим образом :
В файле net_nic.c вместо кода
Код
    n_new = NIC_GetNRdy() - NIC_RxNRdyCtr;                              /* Determine how many NEW packets have been received    */
    
    while (n_new > 0) {


нужен код примерно такой :
Код
    
while ((n_new = NIC_GetNRdy() - NIC_RxNRdyCtr) > 0) {


Это позволяет отловить вышеописанную ситуацию и отреагировать на второй пакет.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
aste
сообщение Mar 12 2009, 09:50
Сообщение #2





Группа: Новичок
Сообщений: 1
Регистрация: 8-10-05
Пользователь №: 9 398



Недавно столкнулся с алогичной проблемой подвивания сетевой подсистемы в uC/TCP-IP для at91sam7x256 (описание полностью соответствует тому которое привёл _dem в первом посте топика), предложенные здесь решения проблему не решили. Однако после некоторого анализа и отладки реальная проблема данной ситуации была обнаружена и исправлена.

Перед описание решения проблемы несколько комментариев:

2_dem: видимо у вас был какой-то частный случай что вам помог ваш фикс, в моём случае не было замечено практически никакого увеличения стабильности (кроме возможно увеличения на несколько тысяч удачно прошедших пакетов до первого замирания).

2defunct: насчёт идеологии, то как раз в uC реализации стека и пользуется описанная вами идеология -- в прерывании только читаются и обновляются статусные регистры и взводятся необходимые семафоры, а сама обработка пакетов производиться в отдельном таске.

2timofey_99: уж кто кто а разработчики uC/TCP-IP и NIС драйверов еррату читали и не раз, поэтому и решили вообще не использовать в обработчике прерывания от EMAC значения регистра EMAC_ISR, а сразу (как и рекомендуется в еррате) использовать значение конкретных статусных регистров.

Проблема как и было предположено находиться именно в NIC драйвере для at91sam7x256, patch для net_nic.c V1.92 (однако он справедлив и для предыдущих версий и видимо для нескольких следующих smile.gif )
CODE
Index: net_nic.c
===================================================================
--- net_nic.c (revision 114)
+++ net_nic.c (working copy)
@@ -1543,9 +1543,9 @@
}
}

+ CPU_CRITICAL_ENTER();
search_ptr->addr &= ~EMAC_RXBUF_SW_OWNED; /* Free the EOF desc. */

- CPU_CRITICAL_ENTER();
if (NIC_RxNRdyCtr > 0) { /* One fewer packet to process. */
NIC_RxNRdyCtr--;
}
@@ -1596,9 +1596,9 @@
}
}

+ CPU_CRITICAL_ENTER();
search_ptr->addr &= ~EMAC_RXBUF_SW_OWNED; /* Free the last descriptor. */

- CPU_CRITICAL_ENTER();
if (NIC_RxNRdyCtr > 0) { /* One fewer packet to process. */
NIC_RxNRdyCtr--;
}


Итак причина проблемы: потеря увеличения семафора приходящих пакетов (вызова метода NetOS_IF_RxTaskSignal) в прерывании от EMAC (а именно NetNIC_RxISR_Handler) из-за ошибки в подсчёте новых пришедших пакетов (выражение n_new = NIC_GetNRdy() - NIC_RxNRdyCtr). Ошибка происходила из-за разсинхронизации значения переменной NIC_RxNRdyCtr и реального состояния буферов приёма периферии EMAC. Это происходило когда мы снимали флаг SW на буфере (search_ptr->addr &= ~EMAC_RXBUF_SW_OWNED) и сразу после этого происходило прерывание по приходу нового пакета, при это мы ещё не декрементировали значение переменной NIC_RxNRdyCtr, в связи с чем в логика перывания решала что новых пакетов нет, и не инкрементировла значение семафора приходящих пакетов. ВУАЛЯ мы замираем до прихода любого нового пакета.
Go to the top of the page
 
+Quote Post



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

 


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


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