[i] Начальные сведения об Ethernet
Тактирование 25МГц
Для работы блока Ethernet PHY нужна высокоточная частота тактирования 25МГц. Как правило, для этого используется отдельный генератор HSE2, запускаемый от внешнего резонатора на 25МГц. Дело в том, что внутренняя PLL имеет недопустимый по стандарту Ethernet джиттер, поэтому ее нельзя использовать для получения точной частоты. По этой причине в микроконтроллере К1986ВЕ1QI реализован отдельный генератор HSE2.
Второй вариант - использовать вместо резонатора внешний генератор на 25МГц, подключенный ко входу OSC_IN. В данном случае в HSE необходимо включить режим BYPASS, при котором внутренний генератор HSE не работает, а лишь пропускает входную частоту. Таким образом, на выходе HSE будут необходимые стабильные 25МГц для PHY. Но на вход PLL можно подавать частоту от 2МГц до 16МГц, поэтому необходимо включить делитель на 2. Теперь на выходе мультиплексора CPU_C1 получится частота 25МГц/2, что уже вписывается в условие < 16МГц.
Резонатор 25МГц на вход HSE (вместо генератора) подключать нельзя, потому что внутренний генератор HSE формирует выходную частоту в диапазоне 2-16МГц. А поскольку генератор не умеет делить/умножать частоту, а только делает из синусоидального сигнала прямоугольные импульсы, то это означает, что на вход HSE можно подключать резонатор с теми же частотами 2-16МГц. Для тактирования PHY и ядра от HSE можно использовать только внешний генератор!
На самом деле частота 25 МГц - это частота, на которой передаются данные между блоками MAC и PHY в режиме 100 Мбит/c. Данные передаются по интерфейсу MII.
Буферы приема и передачи
Для обработки пакетов Ethernet в К1986ВЕ1QI выделена память размером 8 Кбайт (в микроконтроллере К1986ВК01GI 32 Кбайт, но работа аналогичная). Это отдельная память в блоке периферии, а не часть ОЗУ ядра.
Регистр Delimeter делит эту память на два буфера - буфер входных данных и буфер выходных данных. В зависимости от того, чего ожидается больше - входных или выходных данных, можно поделить общую память в необходимой пропорции. Например, если в рассматриваемой задаче выходных данных генерируется много больше, чем входных, то имеет смысл выделить больше памяти для передатчика, то есть выставить регистр Delimeter не в середину (0х1000), а в меньшее значение, например Delimeter = 0х800.
Буферы являются кольцевыми, поэтому для считывания и записи данных в каждый буфер выделено по два регистра Head и Tail, отдельные для приемника и передатчика. Head - указывает на начало действительных данных, Tail - на конец действительных данных. Соответственно регистры R_Head и R_Tail могут принимать значения [0 .. Delimeter-1], а регистры X_Head и X_Tail - [Delimeter .. 0x2000]. Данные регистры необходимы для "ручного" управления данными в буферах в линейном режиме. На рисунке 1 представлен схематичный вид буферов Ethernet.
Рисунок 1 - Буферы Ethernet
На рисунке 2 изображена передача шести кадров с увеличивающейся длиной в некотором микроконтроллере в режиме КЗ, то есть блок МАС принимает то, что сам посылает. Блок PHY в обмене не участвует. В Payload в первых 4-х байтах передается индекс кадра. В последние два байта записан импровизированный маркер длины пакета - по нему удобно отслеживать конец данных.
Рисунок 2 - Передача шести кадров в режиме КЗ
Режимы работы буферов
В микроконтроллерах К1986ВЕ1QI и К1986ВК01GI в блоке Ethernet реализовано три режима работы буферов - линейный, автоматический и FIFO.
В линейном режиме регистры R_Tail и X_Head изменяются аппаратно при приеме и передаче данных с линии, программист же должен модифицировать регистры R_Head и X_Tail. R_Head - при чтении из буфера полученных данных, X_Tail - при записи в буфер пакетов на отправку.
В автоматическом режиме происходит все тоже самое, только модифицировать регистры R_Head и X_Tail не надо. Они изменяются автоматически при чтении слова входных данных и при записи слова данных на отправку соответственно.
В режиме FIFO считывание входных данных происходит через чтение адреса 0х0000, отправка же через запись в адрес 0х0004. В SPL для ускорения работы с данными в этом режиме используется DMA. Регистры R_Head и X_Tail здесь не участвуют.
Следует отметить, что в случае, когда есть необходимость пропускать считывание из буфера входного пакета целиком, следует использовать линейный режим работы буферов. Только в нем есть возможность переместить указатель R_Head сразу за конец текущего пакета.
В SPL реализованы функции, которые инкапсулируют в себе работу с буферами во всех режимах. Изучение их реализации поможет в большем понимании принципов работы с буферами.
void ETH_SendFrame(MDR_ETHERNET_TypeDef * ETHERNETx, uint32_t * ptr_OutputBuffer, uint32_t BufLen);
uint32_t ETH_ReceivedFrame(MDR_ETHERNET_TypeDef * ETHERNETx, uint32_t * ptr_InputBuffer);
Отправка пакета
Для отправки пакета необходимо записать его в буфер передатчика.
-
Первым 32-х битным словом необходимо записать "Поле управления передачей пакета". В этом поле указывается длина пакета в байтах. Когда передатчик считывает это слово, он понимает, сколько последующих байт относится к данному пакету и должно быть передано. Данное слово должно располагаться по выровненному 32-битному адресу.
-
После указания длины пакета в буфер записывается сам пакет обозначенной длины. В линейном режиме после записи пакета необходимо выставить указатель X_Tail на адрес, следующий за статусным словом (пункт 3).
-
При передаче каждого слова передатчик перемещает указатель X_Head. После того, как передатчик осуществит посылку пакета в следующий выровненный 32-битный адрес, он запишет статус передачи пакета. Выставляется флаг прерывания от передатчика.
Далее передатчик читает длину следующего пакета и так далее по циклу, пока не дойдет до указателя X_Tail. Если X_Head = X_Tail, то это значит, что действительных данных для пересылки больше нет. Теперь передатчик ждет, пока программа не положит в буфер новый пакет, после чего работа возобновится.
Прием пакета
Приемник принимает пакет с линии и записывает его в буфер.
-
Первым 32-битным выровненным словом записывается "Поле состояния приема пакета". Это поле содержит биты статуса приема и длину пакета в байтах.
-
Затем записываются данные самого пакета.
Со стороны приемопередатчика работа с буфером и регистрами всегда одинакова. Разница в режимах (линейный, автоматический и FIFO) сказывается только при обращении к буферу из ядра.
Когда данные принимаются с линии, они записываться в буфер приемника, начиная с указателя R_Tail. После приема заголовка с МАС адресами приемник проверяет, надо ли дальше принимать данные. Если прием чужих, широковещательных и т.д. типов пакетов выключен, то дальше данные не записываются. Все это время R_Tail стоит на месте. Если МАС адреса данных соответствуют принимаемым, то данные с линии сохраняются в буфер дальше. После приема всех данных проверяется CRC, и если пакет битый, а при этом установлена опция не принимать битые пакеты, то принятые данные опять игнорируются и R_Tail остается на месте. Если же пакет засчитывается принятым, то в поле приема пакета (адрес которого как раз содержится в R_Tail) записывается статусная информация, а в регистр R_Tail записывается адрес следующей свободной ячейки в буфере приема.
Поэтому неравенство R_Tail и R_Head говорит о том, что в буфере есть данные для считывания и пользовательская программа может с ними работать.
Подключение
Для подключения друг к другу двух микроконтроллеров необходимо использовать кабель Crossover. В этом кабеле пины выходного сигнала с одной стороны идут к входным пинам с другой стороны.
При подключении к PC можно использовать любой кабель, поскольку сетевые карточки, как правило, поддерживают режим Auto-MDI(X). При этом выводы на PC автоматически подстроятся на прием или выдачу сигнала.
При подключении двух устройств происходит процедура автосогласования (Autonegotiation) скорости обмена и дуплекса. Микроконтроллеры Миландр поддерживают скорости обмена 10Мбит/сек и 100Мбит/сек (Fast Ethernet). В режиме полудуплекса используется один кабель и обмен происходит то в одну сторону, то в другую - микроконтроллер, то передает, то принимает данные. В полнодуплексном режиме прием и передача идут одновременно - каждый по своему кабелю. При автосогласовании выбирается режим, который поддерживают оба устройства и который обеспечивает максимальную скорость обмена. Приоритеты выбора режимов такие:
-
100BASE-TX Full Duplex
-
100BASE-TX Half Duplex
-
10BASE-T Full Duplex
-
10BASE-T Half Duplex
Процедура Autonegotiation не является обязательной и ее можно отключить. В таком случае режим обмена должен быть выбран одинаковым в обоих подключенных устройствах. Делается это в регистре PHY_Control.
Также в блоке PHY есть регистры, значения которых влияют на процесс выбора скорости и дуплекса. Доступ к этим расширенным регистрам осуществляется через интерфейс MDIO.
Интерфейс MDIO
Контроллер Ethernet состоит из двух частей блока MAC и блока PHY. Обмен данными между этими блоками происходит по интерфейсу MII. Настройка же блока PHY производится по интерфейсу MDIO.
По стандарту интерфейс MDIO позволяет адресовать до 31-го PHY устройства. Это обусловлено тем, что в обмене используется поле PHY_ADDR, который имеет ширину 5 бит. 0-й адрес является широковещательным, а остальные 31 - это адреса конкретного блока PHY. Соответственно, для работы с блоком PHY необходимо в регистре PHY_Control задать поле PHYADDR[15..11]. И затем именно этот адрес необходимо указывать в транзакциях по MDIO. В библиотеке SPL в функции ETH_StructInit() поле PHYADDR задается равным 0x1C, но значение может быть любым другим (ненулевым).
Для работы с MDIO используются два регистра:
-
MDIO_CTRL - регистр управления;
-
MDIO_DATA - регистр данных для чтения и записи регистров PHY.
Именно в регистре MDIO_CTRL указывается PHY_ADDR для выбора блока PHY, с которым будет происходить обмен данными через регистр MDIO_DATA. В этом же регистре MDIO_CTRL указывается адрес внутреннего регистра PHY, текущая операция - чтение или запись, а также частота обмена и прочее. Подробно биты расписаны в спецификации. В SPL(pack) работа с MDIO реализована в функциях:
uint32_t ETH_WritePHYRegister(MDR_ETHERNET_TypeDef * ETHERNETx, uint16_t PHYAddress, uint16_t PHYReg, uint16_t PHYValue);
uint16_t ETH_ReadPHYRegister(MDR_ETHERNET_TypeDef * ETHERNETx, uint16_t PHYAddress, uint16_t PHYReg);
К примеру, вот как можно выключить подключение на скорости 100Мбит/сек при Autonegotiation. Функция сбрасывает биты 7 и 8 в "Регистре рекомендации автоподстройки (4)". После вызова данной функции МК будет подключаться к PC на скорости 10Мбит/сек.
#define ETH_PHY_ADDR 0x1C // - адрес указанный в PHY_Control
void PHY_100TX_Disable(void)
{
volatile uint32_t regValue = ETH_ReadPHYRegister(MDR_ETHERNET1, ETH_PHY_ADDR, 4);
regValue &= ~(3 << 7);
ETH_WritePHYRegister(MDR_ETHERNET1, ETH_PHY_ADDR, 4, regValue);
}
Бит G_CFGh.EXT_EN
Бит EXT_EN регистра G_CFGl определен в спецификации как "Включение режима дополнения коротких пакетов до размера SlotTime полем Extension".
Данный бит выставлен в регистре G_CFGl после Reset и предназначен для борьбы с коллизиями в Half Duplex режиме.
Время канала ST (slot time)- это минимальное время, в течении которого узел обязан вести передачу, занимать канал. Это время соответствует передаче кадра минимально допустимого размера, принятого стандартом Ethernet IEEE 802.3. Время канала связано с максимальным допустимым расстоянием между узлами сети - диаметром коллизионного домена.
При работе в Full Duplex необходимости в данном бите нет. Поэтому для работы в современных сетях данный бит необходимо сбросить.
По факту, при EXT_EN = 1 в конец пакета, отправляемого микроконтроллером, приписывается 10 дополнительных байт. Это происходит в любом случае - меньше ли отправляемый пакет минимального размера в 64 байта или больше.
Толкование регистров
Согласно пункту "Режим детерминированного времени доставки" спецификации на микроконтроллер КК1986ВЕ1QI пакеты могут передаваться в привязке к отсчетам времени (с периодом BAG при DTRM_EN = 1). То есть, если передатчик успевает в окно JitterWnd начать передачу, то он ее начинает. Если не успевает, то ожидает следующего отсчета периода BAG. BAG и JitterWnd выражаются в квантах времени, которые задаются из ETH_Clock делителем PSC.
1/TimeStep = ETH_Clock / (PSC + 1), что согласуется с 1мкс для 50МГц из спецификации.
IPG - межпакетный интервал и в соответствии с IEEE802.3 должен составлять 96 битовых интервалов.
Сохранить статью в PDF