Question
Ethernet close connection and restart MCU
Hi,
I have STM32F767 - Nucleo kit. I implement FreeRTOS, lwIP. And I create this connect.
struct tcp_pcb *server_pcb;
struct server_struct
{
uint8_t state; /* current connection state */
uint8_t retries;
struct tcp_pcb *pcb; /* pointer on the current tcp_pcb */
struct pbuf *p; /* pointer on the received/to be transmitted pbuf */
};
struct server_struct *ss;
enum server_states
{
ES_NONE = 0,
ES_ACCEPTED,
ES_RECEIVED,
ES_CLOSING
};
static void tcp_server_send(struct tcp_pcb *tpcb, struct server_struct *es)
{
struct pbuf *ptr;
err_t wr_err = ERR_OK;
while ((wr_err == ERR_OK) && (es->p != NULL) && (es->p->len <= tcp_sndbuf(tpcb)))
{
ptr = es->p;
wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
if (wr_err == ERR_OK)
{
uint16_t plen;
uint8_t freed;
plen = ptr->len;
es->p = ptr->next;
if(es->p != NULL)
{
pbuf_ref(es->p);
}
do
{
freed = pbuf_free(ptr);
}
while(freed == 0);
tcp_recved(tpcb, plen);
}
else if(wr_err == ERR_MEM)
{
es->p = ptr;
}
else
{
//other problem
}
}
}
static void tcp_server_connection_close(struct tcp_pcb *tpcb, struct server_struct *es)
{
// remove all callbacks
tcp_arg(tpcb, NULL);
tcp_sent(tpcb, NULL);
tcp_recv(tpcb, NULL);
tcp_err(tpcb, NULL);
tcp_poll(tpcb, NULL, 1);
if (es != NULL)
{
mem_free(es);
}
tcp_close(tpcb);
}
static void tcp_server_error(void *arg, err_t err)
{
//-TODO-
}
static err_t tcp_server_poll(void *arg, struct tcp_pcb *tpcb)
{
err_t ret_err;
struct server_struct *es;
es = (struct server_struct *)arg;
if (es != NULL)
{
if (es->p != NULL)
{
}
else
{
if(es->state == ES_CLOSING)
{
tcp_server_connection_close(tpcb, es);
}
}
ret_err = ERR_OK;
}
else
{
tcp_abort(tpcb);
ret_err = ERR_ABRT;
}
return ret_err;
}
static err_t tcp_server_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len)
{
struct server_struct *es;
LWIP_UNUSED_ARG(len);
es = (struct server_struct *)arg;
es->retries = 0;
if(es->p != NULL)
{
tcp_server_send(tpcb, es);
}
else
{
if(es->state == ES_CLOSING)
{
tcp_server_connection_close(tpcb, es);
}
}
return ERR_OK;
}
static err_t tcp_server_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
char str1[100];
struct server_struct *es;
err_t ret_err;
LWIP_ASSERT("arg != NULL",arg != NULL);
es = (struct server_struct *)arg;
if (p == NULL)
{
es->state = ES_CLOSING;
if(es->p == NULL)
{
tcp_recved(tpcb, p->tot_len);
}
else
{
//acknowledge received packet
tcp_sent(tpcb, tcp_server_sent);
//send remaining data
tcp_server_send(tpcb, es);
}
ret_err = ERR_OK;
}
else if(err != ERR_OK)
{
if (p != NULL)
{
es->p = NULL;
pbuf_free(p);
}
ret_err = err;
}
else if(es->state == ES_ACCEPTED)
{
tcp_recved(tpcb, p->tot_len);
strncpy(str1,p->payload,p->len);
str1[p->len] = '\0';
/* -- Send data to Serial PORT */
PrintSerial(str1);
ret_err = ERR_OK;
}
else if (es->state == ES_RECEIVED)
{
if(es->p == NULL)
{
ret_err = ERR_OK;
}
else
{
struct pbuf *ptr;
ptr = es->p;
pbuf_chain(ptr,p);
}
ret_err = ERR_OK;
}
else if(es->state == ES_CLOSING)
{
tcp_recved(tpcb, p->tot_len);
es->p = NULL;
pbuf_free(p);
ret_err = ERR_OK;
}
else
{
tcp_recved(tpcb, p->tot_len);
es->p = NULL;
pbuf_free(p);
ret_err = ERR_OK;
}
return ret_err;
}
static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
err_t ret_err;
struct server_struct *es;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(err);
tcp_setprio(newpcb, TCP_PRIO_MIN);
es = (struct server_struct *)mem_malloc(sizeof(struct server_struct));
ss = (struct server_struct *)mem_malloc(sizeof(struct server_struct));
if (es != NULL)
{
es->state = ES_ACCEPTED;
es->pcb = newpcb;
ss->pcb = newpcb;
es->retries = 0;
es->p = NULL;
tcp_arg(newpcb, es);
tcp_recv(newpcb, tcp_server_recv);
tcp_err(newpcb, tcp_server_error);
tcp_sent(newpcb, tcp_server_sent);
tcp_poll(newpcb, tcp_server_poll, 1);
ret_err = ERR_OK;
}
else
{
tcp_server_connection_close(newpcb, es);
ret_err = ERR_MEM;
}
return ret_err;
}
void Hello(void *pvParameters)
{
ip_addr_t ipaddr;
IP4_ADDR(&ipaddr, 192, 168, 11, 208);
server_pcb = tcp_new();
if (server_pcb != NULL)
{
err_t err;
err = tcp_bind(server_pcb, IP_ADDR_ANY, 502);
if (err == ERR_OK)
{
server_pcb = tcp_listen(server_pcb);
tcp_accept(server_pcb, tcp_server_accept);
}
else
{
memp_free(MEMP_TCP_PCB, server_pcb);
}
}
while(1)
{
vTaskDelay(100);
}
}
In main function I create a task:
xTaskCreate( Hello, "Hello", 4096, ( void * ) NULL, 2, NULL );And program works (when I send anything over TCP i see it in serial output). Problem is when I try disconnect. MCU is restart.
Any idea, what is wrong?
I always get this massage:
HardFault Exception
Here is output:
- >>>> HardFault Exception <<<<
- Fault registers:
- SCB->HFSR = 0x40000000
- DEBUGEVT = 0
- FORCED = 1
- VECTTBL = 0
- SCB->CFSR = 0x00010000
- IACCVIOL = 0
- DACCVIOL = 0
- MUNSTKERR = 0
- MSTKERR = 0
- MLSPERR = 0
- MMARVALID = 0
- IBUSERR = 0
- PRECISE E = 0
- IMPRECISE = 0
- UNSTKERR = 0
- STKERR = 0
- LSPERR = 0
- BFARVALID = 0
- UNDEFINSTR= 1
- INVSTATE = 0
- INVPC = 0
- NOCP = 0
- UNALIGNED = 0
- DIVBYZERO = 0
- SCB->DFSR = 0x00000000
- SCB->MMFAR = 0x00000000
- SCB->BFAR = 0x00000000
- SCB->AFSR = 0x00000000
- SCB->ABFSR = 0x00000000
- Exception stack frame:
- R0 0x20045c98
- R1 0x20068d8c
- R2 0x00000003
- R3 0x00009a90
- R12 0x20068a54
- LR 0x08007e87
- PC 0x0800fd5c
- xPSR 0x61000000
- >>> forcing SYSTEM RESET
