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: TCP software sends unexpected TCP Retransmission (less than rto)

Part Number: TMS320F28388D
Other Parts Discussed in Thread: TMDSHSECDOCK, TMDSCNCD28388D, C2000WARE

Tool/software:

Hi experts,

I'm facing the following problem. Could you please let us know how sw avoids an unexpected retransmit.

It sometimes happens that lwip(2.1.2) on CM executes "TCP Retransmission" at very closed  previous transmission (less than 1msec)

Hardware 

  TI evaluation board(192.168.1.100)  - PC(192.168.1.11)

  TMDSCNCD28388D(CM) with TMDSHSECDOCK  - PC

Software

   It is based on C2000ware sample(enet_lwip_tcp)

   C:\ti\c2000\C2000Ware_4_01_00_00\libraries\communications\Ethernet\third_party\lwip\examples

//###########################################################################
//
// FILE:   enet_lwip.c
//
// TITLE:  lwIP based Ethernet Example.
//
//###########################################################################
// $TI Release: $
// $Release Date: $
// $Copyright:
// Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com
//
// 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.
// $
//###########################################################################


#include <string.h>

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_emac.h"

#include "driverlib_cm/ethernet.h"
#include "driverlib_cm/gpio.h"
#include "driverlib_cm/interrupt.h"
#include "driverlib_cm/flash.h"
#include "driverlib_cm/cputimer.h"

#include "driverlib_cm/sysctl.h"
#include "driverlib_cm/systick.h"

#include "utils/lwiplib.h"
#include "lwipopts.h"

#include "cmd_msg.h"
#include "wave.h"

//*****************************************************************************
//
//! \addtogroup master_example_list
//! <h1>Ethernet with lwIP (enet_lwip)</h1>
//!
//! This example application demonstrates the operation of the F2838x
//! microcontroller Ethernet controller using the lwIP TCP/IP Stack. Once
//! programmed, the device sits endlessly waiting for ICMP ping requests. It
//! has a static IP address. To ping the device, the sender has to be in the
//! same network. The stack also supports ARP.
//!
//! For additional details on lwIP, refer to the lwIP web page at:
//! http://savannah.nongnu.org/projects/lwip/
//
//*****************************************************************************

// These are defined by the linker (see device linker command file)
extern uint16_t RamfuncsLoadStart;
extern uint16_t RamfuncsLoadSize;
extern uint16_t RamfuncsRunStart;
extern uint16_t RamfuncsLoadEnd;
extern uint16_t RamfuncsRunEnd;
extern uint16_t RamfuncsRunSize;

extern uint16_t constLoadStart;
extern uint16_t constLoadEnd;
extern uint16_t constLoadSize;
extern uint16_t constRunStart;
extern uint16_t constRunEnd;
extern uint16_t constRunSize;

#define DEVICE_FLASH_WAITSTATES 2

//*****************************************************************************
//
// Driver specific initialization code and macro.
//
//*****************************************************************************

#define ETHERNET_NO_OF_RX_PACKETS   2U
#define ETHERNET_MAX_PACKET_LENGTH 1538U
#define NUM_PACKET_DESC_RX_APPLICATION PBUF_POOL_SIZE //8 - same as PBUF_POOL_SIZE

Ethernet_Handle emac_handle;
Ethernet_InitConfig *pInitCfg;
uint32_t Ethernet_numRxCallbackCustom = 0;
uint32_t releaseTxCount = 0;
uint32_t genericISRCustomcount = 0;
uint32_t genericISRCustomRBUcount = 0;
uint32_t genericISRCustomROVcount = 0;
uint32_t genericISRCustomRIcount = 0;

uint32_t systickPeriodValue = 125000;   // 1msec, 125MHz 

Ethernet_Pkt_Desc  pktDescriptorRXCustom[NUM_PACKET_DESC_RX_APPLICATION];
extern uint32_t Ethernet_numGetPacketBufferCallback;
extern Ethernet_Device Ethernet_device_struct;
uint8_t Ethernet_rxBuffer[ETHERNET_NO_OF_RX_PACKETS *
                          ETHERNET_MAX_PACKET_LENGTH];

extern Ethernet_Pkt_Desc*
lwIPEthernetIntHandler(Ethernet_Pkt_Desc *pPacket);

