|
|
  |
lwip с Rtos или без Rtos, Как лучше, правильнее, удобнее использовать стек с rtos или без |
|
|
|
Jan 31 2014, 12:45
|
Гуру
     
Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923

|
Думаю что не хочет работать из за этой ошибки tcp_slowtmr: no active pcbs вот часть кода: Код void tcp_slowtmr(void) { struct tcp_pcb *pcb, *prev; u16_t eff_wnd; u8_t pcb_remove; /* flag if a PCB should be removed */ u8_t pcb_reset; /* flag if a RST should be sent when removing */ err_t err;
err = ERR_OK;
++tcp_ticks; ++tcp_timer_ctr;
tcp_slowtmr_start: /* Steps through all of the active PCBs. */ prev = NULL; pcb = tcp_active_pcbs; if (pcb == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); } while (pcb != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); Не разобрася до конца с этим стеком, предполагаю он не может найти интерфейс активный. После лов иннициализации нужно установить какойто бит? Если нет системы не получиться использовать сокет, если правильно понял.
|
|
|
|
|
Jan 31 2014, 14:01
|
Гуру
     
Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923

|
Быстрый ,медленый таймер дергае tcptmr(), может еще что то нужно сбрасывать или устанавливать. Код void lwip_init_user(void) { lwip_init();
IP4_ADDR(&my_ipaddr_data, 192, 168, 0, 17); IP4_ADDR(&my_netmask_data, 255, 255, 255, 0); IP4_ADDR(&my_gw_data, 0, 0, 0, 0);
netif_add(netif_eth0, &my_ipaddr_data, &my_netmask_data, &my_gw_data, NULL, ethernetif_init,ethernet_input );//ip_input
netif_set_default(netif_eth0);
netif_set_up(netif_eth0);
}
while (1) // repeat forever { if (karusel < 10) karusel++; else karusel = 0;
switch (karusel) { case 1: {
curTicks = systick_counter;
// process packets that arrive in the interface ethernetif_input(netif_eth0);
// functions that should call from times to times if (curTicks - last_arp_time > ARP_TMR_INTERVAL) { etharp_tmr(); last_arp_time = curTicks; }
if (curTicks - last_tcp_time > TCP_TMR_INTERVAL) { last_tcp_time = curTicks; tcp_tmr(); } break; } //1
|
|
|
|
|
Jan 31 2014, 14:03
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата Если нет системы не получиться использовать сокет, если правильно понял. Да. Если у Вас пинга нету чего вы лезете к tcp_slowtmr ??? вам нужен только ARP, IP, ICMP. В изернете нельзя передавать пакеты меньшие 64 байт!!!, многие МАС не умеют дополнять пакет если он меньше 64 байт это надо будет сделать вам самим. STM32 умеет это делать но п омоему надо где то битик установить. P.S. Все по шагам. 1) Делаем функцию приема кадров изернет. Запускаем ее проверяем что она принимает правильно. Буфер расшифровываем в уме. 2) Делаем функцию передачи, создаем константный фрейм, засовываем его в функцию ловим ваершарком убеждаемся что все ок. 3) Прикручиваем эти функции к стеку. 4) Запускаем пинг. Смотрим ARP таблицу, если ваш МАС есть а девайс не пингается что с IP + ICMP, Если в таблице нету вашего МАСа копаем ARP. 5) Потом уже UDP + TCP Я использую FreeRTOS + LwIP примерно так у меня выглядят функции драйвера (прием вынесен в отдельную задачу) Прием: Код __task void EthernetDeamon(void *arg) { int32_t size; struct pbuf *p,*q; uint8_t* pkt; struct netif *ethif = (struct netif *)arg; for(;; ) { size = HwEMAC::RecivePacket((void**)&pkt, 1000); if ( size > 0 ) { p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); if (p != NULL) { for (q = p; q != NULL; q = q->next) { memcpy((u8_t*)q->payload, pkt, q->len); pkt += q->len; } HwEMAC::Recived(); if (tcpip_input(p,ethif) != ERR_OK) pbuf_free(p); } } else { LINKSTATUS_t ls = HwPHY::LinkStatus(PHY_ADDR); if ( ls == NOLINK ) { netif_set_link_down(ethif); HwEMAC::Stop(); } else { if (!netif_is_link_up(ethif)) { HwEMAC::Start(ls); netif_set_link_up(ethif); } } } } }; P.S. tcpip_input - используется если стек работает в режиме ОС (NO_SYS = 0), если без ос то фреймы нужно запихивать в ethernet_input передача: Цитата err_t EthernetOutput(struct netif *ethif, struct pbuf *p) { uint8_t* pkt; struct pbuf *q; if (HwEMAC::GetSendBuffer((void**)&pkt,20) != 0 ) return ERR_IF; for(q = p; q != NULL; q = q->next) { memcpy(pkt, q->payload, q->len); pkt += q->len; } HwEMAC::Send(p->tot_len); return ERR_OK; }
|
|
|
|
|
Feb 3 2014, 07:04
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата Первый с копированием данных из pbuf и второй запись указателя в дескриптор на pbuf в dma, в первом скопировал стек продолжает работать. во втором передал указатель и ждем когда произойдет передача. Может еще есть варианты и какой из этих лучше? Вам следует хорошо изучить PBUF, в pbuf пакет может лежать не одним цельным, а кусками этот код собирает из кусков 1 целый буфер. Код for(q = p; q != NULL; q = q->next) {[quote][/quote] memcpy(pkt, q->payload, q->len); pkt += q->len; } Это можно конечно исправить, установив в настройках размер PBUF максимальному размеру фрейма. Но это очень большое расточительство памяти и никак не оправдывает себя. Есть маленький плюс позволяет сделать зеро копи драйвер. Но выигрыш очень мизерный. А памяти все будет жрать немерено. У меня сделано так. Для дма драйвера выделено 2-4 буфера на передачу размером в максимальный фрейм (1512 по моему). Есть указатель на текущий буфер. Я его беру туда копирую pbuf, запускаю передачу дма, а текущему указателю присваиваю адрес следующего буфера и так по кругу. С приемом также есть от 2 - 16 (буферов дма размером в фрейм), есть указатель на текущий. Так как я использую ОС нет необходимости для приема использовать прерывания, так как дма умеет по кругу писать в буфера. Буру текущий указатель проверяю есть ли новый фрейм если есть, копирую его в новый pbuf, этот мечу свободным передвигаю указатель на следующий. И так по кругу. У меня stm32f107 UDP - 70 Mbit/s TCP - 52 Mbit/s (4 буфера на передачу и 4 буфера на прием). #define PBUF_POOL_SIZE 24 #define PBUF_POOL_BUFSIZE 256 Цитата Понятно. Еще наверно будет проблема без ос, если потребуется управлять через веб интерфейс с нескольких компьютеров. Хотя наверно можно обойтись, слушаем порт 80 как присоединился клиент его апи сохраняем, делаем что то, тут присоединился компьютер с другим айпи ему отправиться последняя страница которую смотрели последний раз,как это лучше реализовать. С ос понятно каждому клиенту новый поток. Проблемы нету, это можно сделать. Но именно это меня и заставило перейти на ОС. Так под ОС это реализовывается очень просто на каждое соединение свой таск. Без ОС это столько всякого гемора. Особенно если надо передавать большие фалы устройству. Когда я это сделал без ОС я понял что у меня получилась своя собственная маленькая ос в программе и зачем это ?. Почему это так я могу рассказать но много писать. Могу сказать так что стек под ОС быстрее работает (следует понимать не скорость передачи,а больше ресурсов остается основной программе), меньше расходуется памяти, да да МЕНЬШЕ. Код становится хорошо читаемым и понимаемым, вместо громадных автоматов состояний. Ну и конечно же надо хорошо понимать много поточность, и как правильно писать под ОС и наче получите что то работающее очень плохо.
|
|
|
|
|
Feb 3 2014, 12:24
|
Гуру
     
Группа: Свой
Сообщений: 2 546
Регистрация: 23-05-07
Из: Самарская область Сызрань
Пользователь №: 27 923

|
Цитата максимальный фрейм (1512 по моему). наверно 1536 #define PBUF_POOL_SIZE 24 * #define PBUF_POOL_BUFSIZE 256 / 4 Пока тоже так сделал сейчас немного поэкспериментирую что получится. Как различаете соединения по портам если они все приходят на порт 80 и с одного айпи?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|