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.

[参考译文] AM2434:icssg lwip 演示在一个 UDP 发送周期内、进入 UDP 发送时分配的 pbuf 地址在 UDP 发送结束后的 SYS_ARCH_PROTECT 之后发生了更改

Guru**** 1785650 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1219740/am2434-icssg-lwip-demo-in-one-udp-send-cycle-the-pbuf-address-malloced-when-entering-udp-send-has-been-changed-after-sys_arch_protect-in-the-end-of-udp-send

器件型号:AM2434

尊敬的团队:

我们做以下事情:

基于 AM24的 AM243x_MCU_SDK8.4.0.17中的1.use icssg lwip 演示。

2.delete task sys_threade_new ("UDP Iperf"、start_application、NULL、DEFAULT_THREAD_STACKSIZE、 DEFAULT_THREAD_PRIO);  

3.创建 UDP 发送任务,代码如下,发送 buf 为1024字节。

static void udp_task ( void* arg )
{

	int  ret,  sockfd = -1;
	int udp_port = 10250;
	const int reuse = 1;
	struct sockaddr_in rmt_addr, bod_addr;
	uint32_t id  = *( uint32_t* )arg;
	DebugP_log ( "id=%u\r\n",id );

	u32_t len = sizeof ( rmt_addr );
	int i;
	ip_addr_t ipaddr,ipaddr1;
	ssize_t recvnum=0;
	ssize_t sendnum=0;
	int32_t status;
	uint32_t cnt = 0;
	uint16_t count = 1024;
	uint32_t sendcnt = 0;
	uint32_t recvcnt = 0;
	uint64_t timestart = 0;
	uint64_t timeelapse = 0;
	uint64_t time = 0,time1 = 0;
	uint32_t val;

	struct timeval tv;

	IP4_ADDR ( &ipaddr, 192, 168, 2, 100 );
	IP4_ADDR ( &ipaddr1, 192, 168, 2, 220 );

	/* set up address to connect to */
	rmt_addr.sin_family = AF_INET;
	rmt_addr.sin_port = htons ( udp_port );
	rmt_addr.sin_addr.s_addr = ipaddr.addr;

	bod_addr.sin_family = AF_INET;
	bod_addr.sin_port = htons ( udp_port );
	bod_addr.sin_addr.s_addr = ipaddr1.addr;//htons ( INADDR_ANY );

	//while ( 1 )
	{
		do
		{
		   net_is_linked=get_enet_link(id);
			ClockP_usleep ( 100000 );
		}
		while ( !net_is_linked );
		DebugP_log ( "is linked\r\n" );

		/* create the socket */
		sockfd = socket ( AF_INET, SOCK_DGRAM, 0 );
		if ( sockfd < 0 )
		{
		    DebugP_log ( "fail to create sockopt\r\n" );
		}

		tv.tv_sec = 0;
		tv.tv_usec = 30000;
		ret = setsockopt ( sockfd, SOL_SOCKET, SO_RCVTIMEO, ( void* ) &tv, sizeof ( tv ) );
		if ( ret < 0 )
		{
			DebugP_log ( "fail to setsockopt\r\n" );
			lwip_close ( sockfd );
			sockfd = -1;
			//continue;
			//return ERROR;
		}

		ret = bind ( sockfd, ( struct sockaddr* ) &bod_addr, sizeof ( bod_addr ) );

		if ( ret < 0 )
		{
			lwip_close ( sockfd );
			sockfd = -1;
			DebugP_log ( "fail to bind sockopt\r\n" );
		}

        send_buf[0] = id;
        send_buf[1] = cnt%256;
        for (  i=2; i<count-1; i++ )
        {
            send_buf[i]=i&0xff;
        }
        send_buf[count-1]=0x5A;


		timestart = ClockP_getTimeUsec();
		/* reveive packets from rmt_addr, and limit a reception to MAX_BUF_SIZE bytes */
		//recvnum = recvfrom ( sockfd, buf, MAX_BUF_SIZE, 0, ( struct sockaddr* ) &rmt_addr, &len );

		while (( -1 != sockfd && net_is_linked ) && ( timeelapse < (60*1000000) ))
		{
			/* send packets to rmt_addr */
			sendnum=sendto ( sockfd, send_buf, sizeof (send_buf), 0, ( struct sockaddr* ) &rmt_addr, len );
			if(sendnum == sizeof (send_buf))
			{
//			    DebugP_log ( " sendbuf[0]-sendbuf[4] %d %d %d %d %d \r\n",send_buf[0],send_buf[1],send_buf[2],send_buf[3],send_buf[4]);
			    sendcnt++;
			    send_buf[1] = sendcnt%256;
			}
			else
			    DebugP_log ( "ERROR: send count %d sendnum != sizeof ( buf ),no need to recv\r\n",sendcnt);

			 timeelapse = ClockP_getTimeUsec()-timestart;
		}
		DebugP_log ( "total cycle %d,sendcount %d,recvcount %d\r\n",cnt,sendcnt,recvcnt);
		DebugP_log ( "1min UDP pingpong test end \r\n");
		lwip_close ( sockfd );
	}
}

 