void CM_init(void)
{
    //
    // Disable the watchdog
    //
    SysCtl_disableWatchdog();

#ifdef _FLASH
    //
    // Copy time critical code and flash setup code to RAM. This includes the
    // following functions: InitFlash();
    //
    // The RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart symbols
    // are created by the linker. Refer to the device .cmd file.
    // Html pages are also being copied from flash to ram.
    //
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    memcpy(&constRunStart, &constLoadStart, (size_t)&constLoadSize);
    //
    // Call Flash Initialization to setup flash waitstates. This function must
    // reside in RAM.
    //
    Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
#endif

    //
    // Sets the NVIC vector table offset address.
    //
#ifdef _FLASH
    Interrupt_setVectorTableOffset((uint32_t)vectorTableFlash);
#else
    Interrupt_setVectorTableOffset((uint32_t)vectorTableRAM);
#endif

}
//*****************************************************************************
//
// The interrupt handler for the SysTick interrupt.
//
//*****************************************************************************
interrupt void
SysTickIntHandler(void)
{
    //
    // Call the lwIP timer handler.
    //
    lwIPTimer(1U);  /* 1msec */
}

//*****************************************************************************
//
//  This function is a callback function called by the example to
//  get a Packet Buffer. Has to return a ETHERNET_Pkt_Desc Structure.
//  Rewrite this API for custom use case.
//
//*****************************************************************************
Ethernet_Pkt_Desc* Ethernet_getPacketBufferCustom(void)
{
    //
    // Get the next packet descriptor from the descriptor pool
    //
    uint32_t shortIndex = (Ethernet_numGetPacketBufferCallback + 3)
                % NUM_PACKET_DESC_RX_APPLICATION;

    //
    // Increment the book-keeping pointer which acts as a head pointer
    // to the circular array of packet descriptor pool.
    //
    Ethernet_numGetPacketBufferCallback++;

    //
    // Update buffer length information to the newly procured packet
    // descriptor.
    //
    pktDescriptorRXCustom[shortIndex].bufferLength =
                                  ETHERNET_MAX_PACKET_LENGTH;

    //
    // Update the receive buffer address in the packer descriptor.
    //
    pktDescriptorRXCustom[shortIndex].dataBuffer =
                                      &Ethernet_device_struct.rxBuffer [ \
               (ETHERNET_MAX_PACKET_LENGTH*Ethernet_device_struct.rxBuffIndex)];

    //
    // Update the receive buffer pool index.
    //
    Ethernet_device_struct.rxBuffIndex += 1U;
    Ethernet_device_struct.rxBuffIndex  = \
    (Ethernet_device_struct.rxBuffIndex%ETHERNET_NO_OF_RX_PACKETS);

    //
    // Receive buffer is usable from Address 0
    //
    pktDescriptorRXCustom[shortIndex].dataOffset = 0U;

    //
    // Return this new descriptor to the driver.
    //
    return (&(pktDescriptorRXCustom[shortIndex]));
}

//*****************************************************************************
//
//  This is a hook function and called by the driver when it receives a
//  packet. Application is expected to replenish the buffer after consuming it.
//  Has to return a ETHERNET_Pkt_Desc Structure.
//  Rewrite this API for custom use case.
//
//*****************************************************************************
Ethernet_Pkt_Desc* Ethernet_receivePacketCallbackCustom(
        Ethernet_Handle handleApplication,
        Ethernet_Pkt_Desc *pPacket)
{

    Ethernet_Pkt_Desc* temp_eth_pkt;
    //
    // Book-keeping to maintain number of callbacks received.
    //
    Ethernet_numRxCallbackCustom++;

    Ethernet_disableRxDMAReception(EMAC_BASE,0);

    //
    // This is a placeholder for Application specific handling
    // We are replenishing the buffer received with another buffer
    //
      temp_eth_pkt=lwIPEthernetIntHandler(pPacket);

      Ethernet_enableRxDMAReception(EMAC_BASE,0);

      return temp_eth_pkt;
}

void Ethernet_releaseTxPacketBufferCustom(
        Ethernet_Handle handleApplication,
        Ethernet_Pkt_Desc *pPacket)
{
    //
    // Once the packet is sent, reuse the packet memory to avoid
    // memory leaks. Call this interrupt handler function which will take care
    // of freeing the memory used by the packet descriptor.
    //
    lwIPEthernetIntHandler(pPacket);

    //
    // Increment the book-keeping counter.
    //
#ifdef ETHERNET_DEBUG
    releaseTxCount++;
#endif
}

