Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/21: Рейтинг темы: голосов - 21, средняя оценка - 4.71
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511

TCP сервер LWIP stm32f746

21.10.2020, 12:25. Показов 4844. Ответов 23

Студворк — интернет-сервис помощи студентам
Настроил TCP сервер на плате stm32f746 discovery при помощи FREERTOS и LWIP (использую CubeMX). Дальше измеряю скорость передачи данных от ПК к МК, использую передачу одного и того же массива данных в цикле определенное колличесво раз (сеть локальная, просто провод 10 м от МК к ПК).
А именно массив в 1 кбайт передаю 12800 раз (итого передается 100 МБит)
C
1
uint8_t TcpSendBuffer[1024];
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
            for (n = 0; n < 16; n++)
            {
            HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
                HAL_TIM_OC_Start_IT(&htim4, TIM_CHANNEL_4);
                for (i = 0; i < 800; i++)
                {
                    netconn_write(conn, TcpSendBuffer, 1024, NETCONN_COPY);
                }
                HAL_TIM_OC_Stop_IT(&htim4, TIM_CHANNEL_4);
                HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
                TcpTime = TcpTime + CountTime;
                CountTime = 0;
                osDelay(100);
            }
Разбил передачу на два цикла 16 и 800, чтобы добавить задержку в передаче 100 мсек, т.к. иначе терминальная программа подтормаживала.
Дальше замеряю таймером время передачи всех этих данных в преывании увеличивая счетчик
C
1
2
3
4
5
6
7
8
9
10
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM4)
    {
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
        {
            CountTime++;
        }
    }
}
Таймер настроен на срабатывание раз в 1 мсек.
В среднем время, за которое передается все 100 Мбит данных равняется 55 сек, что уже достаточно много, так как PHY позволяет работу на 100 Мбит/сек, а тут получается около 3-4 Мбит/сек.
Но еще есть такой момент: из кода выше видно, что массив передается 16 раз по 800 раз (итого 12800 раз), если замерять логическим анализатором время передачи каждой порции из 800 массивов, то они будут существенно различаться. Т.е. эти 800 массивов могут передаться за 1.5 секунды, следующие 800 уже за 5 секунд и тд. Помимо передачи по TCP программа почти ничего не выполняет, мигает светодиодом раз в секунду в отдельной задаче. Почему наблюдается такое сильное различие ов времени передачи при абсолютно одинаковых условиях работы кода? От каких настроек зависит скорость работы LWIP?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.10.2020, 12:25
Ответы с готовыми решениями:

LWIP TCP сервер ошибки соединения
Уже довольно долго не могу найти причину ошибок соединения TCP сервера с клиентом. Сервер - stm32f746. Клиент - ПК. PHY - LAN8742a ...

Передача данных по Ethernet TCP LWIP
На плате stm32f746 discovery реализован TCP эхо сервер, хочу переделать его под передачу данных с АЦП. Код реализации соединения сокета: ...

LWIP TCP RAW API server
Решил настроить на stm32f746 discovery LWIP TCP RAW сервер, но никак не могу это реализовать. Есть настроенный TCP netconn на FreeRTOS, но...

23
76 / 52 / 26
Регистрация: 23.01.2019
Сообщений: 134
21.10.2020, 20:28
Привет.
Сравнивать физическую возможную скорость интерфейса и реальную скорость передачи данных конкретным приложением не совсем корректно. Вы не учитываете наличие служебных байтов и пакетов протоколов IP и TCP. К тому же TCP - это протокол с подтверждением, то есть, после передачи пакета, ожидается подтверждение его получения с другой стороны. Более того, если подтверждения не приходят, пакеты могут отправляться повторно.
Вы пишете, что у вас подтормаживет терминал. Возможно узкое место в принимающей стороне.
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
21.10.2020, 22:23
Почитав объяснение функции:
- Вы заставляете функцию копировать данные себе куда-то в свой буфер. Может отнимать время у менеджера памяти, помимо самого копирования.
- Вы вызываете функцию без контроля возвращаемого значения. То есть попросту половина месседжей может быть утеряна, но самое главное - вы останавливаете на время вызова поток отправки данных, ну, или хотя бы мешаете ему работать.

