k000858 0 27 октября, 2017 Опубликовано 27 октября, 2017 · Жалоба В проекте используется LwIP + FreeRTOS. Поднят TCP сервер на Netconn API. Необходимо данные из входящего соединения отправлять в последовательный порт, и в обратную сторону. Проблема в том, что реализация TCP соединения подразумевает блокирующую функцию обработки принятых данных while (netconn_recv(ntcnn232->newc, &buf) == ERR_OK) { То есть пока не принял данные по TCP не могу отправить принятые данные по последовательному порту. Как быть в этой ситуации? Пока реализовано так: 2 задачи ОС: 1) сидит в блокирующей функции и отправляет принимаемые данные в последовательный порт 2) отправляет данные, принимаемые по последовательному порту, в TCP Но это создает кучу проблем, например работа этих задач может "сломать" соединение. Есть альтернативы как это можно реализовать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kolobok0 0 27 октября, 2017 Опубликовано 27 октября, 2017 (изменено) · Жалоба В проекте используется LwIP + FreeRTOS....То есть пока не принял данные по TCP не могу отправить принятые данные по последовательному порту. ...Есть альтернативы как это можно реализовать? Насколько я понимаешь - LwIP реализован согласно соответствующих RFC, в том числе и со стороны юзанья. Насколько помнишь - стандартный протокол должен обеспечивать как блокирующий так и не блокирующий режим работы. это раз. ну и второе - тот вариант что у Вас уже реализован(проглядел когда начинал писал)... Не совсем понятен Ваш термин "сломать" соединение. Если в логике нет проблем, то ищите в коде.. как то так (круглый) Изменено 27 октября, 2017 пользователем kolobok0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
deni 6 28 октября, 2017 Опубликовано 28 октября, 2017 · Жалоба Можно включить в LWIP таймауты, тогда из функции netconn_recv будет выходить через указанное время, даже если ничего не принято. #define LWIP_SO_RCVTIMEO 1 // accept, receive #define LWIP_SO_SNDTIMEO 1 // send Если надо прервать ожидание netconn_recv из другой задачи, во FreeRTOS можно включить опцию #define INCLUDE_xTaskAbortDelay 1 и вызовом xTaskAbortDelay(hTask) разблокировать задачу. И насколько помню в lwip/port/sys_arch.c ожидание из очереди без таймаута там зачем-то обернуто в цикл, хотя документация на FreeRTOS говорить что вызов xQueueReceive с portMAX_DELAY бесконечный. Так что если не убрать цикл, задача опять заблокируется. И есть вариант вообще без надобности не блокировать задачу вызовом netconn_recv, для этого при создании соединение использовать netconn_new_with_proto_and_callback и назначить callback, в котором допустим взводить семафор. Сколько раз был вызван callback c NETCONN_EVT_RCVPLUS, столько раз и надо вызвать netconn_recv. Посмотрите как в LWIP реализованы сокеты, там аналогично сделано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dmitrich 0 28 октября, 2017 Опубликовано 28 октября, 2017 · Жалоба А можно, и я свой вопросик втисну? Первый раз пытаюсь использовать Lwip, вот какую проблемку пытаюсь решить: Попробовал пример с эхо - всё хорошо работает: while (1) { accept_err = netconn_accept(conn, &newconn); if (accept_err == ERR_OK) { while ((netconn_recv(newconn, &buf)) == ERR_OK) { do { netbuf_data(buf, &data, &len); netconn_write(newconn, data, len, NETCONN_COPY); } while (netbuf_next(buf) >= 0); netbuf_delete(buf); } netconn_close(newconn); netconn_delete(newconn); } } ( этот цикл крутится в отдельной задаче FreeRTOS) Теперь мне нужно отправить пакет через стек в в произвольный момент времени, то есть - в то время, когда выполняется netconn_recv. Как это можно сделать? С уважением, Ефанов Сергей Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
deni 6 28 октября, 2017 Опубликовано 28 октября, 2017 · Жалоба Как это можно сделать? С уважением, Ефанов Сергей А в чем проблема вызвать из другой задачи netconn_write? Функции netconn сделаны для работы в многозадачной среде. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dmitrich 0 28 октября, 2017 Опубликовано 28 октября, 2017 · Жалоба А в чем проблема вызвать из другой задачи netconn_write? Функции netconn сделаны для работы в многозадачной среде. Не знаю ( ума не хватает). Я пытался. Неизменно получаю ошибку. Делал вот так: void transfer_ip( char *rep, uint16_t len ) { err = netconn_write(newconn, (const unsigned char*)rep, len, NETCONN_COPY); if( err == ERR_OK ) { printf("\rSend OK %d \r",len); } else { printf("\rSend BAD:%d\r", (int)err ); } } Ошибку всегда возвращает -6 (ERR_VAL). Очевидно, я неправильно это делаю. С уважением, Ефанов Сергей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
deni 6 28 октября, 2017 Опубликовано 28 октября, 2017 · Жалоба Можно пройти отладчиком во внутрь функции и посмотреть где возникает ошибка и возвращается ERR_VAL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kolobok0 0 29 октября, 2017 Опубликовано 29 октября, 2017 (изменено) · Жалоба ошибся. приношу извинения... Изменено 29 октября, 2017 пользователем kolobok0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k000858 0 31 октября, 2017 Опубликовано 31 октября, 2017 · Жалоба Не совсем понятен Ваш термин "сломать" соединение (круглый) Если во время выполнения функции netconn_recv выполнится netconn_write в параллельной задаче, соединение ломается. можно было мьютексом асинхронизировать доступ к соединению, но netconn_recv вызывается циклом while (netconn_recv() == ERR_OK), поэтому перед и после выполнения не получится зажать мьютекс Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadon 0 31 октября, 2017 Опубликовано 31 октября, 2017 · Жалоба Если во время выполнения функции netconn_recv выполнится netconn_write в параллельной задаче, соединение ломается. Все должно работать, у меня работает, что то у вас или настроено не так или что не то с файлом sys_arch.c. Если надо прервать ожидание netconn_recv из другой задачи, во FreeRTOS можно включить опцию #define INCLUDE_xTaskAbortDelay 1 и вызовом xTaskAbortDelay(hTask) разблокировать задачу. Это самый глупый совет никогда так не делайте !!!!, в лучшем случае получите утечку памяти, так как ресурсы занятые стеком никто не освободит, в худшем вылет или зависание стека. Если нужно не зависать в netconn_recv: Настроить и включить для соединения TCP_KEEEP_ALIVE это основное. Далее в зависимости от преследуемых целей можно использовать 2 варианта. 1) Установить таймаут на прием и соответсвенно его обрабатывать. 2) Если нужно выйти по команде с другой задачи нужно воспользоваться функцией netconn_shutdown, с параметром закрытия RX, после этой команды цикл netconn_recv прервется с ошибкой ERR_CLS, но соединение по прежнему будет активно только на передачу, этой же командой можно прервать и передачу, если этой функции поставить rx = 1 и tx = 1 она закроет соединение как команда netconn_close. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k000858 0 9 ноября, 2017 Опубликовано 9 ноября, 2017 · Жалоба И есть вариант вообще без надобности не блокировать задачу вызовом netconn_recv, для этого при создании соединение использовать netconn_new_with_proto_and_callback и назначить callback, в котором допустим взводить семафор. Сколько раз был вызван callback c NETCONN_EVT_RCVPLUS, столько раз и надо вызвать netconn_recv. Посмотрите как в LWIP реализованы сокеты, там аналогично сделано. Такой вариант бы хорошо подошел. можете привести пример кода, особенно интересует часть с закрытием соединения (мы сервер, подключен клиент, клиент закрывает соединение - в калбэке NETCONN_EVT_RCVPLUS 0 длинны) ??? у меня с этим какой то затык. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться