реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> STM32F4x9 + LAN8720A + lwIP 2.0.2, утечка памяти PBUF
Hold
сообщение Sep 4 2017, 06:36
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 27-01-17
Пользователь №: 95 184



В топик приглашаются спецы по lwIP.
В процессе написания своего FTP сервера, возникла проблема с приемом данных. Виртуальный диск развернут в SDRAM, прикручен FatFs_R0.13, тут проблем нет. Чтение с FTP также никаких проблем, скорость, если верить Total Comander-у порядка 8 МБ/с. А вот при аплоаде, иногда в дебаг вываливается
Код
memp_malloc: out of memory in pool PBUF_POOL

При этом резко падает скорость передачи, с 3-4 МБ/с до 5-300 КБ/с. При этом коннект не теряется, данные идут. После окончания передачи, сообщения в дебаг продолжают валиться, т.е. пул PBUF_POOL забит до отказа, входящие сообщения теряются.
связь устанавливаю через netconn, поддерживается несколько клиентов, используется FreeRTOS v9.0.0
Задачка, ожидающая соединения клиента на 21 порт.
При подключении создается еще одна задача (экземпляр задачи), куда параметром указываем указатель на подключение клиента
CODE
void LwipFtpListenRTOS( void *pvParameters )
{
err_t res;

while(1)
{
uint8_t State = 0, Run = 1;
while(Run)
{
switch(State)
{
case 0:
{
State++;
xSemaphoreTake(UsartDebugMutex, portMAX_DELAY);
RtcPutTimeStamp();
UsartDebugSendString((const uint8_t*)"[FTP SERVER]->Server start\r\n");
xSemaphoreGive(UsartDebugMutex);

FTP_conn = netconn_new(NETCONN_TCP); // Create a new TCP connection handle
break;
}
case 1:
{
res = netconn_bind(FTP_conn, NULL, 21); // Bind to port with default IP address
if (res == ERR_OK) State++;
break;
}
case 2:
{
xSemaphoreTake(UsartDebugMutex, portMAX_DELAY);
RtcPutTimeStamp();
sprintf((char *)UsartDebugBuffer, "[FTP SERVER]->Port %u is open\r\n",21);
UsartDebugSendString((const uint8_t*)UsartDebugBuffer);
xSemaphoreGive(UsartDebugMutex);
State++;
netconn_listen(FTP_conn); // Слушаем соединение
break;
}
case 3:
{
struct netconn *test_conn;
res = netconn_accept(FTP_conn, &test_conn); // Ждем подключения клиента
if (res == ERR_OK)
{
xTaskCreate(FtpServerRTOS ,(const char*)"FTP_SERVER" ,1024 ,test_conn , tskIDLE_PRIORITY + 2 ,NULL );
}
break;
}
default: break;
}
}
}
}