interrupt void Ethernet_genericISRCustom(void)
{
    genericISRCustomcount++;
    Ethernet_RxChDesc *rxChan;
    uint16_t i=0;

    Ethernet_clearMACConfiguration(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
    Ethernet_clearMACConfiguration(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_TE);
    for(i = 0U;i < Ethernet_device_struct.initConfig.numChannels;i++)
    {
         Ethernet_disableRxDMAReception(
               Ethernet_device_struct.baseAddresses.enet_base,
               i);
    }
    if(((ETHERNET_DMA_CH0_STATUS_AIS |
                         ETHERNET_DMA_CH0_STATUS_RBU) ==
                       (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                              ETHERNET_O_DMA_CH0_STATUS) &
                              (uint32_t)(ETHERNET_DMA_CH0_STATUS_AIS |
                                         ETHERNET_DMA_CH0_STATUS_RBU))) ||
          (ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS) ==
                                   (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                          ETHERNET_O_MTL_Q0_INTERRUPT_CONTROL_STATUS) &
                                          (uint32_t)(ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS
                                                     )))
    {
        if((ETHERNET_DMA_CH0_STATUS_AIS |
                         ETHERNET_DMA_CH0_STATUS_RBU) ==
                       (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                              ETHERNET_O_DMA_CH0_STATUS) &
                              (uint32_t)(ETHERNET_DMA_CH0_STATUS_AIS |
                                         ETHERNET_DMA_CH0_STATUS_RBU)))
        {
          genericISRCustomRBUcount++;
        }
        if((ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS) ==
              (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                     ETHERNET_O_MTL_Q0_INTERRUPT_CONTROL_STATUS) &
                     (uint32_t)(ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS
                                )))
        {
          genericISRCustomROVcount++;
          Ethernet_enableMTLInterrupt(Ethernet_device_struct.baseAddresses.enet_base,0,
                                      ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS);
        }

        /*
         * Clear the AIS and RBU status bit. These MUST be
         * cleared together!
         */
        Ethernet_clearDMAChannelInterrupt(
                Ethernet_device_struct.baseAddresses.enet_base,
                ETHERNET_DMA_CHANNEL_NUM_0,
                ETHERNET_DMA_CH0_STATUS_AIS |
                ETHERNET_DMA_CH0_STATUS_RBU);

        /*
         * Recover from Receive Buffer Unavailable (and hung DMA)
         *
         * All descriptor buffers are owned by the application, and
         * in result the DMA cannot transfer incoming frames to the
         * buffers (RBU condition). DMA has also entered suspend
         * mode at this point, too.
         *
         * Drain the RX queues
         */

        /* Upon RBU error, discard all previously received packets */
        if(Ethernet_device_struct.initConfig.pfcbDeletePackets != NULL)
            (*Ethernet_device_struct.initConfig.pfcbDeletePackets)();

        rxChan =
           &Ethernet_device_struct.dmaObj.rxDma[ETHERNET_DMA_CHANNEL_NUM_0];

        /*
         * Need to disable multiple interrupts, so protect the code to do so within
         * a global disable block (to prevent getting interrupted in between)
         */

        if(NULL!= Ethernet_device_struct.ptrPlatformInterruptDisable)
        {
            (*Ethernet_device_struct.ptrPlatformInterruptDisable)(
                Ethernet_device_struct.interruptNum[
                    ETHERNET_RX_INTR_CH0 + rxChan->chInfo->chNum]);

            (*Ethernet_device_struct.ptrPlatformInterruptDisable)(
                Ethernet_device_struct.interruptNum[
                    ETHERNET_GENERIC_INTERRUPT]);
        }
        /* verify we have full capacity in the descriptor queue */
        if(rxChan->descQueue.count < rxChan->descMax) {
          /* The queue is not at full capacity due to OOM errors.
          Try to fill it again */
            Ethernet_addPacketsIntoRxQueue(rxChan);
        }
        Ethernet_initRxChannel(
                &Ethernet_device_struct.initConfig.chInfo[ETHERNET_CH_DIR_RX][0]);

        Ethernet_writeRxDescTailPointer(
            Ethernet_device_struct.baseAddresses.enet_base,
            0,
            (&Ethernet_device_struct.rxDesc[
             ((uint32_t)ETHERNET_DESCRIPTORS_NUM_RX_PER_CHANNEL) *
              (0 + (uint32_t)1U)]));

        if(NULL!= Ethernet_device_struct.ptrPlatformInterruptEnable)
        {
            (*Ethernet_device_struct.ptrPlatformInterruptEnable)(
                Ethernet_device_struct.interruptNum[
                    ETHERNET_RX_INTR_CH0 + rxChan->chInfo->chNum]);
            (*Ethernet_device_struct.ptrPlatformInterruptEnable)(
                Ethernet_device_struct.interruptNum[
                    ETHERNET_GENERIC_INTERRUPT]);
        }


    }
    if(0U != (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                 ETHERNET_O_DMA_CH0_STATUS) &
                           (uint32_t) ETHERNET_DMA_CH0_STATUS_RI))
    {
        genericISRCustomRIcount++;
        Ethernet_clearDMAChannelInterrupt(
                        Ethernet_device_struct.baseAddresses.enet_base,
                        ETHERNET_DMA_CHANNEL_NUM_0,
                        ETHERNET_DMA_CH0_STATUS_NIS | ETHERNET_DMA_CH0_STATUS_RI);
    }

    for(i = 0U;i < Ethernet_device_struct.initConfig.numChannels;i++)
    {
        Ethernet_enableRxDMAReception(
            Ethernet_device_struct.baseAddresses.enet_base,
            i);
    }
    Ethernet_setMACConfiguration(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
    Ethernet_setMACConfiguration(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_TE);
}

