roboforum.ru

Технический форум по робототехнике.

W5100 DHCP [MEGA AVR]

Программирование микроконтроллеров AVR, PIC, ARM.
Разработка и изготовление печатных плат для модулей.

W5100 DHCP [MEGA AVR]

Сообщение Insler » 10 авг 2014, 15:29

Привет!

Сижу пишу интернет-клиент на базе mega328p & wiznet w5100.
Вроде более или менее все понятно, как настраивать TCP-сервер понятно, судя по ДЩ с клиентом то же самое, но встал тут больной вопрос получение настроек от роутера по DHCP. Насколько понял DHCP юзает UDP, то есть надо отправить под UDP на DHCP-сервер запрос с моим маком, и в ответ получить список всякого дерьмища, из которого надо будет вытащить маску, айпишник и прочие вкусности, необходимые для работы по TCP. Из кучи примеров родил пока примитивную либу, для построения сервера без DHCP.

Вот все дефайны:
Код: Выделить всёРазвернуть
// ATmega328 SPI I/O
#define SPI_PORT PORTB
#define SPI_DDR  DDRB
#define SPI_CS   PORTB2

// Wiznet W5100 Op Codes
#define WIZNET_WRITE_OPCODE 0xF0
#define WIZNET_READ_OPCODE 0x0F

// Wiznet W5100 Register Addresses
#define MR         0x0000      // Mode Register
#define GAR        0x0001      // Gateway Address: 0x0001 to 0x0004
#define SUBR       0x0005      // Subnet mask Address: 0x0005 to 0x0008
#define SAR        0x0009      // Source Hardware Address (MAC): 0x0009 to 0x000E
#define SIPR       0x000F      // Source IP Address: 0x000F to 0x0012
#define RMSR       0x001A      // RX Memory Size Register
#define TMSR       0x001B      // TX Memory Size Register
#define S0_MR      0x0400      // Socket 0: Mode Register Address
#define S0_CR      0x0401      // Socket 0: Command Register Address
#define S0_IR      0x0402      // Socket 0: Interrupt Register Address
#define S0_SR      0x0403      // Socket 0: Status Register Address
#define S0_PORT    0x0404      // Socket 0: Source Port: 0x0404 to 0x0405
#define SO_TX_FSR  0x0420      // Socket 0: Tx Free Size Register: 0x0420 to 0x0421
#define S0_TX_RD   0x0422      // Socket 0: Tx Read Pointer Register: 0x0422 to 0x0423
#define S0_TX_WR   0x0424      // Socket 0: Tx Write Pointer Register: 0x0424 to 0x0425
#define S0_RX_RSR  0x0426      // Socket 0: Rx Received Size Pointer Register: 0x0425 to 0x0427
#define S0_RX_RD   0x0428      // Socket 0: Rx Read Pointer: 0x0428 to 0x0429
#define TXBUFADDR  0x4000      // W5100 Send Buffer Base Address
#define RXBUFADDR  0x6000      // W5100 Read Buffer Base Address// S0_MR values
#define MR_CLOSE     0x00    // Unused socket
#define MR_TCP        0x01    // TCP
#define MR_UDP        0x02    // UDP
#define MR_IPRAW     0x03     // IP LAYER RAW SOCK
#define MR_MACRAW     0x04     // MAC LAYER RAW SOCK
#define MR_PPPOE     0x05     // PPPoE
#define MR_ND        0x20     // No Delayed Ack(TCP) flag
#define MR_MULTI     0x80     // support multicating// S0_CR values
#define CR_OPEN          0x01     // Initialize or open socket
#define CR_LISTEN        0x02     // Wait connection request in tcp mode(Server mode)
#define CR_CONNECT       0x04     // Send connection request in tcp mode(Client mode)
#define CR_DISCON        0x08     // Send closing reqeuset in tcp mode
#define CR_CLOSE         0x10     // Close socket
#define CR_SEND          0x20     // Update Tx memory pointer and send data
#define CR_SEND_MAC      0x21     // Send data with MAC address, so without ARP process
#define CR_SEND_KEEP     0x22     // Send keep alive message
#define CR_RECV          0x40     // Update Rx memory buffer pointer and receive data// S0_SR values
#define SOCK_CLOSED      0x00     // Closed
#define SOCK_INIT        0x13     // Init state
#define SOCK_LISTEN      0x14     // Listen state
#define SOCK_SYNSENT     0x15     // Connection state
#define SOCK_SYNRECV     0x16     // Connection state
#define SOCK_ESTABLISHED 0x17     // Success to connect
#define SOCK_FIN_WAIT    0x18     // Closing state
#define SOCK_CLOSING     0x1A     // Closing state
#define SOCK_TIME_WAIT    0x1B     // Closing state
#define SOCK_CLOSE_WAIT  0x1C     // Closing state
#define SOCK_LAST_ACK    0x1D     // Closing state
#define SOCK_UDP         0x22     // UDP socket
#define SOCK_IPRAW       0x32     // IP raw mode socket
#define SOCK_MACRAW      0x42     // MAC raw mode socket
#define SOCK_PPPOE       0x5F     // PPPOE socket
#define TX_BUF_MASK      0x07FF   // Tx 2K Buffer Mask:
#define RX_BUF_MASK      0x07FF   // Rx 2K Buffer Mask:
#define NET_MEMALLOC     0x05     // Use 2K of Tx/Rx Buffer
#define TCP_PORT         80       // TCP/IP Port

