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.

TMS570LC4357: EMAC Module Fails to Enter Receive Interrupt After Period of Data Reception with lwIP Protocol"

Part Number: TMS570LC4357

 Hello 

   I am using the lwIP protocol with the EMAC module for data transmission and reception. Sending data works perfectly fine, but I'm facing an issue with the EMAC module when it comes to receiving data. After receiving data for a certain period of time, the EMAC module fails to enter the receive interrupt. I'm seeking assistance on how to resolve this problem and ensure that the EMAC module can consistently receive data without interruptions. Thank you! 

  My lwIP initialization is as follows:

void EMAC_LwIP_init (uint8_t * macAddress)
{
    unsigned int 	ipAddr;
    uint32  emacCtrlBase =  0xFCF78800U;
    uint32  emacBase =  0xFCF78000U;	

	EMACInit(emacCtrlBase,emacBase);
	IntMasterIRQEnable();//中断

   /* for static IP address. Change address as required, and uncomment the previous statement. */ 	
	uint8 ip_addr[4] = { 172, 22, 1, 1 };
	uint8 netmask[4] = { 255, 255, 255, 0 };
	uint8 gateway[4] = { 172, 22, 1, 1 };  
	ipAddr = lwIPInit(0, macAddress,
			*((uint32_t *)ip_addr),
			*((uint32_t *)netmask),
			*((uint32_t *)gateway),
			IPADDR_USE_STATIC  );
	

}

      And my EMAC module's receive interrupt is as shown below. During testing, I noticed that the receive interrupt stops occurring after the R0 (Receive Idle Buffer Count Register) receives the value 0xCD(After this point, the register does not change unless I reinitialize). I suspect there might be an issue with the tail processing in my interrupt function. Here's my interrupt function:

#pragma INTERRUPT(EMACCore0RxIsr, IRQ)
uint32 countrxisr = 0;
void EMACCore0RxIsr(void)
{   

    char* tmpptr;
    uint32_t tmp = 0;
    uint32_t CurFinishCP = HWREG(EMAC_BASE + EMAC_RXCP(0)); /* Pointer to the buffer that has completed data reception */
    EMACDesc_t* RXCP = EMAC_SL_CurRXCP; /* Pointer to the current processing receive buffer */
    MACFrame_t* MacFramePtr = NULL;

    ECTRL_C0RXEN = 0U; /* Disable interrupts before processing data */
    HWREG(EMAC_BASE + EMAC_RXCP(0)) = CurFinishCP; /* Confirm the current processed CP (Complete Pointer) */
    HWREG(EMAC_BASE + EMAC_MACEOIVECTOR) = 1U; /* Acknowledge the completion of receive interrupt */

    if (countrxisr == 0U) // First frame
    {
        HWREG(EMAC_BASE + EMAC_RXHDP(0)) = CurFinishCP;
        EMAC_SL_CurRXCP = (EMACDesc_t*)CurFinishCP;
        RXCP = (EMACDesc_t*)CurFinishCP;
        countrxisr = 1;
    } /* When the current receive queue reaches the end, reassign the receive buffer pointer to the first position */
    else if (HWREG(EMAC_BASE + EMAC_RXHDP(0)) == 0U)
    {
        HWREG(EMAC_BASE + EMAC_RXHDP(0)) = CurFinishCP;
        EMAC_SL_CurRXCP = (EMACDesc_t*)CurFinishCP;
        RXCP = (EMACDesc_t*)CurFinishCP; // Original
    } /* When the current receive queue reaches the end, reassign the receive buffer pointer to the first position */
    else
    {
        EMAC_SL_CurRXCP = ((EMACDesc_t*)(CurFinishCP)) + 1U;
        EMAC_SL_CurRXCP = (EMACDesc_t*)((char*)EMAC_SL_CurRXCP + 4); /* Appear 4 bytes more data than 3137, so add this offset */
    } /* Update the last processed CP */

    while ((uint32_t)(RXCP) <= CurFinishCP)
    {
        /*1============================================================================1*/
        /* Only process single packet data, discard fragmented data packets */
        if ((RXCP->EOP == 1U) && (RXCP->SOP == 1U))
        {
            MacFramePtr = (MACFrame_t*)EMACSwizzleData((uint32)RXCP->BufferPtr); /* Pointer to MAC layer data frame information */

            switch (MacFramePtr->FrameType)
            {
                case IPV4_DT_ARP_FRAME:
                {
                    if (EMACSwizzleData16(RXCP->Length) <= sizeof EMAC_SL_RXBuffer.Data[0].Buffer)
                    {
                        memcpy(EMAC_SL_RXBuffer.Data[EMAC_SL_RXBuffer.Tail.Cnt].Buffer, EMACSwizzleData(RXCP->BufferPtr), EMACSwizzleData16(RXCP->Length));
                        EMAC_SL_RXBuffer.Tail.Cnt++;
                    }

                    break;
                } /* Received ARP data frame, store the data in the receive buffer for later processing */

                case IPV4_DT_IP_FRAME:
                {
                    IPHeader_t* IPHeaderPtr = (IPHeader_t*)(EMACSwizzleData(RXCP->BufferPtr) + 14U); /* IP header information of the current data packet */

                    
                    if ((IPHeaderPtr->SrcIP == REMOTE_IP_ADDR) && ((IPHeaderPtr->DstIP == LOCAL_IP_ADDR) || (IPHeaderPtr->DstIP == BROADCAST_IP_ADDR)) && (IPHeaderPtr->Protol == IP_PROTO_UDP))
                    {
                        EMAC_SL_IsRXRemoteUDPData = TRUE;

                        if (EMACSwizzleData16(RXCP->Length) <= sizeof EMAC_SL_RXBuffer.Data[0].Buffer)
                        {
                            memcpy(EMAC_SL_RXBuffer.Data[EMAC_SL_RXBuffer.Tail.Cnt].Buffer, EMACSwizzleData(RXCP->BufferPtr), EMACSwizzleData16(RXCP->Length));
                            EMAC_SL_RXBuffer.Tail.Cnt++;
                        }
                    } /* Received IP address matches the local IP address and data type is UDP, then process the data frame */

                    break;
                } /* Received IP data frame, store the data in the receive buffer for later processing */

                default:
                {
                    break;
                }
            }
        }
        /*1============================================================================1*/

        RXCP->Length = RX_BUFFER_SIZE;
        RXCP->OWNER = 1U;
        RXCP++;
        RXCP = (char*)RXCP + 4; /* Here, don't know why data in buffer is 32 * 5 bytes while 3137 is 32 * 4 bytes, perhaps because of the lwIP protocol */

    }

    ECTRL_C0RXEN = 1U; /* Reactivate interrupts */
}

