EtherCAT SubDevice
 
Loading...
Searching...
No Matches
PHY Configuration

Overview

The SDK consists of the sample application, the EtherCAT Stack API and a Custom PHY library. Each of these parts must be considered for the PHY configuration. Following sections describe what changes must be made to make PHY configurations or adding a new PHY.

Custom PHY overview

Available PHYs

The EtherCAT SDK is delivered with the following PHY drivers. The source and header files can be found in the custom_phy folder of the Industrial Communication SDK examples folder.

PHY Name
TI DP83869
TI DP83826e
TI DP83826b

API

The SDK provides an API to configure the PHYs:

Custom PHY function Description
CUST_PHY_CBregisterReset Register PHY reset function
EC_API_SLV_registerPhy Register PHY index, MII address, link polarity and use of RxLink
CUST_PHY_CBregisterLibDetect Register a PHY not covered by the SDK
CUST_PHY_readReg Read PHY Register
CUST_PHY_writeReg Write PHY Register

Integrating new PHYs

In this section the integration of new PHYs, which are not convered by the SDK delivery, is shown from a example perspective. Before you consider a PHY, please make sure that it suppports the EtherCAT network. For more information refer to the Beckhoff Application Note –PHY Selection Guide on the Beckhoff home page.

The new PHY in this example is named "ADIN1200".

Changing the SysConfig configuration

In the "TI Board Drivers" section, select the "ETHPHY" module and change the following:

  • In "CONFIG_ETHPHY0", change the "ETHPHY Device" to "CUSTOM".
  • In the same config, change the "MDIO Phy Address" to the one of the custom PHY. In this example the address is 10.
  • In the same config, change the "Custom Device Name" to "CUST_PHY".
  • In "CONFIG_ETHPHY1", change the "ETHPHY Device" to "CUSTOM".
  • In the same config, change the "MDIO Phy Address" to the one of the custom PHY. In this example the address is 20.
  • In the same config, change the "Custom Device Name" to "CUST_PHY".
SysConfig changes for new PHY 1
SysConfig changes for new PHY 2

Depending on the actual hardware, there might be other changes which must be done e.g. in the GPIO section.

Writing the PHY drivers, adding them to the project

While writing a PHY driver is the responsibility of the corresponding developer, the existing drivers can be used as templates. You can find the files in your Industrial Communications SDK installation folder under examples/industrial_comms/custom_phy/.

The drivers consist of three parts:

  1. Defines
  2. Function declarations
  3. Function definitions

The first two defines you will notice are:

#define CUST_PHY_ADIN1200_IEEE_IDENT (0x0283BC20u)
#define CUST_PHY_ADIN1200_IEEE_IDENT_MASK (0xFFFFFFF0u)

These are important to automatically detect which PHYs are connected to the controller. The value will compared in the function CUST_PHY_ADIN1200_detect(), which is also responsible for connecting the functions to the TI PHY interface:

int16_t CUST_PHY_ADIN1200_detect(void* pPhyLibCtxt_p, uint32_t phyId_p, CUST_PHY_SPhyDescriptor_t *pPhyLibDesc_p)
{
int16_t retVal = -CUST_PHY_STATUS_ERROR_UNKNOWN_PHY;
OSALUNREF_PARM(pPhyLibCtxt_p);
/* exact match */
if ((phyId_p & CUST_PHY_ADIN1200_IEEE_IDENT_MASK) == CUST_PHY_ADIN1200_IEEE_IDENT)
{
OSAL_printf("ADIN1200 detected\r\n");
pPhyLibDesc_p->softwareReset = CUST_PHY_ADIN1200_softwareReset;
pPhyLibDesc_p->softwareRestart = CUST_PHY_ADIN1200_softwareRestart;
pPhyLibDesc_p->enableAutoMDIX = CUST_PHY_ADIN1200_enableAutoMDIX;
pPhyLibDesc_p->setMiiMode = CUST_PHY_ADIN1200_setMIIMode;
pPhyLibDesc_p->setPowerMode = CUST_PHY_ADIN1200_setPowerMode;
pPhyLibDesc_p->getPowerMode = CUST_PHY_ADIN1200_getPowerMode;
pPhyLibDesc_p->configMLED = CUST_PHY_ADIN1200_configMLED;
pPhyLibDesc_p->enableExtFD = CUST_PHY_ADIN1200_enableExtFD;
pPhyLibDesc_p->enableODDNibbleDet = CUST_PHY_ADIN1200_enableODDNibbleDet;
pPhyLibDesc_p->enableRxErrIdle = CUST_PHY_ADIN1200_enableRxErrIdle;
pPhyLibDesc_p->configLed = CUST_PHY_ADIN1200_configLed;
pPhyLibDesc_p->configLedBlink = CUST_PHY_ADIN1200_configLedBlink;
pPhyLibDesc_p->enableFastLinkDownDet = CUST_PHY_ADIN1200_enableFastLinkDownDet;
pPhyLibDesc_p->enableFastRXDVDet = CUST_PHY_ADIN1200_enableFastRXDVDet;
pPhyLibDesc_p->configSwStrapDone = CUST_PHY_ADIN1200_cofigSwStrapDone;
pPhyLibDesc_p->setLinkConfig = CUST_PHY_ADIN1200_setLinkConfig;
pPhyLibDesc_p->getAutoNegotiation = CUST_PHY_ADIN1200_getAutoNegotiation;
pPhyLibDesc_p->setAutoNegotiation = CUST_PHY_ADIN1200_setAutoNegotiation;
pPhyLibDesc_p->setMdixMode = CUST_PHY_ADIN1200_setMdixMode;
pPhyLibDesc_p->getMdixMode = CUST_PHY_ADIN1200_getMdixMode;
pPhyLibDesc_p->disable1GbAdver = CUST_PHY_ADIN1200_disable1GbAdver;
pPhyLibDesc_p->rgmiiLowLatencyEnable = CUST_PHY_ADIN1200_rgmiiLowLatencyEnable;
pPhyLibDesc_p->rgmiiTxHalfFullThreshold = CUST_PHY_ADIN1200_rgmiiTxHalfFullThreshold;
pPhyLibDesc_p->rgmiiRxHalfFullThreshold = CUST_PHY_ADIN1200_rgmiiRxHalfFullThreshold;
pPhyLibDesc_p->getSpeedDuplex = CUST_PHY_ADIN1200_getSpeedDuplex;
pPhyLibDesc_p->openFxn = CUST_PHY_ADIN1200_openFxn;
pPhyLibDesc_p->commandFxn = CUST_PHY_ADIN1200_commandFxn;
pPhyLibDesc_p->closeFxn = CUST_PHY_ADIN1200_closeFxn;
retVal = 0;
}
return retVal;
}