flash uint8_t mac_addr[] = {0x00,0x16,0x36,0xDE,0x58,0xF6};
flash uint8_t ip_addr[] = {192,168,1,125};
flash uint8_t sub_mask[] = {255,255,255,0};
flash uint8_t gtw_addr[] = {192,168,1,1};

// Define W5100 Socket Register and Variables Used
uint8_t sockreg;

#define MAX_BUF 1024
uint8_t buf[MAX_BUF];


Заголовки функций:
Код: Выделить всёРазвернуть
void SPI_Write
unsigned char SPI_Read
void W5100_Init(void)
void close(uint8_t sock)
void disconnect(uint8_t sock)
uint8_t socket(uint8_t sock,uint8_t eth_protocol,uint16_t tcp_port)
uint8_t listen(uint8_t sock)
uint16_t send(uint8_t sock,const uint8_t *buf,uint16_t buflen)
uint16_t recv(uint8_t sock,uint8_t *buf,uint16_t buflen)
uint16_t recv_size(void)


А вот собственно функции уже имеющиеся для работы с TCP-сервером или клиентом:
Код: Выделить всёРазвернуть
void SPI_Write(uint16_t addr,uint8_t data)
{
  // Activate the CS pin
  SPI_PORT &= ~(1<<SPI_CS);
  // Start Wiznet W5100 Write OpCode transmission
  SPDR = WIZNET_WRITE_OPCODE;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));
  // Start Wiznet W5100 Address High Bytes transmission
  SPDR = (addr & 0xFF00) >> 8;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));
  // Start Wiznet W5100 Address Low Bytes transmission
  SPDR = addr & 0x00FF;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));

  // Start Data transmission
  SPDR = data;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));
  // CS pin is not active
  SPI_PORT |= (1<<SPI_CS);
}

unsigned char SPI_Read(uint16_t addr)
{
  // Activate the CS pin
  SPI_PORT &= ~(1<<SPI_CS);
  // Start Wiznet W5100 Read OpCode transmission
  SPDR = WIZNET_READ_OPCODE;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));
  // Start Wiznet W5100 Address High Bytes transmission
  SPDR = (addr & 0xFF00) >> 8;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));
  // Start Wiznet W5100 Address Low Bytes transmission
  SPDR = addr & 0x00FF;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));

  // Send Dummy transmission for reading the data
  SPDR = 0x00;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));

  // CS pin is not active
  SPI_PORT |= (1<<SPI_CS);
  return(SPDR);
}

