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

 
 
> LPC17, FreeRTOS, uIP, проблема с DHCP, а так же странности с ICMP
Cosmojam
сообщение Feb 2 2012, 14:19
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Всем привет!
Пробую uIP + FreeRTOS, за основу взят пример что в комплекте с осью CORTEX_LPC1768_GCC_RedSuite. После небольшой модификации эзернет драйвера заработало на моей плате.
Выкинул оттуда веб-сервер, поигрался с хелоуворлдами - ОК, теперь нужно DHCP.
Взял из uip-1.0 пример dhcp, В uip-conf.h исправил
Код
#define UIP_CONF_BUFFER_SIZE     1536
#define UIP_CONF_UDP             1

В потоке uip изменения минимальные по сравнению с оригинальным демо:
Код
void vuIP_Task(void *pvParameters)
{
portBASE_TYPE i;
    uip_ipaddr_t xIPAddr;
    struct timer periodic_timer, arp_timer;
    extern void ( vEMAC_ISR_Wrapper)(void);

    (void) pvParameters;

    /* Initialise the uIP stack. */
    timer_set(&periodic_timer, configTICK_RATE_HZ / 2);
    timer_set(&arp_timer, configTICK_RATE_HZ * 10);
    uip_init();
    uip_arp_init(); /* добавил тут /*
//    uip_ipaddr( xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 ); /* убрано т.к. нужен дхцп */
//    uip_sethostaddr( xIPAddr );
//    uip_ipaddr( xIPAddr, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 );
//    uip_setnetmask( xIPAddr );
    /* Create the semaphore used to wake the uIP task. */
    vSemaphoreCreateBinary( xEMACSemaphore );

    /* Initialise the MAC. */
    while (lEMACInit() != pdPASS)
    {
        vTaskDelay(uipINIT_WAIT);
    }

    portENTER_CRITICAL();
    {
        LPC_EMAC->IntEnable = (INT_RX_DONE | INT_TX_DONE);

        /* Set the interrupt priority to the max permissible to cause some
         interrupt nesting. */
        NVIC_SetPriority(ENET_IRQn, configEMAC_INTERRUPT_PRIORITY);

        /* Enable the interrupt. */
        NVIC_EnableIRQ(ENET_IRQn);
        prvSetMACAddress();
    }
    portEXIT_CRITICAL();

    dhcpc_init(&uip_ethaddr, sizeof(uip_ethaddr)); /* собственно оно */
    printf("MAC: %X:%X:%X:%X:%X:%X\n", uip_ethaddr.addr[0], uip_ethaddr.addr[1],uip_ethaddr.addr[2],
            uip_ethaddr.addr[3],uip_ethaddr.addr[4],uip_ethaddr.addr[5]);
    dhcpc_request();

/ * далее цикл без изменеий */


Но ничего не работает. Wireshark-ом не вижу в сети дхцп дискавери от девайса, вообще тишина. dhcpc_appcall() которая задефайнена как UIP_UDP_APPCALL не вызывается вообще.

И ещё странность есть в ответах на пинги. Девайс отвечает дважды на каждый echo request, т.е. вот что вижу если пингую его с компьютера:
Цитата
64 bytes from 192.168.1.100: icmp_req=60916 ttl=64 time=0.140 ms
64 bytes from 192.168.1.100: icmp_req=60916 ttl=64 time=0.156 ms (DUP!)
64 bytes from 192.168.1.100: icmp_req=60917 ttl=64 time=0.139 ms
64 bytes from 192.168.1.100: icmp_req=60917 ttl=64 time=0.156 ms (DUP!)
64 bytes from 192.168.1.100: icmp_req=60918 ttl=64 time=0.137 ms
64 bytes from 192.168.1.100: icmp_req=60918 ttl=64 time=0.154 ms (DUP!)

И ваершарком чётко видно 2 одинаковых ответа на каждый запрос. Пока не копал в реализацию этой фичи (реализовано в uip.c, а там чёрт ногу сломит). Возможно это как-то связано с вышеописанной проблемой с DHCP и причиной тому какая-то врождённая кривизна той демки, либо моих рук sm.gif


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 4)
Cosmojam
сообщение Feb 2 2012, 17:49
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Небольшой прогресс благодаря чтению мануалов
В цикле потока нужно добавить обработку UDP:
Код
for (i = 0; i < UIP_UDP_CONNS; i++)
{
     uip_udp_periodic(i);
     if (uip_len > 0)
     {
         uip_arp_out();
         vSendEMACTxData(uip_len);
     }
}