экземпляр задачи обслуживания клиента.
Код урезал для форума, каждый case обрабатывает соответствующий запрос, с ними проблем нет.
Пока что сделан только пассивный режим, т.е. при команде PASV, открываем еще один входящий порт, сообщаем клиенту и уже по этому порту гоняются все данные, типа списка файлов, приема/передачи.
CODE
// Клиент подключился
void FtpServerRTOS( void *pvParameters )
{
struct netconn *conn;
struct netbuf *inbuf;
struct ip4_addr ClientAddr, RecvAddr;
err_t res;
uint16_t RecvLen;
uint16_t ClientPort = 0, RecvPort;
uint8_t* pRecvData;
List_IdFtpCmd RecvIdCmd;
static uint8_t InitFlag = 0;


uint8_t TxBuffer[128];

conn = (struct netconn*)pvParameters;


ClientAddr.addr = 0;
netconn_getaddr(conn, &ClientAddr, &ClientPort, NULL); //посмотрим, кто к нам подключился

xSemaphoreTake(UsartDebugMutex, portMAX_DELAY);
RtcPutTimeStamp();
sprintf((char *)UsartDebugBuffer, "[FTP SERVER]->Client %u.%u.%u.%u:%u connected\r\n",ip4_addr1(&ClientAddr),
ip4_addr2(&ClientAddr),ip4_addr3(&ClientAddr),ip4_addr4(&ClientAddr),ClientPort);
UsartDebugSendString((const uint8_t*)UsartDebugBuffer);
xSemaphoreGive(UsartDebugMutex);


// Say hello to new user
res = netconn_write(conn ,ANS_220 ,strlen((const char*)ANS_220) ,NETCONN_NOCOPY );
if (res != ERR_OK)
{
netconn_delete(conn);
vTaskDelete(NULL);
}

while(1)
{
res = netconn_recv(conn, &inbuf);
if (res == ERR_OK) //приняли посылку
{
RecvLen = netbuf_len(inbuf);

pRecvData = pvPortMalloc(RecvLen); //выделяем память
if (pRecvData != NULL) //смогли выделить
{
netbuf_copy(inbuf ,pRecvData ,RecvLen );
}
else
{
xSemaphoreTake(UsartDebugMutex, portMAX_DELAY);
RtcPutTimeStamp();
UsartDebugSendString((const uint8_t*)"[FTP SERVER]->Malloc failed, can't read new data\r\n");
xSemaphoreGive(UsartDebugMutex);

netbuf_delete(inbuf);
netconn_delete(conn);
vTaskDelete(NULL);
}
netbuf_delete(inbuf);


RecvIdCmd = FindIdCmd(pRecvData);
if (RecvIdCmd != NULL)
{
switch (RecvIdCmd)
{
case USER_CMD:
case PASS_CMD:
case CWD_CMD:
case CDUP_CMD:
case PORT_CMD:
case PASV_CMD:
case TYPE_CMD:
case RETR_CMD:
case STOR_CMD:
case PWD_CMD:
case LIST_CMD:
case SYST_CMD:
case NOOP_CMD:
default: // скажем 502, на команды которые еще не написали
{
res = netconn_write(conn ,ANS_502 ,strlen((const char*)ANS_502) ,NETCONN_NOCOPY );
if (res != ERR_OK)
{
vPortFree(pRecvData);
netconn_delete(conn);
vTaskDelete(NULL);
}
}
}
}
else // нет такой команды
{
res = netconn_write(conn ,ANS_502 ,strlen((const char*)ANS_502) ,NETCONN_NOCOPY );
if (res != ERR_OK)
{
vPortFree(pRecvData);
netconn_delete(conn);
vTaskDelete(NULL);
}
}

vPortFree(pRecvData);
}
else //клиент закрыл соединение, либо пропал линк, либо вышел таймаут
{
xSemaphoreTake(UsartDebugMutex, portMAX_DELAY);
RtcPutTimeStamp();
sprintf((char *)UsartDebugBuffer, "[FTP SERVER]->Client %u.%u.%u.%u:%u disconnected\r\n",ip4_addr1(&ClientAddr),
ip4_addr2(&ClientAddr),ip4_addr3(&ClientAddr),ip4_addr4(&ClientAddr),ClientPort);
UsartDebugSendString((const uint8_t*)UsartDebugBuffer);
xSemaphoreGive(UsartDebugMutex);

netbuf_delete(inbuf);
netconn_delete(conn);

vTaskDelete(NULL);
}
}
}


Код приема файла от клиента, упрощенный:
Код
                        f_res = f_open(file_name);

                        pData = pvPortMalloc(2048);  // пакет максимум 1460 байт
                        while (1)
                        {
                            res = netconn_recv(FtpDataConn.ClientConn, &(FtpDataConn.inbuf));
                            if (res == ERR_OK)    //приняли посылку
                            {
                                uint16_t DataLen = netbuf_len(FtpDataConn.inbuf);
                                netbuf_copy(FtpDataConn.inbuf    ,pData    ,DataLen    );
                                netbuf_delete(FtpDataConn.inbuf);

                                f_write(&fil, pData, DataLen, &BytesWrite);

//                                vTaskDelay(1);
                            }
                            else break;
                        }
                        f_close(&fil);

                        vPortFree(pData);