void W5100_Init(void)
{
  // Ethernet Setup
  // Setting the Wiznet W5100 Mode Register: 0x0000
  SPI_Write(MR,0x80);            // MR = 0b10000000;
  // Setting the Wiznet W5100 Gateway Address (GAR): 0x0001 to 0x0004
  SPI_Write(GAR + 0,gtw_addr[0]);
  SPI_Write(GAR + 1,gtw_addr[1]);
  SPI_Write(GAR + 2,gtw_addr[2]);
  SPI_Write(GAR + 3,gtw_addr[3]);
  // Setting the Wiznet W5100 Source Address Register (SAR): 0x0009 to 0x000E
  SPI_Write(SAR + 0,mac_addr[0]);
  SPI_Write(SAR + 1,mac_addr[1]);
  SPI_Write(SAR + 2,mac_addr[2]);
  SPI_Write(SAR + 3,mac_addr[3]);
  SPI_Write(SAR + 4,mac_addr[4]);
  SPI_Write(SAR + 5,mac_addr[5]);
  // Setting the Wiznet W5100 Sub Mask Address (SUBR): 0x0005 to 0x0008
  SPI_Write(SUBR + 0,sub_mask[0]);
  SPI_Write(SUBR + 1,sub_mask[1]);
  SPI_Write(SUBR + 2,sub_mask[2]);
  SPI_Write(SUBR + 3,sub_mask[3]);
  // Setting the Wiznet W5100 IP Address (SIPR): 0x000F to 0x0012
  SPI_Write(SIPR + 0,ip_addr[0]);
  SPI_Write(SIPR + 1,ip_addr[1]);
  SPI_Write(SIPR + 2,ip_addr[2]);
  SPI_Write(SIPR + 3,ip_addr[3]);

  // Setting the Wiznet W5100 RX and TX Memory Size (2KB),
  SPI_Write(RMSR,NET_MEMALLOC);
  SPI_Write(TMSR,NET_MEMALLOC);
}

void close(uint8_t sock)
{
   if (sock != 0) return;
   // Send Close Command
   SPI_Write(S0_CR,CR_CLOSE);
   // Waiting until the S0_CR is clear
   while(SPI_Read(S0_CR));
}

void disconnect(uint8_t sock)
{
   if (sock != 0) return;
   // Send Disconnect Command
   SPI_Write(S0_CR,CR_DISCON);
   // Wait for Disconecting Process
   while(SPI_Read(S0_CR));
}

uint8_t socket(uint8_t sock,uint8_t eth_protocol,uint16_t tcp_port)
{
    uint8_t retval=0;
    if (sock != 0) return retval;

    // Make sure we close the socket first
    if (SPI_Read(S0_SR) == SOCK_CLOSED) {
      close(sock);
    }
    // Assigned Socket 0 Mode Register
    SPI_Write(S0_MR,eth_protocol);

    // Now open the Socket 0
    SPI_Write(S0_PORT,((tcp_port & 0xFF00) >> 8 ));
    SPI_Write(S0_PORT + 1,(tcp_port & 0x00FF));
    SPI_Write(S0_CR,CR_OPEN);
    // Open Socket
    // Wait for Opening Process
    while(SPI_Read(S0_CR));
    // Check for Init Status
    if (SPI_Read(S0_SR) == SOCK_INIT)
      retval=1;
    else
      close(sock);

    return retval;
}

uint8_t listen(uint8_t sock)
{
   uint8_t retval = 0;
   if (sock != 0) return retval;
   if (SPI_Read(S0_SR) == SOCK_INIT) {
     // Send the LISTEN Command
     SPI_Write(S0_CR,CR_LISTEN);

     // Wait for Listening Process
     while(SPI_Read(S0_CR));
     // Check for Listen Status
     if (SPI_Read(S0_SR) == SOCK_LISTEN)
       retval=1;
     else
       close(sock);
    }
    return retval;
}

