This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RM57L843: TCP/IP client code does not work

Part Number: RM57L843

Hi,

Customer is trying to modify HDK lwip sample code for TCP/IP client.
The base code is provided from below git (see the original E2E post).
http://git.ti.com/hercules_examples/hercules_examples/trees/master/Application/LwIP

Customer modified below code:
hercules_examples-master\Application\LwIP\v00.04.00\example\hdk\src\lwip_main.c

Modified code is below.

err_t connected(void *arg, struct tcp_pcb *newpcb, err_t err) // err is always ERR_OK。
{
	err = tcp_write(newpcb, "ABCDE", 5, 0);
    if (err != ERR_OK)
	{
		return err;
	}

	err = tcp_output(newpcb);
    if (err != ERR_OK)
	{
		return err;
	}

	return ERR_OK;
}

void EMAC_LwIP_Main (uint8_t * macAddress) {
    unsigned int 	ipAddr;
///    uint8_t 		testChar;
///    struct in_addr 	devIPAddress;
///    err_t udp_error;
    err_t tcp_error;
	u16_t send_bufs;
//u8_t senddat[]={ 1,  2,  3,  4};//"ABCDE";
//s	struct pbuf send_p;
	
	//iommUnlock();
	//iommMuxEnableMdio();
	//iommMuxEnableMii();
	//iommLock();
	sciInit();
	
	/* Enable the interrupt generation in CPSR register */
	IntMasterIRQEnable();
	_enable_FIQ();

	sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
	sciDisplayText(sciREGx, txtTitle, sizeof(txtTitle));
	sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
	sciDisplayText(sciREGx, txtTI, sizeof(txtTI));
	sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
#ifdef __little_endian__        
    sciDisplayText(sciREGx, txtLittleEndian, sizeof(txtLittleEndian));
    sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
#else        
    sciDisplayText(sciREGx, txtBigEndian, sizeof(txtBigEndian));
    sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF)); #endif

	/* Initialze the lwIP library, using DHCP.*/
	sciDisplayText(sciREGx, txtEnetInit, sizeof(txtEnetInit));
///	ipAddr = lwIPInit(0, macAddress, 0, 0, 0, IPADDR_USE_DHCP);
	/* Uncomment the following if you'd like to assign a static IP address. Change address as required, and uncomment the previous statement. */
///	/*
///	uint8 ip_addr[4] = {  44,   2, 168, 192 };
///	uint8 netmask[4] = {   0, 255, 255, 255 };
///	uint8 gateway[4] = { 254,   2, 168, 192 };

/*    IP4_ADDR(&ipaddr, 192, 168,   2,  44);
    IP4_ADDR(&netmask, 255, 255, 255,   0);
    IP4_ADDR(&gateway, 192, 168,   2, 254);
LWIP_PLATFORM_BYTE_SWAP
LWIP_PLATFORM_HTONS()
LWIP_PLATFORM_HTONL()*/
    IP4_ADDR(&ipaddr,   44,   2, 168, 192); // my node ip addr
    IP4_ADDR(&netmask,   0, 255, 255, 255);
    IP4_ADDR(&gateway, 254,   2, 168, 192);
	ipAddr = lwIPInit(0, macAddress,
///			*((uint32_t *)ip_addr),
///			*((uint32_t *)netmask),
///			*((uint32_t *)gateway),
			ipaddr.addr,
			netmask.addr,
			gateway.addr,
			IPADDR_USE_STATIC);///*/
	sciDisplayText(sciREGx, (uint8_t*)"..DONE", sizeof("..DONE"));
	sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
	
	if (0 == ipAddr) {
		sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
		sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
        sciDisplayText(sciREGx, txtErrorInit, sizeof(txtErrorInit));
        sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
        sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
	} else {
#if 0 ///削除
		/* Convert IP Address to string */
		devIPAddress.s_addr = ipAddr;
		txtIPAddrItoA = (uint8_t *)inet_ntoa(devIPAddress);
		LocatorConfig(macAddress, "HDK enet_lwip");
	
		/* Initialize the sample httpd server. */
		sciDisplayText(sciREGx, (uint8_t*)"Starting Web Server", sizeof("Starting Web Server"));
	    httpd_init();
	    sciDisplayText(sciREGx, (uint8_t*)"..DONE", sizeof("..DONE"));
	    sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
	    
	     /* Loop forever.  All the work is done in interrupt handlers. */
	    while(1)
	    {    	
	        sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
	        
	        sciDisplayText(sciREGx, txtTitle, sizeof(txtTitle));
	        sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
	        
	        sciDisplayText(sciREGx, txtTI, sizeof(txtTI));
	        sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
#ifdef __little_endian__        
	        sciDisplayText(sciREGx, txtLittleEndian, sizeof(txtLittleEndian));
	        sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
#else        
	        sciDisplayText(sciREGx, txtBigEndian, sizeof(txtBigEndian));
	        sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF)); #endif
			sciDisplayText(sciREGx, txtIPAddrTxt, sizeof(txtIPAddrTxt));
	        sciDisplayText(sciREGx, txtIPAddrItoA, 16);
			sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
			
			sciDisplayText(sciREGx, txtNote1, sizeof(txtNote1));
			sciDisplayText(sciREGx, txtIPAddrItoA, 16);
			sciDisplayText(sciREGx, txtCRLF, sizeof(txtCRLF));
			
	        
	        /* Before printing the next set, wait for a character on the terminal */
	        sciReceive(sciREGx, 1, &testChar);
	    }
