Project

General

Profile

Работа с Ethernet (Си) » History » Version 20

krufter_multiclet, 04/22/2013 12:36 PM

1 1 krufter_multiclet
h1. Работа с Ethernet (Си) 
2 4 krufter_multiclet
3 4 krufter_multiclet
Рассмотрим простой пример по отправке одного пакета с заданным IP-адресом в виде широковещательной рассылки.
4 4 krufter_multiclet
Но сначала заметим, что настройка микросхемы, реализующей физический уровень Ethernet происходит программно.
5 4 krufter_multiclet
6 4 krufter_multiclet
На Си реализованы функции записи и чтения в регистры микросхемы, реализующей физический уровень Ethernet.
7 5 krufter_multiclet
8 5 krufter_multiclet
1) Функция записи в регистры PHY
9 5 krufter_multiclet
10 5 krufter_multiclet
<pre>
11 5 krufter_multiclet
void mdio_wr(int phy_addr, int reg, int data)
12 5 krufter_multiclet
</pre> 
13 5 krufter_multiclet
14 5 krufter_multiclet
phy_addr - адрес микросхемы PHY (по умолчанию 0x00)
15 5 krufter_multiclet
reg - номер регистра
16 5 krufter_multiclet
data - значение для установки в регистр
17 5 krufter_multiclet
18 5 krufter_multiclet
2) Функция чтения регистра PHY
19 5 krufter_multiclet
20 5 krufter_multiclet
<pre>
21 5 krufter_multiclet
int mdio_rd(int phy_addr, int reg)
22 5 krufter_multiclet
</pre>
23 5 krufter_multiclet
24 5 krufter_multiclet
phy_addr - адрес микросхемы PHY (по умолчанию 0x00)
25 5 krufter_multiclet
reg - номер регистра
26 5 krufter_multiclet
Функция возвращает 32 разрядное значение регистра
27 6 krufter_multiclet
28 6 krufter_multiclet
29 6 krufter_multiclet
Перейдём непосредственно к рассмотрению примеров отправки и приёма пакетов.
30 6 krufter_multiclet
31 7 krufter_multiclet
h2. а) Передача пакета по Ethernet
32 6 krufter_multiclet
33 9 krufter_multiclet
Перед передачей пакета необходимо учесть, что области размещения дескрипторов передачи и приёма должны быть 
34 10 krufter_multiclet
выравнены на 1 килобайт. Области памяти, содержащие данные для передачи или принятые данные должны быть
35 10 krufter_multiclet
выравнены на 4 байта.
36 8 krufter_multiclet
37 11 krufter_multiclet
h3. 1. Объявим переменные и массивы данных с выравниванием
38 11 krufter_multiclet
39 11 krufter_multiclet
<pre>
40 11 krufter_multiclet
    static unsigned char buf_tx_desc[2048];
41 11 krufter_multiclet
    static unsigned char buf_rx_desc[2048];
42 11 krufter_multiclet
    unsigned int buf_tx[400];
43 11 krufter_multiclet
    unsigned int buf_rx[400];
44 11 krufter_multiclet
    unsigned char *eth_tx_desc;
45 11 krufter_multiclet
    unsigned char *eth_rx_desc;
46 11 krufter_multiclet
    
47 11 krufter_multiclet
    eth_tx_desc=(unsigned char *)(((int)buf_tx_desc+1024)& ~(1024-1)); //указатель на область памяти дескрипторов передачи
48 11 krufter_multiclet
    eth_rx_desc=(unsigned char *)(((int)buf_rx_desc+1024)& ~(1024-1)); //указатель на область памяти дескрипторов приема
49 11 krufter_multiclet
</pre>
50 8 krufter_multiclet
 
51 20 krufter_multiclet
h3. 2. Заполним данные на передачу
52 1 krufter_multiclet
53 20 krufter_multiclet
<pre>
54 20 krufter_multiclet
    for(i=0;i<400;i++)
55 20 krufter_multiclet
    {
56 20 krufter_multiclet
        buf_tx[i] = 0xFFFFFFFF;
57 20 krufter_multiclet
    }
58 20 krufter_multiclet
</pre>
59 1 krufter_multiclet
60 20 krufter_multiclet
h3. 3. Сформируем простую функцию передачи данных
61 20 krufter_multiclet
62 13 krufter_multiclet
<pre>
63 12 krufter_multiclet
void send_pack(unsigned int *buf_tx, int size, unsigned char *eth_tx_desc)
64 12 krufter_multiclet
{
65 12 krufter_multiclet
   int pre;
66 12 krufter_multiclet
   GPIOA->BPS = 0x0000FFFF; //разрешаем альтернативные функции порта для работы Ethernet
67 12 krufter_multiclet
   ETH->TDP = 0xE0200000 + (unsigned int)(eth_tx_desc); //задаём область размещения дескрипторов передачи
68 12 krufter_multiclet
   pre = 0xE0200000 + (unsigned int)buf_tx; //область размещения данных в ПД
69 12 krufter_multiclet
70 14 krufter_multiclet
   //переворачиваем pre из big endian в little endian и формируем вторую часть дескриптора передачи
71 12 krufter_multiclet
   eth_tx_desc[3] = (pre & 0xFF);
72 12 krufter_multiclet
   eth_tx_desc[2] = ((pre & 0xFF00)>>8);
73 12 krufter_multiclet
   eth_tx_desc[1] = ((pre & 0xFF0000)>>16);
74 12 krufter_multiclet
   eth_tx_desc[0] = ((pre & 0xFF000000)>>24);
75 1 krufter_multiclet
  
76 16 krufter_multiclet
   pre = (size & 0x3FF) + 0x1800; //первая часть дескриптора передачи EN, WP - "1"
77 14 krufter_multiclet
   
78 14 krufter_multiclet
   eth_tx_desc[7] = (pre & 0xFF);
79 14 krufter_multiclet
   eth_tx_desc[6] = ((pre & 0xFF00)>>8);
80 17 krufter_multiclet
   eth_tx_desc[5] = 0x00;
81 19 krufter_multiclet
   eth_tx_desc[4] = 0x00;
82 17 krufter_multiclet
   
83 17 krufter_multiclet
   ETH->CR = 0x00000001; //разрешаем передачу
84 17 krufter_multiclet
   while((ETH->CR & 1) != 0);
85 17 krufter_multiclet
}
86 17 krufter_multiclet
</pre>
87 17 krufter_multiclet
88 17 krufter_multiclet
89 17 krufter_multiclet
90 18 krufter_multiclet
Первые 12 байт отводятся в пакете под МАК адреса отправителя и получателя, если заполнить
91 18 krufter_multiclet
МАК адреса единицами, то получим широковещательную посылку.
92 18 krufter_multiclet
В примере, который будет доступен в хранилище задаётся тип пакета IPv4 и IP адрес с данными.
93 17 krufter_multiclet
94 17 krufter_multiclet
95 17 krufter_multiclet
96 12 krufter_multiclet
97 12 krufter_multiclet
98 12 krufter_multiclet
99 12 krufter_multiclet
100 6 krufter_multiclet
101 6 krufter_multiclet