The detect function "CUST_PHY_ADIN1200_detect()" must be added to the struct "CUST_PHY_knownImplementation_s", which is defined in "CUST_PHY_base.c".

static CUST_PHY_CBextPhyLibDetect_t CUST_PHY_knownImplementation_s [] =
{
#if (defined CUST_PHY_DP83869) && (1==CUST_PHY_DP83869)
CUST_PHY_DP83869_detect,
#endif
#if (defined CUST_PHY_ADIN1200) && (1==CUST_PHY_ADIN1200)
CUST_PHY_ADIN1200_detect,
#endif
#if (defined CUST_PHY_DP83826) && (1==CUST_PHY_DP83826)
CUST_PHY_DP83826E_detect,
CUST_PHY_DP83826B_detect,
#endif
NULL
};

The define "CUST_PHY_ADIN1200" must be added to the "Predefined Symbols" section of the CCS project.

Functions like "CUST_PHY_ADIN1200_softwareReset()" must be written accordingly to the PHY datasheet. Because of our current architecture not implementing these functions isn't an option. If the function isn't needed, the function body can be left empty.

Assuming the new PHY drivers are named accordingly to the existing ones and are placed in the Industrial Communications SDK directory under "/examples/industrial_comms/custom_phy/src/" and "/inc", select both files "CUST_PHY_ADIN1200.c" and "CUST_PHY_ADIN1200.c" and drag and drop them into the project in the Project Explorer. Following window appears, asking how to import the files to the project. Adopt these changes:

Adding new files to the project
Adapt the example project configuration

The example project abstracts the board initialization with functions written for the demo. The function "EC_SLV_APP_SS_registerStacklessBoardFunctions()" in "ecSubDeviceSimple.c" calls three APIs:

  • ESL_BOARD_OS_registerPhys()
  • CUST_PHY_CBregisterLibDetect()
  • CUST_PHY_CBregisterReset()

The first one is a API written exclusively for the example and calls the stack API "EC_API_SLV_registerPhy()", which takes, apart from the context handle, four parameters:

Parameter Description
phyIdx Index of the PHY (0/1)
phyAddr PHY address on MII bus
invertLinkPolarity true: link polarity active high, false: link polarity active low
useRxLinkPin true: use RxLink pin for Link Detection, false: use MDIO state machine

In the example, these parameters are defined in "ESL_BOARD_config.h" and must be adapted according to the PHY:

#define ECAT_PHYADDR_IN (10u)
#define ECAT_PHYADDR_OUT (20u)
#define ECAT_PHYPOLINVERT_IN (true)
#define ECAT_PHYPOLINVERT_OUT (true)
#define ECAT_PHYUSERXLINK_IN (true)
#define ECAT_PHYUSERXLINK_OUT (true)

The second API registers the function "CUST_PHY_detect()" from "CUST_PHY_base.c", the third API registers functions regarding the PHY reset as a callback, which are then called from the stack.