uint16_t send(uint8_t sock,const uint8_t *buf,uint16_t buflen)
{
    uint16_t ptr,offaddr,realaddr,txsize,timeout;

    if (buflen <= 0 || sock != 0) return 0;

    // Make sure the TX Free Size Register is available
    txsize=SPI_Read(SO_TX_FSR);
    txsize=(((txsize & 0x00FF) << 8 ) + SPI_Read(SO_TX_FSR + 1));

    timeout=0;
    while (txsize < buflen) {
     delay_ms(1);     txsize=SPI_Read(SO_TX_FSR);
     txsize=(((txsize & 0x00FF) << 8 ) + SPI_Read(SO_TX_FSR + 1));
     // Timeout for approx 1000 ms
     if (timeout++ > 1000) {

       // Disconnect the connection
       disconnect(sock);
       return 0;
     }
   }

   // Read the Tx Write Pointer
   ptr = SPI_Read(S0_TX_WR);
   offaddr = (((ptr & 0x00FF) << 8 ) + SPI_Read(S0_TX_WR + 1));

    while(buflen) {
      buflen--;
      // Calculate the real W5100 physical Tx Buffer Address
      realaddr = TXBUFADDR + (offaddr & TX_BUF_MASK);
      // Copy the application data to the W5100 Tx Buffer
      SPI_Write(realaddr,*buf);
      offaddr++;
      buf++;
    }

    // Increase the S0_TX_WR value, so it point to the next transmit
    SPI_Write(S0_TX_WR,(offaddr & 0xFF00) >> 8 );
    SPI_Write(S0_TX_WR + 1,(offaddr & 0x00FF));

    // Now Send the SEND command
    SPI_Write(S0_CR,CR_SEND);

    // Wait for Sending Process
    while(SPI_Read(S0_CR));

    return 1;
}

uint16_t recv(uint8_t sock,uint8_t *buf,uint16_t buflen)
{
    uint16_t ptr,offaddr,realaddr;

    if (buflen <= 0 || sock != 0) return 0;

    // If the request size > MAX_BUF,just truncate it
    if (buflen > MAX_BUF)
      buflen=MAX_BUF - 2;
    // Read the Rx Read Pointer
    ptr = SPI_Read(S0_RX_RD);
    offaddr = (((ptr & 0x00FF) << 8 ) + SPI_Read(S0_RX_RD + 1));

    while(buflen) {
      buflen--;
      realaddr=RXBUFADDR + (offaddr & RX_BUF_MASK);
      *buf = SPI_Read(realaddr);
      offaddr++;
      buf++;
    }
    *buf='\0';        // String terminated character

    // Increase the S0_RX_RD value, so it points to the next receive
    SPI_Write(S0_RX_RD,(offaddr & 0xFF00) >> 8 );
    SPI_Write(S0_RX_RD + 1,(offaddr & 0x00FF));

    // Now Send the RECV command
    SPI_Write(S0_CR,CR_RECV);
    delay_us(5);    // Wait for Receive Process

    return 1;
}

uint16_t recv_size(void)
{
  return ((SPI_Read(S0_RX_RSR) & 0x00FF) << 8 ) + SPI_Read(S0_RX_RSR + 1);
}


Может кто сможет подсказать как на базе сего организовать получение настроек по DHCP ? :pardon:
Insler
 
Сообщения: 42
Зарегистрирован: 24 апр 2014, 02:46
Откуда: Санкт-Петербург
прог. языки: С

Re: W5100 DHCP [MEGA AVR]

Сообщение Виктор Казаринов » 10 авг 2014, 15:35

А какую-нибудь Raspberry PI или что-то аналогичное использовать религия не позволяет?
Проект Robosonic RS http://www.aigod.com
Аватара пользователя
Виктор Казаринов
 
