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.

[参考译文] TMS320F28388D:由于 LwIP echo TCP 服务器、我必须重新启动电路板

Guru**** 2531550 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1115080/tms320f28388d-i-have-to-reboot-my-board-because-of-lwip-echo-tcp-server

器件型号:TMS320F28388D

我使用 SPI、ADC、IPC、以太网等制作了具有 F28388的电路板

我使用 TCP 服务器与 PC MATLAB 程序通信。

似乎工作正常、但以太网在 大约3小时后断开。

软件复位无法修复我的以太网。 只能重新启动。 (电源必须关闭。)

但 CM4始终运行良好、除了以太网、它可以从内核1接收 IPC 数据。它似乎可以处理 IPC 中断。

我通过 JTAG 调试它。我只使用 Lwip echo 示例。

我找到了以下内容  

 1.运行良好时,它在 while 循环中执行工作,但在通信中断后,它仅在 [ interrupt void ethernet_genericisrCustom (void)]中执行  

因此 、genericISRCustomcount 会重复递增。

因此 我将 while 循环中的代码插入 getnericISRCustom。 它似乎也起作用,但运行时间是不规则的。

 而 genericISRCustomROVcount 和 genericISRCustomRIcount  也增长良好。

3. Ethernet_rxInterruptCount 和 Ethernet_txInterruptCount 增加得很好。

我假设内存问题、因为只有硬件复位工作正常。 软件暂停无法正常工作。

有人可以帮助我吗?