И вот тут начинаются проблемы. Если закоментировать vTaskDelay(1), то скорость приема поначалу 3-4 МБ/с, затем начинается срыв пула PBUF скорость падает. Если раскоментить, то скорость порядка 1.5МБ/с, что воплне ожидаемо, средний пакет порядка 1460 байт, с частотой 1 кГц грубо, мы его вычитываем.
Скорее всего проблема кроется где-то в драйвере ethernetif.c, однако в него уже внес фиксы на все найденные баги, код прикладываю
CODE
/**
* @file
* Ethernet Interface Skeleton
*
*/

/*
* Copyright © 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/

/*
* This file is a skeleton for developing Ethernet network interface
* drivers for lwIP. Add code to the low_level functions and do a
* search-and-replace for the word "ethernetif" to replace it with
* something that better describes your network interface.
*/

#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "netif/etharp.h"
#include "ethernetif.h"
#include "lwip/timeouts.h"

#include "EthernetComm.h"
#include "stm32f4x7_eth.h"
#include <string.h>


#define netifMTU (1500)
#define netifINTERFACE_TASK_STACK_SIZE ( 350 )
#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define netifGUARD_BLOCK_TIME ( 250 )
/* The time to block waiting for input. */
#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( TickType_t ) 200 )

/* Define those to better describe your network interface. */
#define IFNAME0 's'
#define IFNAME1 't'


static struct netif *s_pxNetIf = NULL;
SemaphoreHandle_t s_xSemaphore = NULL;


/* Ethernet Rx & Tx DMA Descriptors */
extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];

/* Ethernet Receive buffers */
extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];

/* Ethernet Transmit buffers */
extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];

/* Global pointers to track current transmit and receive descriptors */
extern ETH_DMADESCTypeDef *DMATxDescToSet;
extern ETH_DMADESCTypeDef *DMARxDescToGet;

/* Global pointer for last received frame infos */
extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos;




static void ethernetif_input( void * pvParameters );
static void arp_timer(void *arg);


/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void low_level_init(struct netif *netif)
{
uint32_t i;

/* set netif MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;

/* set netif MAC hardware address */
netif->hwaddr[0] = MAC_ADDR0;
netif->hwaddr[1] = MAC_ADDR1;
netif->hwaddr[2] = MAC_ADDR2;
netif->hwaddr[3] = MAC_ADDR3;
netif->hwaddr[4] = MAC_ADDR4;
netif->hwaddr[5] = MAC_ADDR5;

/* set netif maximum transfer unit */
netif->mtu = 1500;

/* Accept broadcast address and ARP traffic */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;

s_pxNetIf =netif;

/* create binary semaphore used for informing ethernetif of frame reception */
if (s_xSemaphore == NULL)
{
s_xSemaphore= xSemaphoreCreateCounting(50,0);
}

/* initialize MAC address in ethernet MAC */
ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr);

/* Initialize Tx Descriptors list: Chain Mode */
ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
/* Initialize Rx Descriptors list: Chain Mode */
ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);

/* Enable Ethernet Rx interrrupt */
{
for(i=0; i<ETH_RXBUFNB; i++)
{
ETH_DMARxDescReceiveITConfig(&DMARxDscrTab[i], ENABLE);
}
}

#ifdef CHECKSUM_BY_HARDWARE
/* Enable the checksum insertion for the Tx frames */
{
for(i=0; i<ETH_TXBUFNB; i++)
{
ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
}
}
#endif

/* create the task that handles the ETH_MAC */
xTaskCreate(ethernetif_input, "Eth_if", netifINTERFACE_TASK_STACK_SIZE, NULL,
netifINTERFACE_TASK_PRIORITY,NULL);

/* Enable MAC and DMA transmission and reception */
ETH_Start();
}


