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