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

 
 
> EMAC AT91SAM9260, Вопросы, касающиеся Ethernet MAC для AT91SAM9260
ZED
сообщение Oct 28 2010, 13:27
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Доброго всем здравия!!!

Начал разбираться с EMAC для AT91SAM9260. Имеется документация на сам контроллер и тестовый пример для IAR под названием basic-emac-uip-webserver-project-at91sam9260-ek. В этой теме планируется задавать вопросы, которые касаются проблемы запуска Ethernet на вышеупомянутом контроллере и просто непонятные вещи.

Первый вопрос заключается в следующем. В файле emac.h имеются некоторые указатели на функции:
Код
/// Callback used by send function
typedef void (*EMAC_TxCallback)(unsigned int status); // EMAC_TxCallback - указатель на функцию, возвращающую void и принимающую unsigned int
typedef void (*EMAC_RxCallback)(unsigned int status); // EMAC_RxCallback - указатель на функцию, возвращающую void и принимающую unsigned int
typedef void (*EMAC_WakeupCallback)(void); //  EMAC_WakeupCallback - указатель на функцию, возвращающую void и принимающую void


Далее они используются, например в функции EMAC_Handler, которая управляет прерываниями, расположенной в emac.c:
Код
    volatile EmacTxTDescriptor *pTxTd;
    volatile EMAC_TxCallback   *pTxCb;

Код
if (rxTd.rxCb) {
            rxTd.rxCb(rxStatusFlag);
        }

Код
            if (*pTxCb) {
                (*pTxCb)(txStatusFlag);
            }

Я так понял это так называемые обратные функции, но что они делают нигде не определено (по-крайней мере я не нашел). Вопрос собственно для чего они нужны?

Еще один вопрос, что выполняет следующий кусок кода в той же функции EMAC_Handler и для чего он нужен? Можно ли обойтись без всего этого?
Код
        // Check the buffers
        while (CIRC_CNT(txTd.head, txTd.tail, TX_BUFFERS)) {
            pTxTd = txTd.td + txTd.tail;
            pTxCb = txTd.txCb + txTd.tail;

            // Exit if buffer has not been sent yet
            if ((pTxTd->status & EMAC_TX_USED_BIT) == 0) {
                break;
            }
            
            // Notify upper layer that packet has been sent
            if (*pTxCb) {
                (*pTxCb)(txStatusFlag);
            }
            
            CIRC_INC( txTd.tail, TX_BUFFERS );
        }

        // If a wakeup has been scheduled, notify upper layer that it can send
        // other packets, send will be successfull.
        if( (CIRC_SPACE(txTd.head, txTd.tail, TX_BUFFERS) >= txTd.wakeupThreshold)
         &&  txTd.wakeupCb) {
            txTd.wakeupCb();
        }
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 24)
ZED
сообщение Oct 29 2010, 06:35
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



И еще один вопрос. В функции EMAC_Init, расположенной в emac.c есть следующие строки:
Код
    // Инициализация дескриgторов передающего буфера.
    for(Index = 0; Index < TX_BUFFERS; Index++) {// Цикл по количеству передающих буферов
        // Инициализация адресов дескрипторов передающего буфера
        Address = (unsigned int)(&(pTxBuffer[Index * EMAC_TX_UNITSIZE]));
        txTd.td[Index].addr = Address; // Нет Маски, т.к. Слово 0 - адрес начала буфера
        txTd.td[Index].status = EMAC_TX_USED_BIT; // Установка для всех буферов бита used!!!
    }
    txTd.td[TX_BUFFERS - 1].status = EMAC_TX_USED_BIT | EMAC_TX_WRAP_BIT;


Строка txTd.td[Index].status = EMAC_TX_USED_BIT; устанавливает биты 31 в слове 1 ВСЕХ дескрипторов в единицу, тогда как в документации сказано, что этот бит должен быть установлен только для первого буфера, а при инициализации все биты 31 из слова 1 должны быть сброшены:

Цитата
This bit is only set for the first buffer in a frame unlike receive where all buffers have the Used bit set once used.

Mark all entries in this list as owned by EMAC, i.e. bit 31 of word 1 set to 0.


Вопрос: пример не рабочий получается или что?
Go to the top of the page
 
+Quote Post
ZED
сообщение Nov 25 2010, 09:20
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



На счет строки txTd.td[Index].status = EMAC_TX_USED_BIT; все вроде правильно. В документации сказано про прием, а не про передачу, это я не туда посмотрел.
С остальным трудности, специалисты откликнитесь.
Go to the top of the page
 
