Post Go back to editing

ETH0 not transmiting data in ADSP-SC835 SOM + SOMCRR-EZLITE even if loopback test works

Thread Summary

The user is experiencing issues with data transmission from ADSP-SC835 using EMAC0 in a non-loopback configuration. Despite successful link negotiation and error-free DMA descriptor processing, the data does not exit the PHY or is discarded by the router. The final answer suggests reviewing an example project for ADSP-SC598 and adapting it for the ADSP-SC835 to ensure correct configuration and operation.
AI Generated Content
Category: Software
Product Number: ADSP-SC835
Software Version: CCES 3.0.3

Hi, I am working in CCES 3.0.3 with ADSP-SC835W-EV-SOM + SOMCRR breakout board.
I was able to replicate the EMAC0 Loopback sample succesfully, but when I implement a comunication without loopback, aiming to interact with my router and PC connected to the same net, I can't get the data to effectively exit the PHY.

The PHY and MAC configurations are exactly the same that in EMAC0 Looopback sample, with the exception of disabling the Loopback mode and Loopback bits, enabling auto negotiation, and witing for a link to be stablished with the router, which indeed succeeds negotiating a speed of 1000 Mbps Full Duplex.

Phy initialization:

// PHY initialize
void initializePhy(void)
{
	uint16_t deviceid[2], lstat;

	// Reset EMAC
	ADI_GPIO_PADS_RESULT padResult = adi_pads_Config(
			(ADI_GPIO_PADS_CFG)(BITM_PADS_PCFG0_EMACRESET|(ADI_EMAC_PHY_EMACPHYISEL_RGMII<<BITP_PADS_PCFG0_EMACPHYISEL)),true);
	pr_debug("adi_pads_Config 1 result: %i\n\r", padResult);

	// Open EMAC device
	eMACResult = adi_emac_Open( EMAC_DEVICE_NO, EMAC_MEMORY, ADI_EMAC_MEMORY_SIZE, &hemac );
	CHECK_EMAC_RESULT( eMACResult );

	// Configure EMAC0 as little endian
	padResult = adi_pads_Config( (ADI_GPIO_PADS_CFG)(BITM_PADS_PCFG0_EMAC0_ENDIANNESS), false );
	pr_debug("adi_pads_Config 2 result: %i\n\r", padResult);

	// Configure PHY device address and SCLK range
	ePhyresult = adi_emac_phy_Config( &hemac, PHY_DEVICE_ADD, ADI_SCLK_RANGE_100_150, false, false, 0, false, false );
	CHECK_EMAC_RESULT( ePhyresult );

	// Read PHY device ID
	ePhyresult = adi_emac_phy_GetBasicPhyIdentifiers( hemac, deviceid );
	CHECK_EMAC_RESULT( ePhyresult );
	pr_debug("PHY identifiers are 0x%x and 0x%x\n\r", deviceid[0], deviceid[1]);

	// Issue soft reset to PHY
	ePhyresult = adi_emac_phy_IssueSoftReset( hemac );
	CHECK_EMAC_RESULT( ePhyresult );
	pr_debug("PHY reset successful\n\r");

    // Enable auto-negotiation for real network
    ePhyresult = adi_emac_phy_AutonegEnable( hemac, true );
    CHECK_EMAC_RESULT( ePhyresult );

    // Make sure loopback is DISABLED
    ePhyresult = adi_emac_phy_LoopbackEnable( hemac, false );
    CHECK_EMAC_RESULT( ePhyresult );

    // Make sure isolate is DISABLED
    ePhyresult = adi_emac_phy_IsolateEnable( hemac, false );
    CHECK_EMAC_RESULT( ePhyresult );

	/* Configure basic PHY parameters - 1 Gbps, Full Duplex, Collision Test Disabled */
	ePhyresult=adi_emac_phy_SetBasicConfiguration(hemac, true, ADI_EMAC_PHY_SPEED_1000, false);
	CHECK_EMAC_RESULT(ePhyresult);

	/* Disable all loopback bits */
	ePhyresult=adi_emac_phy_RegisterWrite(hemac, ADIN1300_PHY_CTRL_STATUS_1_REG, 0x0);
	CHECK_EMAC_RESULT(ePhyresult);

    // Wait for link and auto-negotiation
    uint16_t status;
    int timeout = 10000;

    do {
        int counter = 1000000;
        while(counter--) { asm("nop;");}
        ePhyresult = adi_emac_phy_RegisterRead( hemac, ADIN1300_PHY_STATUS_1_REG, &status);
        timeout--;
    } while (!(status & ADIN1300_PHY_STATUS_1_REG_LINK_STAT) && timeout > 0);

    if ( timeout > 0 )
    {
        pr_success("PHY Link Established with status: 0x%08x !!!\n\r", status);

        // Read negotiated speed
        lstat = (status >> ADIN1300_PHY_STATUS_1_REG_HCD_TECH_BITP) & 0x7;

        if (lstat == ADIN1300_PHY_STATUS_1_REG_1000FD)
        {
            pr_success("Full Duplex 1000 base T\n\r");
            eMACResult = adi_emac_ConfigureMACSpeed( hemac, ADI_EMAC_MAC_SPEED_1000M );
            CHECK_EMAC_RESULT( eMACResult );
        }
        else if (lstat == ADIN1300_PHY_STATUS_1_REG_1000HD)
        {
            pr_success("Half Duplex 1000 base T\n\r");
            eMACResult = adi_emac_ConfigureMACSpeed( hemac, ADI_EMAC_MAC_SPEED_1000M );
            CHECK_EMAC_RESULT( eMACResult );
        }
        else if (lstat == ADIN1300_PHY_STATUS_1_REG_100FD)
        {
            pr_success("Full Duplex 100 base T\n\r");
            eMACResult = adi_emac_ConfigureMACSpeed( hemac, ADI_EMAC_MAC_SPEED_100M );
            CHECK_EMAC_RESULT( eMACResult );
        }
        else if (lstat == ADIN1300_PHY_STATUS_1_REG_100HD)
        {
            pr_success("Half Duplex 100 base T\n\r");
            eMACResult = adi_emac_ConfigureMACSpeed( hemac, ADI_EMAC_MAC_SPEED_100M );
            CHECK_EMAC_RESULT( eMACResult );
        }
        else if (lstat == ADIN1300_PHY_STATUS_1_REG_10FD)
        {
            pr_success("Full Duplex 10 base T\n\r");
            eMACResult = adi_emac_ConfigureMACSpeed( hemac, ADI_EMAC_MAC_SPEED_10M );
            CHECK_EMAC_RESULT( eMACResult );
        }
        else if (lstat == ADIN1300_PHY_STATUS_1_REG_10HD)
        {
            pr_success("Half Duplex 10 base T\n\r");
            eMACResult = adi_emac_ConfigureMACSpeed( hemac, ADI_EMAC_MAC_SPEED_10M );
            CHECK_EMAC_RESULT( eMACResult );
        }
        else
        {
        	pr_warning("Implement configuration for other speed negotiated: %i\n\r", lstat);
        }
    }
    else
    {
        pr_error("PHY link timeout\n\r");
    }

    pr_success("PHY initialization complete\n\r");
}