/**
* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/

static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
static SemaphoreHandle_t xTxSemaphore = NULL;
struct pbuf *q;
uint32_t l = 0;
u8 *buffer;

if (xTxSemaphore == NULL)
{
vSemaphoreCreateBinary (xTxSemaphore);
}

if (xSemaphoreTake(xTxSemaphore, netifGUARD_BLOCK_TIME))
{
buffer = (u8 *)(DMATxDescToSet->Buffer1Addr);
for(q = p; q != NULL; q = q->next)
{
memcpy((u8_t*)&buffer[l], q->payload, q->len);
l = l + q->len;
}
ETH_Prepare_Transmit_Descriptors(l);
xSemaphoreGive(xTxSemaphore);
}

return ERR_OK;
}





/**
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
static struct pbuf * low_level_input(struct netif *netif)
{
struct pbuf *p, *q;
u16_t len;
uint32_t l=0,i =0;
FrameTypeDef frame;
u8 *buffer;
__IO ETH_DMADESCTypeDef *DMARxNextDesc;

p = NULL;

/* Get received frame */
frame = ETH_Get_Received_Frame_interrupt();

if (frame.descriptor && frame.buffer) {
/* check that frame has no error */
if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET)
{

/* Obtain the size of the packet and put it into the "len" variable. */
len = frame.length;
buffer = (u8 *)frame.buffer;

/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);

/* Copy received frame from ethernet driver buffer to stack buffer */
if (p != NULL)
{
for (q = p; q != NULL; q = q->next)
{
memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len);
l = l + q->len;
}
}
}

/* Release descriptors to DMA */
/* Check if received frame with multiple DMA buffer segments */
if (DMA_RX_FRAME_infos->Seg_Count > 1)
{
DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc;
}
else
{
DMARxNextDesc = frame.descriptor;
}

/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
for (i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
{
DMARxNextDesc->Status = ETH_DMARxDesc_OWN;
DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr);
}

/* Clear Segment_Count */
DMA_RX_FRAME_infos->Seg_Count =0;
}
return p;
}



/**
* This function is the ethernetif_input task, it is processed when a packet
* is ready to be read from the interface. It uses the function low_level_input()
* that should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
static void ethernet_watchdog(void) {
/* When Rx Buffer unavailable flag is set: clear it and resume reception */
if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
{
/* Clear RBUS ETHERNET DMA flag */
ETH->DMASR = ETH_DMASR_RBUS;

/* Resume DMA reception. The register doesn't care what you write to it. */
ETH->DMARPDR = 0;
}
}

void ethernetif_input( void * pvParameters )
{
struct pbuf *p;

for(;; )
{
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
{
GET_NEXT_FRAGMENT:
p = low_level_input( s_pxNetIf );
if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
{
if (p != NULL)
{
pbuf_free(p);
p = NULL;
}
}
else
{
xSemaphoreTake(s_xSemaphore, 0);
goto GET_NEXT_FRAGMENT;
}
}
ethernet_watchdog();
}
}

/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));

#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */

netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;

netif->output = etharp_output;
netif->linkoutput = low_level_output;

/* initialize the hardware */
low_level_init(netif);

etharp_init();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);

return ERR_OK;
}


static void arp_timer(void *arg)
{
etharp_tmr();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}

void ETH_IRQHandler(void)
{
static portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;

/* Frame received */
if ( ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET) xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken ); /* Give the semaphore to wakeup LwIP task */

/* Clear the interrupt flags. */
/* Clear the Eth DMA Rx IT pending bits */
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);

/* Switch tasks if necessary. */
if( xHigherPriorityTaskWoken != pdFALSE ) portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}


также прикладываю lwipports.h
CODE

/**
******************************************************************************
* @file lwipopts.h
* @author MCD Application Team
* @version V1.0.0
* @date 31-October-2011
* @brief lwIP Options Configuration.
* This file is based on Utilities\lwip_v1.3.2\src\include\lwip\opt.h
* and contains the lwIP configuration for the STM32F4x7 demonstration.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/

#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__

/**
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
* critical regions during buffer allocation, deallocation and memory
* allocation and deallocation.
*/
#define SYS_LIGHTWEIGHT_PROT 0

#define ETHARP_TRUST_IP_MAC 0
#define IP_REASSEMBLY 0
#define IP_FRAG 0
#define ARP_QUEUEING 0