void
Ethernet_init(const unsigned char *mac)
{
    Ethernet_InitInterfaceConfig initInterfaceConfig;
    uint32_t macLower;
    uint32_t macHigher;
    uint8_t *temp;

    initInterfaceConfig.ssbase = EMAC_SS_BASE;
    initInterfaceConfig.enet_base = EMAC_BASE;
    initInterfaceConfig.phyMode = ETHERNET_SS_PHY_INTF_SEL_MII;

    //
    // Assign SoC specific functions for Enabling,Disabling interrupts
    // and for enabling the Peripheral at system level
    //
    initInterfaceConfig.ptrPlatformInterruptDisable =
                                                    &Platform_disableInterrupt;
    initInterfaceConfig.ptrPlatformInterruptEnable =
                                                     &Platform_enableInterrupt;
    initInterfaceConfig.ptrPlatformPeripheralEnable =
                                                    &Platform_enablePeripheral;
    initInterfaceConfig.ptrPlatformPeripheralReset =
                                                     &Platform_resetPeripheral;

    //
    // Assign the peripheral number at the SoC
    //
    initInterfaceConfig.peripheralNum = SYSCTL_PERIPH_CLK_ENET;

    //
    // Assign the default SoC specific interrupt numbers of Ethernet interrupts
    //
    initInterfaceConfig.interruptNum[0] = INT_EMAC;
    initInterfaceConfig.interruptNum[1] = INT_EMAC_TX0;
    initInterfaceConfig.interruptNum[2] = INT_EMAC_TX1;
    initInterfaceConfig.interruptNum[3] = INT_EMAC_RX0;
    initInterfaceConfig.interruptNum[4] = INT_EMAC_RX1;

    pInitCfg = Ethernet_initInterface(initInterfaceConfig);

    Ethernet_getInitConfig(pInitCfg);
    pInitCfg->dmaMode.InterruptMode = ETHERNET_DMA_MODE_INTM_MODE2;

    //
    // Assign the callbacks for Getting packet buffer when needed
    // Releasing the TxPacketBuffer on Transmit interrupt callbacks
    // Receive packet callback on Receive packet completion interrupt
    //
    pInitCfg->pfcbRxPacket = &Ethernet_receivePacketCallbackCustom;
    pInitCfg->pfcbGetPacket = &Ethernet_getPacketBuffer;
    pInitCfg->pfcbFreePacket = &Ethernet_releaseTxPacketBufferCustom;

    //
    //Assign the Buffer to be used by the Low level driver for receiving
    //Packets. This should be accessible by the Ethernet DMA
    //
    pInitCfg->rxBuffer = Ethernet_rxBuffer;

    //
    // The Application handle is not used by this application
    // Hence using a dummy value of 1
    //
    Ethernet_getHandle((Ethernet_Handle)1, pInitCfg , &emac_handle);

    //
    // Disable transmit buffer unavailable and normal interrupt which
    // are enabled by default in Ethernet_getHandle.
    //
    Ethernet_disableDmaInterrupt(Ethernet_device_struct.baseAddresses.enet_base,
                                 0, (ETHERNET_DMA_CH0_INTERRUPT_ENABLE_TBUE |
                                     ETHERNET_DMA_CH0_INTERRUPT_ENABLE_NIE));

    //
    // Enable the MTL interrupt to service the receive FIFO overflow
    // condition in the Ethernet module.
    //
    Ethernet_enableMTLInterrupt(Ethernet_device_struct.baseAddresses.enet_base,0,
                                ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOIE);

    //
    // Disable the MAC Management counter interrupts as they are not used
    // in this application.
    //
    HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_RX_INTERRUPT_MASK) = 0xFFFFFFFF;
    HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_IPC_RX_INTERRUPT_MASK) = 0xFFFFFFFF;
    //
    //Do global Interrupt Enable
    //
    (void)Interrupt_enableInProcessor();

    //
    //Assign default ISRs
    //
    Interrupt_registerHandler(INT_EMAC_TX0, Ethernet_transmitISR);
    Interrupt_registerHandler(INT_EMAC_RX0, Ethernet_receiveISR);
    Interrupt_registerHandler(INT_EMAC, Ethernet_genericISRCustom);

    //
    // Convert the mac address string into the 32/16 split variables format
    // that is required by the driver to program into hardware registers.
    // Note: This step is done after the Ethernet_getHandle function because
    //       a dummy MAC address is programmed in that function.
    //
    temp = (uint8_t *)&macLower;
    temp[0] = mac[0];
    temp[1] = mac[1];
    temp[2] = mac[2];
    temp[3] = mac[3];

    temp = (uint8_t *)&macHigher;
    temp[0] = mac[4];
    temp[1] = mac[5];

    //
    // Program the unicast mac address.
    //
    Ethernet_setMACAddr(EMAC_BASE,
                        0,
                        macHigher,
                        macLower,
                        ETHERNET_CHANNEL_0);
    Ethernet_clearMACConfiguration(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
    Ethernet_setMACConfiguration(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
}



/* TCP server initialization ......................................................*/
err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err);
err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
void tcp_err_callback(void *arg, err_t err);
void tcp_close_connection(struct tcp_pcb *tpcb);

