Jump to content

    

IvanPletnev

Участник
  • Content Count

    60
  • Joined

  • Last visited

Everything posted by IvanPletnev


  1. В моём случае точно не из-за питания, на одной и той же плате всё. Сейчас тестирую, всё работает отлично.
  2. А и правда компилируется этот код. Но избавиться от подсветки "неактивного" кода мне так и не удалось. #include "lwip/opt.h" #if LWIP_NETIF_STATUS_CALLBACK void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback){ ..... #error bla-bla } #endif Даёт ошибку. Значит, всё работает. Но эта подсветка сильно сбивает с толку.
  3. Здравствуйте, коллеги!! Может, конечно, глупый вопрос задам, не пинайте сильно. В который раз уже замечаю, что CubeIDE иногда отказывается реагировать на define. Вот пример: В файле lwipopts.h #define LWIP_NETIF_STATUS_CALLBACK 1 в файле netif.c #include "lwip/opt.h" #if LWIP_NETIF_STATUS_CALLBACK void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback){ ..... } Соответственно, в файле lwip/opt.h подключен файл lwipopts.h. Всё, как обычно. Но! Код, который внутри #if #endif неактивен(подсвечен) и не компилируется. При наведении курсора на LWIP_NETIF_STATUS_CALLBACK в подсказке показывается 0. При этом в файле opt.h конструкция #if !defined LWIP_NETIF_STATUS_CALLBACK || defined __DOXYGEN__ #define LWIP_NETIF_STATUS_CALLBACK 0 #endif работает. И если нажать в файле netif.c на LWIP_NETIF_STATUS_CALLBACK с зажатым ctrl, то редактор перекидывает на этот дефайн в файле lwipopts.h, где стоит единица. Такое регулярно случается, потом проходит само собой. Почему это происходит и как бороться с этим, кто нибудь может объяснить?
  4. В общем, экспериментальным путём я выяснил, что эта проблема появляется, когда код генерируется CubeMX v. 6.2.1 и STM32Cube F4 v. 1.26.1. Когда код сгенерирован CubeMX v. 6.1.1 или 6.1.2 и STM32Cube F4 v. 1.25.2 всё работает отлично. Заметил, что в версии 1.26.1 обновлена FreeRTOS до 10.3.1. Пока не разбирался, в чём там отличия.
  5. Больше нет никакой разницы. Просто мне понадобился web интерфейс на устройство, которое уже почти готово. Для того, чтобы потренироваться с http сервером я не стал встраивать его сразу в устройство, а решил сначала сделать для него отдельный проект. Взял CubeIDE, настроил LWIP, сгенерировал, запустил. И потом несколько дней провозился собственно с сабжем. Пока не создал проект в CubeMX с точно такими же настройками. Всё совершенно одинаково, но проект из CubeMX работает хорошо, а из CubeIDE нет. Теперь вот надо прикручивать SGI и SSI. Если кто-то поделится опытом в этом смысле, буду благодарен.
  6. STM32CubeMX встроен в STM32CubeIDE, то есть в Eclipse, по сути. Но, видимо, кривовато
  7. В общем, коллеги, я совершенно не понимаю, почему, но когда я сгенерировал проект не в STM32CubeIDE, а в STM32CubeMX, проблема пропала сама собой. Теперь мой сервер работает отлично.
  8. Сегодня проверил то же самое с F746-DISCO. Собрал пример от ST, закинул свою страницу, запустил. Всё работает отлично, несмотря на то, что стек жалуется на нехватку памяти. Но с нехваткой памяти я знаю, как справиться. А когда генерирую новый проект из CubeIDE, http сервер работает медленно и генерирует ретрансмиты. Код сервера беру из этого же примера. Три дня уже потратил в поисках проблемы. Куда смотреть, подскажите пожалуйста.
  9. void http_server_serve(struct netconn *conn) { struct netbuf *inbuf; err_t recv_err; char* buf; u16_t buflen; struct fs_file file; /* Read the data from the port, blocking if nothing yet there. We assume the request (the part we care about) is in one netbuf */ recv_err = netconn_recv(conn, &inbuf); if (recv_err == ERR_OK) { if (netconn_err(conn) == ERR_OK) { netbuf_data(inbuf, (void**)&buf, &buflen); /* Is this an HTTP GET command? (only check the first 5 chars, since there are other formats for GET, and we're keeping it very simple )*/ if ((buflen >=5) && (strncmp(buf, "GET /", 5) == 0)) { if ((strncmp((char const *)buf,"GET / ",6)==0)||(strncmp((char const *)buf,"GET /index.html",15)==0)) { fs_open(&file, "/index.html"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else if (strncmp((char const *)buf,"GET /port1.html",15)==0) { fs_open(&file, "/port1.html"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else if (strncmp((char const *)buf,"GET /IMG/logo.png",17)==0) { fs_open(&file, "/IMG/logo.png"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else if (strncmp((char const *)buf,"GET /NotoSerif.woff",19)==0) { fs_open(&file, "/NotoSerif.woff"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else if (strncmp((char const *)buf,"GET /style.css",14)==0) { fs_open(&file, "/style.css"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else if (strncmp((char const *)buf,"GET /IMG/img1.jpg",17)==0) { fs_open(&file, "/IMG/img1.jpg"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else if (strncmp((char const *)buf,"GET /IMG/img2.jpg",17)==0) { fs_open(&file, "/IMG/img2.jpg"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else if (strncmp((char const *)buf,"GET /IMG/img3.jpg",17)==0) { fs_open(&file, "/IMG/img3.jpg"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else if (strncmp((char const *)buf,"GET /IMG/arrow.png",18)==0) { fs_open(&file, "/IMG/arrow.png"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } else { fs_open(&file, "/404.html"); netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY); fs_close(&file); } printf("Heap minimum size %u\r\n",xPortGetMinimumEverFreeHeapSize()); } } } /* Close the connection (server closes in HTTP) */ netconn_close(conn); /* Delete the buffer (netconn_recv gives us ownership, so we have to make sure to deallocate the buffer) */ netbuf_delete(inbuf); } На самом деле, сейчас функция передачи это функция из примера ST. Только с моими файлами и путями. Только в примере она работает, как нужно, а у меня пока нет. Сейчас смотрю в сторону приоритетов прерываний, сравниваю пример с моими.
  10. Да, и еще. Вставляю свою страницу в пример от ST, меняю пути к файлам, всё работает отлично. Хотя в lwipopts у меня гораздо больше ресурсов, чем в примере от ST.
  11. Уважаемые коллеги, здравствуйте! Делаю http сервер на sockets API, всё в целом работает, но во-первых, иногда (не всегда) страница 60кб довольно долго грузится (3-4c), а во-вторых, wireshark показывает ретрансмиты (см. картинку). Статистика LWIP показывает, что всего хватает. И памяти, и буферов. Ошибки в статистике все по нолям. И в общем, эти ретрансмиты не мешают, но всё равно хочется избавиться от них. Пробовал делать параллельный сервер (отдельная задача на каждый сокет), но во-первых это не помогло уйти от ретрансмитов, а во-вторых появилась проблема некорректного закрытия сокетов, которые со временем накапливались и вешали приложение напрочь. В общем, подскажите, пожалуйста, может у кого-то есть решение вышеперечисленных проблем?
  12. Да, именно так. Поэтому спасибо за наводку)
  13. Да, коллеги, это делается элементарно, оказывается. int optValue = 1; setsockopt(newconn, IPPROTO_TCP, TCP_NODELAY, (void*)&optValue, sizeof(optValue)); Работает идеально, я получил, что хотел.
  14. UDP тоже надо сделать. Позже займусь) А как определить текущий PCB для tcp_nagle_disable?
  15. Уважаемые коллеги, здравствуйте! Делаю устройство на STM32F427 с использованием LWIP Sockets. Отправляю в сокет пакеты длиной 9 байт с частотой 120Гц. На приёмной стороне среднее количество полученных девятибайтовых пакетов за секунду 120. То есть все пакеты доходят до адресата отлично. Но! Wireshark мне показывает вот такую картину. Он говорит, что за секунду отправляется 5 TCP пакетов с payload 216 байт. То есть 24 девятибайтовых посылки в одном пакете. Мне нужно передавать быстроменяющийся сигнал, и за 200мс он безнадежно устареет. Вопрос такой. Как сделать, чтобы LWIP старался отправить TCP пакет сразу, а не накапливал данные в буфере? Я понимаю, что такой подход неэффективен, но нужно именно так. Заранее благодарю за ответы.
  16. Уважаемые коллеги, не нашел на форуме ветки про ESP32, поэтому напишу здесь. Тем, кто изучает этот МК полезно будет это знать. Начал знакомиться с этим МК, запустил пример TCP сервера из комплекта SDK, всё работает замечательно. Решил пропинговать пакетами по 64 байта, заметил, что время пинга значительное - от 80 до 200мс. Начал изучать документацию, оказалось, что начиная с версии 3.1, по умолчанию стоит режим пониженного потребления (WIFI_PS_MIN_MODEM). Это значит, что в промежутке между маяками точки доступа WiFi спит. Чтобы включить нормальный режим, нужно вызвать функцию esp_wifi_set_ps(WIFI_PS_NONE); Время пинга теперь составляет от 2 до 5 мс. Пользуйтесь.
  17. Точно! Вы правы! У меня включен аппаратный расчет контрольных сумм. Я просто закомментировал функцию расчета контрольной суммы iecho->chksum = inet_chksum(iecho, len); и всё заработало!!!! Спасибо огромное!.
  18. Так, кое-что заработало. Теперь у меня отправляется один ICMP пакет тык. Но вылезла очередная проблема. Вот моя функция подготовки пакета: static void ping_prepare_echo(struct icmp_echo_hdr *iecho, u16_t len) { size_t i; size_t data_len = len - sizeof(struct icmp_echo_hdr); ICMPH_TYPE_SET(iecho, ICMP_ECHO); ICMPH_CODE_SET(iecho, 0); iecho->chksum = 0; iecho->id = PING_ID; iecho->seqno = htons(++ping_seq_num); /* fill the additional data buffer with some data */ for (i = 0; i < data_len; i++) { ((char*) iecho)[sizeof(struct icmp_echo_hdr) + i] = (char) i; } iecho->chksum = inet_chksum(iecho, len); } Wireshark говорит мне, что некорректная контрольная сумма. 0x0000 вместо 0x574e тык. Хотя контрольная сумма считается правильно и заносится в заголовок ICMP пакета тык. Все остальные поля структуры передаются правильно, а контрольная сумма при передаче куда-то исчезает. Видимо поэтому, когда я пытаюсь пинговать windows компьютер, он на этот пакет ничего не отвечает.
  19. Похоже, я нашел причину. В отладчике Atollic TrueStudio я обратил внимание на то, что задача виснет, когда в стеке находятся функции, отправляющие сообщения в очередь. Начал копать LWIP и обнаружил, что DEFAULT_RAW_RECVMBOX_SIZE в файле opt.h равен 0. Поэтому, наверное, задача и виснет. Пока не пробовал, но должно помочь.
  20. Уважаемые коллеги, здравствуйте! Столкнулся с такой проблемой. STM32F429, стек LWIP v.2.0.3, FreeRTOS. Пытаюсь создать сокет SOCK_RAW для периодического пинга подключенного клиента, он не создаётся. Причем, похоже, задача виснет, потому что диагностические сообщение не выводятся. При этом сокеты SOCK_STREAM и SOCK_DGRAM создаются без проблем. Кто-нибудь подскажет, куда копнуть? if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { puts("PING socket error"); return; } printf("Socket No %u created\r\n", s);
  21. Ну так можно посчитать клиентов, и если их больше заданного количества принудительно разрывать соединение, не создавая задач.
  22. Попробовал сделать так, через создание новых задач, работает отлично! Если от клиента мы получаем запрос на закрытие соединения (FIN), в задаче, в которой крутится функция recv, корректно закрываем сокет, удаляем созданные задачи. newconn = accept(sock, (struct sockaddr *)&remotehost, (socklen_t *)&size);//принимаем входящее подключение if ((newconn>1)||(newconn<1)){ close(newconn); } else if (newconn==1){ HAL_GPIO_WritePin(LD1_GPIO_Port,LD1_Pin, GPIO_PIN_SET); socketReceiveTaskHandle=sys_thread_new("sockRecvTask",socketReceiveTask,(void*)newconn,256,osPriorityNormal); socketSendTaskHandle=sys_thread_new("sockSendTask",socketSendTask,(void*)newconn,256,osPriorityNormal); } Еще нужно сделать, чтобы по прерыванию от PHY, сигнализирующему о какой-либо ошибке соединения, делалось тоже самое. Надо тестировать, конечно. Нет, в моём случае количество соединений ограничено, мне не нужно создавать много.
  23. На одном из форумов нашёл решение. После успешного accept создаётся задача, которой в качестве аргумента передаётся идентификатор сокета. И уже в этой задаче обрабатывается функция recv. Еще не пробовал, но, думаю, должно получиться.
  24. Доброго времени суток, уважаемые коллеги! Встала задача принимать пакеты из UART и передавать их в сеть. Запустил задачу-сервер на Socket API из примера ST, проверил, send - receive работает. Но когда дело дошло до реальной реализации, выяснилось, что функции accept и receive намертво блокируют задачу. Блокировку функцией accept решил вот такой нехитрой конструкцией: if (accept_state==0){ newconn = accept(sock, (struct sockaddr *)&remotehost, (socklen_t *)&size);//принимаем входящее подключение accept_state=1; } То есть, сервер принимает только одно входящее подключение. Общий вид главного цикла задачи-сервера: while (1) { if (accept_state==0){ newconn = accept(sock, (struct sockaddr *)&remotehost, (socklen_t *)&size);//принимаем входящее подключение accept_state=1; } event=osMessageGet(UART_RX_QHandle,10);//получаем указатель на структуру, которую нужно передать в сокет if (event.status==osEventMessage){ printf ("Queue received at %lu\r\n", osKernelSysTick()); pDataToSend=(UART_RX_Data*)event.value.v; HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin); send(newconn, pDataToSend->payload, pDataToSend->size, 0);//отправляем данные в сокет HAL_UART_Receive_IT(&huart3,uartRXBuffer,UART3RX_BUF_SIZE);//включаем приём в UART printf ("Switch context at %lu\r\n", osKernelSysTick()); osThreadYield(); } } в общем, циклично, по приходу пакета в UART, в задачу-сервер через очередь передается указатель на данные, которые нужно отправить в сокет. Вот теперь возникли два вопроса. Первый - как корректно завершить соединение по запросу от клиента? Попробовал сделать так: nbytes=recv(newconn, rxBuf, BUFLEN, MSG_PEEK); if (nbytes<=0){ close(newconn); } Сразу перестала работать очередь, потому что функция recv наглухо блокирует задачу. Что подскажете? И второй вопрос. Как отслеживать физический дисконнект? Может, кто уже решал эту задачу?