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.

AM263P4: LwIP example issue on custom board

Part Number: AM263P4
Other Parts Discussed in Thread: DP83869, SYSCONFIG, TCA6416, TCA6424

Tool/software:

Hi,

My customer wants to evaluate "Enet LwIP HTTP Server On Bare Metal (No-RTOS)" example on their custom board.
https://dev.ti.com/tirex/explore/content/mcu_plus_sdk_am263px_10_02_00_15/docs/api_guide_am263px/EXAMPLES_ENET_LWIP_CPSW_HTTPSERVER.html
This example works fine on Control Card.

There are a few difference on the custom board compared to Control Card.
- There is no EEPROM to store MAC address.
- There are two DP83867 Ethernet PHY. (one DP83869 on Control card)

The customer changed below points in sysconfig and codes.
Remove I2C:

Remove EEPROM:

Modify syscfg/ti_board_config.c:
- Remove EnetBoard_setMacPort2IOExpanderCfg() function
- Do not call EnetBoard_setMacPort2IOExpanderCfg() in EnetBoard_setupPorts() function.
- Just do "*pAvailMacEntries = 0;" in EnetBoard_getMacAddrList()

Modified ti_board_config.c

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */

#include <stdint.h>
#include <enet.h>
#include "dp83867.h"

#include <enet_apputils.h>
#include <enet_appboardutils.h>

#include <drivers/hw_include/cslr_soc.h>
#include <networking/enet/core/src/phy/generic_phy.h>
#include <networking/enet/core/src/phy/enetphy_priv.h>
#include "ti_board_open_close.h"
#include <kernel/dpl/AddrTranslateP.h>

#include <ti_drivers_config.h>
#include <drivers/i2c.h>
#include <board/ioexp/ioexp_tca6424.h>
#include <board/ioexp/ioexp_tca6416.h>

static void EnetBoard_setMacPort2IOExpanderCfg(void);

/* PHY drivers */
extern Phy_DrvObj_t gEnetPhyDrvDp83867;
extern Phy_DrvObj_t gEnetPhyDrvGeneric;

/*! \brief All the registered PHY specific drivers. */
static const EthPhyDrv_If gEnetPhyDrvs[] =
{
    &gEnetPhyDrvDp83867,    /* DP83867 */
    &gEnetPhyDrvGeneric,   /* Generic PHY - must be last */
};

const EnetPhy_DrvInfoTbl gEnetPhyDrvTbl =
{
    .numHandles = ENET_ARRAYSIZE(gEnetPhyDrvs),
    .hPhyDrvList = gEnetPhyDrvs,
};

/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/**
   TPR:MSS_CTRL:CPSW_CONTROL

   Address offset    0x0000016C
   Physical address  0x0212016C
   Instance          MSS_CTRL
   CPSW_CONTROL_RGMII1_ID_MODE     16  Writing 1'b1 would disable the internal clock delays. And those delays need to be handled on board.
   CPSW_CONTROL_RMII_REF_CLK_OE_N  8   To select the rmii_ref_clk from PAD or from MSS_RCM. 0: clock will be from mss_rcm through IO internal loopback 1: will be from
   CPSW_CONTROL_PORT1_MODE_SEL     2:0 Port 1 Interface
                                         00 = GMII/MII
                                         01 = RMII
                                         10 = RGMII
                                         11 = Not Supported
*/

#define MSS_CPSW_CONTROL_PORT_MODE_RMII                                   (0x1U)
#define MSS_CPSW_CONTROL_PORT_MODE_RGMII                                  (0x2U)

#define EEPROM_MAGIC_NUMBER_VAL                                           (0xEE3355AAU)
#define EEPROM_MAGIC_NUMBER_OFFSET                                        (0x0U)
#define EEPROM_READ_PCB_REV_DATA_OFFSET                                   (0x0022)

#define I2C_EEPROM_MAC_DATA_OFFSET                                        (0x3D)
#define I2C_EEPROM_MAC_CTRL_OFFSET                                        (0x3B)

#define ENET_BOARD_NUM_MACADDR_MAX                                        (3U)
#define ENET_GET_NUM_MAC_ADDR(num)                                        ((num>>3)+1)
#define ENET_MAC_ADDR_VALIDATE_MASK                                       (0x01U)

/* ========================================================================== */
/*                         Structure Declarations                             */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                          Function Declarations                             */
/* ========================================================================== */

static const EnetBoard_PortCfg *EnetBoard_getPortCfg(const EnetBoard_EthPort *ethPort);

static const EnetBoard_PortCfg *EnetBoard_findPortCfg(const EnetBoard_EthPort *ethPort,
                                                      const EnetBoard_PortCfg *ethPortCfgs,
                                                      uint32_t numEthPorts);

static void EnetBoard_enableExternalMux();

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

/*!
 * \brief Common Processor Board (CPB) board's DP83867 PHY configuration.
 */
static const Dp83867_Cfg gEnetCpbBoard_ConfigEnetEthphy1PhyCfg =
{
	.txClkShiftEn         = false,
.rxClkShiftEn         = false,
.txDelayInPs          = 2000U,  /* 2.00 ns */
.rxDelayInPs          = 2000U,  /* 2.00 ns */
.txFifoDepth          = 4U,     /* 4 bytes/nibbles */
.impedanceInMilliOhms = 50000U, /* 50 ohms */
.idleCntThresh        = 5U,
.gpio0Mode            = DP83867_GPIO0_RXERR,
.gpio1Mode            = DP83867_GPIO1_COL,
.ledMode			  =
{
	DP83867_LED_LINKED,
	DP83867_LED_LINKED_1000BT,
	DP83867_LED_RXTXACT,
	DP83867_LED_LINKED_100BTX,
},
};

