Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Интересное поведение EMAC на LPC17xx
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Rst7
Очень занятное поведение флага INTSTATUS_bit.RXDONEINT обнаружилось.

Разрешено только прерывания RXDONEINT. Там такой код:
CODE
void Ethernet_IRQHandler(void)
{
  UREG i='0';
  do
  {
    INTCLEAR=1UL<<3; //RxDoneInt
    i++;
  }
  while(INTSTATUS_bit.RXDONEINT);
  usart0_txc(i);
  NVIC_ClrPend(NVIC_ETHR);
  NVIC_SetPend(NVIC_RIT); //Ñòàðòóåì RIT_IRQHandler
}


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

CODE
122212112121121112122222222112112211212222222121111....


Пуристы для тестов могут заменить usart0_txc на ногодрыг и наблюдать осциллографом тот же результат - импульсов то 1, то 2.

Если бы просто сделать
CODE
void Ethernet_IRQHandler(void)
{
  INTCLEAR=1UL<<3; //RxDoneInt
  NVIC_ClrPend(NVIC_ETHR);
  NVIC_SetPend(NVIC_RIT); //Ñòàðòóåì RIT_IRQHandler
}

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

Вот такой код вроде (ну ибо на обозримом отрезке времени мне не удалось наблюдать двойной вызов) всегда вызывается один раз:
CODE
void Ethernet_IRQHandler(void)
{
  INTSTATUS;
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
  INTCLEAR=1UL<<3;//RxDoneInt
  NVIC_ClrPend(NVIC_ETHR);
  NVIC_SetPend(NVIC_RIT); //Ñòàðòóåì RIT_IRQHandler
}


Ересь какая-то в общем. Другие биты не проверял.

Есть у кого какие мысли?

В общем-то такое поведение и не особо страшно, но уж очень стремно biggrin.gif
VslavX
Цитата(Rst7 @ Jun 15 2011, 14:40) *
Очень занятное поведение флага INTSTATUS_bit.RXDONEINT обнаружилось.

Мне кажется что у него какой-то внутренний сигнал, устанавливающий запрос RXDONEINT не успевает сняться.
Если быстро заходите в прерывание и пытаетесь сбросить запрос, то внутренний "триггер" (не флип-флоп, а именно спусковой крючок) снова его ставит. А если немножко подождать - то внутренний "триггер" успевает сняться и все OK.
У меня в прерывании с регистрами EMAC ничего не делается - просто ставится событие RTOS, поэтому до обработки собственно запроса в приоритетном потоке проходит некоторое время (явно больше чем Ваши NOPы), и такого поведения не наблюдается.
Rst7
QUOTE
Мне кажется что у него какой-то внутренний сигнал, устанавливающий запрос RXDONEINT не успевает сняться.


Да вот там есть интересная фраза такая в мане, что
QUOTE
Note that all bits are flip-flops with an asynchronous set in order to be able to generate interrupts if there are wake-up events while clocks are disabled.


Какими они там сигналами асинхронно выставляются, я уж хз. Запросто эти сигналы могут быть заведены на вход S триггеров и быть по длительности хз какими. Вот и не сбрасывается.

QUOTE
У меня в прерывании с регистрами EMAC ничего не делается - просто ставится событие RTOS


Так тут тоже самое. NVIC_SetPend(NVIC_RIT) - это и есть запуск потока обработки. Только у него приоритет ниже, посему начинает обрабатывать позже.
aaarrr
А если dsb вставить после записи INTCLEAR?
GetSmart
Цитата(Rst7 @ Jun 15 2011, 16:40) *
Разрешено только прерывания RXDONEINT. Там такой код:

Я правильно понял - происходит двойной заход в обработчик?
По моему NVIC должен запрещать двойные заходы. Только после полного выхода.
alag57
Цитата
while(INTSTATUS_bit.RXDONEINT);

Посмотрите соответствующий код в ассемблере, нет ли там записи в INTSTATUS.
У меня были какие-то неприятности с прерываниями от ЕМАС, когда я делал так:
Код
if (LPC_EMAC->IntStatus & (1 << INT_RX_DONE))

давненько было - не помню подробностей.
Сделал так:
Код
unsigned int temp = LPC_EMAC->IntStatus;
if (temp & INT_RX_DONE)
{
  LPC_EMAC->IntClear = INT_RX_DONE;
}

И неприятностей больше не было.
Rst7
QUOTE
А если dsb вставить после записи INTCLEAR?


Барьеры не помогают (только как задержка вместо нопов). Я тоже сразу подумал о синхронизации всяких Load-Store конвейеров, но это не оно.

QUOTE
Я правильно понял - происходит двойной заход в обработчик?


Не двойной заход. Вход-выход и опять вход-выход. На втором входе все замечательно очищается.

CODE
void Ethernet_IRQHandler(void)
{
  INTCLEAR=1UL<<3;//RxDoneInt
  NVIC_ClrPend(NVIC_ETHR);
  ...тут например дрыгаем ножкой для теста
}


Такой код дрыгает ножкой два раза на один пакет. Без паузы.

QUOTE
Посмотрите соответствующий код в ассемблере, нет ли там записи в INTSTATUS.


