Skip to main content
Graduate
May 6, 2024
Solved

void HardFault_Handler(void) issue during data sent via ethernet through TCP_Client

  • May 6, 2024
  • 1 reply
  • 1291 views

HI team,

I am Using NUCLEO-F439ZI board for Ethernet Interface. I successfully transferred the data in UDP, Now I try to send the data using TCP client method. 

In the .ioc configuration file, I followed the below setup

1. Connectivity -> ETH -> RMII mode.

2. Middleware and Software Packs -> LWIP -> General Setting -> LWIP_DHCP (set own IP -> 192.168.1.10)

 Middleware and Software Packs -> LWIP -> Key Option -> heap memory size = 10*1024 bytes.

 Middleware and Software Packs -> LWIP -> HTTPD -> LWIP_HTTPD - enable

after all this setup I generate the code

In the Main.c file 

1. by using this code I ping the connection, its works fine "extern struct netif gnetif;      

ethernetif_input(&gnetif);

sys_check_timeouts();".

2. from this sub function "tcp_server_init();",

To create a TCP block,

Bind the socket to Server Address

Listen from client

Accept function - connection between client and server

After done all this process it successfully debugs and make the connection successfully

 
Ramachandran1992_1-1714984670193.png

The connection made successfully, whenever I try to send the data, the following error

occurred. The below attachment shows the error.

Ramachandran1992_2-1714984987888.png

In the "static void tcp_server_handle (struct tcp_pcb *tpcb, struct tcp_server_struct *es)" function I changed the code this code " char buf[100]; memset (buf, '\0', 100); strncpy(buf, (char *)es->p->payload, es->p->tot_len);