4.然后我们在发送特定 计数后发现(发送37次将发送失败的 MEMP_NUM_PBUF=16、LWIP_malloc_MEMPOOL(201568 ))、UDP sendto 将失败。就像发送池已满一样。

5.因此我们更改了 lwip 栈池大小(发送 187 次将发送失败的 MEMP_NUM_PBUF=100、LWIP_malloc_MEMPOOL (100、 1568))。

6、我知道一个内核运行一个 UDP 发送任务、不可能有上述现象、所以我们用 JTAG 调试、每次 UDP 发送处理之后我们都发现:

堆栈将 malloc 1个 pbuf by pbuf_alloc  (类型为 PBUF_RAM (大小由 LWIP_malloc_MEMPOOL 定义、数字由 MEMP_NUM_PBUF 定义))

UDP 发送后,堆栈将释放 上面步骤中分配的 pbuf 地址。我们发现这两个地址不是同一个,并且 在输入 pbuf_free() 函数()断点后,这个地址就变成了一个异常的 pbuf 池(类型是 PBUF_POOL )地址。

因此、在发送特定的时间后无法再发送、导致发送 pbuf 已满。  

link.cmd :pbuf 保存在 BSS (MSRAM)中、我们更改为 ddr.现象是相同的、在一定的时间成功后、发送失败、并且 pbuf 地址在 输入 pbuf_free 后更改。

谢谢。