Сообщения: 1387
Зарегистрирован: 21 июн 2006, 11:22
Откуда: г. Омск
Skype: victorkazarinov
прог. языки: почти все понемногу
ФИО: Казаринов Виктор Геннадьевич

Re: W5100 DHCP [MEGA AVR]

Сообщение Insler » 10 авг 2014, 15:38

Виктор Казаринов писал(а):А какую-нибудь Raspberry PI или что-то аналогичное использовать религия не позволяет?

Неа, не позволяет :)
Я делаю много девайсов, и мини-ПК слишком дорогое удовольствие для таких развлечений )
Insler
 
Сообщения: 42
Зарегистрирован: 24 апр 2014, 02:46
Откуда: Санкт-Петербург
прог. языки: С

Re: W5100 DHCP [MEGA AVR]

Сообщение Dmitry__ » 10 авг 2014, 15:44

А чем не устраивают исходники с efo или сайта wiznet? Игрался лет 10 назад, все работало...
http://www.efo.ru/doc/Wiznet/Wiznet.pl?849
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: W5100 DHCP [MEGA AVR]

Сообщение Insler » 10 авг 2014, 15:50

Dmitry__ писал(а):А чем не устраивают исходники с efo или сайта wiznet? Игрался лет 10 назад, все работало...
http://www.efo.ru/doc/Wiznet/Wiznet.pl?849



Хм...
1. У меня W5100
2. Я юзаю CodeVision AVR
3. Непонятно насколько все это совместимо и стоит ли заморачиваться. Я изначально-то потратил несколько часов, чтобы переписать чужие примеры под CV AVR, и то, получился только сервер изначально.

А тут когда уже потрачено столько сил и времени, и либа почти готова, осталось добавить то только получение настроек DHCP по UDP и все в шоколаде :с
Insler
 
Сообщения: 42
Зарегистрирован: 24 апр 2014, 02:46
Откуда: Санкт-Петербург
прог. языки: С

Re: W5100 DHCP [MEGA AVR]

Сообщение Dmitry__ » 10 авг 2014, 15:59

Insler писал(а):Хм...
1. У меня W5100

Ссылку ниже пролистай:
W5100
DHCP - клиент
Описание реализации DHCP-клиента

Какие-то ссылки не работают, искать их в гугле...

Insler писал(а):3. Непонятно насколько все это совместимо и стоит ли заморачиваться.

Не знаю что ответить :)
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: W5100 DHCP [MEGA AVR]

Сообщение Insler » 10 авг 2014, 16:48

Там просто в этих примерах кода на over 1000 строчек кода на GCC-подобном языке с вытаскиванием функций из 3-4х либ, раскиданных по разным папкам. И перебегать туда сюда в поисках зависимостей, отсекая все лишнее - это многодневный ад. Я, собственно, и понадеялся, что кто-то уже раскурил все это дело и мог бы поделиться советом каким..
Insler
 
Сообщения: 42
Зарегистрирован: 24 апр 2014, 02:46
Откуда: Санкт-Петербург
прог. языки: С

Re: W5100 DHCP [MEGA AVR]

Сообщение Виктор Казаринов » 10 авг 2014, 21:44

Insler писал(а):Я делаю много девайсов, и мини-ПК слишком дорогое удовольствие для таких развлечений )
Какова же смета вашего устройства, если 35$ вам дорого? Вы еще добавьте стоимость разработки ПО. Она может быть много меньше чем в вашем варианте.
Проект Robosonic RS http://www.aigod.com
Аватара пользователя
Виктор Казаринов
 
Сообщения: 1387
Зарегистрирован: 21 июн 2006, 11:22
Откуда: г. Омск
Skype: victorkazarinov
прог. языки: почти все понемногу
ФИО: Казаринов Виктор Геннадьевич

Re: W5100 DHCP [MEGA AVR]

Сообщение Insler » 10 авг 2014, 22:11

