Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Lwip: netconn TCP app
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
k000858
В проекте используется LwIP + FreeRTOS. Поднят TCP сервер на Netconn API.
Необходимо данные из входящего соединения отправлять в последовательный порт, и в обратную сторону.
Проблема в том, что реализация TCP соединения подразумевает блокирующую функцию обработки принятых данных

Код
            while (netconn_recv(ntcnn232->newc, &buf) == ERR_OK)
            {


То есть пока не принял данные по TCP не могу отправить принятые данные по последовательному порту.

Как быть в этой ситуации?

Пока реализовано так: 2 задачи ОС:
1) сидит в блокирующей функции и отправляет принимаемые данные в последовательный порт
2) отправляет данные, принимаемые по последовательному порту, в TCP

Но это создает кучу проблем, например работа этих задач может "сломать" соединение.

Есть альтернативы как это можно реализовать?
kolobok0
Цитата(k000858 @ Oct 27 2017, 09:09) *
В проекте используется LwIP + FreeRTOS....То есть пока не принял данные по TCP не могу отправить принятые данные по последовательному порту. ...Есть альтернативы как это можно реализовать?


Насколько я понимаешь - LwIP реализован согласно соответствующих RFC, в том числе и со стороны юзанья.
Насколько помнишь - стандартный протокол должен обеспечивать как блокирующий так и не блокирующий режим работы.

это раз.
ну и второе - тот вариант что у Вас уже реализован(проглядел когда начинал писал)...
Не совсем понятен Ваш термин "сломать" соединение. Если в логике нет проблем, то ищите в коде..

как то так
(круглый)
DeNi
Можно включить в 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
А можно, и я свой вопросик втисну?
Первый раз пытаюсь использовать 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
Цитата
Как это можно сделать?

С уважением, Ефанов Сергей

А в чем проблема вызвать из другой задачи netconn_write? Функции netconn сделаны для работы в многозадачной среде.
Dmitrich
Цитата(DeNi @ Oct 28 2017, 14:08) *
А в чем проблема вызвать из другой задачи 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
Можно пройти отладчиком во внутрь функции и посмотреть где возникает ошибка и возвращается ERR_VAL.
kolobok0
ошибся. приношу извинения...
k000858
Цитата(kolobok0 @ Oct 27 2017, 20:07) *
Не совсем понятен Ваш термин "сломать" соединение
(круглый)

Если во время выполнения функции netconn_recv выполнится netconn_write в параллельной задаче, соединение ломается.
можно было мьютексом асинхронизировать доступ к соединению, но netconn_recv вызывается циклом while (netconn_recv() == ERR_OK), поэтому перед и после выполнения не получится зажать мьютекс
vadon
Цитата
Если во время выполнения функции 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
Цитата(DeNi @ Oct 28 2017, 13:07) *
И есть вариант вообще без надобности не блокировать задачу вызовом netconn_recv,
для этого при создании соединение использовать netconn_new_with_proto_and_callback и назначить callback,
в котором допустим взводить семафор. Сколько раз был вызван callback c NETCONN_EVT_RCVPLUS, столько раз
и надо вызвать netconn_recv. Посмотрите как в LWIP реализованы сокеты, там аналогично сделано.

Такой вариант бы хорошо подошел. можете привести пример кода, особенно интересует часть с закрытием соединения (мы сервер, подключен клиент, клиент закрывает соединение - в калбэке NETCONN_EVT_RCVPLUS 0 длинны) ??? у меня с этим какой то затык.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.