/**
* NO_SYS==1: Provides VERY minimal functionality. Otherwise,
* use lwIP facilities.
*/
#define NO_SYS 0

/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT 4

/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE (8*1024)

/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 100
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 6
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 10
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 5
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 20
/* MEMP_NUM_NETBUF: the number of struct netbufs.
(only needed if you use the sequential API, like api_lib.c) */
#define MEMP_NUM_NETBUF 10
/* MEMP_NUM_NETCONN: the number of struct netconns.
(only needed if you use the sequential API, like api_lib.c)*/
#define MEMP_NUM_NETCONN 10

/**
* MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
* for incoming packets.
* (only needed if you use tcpip.c)
*/
#define MEMP_NUM_TCPIP_MSG_INPKT 200

/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 15

/* LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and SO_RCVTIMEO processing. */
#define LWIP_SO_RCVTIMEO 1





/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 64

/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 512


/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255

/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 0

/* TCP Maximum segment size. */
#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */

/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (5*TCP_MSS)

/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */

#define TCP_SND_QUEUELEN (4* TCP_SND_BUF/TCP_MSS)

/* TCP receive window. */
#define TCP_WND (2*TCP_MSS)


/**
* LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname
* field.
*/
#define LWIP_NETIF_HOSTNAME 1

/* ---------- ICMP options ---------- */
#define LWIP_ICMP 1


/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
turning this on does currently not work. */
#define LWIP_DHCP 1


/* ---------- UDP options ---------- */
#define LWIP_UDP 1
#define UDP_TTL 255


/* ---------- Statistics options ---------- */
#define LWIP_STATS 0
#define LWIP_PROVIDE_ERRNO 0

/**
* LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf.
*/
#define LWIP_NETBUF_RECVINFO 1

/*
--------------------------------------
---------- Checksum options ----------
--------------------------------------
*/

/*
The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
- To use this feature let the following define uncommented.
- To disable it and process by CPU comment the the checksum.
*/
#define CHECKSUM_BY_HARDWARE


#ifdef CHECKSUM_BY_HARDWARE
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 0
/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 0
/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 0
/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 0
/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 0
/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 0
/* CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets.*/
#define CHECKSUM_GEN_ICMP 0
#else
/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 1
/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 1
/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 1
/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 1
/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 1
/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 1
/* CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets.*/
#define CHECKSUM_GEN_ICMP 1
#endif


/*
----------------------------------------------
---------- Sequential layer options ----------
----------------------------------------------
*/
/**
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
*/
#define LWIP_NETCONN 1

/*
------------------------------------
---------- Socket options ----------
------------------------------------
*/
/**
* LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
*/
#define LWIP_SOCKET 0

/*
-----------------------------------
---------- DEBUG options ----------
-----------------------------------
*/

#define LWIP_DEBUG 1

#define MEM_DEBUG LWIP_DBG_ON
#define MEMP_DEBUG LWIP_DBG_ON


/*
---------------------------------
---------- OS options ----------
---------------------------------
*/

#define TCPIP_THREAD_STACKSIZE 1500
#define TCPIP_MBOX_SIZE 20
#define DEFAULT_UDP_RECVMBOX_SIZE 2000
#define DEFAULT_TCP_RECVMBOX_SIZE 2000
#define DEFAULT_ACCEPTMBOX_SIZE 2000
#define DEFAULT_THREAD_STACKSIZE 500
#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES - 2)



#endif /* __LWIPOPTS_H__ */

