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.

RTOS/PROCESSOR-SDK-AM437X: IGMP issues

Part Number: PROCESSOR-SDK-AM437X

Tool/software: TI-RTOS

My program opens 2 udp sockets:  port #1: ip 192.168.1.16 and port 6000 on eth0 and port #2:  ip 192.168.2.33 and port 6000 and
Then it joins port #1 to a multicast group 226.10.1.7 and port #2 to a multicast group 226.10.2.7.

Both Ethernett interfaces of the board are connected to a network switch. A PC is connected to the switch too.

The wireshark only shows IGMP messages from ip 192.168.2.33. It shows 4 messages: 2 for 226.10.1.7 and 2 for 226.10.2.7. It shows no messages from ip 192.168.1.16.

Following are the functions that open the socket and join to group.

ERROR_CODES_T UDP::Open (uint32_t ipAddr, uint16_t port)
{
    SOCKET sock;
    struct sockaddr_in sockAddress;
    int sockOption;
	
    // Create the socket.
    sock = NDK_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock == INVALID_SOCKET)
    {
        return EC_FAIL;
    }

    // Bind the port to a socket
    bzero(&sockAddress, sizeof(struct sockaddr_in));
    sockAddress.sin_family = AF_INET;
    sockAddress.sin_port = port;
    sockAddress.sin_addr.s_addr = ipAddr;

    if (SOCKET_ERROR == NDK_bind(sock, (struct sockaddr *)&sockAddress, sizeof(struct sockaddr_in)))
    {
        return EC_FAIL;
    }

    // Sets the socket option for broadcast packet.
    sockOption = TRUE;
    if (SOCKET_ERROR == NDK_setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (void *)&sockOption, sizeof(int)))
    {
        return EC_FAIL;
    }

    // Set the buffer size for output.
    sockOption = 8192;
    if (SOCKET_ERROR == NDK_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sockOption, sizeof(int)))
    {
        return EC_FAIL;
    }

    // Set the buffer size for input.
    sockOption = 8192;
    if (SOCKET_ERROR == NDK_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sockOption, sizeof(int)))
    {
        return EC_FAIL;
    }

    // Success.
    socketPtr = sock;
    state = OPENED;

    return EC_SUCCESS;
} // Open

ERROR_CODES_T UDP::Join (uint32_t multIpAddr)
{
    struct ip_mreq mreq;

    // Create the structure for the Multicast address socket options.
    bzero(&mreq, sizeof(struct ip_mreq));
    mreq.imr_multiaddr.s_addr = multIpAddr;
    mreq.imr_interface.s_addr = LocalIpAddr();

    // Join the group.
    if (SOCKET_ERROR == NDK_setsockopt(socketPtr, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)))
    {
        return EC_FAIL;
    }

    return EC_SUCCESS;
} // Join


Do you see anything wrong with the code?
Have you seen this behaviour before?
Do you have any clue?


Installed itens:
CCS 7.2
GCC ARM Compiler 4.9.3
processor_sdk_rtos_am437x  4.00.00.04
am437x PDK v1.0.7
bios 6.46.05.55
xdctools 3.32.02.25_core

Board: AM437x Starter Kit