PS: все это теоретические рассуждения.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
22.10.2020, 08:10  [ТС]
yatrim,
Цитата Сообщение от yatrim Посмотреть сообщение
Вы не учитываете наличие служебных байтов и пакетов протоколов IP и TCP.
Тут я с Вами согласен, не стал учитывать заголовки и тд, но там служебных данных на 30 байт
https://studfile.net/preview/5... %BE%D0%B2.
Я думаю это не существено сказывается на скорости по сравнению с размером передеваемых данных в 1 Кбайт
Со служебными протоколами уже посложнее, на каждый отправленый пакет мы получаем пакет с подтверждением, тут уже на скорости значительнее может сказаться, но опять же, я получил скорость 3-4 МБит/сек, а хотелось бы 40-50. Можно же как-то получить такие значения, вопрос только на что обратить внимание.
Цитата Сообщение от yatrim Посмотреть сообщение
Более того, если подтверждения не приходят, пакеты могут отправляться повторно
Ну тут сеть локальная, напрямую к ПК, там если смотреть при помощи Wireshark, то в целом все нормально, все зеленым, изредка проскакивают какие-то ошибки.
Цитата Сообщение от yatrim Посмотреть сообщение
Вы пишете, что у вас подтормаживет терминал. Возможно узкое место в принимающей стороне.
Я не совсем правильно написал, там по-моему whireshark зависал, если сразу все 12800 пакетов слать, терминал вроде нормально работал. Терминал использую PuTTY
Voland_,
Цитата Сообщение от Voland_ Посмотреть сообщение
Вы заставляете функцию копировать данные себе куда-то в свой буфер
Если Вы про NETCONN_COPY, то я думал, что это копирование данных на тот случай, если вдруг пакет будет утерян, чтобы можно было осуществить его повторную отправку. На самом деле не обращал особого внимания на этот параметр функции, во всех примерах, которые находил, делали так. Может ошибаюсь на счет назначения данного параметра.
Цитата Сообщение от Voland_ Посмотреть сообщение
Вы вызываете функцию без контроля возвращаемого значения.
Можете здесь поподробнее, не совсем понял о каком возвращаемом значении идет речь?
Цитата Сообщение от Voland_ Посмотреть сообщение
но самое главное - вы останавливаете на время вызова поток отправки данных, ну, или хотя бы мешаете ему работать
Это Вы про прерывание от таймера или про задержку в 10 мсек?
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
22.10.2020, 10:44
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Можете здесь поподробнее, не совсем понял о каком возвращаемом значении идет речь?
[попробую объяснить свою мысль. Исходник lwip взят первый попавшийся, для примера]:
Функция netconn_write() - по-сути обрезанная netconn_write_partly():
https://github.com/m-labs/lwip... #L277-L280