/*
 * am263px-cc board configuration.
 *
 * RMII/RGMII PHY connected to am263px-cc CPSW_3G MAC port.
 */
static const EnetBoard_PortCfg gEnetCpbBoard_am263px_cc_EthPort[] =
{
    {    /* "CPSW3G" */
        .enetType = ENET_CPSW_3G,
        .instId   = 0U,
        .macPort  = ENET_MAC_PORT_2,
        .mii      = {ENET_MAC_LAYER_GMII, ENET_MAC_SUBLAYER_REDUCED},
        .phyCfg   =
        {
            .phyAddr         = 0,
            .isStrapped      = false,
            .skipExtendedCfg = false,
			.extendedCfg     = &gEnetCpbBoard_ConfigEnetEthphy1PhyCfg,
			.extendedCfgSize = sizeof(gEnetCpbBoard_ConfigEnetEthphy1PhyCfg)
        },
        .flags    = 0U,
    },
};

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

const EnetBoard_PhyCfg *EnetBoard_getPhyCfg(const EnetBoard_EthPort *ethPort)
{
    const EnetBoard_PortCfg *portCfg;

    portCfg = EnetBoard_getPortCfg(ethPort);

    return (portCfg != NULL) ? &portCfg->phyCfg : NULL;
}

static void EnetBoard_enableExternalMux()
{
    /* Enable external MUXes, if any, as per the board design */
}

static const EnetBoard_PortCfg *EnetBoard_getPortCfg(const EnetBoard_EthPort *ethPort)
{
    const EnetBoard_PortCfg *portCfg = NULL;

    if (ENET_NOT_ZERO(ethPort->boardId & ENETBOARD_CPB_ID) ||
        ((portCfg == NULL) && ENET_NOT_ZERO(ethPort->boardId & ENETBOARD_LOOPBACK_ID)))
    {
        portCfg = EnetBoard_findPortCfg(ethPort,
                                        gEnetCpbBoard_am263px_cc_EthPort,
                                        ENETPHY_ARRAYSIZE(gEnetCpbBoard_am263px_cc_EthPort));
    }

    return portCfg;
}

static const EnetBoard_PortCfg *EnetBoard_findPortCfg(const EnetBoard_EthPort *ethPort,
                                                      const EnetBoard_PortCfg *ethPortCfgs,
                                                      uint32_t numEthPorts)
{
    const EnetBoard_PortCfg *ethPortCfg = NULL;
    bool found = false;
    uint32_t i;

    for (i = 0U; i < numEthPorts; i++)
    {
        ethPortCfg = &ethPortCfgs[i];

        if ((ethPortCfg->enetType == ethPort->enetType) &&
            (ethPortCfg->instId == ethPort->instId) &&
            (ethPortCfg->macPort == ethPort->macPort) &&
            (ethPortCfg->mii.layerType == ethPort->mii.layerType) &&
            (ethPortCfg->mii.sublayerType == ethPort->mii.sublayerType))
        {
            found = true;
            break;
        }
    }

    return found ? ethPortCfg : NULL;
}

void EnetBoard_getMiiConfig(EnetMacPort_Interface *mii)
{
    mii->layerType      = ENET_MAC_LAYER_GMII;
    mii->variantType    = ENET_MAC_VARIANT_FORCED;
    mii->sublayerType   = ENET_MAC_SUBLAYER_REDUCED;
}

int32_t EnetBoard_setupPorts(EnetBoard_EthPort *ethPorts,
                             uint32_t numEthPorts)
{
    CSL_mss_ctrlRegs *mssCtrlRegs = (CSL_mss_ctrlRegs *)CSL_MSS_CTRL_U_BASE;

    DebugP_assert(numEthPorts == 1);
    DebugP_assert(ethPorts->mii.sublayerType == ENET_MAC_SUBLAYER_REDUCED);

    EnetBoard_enableExternalMux();

    switch(ethPorts->macPort)
    {
        case ENET_MAC_PORT_1:
            CSL_FINS( mssCtrlRegs->CPSW_CONTROL,MSS_CTRL_CPSW_CONTROL_RGMII1_ID_MODE, 0U);
            CSL_FINS( mssCtrlRegs->CPSW_CONTROL,MSS_CTRL_CPSW_CONTROL_PORT1_MODE_SEL, MSS_CPSW_CONTROL_PORT_MODE_RGMII);
            break;
        case ENET_MAC_PORT_2:
            CSL_FINS( mssCtrlRegs->CPSW_CONTROL,MSS_CTRL_CPSW_CONTROL_RGMII2_ID_MODE, 0U);
            CSL_FINS( mssCtrlRegs->CPSW_CONTROL,MSS_CTRL_CPSW_CONTROL_PORT2_MODE_SEL, MSS_CPSW_CONTROL_PORT_MODE_RGMII);
  ////          EnetBoard_setMacPort2IOExpanderCfg();  Do not call
            break;
        default:
            DebugP_assert(false);
    }

    /* Nothing else to do */
    return ENET_SOK;
}