regards,
Marcio.

  • The RTOS team have been notified. They will respond here.
  • Hi !

    Have you got a chance to look into my problem with the IGMP?

    regards,

    Marcio.

  • Sorry about the delay. There were holidays last week in the USA. I have escalated the request.
  • Hi,

    Do have any feedback on my issue? Did you managed to reproduce the problem?

    regards,

    Marcio.

  • Hi,

    Sorry for the late! Can you provide the CCS projects to reproduce the issue and this needs an EVM with two Ethernet ports, correct? Does you program use NIMU driver and NDK package? What version of NDK?

    Regards, Eric
  • Hi Eric,

    You wrote: Can you provide the CCS projects to reproduce the issue and this needs an EVM with two Ethernet ports, correct?

    Yes, you need a EVM with two Ethernet ports (cpsw), like the  AM437x Starter Kit.
    My CCS program has a lot of code that I cannot make public, I'd have to strip out the extra code and it would take a while. But you can use any CCS project that uses two Ethernet ports. When I opened this thread I have provided the functions used to open the port and configure the IGMP.

    You wrote: Does you program use NIMU driver and NDK package? What version of NDK?

    Yes, it uses NIMU driver and NDK package: processor_sdk_rtos_am437x  4.00.00.04. The CCS is 7.2.

    regards,
    Marcio.

  • Hi,

    Was your test based on the NIMU_BasicExample_skAM437x_armExampleproject example? or the EMAC_BasicExample_skAM437x_armBiosExampleProject?

    If is the NIMU, what parts of the main_skAM437x.c was replaced? How to integrate your code into the test example?

    Regards, Eric
  • Hi,

    Actualy my project is based on NIMU_DualMacExample_idkAM572x_armExampleproject, which was the one recommend by the TI team. I think there isn't an example for AM437x that uses 2 ports.

    Following is the code to inicialize the 2 ports. Call ethInit() procedure to initialize the EMAC and NIMU.

    The changes I've made to the EMAC driver are attached. They are result of other threads.

    MB-pdk_am437x_1_0_7_Fix.zip

    Let me know if you need more stuff.

    regards,

    Marcio.

    #define EMAC_CPSW_PORT0_PHY_ADDR_SK 4  ///< Phy address of the CPSW port 1
    #define EMAC_CPSW_PORT1_PHY_ADDR_SK 5  ///< Phy address of the CPSW port 2
    
    NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[NUM_NIMU_DEVICES + 1];
    
    void ethInit(void)
    {
        EMAC_HwAttrs_V4 cfg;
    
        dcPrint("Initializing Ethernet module...\n");
    
        /* Chip configuration MII/RMII selection */
        ethCpswPortMacModeSelect(0, ETHERNET_MAC_TYPE_RGMII);
        ethCpswPortMacModeSelect(1, ETHERNET_MAC_TYPE_RGMII);
    
        EMAC_socGetInitCfg(0, &cfg);
        cfg.numPorts = 2;
        cfg.port[0].phy_addr = EMAC_CPSW_PORT0_PHY_ADDR_SK;
        cfg.port[1].phy_addr = EMAC_CPSW_PORT1_PHY_ADDR_SK;
        EMAC_socSetInitCfg(0, &cfg);
    
        // Populate the NIMU Device Table to initialize 2 devices (Ethernet interfaces).
        NIMUDeviceTable[0].init = &CpswEmacInit;
        NIMUDeviceTable[1].init = &CpswEmacInit;
        NIMUDeviceTable[2].init =  NULL;
     
    } // ethInit
    
    void ethCpswPortMacModeSelect(uint16_t ethIndex, uint32_t macMode)
    {
        uint32_t portNum = ethIndex + 1;
        uint32_t regVal = 0U;
    
        regVal = HW_RD_REG32(SOC_CONTROL_MODULE_REG + CTRL_GMII_SEL);
    
        switch(macMode)
        {
            case ETHERNET_MAC_TYPE_MII:
            case ETHERNET_MAC_TYPE_GMII:
                if(1U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII1, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII1_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII1_IO_CLK_EN, 0U);
                }
                else if(2U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII2, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII2_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII2_IO_CLK_EN, 0U);
                }
                else
                {
                    /* This error does not happen because of check done already */
                }
                break;
    
            case ETHERNET_MAC_TYPE_RMII: /* RMII */
                if(1U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII1, 1U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII1_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII1_IO_CLK_EN, 0U);
                }
                else if(2U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII2, 1U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII2_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII2_IO_CLK_EN, 0U);
                }
                else
                {
                    /* This error does not happen because of check done already */
                }
                break;
    
            case ETHERNET_MAC_TYPE_RGMII: /* RGMII */
                if(1U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII1, 2U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII1_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII1_IO_CLK_EN, 0U);
                }
                else if(2U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII2, 2U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII2_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII2_IO_CLK_EN, 0U);
                }
                else
                {
                    /* This error does not happen because of check done already */
                }
                break;
    
             default:
             break;
        }
    
        HW_WR_REG32((SOC_CONTROL_MODULE_REG + CTRL_GMII_SEL), regVal);
    } // ethCpswPortMacModeSelect
    


  • Hi,

    Thanks for the details. We only have AM57x EMAC with two Ethernet ports tested and supported int the driver example, but not AM437x. After you changed the AM437x for two ports support, are you able to run two separate Ethernet interfaces and ping them from a PC? If no, there may be some issue in the driver. If yes, then the problem is in the socket programming or the IGMP support in the NDK.

    Regards, Eric
  • Hi Eric,

    Yes, I can receive pings and send replies from/to a PC on both Ethernet interfaces individualy. I can also send and receive UDP messages using unicast adresses.

    I cannot receive UDP multicast messages on the first interface, because the IGMP only works on the second interface (the board sends 2 requests to join a group for the second interface and no requests for the first interface).

    I have provided the functions I use to program the socket and join an IGMP group in the first message of this thread.

    Could you try to reproduce the problem using your AM57x board? I believe the NDK is the same. If it works, the problem may be in between the hardware and driver (NIMU + EMAC) and the NDK would be correct.

    regards,