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

 
 
> 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
Ответов
Cosmojam
сообщение Feb 2 2012, 19:24
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 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



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

 


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


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