MAC initialization:

// Function to initialize EMAC controller
void initializeMac(void)
{
	ADI_EMAC_RESULT  eMACResult = ADI_EMAC_SUCCESS;

	// Set MAC address
	eMACResult = adi_emac_SetMACAddress( hemac, 0, hwaddr );
	CHECK_EMAC_RESULT( eMACResult );

	// MAC configuration - enable duplex mode
//	eMACResult = adi_emac_EnableMACConfigurationModes( hemac, ADI_EMAC_MAC_CONFIG_DUPLEX_ENABLE);
	eMACResult = adi_emac_EnableMACConfigurationModes( hemac, ADI_EMAC_MAC_CONFIG_DUPLEX_ENABLE | ADI_EMAC_MAC_CONFIG_AUTOMATIC_PAD_CRCSTRIP_ENABLE);
	CHECK_EMAC_RESULT( eMACResult );

	// Configure RX frame filters - no filters, pass all types of frames
	eMACResult = adi_emac_EnableRXFrameFilters( hemac, ADI_EMAC_MACFRMFILT_RA|ADI_EMAC_MACFRMFILT_PAC|ADI_EMAC_MACFRMFILT_PM|ADI_EMAC_MACFRMFILT_PR );
	CHECK_EMAC_RESULT( eMACResult );

	// Configure DMA burst - 32 bytes burst for TX, 1 byte burst for RX, fixed burst - false, PBL8 = false
	eMACResult = adi_emac_ConfigureDMABurst( hemac, 0, ADI_EMAC_TRANSMIT_32, ADI_EMAC_RECEIVE_BL_32, false);
	CHECK_EMAC_RESULT( eMACResult );

	// Configure SCB interface
	eMACResult = adi_emac_ConfigureSCBInterface( hemac, 16, 16, ADI_EMAC_SCB_BURSTMODE_16_8_4, false, false, false);
	CHECK_EMAC_RESULT( eMACResult );

	// Configure RX buffer size
	eMACResult = adi_emac_SetRxBuffSizeLimit( hemac, 0, false, RX_BUFFER_SIZE, 0 );
	CHECK_EMAC_RESULT( eMACResult );

	// Enable Tx Queue 0
	eMACResult = adi_emac_EnableTxQueue( hemac, 0, ADI_EMAC_TXQ_ENABLE_GEN );
	CHECK_EMAC_RESULT( eMACResult );

	// Use maximum queue size for EMAC0 = 64*256 = 16384 bytes
	eMACResult = adi_emac_SetTxQueueSize( hemac, 0, 63 );
	CHECK_EMAC_RESULT( eMACResult );

	// Enable Rx Queue 0
	eMACResult = adi_emac_EnableRxQueue( hemac, 0, ADI_EMAC_RXQ_ENABLE_DCB_GEN );
	CHECK_EMAC_RESULT( eMACResult );

	// Use maximum queue size for EMAC0 = 64*256 = 16384 bytes
	eMACResult = adi_emac_SetRxQueueSize( hemac, 0, 63 );
	CHECK_EMAC_RESULT( eMACResult );

	// Configure opmode settings for Tx queue 0
	eMACResult = adi_emac_SetTxQueueOpmode( hemac, 0, false, ADI_EMAC_OPMODE_TTC_32 );
	CHECK_EMAC_RESULT( eMACResult );

	// Configure opmode settings for Rx queue 0
	eMACResult = adi_emac_SetRxQueueOpmode( hemac, 0, false, false, false, ADI_EMAC_OPMODE_RTC_64 );
	CHECK_EMAC_RESULT( eMACResult );

	// Configure DMA in OSF mode if needed
	eMACResult = adi_emac_TxDMAEnableOSFMode( hemac, 0, true );
	CHECK_EMAC_RESULT( eMACResult );

    // Check GIGE MAC link status
	uint32_t Mlstat=0;
	eMACResult =  adi_emac_GigELinkStatus( hemac, &Mlstat );
	CHECK_EMAC_RESULT( eMACResult );

	if ( Mlstat & ADI_EMAC_MAC_GIGE_LINK_UP )
	{
		pr_debug("GIGE MAC Link Status: Link up, Link Speed: ");
	}

	if ( Mlstat & ADI_EMAC_MAC_GIGE_LINK_SPEED_125M )
	{
		pr_debug(" GigE ");
	}
	else if ( Mlstat & ADI_EMAC_MAC_GIGE_LINK_SPEED_25M )
	{
		pr_debug(" 100 ");
	}
	else
	{
		pr_debug(" 10 ");
	}

	if ( Mlstat & ADI_EMAC_MAC_GIGE_LINK_FULLDUPLEX )
	{
		pr_debug(" and Full Duplex\n\r");
	}
	else
	{
		pr_debug(" and Half Duplex\n\r");
	}
}