/* Remove
static void EnetBoard_setMacPort2IOExpanderCfg(void)
{
    EEPROM_Handle  eepromHandle = gEepromHandle[CONFIG_EEPROM0];
    uint8_t    readBuffer[10] = {0};
    uint8_t* pEepromRdPtr = (uint8_t *) &readBuffer;
    int32_t status    = SystemP_SUCCESS;
    uint32_t magicNum = 0;

    status = EEPROM_read(eepromHandle, EEPROM_MAGIC_NUMBER_OFFSET,  pEepromRdPtr, 4);
    memcpy(&magicNum, pEepromRdPtr, sizeof(uint32_t));

    // Check magic number header
    if (magicNum == EEPROM_MAGIC_NUMBER_VAL)
    {
        // Read from Am263Px PCB revision
        status = EEPROM_read(eepromHandle, EEPROM_READ_PCB_REV_DATA_OFFSET, pEepromRdPtr, 2);
        
        if ((pEepromRdPtr[0] == 'E') && (pEepromRdPtr[1] == '1')) // Checking PCB revision E1
        {
            DebugP_logInfo("AM263Px CC E1 Board found\r\n");

            const uint32_t mdioMuxSelLine = 8*1 + 4; // PORT 1, PIN 4
            const uint32_t rgmii1MuxSelLine = 8*0 + 2; // PORT 0, PIN 2
            const uint32_t rgmii2MuxSelLine = 8*0 + 3; // PORT 0, PIN 3
            static TCA6416_Config  gTCA6416_Config;

            TCA6416_Params      TCA6416Params;
            TCA6416_Params_init(&TCA6416Params);
            status = TCA6416_open(&gTCA6416_Config, &TCA6416Params);

            if (status == SystemP_SUCCESS)
            {
                // Configure as output
                status = TCA6416_config(&gTCA6416_Config,
                            mdioMuxSelLine,
                            TCA6416_MODE_OUTPUT);
            }
            if (status == SystemP_SUCCESS)
            {
                status =  TCA6416_setOutput(&gTCA6416_Config, mdioMuxSelLine, TCA6416_OUT_STATE_HIGH);
            }

            if (status == SystemP_SUCCESS)
            {
                // Configure as output  *
                status = TCA6416_config(&gTCA6416_Config,
                            rgmii1MuxSelLine,
                            TCA6416_MODE_OUTPUT);
            }
            if (status == SystemP_SUCCESS)
            {
                status =  TCA6416_setOutput(&gTCA6416_Config, rgmii1MuxSelLine, TCA6416_OUT_STATE_LOW);
            }

            if (status == SystemP_SUCCESS)
            {
                // Configure as output
                status = TCA6416_config(&gTCA6416_Config,
                            rgmii2MuxSelLine,
                            TCA6416_MODE_OUTPUT);
            }
            if (status == SystemP_SUCCESS)
            {
                status =  TCA6416_setOutput(&gTCA6416_Config, rgmii2MuxSelLine, TCA6416_OUT_STATE_LOW);
            }
        }
        else if (((pEepromRdPtr[0] == 'E') && (pEepromRdPtr[1] == '2')) || (pEepromRdPtr[0] == 'A')) // Checking PCB revision Rev E2/Rev A
        {
            DebugP_logInfo("AM263Px CC E2 Board found\r\n");
            const uint32_t mdioMuxSel1Line  = 8*2 + 2; // PORT 2, PIN 2
            const uint32_t mdioMuxSel2Line  = 8*2 + 3; // PORT 2, PIN 3
            const uint32_t rgmii0MuxSelLine = 8*2 + 4; // PORT 2, PIN 4
            const uint32_t rgmii1MuxSelLine = 8*0 + 2; // PORT 0, PIN 2
            const uint32_t rgmii2MuxSelLine = 8*0 + 3; // PORT 0, PIN 3
            static TCA6424_Config  gTCA6424_Config;

            TCA6424_Params      TCA6424Params;
            TCA6424_Params_init(&TCA6424Params);

            status = TCA6424_open(&gTCA6424_Config, &TCA6424Params);

            if (status == SystemP_SUCCESS)
            {
                // Configure as output
                status = TCA6424_config(&gTCA6424_Config,
                            mdioMuxSel1Line,
                            TCA6424_MODE_OUTPUT);
            }
            if (status == SystemP_SUCCESS)
            {
                status =  TCA6424_setOutput(&gTCA6424_Config, mdioMuxSel1Line, TCA6424_OUT_STATE_HIGH);
            }

            if (status == SystemP_SUCCESS)
            {
                // Configure as output
                status = TCA6424_config(&gTCA6424_Config,
                            mdioMuxSel2Line,
                            TCA6424_MODE_OUTPUT);
            }
            if (status == SystemP_SUCCESS)
            {
                status =  TCA6424_setOutput(&gTCA6424_Config, mdioMuxSel2Line, TCA6424_OUT_STATE_HIGH);
            }

            if (status == SystemP_SUCCESS)
            {
                // Configure as output
                status = TCA6424_config(&gTCA6424_Config,
                            rgmii0MuxSelLine,
                            TCA6424_MODE_OUTPUT);
            }
            if (status == SystemP_SUCCESS)
            {
                status =  TCA6424_setOutput(&gTCA6424_Config, rgmii0MuxSelLine, TCA6424_OUT_STATE_LOW);
            }

            if (status == SystemP_SUCCESS)
            {
                // Configure as output
                status = TCA6424_config(&gTCA6424_Config,
                            rgmii1MuxSelLine,
                            TCA6424_MODE_OUTPUT);
            }
            if (status == SystemP_SUCCESS)
            {
                status =  TCA6424_setOutput(&gTCA6424_Config, rgmii1MuxSelLine, TCA6424_OUT_STATE_HIGH);
            }

            if (status == SystemP_SUCCESS)
            {
                // Configure as output
                status = TCA6424_config(&gTCA6424_Config,
                            rgmii2MuxSelLine,
                            TCA6424_MODE_OUTPUT);
            }
            if (status == SystemP_SUCCESS)
            {
                status =  TCA6424_setOutput(&gTCA6424_Config, rgmii2MuxSelLine, TCA6424_OUT_STATE_LOW);
            }
        }
            else
            {
                DebugP_logInfo("AM263Px CC Unable to get version\r\n");
                status = SystemP_FAILURE;
            }
    }
    else
    {
        DebugP_logInfo("AM263Px CC EEPROM NOT FOUND or CURRUPTED\r\n");
        status = SystemP_FAILURE;
    }

}
*/