Виктор Казаринов писал(а):
Insler писал(а):Я делаю много девайсов, и мини-ПК слишком дорогое удовольствие для таких развлечений )
Какова же смета вашего устройства, если 35$ вам дорого? Вы еще добавьте стоимость разработки ПО. Она может быть много меньше чем в вашем варианте.



600 рублей сейчас получается себестоимость, включая свою мелкую плату под свой корпус. Распберри слишком здоровая, да и вообще формфактор не тот совсем, мне нужна куча клемм с входами/выходами и прочие вкусняшки. Собственно, сейчас не принципиально. Есть задача, надо ее решить )
Insler
 
Сообщения: 42
Зарегистрирован: 24 апр 2014, 02:46
Откуда: Санкт-Петербург
прог. языки: С

Re: W5100 DHCP [MEGA AVR]

Сообщение Angel71 » 11 авг 2014, 00:57

Ещё в ардуиновских либах есть нужный функционал, главное поискать и позаимствовать/адаптировать из них нужное. Хотя упоминание проблемы с несчастными 1000 строк кода настораживает.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: W5100 DHCP [MEGA AVR]

Сообщение elmot » 02 сен 2014, 17:35

Insler писал(а):600 рублей сейчас получается себестоимость, включая свою мелкую плату под свой корпус.

По десять баксов можно найти роутерные платы со всей линуксой на борту. Размер будет еще меньше.
Аватара пользователя
elmot
 
Сообщения: 5691
Зарегистрирован: 10 ноя 2011, 12:02
Откуда: Turku, Finland
Skype: elmot73
прог. языки: Java и все-все=все
ФИО: Илья

Re: W5100 DHCP [MEGA AVR]

Сообщение -= Александр =- » 05 сен 2014, 21:24

W5300 когда-то использовал. Задача была серьезная - данные из ПЛИС гнать. Работает скотина до сих пор где-то. И скорость неплохая была. Но вот до DHCP руки так и не дошли, сделал все на статических адресах.
Ниндзя - круче всех. Они умеют ходить по воде, делить на ноль и угадывать шаффл в АйПоде.
Аватара пользователя
-= Александр =-
Мастер Самоделкин
 
Сообщения: 3678
Зарегистрирован: 11 окт 2004, 19:20
Откуда: Россия, СПб
прог. языки: C/C++, Python, asm
ФИО: Курмис Александр Андреевич

Re: W5100 DHCP [MEGA AVR]

Сообщение Insler » 20 ноя 2014, 13:19

Angel71 писал(а):Ещё в ардуиновских либах есть нужный функционал, главное поискать и позаимствовать/адаптировать из них нужное. Хотя упоминание проблемы с несчастными 1000 строк кода настораживает.



То есть, я вполне могу попросить Вас адаптировать некоторые ардуиновские либы под GCC AVR и GCC MSP430 ? :)
Сколько стоит? 8)
Insler
 
Сообщения: 42
Зарегистрирован: 24 апр 2014, 02:46
Откуда: Санкт-Петербург
прог. языки: С

Re: W5100 DHCP [MEGA AVR]

Сообщение Angel71 » 20 ноя 2014, 13:52

загадочная логическая связь. попросить можно, так же как и заняться этим самостоятельно.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: W5100 DHCP [MEGA AVR]

Сообщение Insler » 20 ноя 2014, 13:54

Angel71 писал(а):загадочная логическая связь.

Вполне прямая связь. Если что-то для кого-то очень просто сделать, то намного продуктивнее будет попросить это его и сделать. А либы выложить потом в открытый доступ, и все будут счастливы. Зачем тратить лишнее время и силы?

Я же этим занимаюсь не потому что получаю удовольствие от написания и переписывания библиотек, и не ради прокачки себя в этом направлении, мне куда интереснее наблюдать результат. А если результата можно добиться меньшими усилиями, то вообще хорошо
Insler
 
Сообщения: 42
Зарегистрирован: 24 апр 2014, 02:46
Откуда: Санкт-Петербург
прог. языки: С


Вернуться в Микроконтроллеры

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6