У которой возвращаемое значение имеет следующие возможные состояния:
https://github.com/m-labs/lwip... .h#L50-L73
которые вы никак не контролируете в момент отправки. Попробуйте поиграться с флагом "NETCONN_FLAG_NON_BLOCKING":
https://github.com/m-labs/lwip... #L302-L305 , т.к. он напрямую влияет на выполнение функции внутри цикла. Возможно, в неблокирующем режиме скорость будет выше (тогда нужно использовать netconn_write_partly()).

Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Это Вы про прерывание от таймера или про задержку в 10 мсек?
пока не знаю. Я подумал, что каждый вызов `netconn_write()` отнимает часть времени от процесса, который занимается обработкой очереди сообщений. Возможно, это не так.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
22.10.2020, 12:56  [ТС]
Voland_,
Цитата Сообщение от Voland_ Посмотреть сообщение
Попробуйте поиграться с флагом "NETCONN_FLAG_NON_BLOCKING":
Вы имеете ввиду NETCONN_DONTBLOCK?
Т.к. именно этот параметр приводится к функции netconn_write_partly()
http://www.nongnu.org/lwip/2_0... 83f7c423bf
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
22.10.2020, 13:34
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Вы имеете ввиду NETCONN_DONTBLOCK?
не совсем, но, возможно, этот флаг влияет на какие-то флаги внутри библиотеки. я исхожу из изучения исходников lwIP, чего бы и Вам посоветовал бы. Не боги горшки обжигают - возможно, библиотека написана не так как бы вам хотелось ). Тогда используйте low-level функции, и напишите свое решение.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
22.10.2020, 13:51  [ТС]
Voland_, Я думаю, я пока еще не так хорошо разобрался в LWIP, чтобы написать свое решение, но понемного изучаю как там все устроено. С NETCONN_COPY и NETCONN_NOCOPY() вроде разобрался. NETCONN_COPY используется в случае если отправляемые данные могут быть изменены в ходе отправки, поэтому они предварительно копируются. NETCONN_NOCOPY используется, если отправляем неизменные данные.
NETCONN_MORE так понимаю если данные могут быть разбиты. И NETCONN_DONTBLOCK если данные должны быть отрпавлены одним пакетом.
Еще у меня возник вопрос относительно функций netconn_write(conn, dataptr, size, apiflags) и netconn_write_partly(conn, dataptr, size, apiflags, bytes_written)
В чем их различие, почему netconn_write используется чаще?
И к парметру bytes_written отдельные вопросы:
bytes_written pointer to a location that receives the number of written bytes
Указатель на место, которое получает количество отправленных байтов?
Т.е. сюда мы должны записать переменную, в которую будет записываться сколько байт отправилось функцией netconn_write_partly?
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
22.10.2020, 18:15
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Т.е. сюда мы должны записать переменную, в которую будет записываться сколько байт отправилось функцией netconn_write_partly?
похоже. Размещаете указатель на переменную, и функция вернет сколько было отправлено байт. Но в исходниках я встречал объяснение, что этот параметр актуален для не-блокирующего режима. И это очень важно - какой режим передполагается в связке с FreeRTOS
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
23.10.2020, 06:55  [ТС]
Voland_, Если я правильно понял, то в функцию netconn_write и netconn_write_partly (я так и не понял их различие) мы можем поместить массив размера больше 1,5 КБ, т.е. больше максимального размера кадра для TCP, например 100 МБайт, и функция отправки уже будет заниматься фрагментацией на кадры и т.д. Однако если мы укажем параметром NETCONN_DONTBLOCK, то отправлять можно данные только размером меньше 1,5 КБ.
Опять же я не понимаю разницы между netconn_write и netconn_write_partly, что первое может фрагментировать пакет что второе

Добавлено через 1 минуту
Voland_,
Цитата Сообщение от Voland_ Посмотреть сообщение
Размещаете указатель на переменную, и функция вернет сколько было отправлено байт
Опять же зачем мне знать сколько отправлено байт, если мне надо чтобы был отправлен весь массив, а тем сколько уже отправлено, а сколько осталось отправить должен заниматься LWIP. Но я подозреваю, что в функции netconn_write и организовано что-то подобное, где осуществляется проверка сколько отправилось, а сколько оставлось отправить
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,870
23.10.2020, 09:00

Не по теме:

Voland_, верни аву, а то "я не узнаю вас в гриме"


0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
23.10.2020, 09:19
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
разницы между netconn_write и netconn_write_partly
загляните в исходники, и все станет ясно . Я ж Вам дал ссылки на места где функции написаны?
Функция netconn_write() вызывает netconn_write_partly() с параметром получения оставшихся байт = NULL. Это значит, что netconn_write() является частным случаем, с учетом определенного режима, скорее всего дефолтного, в котором этот параметр всегда возвращает 0 (при отсутствии проблем) - по крайней мере в BLOCKING-режиме так должно быть, исходя из назначения.
Цитата Сообщение от ValeryS Посмотреть сообщение
я не узнаю

Не по теме:

Дети подрастают :). Меняются игры...