jimin.li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Jimin:

    我们已经开始调查该问题、让我检查并返回。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Jimin Li:

    如果您回答几个问题、可以帮助我更好地理解问题。

    问题1: 类型 netconn_send ()和 netconn_free ()函数 套接字.c ?. " 缓冲器 "传入了 netconn_send ()和 netconn_free ()为类型 PBUF_POOL PBUF_RAM


    问题2. 您是否在使用 udp_sendto_if_src_chksum ()函数 udp.c?  'P' (pbuf)是一种类型 PBUF_RAM ,在同一函数中再次被释放。

    此致、

    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shaunak Deshpande:

    问题1:是,我们使用  netconn_send ()和  netconn_free ()函数  套接字

    缓冲器   传入  netconn_send() 是 PBUF_RAM 作为 netbuf_alloc()点, 但是、在 netconn_free ()  已更改(我们检查此内容 缓冲器 指定 pbuf_free() 传递函数)更新为  PBUF_POOL。

    问题2:是的、我们使用  udp_sendto_if_src_chksum() 传递函数  Udp.c.

     

    谢谢。

    jimin.li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Jimin:

    我想了解您尝试通过使用 Netconn API 和 UDP.c 的 API 实现或实现的确切功能

    TI 不建议使用 Netconn API。  

    我还建议使用  Enet_cpsw_udpclient  以 UDP 乒乓示例为例。

    Br、

    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shaunak Deshpande:

    (__LW_AT__发现原因是另一台)PC 与 AM243(客户主板基本 AM2434-EVM)连接的是一直发送 UDP 包(类型是 PBUF_POOL )至 AM24、因此 我之前的说明是不可更正的。

    缓冲器   传入  netconn_send() 是 PBUF_RAM 作为 netbuf_alloc()点, 但是、在 netconn_free ()  已更改(我们检查此内容 缓冲器 指定 pbuf_free() 传递函数)更新为  PBUF_POOL。 [/报价]

    但是、在 PC 端停止 UDP 发送、AM24仍然发送特定的时间后发送失败。  

    然后、我们做两件事情:

    1.use AM24-LP 运行该演示:

    可以发送成功、而不会出现"发送特定时间后发送失败"现象。

    在一个发送过程中、pbuf 分配方式 netbuf_alloc ()  之前的发送与相同  netconn_free () 发送后

    2.use 客户电路板(base AM2434-EVM)运行该演示:

    仍然存在"发送特定时间后发送失败" 现象。

    在一个发送过程中、pbuf 分配方式  netbuf_alloc ()  之前的发送与相同  netconn_free () 发送后

    你有什么想法吗?

    谢谢。

    jimin.li  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Jimin Li:

    对于开箱即用示例、AM243x-LP 和 AM243x-EVM 的行为应相同。 为了帮助我进一步分析并在最后重现此问题、您能否共享您的示例的 zip 文件( MCU_SDK/examples/networking/lwip/ Enet_lwip_icssg)?

    此外、当您在 PC 端禁用 UDP 发送的情况下测试上述内容时、PBUFS 会保存在 MSRAM 或 DDR (对于 AM243x-EVM)中? (因为在您的原始问题中、您提到您将其更改为 DDR)。

    谢谢。

    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的  Shaunak Deshpande:

    很抱歉最近更新导致我们 OOO 一周。

    我们 以客户请求的身份配置 lwip icssg 双 Mac 模式、因此 SDK 已被大幅更改。以下代码可能会有所帮助。

    我们现在将 PBUFS 保存在 MSRAM 中。出于调试目的、我们还尝试将它们保存在 DDR 中、发现无论它们保存在 MSRAM 或 DDR 中、这种现象都是相同的。

    此外,在 PC 端禁用 UDP 发送的情况下测试上述内容时,PBUFS 将保存在 MSRAM 或 DDR (对于 AM243x-EVM)中? (因为您在原始问题中提到您将其更改为 DDR)。

    此外、如果此池中的 config total num 为10 (LWIP_malloc_MEMPOOL (101568))。我们的客户板显示了可以使用所有 PBREF、然后发送失败导致堆栈无法 分配新的 PBUF。 但在 AM243-LP 板上,在发送5次后,PBUs 将处于空闲状态,并在下一个发送周期中重新设置。

    谢谢。

    jimin.li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Jimin:

    您能否重新检查您共享的 example.rar 文件、似乎缺少一些文件、这使我无法在本地构建您的示例(对于 am243x-evm、为 example.syscfg)。

    此致、

    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的  Shaunak Deshpande:

    RAR 文件全部为示例。已在我们的客户板中删除 syscfg 文件。

    现在、我们可以在客户电路板上成功运行 UDP 发送测试(数据包长度为1024Byte)。但项目处于调试模式。  如果使用释放模式、 在发送特定 计数之后(发送37次将发送失败 MEMP_NUM_PBUF=16、LWIP_malloc_MEMPOOL (20、 1568))、UDP sendto 将失败。

    此外、如果数据包长度为20Byte、则无论工程模式是调试还是释放、都不会出现发送失败现象。请按下图显示详细信息:

    这让我由此得出了有关调试和发布条件的结论。

    谢谢。

    jimin.li  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Jimin.Li:

    我看到你已经在 SDK 中针对 ICSSG 上的双 Mac 大幅改变了 Enet-LLD。 我们的8.4SDK 不支持此功能。 8.6 SDK 支持 ICSSG 上的 Dual Mac,该 SDK 将在未来2周内于 TI.com 上推出。 如果您可以迁移到8.6 SDK 并使用双核 Mac 功能,那就更好了。

    我已经在8.4SDK 上验证了开箱即用 enet_lwip_icssg 示例。 我添加了一个与您类似的 UDP 服务器任务(如下所示)、并测试了 am243x 是否在 SDK 上连续发送 UDP 数据包  8.4.0.17。(这在 enet_lwip_icssg 示例中写入、以代替 udp_iperf)。 任务等待第一个接收到的数据 包、并连续发回该数据包 、直到超时。  

    这里我没有看到任何问题、我已尝试使用20字节和1024字节、数据包由 am243x DUT 连续发送。 附件是 Wireshark 上的屏幕截图、其中10.24.69.20是 am243x 的 IP 地址、我将在 发布模式和调试模式下连续接收数据包(超过10k 个数据包)。  

    #define UTILS_ALIGN(x,align)  ((((x) + ((align) - 1))/(align)) * (align))
    void udp_task_0 ( void* arg )
    {
        err_t err;
        int sock;
        struct sockaddr_in socketAddr;
        struct timeval tv;
        char recv_buf[UTILS_ALIGN(UDP_RECV_BUFSIZE, 32)] __attribute__ ((aligned(32)));
        struct sockaddr_in from = { 0 };
        socklen_t fromlen = sizeof(from);
        int32_t count;
        int32_t sendnum;
        uint64_t timestart = 0;
        uint64_t timeelapse = 0;
    
        memset(&socketAddr, 0, sizeof(socketAddr));
        socketAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        socketAddr.sin_family = AF_INET;
        socketAddr.sin_port = htons(10255);
        if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        {
            DebugP_log("UDP server: Error creating Socket\r\r\n");
            return;
        }
    
        tv.tv_sec = 0;
        tv.tv_usec = 30000;
        err = setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, ( void* ) &tv, sizeof ( tv ) );
        if (err != ERR_OK)
        {
            DebugP_log ( "socket fail to setsockopt\r\n");
            lwip_close ( sock );
            sock = -1;
        }
        err = bind (sock, (struct sockaddr*) &socketAddr, sizeof (socketAddr));;
        if (err != ERR_OK)
        {
            DebugP_log("UDP server: Error on bind: %d\r\r\n", err);
            close(sock);
            return;
        }
        while (1)
        {
            count = lwip_recvfrom(sock, recv_buf, UDP_RECV_BUFSIZE, 0, (struct sockaddr*) &from, &fromlen);
            if (count <= 0)
                continue;
    
            DebugP_log("Packet recieved \r\n\r");
            count = (count >= UDP_RECV_BUFSIZE) ? UDP_RECV_BUFSIZE - 1 : count;
            recv_buf[count] = '\0';
            /*CacheP_wbInv(recv_buf, sizeof(recv_buf), CacheP_TYPE_ALLD);*/
            DebugP_log("Client: %s\r\n", recv_buf);
            timeelapse = 0U;
            timestart = ClockP_getTimeUsec();
            while( timeelapse < (60*1000000) )
            {
                sendnum = sendto(sock, recv_buf, count, 0, (struct sockaddr*) &from, fromlen);
                if (sendnum != count)
                {
                    DebugP_log("Error in write\r\n\r");
                }
                else
                {
                    DebugP_log("Echo pkt completed\r\n\r");
                }
                timeelapse = ClockP_getTimeUsec()-timestart;
                DebugP_log("timeelapsed to send %d \r\n\r", timeelapse);
            }
            ClockP_sleep(2);
        }
    }
    




    谢谢。

    Susheel。