strcat (buf, "+ Hello from TCP SERVER\n"); " to " int len = sprintf(buf, ""%s + Hello from TCPServer\n",(char *)es->p->payload);" the above error was cleared. but my data was not transfer to client, I don't know where I do the mistake. notify my error and mistake.  

The detailed "tcp_server_init()" program was attached below for your reference

Thank you

regards

RAMACHANDRAN.S

    This topic has been closed for replies.
    Best answer by STea

    Hello @Ramachandran1992 ,

    After an examination of the attached file, it seems  tcp_server_handle you are implementing is unable to properly allocate a buffer this should be done with the Pbuf_alloc function.
    my recommendation is to take the example we give in the cube Firmware which can be obtained from Github or from the ST website as a reference so the revised version of your tcp_server_raw.c will be as follows :

    /**
     ******************************************************************************
     * @file LwIP/LwIP_TCP_Echo_Client/Src/tcp_echoclient.c
     * @author MCD Application Team
     * @brief tcp echoclient application using LwIP RAW API
     ******************************************************************************
     * @attention
     *
     * Copyright (c) 2017 STMicroelectronics.
     * All rights reserved.
     *
     * This software is licensed under terms that can be found in the LICENSE file
     * in the root directory of this software component.
     * If no LICENSE file comes with this software, it is provided AS-IS.
     *
     ******************************************************************************
     */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "lwip/debug.h"
    #include "lwip/stats.h"
    #include "lwip/tcp.h"
    #include "lwip/memp.h"
    #include <stdio.h>
    #include <string.h>
    
    #if LWIP_TCP
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    u8_t recev_buf[50];
    __IO uint32_t message_count=0;
    
    u8_t data[100];
    
    struct tcp_pcb *echoclient_pcb;
    
    /* ECHO protocol states */
    enum echoclient_states
    {
     ES_NOT_CONNECTED = 0,
     ES_CONNECTED,
     ES_RECEIVED,
     ES_CLOSING,
    };
    
    /* structure to be passed as argument to the tcp callbacks */
    struct echoclient
    {
     enum echoclient_states state; /* connection status */
     struct tcp_pcb *pcb; /* pointer on the current tcp_pcb */
     struct pbuf *p_tx; /* pointer on pbuf to be transmitted */
    };
    
    /* Private function prototypes -----------------------------------------------*/
    static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
    static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es);
    static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb);
    static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
    static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es);
    static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err);
    
    /* Private functions ---------------------------------------------------------*/
    
    
    /**
     * @brief Connects to the TCP echo server
     * @param None
     * @retval None
     */
    void tcp_echoclient_connect(void)
    {
     ip_addr_t DestIPaddr;
     
     /* create new tcp pcb */
     echoclient_pcb = tcp_new();
     
     if (echoclient_pcb != NULL)
     {
     IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
     
     /* connect to destination address/port */
     tcp_connect(echoclient_pcb,&DestIPaddr,DEST_PORT,tcp_echoclient_connected);
     }
    }
    
    /**
     * @brief Function called when TCP connection established
     * @param tpcb: pointer on the connection control block
     * @param err: when connection correctly established err should be ERR_OK 
     * @retval err_t: returned error 
     */
    static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
    {
     struct echoclient *es = NULL;
     
     if (err == ERR_OK) 
     {
     /* allocate structure es to maintain tcp connection information */
     es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));
     
     if (es != NULL)
     {
     es->state = ES_CONNECTED;
     es->pcb = tpcb;
     
     sprintf((char*)data, "sending tcp client message %d", (int)message_count);
     
     /* allocate pbuf */
     es->p_tx = pbuf_alloc(PBUF_TRANSPORT, strlen((char*)data) , PBUF_POOL);
     
     if (es->p_tx)
     { 
     /* copy data to pbuf */
     pbuf_take(es->p_tx, (char*)data, strlen((char*)data));
     
     /* pass newly allocated es structure as argument to tpcb */
     tcp_arg(tpcb, es);
     
     /* initialize LwIP tcp_recv callback function */ 
     tcp_recv(tpcb, tcp_echoclient_recv);
     
     /* initialize LwIP tcp_sent callback function */
     tcp_sent(tpcb, tcp_echoclient_sent);
     
     /* initialize LwIP tcp_poll callback function */
     tcp_poll(tpcb, tcp_echoclient_poll, 1);
     
     /* send data */
     tcp_echoclient_send(tpcb,es);
     
     return ERR_OK;
     }
     }
     else
     {
     /* close connection */
     tcp_echoclient_connection_close(tpcb, es);
     
     /* return memory allocation error */
     return ERR_MEM; 
     }
     }
     else
     {
     /* close connection */
     tcp_echoclient_connection_close(tpcb, es);
     }
     return err;
    }
     
    /**
     * @brief tcp_receiv callback
     * @param arg: argument to be passed to receive callback 
     * @param tpcb: tcp connection control block 
     * @param err: receive error code 
     * @retval err_t: returned error 
     */
    static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
    { 
     struct echoclient *es;
     err_t ret_err; 
    
     LWIP_ASSERT("arg != NULL",arg != NULL);
     
     es = (struct echoclient *)arg;
     
     /* if we receive an empty tcp frame from server => close connection */
     if (p == NULL)
     {
     /* remote host closed connection */
     es->state = ES_CLOSING;
     if(es->p_tx == NULL)
     {
     /* we're done sending, close connection */
     tcp_echoclient_connection_close(tpcb, es);
     }
     else
     { 
     /* send remaining data*/
     tcp_echoclient_send(tpcb, es);
     }
     ret_err = ERR_OK;
     } 
     /* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
     else if(err != ERR_OK)
     {
     /* free received pbuf*/
     if (p != NULL)
     {
     pbuf_free(p);
     }
     ret_err = err;
     }
     else if(es->state == ES_CONNECTED)
     {
     /* increment message count */
     message_count++;
     
     /* Acknowledge data reception */
     tcp_recved(tpcb, p->tot_len); 
     
     pbuf_free(p);
     tcp_echoclient_connection_close(tpcb, es);
     ret_err = ERR_OK;
     }
    
     /* data received when connection already closed */
     else
     {
     /* Acknowledge data reception */
     tcp_recved(tpcb, p->tot_len);
     
     /* free pbuf and do nothing */
     pbuf_free(p);
     ret_err = ERR_OK;
     }
     return ret_err;
    }
    
    /**
     * @brief function used to send data
     * @param tpcb: tcp control block
     * @param es: pointer on structure of type echoclient containing info on data 
     * to be sent
     * @retval None 
     */
    static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es)
    {
     struct pbuf *ptr;
     err_t wr_err = ERR_OK;
     
     while ((wr_err == ERR_OK) &&
     (es->p_tx != NULL) && 
     (es->p_tx->len <= tcp_sndbuf(tpcb)))
     {
     
     /* get pointer on pbuf from es structure */
     ptr = es->p_tx;
    
     /* enqueue data for transmission */
     wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
     
     if (wr_err == ERR_OK)
     { 
     /* continue with next pbuf in chain (if any) */
     es->p_tx = ptr->next;
     
     if(es->p_tx != NULL)
     {
     /* increment reference count for es->p */
     pbuf_ref(es->p_tx);
     }
     
     /* free pbuf: will free pbufs up to es->p (because es->p has a reference count > 0) */
     pbuf_free(ptr);
     }
     else if(wr_err == ERR_MEM)
     {
     /* we are low on memory, try later, defer to poll */
     es->p_tx = ptr;
     }
     else
     {
     /* other problem ?? */
     }
     }
    }
    
    /**
     * @brief This function implements the tcp_poll callback function
     * @param arg: pointer on argument passed to callback
     * @param tpcb: tcp connection control block
     * @retval err_t: error code
     */
    static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb)
    {
     err_t ret_err;
     struct echoclient *es;
    
     es = (struct echoclient*)arg;
     if (es != NULL)
     {
     if (es->p_tx != NULL)
     {
     /* there is a remaining pbuf (chain) , try to send data */
     tcp_echoclient_send(tpcb, es);
     }
     else
     {
     /* no remaining pbuf (chain) */
     if(es->state == ES_CLOSING)
     {
     /* close tcp connection */
     tcp_echoclient_connection_close(tpcb, es);
     }
     }
     ret_err = ERR_OK;
     }
     else
     {
     /* nothing to be done */
     tcp_abort(tpcb);
     ret_err = ERR_ABRT;
     }
     return ret_err;
    }
    
    /**
     * @brief This function implements the tcp_sent LwIP callback (called when ACK
     * is received from remote host for sent data) 
     * @param arg: pointer on argument passed to callback
     * @param tcp_pcb: tcp connection control block
     * @param len: length of data sent 
     * @retval err_t: returned error code
     */
    static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
    {
     struct echoclient *es;
    
     LWIP_UNUSED_ARG(len);
    
     es = (struct echoclient *)arg;
     
     if(es->p_tx != NULL)
     {
     /* still got pbufs to send */
     tcp_echoclient_send(tpcb, es);
     }
    
     return ERR_OK;
    }
    
    /**
     * @brief This function is used to close the tcp connection with server
     * @param tpcb: tcp connection control block
     * @param es: pointer on echoclient structure
     * @retval None
     */
    static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es )
    {
     /* remove callbacks */
     tcp_recv(tpcb, NULL);
     tcp_sent(tpcb, NULL);
     tcp_poll(tpcb, NULL,0);
    
     if (es != NULL)
     {
     mem_free(es);
     }
    
     /* close tcp connection */
     tcp_close(tpcb); 
    }
    
    #endif /* LWIP_TCP */
    

     
    Regards 

    1 reply

    STeaAnswer
    ST Employee
    May 31, 2024

    Hello @Ramachandran1992 ,

    After an examination of the attached file, it seems  tcp_server_handle you are implementing is unable to properly allocate a buffer this should be done with the Pbuf_alloc function.
    my recommendation is to take the example we give in the cube Firmware which can be obtained from Github or from the ST website as a reference so the revised version of your tcp_server_raw.c will be as follows :

    /**
     ******************************************************************************
     * @file LwIP/LwIP_TCP_Echo_Client/Src/tcp_echoclient.c
     * @author MCD Application Team
     * @brief tcp echoclient application using LwIP RAW API
     ******************************************************************************
     * @attention
     *
     * Copyright (c) 2017 STMicroelectronics.
     * All rights reserved.
     *
     * This software is licensed under terms that can be found in the LICENSE file
     * in the root directory of this software component.
     * If no LICENSE file comes with this software, it is provided AS-IS.
     *
     ******************************************************************************
     */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "lwip/debug.h"
    #include "lwip/stats.h"
    #include "lwip/tcp.h"
    #include "lwip/memp.h"
    #include <stdio.h>
    #include <string.h>
    
    #if LWIP_TCP
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    u8_t recev_buf[50];
    __IO uint32_t message_count=0;
    
    u8_t data[100];
    
    struct tcp_pcb *echoclient_pcb;
    
    /* ECHO protocol states */
    enum echoclient_states
    {
     ES_NOT_CONNECTED = 0,
     ES_CONNECTED,
     ES_RECEIVED,
     ES_CLOSING,
    };
    
    /* structure to be passed as argument to the tcp callbacks */
    struct echoclient
    {
     enum echoclient_states state; /* connection status */
     struct tcp_pcb *pcb; /* pointer on the current tcp_pcb */
     struct pbuf *p_tx; /* pointer on pbuf to be transmitted */
    };
    
    /* Private function prototypes -----------------------------------------------*/
    static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
    static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es);
    static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb);
    static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
    static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es);
    static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err);
    
    /* Private functions ---------------------------------------------------------*/
    
    
    /**
     * @brief Connects to the TCP echo server
     * @param None
     * @retval None
     */
    void tcp_echoclient_connect(void)
    {
     ip_addr_t DestIPaddr;
     
     /* create new tcp pcb */
     echoclient_pcb = tcp_new();
     
     if (echoclient_pcb != NULL)
     {
     IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
     
     /* connect to destination address/port */
     tcp_connect(echoclient_pcb,&DestIPaddr,DEST_PORT,tcp_echoclient_connected);
     }
    }
    
    /**
     * @brief Function called when TCP connection established
     * @param tpcb: pointer on the connection control block
     * @param err: when connection correctly established err should be ERR_OK 
     * @retval err_t: returned error 
     */
    static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
    {
     struct echoclient *es = NULL;
     
     if (err == ERR_OK) 
     {
     /* allocate structure es to maintain tcp connection information */
     es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));
     
     if (es != NULL)
     {
     es->state = ES_CONNECTED;
     es->pcb = tpcb;
     
     sprintf((char*)data, "sending tcp client message %d", (int)message_count);
     
     /* allocate pbuf */
     es->p_tx = pbuf_alloc(PBUF_TRANSPORT, strlen((char*)data) , PBUF_POOL);
     
     if (es->p_tx)
     { 
     /* copy data to pbuf */
     pbuf_take(es->p_tx, (char*)data, strlen((char*)data));
     
     /* pass newly allocated es structure as argument to tpcb */
     tcp_arg(tpcb, es);
     
     /* initialize LwIP tcp_recv callback function */ 
     tcp_recv(tpcb, tcp_echoclient_recv);
     
     /* initialize LwIP tcp_sent callback function */
     tcp_sent(tpcb, tcp_echoclient_sent);
     
     /* initialize LwIP tcp_poll callback function */
     tcp_poll(tpcb, tcp_echoclient_poll, 1);
     
     /* send data */
     tcp_echoclient_send(tpcb,es);
     
     return ERR_OK;
     }
     }
     else
     {
     /* close connection */
     tcp_echoclient_connection_close(tpcb, es);
     
     /* return memory allocation error */
     return ERR_MEM; 
     }
     }
     else
     {
     /* close connection */
     tcp_echoclient_connection_close(tpcb, es);
     }
     return err;
    }
     
    /**
     * @brief tcp_receiv callback
     * @param arg: argument to be passed to receive callback 
     * @param tpcb: tcp connection control block 
     * @param err: receive error code 
     * @retval err_t: returned error 
     */
    static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
    { 
     struct echoclient *es;
     err_t ret_err; 
    
     LWIP_ASSERT("arg != NULL",arg != NULL);
     
     es = (struct echoclient *)arg;
     
     /* if we receive an empty tcp frame from server => close connection */
     if (p == NULL)
     {
     /* remote host closed connection */
     es->state = ES_CLOSING;
     if(es->p_tx == NULL)
     {
     /* we're done sending, close connection */
     tcp_echoclient_connection_close(tpcb, es);
     }
     else
     { 
     /* send remaining data*/
     tcp_echoclient_send(tpcb, es);
     }
     ret_err = ERR_OK;
     } 
     /* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
     else if(err != ERR_OK)
     {
     /* free received pbuf*/
     if (p != NULL)
     {
     pbuf_free(p);
     }
     ret_err = err;
     }
     else if(es->state == ES_CONNECTED)
     {
     /* increment message count */
     message_count++;
     
     /* Acknowledge data reception */
     tcp_recved(tpcb, p->tot_len); 
     
     pbuf_free(p);
     tcp_echoclient_connection_close(tpcb, es);
     ret_err = ERR_OK;
     }
    
     /* data received when connection already closed */
     else
     {
     /* Acknowledge data reception */
     tcp_recved(tpcb, p->tot_len);
     
     /* free pbuf and do nothing */
     pbuf_free(p);
     ret_err = ERR_OK;
     }
     return ret_err;
    }
    
    /**
     * @brief function used to send data
     * @param tpcb: tcp control block
     * @param es: pointer on structure of type echoclient containing info on data 
     * to be sent
     * @retval None 
     */
    static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es)
    {
     struct pbuf *ptr;
     err_t wr_err = ERR_OK;
     
     while ((wr_err == ERR_OK) &&
     (es->p_tx != NULL) && 
     (es->p_tx->len <= tcp_sndbuf(tpcb)))
     {
     
     /* get pointer on pbuf from es structure */
     ptr = es->p_tx;
    
     /* enqueue data for transmission */
     wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
     
     if (wr_err == ERR_OK)
     { 
     /* continue with next pbuf in chain (if any) */
     es->p_tx = ptr->next;
     
     if(es->p_tx != NULL)
     {
     /* increment reference count for es->p */
     pbuf_ref(es->p_tx);
     }
     
     /* free pbuf: will free pbufs up to es->p (because es->p has a reference count > 0) */
     pbuf_free(ptr);
     }
     else if(wr_err == ERR_MEM)
     {
     /* we are low on memory, try later, defer to poll */
     es->p_tx = ptr;
     }
     else
     {
     /* other problem ?? */
     }
     }
    }
    
    /**
     * @brief This function implements the tcp_poll callback function
     * @param arg: pointer on argument passed to callback
     * @param tpcb: tcp connection control block
     * @retval err_t: error code
     */
    static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb)
    {
     err_t ret_err;
     struct echoclient *es;
    
     es = (struct echoclient*)arg;
     if (es != NULL)
     {
     if (es->p_tx != NULL)
     {
     /* there is a remaining pbuf (chain) , try to send data */
     tcp_echoclient_send(tpcb, es);
     }
     else
     {
     /* no remaining pbuf (chain) */
     if(es->state == ES_CLOSING)
     {
     /* close tcp connection */
     tcp_echoclient_connection_close(tpcb, es);
     }
     }
     ret_err = ERR_OK;
     }
     else
     {
     /* nothing to be done */
     tcp_abort(tpcb);
     ret_err = ERR_ABRT;
     }
     return ret_err;
    }
    
    /**
     * @brief This function implements the tcp_sent LwIP callback (called when ACK
     * is received from remote host for sent data) 
     * @param arg: pointer on argument passed to callback
     * @param tcp_pcb: tcp connection control block
     * @param len: length of data sent 
     * @retval err_t: returned error code
     */
    static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
    {
     struct echoclient *es;
    
     LWIP_UNUSED_ARG(len);
    
     es = (struct echoclient *)arg;
     
     if(es->p_tx != NULL)
     {
     /* still got pbufs to send */
     tcp_echoclient_send(tpcb, es);
     }
    
     return ERR_OK;
    }
    
    /**
     * @brief This function is used to close the tcp connection with server
     * @param tpcb: tcp connection control block
     * @param es: pointer on echoclient structure
     * @retval None
     */
    static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es )
    {
     /* remove callbacks */
     tcp_recv(tpcb, NULL);
     tcp_sent(tpcb, NULL);
     tcp_poll(tpcb, NULL,0);
    
     if (es != NULL)
     {
     mem_free(es);
     }
    
     /* close tcp connection */
     tcp_close(tpcb); 
    }
    
    #endif /* LWIP_TCP */
    

     
    Regards