+Quote Post
Zelepuk
сообщение Dec 10 2010, 05:35
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Один "специалист" мне когда-то сказал, что Ethernet у ARM есть, но никто не знает как он работает. После чего к арму был успешно прикручен модуль WIZNET.
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Dec 10 2010, 08:44
Сообщение #5


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Цитата
Один "специалист" мне когда-то сказал, что Ethernet у ARM есть, но никто не знает как он работает. После чего к арму был успешно прикручен модуль WIZNET.


У нас тоже был такой "специалист" как только сказал что нужно поставить WIZNET, так сразу и пошел лесом.

Счас работаю c SAM9XE(думаю мак контроллер ничем не отличается) LwIP и FREERTOS, могу сказать что МАС довольно примитивный и простой, посмотрел на примеры от атмела сразу отставил их в сторону, делал все по доке, все работает.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Dec 10 2010, 10:59
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Берете u-boot и смотрите как там at91-eth.c реализован. Единственное, u-boot работает без прерываний, но это, надеюсь, не проблема. Подтверждаю, что c lwip'ом, по крайней мере at91rm9200, работает как надо.
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 13 2010, 04:31
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



О, спасибо за указание направление, а то там дальше такой треш начинается wacko.gif Попробую поразбираться с U-Boot'ом, будут вопросы напишу.
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 13 2010, 07:45
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



MALLOY2, а не выложите Ваш вариант EMAC?
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Dec 13 2010, 09:38
Сообщение #9


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Могу, только это шаблонный класс для C++, и не очень оптимальная версия, не оптимальность заключается в том что МАС контролер позволяет принимать пакеты с определенным смещением, эта фича позволяет отказаться от упаковки сетевых структур что немного подымает производительность сетевого стека. Ну мож еще какие есть бажки, сильно не тестил.
Прикрепленные файлы
Прикрепленный файл  HwEMAC.zip ( 3.32 килобайт ) Кол-во скачиваний: 48
 
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 14 2010, 01:22
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Огромное спасибо, буду разбираться.
Кстати в U-boot я не нашел файл с именем at91-eth.c и даже что-то похожее на правду.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Dec 14 2010, 03:41
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



u-boot\drivers\net\at91_emac.c
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 14 2010, 04:51
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Вот именно, что нету, у меня есть U-boot для MMNET1000 u-boot-2009.01-MMnet1000.tar и U-Boot u-boot-1.3.4.tar. И там нет этого файла. Если можно, прикрепите его пожалуйста в сообщении.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Dec 14 2010, 06:23
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Пожалуйста.

Сам u-boot вы можете скачать с его FTP: ftp://ftp.denx.de/pub/u-boot/

Последняя версия : u-boot-2010.09.tar.bz2
Прикрепленные файлы
Прикрепленный файл  at91_emac.zip ( 3.83 килобайт ) Кол-во скачиваний: 37
 
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 14 2010, 08:19
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Спасибо, буду разбираться

Мне кажется в U-boot еще больший треш, если честно. Тоже, что и в тестовом примере, только более все разбросано по отдельным файлам и без комментариев.

Спасибо MALLOY2, но C++ я к сожалению не знаю sad.gif Но Вам огромное уважение, что Вы сам по доке разобрались и написали код! a14.gif Я вот никак не могу с этими дескрипторами разобраться.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Dec 14 2010, 09:22
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(ZED @ Dec 14 2010, 11:19) *
Спасибо, буду разбираться

Мне кажется в U-boot еще больший треш, если честно. Тоже, что и в тестовом примере, только более все разбросано по отдельным файлам и без комментариев.

Спасибо MALLOY2, но C++ я к сожалению не знаю sad.gif Но Вам огромное уважение, что Вы сам по доке разобрались и написали код! a14.gif Я вот никак не могу с этими дескрипторами разобраться.


Ладно вам накатывать. Пример - он и в Африке пример. Но, по крайней мере, u-boot живой проект и работает. А то что голову придется все равно поднапрячь, так это работа наша такая.


Насчет дескрипторов. Обратите внимание на:
1. Выравнивание.
2. Вы же, скорее всего кеши включили? Так вот приемо/передаточные буфера разместите в некешируемой области.
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Dec 14 2010, 09:24
Сообщение #16


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



И сами дескрипторы должны быть в не кешируемой области.
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 14 2010, 09:52
Сообщение #17


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Цитата
Вы же, скорее всего кеши включили? Так вот приемо/передаточные буфера разместите в некешируемой области.

Извините за глупость, я знаю, что в контроллере есть 2 Кэша ICache и DCache. Я так понял, что они нужны для ускорения работы ядра наряду с MMU. Но я с ними так и не разобрался, тем более не знаю как его включать/выключать. Тем более не знаю как вне кэша размещать переменные.