/* TCP/IP ��M�Ǘ� */
uint8_t tcp_buf_cmd_au8g[ TCP_BUF_NUM][ TCP_BUF_SIZE];
uint16_t tcp_buf_cmd_len_au16g[ TCP_BUF_NUM];
uint8_t tcp_buf_rply_au8g[ TCP_BUF_RLY_SIZE];
uint8_t tcp_buf_poll_au8g[ TCP_BUF_POLL_SIZE];
uint8_t tcp_buf_wave_au8g[ TCP_BUF_WAVE_SIZE];
uint16_t tcp_bufW_id_u16g = 0U;     /* write index */
uint16_t tcp_bufR_id_u16g = 0U;     /* read index */
uint16_t tcp_cmd_no_u16g = 0U;      /* command sequenced number */

uint16_t tcp_debug_status = 0U;
uint16_t tcp_debug_err = 0U;
err_t tcp_err_accept = ERR_OK;
err_t tcp_err_error = ERR_OK;
err_t tcp_err_write = ERR_OK;
err_t tcp_err_out = ERR_OK;
err_t tcp_err_latch_error = ERR_OK;
err_t tcp_err_latch_write = ERR_OK;
err_t tcp_err_latch_out = ERR_OK;

struct tcp_pcb *tcp_pcb_g = NULL;
struct tcp_pcb *tcp_pcb_acpt_g = NULL;

volatile uint32_t timer0_period_u32g = 0UL;
volatile uint32_t timer0_max_period_u32g = 0UL;
volatile uint32_t timer0_pre_clock_u32g = 0UL;

err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err) {
    tcp_bufW_id_u16g = 0;
    tcp_bufR_id_u16g = 0;

    tcp_recv(newpcb, tcp_recv_callback);
    tcp_err(newpcb, tcp_err_callback);
    tcp_err_accept = err;
    tcp_pcb_acpt_g = newpcb;
    CMD_ResetCmdNo_vo( tcp_cmd_no_u16g);
    timer0_max_period_u32g = 0U;
    return ERR_OK;
}

void tcp_err_callback(void *arg, err_t err) {
    struct tcp_pcb *tpcb = (struct tcp_pcb *)arg;
    tcp_err_error = err;
    if (tpcb != NULL) {
        tcp_close_connection(tpcb);
    }
}