0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
23.10.2020, 12:29  [ТС]
Voland_,
Цитата Сообщение от Voland_ Посмотреть сообщение
Я ж Вам дал ссылки на места где функции написаны?
Да, спасибо зассылки, я их посмотрел, уже и все настройки LWIP перебрал, почитал что там и для чего, указал все значения буферов и т.д. с запасом, но все равно измеряю скорость передачи 100 Мбит, получаю 3 Мбита/сек
0
Эксперт по электронике
6785 / 3212 / 335
Регистрация: 28.10.2011
Сообщений: 12,545
Записей в блоге: 7
23.10.2020, 13:19
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
получаю 3 Мбита/сек
Вы уверены что у МК хватит производительности на большую скорость?
Запретите все прерывания и передавайте в цикле, а еще лучше через DMA остановив ядро переведя в режим Sleep.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
23.10.2020, 13:55  [ТС]
locm,
Цитата Сообщение от locm Посмотреть сообщение
Вы уверены что у МК хватит производительности на большую скорость?
Ну у меня stm32f746 на 200 МГц
Цитата Сообщение от locm Посмотреть сообщение
Запретите все прерывания и передавайте в цикле
Там из прерываний только таймер раз в миллисекунду срабатывает, увеличивая счетчик
Цитата Сообщение от locm Посмотреть сообщение
а еще лучше через DMA
А как тут DMA использовать, только если из памяти в память?

Добавлено через 22 минуты
locm, Voland_, приведу еще код, но он практически такой же как и во всех примерах
Настройка LWIP
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
  ******************************************************************************
  * File Name          : Target/lwipopts.h
  * Description        : This file overrides LwIP stack default configuration
  *                      done in opt.h file.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
 
/* Define to prevent recursive inclusion --------------------------------------*/
#ifndef __LWIPOPTS__H__
#define __LWIPOPTS__H__
 
#include "main.h"
 
/*-----------------------------------------------------------------------------*/
/* Current version of LwIP supported by CubeMx: 2.1.2 -*/
/*-----------------------------------------------------------------------------*/
 