// Just do *pAvailMacEntries = 0;
void EnetBoard_getMacAddrList(uint8_t macAddr[][ENET_MAC_ADDR_LEN],
                              uint32_t maxMacEntries,
                              uint32_t *pAvailMacEntries)
{
   *pAvailMacEntries = 0;
}

/* Remove
void EnetBoard_getMacAddrList(uint8_t macAddr[][ENET_MAC_ADDR_LEN],
                              uint32_t maxMacEntries,
                              uint32_t *pAvailMacEntries)
{
    int32_t status = ENET_SOK;
    uint32_t macAddrCnt;
    uint32_t i;
    uint8_t numMacMax;
    uint8_t macAddrBuf[ENET_BOARD_NUM_MACADDR_MAX * ENET_MAC_ADDR_LEN];
    uint8_t validNumMac = 0U;

    status = EEPROM_read(gEepromHandle[CONFIG_EEPROM0],  I2C_EEPROM_MAC_CTRL_OFFSET, &numMacMax, sizeof(uint8_t));
    EnetAppUtils_assert(status == ENET_SOK);
    EnetAppUtils_assert(ENET_GET_NUM_MAC_ADDR(numMacMax) <= ENET_BOARD_NUM_MACADDR_MAX);
    EnetAppUtils_assert(pAvailMacEntries != NULL);

    macAddrCnt = EnetUtils_min(ENET_GET_NUM_MAC_ADDR(numMacMax), maxMacEntries);

    status = EEPROM_read(gEepromHandle[CONFIG_EEPROM0], I2C_EEPROM_MAC_DATA_OFFSET, macAddrBuf, (macAddrCnt * ENET_MAC_ADDR_LEN) );
    EnetAppUtils_assert(status == ENET_SOK);

    // Save only those required to meet the max number of MAC entries *
    // Validating that the MAC addresses from the EEPROM are not MULTICAST addresses
    for (i = 0U; i < macAddrCnt; i++)
    {
        if(!(macAddrBuf[i * ENET_MAC_ADDR_LEN] & ENET_MAC_ADDR_VALIDATE_MASK)){
            memcpy(macAddr[validNumMac], &macAddrBuf[i * ENET_MAC_ADDR_LEN], ENET_MAC_ADDR_LEN);
            validNumMac++;
        }
    }

    *pAvailMacEntries = validNumMac;

    if (macAddrCnt == 0U)
    {
        EnetAppUtils_print("EnetBoard_getMacAddrList Failed - IDK not present\n");
        EnetAppUtils_assert(false);
    }
}
*/

/*
 * Get ethernet board id
 */
uint32_t EnetBoard_getId(void)
{
    return ENETBOARD_AM263PX_EVM;
}



void Board_init(void)
{

}

void Board_deinit(void)
{


}


Set PHY part# in sysconfig:
Part# is DP83867. PHY address is 0x3 for port1, 0xC for port2.

Configure MAC address:
Assignment Method is "Manual Entry"
70:ff:76:1d:ec:f2(MAC port1)
70:ff:76:1d:ec:e3(MAC port2)


Configure Static IP: App_allocateIPAddress() in app_main.c
#define IP_ADDR_POOL_COUNT  (2U)
 
const ip_addr_t gStaticIP[IP_ADDR_POOL_COUNT]   =  { IPADDR4_INIT_BYTES(192, 168, 1, 200) /* For NetifIdx = 0 */,  IPADDR4_INIT_BYTES(  10,  64,  1, 200) /* For NetifIdx = 1 */};
 (OR)
const ip_addr_t gStaticIP[IP_ADDR_POOL_COUNT]   =  { IPADDR4_INIT_BYTES(192, 168, 0, 2) /* For NetifIdx = 0 */,  IPADDR4_INIT_BYTES(  10,  64,  0, 2) /* For NetifIdx = 1 */};
 
const ip_addr_t gStaticIPGateway[IP_ADDR_POOL_COUNT] =  { IPADDR4_INIT_BYTES(192, 168, 1, 1) /* For NetifIdx = 0 */, IPADDR4_INIT_BYTES(  10,   64, 1, 1) /* For NetifIdx = 1 */};
 