void tcp_close_connection(struct tcp_pcb *tpcb) {
    tcp_arg(tpcb, NULL);
    tcp_recv(tpcb, NULL);
    tcp_err(tpcb, NULL);
    tcp_close(tpcb);

    tcp_err_latch_error = tcp_err_error;
    tcp_err_latch_write = tcp_err_write;
    tcp_err_latch_out = tcp_err_out;

    CMD_ResetCmdNo_vo( tcp_cmd_no_u16g);
    tcp_err_accept = 0U;
    tcp_err_error = 0U;
}

err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {

    if (p != NULL) {

        /* �f�[�^���M�����ꍇ�̏��� */
        tcp_recved(tpcb, p->tot_len);

        if (TCP_BUF_SIZE >= p->tot_len) {
            tcp_cmd_no_u16g++;

            /* receive a command */
            memcpy( (void*)&tcp_buf_cmd_au8g[ tcp_bufW_id_u16g][0], (void*)(p->payload), p->tot_len);
            tcp_buf_cmd_len_au16g[ tcp_bufW_id_u16g] = p->tot_len;

            if (TCP_BUF_NUM <= (tcp_bufW_id_u16g + 1)) {
                tcp_bufW_id_u16g = 0;
            }
            else {
                tcp_bufW_id_u16g++;
            }
        }
        else {
        }

        pbuf_free(p);
    }
    else {
    }

    return ERR_OK;
}

uint16_t tcp_debug_proccess( void ) {
    uint16_t ret_cd = 0U;

    if (NULL != tcp_pcb_acpt_g) {
        ret_cd = CMD_CommnMsg_u16( tcp_cmd_no_u16g, &tcp_buf_cmd_au8g[ tcp_bufR_id_u16g][0], tcp_buf_cmd_len_au16g[tcp_bufR_id_u16g]);
    }
    else{}

    return ret_cd;
}

void tcp_switch_buf( void ){

    if (TCP_BUF_NUM <= (tcp_bufR_id_u16g + 1)) {
        tcp_bufR_id_u16g = 0;
    }
    else {
        tcp_bufR_id_u16g++;
    }
}

uint16_t tcp_out_reply( uint8_t* reply_buf_pu8, uint16_t len_u16){

    uint16_t ret_code_u16;

    Interrupt_disable(INT_EMAC_TX0);
    Interrupt_disable(INT_EMAC_RX0);
    SYSTICK_disableInterrupt();
    tcp_err_write = tcp_write( tcp_pcb_acpt_g, (void*)reply_buf_pu8, len_u16, TCP_WRITE_FLAG_COPY);

    if (ERR_OK == tcp_err_write) {
        tcp_err_out = tcp_output( tcp_pcb_acpt_g);
        SYSTICK_enableInterrupt();
        Interrupt_enable(INT_EMAC_RX0);
	    Interrupt_enable(INT_EMAC_TX0);

        if (ERR_OK != tcp_err_out) {
            tcp_close_connection( tcp_pcb_acpt_g);
            tcp_pcb_acpt_g = NULL;
            ret_code_u16 = 2;
        }
        else{
            ret_code_u16 = 0;
        }
    }
    else{
	    SYSTICK_enableInterrupt();
	    Interrupt_enable(INT_EMAC_RX0);
	    Interrupt_enable(INT_EMAC_TX0);
        tcp_close_connection( tcp_pcb_acpt_g);
        tcp_pcb_acpt_g = NULL;
        ret_code_u16 = 1U;
    }

    return ret_code_u16;
}

uint16_t tcp_out_write_wave_data( uint8_t* reply_buf_pu8, uint16_t len_u16){

    uint16_t ret_code_u16;

    Interrupt_disable(INT_EMAC_TX0);
    Interrupt_disable(INT_EMAC_RX0);
    SYSTICK_disableInterrupt();
    tcp_err_write = tcp_write( tcp_pcb_acpt_g, (void*)reply_buf_pu8, len_u16, TCP_WRITE_FLAG_COPY);
    if( ERR_OK == tcp_err_write ){
    	tcp_err_out = tcp_output( tcp_pcb_acpt_g);
	    if( ERR_OK == tcp_err_out ){
	        ret_code_u16 = 0U;
	    }
	    else{
	        ret_code_u16 = 2U;
	    }
    }
    else{
        ret_code_u16 = 1U;
    }
    SYSTICK_enableInterrupt();
    Interrupt_enable(INT_EMAC_RX0);
    Interrupt_enable(INT_EMAC_TX0);
    
    return ret_code_u16;
}

