roboforum.ru

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

W5100 DHCP [MEGA AVR]

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:

Re: W5100 DHCP [MEGA AVR]

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

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

Re: W5100 DHCP [MEGA AVR]

Insler » 10 авг 2014, 15:38

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

Неа, не позволяет :)
Я делаю много девайсов, и мини-ПК слишком дорогое удовольствие для таких развлечений )

Re: W5100 DHCP [MEGA AVR]

Dmitry__ » 10 авг 2014, 15:44

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

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 и все в шоколаде :с

Re: W5100 DHCP [MEGA AVR]

Dmitry__ » 10 авг 2014, 15:59

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

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

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

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

Не знаю что ответить :)

Re: W5100 DHCP [MEGA AVR]

Insler » 10 авг 2014, 16:48

Там просто в этих примерах кода на over 1000 строчек кода на GCC-подобном языке с вытаскиванием функций из 3-4х либ, раскиданных по разным папкам. И перебегать туда сюда в поисках зависимостей, отсекая все лишнее - это многодневный ад. Я, собственно, и понадеялся, что кто-то уже раскурил все это дело и мог бы поделиться советом каким..

Re: W5100 DHCP [MEGA AVR]

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

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

Re: W5100 DHCP [MEGA AVR]

Insler » 10 авг 2014, 22:11

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



600 рублей сейчас получается себестоимость, включая свою мелкую плату под свой корпус. Распберри слишком здоровая, да и вообще формфактор не тот совсем, мне нужна куча клемм с входами/выходами и прочие вкусняшки. Собственно, сейчас не принципиально. Есть задача, надо ее решить )

Re: W5100 DHCP [MEGA AVR]

Angel71 » 11 авг 2014, 00:57

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

Re: W5100 DHCP [MEGA AVR]

elmot » 02 сен 2014, 17:35

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

По десять баксов можно найти роутерные платы со всей линуксой на борту. Размер будет еще меньше.

Re: W5100 DHCP [MEGA AVR]

-= Александр =- » 05 сен 2014, 21:24

W5300 когда-то использовал. Задача была серьезная - данные из ПЛИС гнать. Работает скотина до сих пор где-то. И скорость неплохая была. Но вот до DHCP руки так и не дошли, сделал все на статических адресах.

Re: W5100 DHCP [MEGA AVR]

Insler » 20 ноя 2014, 13:19

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



То есть, я вполне могу попросить Вас адаптировать некоторые ардуиновские либы под GCC AVR и GCC MSP430 ? :)
Сколько стоит? 8)

Re: W5100 DHCP [MEGA AVR]

Angel71 » 20 ноя 2014, 13:52

загадочная логическая связь. попросить можно, так же как и заняться этим самостоятельно.

Re: W5100 DHCP [MEGA AVR]

Insler » 20 ноя 2014, 13:54

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

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

Я же этим занимаюсь не потому что получаю удовольствие от написания и переписывания библиотек, и не ради прокачки себя в этом направлении, мне куда интереснее наблюдать результат. А если результата можно добиться меньшими усилиями, то вообще хорошо


Rambler\'s Top100 Mail.ru counter