После этого девайс начинает слать дхцп дискавери. Роутер тоже пишет что появился дхцп клиент с мак-адресом девайса и даже IP, т.е. роутре отдаёт ему настройки сети. Но девайс похоже их не принимает.


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Feb 2 2012, 19:24
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Продолжаю сам с собой говорить sm.gif
Странности получаются. В прототреде handle_dhcp есть 2 цикла. В первом отправляется DHCPDISCOVER и ожидается DHCPOFFER. Ответ проверяется так:
Код
if(uip_newdata() && parse_msg() == DHCPOFFER)
{
        s.state = STATE_OFFER_RECEIVED;
        break;
}

Функция parse_msg() первым делом проверяет message op code:
Код
if (m->op == DHCP_REPLY && memcmp(m->xid, xid, sizeof(xid)) == 0 && memcmp(
            m->chaddr, s.mac_addr, s.mac_len) == 0)
{
    memcpy(s.ipaddr, m->yiaddr, 4);
    return parse_options(&m->options[4], uip_datalen());
}
    return 0;

DHCP_REPLY == 2, тут всё сходится с RFC2131 (1 = BOOTREQUEST, 2 = BOOTREPLY), остальные условия тоже выполнятся и мы выпадаем из этого цикла и попадаем в новый. Теперь отправляется DHCPREQUEST и ожидается DHCPACK. Проверка message op code аналогична, но теперь она не выполняется т.к. в сообщении этот message op code не 2, а 1 что соответствует BOOTREQUEST, но не BOOTREPLY. При этом если отключить проверку этого условия (грязный хак) то всё работает, IP получает и всё красиво:
Код
f(uip_newdata()/* && parse_msg() == DHCPACK*/)
{
    struct dhcp_msg *m = (struct dhcp_msg *) uip_appdata;
    printf("xid: %X%X%X%X op: %d\n", m->xid[0], m->xid[1], m->xid[2], m->xid[3], m->op); /* в отладочных целях, именно тут видно не верный опкод */
    s.state = STATE_CONFIG_RECEIVED;
    break;
}

Т.е. DHCPACK всё же получен и даже верно распарсен, но почему в нём был не верный опкод? Попробовал вырубить дхцп сервер на роутере и включить dhcpd на компьютере - тоже самое.


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Feb 3 2012, 08:08
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



В дублировании пингов (как оказалось не только пингов, но и вообще всех пакетов) был виноват драйвер эзернет. Вроде разобрался с этим.
А DHCP не понятно всё так же. В DHCPACK, отправленном с компьютера, опкод верный - 2, а принимается на девайсе 1. Вот не знаю оставить грязный хак в надежде что больше багов не вылезет, или копать дальше


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Feb 4 2012, 21:04
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



На NXP-шном форуме помогли http://knowledgebase.nxp.com/showthread.php?t=2859
Надо добавить сброс флага UIP_NEWDATA после приёма DHCPOFFER
Код
   if(uip_newdata() && parse_msg() == DHCPOFFER) {
        uip_flags &= ~UIP_NEWDATA;
      dhcp_s.state = STATE_OFFER_RECEIVED;
      break;
    }
    uip_flags &= ~UIP_NEWDATA;

и после DHCPACK
Код
    if(uip_newdata() && parse_msg() == DHCPACK) {
        uip_flags &= ~UIP_NEWDATA;
      dhcp_s.state = STATE_CONFIG_RECEIVED;
      break;
    }
    uip_flags &= ~UIP_NEWDATA;

Ну, хоть так sm.gif
Цитата("uip.c")
UDP processing is really just a hack


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th July 2025 - 06:41
Рейтинг@Mail.ru


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