Can you help me analyze where the problem might be occurring? Thank you.

  • Hi,

    You have to free the Pbuf after each processing of the packet by calling the function "pbuf_free()".

    For more details have a look on below thread:

    (+) TMS570LS3137: lwIP demo halts after about 60 UDP packets - Arm-based microcontrollers forum - Arm-based microcontrollers - TI E2E support forums

    --

    Thanks & regards,
    Jagadish.

  • Hello

      I have read the post you provided and tried the method you mentioned, using pbuf_free(). I can receive more data packets than before, but the previous issue still persists – the interrupt stops triggering for data reception.

      Furthermore, I noticed that when I modify the MAX_RX_PBUF_ALLOC in this function, I can receive more data packets. However, the maximum value I can set it to is 60U. I still haven't found a way to restore the receive buffer, and the issue of the interrupt not triggering for data reception persists. Could you please take a look at this code and help me analyze the problem?

    /* Initialize the descriptors for the RX channel */
      rxch = &(hdkif->rxch);
      rxch->active_head = (volatile struct emac_rx_bdp*)(curr_txbd + 1);
      
      rxch->free_head = NULL;
      rxch->freed_pbuf_len = 0;
      num_bd = ((SIZE_EMAC_CTRL_RAM >> 1) / sizeof(emac_rx_bdp) - 1);
      curr_bd = rxch->active_head;
      last_bd = curr_bd;
    
      /*
      ** Allocate the pbufs for the maximum count permitted or till the
      ** number of buffer desceriptors expire, which ever is earlier.
      */
      while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {
        p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
        pbuf_cnt++;
        
        if(p != NULL) {
          /* write the descriptors if there are enough numbers to hold the pbuf*/
          if(((uint32)pbuf_clen(p)) <= num_bd) {
            for(q = p; q != NULL; q = q->next) {
              curr_bd->bufptr = hdkif_swizzle_data((uint32)(q->payload));
              curr_bd->bufoff_len = hdkif_swizzle_data(q->len);
              curr_bd->next = hdkif_swizzle_rxp(curr_bd + 1);
              curr_bd->flags_pktlen = hdkif_swizzle_data(EMAC_BUF_DESC_OWNER);
              
              /* Save the pbuf */
              curr_bd->pbuf = q;
              last_bd = curr_bd;
              curr_bd = hdkif_swizzle_rxp(curr_bd->next);
              num_bd--;
    
            }
          }
        
          /* free the allocated pbuf if no free descriptors are left */
       //else {
           pbuf_free(p);
      //  break;
        //  }
        }
        else {
          break;
        }
      }
    
      last_bd->next = NULL;
      rxch->active_tail = last_bd;
    
      /* Acknowledge receive and transmit interrupts for proper interrupt pulsing*/
      EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
      EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
      
      EMACRxUnicastSet(hdkif->emac_base, 0);
      EMACNumFreeBufSet(hdkif->emac_base, 0, 10);
      EMACTxEnable(hdkif->emac_base);
      EMACRxEnable(hdkif->emac_base);
    
      /* Write the RX HDP for channel 0 */
      EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32)rxch->active_head, 0);
     
      EMACMIIEnable(hdkif->emac_base); 
    
      
      /**
      * Enable the Transmission and reception, enable the interrupts for
      * channel 0 and for control core 0
      */
      EMACTxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, 0);
      EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, 0);
    
      return ERR_OK;
     

     Thanks & regards,

  • Hi,

    I am not talking about in initializations routine.

    But after processing the packet you should free the pbuf.

    please verify this example Lwip code to understand:

    0677.Hercules_Ethernet_Bootloader.zip

    --

    Thanks & regards,
    Jagadish.