И еще я вот тут начал с Вашим кодом разбираться. Вот в функции irq_handler() вызываются две не понятные функции:
Код
  static void irq_handler()
  {
    portBASE_TYPE xYieldRequired = pdFALSE;
    uint32_t status = AT91C_BASE_EMAC->EMAC_ISR;
    if ( status &  AT91C_EMAC_RCOMP)
    {
      xSemaphoreGiveFromISR(RxSem, &xYieldRequired);
    };
    portEND_SWITCHING_ISR(&xYieldRequired);
  }

Что должен делать EMAC по прерыванию? В примере он подсчитывает статистику тех или иных ситуаций и возвращает ее в регистр статистики (статуса передачи или приема). А еще какие-то операции с указателями, про которые я задавал вопрос вначале темы.

Сообщение отредактировал ZED - Dec 14 2010, 09:54
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Dec 14 2010, 10:08
Сообщение #18


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Цитата
Что должен делать EMAC по прерыванию?


то что запрограммируете, мне пока статистика не нужна. Если у вас не используется ОС то можно обойтись и без прерываний.

У меня используется ОС FreeRTOS и функции о которых вы спрашиваете являются функциями ОС.

Цитата
Извините за глупость, я знаю, что в контроллере есть 2 Кэша ICache и DCache. Я так понял, что они нужны для ускорения работы ядра наряду с MMU. Но я с ними так и не разобрался, тем более не знаю как его включать/выключать. Тем более не знаю как вне кэша размещать переменные.


Если не разберетесь с MMU и кешами, то получите редкую черепаху.

О работе с кешами все расписано в ARM926EJ-S™ Technical Reference Manual или на сайте
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 14 2010, 11:57
Сообщение #19


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



А вот еще вопросик по приему пакетов (фреймов). Я так понял, что его осуществляет у вас функция task Что делает функция pbuf_alloc(PBUF_RAW,1536,PBUF_POOL)?

Каков вообще алгоритм приема фрейма?
Сначала мы проверяем бит Ownership Слова 0 дескриптора приемного буфера. Если он установлен, это значит, что этот буфер используется. Тогда мы проверяем бит начала фрейма SOF. Если он установлен, то в примере от IAR делается какая-то хитрая операция. Видимо связанная со сбросом предыдущего кадра и подсчетом кол-ва использованных буферов. По мимо всего прочего разрешается прием фрема:
Код
if ( RxIndx->status & EMAC_RX_SOF_BIT )
          {
            ptr = static_cast<uint8_t*>(p->payload);
            flen =  0;
            sof  = ~0;
          };
          
          if ( sof )
.......................


Дальше я пока встрял. Пока пытаюсь разобраться.

Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 14 2010, 13:00
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Блин, ведь прием возможен только, если буфер не занят (Ownership = '0'). Я совсем запутался. Читаю доку - вижу фигу.
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 15 2010, 05:46
Сообщение #21


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Появился еще один дополнительный вопрос, когда устанавливается и кем бит начала фрейма SOF? Зачем его вообще проверять? При инициализации ончдолжен быть равен нулю, как в принципе и все Слово 1 (Статуса) дескриптора. Каков тогда вообще принцип работы с этими дескрипторами?
Еще в доке сказано про 11-битный счетчик, значения которого складывается со значением регистра указателя очереди приемных буферов EMAC_RBQP. Этот счетчик нужно реализовывать или он уже есть в процессоре? При этом не понятно регистр EMAC_RBQP процессор сам инкрементирует ибо написано, что он содержит адрес (точку входа) дескриптора к которому производится обращение в настоящее время или что-то туда нужно постоянно писать?
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 22 2010, 11:45
Сообщение #22


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Я так понял, что когда кадр (фрейм) находится в приемном буфере, а точнее он может находиться сразу в нескольких буферах, то в дескрипторах этих буферах автоматически устанавливается бит used (Ownership = '1'). Помимо всего прочего, в дескрипторах начального буфера и в конечного буфера, где располагается принимаемый фрейм, установлены биты начала кадра SOF и конца кадра EOF. В дескрипторе буфера, где расположен бит конца кадра EOF в слове статуса в битах 0..11 содержится информация о длине фрейма. Тогда можно предложить следующий алгоритм принятия фрейма:

Среди всех буферов с установленным битом Ownership найти буфер с установленным битом начала кадра SOF и буфер с установленным битом конца кадра EOF. Для последнего считать длину. Если таковые не найдены - кадр не принимать!
Если буферы с SOF и EOF найдены, значения из них и всех буферах между ними переписать в память функцией memcpy и сбросить бит Ownership.