uint16_t tcp_out_wave_data( void ){

    uint16_t ret_code_u16;

    Interrupt_disable(INT_EMAC_TX0);
    Interrupt_disable(INT_EMAC_RX0);
    SYSTICK_disableInterrupt();
    tcp_err_out = tcp_output( tcp_pcb_acpt_g);
    SYSTICK_enableInterrupt();
    Interrupt_enable(INT_EMAC_RX0);
    Interrupt_enable(INT_EMAC_TX0);
    if( ERR_OK == tcp_err_out ){
        ret_code_u16 = 0U;
    }
    else{
        ret_code_u16 = 1U;
    }
    
    return ret_code_u16;
}

void tcp_close_con( void ){

    tcp_close_connection( tcp_pcb_acpt_g);
    Interrupt_enable(INT_EMAC_RX0);
    Interrupt_enable(INT_EMAC_TX0);
    SYSTICK_enableInterrupt();
    tcp_pcb_acpt_g = NULL;
}


/* TCP server initialization ......................................................*/
void MW_TcpServerInit(void)
{
    struct tcp_pcb *pcb_local;

    tcp_bufR_id_u16g = 0;
    tcp_bufW_id_u16g = 0;

    pcb_local = tcp_new();
    if (NULL != pcb_local) {
        tcp_bind( pcb_local, IP_ADDR_ANY, TCPIP_PE_EXPERT4_PORTNO);
        tcp_pcb_g = tcp_listen( pcb_local);
        tcp_accept(tcp_pcb_g, tcp_accept_callback);
    }
    else {
        tcp_pcb_g = (struct tcp_pcb *)NULL;
    }

    CMD_SetReplyBuf_vo( tcp_buf_rply_au8g, tcp_buf_poll_au8g, tcp_buf_wave_au8g);
}

//*****************************************************************************
//
// The interrupt handler for the Timer0 interrupt.
//
//*****************************************************************************
interrupt void Timer0IntHandler(void)
{
    uint64_t now_clk_u64;
    uint32_t now_clk_u32;
    uint32_t diff_clk_u32;

    CPUTimer_clearOverflowFlag( CPUTIMER0_BASE);
    WAV_SampleValues_s16( (float*)CMD_IpcWaveRec_af32g );

    now_clk_u64 = IPC_getCounter( IPC_CM_L_CPU1_R);
    now_clk_u32 = (uint32_t)now_clk_u64;
    diff_clk_u32 = now_clk_u32 - timer0_pre_clock_u32g;
    timer0_pre_clock_u32g = now_clk_u32;
    timer0_period_u32g = diff_clk_u32;
    if( timer0_max_period_u32g < diff_clk_u32 ){
        timer0_max_period_u32g = diff_clk_u32;
    }
    else{}

}


//*****************************************************************************
//
// This use of the Ethernet Controller.
//
//*****************************************************************************

unsigned long cnt_total_loop = 0UL;