#endif
	    IP4_ADDR(&server,   1,   2, 168, 192); // server ip addr
	    pcbRcv = tcp_new();
	    if (!pcbRcv) {
	        exit(1);
        }
//#if 0 //for client
//	tcp_bind(pcbRcv, IP_ADDR_ANY, rsv_port);
//		tcp_arg(pcbRcv, NULL);
	    tcp_error = tcp_connect(pcbRcv, &server, rsv_port, connected); //connect to the server
	    if (tcp_error != ERR_OK)
	    {
	        exit(1);
	    }
		send_bufs = tcp_sndbuf(pcbRcv);
//		tcp_error = tcp_write(pcbRcv, "ABCDE", 5, 0);
//		tcp_error = tcp_write(pcbRcv, senddat, 2, TCP_WRITE_FLAG_COPY);
/*		tcp_error = tcp_write(pcbRcv, send_p.payload, 2, TCP_WRITE_FLAG_COPY);
	    if (tcp_error != ERR_OK)
	    {
	        exit(1);
	    }

		tcp_error = tcp_output(pcbRcv);
	    if (tcp_error != ERR_OK)
	    {
	        exit(1);
	    }
*/
//#endif

#if 0 //for server
	    tcp_bind(pcbRcv, IP_ADDR_ANY, rsv_port);

		/* we do not need any arguments to callback functions */
//		tcp_arg(pcbRcv, NULL);

		/* listen for connections */
//		pcbRcv = tcp_listen(pcbRcv);
        pcbRcv = tcp_listen_with_backlog(pcbRcv, 2);
		if (!pcbRcv) {
//			xil_printf("Out of memory while tcp_listen\n\r");
//			return -3;
		}

		/* specify callback to use for incoming connections */
		tcp_accept(pcbRcv, accept_callback);
#endif //for server
	    while(1){}
	}
}


Customer tries to connect the device to PC(server), but it cannot connect.
The code is in while(1) loop at the end of EMAC_LwIP_Main().
tcp_connect() returns ERR_OK.

Anything is missing?
It seems the sample code is http. Any initialization for TCP/IP required, etc.?

By the way, the above code works fine, if it is configured as TCP/IP server (by commenting out "#if 0 //for server").

Thanks and regards,
Koichiro Tashiro

  • Hi Koichiro-san,

    To be honest, I am not an Ethernet person. I just read the code, it looks fine to me. Are the "192.168.2.1" and rev_port correct for your server? When the connection is established, the call-back function connected() should be called. If adding a breakpoint at  err = tcp_output(newpcb); what is the return value?

  • Hi QJ,

    Are the "192.168.2.1" and rev_port correct for your server?

    Yes. It is correct. Customer confirmed PC(server) to PC(client) connection works fine.

    When the connection is established, the call-back function connected() should be called. If adding a breakpoint at  err = tcp_output(newpcb); what is the return value?

    In fact, the call-back function connected() is not called. This is the problem.
    Customer tried to add a breakpoint at the top of connected() function  
    "
    err = tcp_write(newpcb, "ABCDE", 5, 0);"
    But code does not stop here. So the return value cannot be confirmed.

    Customer has a few additional questions.
    1) We do not need specific initialization to use TCP/IP?
    (No need to modify lwipopts.h ?)

    2) Do we have document for lwIP-1.4.1?
    Customer checked documents under below folder.
    \hercules_examples-master\Application\LwIP\v00.04.00\docs
    But more detailed information is needed, something like;
    - What each lwipopts.h definition means?
    - What configurations are needed to use client / TCP/IP?

    Thanks and regards,
    Koichiro Tashiro

  • 1) We do not need specific initialization to use TCP/IP?

    TCP is enabled in lwipopts.h:

    #define LWIP_TCP                        1

    2) Do we have document for lwIP-1.4.1?

    The lwipopts.h allows user to configure the stack and all its modules. The user does not need to define all the LwIP options: if an option is not defined, a default value defined in opt.h file is used. Therefore, lwipopts.h provides a way to override much of the lwIP behavior.

    LWIP_TCP should be enabled. You can use the default TCP settings, for example TCP_MSS

    TCP_MSS: TCP maximum segment size

    TCP_SND_BUF: TCP send buffer space for a connection.

    MEMP_NUM_TCP_PCB: Total number of TCP PCB structures

    https://lwip.fandom.com/wiki/LwIP_Wiki

    https://lwip.fandom.com/wiki/Tuning_TCP