Прошу Вас прокомментируйте мои соображения. Особенно хочется услышать мнение MALLOY2.

Сообщение отредактировал ZED - Dec 22 2010, 11:52
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Dec 23 2010, 05:46
Сообщение #23


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



да, так и есть, только нужно учесть то что может отсутствовать SOF или EOF, и в этом случае вы должны правильно отработать и сбросить Ownnership.
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 23 2010, 06:48
Сообщение #24


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



А нельзя ли сделать так: если биты SOF или EOF (какой-нибудь из них) не обнаружены, то сбросить Ownnership во всех дескрипторах?

Сообщение отредактировал ZED - Dec 23 2010, 06:55
Go to the top of the page
 
+Quote Post
ZED
сообщение Dec 23 2010, 08:20
Сообщение #25


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Вы не могли бы прокомментировать мою функцию приема пакета:

CODE
//-----------------------------------------------------------------------------
/// Прием пакета:
// pFrame - Адрес области памяти, куда копировать фрейм;
// pFrame_Size - Адрес, где расположено значение размера принимаемого кадра
//-----------------------------------------------------------------------------
void EMAC_Receive_Frame(unsigned char *pFrame, unsigned int *pFrame_Size)
{
unsigned int Rx_Index_tmp = Rx_Index; // Локальный номер приемных буферов
unsigned char SOF_Enable = 0; // Обнаружен бит начала кадра SOF
unsigned char EOF_Enable = 0; // Обнаружен бит конца кадра EOF

unsigned int *Rx_Buffer_SOF = 0; // Адрес буфера с установленным битом начала кадра SOF

// Пока бит Ownership = 1 (буфер используется и в нем есть данные)
while (Rx_Descriptor[Rx_Index].addr & EMAC_RX_OWNERSHIP_BIT) {

// Перебераем все буферы, чтобы найти буфер с установленным битом
// Начала кадра EOF.

// Если буфер с установленым битом начала кадра SOF найден
// сбросить во всех дескрипторах предыдущих буферов бит Ownership:
if (Rx_Descriptor[Rx_Index_tmp].addr & EMAC_RX_SOF_BIT) {

// Сбросить предыдущий фрагмент кадра (буфер):
while (Rx_Index_tmp != Rx_Index) {
// Сбросить бит USED:
Rx_Descriptor[Rx_Index].addr &= ~(EMAC_RX_OWNERSHIP_BIT);

// Инкрементировать счетчик количества приемных буферов и,
// если он равен количеству приемных буферов - обнулить его:
if (++Rx_Index == RX_BUFFERS){
Rx_Index = 0; // Обнуление
}
}
// Найдено начало кадра:
SOF_Enable = 1;

// Запомнить адрес буфера с установленным битом начала кадра SOF
Rx_Buffer_SOF = (unsigned int)(&Rx_Buffer[Rx_Index_tmp]) & EMAC_ADDRESS_MASK; // Маска адреса;
}

if (Rx_Descriptor[Rx_Index_tmp].addr & EMAC_RX_EOF_BIT) {
// Найден конец кадра:
EOF_Enable = 0

// Запомнить размер кадра
*pFrame_Size = Rx_Descriptor[Rx_Index_tmp].status & EMAC_LENGTH_FRAME;
}


// Инкрементировать счетчик количества приемных буферов и,
// если он равен количеству приемных буферов - обнулить его:
if (++Rx_Index_tmp == RX_BUFFERS){
Rx_Index_tmp = 0; // Обнуление
}
}

// Eсли обнаружены биты начала кадра и конца кадра, копировать данные
// из буфера в память:
if (SOF_Enable && EOF_Enable) {
memcpy(pFrame, Rx_Buffer_SOF, *pFrame_Size);
}

// Обнуление счетчика приемных буферов
Rx_Index = 0;

// Сбросить бит Ownership во всех дескрипторах:
while (Rx_Index != RX_BUFFERS) { //

// Сбросить бит USED:
Rx_Descriptor[Rx_Index].addr &= ~(EMAC_RX_OWNERSHIP_BIT);

// Инкрементировать счетчик приемных буферов
Rx_Index++;
}
// Обнуление счетчика приемных буферов
Rx_Index = 0;

} // End While
} // End Function


Я просто думаю, зачем принимать часть кадра? Если все равно его потом отбрасывать? Лучше сразу принимать только корректные фреймы. Жду с нетерпением Ваших комментариев, спасибо!

Сообщение отредактировал IgorKossak - Dec 23 2010, 12:23
Причина редактирования: Для длинного кода используйте теги codebox
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 13:13
Рейтинг@Mail.ru


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