/* Within 'USER CODE' section, code will be kept by default at each generation */
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
#ifdef __cplusplus
 extern "C" {
#endif
 
/* STM32CubeMX Specific Parameters (not defined in opt.h) ---------------------*/
/* Parameters set in STM32CubeMX LwIP Configuration GUI -*/
/*----- WITH_RTOS enabled (Since FREERTOS is set) -----*/
#define WITH_RTOS 1
/*----- CHECKSUM_BY_HARDWARE enabled -----*/
#define CHECKSUM_BY_HARDWARE 1
/*-----------------------------------------------------------------------------*/
 
/* LwIP Stack Parameters (modified compared to initialization value in opt.h) -*/
/* Parameters set in STM32CubeMX LwIP Configuration GUI -*/
/*----- Default Value for MEMP_NUM_UDP_PCB: 4 ---*/
#define MEMP_NUM_UDP_PCB 5
/*----- Default Value for MEMP_NUM_TCP_PCB: 5 ---*/
#define MEMP_NUM_TCP_PCB 10
/*----- Value in opt.h for MEM_ALIGNMENT: 1 -----*/
#define MEM_ALIGNMENT 4
/*----- Default Value for MEM_SIZE: 1600 ---*/
#define MEM_SIZE 2048
/*----- Default Value for MEMP_NUM_PBUF: 16 ---*/
#define MEMP_NUM_PBUF 24
/*----- Default Value for MEMP_NUM_TCP_SEG: 16 ---*/
#define MEMP_NUM_TCP_SEG 24
/*----- Default Value for PBUF_POOL_BUFSIZE: 592 ---*/
#define PBUF_POOL_BUFSIZE 1536
/*----- Value in opt.h for LWIP_ETHERNET: LWIP_ARP || PPPOE_SUPPORT -*/
#define LWIP_ETHERNET 1
/*----- Value in opt.h for LWIP_DNS_SECURE: (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) -*/
#define LWIP_DNS_SECURE 7
/*----- Default Value for TCP_MSS: 536 ---*/
#define TCP_MSS 1024
/*----- Value in opt.h for TCP_SND_QUEUELEN: (4*TCP_SND_BUF + (TCP_MSS - 1))/TCP_MSS -----*/
#define TCP_SND_QUEUELEN 9
/*----- Value in opt.h for TCP_SNDQUEUELOWAT: LWIP_MAX(TCP_SND_QUEUELEN)/2, 5) -*/
#define TCP_SNDQUEUELOWAT 5
/*----- Value in opt.h for LWIP_NETIF_LINK_CALLBACK: 0 -----*/
#define LWIP_NETIF_LINK_CALLBACK 1
/*----- Value in opt.h for TCPIP_THREAD_STACKSIZE: 0 -----*/
#define TCPIP_THREAD_STACKSIZE 2048
/*----- Value in opt.h for TCPIP_THREAD_PRIO: 1 -----*/
#define TCPIP_THREAD_PRIO osPriorityNormal
/*----- Value in opt.h for TCPIP_MBOX_SIZE: 0 -----*/
#define TCPIP_MBOX_SIZE 8
/*----- Value in opt.h for SLIPIF_THREAD_STACKSIZE: 0 -----*/
#define SLIPIF_THREAD_STACKSIZE 1024
/*----- Value in opt.h for SLIPIF_THREAD_PRIO: 1 -----*/
#define SLIPIF_THREAD_PRIO 3
/*----- Value in opt.h for DEFAULT_THREAD_STACKSIZE: 0 -----*/
#define DEFAULT_THREAD_STACKSIZE 2048
/*----- Value in opt.h for DEFAULT_THREAD_PRIO: 1 -----*/
#define DEFAULT_THREAD_PRIO 3
/*----- Value in opt.h for DEFAULT_UDP_RECVMBOX_SIZE: 0 -----*/
#define DEFAULT_UDP_RECVMBOX_SIZE 6
/*----- Value in opt.h for DEFAULT_TCP_RECVMBOX_SIZE: 0 -----*/
#define DEFAULT_TCP_RECVMBOX_SIZE 8
/*----- Value in opt.h for DEFAULT_ACCEPTMBOX_SIZE: 0 -----*/
#define DEFAULT_ACCEPTMBOX_SIZE 8
/*----- Value in opt.h for RECV_BUFSIZE_DEFAULT: INT_MAX -----*/
#define RECV_BUFSIZE_DEFAULT 2000000000
/*----- Value in opt.h for LWIP_STATS: 1 -----*/
#define LWIP_STATS 0
/*----- Value in opt.h for CHECKSUM_GEN_IP: 1 -----*/
#define CHECKSUM_GEN_IP 0
/*----- Value in opt.h for CHECKSUM_GEN_UDP: 1 -----*/
#define CHECKSUM_GEN_UDP 0
/*----- Value in opt.h for CHECKSUM_GEN_TCP: 1 -----*/
#define CHECKSUM_GEN_TCP 0
/*----- Value in opt.h for CHECKSUM_GEN_ICMP: 1 -----*/
#define CHECKSUM_GEN_ICMP 0
/*----- Value in opt.h for CHECKSUM_GEN_ICMP6: 1 -----*/
#define CHECKSUM_GEN_ICMP6 0
/*----- Value in opt.h for CHECKSUM_CHECK_IP: 1 -----*/
#define CHECKSUM_CHECK_IP 0
/*----- Value in opt.h for CHECKSUM_CHECK_UDP: 1 -----*/
#define CHECKSUM_CHECK_UDP 0
/*----- Value in opt.h for CHECKSUM_CHECK_TCP: 1 -----*/
#define CHECKSUM_CHECK_TCP 0
/*----- Value in opt.h for CHECKSUM_CHECK_ICMP: 1 -----*/
#define CHECKSUM_CHECK_ICMP 0
/*----- Value in opt.h for CHECKSUM_CHECK_ICMP6: 1 -----*/
#define CHECKSUM_CHECK_ICMP6 0
/*-----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
 
/* USER CODE END 1 */
 
#ifdef __cplusplus
}
#endif
#endif /*__LWIPOPTS__H__ */
 
/************************* (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


Создание соединения
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
void StartDefaultTask(void const * argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN 5 */
  //-----------------------------------------------------------
    int i = 0;
    struct netconn *conn;
    struct netconn *newconn;
    err_t err;
    conn = netconn_new(NETCONN_TCP);
    if(conn!=NULL)
    {
      err = netconn_bind(conn, NULL, 80);   // Binding the socket struck for sending data and TCP struck
      if (err == ERR_OK)
      {
        netconn_listen(conn);
        if (err != ERR_OK)
        {
            HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_6);
        }
        /* Infinite loop */
        for(;;)
        {
          if (netconn_accept(conn, &newconn) == ERR_OK)
          {
                // client connected
                HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_SET);
                sock.conn = newconn;
                sys_thread_new("tcp_thread", tcp_thread, (void*)&sock, DEFAULT_THREAD_STACKSIZE, osPriorityNormal );
                sys_thread_new("tcp_thread_send", tcp_thread_send, (void*)&sock, DEFAULT_THREAD_STACKSIZE, osPriorityNormal );
                TcpCreate++;
          }
          else if (err != ERR_OK)
          {
              HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_6);
          }
        }
      }
      else
      {
          HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_6);
          netconn_delete(conn);
      }
    }
    else if (conn == NULL)
    {
        HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_6);
    }
  //-----------------------------------------------------------
  /* USER CODE END 5 */
}