const ip_addr_t gStaticIPNetmask[IP_ADDR_POOL_COUNT] =  { IPADDR4_INIT_BYTES(255,255,255,0)  /* For NetifIdx = 0 */, IPADDR4_INIT_BYTES(255,255,252,0) /* For NetifIdx = 1 */};
 
 
static void App_allocateIPAddress()
{
    sys_lock_tcpip_core();
 
    for (uint32_t  netifIdx = 0U; netifIdx < ENET_SYSCFG_NETIF_COUNT; netifIdx++)
    {
        netif_set_addr(g_pNetif[NETIF_INST_ID0 + netifIdx],
                                &gStaticIP[NETIF_INST_ID0 + netifIdx],
                                &gStaticIPNetmask[NETIF_INST_ID0 + netifIdx],
                                &gStaticIPGateway[NETIF_INST_ID0 + netifIdx]);
    }
    sys_unlock_tcpip_core();
    return;
}


When running the example, Ethernet link-up fails. Here is CSS log:
  [Cortex_R5_0]
  ==========================
    CPSW LWIP HTTP WEB SERVER 
  ==========================
  EnetAppUtils_reduceCoreMacAllocation: Reduced Mac Address Allocation for CoreId:0 From 4 To 2 
  Mdio_open:318 
  Open MAC port 2
  Mdio_manual_ioctl_handler_ENET_MDIO_IOCTL_C22_READ:495 
  EnetMod_ioctl:1603 
  EnetPhyMdioDflt_readC22:296 
  EnetPhy_readReg:646 
  PHY 3 is alive
  PHY 12 is alive
  Starting lwIP, local interface IP is dhcp-enabled
  [LWIPIF_LWIP] NETIF INIT SUCCESS
  Host MAC address-0 : 70:ff:76:1d:ec:f2
  
  Enet IF UP Event. Local interface IP:0.0.0.0
  Enet IF UP Event. Local interface IP:192.168.1.200

[No more log after this point]

FYI, below is the log with Control Card. Link-up is OK:
[Cortex_R5_0]
==========================
    CPSW LWIP HTTP WEB SERVER
  ==========================
  EnetAppUtils_reduceCoreMacAllocation: Reduced Mac Address Allocation for CoreId:0 From 4 To 2 
  Open MAC port 2
  EnetPht_bindDriver:1873
  PHY 0 is alive
  EnetMod_ioctl:1603 
  Starting lwIP, local interface IP is dhcp-enabled
  [LWIPIF_LWIP] NETIF INIT SUCCESS
  Host MAC address-0 : 70:ff:76:1d:ec:f2
  Enet IF UP Event. Local interface IP:0.0.0.0
  Enet IF UP Event. Local interface IP:192.168.0.2
  Cpsw_handleLinkUp:1626
  MAC Port 2: Link up
  Network Link UP Event
  Network is UP ...


Are there anything missed in their setup?
The customer found below E2E. According to this thread, a few more configurations are needed.
- Adding EXTPHY
- Adding handle in structure
Are they needed?

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1334440/am2632-dp83867-ethernet-phy-driver-support-in-sdk/5091192?tisearch=e2e-sitesearch&keymatch=AM263x%20DP83867# 