Raw ARP test message send:

void test_raw_arp_transmission(void)
{
    static uint8_t test_tx_buffer[64] __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
    static ADI_EMAC_DMA_DESC test_tx_desc __attribute__((section(".L1.data"))) ADI_CACHE_ALIGN;
    static uint32_t test_count = 0;

    pr_info("=== Sending RAW ARP Request %i ===\n\r", ++test_count);

    // Build ARP request packet manually
    // Destination MAC: Broadcast
    test_tx_buffer[0] = 0xFF;
    test_tx_buffer[1] = 0xFF;
    test_tx_buffer[2] = 0xFF;
    test_tx_buffer[3] = 0xFF;
    test_tx_buffer[4] = 0xFF;
    test_tx_buffer[5] = 0xFF;

    // Source MAC: Your device
    test_tx_buffer[6] = 0xE1;
    test_tx_buffer[7] = 0x2E;
    test_tx_buffer[8] = 0x4F;
    test_tx_buffer[9] = 0xFF;
    test_tx_buffer[10] = 0x55;
    test_tx_buffer[11] = 0xAB;

    // EtherType: ARP (0x0806)
    test_tx_buffer[12] = 0x08;
    test_tx_buffer[13] = 0x06;

    // ARP Header
    test_tx_buffer[14] = 0x00; test_tx_buffer[15] = 0x01; // Hardware type: Ethernet
    test_tx_buffer[16] = 0x08; test_tx_buffer[17] = 0x00; // Protocol type: IPv4
    test_tx_buffer[18] = 0x06; // Hardware size
    test_tx_buffer[19] = 0x04; // Protocol size
    test_tx_buffer[20] = 0x00; test_tx_buffer[21] = 0x01; // Opcode: Request

    // Sender MAC: Your device
    test_tx_buffer[22] = 0xE1;
    test_tx_buffer[23] = 0x2E;
    test_tx_buffer[24] = 0x4F;
    test_tx_buffer[25] = 0xFF;
    test_tx_buffer[26] = 0x55;
    test_tx_buffer[27] = 0xAB;

    // Sender IP: 192.168.2.100
    test_tx_buffer[28] = 192;
    test_tx_buffer[29] = 168;
    test_tx_buffer[30] = 2;
    test_tx_buffer[31] = 100;

    // Target MAC: 00:00:00:00:00:00 (unknown)
    test_tx_buffer[32] = 0x00;
    test_tx_buffer[33] = 0x00;
    test_tx_buffer[34] = 0x00;
    test_tx_buffer[35] = 0x00;
    test_tx_buffer[36] = 0x00;
    test_tx_buffer[37] = 0x00;

    // Target IP: 192.168.2.230 (your PC)
    test_tx_buffer[38] = 192;
    test_tx_buffer[39] = 168;
    test_tx_buffer[40] = 2;
    test_tx_buffer[41] = 230;

    // Padding to 60 bytes (minimum Ethernet frame size without FCS)
    for (int i = 42; i < 60; i++)
    {
        test_tx_buffer[i] = 0x00;
    }

    // Print what we're sending
    pr_info("Packet contents (60 bytes):\n\r");
    for (int i = 0; i < 60; i++)
    {
        pr_info("%02X ", test_tx_buffer[i]);
        if ((i + 1) % 16 == 0) pr_info("\n\r");
    }
    pr_info("\n\r");

    // Set up TX descriptor
    memset(&test_tx_desc, 0, sizeof(ADI_EMAC_DMA_DESC));

    test_tx_desc.TxDescRead.Buffer1 = (uint32_t)(uintptr_t)test_tx_buffer;
    test_tx_desc.TxDescRead.BufferLen = 60 & ADI_EMAC_TX_DESC_READ_HB1LEN_BITM;
    test_tx_desc.TxDescRead.BufferLen |= ADI_EMAC_TX_DESC_READ_IOC;
    test_tx_desc.TxDescRead.FrameLenCtrl = 60 & ADI_EMAC_TX_DESC_READ_PL_BITM;
    test_tx_desc.TxDescRead.FrameLenCtrl |= ADI_EMAC_TX_DESC_READ_OWN |
                                            ADI_EMAC_TX_DESC_READ_FD |
                                            ADI_EMAC_TX_DESC_READ_LD;

    // Submit descriptor
    eMACResult = adi_emac_SubmitDescriptorListTx(hemac, 0, &test_tx_desc, 1, false);

    if (eMACResult == ADI_EMAC_SUCCESS)
    {
        pr_success("RAW TX submitted successfully\n\r");

        // Wait and check if descriptor was processed
        int counter = 100000000;
        while(counter--) asm("nop;");

        bool busy;
        adi_emac_IsDescriptorBusyTx(&test_tx_desc, &busy);

        if (!busy)
        {
            pr_success("TX descriptor processed by DMA\n\r");

            // Check write-back status
            uint32_t wb_status = test_tx_desc.TxDescWB.Status;
            pr_info("TX WB Status: 0x%08x\n\r", wb_status);

            if (wb_status & 0x8000)
            {
                pr_error("TX had errors! Status: 0x%08x\n\r", wb_status);
            }
            else
            {
                pr_success("TX completed without errors\n\r");
            }
        }
        else
        {
            pr_error("TX descriptor still busy after 100ms\n\r");
        }
    }
    else
    {
        pr_error("RAW TX submit failed: %d\n\r", eMACResult);
    }

    pr_info("===================\n\r\n\r");
}