Поток приема
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
static void tcp_thread(void *arg)
{
    err_t err, recv_err;                 // Variables for arguments (errors)
    struct netconn *conn;                // Structure for connection
    struct netbuf *inbuf;                // Pointer to connection buffer
    struct_sock *arg_sock;               // Pointer to arguments of task
    struct_handler *qstructhandler;      // Handler Queue
    arg_sock = (struct_sock*) arg;
    conn = arg_sock->conn;
    u16_t buflen;
    char* buf;
    for(;;)
    {
       netconn_write(conn, "READY", 5, NETCONN_COPY);                // Sending "READY"
       for(;;)
       {
          recv_err = netconn_recv(conn, &inbuf);                     // Receiving the socket data in inbuf
          if (recv_err == ERR_OK)
          {
            netbuf_data(inbuf, (void**)&buf, &buflen);               // Data transfer of the inbuf data to buf
            if((buf[0]==0x0D)||(buf[0]==0x0A))                       // Checking of the data ending
            {
              netbuf_delete(inbuf);
              continue;
            }
            qstructhandler = osMailAlloc(handler_Queue, osWaitForever);      // Handler Queue
            strncpy(str_buf,buf,buflen);
            str_buf[buflen]=0;
            sprintf(qstructhandler->handler_str,"%-20s", str_buf);           // Handler Queue
            osMailPut(handler_Queue, qstructhandler);                        // Handler Queue
            netbuf_delete(inbuf);
          }
          else
          {
              if (TcpCreate > TcpDelete)
              {
                  netbuf_delete(inbuf);
                  netconn_close(conn);
                  netconn_delete(conn);
                  TcpDelete++;
                  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
                  break;
              }
              else
              {
                  osDelay(1000);
              }
          }
       }
    }
}


Поток отправки
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
static void tcp_thread_send(void *arg)
{
    struct netconn *conn;                // Structure for connection
    struct_sock *arg_sock;               // Pointer to arguments of task
    arg_sock = (struct_sock*) arg;
    conn = arg_sock->conn;
    uint8_t TcpSendBuffer[1024];
    uint16_t i = 0;
    uint16_t j = 0;
    uint16_t n = 0;
    for (j = 0; j < 1024; j++)
    {
        TcpSendBuffer[j] = 5;
    }
    for(;;)
    {
        if (xSemaphoreTake(binary_semaphore_SEND, portMAX_DELAY) == pdTRUE)
        {
            //for (n = 0; n < 16; n++)
            //{
                HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
                //HAL_TIM_OC_Start_IT(&htim4, TIM_CHANNEL_4);
                for (i = 0; i < 12800; i++)
                {
                    //netconn_write(conn, TcpSendBuffer, 1024, NETCONN_COPY);
                    netconn_write(conn, TcpSendBuffer, 1024, NETCONN_NOCOPY);
                }
                //HAL_TIM_OC_Stop_IT(&htim4, TIM_CHANNEL_4);
                HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
                osDelay(100);
            //}
            xSemaphoreGive(binary_semaphore_DONE);
        }
        else
        {
            osDelay(1000);
        }
    }
}