Thanks and regards,
Koichiro Tashiro

  • Hi Koichiro,

    Allow me to check on this and get back to you.

    Regards,

    Aswin

  • https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/908/6747.enet_5F00_board_5F00_cfg.c.xdtHi Koichiro,

    For adding and external PHY and removing the I2C EEPROM dependency, modifying the ti_board_config.c directly will not suffice. On rebuilding the example, the changes will be overwritten. Once way to overcome this is to modify the sysconfig template file which generates this code.

    I have attached the sysconfig template file (enet_board_cfg.c.xdt), by using this the user can avoid the I2C and EEPROM dependencies.

    Please follow the steps below for the same,

    1. Replace the {MCU_PLUS_SDK}\source\networking\enet\core\sysconfig\board\.meta\ethphy_cpsw_icssg\templates\am263px\enet_board_cfg.c.xdt wtih the attached enet_board_cfg.c.xdt file.

    2. Now relaunch the example.syscfg of the project.

    3. Then remove EEPROM and I2C from Sysconfig.

    4.  Build the project.

    Steps for addition of DP83867 seems to be correct since it is a TI PHY supported PHY. Also MAC address needs to be kept as manual entry as how it is kept now.

    Can you try with the new template file that I have attached by following the above mentioned steps.

    Best Regards,

    Aswin

  • Hi Aswin,

    Thanks for your reply.

    For adding and external PHY and removing the I2C EEPROM dependency, modifying the ti_board_config.c directly will not suffice. On rebuilding the example, the changes will be overwritten.

    Sorry I should have described the modification process in detail.
    Before modifying the ti_board_config.c, the customer moved the file from "syscfg" folder to project folder.
    Then auto generation for ti_board_config.c is disabled in sysconfig. So it will not be overwritten on rebuild.

    Do you still recommend to use the sysconfig template file?

    And below steps are not needed?

    The customer found below E2E. According to this thread, a few more configurations are needed.
    - Adding EXTPHY
    - Adding handle in structure

    Thanks and regards,
    Koichiro Tashiro

  • Hi Koichiro,

    If the file was modified in this manner, then it would be fine. But I see that the function EnetBoard_setMacPort2IOExpanderCfg() is commented in the attached file.

    This function is responsible for selecting the RGMII 1&2 and MDIO mux line configuration. The configuration would not be done if the function is not called. 

    May I know if the the customer has made the equivalent changes in application or in their custom board hardware. 

    If RGMII/MDIO configs are done here then this function would be required. In that case using the modified xdt file is recommended. 

    Also since the file is now exempted from being generated, changes in some other peripheral will also be not reflected. 

    And below steps are not needed?

    The customer found below E2E. According to this thread, a few more configurations are needed.
    - Adding EXTPHY
    - Adding handle in structure

    These steps would not be required as the PHY is supported out of the box. Those steps were mentioned based on and older SDK

    Thanks & Regards,

    Aswin

  • /*
     *  Copyright (C) 2021 Texas Instruments Incorporated
     *
     *  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 Files                                  */
    /* ========================================================================== */
    
    #include <stdint.h>
    #include <enet.h>
    #include <networking/enet/core/include/phy/enetphy.h>
    #include <dp83869.h>
    #include <enet_apputils.h>
    #include <enet_appboardutils.h>
    #include <drivers/hw_include/cslr_soc.h>
    #include <networking/enet/core/src/phy/enetphy_priv.h>
    #include "ti_board_open_close.h"
    #include <kernel/dpl/AddrTranslateP.h>
    #include "ti_board_config.h"
    
    #if (ENETBOARD_SYSCFG_CUSTOM_BOARD == 1)
    
    #define CONFIG_ENET_CPSW0_PHY0_ADDR (3U)
    #define CONFIG_ENET_CPSW0_PHY1_ADDR (12U)
    
    
    /* PHY drivers */
    extern Phy_DrvObj_t gEnetPhyDrvGeneric;
    extern Phy_DrvObj_t gEnetPhyDrvDp83869;
    
    /*! \brief All the registered PHY specific drivers. */
    static const EthPhyDrv_If gEnetPhyDrvs[] =
    {
        &gEnetPhyDrvDp83869,   /* DP83869 */
        &gEnetPhyDrvGeneric,   /* Generic PHY - must be last */
    };
    
    const EnetPhy_DrvInfoTbl gEnetPhyDrvTbl =
    {
        .numHandles = ENET_ARRAYSIZE(gEnetPhyDrvs),
        .hPhyDrvList = gEnetPhyDrvs,
    };
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /**
       TPR:MSS_CTRL:CPSW_CONTROL
    
       Address offset    0x0000016C
       Physical address  0x0212016C
       Instance          MSS_CTRL
       CPSW_CONTROL_RGMII1_ID_MODE     16  Writing 1'b1 would disable the internal clock delays. And those delays need to be handled on board.
       CPSW_CONTROL_RMII_REF_CLK_OE_N  8   To select the rmii_ref_clk from PAD or from MSS_RCM. 0: clock will be from mss_rcm through IO internal loopback 1: will be from
       CPSW_CONTROL_PORT1_MODE_SEL     2:0 Port 1 Interface
                                             00 = GMII/MII
                                             01 = RMII
                                             10 = RGMII
                                             11 = Not Supported
    */
    
    #define MSS_CPSW_CONTROL_PORT_MODE_RMII                                   (0x1U)
    #define MSS_CPSW_CONTROL_PORT_MODE_RGMII                                  (0x2U)
    
    
    #define I2C_EEPROM_MAC_DATA_OFFSET                                        (0x3D)
    #define I2C_EEPROM_MAC_CTRL_OFFSET                                        (0x3B)
    
    #define ENET_BOARD_NUM_MACADDR_MAX                                        (3U)
    #define ENET_GET_NUM_MAC_ADDR(num) ((num>>3)+1)
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    /* None */
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    static const EnetBoard_PortCfg *EnetBoard_getPortCfg(const EnetBoard_EthPort *ethPort);
    
    static const EnetBoard_PortCfg *EnetBoard_findPortCfg(const EnetBoard_EthPort *ethPort,
                                                          const EnetBoard_PortCfg *ethPortCfgs,
                                                          uint32_t numEthPorts);
    
    static void EnetBoard_enableExternalMux();
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /*!
     * \brief Common Processor Board (CPB) board's DP83869 PHY configuration.
     */
    static const Dp83869_Cfg gEnetCpbBoard_dp83869PhyCfg =
    {
        .txClkShiftEn         = true,
        .rxClkShiftEn         = true,
        .txDelayInPs          = 500U,  /* Value in pecosec. Refer to DLL_RX_DELAY_CTRL_SL field in ANA_RGMII_DLL_CTRL register of DP83869 PHY datasheet */
        .rxDelayInPs          = 500U,  /* Value in pecosec. Refer to DLL_TX_DELAY_CTRL_SL field in ANA_RGMII_DLL_CTRL register of DP83869 PHY datasheet */
        .txFifoDepth          = 4U,
        .impedanceInMilliOhms = 35000,  /* 35 ohms */
        .idleCntThresh        = 4U,     /* Improves short cable performance */
        .gpio0Mode            = DP83869_GPIO0_LED3,
        .gpio1Mode            = DP83869_GPIO1_COL, /* Unused */
        .ledMode              =
        {
            DP83869_LED_LINKED,         /* Unused */
            DP83869_LED_LINKED_100BTX,
            DP83869_LED_RXTXACT,
            DP83869_LED_LINKED_1000BT,
        },
    };
    
    /*
     * AM263x board configuration.
     *
     * 1 x RGMII PHY connected to AM263x CPSW_3G MAC port.
     */
    static const EnetBoard_PortCfg gEnetCpbBoard_am263xEthPort[] =
    {
        {    /* "CPSW3G" */
            .enetType = ENET_CPSW_3G,
            .instId   = 0U,
            .macPort  = ENET_MAC_PORT_1,
            .mii      = { ENET_MAC_LAYER_GMII, ENET_MAC_SUBLAYER_REDUCED },
            .phyCfg   =
            {
                .phyAddr         = 3,
                .isStrapped      = false,
                .skipExtendedCfg = false,
                .extendedCfg     = &gEnetCpbBoard_dp83869PhyCfg,
                .extendedCfgSize = sizeof(gEnetCpbBoard_dp83869PhyCfg),
            },
            .flags    = 0U,
        },
        {    /* "CPSW3G" */
            .enetType = ENET_CPSW_3G,
            .instId   = 0U,
            .macPort  = ENET_MAC_PORT_2,
            .mii      = { ENET_MAC_LAYER_GMII, ENET_MAC_SUBLAYER_REDUCED },
            .phyCfg   =
            {
                .phyAddr         = 12,
                .isStrapped      = false,
                .skipExtendedCfg = false,
                .extendedCfg     = &gEnetCpbBoard_dp83869PhyCfg,
                .extendedCfgSize = sizeof(gEnetCpbBoard_dp83869PhyCfg),
            },
            .flags    = 0U,
        },
    };
    
    /*
     * AM263X dummy board used for MAC loopback setup.
     */
    static const EnetBoard_PortCfg gEnetLpbkBoard_am263xEthPort[] =
    {
        {    /* RGMII MAC loopback */
            .enetType = ENET_CPSW_3G,
            .instId   = 0U,
            .macPort  = ENET_MAC_PORT_1,
            .mii      = { ENET_MAC_LAYER_GMII, ENET_MAC_SUBLAYER_REDUCED },
            .phyCfg   =
            {
                .phyAddr = ENETPHY_INVALID_PHYADDR,
            },
            .flags    = 0U,
        },
        {    /* RMII MAC loopback */
            .enetType = ENET_CPSW_3G,
            .instId   = 0U,
            .macPort  = ENET_MAC_PORT_1,
            .mii      = { ENET_MAC_LAYER_MII, ENET_MAC_SUBLAYER_REDUCED },
            .phyCfg   =
            {
                .phyAddr = ENETPHY_INVALID_PHYADDR,
            },
            .flags    = 0U,
        },
    };
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    const EnetBoard_PhyCfg *EnetBoard_getPhyCfg(const EnetBoard_EthPort *ethPort)
    {
        const EnetBoard_PortCfg *portCfg;
    
        portCfg = EnetBoard_getPortCfg(ethPort);
    
        return (portCfg != NULL) ? &portCfg->phyCfg : NULL;
    }
    
    static void EnetBoard_enableExternalMux()
    {
        /* Enable the  External MUX selection. Applicable for AM263x LP E2 ver board.
         * Has no effect on AM263x LP E1 ver board.
         *
         * For AM263x-LP E2 board:
         *  - GPIO0_1 - RGMII1 MUX Enable PIN:
         *        HIGH to enable
         *        LOW  to disable
         *  - GPIO_58 - MII MUX Enable PIN:
         *        HIGH to enable
         *        LOW  to disable
         */
    
        uint32_t rgmii1MuxEnPinAddr = (uint32_t) AddrTranslateP_getLocalAddr(CONFIG_GPIO1_BASE_ADDR);
        uint32_t miiMuxEnPinAddr    = (uint32_t) AddrTranslateP_getLocalAddr(CONFIG_GPIO58_BASE_ADDR);
    
        GPIO_setDirMode(rgmii1MuxEnPinAddr, CONFIG_GPIO1_PIN, CONFIG_GPIO1_DIR);
        GPIO_setDirMode(miiMuxEnPinAddr, CONFIG_GPIO58_PIN, CONFIG_GPIO58_DIR);
        GPIO_pinWriteHigh(rgmii1MuxEnPinAddr, CONFIG_GPIO1_PIN);
        GPIO_pinWriteHigh(miiMuxEnPinAddr, CONFIG_GPIO58_PIN);
    }
    
    static const EnetBoard_PortCfg *EnetBoard_getPortCfg(const EnetBoard_EthPort *ethPort)
    {
        const EnetBoard_PortCfg *portCfg = NULL;
    
        if (ENET_NOT_ZERO(ethPort->boardId & ENETBOARD_CPB_ID))
        {
            portCfg = EnetBoard_findPortCfg(ethPort,
                                            gEnetCpbBoard_am263xEthPort,
                                            ENETPHY_ARRAYSIZE(gEnetCpbBoard_am263xEthPort));
        }
        if ((portCfg == NULL) &&
            ENET_NOT_ZERO(ethPort->boardId & ENETBOARD_LOOPBACK_ID))
        {
            portCfg = EnetBoard_findPortCfg(ethPort,
                                            gEnetLpbkBoard_am263xEthPort,
                                            ENETPHY_ARRAYSIZE(gEnetLpbkBoard_am263xEthPort));
        }
    
        return portCfg;
    }
    
    static const EnetBoard_PortCfg *EnetBoard_findPortCfg(const EnetBoard_EthPort *ethPort,
                                                          const EnetBoard_PortCfg *ethPortCfgs,
                                                          uint32_t numEthPorts)
    {
        const EnetBoard_PortCfg *ethPortCfg = NULL;
        bool found = false;
        uint32_t i;
    
        for (i = 0U; i < numEthPorts; i++)
        {
            ethPortCfg = &ethPortCfgs[i];
    
            if ((ethPortCfg->enetType == ethPort->enetType) &&
                (ethPortCfg->instId == ethPort->instId) &&
                (ethPortCfg->macPort == ethPort->macPort) &&
                (ethPortCfg->mii.layerType == ethPort->mii.layerType) &&
                (ethPortCfg->mii.sublayerType == ethPort->mii.sublayerType))
            {
                found = true;
                break;
            }
        }
    
        return found ? ethPortCfg : NULL;
    }
    
    int32_t EnetBoard_setupPorts(EnetBoard_EthPort *ethPorts,
                                 uint32_t numEthPorts)
    {
        CSL_mss_ctrlRegs *mssCtrlRegs = (CSL_mss_ctrlRegs *)CSL_MSS_CTRL_U_BASE;
    
        DebugP_assert(numEthPorts == 1);
        DebugP_assert((ethPorts[0].macPort == ENET_MAC_PORT_1)|| (ethPorts[0].macPort == ENET_MAC_PORT_2));
        DebugP_assert(ethPorts[0].mii.sublayerType == ENET_MAC_SUBLAYER_REDUCED);
        EnetBoard_enableExternalMux();
        switch(ethPorts[0].mii.layerType)
        {
            case ENET_MAC_LAYER_MII:
                CSL_FINS( mssCtrlRegs->CPSW_CONTROL,MSS_CTRL_CPSW_CONTROL_PORT1_MODE_SEL, MSS_CPSW_CONTROL_PORT_MODE_RMII);
                CSL_FINS( mssCtrlRegs->CPSW_CONTROL,MSS_CTRL_CPSW_CONTROL_PORT2_MODE_SEL, MSS_CPSW_CONTROL_PORT_MODE_RMII);
                break;
            case ENET_MAC_LAYER_GMII:
                CSL_FINS( mssCtrlRegs->CPSW_CONTROL,MSS_CTRL_CPSW_CONTROL_PORT1_MODE_SEL, MSS_CPSW_CONTROL_PORT_MODE_RGMII);
                CSL_FINS( mssCtrlRegs->CPSW_CONTROL,MSS_CTRL_CPSW_CONTROL_PORT2_MODE_SEL, MSS_CPSW_CONTROL_PORT_MODE_RGMII);
                break;
            default:
                DebugP_assert(false);
        }
    
        /* Nothing else to do */
        return ENET_SOK;
    }
    
    
    void EnetBoard_getMacAddrList(uint8_t macAddr[][ENET_MAC_ADDR_LEN],
                                  uint32_t maxMacEntries,
                                  uint32_t *pAvailMacEntries)
    {
        int32_t status = ENET_SOK;
        uint32_t macAddrCnt;
        uint8_t numMacMax;
        uint32_t i;
        uint8_t macAddrBuf[ENET_BOARD_NUM_MACADDR_MAX * ENET_MAC_ADDR_LEN];
    
        status = EEPROM_read(gEepromHandle[CONFIG_EEPROM0],  I2C_EEPROM_MAC_CTRL_OFFSET, &numMacMax, sizeof(uint8_t));
        EnetAppUtils_assert(status == ENET_SOK);
        EnetAppUtils_assert(ENET_GET_NUM_MAC_ADDR(numMacMax) <= ENET_BOARD_NUM_MACADDR_MAX);
        EnetAppUtils_assert(pAvailMacEntries != NULL);
    
        macAddrCnt = EnetUtils_min(ENET_GET_NUM_MAC_ADDR(numMacMax), maxMacEntries);
    
        status = EEPROM_read(gEepromHandle[CONFIG_EEPROM0], I2C_EEPROM_MAC_DATA_OFFSET, macAddrBuf, (macAddrCnt * ENET_MAC_ADDR_LEN) );
        EnetAppUtils_assert(status == ENET_SOK);
    
        /* Save only those required to meet the max number of MAC entries */
        /* TODO Read number of mac addresses from the board eeprom */
        for (i = 0U; i < macAddrCnt; i++)
        {
            memcpy(macAddr[i], &macAddrBuf[i * ENET_MAC_ADDR_LEN], ENET_MAC_ADDR_LEN);
        }
    
        *pAvailMacEntries = macAddrCnt;
    
        if (macAddrCnt == 0U)
        {
            EnetAppUtils_print("EnetBoard_getMacAddrList Failed - IDK not present\n");
            EnetAppUtils_assert(false);
        }
    }
    
    /*
     * Get ethernet board id
     */
    uint32_t EnetBoard_getId(void)
    {
        return ENETBOARD_AM263X_EVM;
    }
    
    void EnetBoard_getMiiConfig(EnetMacPort_Interface *mii)
    {
        mii->layerType      =     ENET_MAC_LAYER_GMII;
        mii->sublayerType   =     ENET_MAC_SUBLAYER_REDUCED;
        mii->variantType    =     ENET_MAC_VARIANT_FORCED;
    }
    
    #endif /*#if (ENETBOARD_SYSCFG_CUSTOM_BOARD == 1) */
    

    Hi Koichiro, 

    While working on custom board, for Enet integration, the following documentation can be referred.

    https://software-dl.ti.com/mcu-plus-sdk/esd/AM263PX/10_02_00_15/exports/docs/api_guide_am263px/enet_migration_guide_top.html#CustomBoardSupport

    I have a added a .c file which is a template file that the customer can use. There are placeholder code in the file for PHY, MAC Address and port setup configurations. Additionally the custom board option needs to be enabled in sysconfig.

    By enabling this, the enet related code that is generated in ti_board_config.c and ti_board_config.h will be removed. Customer can then use the template file to include the configurations.

    Regards,

    Aswin