/******************* © COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/



Сообщение отредактировал IgorKossak - Sep 4 2017, 12:43
Причина редактирования: [codebox] для длинного кода. [code]-для короткого!!!
Go to the top of the page
 
+Quote Post
sadat
сообщение Sep 7 2017, 16:57
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 90
Регистрация: 6-07-05
Из: Белгород
Пользователь №: 6 575



Есть ли возможность установить WireShark и посмотреть статистику передачи пакетов?
Посмотрел lwipports.h - у меня немного другие константы, добивал экспериментальным путём.

/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 1524
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (16*TCP_MSS)


в ethernetif.c есть вставка выравнивания буферов по адресу, кратному 4, ну и, соответственно, размер его должен быть приличным.

Так же я сталкивался с глюком самой LAN7820 на передаче больших пакетов, лично у меня она полностью зависала, приходилось дёргать Reset, чтобы привести её "в чувство". Есть ли возможность мониторить состояние физики?
Go to the top of the page
 
+Quote Post
mantech
сообщение Sep 7 2017, 18:03
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 500
Регистрация: 16-08-12
Из: Киров
Пользователь №: 73 143



Цитата(sadat @ Sep 7 2017, 19:57) *
Так же я сталкивался с глюком самой LAN7820 на передаче больших пакетов


Больших - это сколько? У этой физики замечал только один глюк, при чтении статуса линка бывал подвисон.
Go to the top of the page
 
+Quote Post
Hold
сообщение Sep 8 2017, 01:56
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 27-01-17
Пользователь №: 95 184



Итак, что было сделано с момента первого поста. Решил еще раз переписать всё, используя последнее обновление "STSW-STM32070 LwIP TCP/IP stack demonstration for STM32F4x7 microcontrollers (AN3966)". Еще раз проверил все адреса PHY, убедился что регистры корректно читаются/пишутся, Auto-negotiation даёт нужные параметры. ethernetif.c взял оттуда же, к слову они внесли туда значительные изменения( правильное освобождение pbuf, проверка ошибок RBU и еще по мелочи). Еще раз пересобрал проект, отключил все остальные программные модули, оставил только дебажный usart, SDRAM 64 мбайта и ethernet. К тому же в их реализации sys_arch.c был критичный баг, при использовании мьютексов, они неверно передавали указатель (точнее передавали указатель на указатель, в итоге FreeRTOS вываливалась в assert). В итоге, всё завелось. Уж не знаю где конкретно был косяк, но проще было собрать всё заново, чем искать, к тому же прошлые исходники были далеко не свежие. Сейчас аплоад на виртуальный диск FTP составляет 8-9 МБайт/с (без физической записи на диск, файл просто создается и закрывается в конце передачи). Гоняю, проверяю на зависоны, но пока-что всё хорошо, залил 2 ТБ суммарно, ничего не зависло и не отвалилось. Как проверить на подвисание phy пока не могу придумать, но в принципе у меня отслеживается линк, низко-приоритетным таском, можно по таймауту функции ETH_ReadPHYRegister() отловить, попробую.
Прикладываю все драйвера для LAN8720A + сам lwIP 2.0.2 (исправленным багом hostname-а DHCP) c портом для STM32 (исправлен косяк с взятием мьютекса). В lwIP 2.0.2 по сравнению с 1.4.1 внесли довольно много изменений, поменяли часть структур (к примеру, dhcp теперь отдельная структура, а не чать netif), инициазация заточена именно по 2.0.2.
Инициализация всей сети:
Код
    ETH_BSP_Config();
    LwIP_Init();
#ifdef USE_DHCP
    xTaskCreate(LwIP_DHCP_task, (char const*) "DHCP", configMINIMAL_STACK_SIZE * 2, NULL,DHCP_TASK_PRIO, NULL);
#endif
        http_server_netconn_init();   // тестовая страничка

в каком-нибудь таске.
Прикрепленный файл  lwIP_2.0.2_fix.zip ( 3.08 мегабайт ) Кол-во скачиваний: 24

Прикрепленный файл  STM32F4x7_ETH_Driver_LAN8720A_lwIP_2.0.2.zip ( 48.36 килобайт ) Кол-во скачиваний: 21
Go to the top of the page
 
+Quote Post
scifi
сообщение Sep 8 2017, 07:22
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 739
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Hold @ Sep 8 2017, 04:56) *
Как проверить на подвисание phy пока не могу придумать

Минуточку. Кто-то хоть раз видел, как "подвисает phy"? Хочу всё знать.
А вот разрыв линка (патчкорд выдернули из розетки) отслеживать надо, конечно. Потому что потом после autonegotiation могут быть другие скорость и дуплекс.
Go to the top of the page
 
+Quote Post
Hold
сообщение Sep 8 2017, 07:58
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 27-01-17
Пользователь №: 95 184



Вон, сообщением выше, утверждают что данный PHY подвисает при чтении линка (статусного регистра). Естественно линки отслеживаю, запускаю Auto-negotiation.
Go to the top of the page
 
+Quote Post
scifi
сообщение Sep 8 2017, 08:04
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 739
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Hold @ Sep 8 2017, 10:58) *
Вон, сообщением выше, утверждают что данный PHY подвисает при чтении линка (статусного регистра).

Слишком мало доказательств для столь серьёзного обвинения. Гугл по этому поводу молчит. А вот принять собственную криворукость за глюки мелкосхемы/компилятора/чужого кода проще простого. Скорее всего, это именно такой случай.
Go to the top of the page
 
+Quote Post
Hold
сообщение Sep 8 2017, 08:08
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 27-01-17
Пользователь №: 95 184



Сам я с зависанием LAN8720A не сталкивался, ничего утверждать не могу. Пока продолжаю тесты, прогнал еще 2 Тб данных, ни потерь ни вылетов.
Go to the top of the page
 
+Quote Post
vlad_new
сообщение Sep 8 2017, 09:22
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 212
Регистрация: 24-06-10
Пользователь №: 58 127



На счет подвисания. Все они виснут. Вопрос при каких условиях это происходит. На счет ланки, могу сказать, что в домашних условиях, она редко виснет.
У меня она работает уже лет 5. Но она очень помехо не защищенная. Если рядом с ethernet кабелем создать даже небольшую помеху, то она сразу перестает работать.
В 90% помогает обычный импульс сброса на её лапку. типа: if(read_PHY(0)==0), то сбрасываем её. К стате, зависнуть может даже от включения холодильника ( если проводка в доме неважная). В промышленных вариантах использую DP83848. Она на порядок более помехо защищенная.
Вот как то так.
Go to the top of the page
 
+Quote Post
Hold
сообщение Sep 8 2017, 10:01
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 27-01-17
Пользователь №: 95 184



После ресета, необходимо ли опять переинициализировать lwip, как в случае пропадания линка, или просто дернули лапкой, и она продолжила работу?
Go to the top of the page
 
+Quote Post
scifi
сообщение Sep 8 2017, 10:48
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 739
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Hold @ Sep 8 2017, 13:01) *
После ресета, необходимо ли опять переинициализировать lwip, как в случае пропадания линка, или просто дернули лапкой, и она продолжила работу?

Софт внутри МК и PHY требуют согласования только в вопросе скорость/дуплекс. Поэтому ничего там не надо переинициализировать.
Go to the top of the page
 
+Quote Post
sadat
сообщение Sep 8 2017, 14:23
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 90
Регистрация: 6-07-05
Из: Белгород
Пользователь №: 6 575



Многократные передачи мегабайтной картинки, виснет именно 8720, как на собственной плате, так и на примере от starterkit.
Вполне допускаю "нюансы разводки", но иногда проблема проявлялась через неделю использования, поэтому постоянно в коде проверка на статус, если 0 - принудительный ресет, другие способы общения не помогают - микруха стабильно "висит".
Хочу вернуться на старый добрый реалтек в новых проектах.
Никаких других "телодвижений" больше не делал - lwIP нормально подхватывает.

Код
  //СБРОС ВНУТРЕННЕГО ЛАНА ПРИ ПОТЕРЕ ЛИНКА
      HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &temp32);
      temp32&=0x0004; //Valid link established
    temp = (&gnetif)->flags & NETIF_FLAG_UP;
      if ((temp32 == 0x0004) && (!(temp))) {netif_set_up(&gnetif);}  
    else if((temp32 == 0x0000) && (temp))
     {
      netif_set_down(&gnetif);
     };
// ПРОВЕРКА НА ТО, ЧТО ЛАН ПОВИС
    HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &temp32);
    temp32&=0x0020;//Auto-Negotiation process completed
    if (temp32==0)
     {
         timeout_ethernet_reset = 2500;
         for (register uint32_t tempss=0; tempss<0x3FFFF;tempss++) HAL_GPIO_WritePin (GPIOD, GPIO_PIN_11, GPIO_PIN_RESET);
         HAL_GPIO_WritePin (GPIOD, GPIO_PIN_11, GPIO_PIN_SET);
     };
Go to the top of the page
 
+Quote Post
Hold
сообщение Sep 11 2017, 09:49
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 27-01-17
Пользователь №: 95 184



Полезли первые ошибки. Подключил два клиента, и начал вылетать в HardFault, со следующим логом:
Код
[Hard fault handler]
R0 = 0x20030003
R1 = 0x360cab80
R2 = 0x36076f22
R3 = 0xa5a5a5a5
R12 = 0xa5a5a5a5
LR = 0x8003f51
PC = 0x80056c2
PSR = 0x21000000


Обработчик HardFault:
CODE

void Hard_fault_handler_c(unsigned int* hardfault_args)
{
unsigned int stacked_r0;
unsigned int stacked_r1;
unsigned int stacked_r2;
unsigned int stacked_r3;
unsigned int stacked_r12;
unsigned int stacked_lr;
unsigned int stacked_pc;
unsigned int stacked_psr;

stacked_r0 = ((unsigned long) hardfault_args[0]);
stacked_r1 = ((unsigned long) hardfault_args[1]);
stacked_r2 = ((unsigned long) hardfault_args[2]);
stacked_r3 = ((unsigned long) hardfault_args[3]);

stacked_r12 = ((unsigned long) hardfault_args[4]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);

printf("\r\n[Hard fault handler]\r\n");
printf("R0 = 0x%x\r\n", stacked_r0);
printf("R1 = 0x%x\r\n", stacked_r1);
printf("R2 = 0x%x\r\n", stacked_r2);
printf("R3 = 0x%x\r\n", stacked_r3);
printf("R12 = 0x%x\r\n", stacked_r12);
printf("LR = 0x%x\r\n", stacked_lr);
printf("PC = 0x%x\r\n", stacked_pc);
printf("PSR = 0x%x\r\n", stacked_psr);

/* Go to infinite loop when Hard Fault exception occurs */
while (1);
}