Конечно нет. Код корректный.
VslavX
Цитата(Rst7 @ Jun 15 2011, 15:41) *
Так тут тоже самое. NVIC_SetPend(NVIC_RIT) - это и есть запуск потока обработки. Только у него приоритет ниже, посему начинает обрабатывать позже.

Не совсем то же самое - Вы цупите INTCLEAR. Я прерывания от EMAC запрещаю через NVIC:
Код
void
lw_lpc17_emac_handler(
    void)
{
    tn_event_iset(&glw_lpc17_netif->event, MACEVT_MACIRQ);
    NVIC_IDCR0 = (1<<IRQ_EMAC);
}

Разбор чего там EMAC захотел и общение с его регистрами происходит позже в потоке
Rst7
QUOTE
Не совсем то же самое - Вы цупите INTCLEAR. Я прерывания от EMAC запрещаю через NVIC:


Ну тогда похоже Вы не видите этих граблей, ибо очень долго до собственно сброса флага.
gladov
Цитата(Rst7 @ Jun 15 2011, 15:40) *
Код
void Ethernet_IRQHandler(void)
{
  UREG i='0';
  do
  {
    INTCLEAR=1UL<<3; //RxDoneInt
    i++;
  }
  while(INTSTATUS_bit.RXDONEINT);
  usart0_txc(i);
  NVIC_ClrPend(NVIC_ETHR);
  NVIC_SetPend(NVIC_RIT); //Ñòàðòóåì RIT_IRQHandler
}


Код
void Ethernet_IRQHandler(void)
{
  INTSTATUS;
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
  INTCLEAR=1UL<<3;//RxDoneInt
  NVIC_ClrPend(NVIC_ETHR);
  NVIC_SetPend(NVIC_RIT); //Ñòàðòóåì RIT_IRQHandler
}


Я с EMAC плотно пока не работал, поэтому есть лишь догадка: в первом случае INTSTATUS вычитывается ПОСЛЕ первого обнуления в INTCLEAR, а во втором СНАЧАЛА читается статус, потом очищается прерывание. Может быть тот самый упомянутый выше "спусковой крючок" находится в INTSTATUS и сначала надо его прочитать (как в некоторых self-clear прерываниях), а потом уже принудительно прописать бит в INTCLEAR?
andrewlekar
Я в LPC1768 не смог победить их работу с прерыванием RxDone. По итогу сделал поллинг индекса в DMA. В других примерах (FreeRTOS например), сделано так же. Прерывание там используется только чтобы проснуться. Да, а заметили, что первые пара пакетов шлётся криво? В Errata описан такой баг.
Rst7
QUOTE
поэтому есть лишь догадка


Я так тоже думал. Нет, просто паузы достаточно для последующей нормальной очистки флага.

QUOTE
Я в LPC1768 не смог победить их работу с прерыванием RxDone.


А что его побеждать? Оно работает.

QUOTE
Да, а заметили, что первые пара пакетов шлётся криво? В Errata описан такой баг.


Хватило квалификации не наступить. Ибо изначально изучил Errata и закодил передачу пары пакетов заранее. И вообще, описанный баг превращается в фичу wink.gif
andrewlekar
Цитата
А что его побеждать? Оно работает.

А у меня не работает. Киньте что ли сюда код обработки прерывания - уберу у себя поллинг.
Slowhan
Люди, а каких вы скоростей на Lpc17 достигаете по tcp?
Rst7
QUOTE
Люди, а каких вы скоростей на Lpc17 достигаете по tcp?


Смотря какую полезную нагрузку вкладывать. В принципе, при верном подходе утилизируется вся доступная полоса.

Да, кстати, собственно по теме топика. Оказывается, у меня не была припаяна ножка RX- на PHY - работало по одному проводу. В результате после окончания пакета на 10МБит были еще дрыгания, которые интерпретировались PHY как начало нового фрейма. А MAC, как оказалось, даже такой в упор непакет все таки отбрасывает с установкой флага прерывания.

В общем, имейте в виду, что может происходить и такая ересь.
Vitaliy_ARM
Цитата(Rst7 @ Jul 21 2011, 18:37) *
Смотря какую полезную нагрузку вкладывать. В принципе, при верном подходе утилизируется вся доступная полоса.

Да, кстати, собственно по теме топика. Оказывается, у меня не была припаяна ножка RX- на PHY - работало по одному проводу. В результате после окончания пакета на 10МБит были еще дрыгания, которые интерпретировались PHY как начало нового фрейма. А MAC, как оказалось, даже такой в упор непакет все таки отбрасывает с установкой флага прерывания.

В общем, имейте в виду, что может происходить и такая ересь.


Может у кого попадалось. Была у меня плата MCB2300, выбросил от туда LPC2378 и поставил LPC1768. Перенес проект со стеком ARP+ICMP+UDP на этот микроконтроллер. Написал программу. Блок данных передается от платы в ПК и возвращается обратно в плату. После некоторых манипуляций заметил следующую ерунду. Каждый десятый пакет приходит битый. Причем битый там всего один байт. Может быть в начале, может в конце, происходит случайно. Проверил снифером, пакет бьется в микроконтроллере по приему, так как входящие пакеты на пк и исходящие - целые. Думал, вышли из строя микросхемы LPC и PHY. Обе заменил, все тоже самое. Может у кого было нечто подобное?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.