Main ethernet routine

void inithializeEthernet()
{
	initializePhy();

	initializeMac();

	eMACResult = adi_emac_RegisterTxDmaDataCallback  (hemac, 0, lwip_tx_callback, NULL); CHECK_EMAC_RESULT(eMACResult);
	pr_info("adi_emac_RegisterTxDmaDataCallback: %i\n\r", eMACResult);

	eMACResult = adi_emac_RegisterRxDmaDataCallback (hemac, 0, lwip_rx_callback, NULL); CHECK_EMAC_RESULT(eMACResult);
	pr_info("adi_emac_RegisterRxDmaDataCallback: %i\n\r", eMACResult);

	lwip_rx_desc_init();
	lwip_tx_desc_init();

	eMACResult = adi_emac_SubmitDescriptorListRx(hemac,0,lwip_rx_desc,NUM_RX_BUFFERS, true); CHECK_EMAC_RESULT(eMACResult);
	pr_info("adi_emac_SubmitDescriptorListRx: %i\n\r", eMACResult);


	eMACResult = adi_emac_EnableRx( hemac, true );
	pr_info("adi_emac_EnableRx: %i\n\r", eMACResult);

    eMACResult = adi_emac_EnableTx( hemac, true );
	pr_info("adi_emac_EnableTx: %i\n\r", eMACResult);

	while(1)
	{
        uint32_t counter2 = 1000000000;
        while(counter2--) asm("nop;");

        test_raw_arp_transmission();

		pr_info("EMAC DMA Callbacks: Tx=%i TxPx=%i Rx=%i RxPx=%i\n\r",
				txCallbackCount, txCallbackCountProcessed,
				rxCallbackCount, rxCallbackCountProcessed);
	}
}