int
main(void)
{
    unsigned long ulUser0, ulUser1;
    unsigned char pucMACArray[8];

    //
    // User specific IP Address Configuration.
    // Current implementation works with Static IP address only.
    //
    unsigned long IPAddr =  TCPIP_IP_ADDR; 
    unsigned long NetMask = TCPIP_NET_MASK;
    unsigned long GWAddr = TCPIP_GW_ADDR;

    //
    // Initializing the CM. Loading the required functions to SRAM.
    //
    CM_init();

    SYSTICK_setPeriod(systickPeriodValue);
    SYSTICK_registerInterruptHandler(SysTickIntHandler);
    Interrupt_setPriority(FAULT_SYSTICK, 3);
    SYSTICK_enableCounter();
    SYSTICK_enableInterrupt();

    //
    // Enable processor interrupts.
    //
    Interrupt_enableInProcessor();

    // Set user/company specific MAC octets
    // (for this code we are using A8-63-F2-00-00-80)
    // 0x00 MACOCT3 MACOCT2 MACOCT1
    ulUser0 = 0x00F263A8;

    // 0x00 MACOCT6 MACOCT5 MACOCT4
    ulUser1 = 0x00800000;

    //
    // Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
    // address needed to program the hardware registers, then program the MAC
    // address into the Ethernet Controller registers.
    //
    pucMACArray[0] = ((ulUser0 >>  0) & 0xff);
    pucMACArray[1] = ((ulUser0 >>  8) & 0xff);
    pucMACArray[2] = ((ulUser0 >> 16) & 0xff);
    pucMACArray[3] = ((ulUser1 >>  0) & 0xff);
    pucMACArray[4] = ((ulUser1 >>  8) & 0xff);
    pucMACArray[5] = ((ulUser1 >> 16) & 0xff);

    //
    // Initialize ethernet module.
    //
    Ethernet_init(pucMACArray);

    //
    // Initialze the lwIP library w/ fixed IP address 
    //
    lwIPInit(0, pucMACArray, IPAddr, NetMask, GWAddr, IPADDR_USE_STATIC);

    //
    // Initialize the TCP/IP server daemon.
    //
    MW_TcpServerInit();     //  

    //
    //Enable the default interrupt handlers
    //
    Interrupt_setPriority(INT_EMAC_TX0, 3);
    Interrupt_setPriority(INT_EMAC_RX0, 3);
    Interrupt_setPriority(INT_EMAC, 3);
    Interrupt_enable(INT_EMAC_TX0);
    Interrupt_enable(INT_EMAC_RX0);
    Interrupt_enable(INT_EMAC);

    //
    //Enable timer0 interrupt handlers
    //
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER0);
    CPUTimer_setPeriod( CPUTIMER0_BASE, 2500);  /* 2,500clk = 20,000 ns */
    CPUTimer_clearOverflowFlag( CPUTIMER0_BASE);
    CPUTimer_stopTimer( CPUTIMER0_BASE);

    Interrupt_registerHandler( INT_TIMER0, Timer0IntHandler);
    Interrupt_setPriority( INT_TIMER0, 0);
    Interrupt_enable( INT_TIMER0);

    CPUTimer_startTimer( CPUTIMER0_BASE);
    CPUTimer_enableInterrupt( CPUTIMER0_BASE);

    //
    // Loop forever. All the work is done in interrupt handlers.
    //
    while(1)
    {
        cnt_total_loop++;

        SysCtl_delay(104166);  //aprox 3.3ms (N x 8ns(125MHz) x 6cycle + 9cycle)

        sys_check_timeouts();

        tcp_debug_status = tcp_debug_proccess();    /* debug agent process */
        if( (0 != tcp_debug_err) || (0 != tcp_debug_status) ){
            tcp_debug_err = tcp_debug_status;
            tcp_err_latch_error = tcp_err_error;
            tcp_err_latch_write = tcp_err_write;
            tcp_err_latch_out = tcp_err_out;
        }

		if( 0U == tcp_err_latch_error ){
            tcp_err_latch_error = tcp_err_error;
		}
		if( 0U == tcp_err_latch_write ){
            tcp_err_latch_write = tcp_err_write;
		}
		if( 0U == tcp_err_latch_out ){
            tcp_err_latch_out = tcp_err_out;
		}

    }
}


//*****************************************************************************
//
// Called by lwIP Library. Could be used for periodic custom tasks.
//
//*****************************************************************************

uint32_t cnt_ms_lwip_Htimer=0;

void lwIPHostTimerHandler(void)
{
    cnt_ms_lwip_Htimer++;
}

Interrupt_enable(INT_EMAC_TX0);
Interrupt_enable(INT_EMAC_RX0);
Interrupt_enable(INT_EMAC);

lwIPTimer() is called on SysTickIntHandler

tcp_write() and tcp_output() are called on Main level(not on interrupt routines)

And I disable interrupt TX, RX and SysTick between start of tcp_write() and end tcp_output()

to avoid context switching problem like below issues

And I set related interrupts on same priority level to avoid multiple interrupt problem.

Interrupt_setPriority(INT_EMAC_TX0, 3);
Interrupt_setPriority(INT_EMAC_RX0, 3);
Interrupt_setPriority(INT_EMAC, 3);
Interrupt_setPriority(FAULT_SYSTICK, 3);

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/992830/tms320f28388d-faulty-lwip-f2838x-port-tested-both-udp-and-tcp-ip-via-mqtt#pifragment-323267=1

However TCP retransmission is executed closed interval time (less than 1msec from previous previous transmission ).

I donot  find code for this behavior.

I think that the below codes to send re-transmission packet but BP is not hit when this behavior happen in wire shark log.

tcp_slowtmr() 

if (pcb->rtime >= pcb->rto) {
/* Time for a retransmission. */

Best regards,

Hidehiko