如果需要、我可以上传我的主代码 cm4。

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

    您好!  

    请参考此主题  

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1074652/tms320f28388d-lwip-webserver-example-memory-errors-due-to-ethernet-descriptors-queue-management/4030084?tisearch=e2e-sitesearch&keymatch=lwip#4030084

    此问题可能是由于内存泄漏引起的。  请尝试上述主题中提到的修复程序、看看它是否有用。

    此致

    Siddharth

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

    大家好、感谢您让我知道参考资料。

    我阅读了其中的所有答复。

    然后,我只需 在 driverlib_cm 中编辑以太网.c 即可?

    使用假定的代码似乎可以解决问题、但我无法重建 driverlib_cm

    我使用[从文件系统打开项目文件]打开了 C2000的 driverlib_cm。 但我无法执行[clean project]和[build project]。

    我无法检查我是否正确编辑了代码。

    此致

    Subeen

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

    Subeen、  

    您能否发布您使用更新的代码获取的编译错误?

    此致

    Siddharth

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

    你(们)好

    在更新 driverlib 中的代码之前、我必须知道如何重建 driverlib。

    发生任何错误、只是我无法编译项目文件夹。  

    我单击了"Build Project"和"Clean Project"、但没有发生任何情况。  

    我认为 CCS 不会将 driverlib 文件夹识别为 CCS 项目。

    我无法读取控制台窗口中的任何行。  

    即使我清理了项目、输出文件也不会消失。

    此致

    Subeen

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

    Subeen、

    您能否分享您看到的错误的屏幕截图?

    您应该能够将   driverlib_cm 项目导入到 CCS 中、并且编译该项目时不会出现任何问题。

    此致

    Siddharth

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

    最后、我将 ethernet.h 和 Ethernet.c 等 SoM 源文件复制到我的项目中、并在参考线程中应用新代码。

    但有一些拼写错误的单词。

    这似乎需要 一些时间。

    我将在测试3~5小时后再次回复。  

    感谢您的反馈。

    此致

    Subeen。

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

    Subeen、

    好的、请告诉我您的观察结果。

    此致

    Siddharth

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

    我复制了以 太网.c 的 JK f2838xif.c 和 void Ethernet_removePacketsFromTxQueue  

    但没有显著的结果。

    以太网在我启动它大约3小时后停止。

    我是否错过了任何内容?

    我很困惑我是否 应该 编辑 FS.C.

    我将分享我的编辑方式。  

    *我使用的是 C2000 3.04 版本  

    void ethernet_removePacketsFromTxQueue of ethernet.c  

    #if 0
    // 0 : code from e2e
    // 1 : origin code from c2000
    
    //original
    void Ethernet_removePacketsFromTxQueue
                                        (Ethernet_DescCh *channelDescPtr,
                                        Ethernet_CompletionMode earlyFlag)
    {
        Ethernet_Pkt_Desc *pktPtr = NULL;
        Ethernet_HW_descriptor *descRead, *newDescRead;
    
        //
        //we now own the packet meaning its been transferred to the port
        //
        pktPtr = Ethernet_performPopOnPacketQueue(&channelDescPtr->descQueue);
        if(0U != pktPtr)
        {
            pktPtr->flags |= ETHERNET_INTERRUPT_FLAG_TRANSMIT;
            if(ETHERNET_COMPLETION_EARLY == earlyFlag )
            {
                pktPtr->flags = ETHERNET_INTERRUPT_FLAG_EARLY;
            }
    
            descRead = &channelDescPtr->descFirst[channelDescPtr->indexRead];
            //
            //   Timestamp is not written back on context descriptors, so skip
            //until we have a non-context transmit descriptor
            //
            while((descRead->des3 & ETHERNET_PKT_EXTENDED_FLAG_CTXT) != 0)
            {
                channelDescPtr->indexRead = (channelDescPtr->indexRead + 1U) %
                                            channelDescPtr->descMax;
                descRead = &channelDescPtr->descFirst[channelDescPtr->indexRead];
            }
            newDescRead = descRead;
    
            do {
                //
                // Capture the timestamp if "last descriptor" and "timestamp
                // captured" bit is set in the descriptor.
                //
                if((ETHERNET_TX_DESC_LAST_DESC ==
                    (descRead->des3 & ETHERNET_TX_DESC_LAST_DESC)) &&
                   (ETHERNET_TX_DESC_TTSS ==
                    (descRead->des3 & ETHERNET_TX_DESC_TTSS)))
                {
                    pktPtr->timeStampLow = descRead->des0;
                    pktPtr->timeStampHigh = descRead->des1;
                }
    
                //
                // Save the descriptor which will be checked for condition
                // "whether this is the last sengment of the packet" at the
                // end of this do while loop.
                //
                descRead = newDescRead;
                (void)((channelDescPtr->devicePtr->initConfig.pfcbFreePacket)
                       (channelDescPtr->devicePtr->handleApplication[0U],
                        pktPtr));
                channelDescPtr->descCount--;
                if(channelDescPtr->indexRead == channelDescPtr->indexLast)
                {
                  channelDescPtr->indexRead = channelDescPtr->indexFirst;
                }
                else
                {
                  channelDescPtr->indexRead = channelDescPtr->indexRead + 1U ;
                }
    
                //
                // Fetch the nest descriptor from the descriptor array
                //
                newDescRead = &channelDescPtr->descFirst[channelDescPtr->indexRead];
    
                //
                //we now own the packet meaning its been transferred to the port
                //
                pktPtr = Ethernet_performPopOnPacketQueue(
                                                    &channelDescPtr->descQueue);
                if(0U != pktPtr)
                {
                    pktPtr->flags |= ETHERNET_INTERRUPT_FLAG_TRANSMIT;
                    if(ETHERNET_COMPLETION_EARLY == earlyFlag )
                    {
                        pktPtr->flags = ETHERNET_INTERRUPT_FLAG_EARLY;
                    }
                }
            //
            // Need to clear the desc array for all the packets until
            // the last packet segment is encountered, so repeat.
            //
           }while(ETHERNET_TX_DESC_LAST_DESC !=
                   (descRead->des3 & ETHERNET_TX_DESC_LAST_DESC));
        }
    
        channelDescPtr->dmaInProgress = 0U;
        //
        //Try to post any waiting TX packets
        //
        if((0U != channelDescPtr->waitQueue.count) &&
            (channelDescPtr->dmaInProgress == 0U))
        {
            Ethernet_addPacketsIntoTxQueue(channelDescPtr);
        }
    }
    
    
    
    #else
    
    //from e2e
    void Ethernet_removePacketsFromTxQueue
                                        (Ethernet_DescCh *channelDescPtr,
                                        Ethernet_CompletionMode earlyFlag)
    {
        Ethernet_Pkt_Desc *pktPtr = NULL;
        Ethernet_HW_descriptor *descRead, *newDescRead;
    
        //
        //we now own the packet meaning its been transferred to the port
        //
    
        while(0U != Ethernet_returnTopOfPacketQueue(&channelDescPtr->descQueue))
        {
            newDescRead = &channelDescPtr->descFirst[channelDescPtr->indexRead];
            //
            // Timestamp is not written back on context descriptors, so skip
            //until we have a non-context transmit descriptor
            //
            while((newDescRead->des3 & ETHERNET_PKT_EXTENDED_FLAG_CTXT) != 0)
            {
                channelDescPtr->indexRead = (channelDescPtr->indexRead + 1U) %
                channelDescPtr->descMax;
                newDescRead = &channelDescPtr->descFirst[channelDescPtr->indexRead];
            }
    
            do {
                descRead = newDescRead;
                //
                //we now own the packet meaning its been transferred to the port
                //
                pktPtr = Ethernet_performPopOnPacketQueue(&channelDescPtr->descQueue);
                if(0U != pktPtr)
                {
                    pktPtr->flags |= ETHERNET_INTERRUPT_FLAG_TRANSMIT;
                    if(ETHERNET_COMPLETION_EARLY == earlyFlag )
                    {
                        pktPtr->flags |= ETHERNET_INTERRUPT_FLAG_EARLY;
                    }
                }
                //
                // Capture the timestamp if "last descriptor" and "timestamp
                // captured" bit is set in the descriptor.
                //
                if((ETHERNET_TX_DESC_LAST_DESC ==
                    (descRead->des3 & ETHERNET_TX_DESC_LAST_DESC)) &&
                    (ETHERNET_TX_DESC_TTSS ==
                    (descRead->des3 & ETHERNET_TX_DESC_TTSS)))
                {
                    pktPtr->timeStampLow = descRead->des0;
                    pktPtr->timeStampHigh = descRead->des1;
                }
    
                //
                // Save the descriptor which will be checked for condition
                // "whether this is the last sengment of the packet" at the
                // end of this do while loop.
                //
                (void)((channelDescPtr->devicePtr->initConfig.pfcbFreePacket)
                    (channelDescPtr->devicePtr->handleApplication[0U],
                    pktPtr));
                channelDescPtr->descCount--;
                if(channelDescPtr->indexRead == channelDescPtr->indexLast)
                {
                    channelDescPtr->indexRead = channelDescPtr->indexFirst;
                }
                else
                {
                    channelDescPtr->indexRead = channelDescPtr->indexRead + 1U ;
                }
    
                //
                // Fetch the nest descriptor from the descriptor array
                //
                newDescRead = &channelDescPtr->descFirst[channelDescPtr->indexRead];
                //
                // Need to clear the desc array for all the packets until
                // the last packet segment is encountered, so repeat.
                //
                }while(ETHERNET_TX_DESC_LAST_DESC !=
                    (descRead->des3 & ETHERNET_TX_DESC_LAST_DESC));
        }
    
        channelDescPtr->dmaInProgress = 0U;
        //
        //Try to post any waiting TX packets
        //
        if((0U != channelDescPtr->waitQueue.count) &&
            (channelDescPtr->dmaInProgress == 0U))
        {
            Ethernet_addPacketsIntoTxQueue(channelDescPtr);
        }
    }
    
    
    #endif

    fs.c (未编辑任何内容)

    /*
     * Copyright (c) 2001-2003 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>
     *
     */
    
    #include "lwip/mem.h"
    #include "lwip/apps/httpd_opts.h"
    #include "lwip/def.h"
    #include "lwip/apps/fs.h"
    #include <string.h>
    #include "utils/ustdlib.h"
    
    #include HTTPD_FSDATA_FILE
    
    /*-----------------------------------------------------------------------------------*/
    
    #if LWIP_HTTPD_CUSTOM_FILES
    int fs_open_custom(struct fs_file *file, const char *name);
    void fs_close_custom(struct fs_file *file);
    #if LWIP_HTTPD_FS_ASYNC_READ
    u8_t fs_canread_custom(struct fs_file *file);
    u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
    int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg);
    #else /* LWIP_HTTPD_FS_ASYNC_READ */
    int fs_read_custom(struct fs_file *file, char *buffer, int count);
    #endif /* LWIP_HTTPD_FS_ASYNC_READ */
    #endif /* LWIP_HTTPD_CUSTOM_FILES */
    
    unsigned int httpHit = 0;
    extern void(*ledtoggleFuncPtr)(void);
    /*-----------------------------------------------------------------------------------*/
    err_t
    fs_open(struct fs_file *file, const char *name)
    {
      const struct fsdata_file *f;
    
      if ((file == NULL) || (name == NULL)) {
        return ERR_ARG;
      }
    
    #if LWIP_HTTPD_CUSTOM_FILES
      if (fs_open_custom(file, name)) {
        file->is_custom_file = 1;
        return ERR_OK;
      }
      file->is_custom_file = 0;
    #endif /* LWIP_HTTPD_CUSTOM_FILES */
      /*
       * This is a placeholder where custom functions can be executed based on the
       * params received in the url from the http client.
       */
      if(!strncmp(name, "/param", 6))
      {
          static char pcBuf[10];
          usnprintf(pcBuf, 10, "%d", httpHit);
          httpHit++;
    
         //
         // Call the toggle LED function
         //
         (*ledtoggleFuncPtr)();
    
         //
         // Compose the file data to be returned
         //
    
          file->data = pcBuf;
          file->len = strlen(pcBuf);
          file->index = file->len;
          file->pextension = NULL;
          return ERR_OK;
      }
        /*
         * If no params are received, we check which file the client has requested
         * by iterating through the filesystem we created.
         */
      else
      {
          for (f = FS_ROOT; f != NULL; f = f->next) {
            if (!strcmp(name, (const char *)f->name)) {
              file->data = (const char *)f->data;
              file->len = f->len;
              file->index = f->len;
              file->pextension = NULL;
              file->flags = f->flags;
        #if HTTPD_PRECALCULATED_CHECKSUM
              file->chksum_count = f->chksum_count;
              file->chksum = f->chksum;
        #endif /* HTTPD_PRECALCULATED_CHECKSUM */
        #if LWIP_HTTPD_FILE_STATE
              file->state = fs_state_init(file, name);
        #endif /* #if LWIP_HTTPD_FILE_STATE */
              return ERR_OK;
            }
          }
        }
      /* file not found */
      return ERR_VAL;
    }
    
    /*-----------------------------------------------------------------------------------*/
    void
    fs_close(struct fs_file *file)
    {
    #if LWIP_HTTPD_CUSTOM_FILES
      if (file->is_custom_file) {
        fs_close_custom(file);
      }
    #endif /* LWIP_HTTPD_CUSTOM_FILES */
    #if LWIP_HTTPD_FILE_STATE
      fs_state_free(file, file->state);
    #endif /* #if LWIP_HTTPD_FILE_STATE */
        //LWIP_UNUSED_ARG(file);
        //
        // Free the main psFile system object.
        //
        mem_free(file);
    }
    
    //*****************************************************************************
    //
    // Read the next chunk of data from the file.  Return the iCount of data
    // that was read.  Return 0 if no data is currently available.  Return
    // a -1 if at the end of file.
    //
    //*****************************************************************************
    int
    fs_read(struct fs_file *psFile, char *pcBuffer, int iCount)
    {
        int iAvailable;
    
        //
        // Check to see if a command (pextension = 1).
        //
        if(psFile->pextension == (void *)1)
        {
            //
            // Nothing to do for this file type.
            //
            psFile->pextension = NULL;
            return(-1);
        }
    
        //
        // Check to see if more data is available.
        //
        if(psFile->len == psFile->index)
        {
            //
            // There is no remaining data.  Return a -1 for EOF indication.
            //
            return(-1);
        }
    
        //
        // Determine how much data we can copy.  The minimum of the 'iCount'
        // parameter or the available data in the file system buffer.
        //
        iAvailable = psFile->len - psFile->index;
        if(iAvailable > iCount)
        {
            iAvailable = iCount;
        }
    
        //
        // Copy the data.
        //
        memcpy(pcBuffer, psFile->data + iAvailable, iAvailable);
        psFile->index += iAvailable;
    
        //
        // Return the count of data that we copied.
        //
        return(iAvailable);
    }
    
    /*-----------------------------------------------------------------------------------*/
    #if LWIP_HTTPD_DYNAMIC_FILE_READ
    #if LWIP_HTTPD_FS_ASYNC_READ
    int
    fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg)
    #else /* LWIP_HTTPD_FS_ASYNC_READ */
    int
    fs_read(struct fs_file *file, char *buffer, int count)
    #endif /* LWIP_HTTPD_FS_ASYNC_READ */
    {
      int read;
      if (file->index == file->len) {
        return FS_READ_EOF;
      }
    #if LWIP_HTTPD_FS_ASYNC_READ
      LWIP_UNUSED_ARG(callback_fn);
      LWIP_UNUSED_ARG(callback_arg);
    #endif /* LWIP_HTTPD_FS_ASYNC_READ */
    #if LWIP_HTTPD_CUSTOM_FILES
      if (file->is_custom_file) {
    #if LWIP_HTTPD_FS_ASYNC_READ
        return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg);
    #else /* LWIP_HTTPD_FS_ASYNC_READ */
        return fs_read_custom(file, buffer, count);
    #endif /* LWIP_HTTPD_FS_ASYNC_READ */
      }
    #endif /* LWIP_HTTPD_CUSTOM_FILES */
    
      read = file->len - file->index;
      if (read > count) {
        read = count;
      }
    
      MEMCPY(buffer, (file->data + file->index), read);
      file->index += read;
    
      return (read);
    }
    #endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
    /*-----------------------------------------------------------------------------------*/
    #if LWIP_HTTPD_FS_ASYNC_READ
    int
    fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg)
    {
      if (file != NULL) {
    #if LWIP_HTTPD_FS_ASYNC_READ
    #if LWIP_HTTPD_CUSTOM_FILES
        if (!fs_canread_custom(file)) {
          if (fs_wait_read_custom(file, callback_fn, callback_arg)) {
            return 0;
          }
        }
    #else /* LWIP_HTTPD_CUSTOM_FILES */
        LWIP_UNUSED_ARG(callback_fn);
        LWIP_UNUSED_ARG(callback_arg);
    #endif /* LWIP_HTTPD_CUSTOM_FILES */
    #endif /* LWIP_HTTPD_FS_ASYNC_READ */
      }
      return 1;
    }
    #endif /* LWIP_HTTPD_FS_ASYNC_READ */
    /*-----------------------------------------------------------------------------------*/
    int
    fs_bytes_left(struct fs_file *file)
    {
      return file->len - file->index;
    }
    

    f2838xif.c

    //###########################################################################
    //
    // FILE:   f2838xif.c
    //
    // TITLE:  F2838x interface port file.
    //
    //###########################################################################
    // $TI Release:   $
    // $Release Date:   $
    // $Copyright:
    // Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.co/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   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.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "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 COPYRIGHT
    // OWNER OR CONTRIBUTORS 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.
    // $
    //###########################################################################
    
    /**
     * Copyright (c) 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>
     *
     */
    
    /**
     * Copyright (c) 2018 Texas Instruments Incorporated
     *
     * This file is dervied from the ``ethernetif.c'' skeleton Ethernet network
     * interface driver for lwIP.
     *
     */
    
    #include <string.h>
    /**
     * lwIP specific header files
     */
    #include "lwip/opt.h"
    #include "lwip/def.h"
    #include "lwip/mem.h"
    #include "lwip/pbuf.h"
    #include "lwip/sys.h"
    #include <lwip/stats.h>
    #include <lwip/snmp.h>
    #include "netif/etharp.h"
    #include "netif/ppp/pppoe.h"
    #include "netif/f2838xif.h"
    
    /**
     * f2838x device specific header files
     */
    #include "inc/hw_emac.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib_cm/ethernet.h"
    #include "driverlib_cm/interrupt.h"
    #include "driverlib_cm/sysctl.h"
    
    #include "utils/lwiplib.h"
    /**
     * Sanity Check:  This interface driver will NOT work if the following defines
     * are incorrect.
     *
     */
    #if (PBUF_LINK_HLEN != 16)
    #error "PBUF_LINK_HLEN must be 16 for this interface driver!"
    #endif
    #if (ETH_PAD_SIZE != 0)
    #error "ETH_PAD_SIZE must be 0 for this interface driver!"
    #endif
    #if (!SYS_LIGHTWEIGHT_PROT)
    #error "SYS_LIGHTWEIGHT_PROT must be enabled for this interface driver!"
    #endif
    
    /**
     * Number of pbufs supported in low-level tx/rx pbuf queue.
     *
     */
    #ifndef F2838X_NUM_PBUF_QUEUE
    #define F2838X_NUM_PBUF_QUEUE    20
    #endif
    
    #define EMAC_BASE                   0x400C0000U //EMAC
    #define EMAC_SS_BASE                0x400C2000U //EMACSS
    
    /* Define those to better describe your network interface. */
    #define IFNAME0 't'
    #define IFNAME1 'i'
    
    /* Helper struct to hold a queue of pbufs for transmit and receive. */
    struct pbufq
    {
        struct pbuf *pbuf[F2838X_NUM_PBUF_QUEUE];
        unsigned long qwrite;
        unsigned long qread;
        unsigned long overflow;
    };
    
    /* Helper macros for accessing pbuf queues. */
    #define PBUF_QUEUE_EMPTY(q) \
        (((q)->qwrite == (q)->qread) ? true : false)
    
    #define PBUF_QUEUE_FULL(q) \
        ((((((q)->qwrite + 1) % F2838X_NUM_PBUF_QUEUE)) == (q)->qread) ? \
        true : false )
    
    /**
     * Helper struct to hold private data used to operate your ethernet interface.
     * Keeping the ethernet address of the MAC in this struct is not necessary
     * as it is already kept in the struct netif.
     * But this is only an example, anyway...
     */
    struct f2838xif
    {
        struct eth_addr *ethaddr;
        /* Add whatever per-interface state that is needed here. */
        struct pbufq txq;
        Ethernet_Pkt_Desc *pktDesc;
    };
    
    /**
     * A structure used to keep track of driver state and error counts.
     */
    typedef struct {
        uint32_t ui32TXCount;
        uint32_t ui32TXCopyCount;
        uint32_t ui32TXCopyFailCount;
        uint32_t ui32TXNoDescCount;
        uint32_t ui32TXBufQueuedCount;
        uint32_t ui32TXBufFreedCount;
        uint32_t ui32RXBufReadCount;
        uint32_t ui32RXPacketReadCount;
        uint32_t ui32RXPacketErrCount;
        uint32_t ui32RXPacketCBErrCount;
        uint32_t ui32RXNoBufCount;
    }
    tDriverStats;
    
    tDriverStats g_sDriverStats = {0};
    
    volatile uint16_t numDesc = 0;
    
    #define DRIVER_STATS_INC(x) do{ g_sDriverStats.ui32##x++; } while(0)
    #define DRIVER_STATS_DEC(x) do{ g_sDriverStats.ui32##x--; } while(0)
    #define DRIVER_STATS_ADD(x, inc) do{ g_sDriverStats.ui32##x += inc; } while(0)
    #define DRIVER_STATS_SUB(x, dec) do{ g_sDriverStats.ui32##x -= dec; } while(0)
    
    /*
     * Creating a queue that maps an ethernet packet descriptor with
     * the corresponding pbuf. It is useful to free up the allocated pbuf memory
     * after the packet has been sent.
     */
    #ifndef F2838X_INTERFACE_NUM_PKT_DESC_QUEUE
    #define F2838X_INTERFACE_NUM_PKT_DESC_QUEUE    20
    #endif
    
    /**
     * Global variable for this interface's private data.  Needed to allow
     * the interrupt handlers access to this information outside of the
     * context of the lwIP netif.
     *
     */
    static struct f2838xif f2838xif_data;
    
    Ethernet_Handle emac_handle;
    
    /**
     * A macro which determines whether a pointer is within the SRAM address
     * space and, hence, points to a buffer that the Ethernet MAC can directly
     * DMA from.
     */
    #define PTR_SAFE_FOR_EMAC_DMA(ptr) (((uint32_t)(ptr) >= 0x2000800) &&   \
                                        ((uint32_t)(ptr) < 0x2000FFFF))
    
    /**
     * In this function, the hardware should be initialized.
     * Called from f2838xif_init().
     *
     * @param netif the already initialized lwip network interface structure
     *        for this ethernetif
     */
    static void
    f2838xif_hwinit(struct netif *netif)
    {
        uint32_t mac_low,mac_high;
        uint8_t *pucTemp;
    
        /* set MAC hardware address length */
        netif->hwaddr_len = ETHARP_HWADDR_LEN;
    
        /* set MAC address */
        Ethernet_getMACAddr(EMAC_BASE, 0, &mac_high, &mac_low);
    
        pucTemp = (uint8_t *)&mac_low;
        netif->hwaddr[0] = pucTemp[0];
        netif->hwaddr[1] = pucTemp[1];
        netif->hwaddr[2] = pucTemp[2];
        netif->hwaddr[3] = pucTemp[3];
    
        pucTemp = (uint8_t *)&mac_high;
        netif->hwaddr[4] = pucTemp[0];
        netif->hwaddr[5] = pucTemp[1];
    
        /* maximum transfer unit */
        netif->mtu = 1500;
    
        /* device capabilities */
        /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
        netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_IGMP;
    }
    
    /**
     * 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 This function MUST be called with interrupts disabled or with the
     *       F2838x Ethernet transmit fifo protected.
     */
    static err_t
    f2838xif_transmit(struct netif *netif, struct pbuf *p)
    {
        struct pbuf *q;
    
        /* No of pbufs (if chained)*/
        int n=0;
        int i=0;
        Ethernet_Pkt_Desc *pktDescOrigPtr, *pktDescPtr;
    
        /* ENTER CRITICAL SECTION
         * This is to protect the forming of packetc descriptor chain using pbufs
         * passed to the function.
         */
        Interrupt_disable(INT_EMAC_TX0);
        Interrupt_disable(INT_EMAC_RX0);
    
        /*
         * Make sure we still have a valid buffer (it may have been copied)
         */
        if(!p)
        {
            LINK_STATS_INC(link.memerr);
    
            /* EXIT CRITICAL SECTION */
            Interrupt_enable(INT_EMAC_TX0);
            Interrupt_enable(INT_EMAC_RX0);
    
            return(ERR_MEM);
        }
    
        /*
         * Count the number of the pbufs in the chain that we are passed with.
         */
        for(q = p; q != NULL; q = q->next)
                n++;
    
        /*
         * Get the head of the packet descriptor chain that will be passed to
         * the driver for sending.
         */
        pktDescOrigPtr = mem_malloc(sizeof(Ethernet_Pkt_Desc));
        if(pktDescOrigPtr == NULL)
        {
            __asm("   bkpt #0");
        }
        numDesc++;
    
        /*
         * Go over the pbufs present in the chain and allot a packet descriptor for
         * each pbuf. The descriptors will also be chained in the same order as
         * pbufs before passing the head of the chain to the driver.
         */
        for(q = p, pktDescPtr = pktDescOrigPtr; // Initialization
            q != NULL; // Condition evaluation
            q = q->next, pktDescPtr = pktDescPtr->nextPacketDesc) // Manipulation
        {
            /*
             * Initializing this data structure, otherwise garbage values will
             * result in rogue results while running.
             */
            memset(pktDescPtr,0,sizeof(Ethernet_Pkt_Desc));
    
            pktDescPtr->dataOffset = 0;
            pktDescPtr->dataBuffer = q->payload;
            pktDescPtr->pktChannel = ETHERNET_DMA_CHANNEL_NUM_0;
            pktDescPtr->pktLength = q->tot_len;
            pktDescPtr->bufferLength = q->len;
            pktDescPtr->validLength = q->len;
    
    
              if(i==0)
              {
                    if(n!=1)
                    {
                        /*
                         * Prepare the next ethernet packet descriptor holder if
                         * there is a pbuf next in the chain.
                         */
                        pktDescPtr->nextPacketDesc =
                                mem_malloc(sizeof(Ethernet_Pkt_Desc));
                        if(pktDescPtr->nextPacketDesc == NULL)
                            {
                                __asm("   bkpt #0");
                            }
                        numDesc++;
                        pktDescPtr->flags = ETHERNET_PKT_FLAG_SOP ;
                    }
                    else
                    {
                        pktDescPtr->nextPacketDesc = 0;
                        pktDescPtr->flags = ETHERNET_PKT_FLAG_SOP |
                                            ETHERNET_PKT_FLAG_EOP;
                    }
              }
              else
              {
                  if(q->next != NULL)
                  {
                      /*
                       * Prepare the next ethernet packet descriptor holder if
                       * there is a pbuf next in the chain.
                       */
                      pktDescPtr->nextPacketDesc =
                              mem_malloc(sizeof(Ethernet_Pkt_Desc));
                      if(pktDescPtr->nextPacketDesc == NULL)
                          {
                              __asm("   bkpt #0");
                          }
                      numDesc++;
                      pktDescPtr->flags = 0;
                  }
                  else
                  {
                      pktDescPtr->nextPacketDesc = 0;
                      pktDescPtr->flags = ETHERNET_PKT_FLAG_EOP;
                  }
              }
    
              i++;
        }
    
        /* EXIT CRITICAL SECTION */
        Interrupt_enable(INT_EMAC_TX0);
        Interrupt_enable(INT_EMAC_RX0);
    
        /*
         * Hand over the packet descriptor to the driver.
         */
        pktDescOrigPtr->numPktFrags = n;
        Ethernet_sendPacket(emac_handle,pktDescOrigPtr);
    
        LINK_STATS_INC(link.xmit);
    
        return(ERR_OK);
    }
    
    /**
     * This function will process all transmit descriptors and free pbufs attached
     * to any that have been transmitted since we last checked.
     *
     * This function is called only from the Ethernet interrupt handler.
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @return None.
     */
    int descriptorFreeErr=0;
    static void
    f2838xif_process_transmit(struct netif *netif, Ethernet_Pkt_Desc *pPacket)
    {
        Ethernet_Pkt_Desc *pktDescPtr, *pktDescPtrShadow;
    
        /*
         * Free the packet descriptor memory.
         */
        if (pPacket == 0)
            return;
    
        pktDescPtr = pPacket;
    
        /* ENTER CRITICAL SECTION */
        Interrupt_disable(INT_EMAC_TX0);
        //Interrupt_disable(INT_EMAC_RX0);
    
    //    do
    //    {
            pktDescPtrShadow = pktDescPtr->nextPacketDesc;
            mem_free(pktDescPtr);
            pktDescPtr = pktDescPtrShadow;
    
    //    }
    //    while(pktDescPtr != 0);
          numDesc--;
    
        /* EXIT CRITICAL SECTION */
        Interrupt_enable(INT_EMAC_TX0);
        //Interrupt_enable(INT_EMAC_RX0);
    }
    
    /**
     * This function with either place the packet into the F2838x transmit fifo,
     * or will place the packet in the interface PBUF Queue for subsequent
     * transmission when the transmitter becomes idle.
     *
     * @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
     *
     */
    
    static err_t
    f2838xif_output(struct netif *netif, struct pbuf *p)
    {
        f2838xif_transmit(netif, p);
    
        return ERR_OK;
    }
    
    /**
     * This function will read a single packet from the F2838x ethernet
     * interface, if available, and return a pointer to a pbuf.  The timestamp
     * of the packet will be placed into the pbuf structure.
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @return pointer to pbuf packet if available, NULL otherswise.
     */
    Ethernet_Pkt_Desc*
    f2838xif_receive( struct netif *netif, Ethernet_Pkt_Desc *pPacket )
    {
        struct pbuf *p;
    
    #if LWIP_PTPD
        u32_t time_s, time_ns;
        /* Get the current timestamp if PTPD is enabled */
        lwIPHostGetTime(&time_s, &time_ns);
    #endif
    
        p = pbuf_alloc(PBUF_RAW, sizeof(struct pbuf), PBUF_POOL);
        if(p)
        {
            p->payload = pPacket->dataBuffer;
    
            p->len = 1538U; //Max possible length of received packet.
            p->tot_len = p->len;
    
        #if LWIP_PTPD
            /* Place the timestamp in the PBUF */
            p->time_s = time_s;
            p->time_ns = time_ns;
        #endif
    
            if(ethernet_input(p, netif)!=ERR_OK)
            {
                /* drop the packet */
                LWIP_DEBUGF(NETIF_DEBUG, ("f2838xif_input: input error\n"));
                pbuf_free(p);
                p = NULL;
                /* Adjust the link statistics */
                LINK_STATS_INC(link.memerr);
                LINK_STATS_INC(link.drop);
            }
        }
    
        LINK_STATS_INC(link.recv);
    
        return(pPacket);
    }
    
    Ethernet_Pkt_Desc *f2838xif_newbuffcallback(void)
    {
        Ethernet_Pkt_Desc *newPacket = mem_calloc(1, sizeof(Ethernet_Pkt_Desc));
    
        if(newPacket)
        {
            newPacket->dataBuffer= memp_malloc(MEMP_PBUF_POOL);
        }
        return newPacket;
    }
    
    /**
     * Should be called at the beginning of the program to set up the
     * network interface. It calls the function f2838xif_hwinit() 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
    f2838xif_init(struct netif *netif)
    {
        LWIP_ASSERT("netif != NULL", (netif != NULL));
    
    #if LWIP_NETIF_HOSTNAME
        /* Initialize interface hostname */
        netif->hostname = "lwip";
    #endif /* LWIP_NETIF_HOSTNAME */
    
        /*
         * Initialize the snmp variables and counters inside the struct netif.
         * The last argument should be replaced with your link speed, in units
         * of bits per second.
         */
        NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1000000);
    
        netif->state = &f2838xif_data;
        netif->name[0] = IFNAME0;
        netif->name[1] = IFNAME1;
    
        /* We directly use etharp_output() here to save a function call.
         * You can instead declare your own function an call etharp_output()
         * from it if you have to do some checks before sending (e.g. if link
         * is available...) */
        netif->output = etharp_output;
        netif->linkoutput = f2838xif_output;
    
        f2838xif_data.ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
        f2838xif_data.txq.qread = f2838xif_data.txq.qwrite = 0;
        f2838xif_data.txq.overflow = 0;
    
        /* initialize the hardware */
        f2838xif_hwinit(netif);
    
        return ERR_OK;
    }
    
    /**
     * Process tx and rx packets at the low-level interrupt.
     *
     * Should be called from the F2838x Ethernet Interrupt Handler.  This
     * function will read packets from the F2838x Ethernet fifo and place them
     * into a pbuf queue.  If the transmitter is idle and there is at least one packet
     * on the transmit queue, it will place it in the transmit fifo and start the
     * transmitter.
     *
     */
    
    Ethernet_Pkt_Desc*
    f2838xif_interrupt(struct netif *netif, Ethernet_Pkt_Desc *pPacket)
    {
        Ethernet_Pkt_Desc *sPacket = NULL;
    
        /**
         * Based on the flags we get from pPacket, we should decide whether
         * to trasnmit or receive. Currently, it works for only incoming
         * ICMP ping requests.
         */
    
        /* ENTER CRITICAL SECTION
         * This is to protect the forming of packetc descriptor chain using pbufs
         * passed to the function.
         */
        Interrupt_disable(INT_EMAC_TX0);
        Interrupt_disable(INT_EMAC_RX0);
    
        if(pPacket->flags & ETHERNET_INTERRUPT_FLAG_RECEIVE)
            sPacket = f2838xif_receive(netif, pPacket);
    
        if(pPacket->flags & ETHERNET_INTERRUPT_FLAG_TRANSMIT)
            f2838xif_process_transmit(netif, pPacket);
    
        /* EXIT CRITICAL SECTION */
        Interrupt_enable(INT_EMAC_TX0);
        Interrupt_enable(INT_EMAC_RX0);
    
        return (sPacket);
    }
    

    请告诉我是否有任何事情需要我做得更好。

    此致

    Subeen

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

    Subeen、

    请看 并返回给您。

    此致

    Siddharth

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

    此外、我上传我使用的 echo.c。

    我在 ECHO_SEND 中添加了一些代码、用于正确发送数据。 (Read_End_Flag 或 Send_packet 等)。

    因此、我的电路板只能在 PC 向电路板发送数据包时发送回复。

    我通过引用一些博客编写了 mem_ffree 或 pbuf_ffree。 (在错误功能中)

    我希望这对您有所帮助。

    *

    ECHO.c

    /*
     * Copyright (c) 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 and a contribution to the lwIP TCP/IP stack.
     *
     * Credits go to Adam Dunkels (and the current maintainers) of this software.
     *
     * Christiaan Simons rewrote this file to get a more stable echo example.
     */
    
    /**
     * @file
     * TCP echo server example using raw API.
     *
     * Echos all bytes sent by connecting client,
     * and passively closes when client is done.
     *
     */
    
    
    #include "lwip/opt.h"
    #include "lwip/debug.h"
    #include "lwip/stats.h"
    #include "lwip/tcp.h"
    #include "lwip/udp.h"
    #include "echo.h"
    
    #if LWIP_TCP
    
    static struct tcp_pcb *echo_pcb;
    
    enum echo_states
    {
      ES_NONE = 0,
      ES_ACCEPTED,
      ES_RECEIVED,
      ES_CLOSING
    };
    
    struct echo_state
    {
      u8_t state;
      u8_t retries;
      struct tcp_pcb *pcb;
      /* pbuf (chain) to recycle */
      struct pbuf *p;
    };
    
    //#pragma DATA_SECTION(PACKET_BUFFER,"PACKET_SND_BUFF");
    //uint32_t PACKET_BUFFER[8000];
    
    
    // receive data from main loop
    uint8_t Send_packet[BUF_LENGTH];
    uint8_t Snd_Send_packet[BUF_LENGTH];
    uint8_t Rcv_packet[RCV_BUF_LENGTH];
    uint8_t Read_End_Flag = 0;
    uint8_t Rcv_packet_Flag = 0;
    
    // error message
    char message[2] = {0x10, 0xEF};
    
    #ifdef _FLASH
    #pragma CODE_SECTION( echo_accept , ".TI.ramfunc")
    #pragma CODE_SECTION( echo_recv , ".TI.ramfunc")
    #pragma CODE_SECTION( echo_error , ".TI.ramfunc")
    #pragma CODE_SECTION( echo_poll , ".TI.ramfunc")
    #pragma CODE_SECTION( echo_sent , ".TI.ramfunc")
    #pragma CODE_SECTION( echo_send , ".TI.ramfunc")
    #pragma CODE_SECTION( echo_close , ".TI.ramfunc")
    
    #pragma CODE_SECTION( tcp_recved , ".TI.ramfunc")
    #pragma CODE_SECTION( memcpy , ".TI.ramfunc")
    #pragma CODE_SECTION( tcp_write , ".TI.ramfunc")
    #pragma CODE_SECTION( tcp_abort , ".TI.ramfunc")
    #pragma CODE_SECTION( pbuf_free , ".TI.ramfunc")
    #pragma CODE_SECTION( tcp_recved , ".TI.ramfunc")
    #pragma CODE_SECTION( pbuf_chain , ".TI.ramfunc")
    #pragma CODE_SECTION( tcp_sent , ".TI.ramfunc")
    
    #endif
    err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
    err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
    void echo_error(void *arg, err_t err);
    err_t echo_poll(void *arg, struct tcp_pcb *tpcb);
    err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
    void echo_send(struct tcp_pcb *tpcb, struct echo_state *es);
    void echo_close(struct tcp_pcb *tpcb, struct echo_state *es);
    
    void echo_init(void){
    #if LWIP_TCP
      echo_pcb = tcp_new();
      if (echo_pcb != NULL)
      {
        err_t err;
    
        err = tcp_bind(echo_pcb, IP_ADDR_ANY, 5555);
        if (err == ERR_OK)
        {
          echo_pcb = tcp_listen(echo_pcb);
          tcp_accept(echo_pcb, echo_accept);
        }
        else  // err != ERR_OK
        {
          /* abort? output diagnostic? */
            memp_free( MEMP_TCP_PCB , echo_pcb );
            return err;
        }
      }
      else //echo_pcb == NULL
      {
        /* abort? output diagnostic? */
          memp_free( MEMP_TCP_PCB , echo_pcb );
      }
    #elif LWIP_UDP
      echo_pcb = udp_new();
      if (echo_pcb != NULL)
      {
        err_t err;
    
        err = udp_bind(echo_pcb, IP_ADDR_ANY, 5555);
        if (err == ERR_OK)
        {
          echo_pcb = tcp_listen(echo_pcb);
          tcp_accept(echo_pcb, echo_accept);
        }
        else
        {
          /* abort? output diagnostic? */
        }
      }
      else
      {
        /* abort? output diagnostic? */
      }
    
    #endif
    }
    
    
    err_t
    echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
    {
      err_t ret_err;
      struct echo_state *es;
    
      LWIP_UNUSED_ARG(arg);
      LWIP_UNUSED_ARG(err);
    
      /* Unless this pcb should have NORMAL priority, set its priority now.
         When running out of pcbs, low priority pcbs can be aborted to create
         new pcbs of higher priority. */
      tcp_setprio(newpcb, TCP_PRIO_MAX);
    
      es = (struct echo_state *)mem_malloc(sizeof(struct echo_state));
      if (es != NULL)
      {
        es->state = ES_ACCEPTED;
        es->pcb = newpcb;
        es->retries = 0;
        es->p = NULL;
        /* pass newly allocated es to our callbacks */
        tcp_arg(newpcb, es);
        tcp_recv(newpcb, echo_recv);
        tcp_err(newpcb, echo_error);
        tcp_poll(newpcb, echo_poll, 0);
        ret_err = ERR_OK;
      }
      else
      {
    
        ret_err = ERR_MEM;
        echo_close(newpcb, es);
      }
      return ret_err;  
    }
    
    err_t
    echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
    {
      struct echo_state *es;
      err_t ret_err;
    
      LWIP_ASSERT("arg != NULL",arg != NULL);
      es = (struct echo_state *)arg;
    
      if (p == NULL)
      {
        /* remote host closed connection */
        es->state = ES_CLOSING;
        if(es->p == NULL)
        {
           /* we're done sending, close it */
           echo_close(tpcb, es);
        }
        else
        {
          /* we're not done yet */
          tcp_sent(tpcb, echo_sent);
          echo_send(tpcb, es);
        }
        ret_err = ERR_OK;
      }
      else if(err != ERR_OK)
      {
        /* cleanup, for unkown reason */
        if (p != NULL)
        {
          es->p = NULL;
          pbuf_free(p);
        }
        ret_err = err;
      }
      else if(es->state == ES_ACCEPTED)
      {
        /* first data chunk in p->payload */
        es->state = ES_RECEIVED;
        /* store reference to incoming pbuf (chain) */
        es->p = p;
        /* install send completion notifier */
        tcp_sent(tpcb, echo_sent);
        echo_send(tpcb, es);
        ret_err = ERR_OK;
      }
      else if (es->state == ES_RECEIVED)
      {
        /* read some more data */
        if(es->p == NULL)
        {
          es->p = p;
          tcp_sent(tpcb, echo_sent);
          echo_send(tpcb, es);
        }
        else
        {
          struct pbuf *ptr;
    
          /* chain pbufs to the end of what we recv'ed previously  */
          ptr = es->p;
          pbuf_chain(ptr,p);
        }
        ret_err = ERR_OK;
      }
      else if(es->state == ES_CLOSING)
      {
        /* odd case, remote side closing twice, trash data */
        tcp_recved(tpcb, p->tot_len);
        es->p = NULL;
        pbuf_free(p);
        ret_err = ERR_OK;
      }
      else
      {
        /* unkown es->state, trash data  */
        tcp_recved(tpcb, p->tot_len);
        es->p = NULL;
        pbuf_free(p);
        ret_err = ERR_OK;
      }
      return ret_err;
    }
    
    void
    echo_error(void *arg, err_t err)
    {
      struct echo_state *es;
    
      LWIP_UNUSED_ARG(err);
    
      es = (struct echo_state *)arg;
      if (es != NULL)
      {
        mem_free(es);
      }
    }
    
    err_t
    echo_poll(void *arg, struct tcp_pcb *tpcb)
    {
      err_t ret_err;
      struct echo_state *es;
    
      es = (struct echo_state *)arg;
      if (es != NULL)
      {
        if (es->p != NULL)
        {
          /* there is a remaining pbuf (chain)  */
          tcp_sent(tpcb, echo_sent);
          echo_send(tpcb, es);
        }
        else
        {
          /* no remaining pbuf (chain)  */
          if(es->state == ES_CLOSING)
          {
            echo_close(tpcb, es);
          }
        }
        ret_err = ERR_OK;
      }
      else
      {
        /* nothing to be done */
        tcp_abort(tpcb);
        ret_err = ERR_ABRT;
      }
      return ret_err;
    }
    
    err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
    {
      struct echo_state *es;
    
      LWIP_UNUSED_ARG(len);
    
      es = (struct echo_state *)arg;
      es->retries = 0;
      
      if(es->p != NULL)
      {
        /* still got pbufs to send */
        tcp_sent(tpcb, echo_sent);
        echo_send(tpcb, es);
      }
      else
      {
        /* no more pbufs to send */
        if(es->state == ES_CLOSING)
        {
          echo_close(tpcb, es);
        }
      }
      return ERR_OK;
    }
    
    void echo_send(struct tcp_pcb *tpcb, struct echo_state *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;
    
      // received data handler
      if(ptr->len == RCV_BUF_LENGTH){
          memcpy(Rcv_packet, ptr->payload, RCV_BUF_LENGTH);
          Rcv_packet_Flag = 1;
      }
    
      /* enqueue data for transmission */
    //  wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
      if(!Read_End_Flag) wr_err = tcp_write(tpcb, Send_packet, BUF_LENGTH, 1);
      else wr_err = tcp_write(tpcb, Snd_Send_packet, BUF_LENGTH, 1);
    
      if (wr_err == ERR_OK)
      {
         u16_t plen;
          u8_t freed;
    
         plen = ptr->len;
         /* continue with next pbuf in chain (if any) */
         es->p = ptr->next;
         if(es->p != NULL)
         {
           /* new reference! */
           pbuf_ref(es->p);
         }
         /* chop first pbuf from chain */
          do
          {
            /* try hard to free pbuf */
            freed = pbuf_free(ptr);
          }
          while(freed == 0);
         /* we can read more data now */
         tcp_recved(tpcb, plen);
       }
       else if(wr_err == ERR_MEM)
       {
          /* we are low on memory, try later / harder, defer to poll */
         es->p = ptr;
         es->retries++;
       }
       else
       {
         /* other problem ?? */
           es->p = ptr;
           es->retries++;
       }
      }
    }
    
    void echo_close(struct tcp_pcb *tpcb, struct echo_state *es)
    {
      tcp_arg(tpcb, NULL);
      tcp_sent(tpcb, NULL);
      tcp_recv(tpcb, NULL);
      tcp_err(tpcb, NULL);
      tcp_poll(tpcb, NULL, 0);
      
      if (es != NULL)
      {
        mem_free(es);
      }  
      tcp_close(tpcb);
    }
    
    #endif /* LWIP_TCP */
    

    此致

    Subeen

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

    Subeen、

    谢谢、我们会再来看看。

    此致

    Siddharth