The rest of the code not posted here consists of basic clocks configuration as in POST, with SHARC-FX running at 1GHz, EMAC0 SPU enabling, softswitches configuring, and ETH0 hardware resetting.

When running the above code, the link is correctly negotiated with the router, and the green LED in the Ethernet connector goes green. The reception works correctly, which was tested integrating a LwIP stack, initializing the system with a fixed IP and sengind ping messsages from the PC, which the ADSP-SC835 receives correctly verifying general hardware configuration and DMA settings are OK, at least in the reception side (also router, cables, etc).
But when sending the raw ARP data from the SC-835, all the error verifications succeed (DMA switches descriptor ownership as expected, DMA Tx interrupt is triggered, etc) but the data apparently never exites the PHY, or exits corrupted and is discarded by the router, given I can't see any received message in the computer from my ADSP-SC835 IP with Wireshark, and not even in the router system logs.

I tested increasing all the TX pins drive strength to 2, and enabled internal pull downs on PD_03 and PD_04 to ensure the ADIN1300 initializes with the 2ns delay enabled in both Rx and Tx, without achieving any improvement at all.

I also reviewed SOM and SOMCRR schematics looking for any possible influence of softSwitches, but as far as I can see the ETH0 lines are not affected at all by them (except the reset line, which is being managed correctly)

Is there any obvious mistake that I could be doing in the MAC / PHY / DMA settings that could prevent transmission to work as expected? or any other recomendation you could give to help solve this issue?

Thank you,

Leopoldo

Before You Switch


Switching languages will make ADI Explorer unavailable. Resume your session by switching back to English and reopening ADI Explorer.