__stackless void HardFault_Handler(void)
{
asm("MRS R0, PSP"); // FreeRTOS использует PSP
//top of stack is in R0. It is passed to C-function.
asm("BL (Hard_fault_handler_c)");

/* Go to infinite loop when Hard Fault exception occurs */
while (1);
}


PC = 0x80056c2 ведёт на memcpy(), а LR = 0x8003f51, если в нем верный адрес возврата, ведёт на freertos-овскую функцию prvCopyDataFromQueue. Куда копать пока не знаю, ошибка возникает, если просто подключен второй клиент, а первый закачивает данные.
Go to the top of the page
 
+Quote Post
Integro
сообщение Sep 11 2017, 09:59
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 25-12-09
Из: Минск
Пользователь №: 54 460



Цитата(Hold @ Sep 11 2017, 12:49) *
PC = 0x80056c2 ведёт на memcpy(), а LR = 0x8003f51, если в нем верный адрес возврата, ведёт на freertos-овскую функцию prvCopyDataFromQueue. Куда копать пока не знаю, ошибка возникает, если просто подключен второй клиент, а первый закачивает данные.


Залогируйте аргументы функции xQueueReceive(prvCopyDataFromQueue), складывается впечатление что в функцию прилетает не верный указатель.
Go to the top of the page
 
+Quote Post
sadat
сообщение Sep 11 2017, 10:23
Сообщение #15


Частый гость
**

Группа: Свой
Сообщений: 90
Регистрация: 6-07-05
Из: Белгород
Пользователь №: 6 575



Предлагаю оптимизацию при компиляции попробовать в "ноль" выкрутить.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd September 2017 - 18:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01545 секунд с 7
ELECTRONIX ©2004-2016