Еще есть задача, в которую передается все, что принимается по TCP
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void StartHandlerTask(void const * argument)
{
  /* USER CODE BEGIN StartHandlerTask */
  //-----------------------------------------------------------
  osEvent handlerevent;                                                    // Handler Queue
  struct_handler *qstructhandler;                                          // Handler Queue
  /* Infinite loop */
  for(;;)
  {
      handlerevent = osMailGet(handler_Queue, osWaitForever);              // Handler Queue
      if (handlerevent.status == osEventMail)
      {
          qstructhandler = handlerevent.value.p;
          DataSignal = str_buf[0] - '0';
          if (DataSignal == 1)
          {
              xSemaphoreGive(binary_semaphore_SEND);
          }
          else
          {
              osDelay(1000);
          }
          osMailFree(handler_Queue, handlerevent.value.p);                   // Handler Queue
      }
      else
      {
          osDelay(1000);
      }
  }
  //-----------------------------------------------------------
  /* USER CODE END StartHandlerTask */
}
0
Эксперт по электронике
6785 / 3212 / 335
Регистрация: 28.10.2011
Сообщений: 12,545
Записей в блоге: 7
23.10.2020, 15:55
У вас еще и ОС. Все это требует процессорного времени. То что частота 200 МГц ни о чем не говорит. Не оптимальный код может свести на нет все мегагерцы.
Напишите код как можно проще без ОС и прерываний. В цикле функции main передавайте данные и смотрите какая будет скорость. Выберите оптимизацию по скорости и включите LTO.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
23.10.2020, 16:06  [ТС]
locm,
Цитата Сообщение от locm Посмотреть сообщение
У вас еще и ОС
Да, использую netconn, поэтому все это на ОС, да и много где рекомендуют с LWIP использовать ОС.
Хорошо, спасибо за совет, перепишу на RAW.
Цитата Сообщение от locm Посмотреть сообщение
Выберите оптимизацию по скорости и включите LTO
Не совсем понял что это означает
0
Эксперт по электронике
6785 / 3212 / 335
Регистрация: 28.10.2011
Сообщений: 12,545
Записей в блоге: 7
23.10.2020, 17:43
Ни разу не меняли уровень оптимизации компилятора? Вероятно оптимизация отключена. Тогда неудивительно что работает медленно.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
23.10.2020, 20:10  [ТС]
locm,
Цитата Сообщение от locm Посмотреть сообщение
Ни разу не меняли уровень оптимизации компилятора?
Нет, я раньше использовал Keil 5, там только отладкой пользовался. Сейчас использую STM32Cube IDE, с отладкой так толком пока не разобрался, а оптимизацию ставлю O1 (setings -> Optimization -> Optimization level -> Optimize O1). В этом проекте, кстати забыл изменить оптимизацию, она было O0.
Можете подсказать, как выбрать оптимизацию по скорости и почему она будет влиять на скорость передачи TCP?
0
Эксперт по электронике
6785 / 3212 / 335
Регистрация: 28.10.2011
Сообщений: 12,545
Записей в блоге: 7
23.10.2020, 21:08
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Можете подсказать, как выбрать оптимизацию по скорости
STM32CubeIDE не пользуюсь.
Нужно собрать с параметрами компиляции -Ofast и -flto. Ищите что-то похожее в CubeIDE.

Цитата Сообщение от DmitryDDDD Посмотреть сообщение
почему она будет влиять на скорость передачи TCP?
Это будет влиять на скорость выполнения кода. Чтобы достичь скорости передачи 100 МБит/с нужно чтобы при частоте 200 МГц отправка каждого байта требовала не больше 16 тактов (это с учетом всего фонового кода типа прерываний, ОС и т. д.). Если требуется больше тактов, скорость будет снижаться, что наблюдается в вашем случае.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.10.2020, 21:08
Помогаю со студенческими работами здесь

Можно ли на netconn api LwIP сделать сервер с несколькими подключениями на один порт
Добрый вечер, целый день сегодня потратил в поисках решения такой задачи На один порт может конектится несколько клиентов, которые...

TCP сервер stm32
Здравствуйте, пытаюсь организовать TCP сервер на stm32, уже перечитал кучу информации, поискал примеры, но ничего подходящего пока не...

Stm32f746-disco b-02 и b-04
Есть несколько плат stm32f746-disco board b-02 , работают отлично, Получаю board b-04, и получаю тупеж платы -04 раз так в сто! на том же...

STM32F746, sim800l, воспроизведение аудио
День добрый. Нужно сделать голосове меню. Для начала хочу опробовать на отладочном комплекте STM32F746Dyscovery + GSM модуль SIM800....

STM32F746 LCD лишние точки
Доброго всем здравия. Изготовил плату для собственного проекта по аналогии с отладочным комплектом STM32F746Dyscovery. LCD и SDROM...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru