Перейти к содержанию
    

Lwip: netconn TCP app

В проекте используется LwIP + FreeRTOS. Поднят TCP сервер на Netconn API.

Необходимо данные из входящего соединения отправлять в последовательный порт, и в обратную сторону.

Проблема в том, что реализация TCP соединения подразумевает блокирующую функцию обработки принятых данных

 

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

 

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

 

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

 

Пока реализовано так: 2 задачи ОС:

1) сидит в блокирующей функции и отправляет принимаемые данные в последовательный порт

2) отправляет данные, принимаемые по последовательному порту, в TCP

 

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

 

Есть альтернативы как это можно реализовать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В проекте используется LwIP + FreeRTOS....То есть пока не принял данные по TCP не могу отправить принятые данные по последовательному порту. ...Есть альтернативы как это можно реализовать?

 

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

Насколько помнишь - стандартный протокол должен обеспечивать как блокирующий так и не блокирующий режим работы.

 

это раз.

ну и второе - тот вариант что у Вас уже реализован(проглядел когда начинал писал)...

Не совсем понятен Ваш термин "сломать" соединение. Если в логике нет проблем, то ищите в коде..

 

как то так

(круглый)

Изменено пользователем kolobok0

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно включить в 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 реализованы сокеты, там аналогично сделано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можно, и я свой вопросик втисну?

Первый раз пытаюсь использовать 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.

 

Как это можно сделать?

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как это можно сделать?

 

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

А в чем проблема вызвать из другой задачи netconn_write? Функции netconn сделаны для работы в многозадачной среде.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А в чем проблема вызвать из другой задачи 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).

Очевидно, я неправильно это делаю.

 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно пройти отладчиком во внутрь функции и посмотреть где возникает ошибка и возвращается ERR_VAL.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ошибся. приношу извинения...

Изменено пользователем kolobok0

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не совсем понятен Ваш термин "сломать" соединение

(круглый)

Если во время выполнения функции netconn_recv выполнится netconn_write в параллельной задаче, соединение ломается.

можно было мьютексом асинхронизировать доступ к соединению, но netconn_recv вызывается циклом while (netconn_recv() == ERR_OK), поэтому перед и после выполнения не получится зажать мьютекс

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если во время выполнения функции 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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И есть вариант вообще без надобности не блокировать задачу вызовом netconn_recv,

для этого при создании соединение использовать netconn_new_with_proto_and_callback и назначить callback,

в котором допустим взводить семафор. Сколько раз был вызван callback c NETCONN_EVT_RCVPLUS, столько раз

и надо вызвать netconn_recv. Посмотрите как в LWIP реализованы сокеты, там аналогично сделано.

Такой вариант бы хорошо подошел. можете привести пример кода, особенно интересует часть с закрытием соединения (мы сервер, подключен клиент, клиент закрывает соединение - в калбэке NETCONN_EVT_RCVPLUS 0 длинны) ??? у меня с этим какой то затык.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...