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/AM3352: Example project for NDK with interrupts

Part Number: AM3352
Other Parts Discussed in Thread: SYSBIOS, AMIC110, , DP83848M, MATHLIB

Tool/software: TI-RTOS

I was hoping there was a 335x example project for one of the EVM or beagle boards that uses the NDK with interrupts. i have been looking at NIMU_BasicExample_bbbAM335x_armExampleProject but that seems to be set up for polling, but i could be wrong. i don't see anywhere in that project where interrupts are initialized. i am also pretty unsure what most of the setup does since i am new to starterware and Soc and the documentation is so sparse for TI-RTOS.

my main issue is getting the interface from NDK to hardware to function and i was hoping i could find an example since there is no documentation on how to set it up (that i found).

my init code is:

/* Chip configuration MII/RMII selection */
SOCCtrlCpswPortMacModeSelect(1, ETHERNET_MAC_TYPE_RMII);
SOCCtrlCpswPortMacModeSelect(2, ETHERNET_MAC_TYPE_RMII);

EMAC_socGetInitCfg(0, &cfg);
cfg.port[0].phy_addr = EMAC_CPSW_PORT0_PHY_ADDR_UTI;
cfg.port[1].phy_addr = EMAC_CPSW_PORT0_PHY_ADDR_UTI;
cfg.macModeFlags = EMAC_CPSW_CONFIG_MODEFLG_FULLDUPLEX;
EMAC_socSetInitCfg(0, &cfg);

NIMUDeviceTable[nimu_device_index++].init = &CpswEmacInit ;
NIMUDeviceTable[nimu_device_index].init = NULL ;

i have the NDK set up in SYSBIOS and it does run. it goes as far as detecting a cable is plugged in but nothing after that (i am expecting DHCP client to be running, which it is because it times out with a failure, but the network does not respond - Yes, the network does do DHCP)

i believe i have all the clocks enabled. using the clock tree tool i see that all the clocks but one come on when you enable the module, but i am unsure of where to turn on the 250MHz clock or how to verify it is already on. i am not sure which register controls it

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

    Please refer to section 1.3 - Flow Charts on SPRUFP2A (ndk_2_25_01_11\docs) - Network Developer's Kit (NDK) Support Package Ethernet Driver Design Guide, for receive path interrupt function.

    The NIMU_BasicExample_bbbAM335x_armExampleProject uses static IP address, see nimu_bbbam335x.cfg: var enableStaticIP = 1; You can verify if the NDK example work by pinging the beagle board with IP address 192.168.1.4.

    The clocks are enabled by BOARD_INIT_MODULE_CLOCK:

    boardCfg = BOARD_INIT_PINMUX_CONFIG |
    BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO;
    Board_init(boardCfg);

    which calls the PRCMModuleEnable() function in pdk_am335x_1_0_x\packages\ti\starterware\soc\am335x\am335x_prcm.c underneath.

    case CHIPDB_MOD_ID_CPSW:
    {
    HW_WR_REG32((SOC_PRCM_REGS + CM_PER_CPGMAC0_CLKCTRL),
    CM_PER_CPGMAC0_CLKCTRL_MODULEMODE_ENABLE);

    while(0U != (HW_RD_REG32(SOC_PRCM_REGS + CM_PER_CPGMAC0_CLKCTRL)
    & CM_PER_CPGMAC0_CLKCTRL_IDLEST));
    }

    The register CM_PER_CPGMAC0_CLKCTRL is described in 8.1.12 Clock Module Registers of AM335x and AMIC110 Sitara™ Processors Technical Reference Manual, SPRUH73P, www.ti.com/.../spruh73

    Regards,
    Garrett

  • that flow chart goes into details i thought was already worked out for the interface between the NDK and the AM335x.

    i guess i should ask is the NIMU_BasicExample_bbbAM335x_armExampleProject a good example on how to set up the hardware interface to the NDK so the AM3352 can operate ethernet? i don't really care if the project is static IP, i already have the cfg file set up for DHCP.  what i need is the interface to be initialized right and working for the RMII2 pins. 

    this is a custom board. i was under the impression that all the hardware interface work was done and available with the SDK and it is simply a matter of a few library calls to get this up and running. certainly the above example project doesn't include a tremendous amount of code to run the HW interface. am i wrong about that?

  • cobsonchael,

    You can choose NIMU example for bbb, evm or icev2 AM335x as baseline to develop your application and setup the hardware interface to NDK, depending on the similarity of your custom board to these boards.

    With a custom board, some modification to SDK is still need. For details please review the training slides "Application Development Using Processor SDK RTOS" at training.ti.com/application-development-using-processor-sdk-rtos . The 'Port' section in the slide describes the board library modification on pinmux, phy...note the platform listed in the slides is AM572x. For AM335x, there is slight difference with regard to pinmux file location which is pdk_am335x_1_0_x\packages\ti\starterware\board\am335x. Check if you have the same PHY device and address as beagle board if you choose NIMU_BasicExample_bbbAM335x_armExampleProject.

    Regards,
    Garrett

  • what we are doing is porting an existing project on to a new custom board with a new processor. i cannot start with an example project and build from that, i had to start from scratch.

    so i believe i have all the boot up parts required to run the emac: pinmux, power controller.

    trying to translate the API for SoC, though is a pain. i can't seem to find an API or a guide that tells me how to initialize the EMAC to a different port than the example project, and of course the example project has NO COMMENTS that help in any fashion.

    i thought that is why this forum exists

    so my startup code for using RMII2, to link all the necessary hardware up so the NDK can run looks like this:

    void InitNimu(void)
    {
    EMAC_HwAttrs_V4 cfg;

    /* Chip configuration MII/RMII selection */
    SOCCtrlCpswPortMacModeSelect(2, ETHERNET_MAC_TYPE_RMII);

    EMAC_socGetInitCfg(2, &cfg);
    cfg.port[0].phy_addr = EMAC_CPSW_PORT0_PHY_ADDR_UTI;
    cfg.port[1].phy_addr = EMAC_CPSW_PORT1_PHY_ADDR_UTI;
    cfg.macModeFlags = EMAC_CPSW_CONFIG_MODEFLG_FULLDUPLEX;
    EMAC_socSetInitCfg(2, &cfg);

    //NIMUDeviceTable[nimu_device_index++].init = NULL ;
    NIMUDeviceTable[0].init = NULL ;
    NIMUDeviceTable[1].init = NULL ;
    NIMUDeviceTable[2].init = &CpswEmacInit ;
    //NIMUDeviceTable[nimu_device_index].init = NULL ;
    }


    is this wrong? if so, what is wrong? is there more that needs to be done than this? when i look at the example project i listed before it seems like this is all that is needed to start up the processor for use with the NDK.
  • i guess let me elaborate why i am confused about this

    first thing i do is look for an example project that can at least set up the hardware for the EMAC and MDIO, since this is stated to be done for me through starterware. i find NIMU_BasicExample_bbbAM335x_armExampleProject and it seems like that is what i want (ie: it actually uses the NDK in the app.cfg file), however there is no comments on how to alter the project to work on a custom board. this is supposed to be an example project, but the lack of comments make it difficult to port to our board.

    when i ask for help i get "here is the document if you want to write the whole emac layer yourself" or "find an example project and base everything on that" which i did. since starterware is supposed to have taken care of this i opt not to write the whole physical layer myself. so assume that the setup i see in the file main_bbbAM335x.c is all that is needed to set up the hardware. i see a task is created which does nothing but output some text (NIMU_log("\n\rSYS/BIOS Ethernet/IP (CPSW) Sample application\n\r"); this doesn't seem like it actually does anything) and not set anything up, and the actual SOC and NIMU calls, so i focus on the latter.

    so now i have to dig to figure out what the code means. again, no comments

    when i find the source code for the routine SOCCtrlCpswPortMacModeSelect i see that the first parameter is the port. great. i see in the source code that port 2 will start to set up RMII2, great. i m must be using port 2.

    so i look up the source code for EMAC_socGetInitCfg, the first parameter is supposed to be the port as well. but wait, i see that if i use 2 as the port number it will be equal to EMAC_NUM_MAX_MAC_PORTS (= 2) which means the code does nothing. so i am not using port 2 or this is a different port. ok, so i look at the pin mux tool and the tech manual and i see that rmii only has rmii1 and rmii2, so i must be port 1? i guess i'll try that

    now i look at the cfg variable, and the port[0] and port[1] members. port is of type emac_cpsw_port, which has EMAC_NUM_MAX_MAC_PORTS(=2) ports. so again i must not be using port 2, which means i am using port 1? i am using this assumption twice now. i'm guessing since they use the same #define they must mean the same thing. so i see in the example they only use the phy_addr member of the structure. i see in the example they define the phy address for both ports to be the same thing so i assume i have to do the same thing? even though i only need to use one port even though i am not sure what that port is since i can't use 2. this is still confusing because i get the config for port 1, but inside of the config for port 1 there are members for port 0 and port 1, so does that mean each port has 2 ports of it's own? that doesn't make any sense but i don't have any comments to clear things up so i guess i will do that the example code does even though i am not clear as to what it does for me or what it really means.

    next i call EMAC_socSetInitCfg which again i assume i use port 1

    then i set my NIMUDeviceTable: in the example they set table entry 0 to CpswEmacInit, but is it entry 0 because that is what the used as a port number for EMAC_socGetInitCfg and EMAC_socSetInitCfg in the example code or is it more like the number of devices is 1 and they start at 0 and go until they hit a null? again there is no documentation in the code for this. when i look in sprufp2b.pdf it only says that i need to populate the callback function and have everything defined but it gives no meaning to the importance of which element is actually filled with the callback functions or what the elements actually mean. when i further look into this document it gives reference to support for the C64+ devices. when i look at the code and see the reason for multiple elements is see it is because of MAX_TABLE_ENTRIES(=3) but that doesn't really answer any questions. i assume that means the number of ports+1 so there can be a null. does that mean i set up element 1? do i leave element 0 as null (nope that causes a service error CIS_SRV_STATUS_FAILED right away at boot)? do i load up both element 0 and 1 with the callback and leave 2 as null (nope, that causes an _exit)? leaving me at thinking just element 0 should be filled out, but the result of that is still no network traffic

    when i go to the tech manual for the AM3352 for clarity to find out which port i should be using for the routine that only accepts 0 or 1 as a port number the only thing i can find is that rmii2 comes out of CPRMII2, but no indication on what port RMII2 uses.

    when i load up what i think is my best guess and run the code i look in my ROV and see that i have no HWI for the emac, which i assumed there should be some dynamically set up from the NIMU code since the example project didn't define anything. i see that NDK stack thread was created as a task but no polling tasks were created either. so there are no interrupts and no polling tasks so there is nothing to alert me of network traffic. well what is the point of the example project if it can't set up the NDK to actually be USED? sure the NDK can start but what can it DO? who sets up the NDK to load but then does nothing with it? even if you could ping it what good is that for an example project? most people need to do more with a system than just have it pinged.

    i hope i was able to show why i feel confused and lost when attempting to get this to work. i feel like there is some simple thing that i am missing that i just missed when trying to figure this out. it would be great to know what i am doing wrong, what i should be doing, and why i am doing the things that i am doing. i don't like answering "i don't know" to the question "why is this set up this way" and i know my boss doesn't like to hear it.
  • I will forward your feedback to our team.

    Before we look into NDK configuration or NIMU device table, let's first ensure the PHYs are setup properly, have you checked MDIOALIVE and MDIOLINK registers? We expect the corresponding bits of PHY address are set in MDIOALIVE register, and link bit is set in MDIOLINK register if there is a link and acknowledge read transaction.

    You may need a custom PhySetupAndReset() code as noted in main_icev2AM335x.c for AM335x ICEv2.

        /* Chip configuration MII/RMII selection */
        PhySetupAndReset();

    Also please check if this thread helps:

    Regards, Garrett

  • i don't know who your focus group is on the code in your projects but i find it hard to believe you expect people to assume what is happening with the code and know exactly what each parameter does or means. i don't think it's too much to ask for example code to explain what is going on so i don't have to assume everything.

    so i don't see PhySetupAndReset in the project NIMU_BasicExample_bbbAM335x_armExampleproject. am i to ASSUME it is in board init since i wasn't looking at the project AM335x ICEv2?

    either way, MDIOALIVE and MDIOLINK are both equal to 0x00000002

  • Do you define EMAC_CPSW_PORT0_PHY_ADDR_UTI as "1"? and how about your EMAC_CPSW_PORT1_PHY_ADDR_UTI define?

    From the MDIOALIVE bits, it doesn't seem you have PHY setup correctly. We expect two bits of PHY ports defined as EMAC_CPSW_PORT0_PHY_ADDR_UTI and EMAC_CPSW_PORT1_PHY_ADDR_UTI are set in MDIOALIVE.

    That is correct PhySetupAndReset is not needed for project bbbAM335x, however if your custom board is different with bbb, you do need a similar function to get PHY setup and reset per schematic and PHY data sheet, or you need cover it in your custom board init function. What's your PHY part number?

    Regards, Garrett

  • i have EMAC_CPSW_PORT0_PHY_ADDR_UTI defined as 0, as they did in the NIMU example, and EMAC_CPSW_PORT1_PHY_ADDR_UTI defined as 1. i have tried doing it like the example where i only use EMAC_CPSW_PORT0_PHY_ADDR_UTI for both phy_addr, i have tried using EMAC_CPSW_PORT1_PHY_ADDR_UTI as port[1].phy_addr and it doesn't seem to make a difference.

    we have the reset line under control for the phy chip. we are using a TI DP83848M

    why does this project not have PhySetupAndReset ? wouldn't you want to show users what would need to change when they go from a beaglebone to their own custom board? i noticed the same project for the EVM doesn't have this routine as well.
  • Please refer to section 6.4.4 PHY Address of the DP83848 data sheet www.ti.com/.../dp83848m and your board schematic to configure EMAC_CPSW_PORT0_PHY_ADDR_UTI and EMAC_CPSW_PORT1_PHY_ADDR_UTI accordingly. "The PHY Address pins are shared with the RXD and COL pins. Each DP83848x or port sharing an MDIO bus in a system must have a unique physical address."

    The beagle board uses PHY LAN8710A. Do you have a comparison table of registers between DP83848M and LAN8710A, which may help in case you run into issues other than PHY address.

    It really has much details/challenges to change from a beaglebone to custom board, as you can see the changes from a beaglebone to ICEv2.

    Regards,
    Garrett
  • looking at the differences in the NIMU projects between BBB and the ICE and EVM boards there aren't a lot of differences. they all have a minimum amount of code to get things running and are all about the same with minor (unexplained) changes. 

    none of this really explains any of the code or questions i have. yes i need to know the PHY address. in the EVM NIMU example there isn't even an EMAC_socGetInitCfg, but in the ice and bbb example there is but i have no idea why. in the comments for the examples the defines for EMAC_CPSW_PORT0_PHY_ADDR_ICE2 and EMAC_CPSW_PORT1_PHY_ADDR_ICE2 both state /**Phy address of the CPSW port 1*/. am i to believe they are both for port 1? in addition the BBB example has the name for the defines that end in EVM. i see we have 2 ports here, both of which have a phy addr. the line of reasoning is that we can attach 2 phy's to this device and so long as they have different addresses we can have 2 different functioning ports. the phy address for which port being used gets input into the cfg.port[x].phy_addr. do i have that right? if so what do i use for EMAC_socGetInitCfg parameter port_num? is that 0 based like the cfg.port access or is it 1 based like the SOCCtrlCpswPortMacModeSelect which uses 1 and 2? how is NIMU device table being accessed? is the index into the NIMU table based on port or something else? in the ice and bbb example EMAC_socSetInitCfg uses 0 for the port number even though the only valid phy address is used on port [1] or port 2.

    i see the phy setup only seems to set GPIO lines, which implies to me it sets up hardware for reset and anything else that prevents the ethernet from running.  in our case we just have the reset line. so that should be covered. 

  • Hi,

    >>Q1) in the EVM NIMU example there isn't even an EMAC_socGetInitCfg, but in the ice and bbb example there is but i have no idea why.
    This mainly depends on if the default values in EMACInitCfg[0] matches the board configuration, e.g the PHY addresses of emac port are configured in EMAC_CpswPorts port[EMAC_NUM_MAX_MAC_PORTS];

    >>Q2) in the comments for the examples the defines for EMAC_CPSW_PORT0_PHY_ADDR_ICE2 and EMAC_CPSW_PORT1_PHY_ADDR_ICE2 both state /**Phy address of the CPSW port 1*/. am i to believe they are both for port 1?
    This is a typo. The two defines are for emac interface port 0 and port 1 respectively.

    >>Q3) the phy address for which port being used gets input into the cfg.port[x].phy_addr. do i have that right?
    Yes, you are right.

    >>Q4) if so what do i use for EMAC_socGetInitCfg parameter port_num? is that 0 based like the cfg.port access or is it 1 based like the SOCCtrlCpswPortMacModeSelect which uses 1 and 2?
    It is 0 based. Actually both ports share the same EMACInitCfg[0] structure. If you use 1 as parameter port_num, it will be rejected, see pdk_am335x_1_0_7\packages\ti\drv\emac\soc\am335x\emac_soc.c.

    Regards,
    Garrett
  • >>Q5) how is NIMU device table being accessed? is the index into the NIMU table based on port or something else?
    The NIMUDeviceTable is referenced in NIMUInit() (ndk_x/packages/ti/ndk/stack/nimu/nimu.c) where it cycles through the NIMU Device Table and initialize all of the listed network devices. The index into NIMU table is not based on port.
  • ok so let me see if i finally have it right. 

    i want to connect my phy chip to RMII2, which should be on port 2 according to SOCCtrlCpswPortMacModeSelect.  my phy chip address should be 1, as i have no pullups on the phy chip address pins and and they default to address 1 due to weak pull up and pull downs.

    so the important parts of the code is to set SOCCtrlCpswPortMacModeSelect(2, ETHERNET_MAC_TYPE_RMII); to set port 2 to use RMII2 pins, EMAC_socGetInitCfg(0, &cfg); because apparently 0 is the only valid port number for this routine call, cfg.port[1].phy_addr = EMAC_CPSW_PORT1_PHY_ADDR_UTI; since port 2 is what i want so i have to tell the drivers what the phy address is for that port, and NIMUDeviceTable[nimu_device_index++].init =  &CpswEmacInit; 

    overall the code looks like

    /**Phy address of the CPSW port 0*/
    #define EMAC_CPSW_PORT0_PHY_ADDR_UTI 0
    /**Phy address of the CPSW port 1*/
    #define EMAC_CPSW_PORT1_PHY_ADDR_UTI 1

    NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_TABLE_ENTRIES];

    extern int CpswEmacInit (STKEVENT_Handle hEvent);

    void InitNimu(void)
    {
    EMAC_HwAttrs_V4 cfg;

    /* Chip configuration MII/RMII selection */
    SOCCtrlCpswPortMacModeSelect(1, ETHERNET_MAC_TYPE_RMII);
    SOCCtrlCpswPortMacModeSelect(2, ETHERNET_MAC_TYPE_RMII);

    EMAC_socGetInitCfg(0, &cfg);
    cfg.port[0].phy_addr = EMAC_CPSW_PORT0_PHY_ADDR_UTI;
    cfg.port[1].phy_addr = EMAC_CPSW_PORT1_PHY_ADDR_UTI;
    cfg.macModeFlags = EMAC_CPSW_CONFIG_MODEFLG_FULLDUPLEX;
    EMAC_socSetInitCfg(0, &cfg);

    //NIMUDeviceTable[nimu_device_index++].init = NULL;//&CpswEmacInit ;
    NIMUDeviceTable[nimu_device_index++].init = &CpswEmacInit;
    NIMUDeviceTable[nimu_device_index].init = NULL ;
    }

    does that seem right?

    another question: you stated before that i had my phy addresses wrong because i did not have 2 bits set in the MDIO_ALIVE/LINK registers, but i only have 1 phy attached to this board so wouldn't i have just the one bit set in those registers?

  • Yes, that's correct configuration code based on your description above.
    If you only have one phy attached with address 1 to your board, instead of two phys and just use port 2, then the one bit set in MDIO_ALIVE/LINK you observed is correct.

    Here the port 2 in starterware function SOCCtrlCpswPortMacModeSelect() really means the port as defined CPSW_3G in TRM, "The CPSW_3G contains two CPGMAC_SL interfaces (ports 1 and 2), one CPPI 3.0 interface Host Port (port 0), Common Platform Time Sync (CPTS), ALE Engine and CPDMA.", which is a bit confusing with the index cfg.port[1] and EMAC_CPSW_PORT1_PHY_ADDR_UTI.

    Regards, Garrett
  • fantastic

    so now that i have that part where we think it should be...

    when i run the code nothing really happens. i mean the NDK runs, i get the open network stuff, the phy comes out of reset, but no traffic that i am aware of. in addition when i look at the ROV i have the NDK main task and DHCP state, lltimertick in clock, but no additional HWIs defined. i would have expected the ethernet HWIs would be used, and if not that some kind of periodic task or clock function would be generated. my DHCP address in the ROV NDK section is always 0.0.0.0. the NDK eventually errors out due to DHCP error (timeout)

    yes i am hooked up to a network with a DHCP service.

    what do i start looking at to figure out why this would behave this way?

  • so i got a BBB and loaded the NIMU example for that into the board. it would appear that the HWI isn't turned on in that project either but it gets an IP address which means it is processing data.

    is there some kind of NIMU code that is gets used or is defined somewhere else and i am somehow linking in the wrong code?
  • looking through the NIMU code in the PDK: C:\ti\pdk_am335x_1_0_7\packages\ti\transport\ndk\nimu i see that the example uses v4 of the NIMU code, which uses polling and not interrupts. i would like to use the interrupts as we have real-time requirements for our project.

    if i want to use interrupts it looks like i want to use v6. the example code only uses v4 and when i look for CpswEmacInit in v6 i see there are no Cpsw functions. i do find EmacInit which seems to be the equivalent but it is static to that file so i am unsure as to how to use it and the documentation for the NIMU module only seems to reference cpsw (ie: v4)

    how do i go about using v6 of the NIMU code so i can take advantage of interrupts?

  • If you connect the bbb or your board to a PC, are you able to successfully ping the IP address?

    Though the packet receive API is EMAC_poll_pkt_v4(), internally it's actually pending on the semaphore EMAC_GLOBAL_RX_SEM_HANDLE(0) which is posted by EMAC interrupt routine EMAC_cpswHwIntRx().


    Regards, Garrett

  • i didn't bother attempting to ping the board since i got a DHCP address and that was enough for me.

    so since it toggles a semaphore i should be able to see a semaphore listed in the ROV associated with some event ID, correct? in addition, i would assume that semaphore lives in a task and i should see some kind of corresponding task that is pending on that semaphore, correct?

    just so i am sure i have the EMAC even running, i have this for my pinmux:

    *((U32 *)(PINMUX_BASE + 0x14c)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (M18) mdio_clk.mdio_clk */
    *((U32 *)(PINMUX_BASE + 0x148)) = ( PIN_INPUT | MUX_MODE0 ); /* (M17) mdio_data.mdio_data */

    *((U32 *)(PINMUX_BASE + 0x70)) = ( PIN_INPUT | MUX_MODE3 ); /* (T17) gpmc_wait0.rmii2_crs_dv */
    *((U32 *)(PINMUX_BASE + 0x74)) = ( PIN_INPUT | MUX_MODE3 ); /* (U17) gpmc_wpn.rmii2_rxer */
    *((U32 *)(PINMUX_BASE + 0x40)) = ( PIN_OUTPUT | MUX_MODE3 ); /* (R13) gpmc_a0.rmii2_txen */
    *((U32 *)(PINMUX_BASE + 0x54)) = ( PIN_OUTPUT | MUX_MODE3 ); /* (V15) gpmc_a5.rmii2_txd0 */
    *((U32 *)(PINMUX_BASE + 0x50)) = ( PIN_OUTPUT | MUX_MODE3 ); /* (R14) gpmc_a4.rmii2_txd1 */
    *((U32 *)(PINMUX_BASE + 0x6c)) = ( PIN_INPUT | MUX_MODE3 ); /* (V17) gpmc_a11.rmii2_rxd0 */
    *((U32 *)(PINMUX_BASE + 0x68)) = ( PIN_INPUT | MUX_MODE3 ); /* (T16) gpmc_a10.rmii2_rxd1 */
    *((U32 *)(PINMUX_BASE + 0x108)) = ( PIN_INPUT | MUX_MODE1 ); /* (H16) gmii1_col.rmii2_refclk */

    and this for my clock enable:

    pass = PRCMModuleEnable(CHIPDB_MOD_ID_CPSW, 0U, 0U);

    which does this:

    *CM_PER_CPGMAC0_CLKCTRL = CM_PER_CPGMAC0_CLKCTRL_MODULEMODE_ENABLE;

    while(0U != (*CM_PER_CPGMAC0_CLKCTRL & CM_PER_CPGMAC0_CLKCTRL_IDLEST));

    does it seem like i am missing anything on this front?

  • If you already got IP address from DHCP server, EMAC should be running. You can verify this by wireshark capture.

    When you check the semaphore from ROV, did you also run wireshark to capture if any packets are in the wire? Also, have you tried to set a breakpoint at EMAC_cpswHwIntRx() in disassembly window to see if it's hit?

    Regards,
    Garrett
  • i got an IP address on the BBB board running the BBB NIMU example. on my custom board i still get nothing. i'm sorry if i did not make that clear.

    i have run wireshark several times and no DHCP packets ever come out of my board.

    i never hit the breakpoint i set in EMAC_cpswHwIntRx

    so apparently my HWI is disabled or not being set for the semaphore somehow.

    my MIR bits when DHCP fails are:

    MIR0: 0xFFFFFFFE  - i don't have any interrupts enabled in MIR0, it seems like almost all of them are

    MIR1: 0xFFFFF9FF - the 9 shows i have 0's for the ethernet interrupts, i assume 0 means off. as an experiment when i run Hwi_EnableMIR1(0x00000600) it sets those bits to 0, which confuses me, i would have thought 1

    MIR2: 0x0000F5EF - the F5xx are the interrupts that i use and turn on, i do not know why xxEF are enabled, i assume some of these that i didn't turn on get turned on by the drivers?

    MIR3: 0xFFFFFFFF - they all seem to be on

    now unless i misinterpret what the MIR bits are (a mask, usually 1 means enabled. i cannot find in the documentation what a 1 means and what a 0 means in this register) it seem like the ethernet HWI are disabled the whole time and are even disabled when i run Hwi_enableMIR

  • well now that i finally got printf working this is what is being output on the console:

    [CortxA8] SetPhyMode:000021E1 Auto:1, FD10:64, HD10:32, FD100:256, HD100:128, FD1000:8192 LPBK:0
    SetPhyMode:000021E1 Auto:1, FD10:64, HD10:32, FD100:256, HD100:128, FD1000:8192 LPBK:0
    Service Status: DHCPC : Enabled : : 000
    Service Status: DHCPC : Enabled : Running : 000
    ENETPHY_FindingState: Timed Out looking for a Phy!
    ENETPHY_FindingState: PhyNum: 1
    ENETPHY_DisablePhy(1)
    Enable Phy to negotiate external connection
    NWAY Advertising: FullDuplex-1000 FullDuplex-100 HalfDuplex-100 FullDuplex-10 HalfDuplex-10
    Phy: 1, NegMode 00A1, NWAYadvertise 01E1, NWAYREadvertise 40A1
    Negotiated connection: HalfDuplex 100 Mbs
    ENETPHY_FindingState: Timed Out looking for a Phy!
    ENETPHY_FindingState: Timed Out looking for a Phy!

    so apparently i am having problems talking to my phy

    does this mean the address i am trying to use is wrong? why would it tell me the LINK and ALIVE bit of the address i provided if it can't find it?
  • You probably already looked into the ENETPHY_FindingState() function in enet_phy.c under pdk_am335x_1_0_7\packages\ti\board\src\bbbAM335x\device. If you have ALIVE bit set in PHY alive status register MDIOALIVE, you really should not see "Timed Out looking for a Phy" after "ENETPHY_FindingState: PhyNum: 1". Did you step into the function ENETPHY_FoundState() to see if your phy is masked and then disabled by ENETPHY_DisablePhy()?

    Regards, Garrett
  • yes, when i look at the phymask it is always 1 or 8, which doesn't help me because my address is 1 so my phy address will show up as 2 from the alive/link register.  i am having a hard time tracking down where the phymask is set

  • Hi,

    You can add the enet_phy.c file (actually any PDK library file) to your CCS project to step in from source and trace why the ENETPHY_DisablePhy() is called if phymask is 1/8.

    Regards,
    Garrett
  • Hi,

    Hope you have made progress on this thread. Were you able to trace down and find out why the ENETPHY_DisablePhy() is called? For phy address 0 with PhyMask 1, the following logic should really not trigger ENETPHY_DisablePhy.

    j =1;
    for(phynum=0; phynum<32; phynum++)
    {
    if(0u!= (PhyMask & j))
    {
    if( CSL_MDIO_isPhyAlive((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, phynum))
    {
    ENETPHY_DisablePhy(hPhyDev,phynum);
    }
    }

    Regarding the phymask initialization, see EMAC_setupCpswInitConfig() in Emac_drv_v4.c,
    if(0U == i)
    {
    /* program phy_mask for port 1 */
    iCfg->macInitCfg[i].PhyMask = ((uint32_t)1U) << (iCfg->baseConfig.port[i].phy_addr);
    iCfg->macInitCfg[i].MLinkMask = 0x0U;
    }
    else
    {
    /* program phy_mask for port 2 */
    iCfg->macInitCfg[i].PhyMask = ((uint32_t)1U)<<(iCfg->baseConfig.port[i].phy_addr);/*corresponding to address 2 */
    iCfg->macInitCfg[i].MLinkMask = 0x1U;
    }/* end of else block covering settings for port 1 */

    -Garrett
  • unfortunately i have not been able to work on this project for some time. i am just getting back into it right now

    the first thing i hit, before i get a disable to my phy is the log message "ENETPHY_FindingState: Timed Out looking for a Phy!\n" and then i get a _ENETPHY_DisablePhy because CSL_MDIO_isPhyAlive fails, even though MDIOALIVE and MDIOLINK are both 0x00000002 (which would make the phy mask of 1 fail)

    when i get the timeout message my MDIOALIVE is set to 2, but the MDIOLINK is not

    based on the code you posted it looks like my phy mask is determined by my cfg.port[x].phy_addr values. those are set before any of this happens, and my addresses are set to 0 and 1 which is what my phy address should be

    when i set both the addresses to 1 i skipped the message and instead got the message "ENETPHY_FindingState: PhyNum: 1" but i am still hitting disablephy. here is the output from running:

    ENETPHY_FindingState: PhyNum: 1
    ENETPHY_FindingState: PhyNum: 1
    ENETPHY_DisablePhy(1)
    Enable Phy to negotiate external connection
    NWAY Advertising: FullDuplex-1000 FullDuplex-100 HalfDuplex-100 FullDuplex-10 HalfDuplex-10
    ENETPHY_DisablePhy(1)
    Enable Phy to negotiate external connection
    NWAY Advertising: FullDuplex-1000 FullDuplex-100 HalfDuplex-100 FullDuplex-10 HalfDuplex-10
    Phy: 1, NegMode 00A1, NWAYadvertise 01E1, NWAYREadvertise 40A1
    Negotiated connection: HalfDuplex 100 Mbs
    Phy: 1, NegMode 00A1, NWAYadvertise 01E1, NWAYREadvertise 40A1
    Negotiated connection: HalfDuplex 100 Mbs

    so it looks like it negotiates a connection (a crappy one but progress is progress) but no DHCP packets seem to be leaving the device.
  • Hi,

    Does the CPSW_STATS Registers indicate any frame received/transmitted? Also how is the LEDs of PHY configured and do the LED_LINK and LED_SPEED indicate correct link status and data rate? Can you confirm the pinmux you are using is specially generated using pinmux tool for your custom board instead of default IDK or EVM board?

    Regards, Garrett

  • here are a couple of screen shots of my CPSW_STATS registers:

    we have a single LED on our board and it only is solid on with blinks with activity and it does that.

    our pinmux code is posted above several posts for RMII2 and i did use the pinmux tool to develop it. i have yet to be told it is wrong (but i'm starting to think that's because nobody looked at it)

    either way here is my pinmux code:

    #define PINMUX_BASE                 ( CONTROL_BASE + 0x800 )

    #define CONTROL_BASE                0x44E10000

    #define PIN_SLOW_SLEW 0x00000040
    #define PIN_INPUT 0x00000020
    #define PIN_OUTPUT 0x00000000
    #define PIN_INPUT_PULLUP 0x00000030
    #define PIN_INPUT_PULLDOWN 0x00000020
    #define PIN_PULL_DISABLE 0x00000008
    #define MUX_MODE0 0x00000000
    #define MUX_MODE1 0x00000001
    #define MUX_MODE2 0x00000002
    #define MUX_MODE3 0x00000003
    #define MUX_MODE4 0x00000004
    #define MUX_MODE5 0x00000005
    #define MUX_MODE6 0x00000006
    #define MUX_MODE7 0x00000007

    void InitPinMux(void)
    {
    *((U32 *)(PINMUX_BASE + 0x1d0)) = ( PIN_INPUT | MUX_MODE0 ); /* (C11) TMS.TMS */
    *((U32 *)(PINMUX_BASE + 0x1d4)) = ( PIN_INPUT | MUX_MODE0 ); /* (B11) TDI.TDI */
    *((U32 *)(PINMUX_BASE + 0x1d8)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (A11) TDO.TDO */
    *((U32 *)(PINMUX_BASE + 0x1dc)) = ( PIN_INPUT | MUX_MODE0 ); /* (A12) TCK.TCK */
    *((U32 *)(PINMUX_BASE + 0x1e0)) = ( PIN_INPUT | MUX_MODE0 ); /* (B10) nTRST.nTRST */
    *((U32 *)(PINMUX_BASE + 0x1e4)) = ( PIN_INPUT | MUX_MODE0 ); /* (C14) EMU0.EMU0 */
    *((U32 *)(PINMUX_BASE + 0x1e8)) = ( PIN_INPUT | MUX_MODE0 ); /* (B14) EMU1.EMU1 */

    *((U32 *)(PINMUX_BASE + 0x88)) = ( PIN_INPUT_PULLUP | MUX_MODE7 ); /* (T13) gpmc_csn3.gpio2[0] */
    *((U32 *)(PINMUX_BASE + 0x8c)) = ( PIN_INPUT_PULLDOWN | MUX_MODE7 ); /* (V12) gpmc_clk.gpio2[1] */
    *((U32 *)(PINMUX_BASE + 0x90)) = ( PIN_INPUT_PULLUP | MUX_MODE7 ); /* (R7) gpmc_advn_ale.gpio2[2] */
    *((U32 *)(PINMUX_BASE + 0x94)) = ( PIN_OUTPUT | MUX_MODE7 ); /* (T7) gpmc_oen_ren.gpio2[3] */
    *((U32 *)(PINMUX_BASE + 0x98)) = ( PIN_INPUT_PULLDOWN | MUX_MODE7 ); /* (U6) gpmc_wen.gpio2[4] */
    *((U32 *)(PINMUX_BASE + 0x9c)) = ( PIN_INPUT_PULLUP | MUX_MODE7 ); /* (T6) gpmc_be0n_cle.gpio2[5] */
    *((U32 *)(PINMUX_BASE + 0x134)) = ( PIN_INPUT_PULLDOWN | MUX_MODE7 ); /* (L17) gmii1_rxd3.gpio2[18] */
    *((U32 *)(PINMUX_BASE + 0x138)) = ( PIN_INPUT_PULLUP | MUX_MODE7 ); /* (L16) gmii1_rxd2.gpio2[19] */
    *((U32 *)(PINMUX_BASE + 0x13c)) = ( PIN_INPUT_PULLUP | MUX_MODE7 ); /* (L15) gmii1_rxd1.gpio2[20] */
    *((U32 *)(PINMUX_BASE + 0x140)) = ( PIN_INPUT_PULLUP | MUX_MODE7 ); /* (M16) gmii1_rxd0.gpio2[21] */

    *((U32 *)(PINMUX_BASE + 0x164)) = ( PIN_INPUT | MUX_MODE7 ); /* (C18) eCAP0_in_PWM0_out.gpio0[7] */
    *((U32 *)(PINMUX_BASE + 0x11c)) = ( PIN_INPUT | MUX_MODE7 ); /* (J18) gmii1_txd3.gpio0[16] */
    *((U32 *)(PINMUX_BASE + 0x120)) = ( PIN_INPUT | MUX_MODE7 ); /* (K15) gmii1_txd2.gpio0[17] */
    *((U32 *)(PINMUX_BASE + 0x124)) = ( PIN_INPUT | MUX_MODE7 ); /* (K16) gmii1_txd1.gpio0[21] */
    *((U32 *)(PINMUX_BASE + 0x20)) = ( PIN_INPUT | MUX_MODE7 ); /* (U10) gpmc_ad8.gpio0[22] */
    *((U32 *)(PINMUX_BASE + 0x24)) = ( PIN_INPUT | MUX_MODE7 ); /* (T10) gpmc_ad9.gpio0[23] */
    *((U32 *)(PINMUX_BASE + 0x28)) = ( PIN_INPUT | MUX_MODE7 ); /* (T11) gpmc_ad10.gpio0[26] */
    *((U32 *)(PINMUX_BASE + 0x2c)) = ( PIN_INPUT | MUX_MODE7 ); /* (U12) gpmc_ad11.gpio0[27] */
    *((U32 *)(PINMUX_BASE + 0x144)) = ( PIN_INPUT_PULLUP | MUX_MODE7 ); /* (H18) rmii1_ref_clk.gpio0[29] */

    *((U32 *)(PINMUX_BASE + 0x0)) = ( PIN_INPUT | MUX_MODE7 ); /* (U7) gpmc_ad0.gpio1[0] */
    *((U32 *)(PINMUX_BASE + 0x4)) = ( PIN_INPUT | MUX_MODE7 ); /* (V7) gpmc_ad1.gpio1[1] */
    *((U32 *)(PINMUX_BASE + 0x8)) = ( PIN_INPUT | MUX_MODE7 ); /* (R8) gpmc_ad2.gpio1[2] */
    *((U32 *)(PINMUX_BASE + 0xc)) = ( PIN_INPUT | MUX_MODE7 ); /* (T8) gpmc_ad3.gpio1[3] */
    *((U32 *)(PINMUX_BASE + 0x10)) = ( PIN_INPUT | MUX_MODE7 ); /* (U8) gpmc_ad4.gpio1[4] */
    *((U32 *)(PINMUX_BASE + 0x14)) = ( PIN_INPUT | MUX_MODE7 ); /* (V8) gpmc_ad5.gpio1[5] */
    *((U32 *)(PINMUX_BASE + 0x18)) = ( PIN_INPUT | MUX_MODE7 ); /* (R9) gpmc_ad6.gpio1[6] */
    *((U32 *)(PINMUX_BASE + 0x1c)) = ( PIN_INPUT | MUX_MODE7 ); /* (T9) gpmc_ad7.gpio1[7] */
    *((U32 *)(PINMUX_BASE + 0x170)) = ( PIN_INPUT | MUX_MODE7 ); /* (E15) uart0_rxd.gpio1[10] */
    *((U32 *)(PINMUX_BASE + 0x30)) = ( PIN_INPUT | MUX_MODE7 ); /* (T12) gpmc_ad12.gpio1[12] */
    *((U32 *)(PINMUX_BASE + 0x34)) = ( PIN_INPUT | MUX_MODE7 ); /* (R12) gpmc_ad13.gpio1[13] */
    *((U32 *)(PINMUX_BASE + 0x38)) = ( PIN_INPUT | MUX_MODE7 ); /* (V13) gpmc_ad14.gpio1[14] */
    *((U32 *)(PINMUX_BASE + 0x3c)) = ( PIN_INPUT | MUX_MODE7 ); /* (U13) gpmc_ad15.gpio1[15] */
    *((U32 *)(PINMUX_BASE + 0x44)) = ( PIN_INPUT | MUX_MODE7 ); /* (V14) gpmc_a1.gpio1[17] */
    *((U32 *)(PINMUX_BASE + 0x48)) = ( PIN_INPUT | MUX_MODE7 ); /* (U14) gpmc_a2.gpio1[18] */
    *((U32 *)(PINMUX_BASE + 0x4c)) = ( PIN_INPUT | MUX_MODE7 ); /* (T14) gpmc_a3.gpio1[19] */
    *((U32 *)(PINMUX_BASE + 0x58)) = ( PIN_INPUT | MUX_MODE7 ); /* (U15) gpmc_a6.gpio1[22] */
    *((U32 *)(PINMUX_BASE + 0x5c)) = ( PIN_INPUT | MUX_MODE7 ); /* (T15) gpmc_a7.gpio1[23] */
    *((U32 *)(PINMUX_BASE + 0x60)) = ( PIN_INPUT | MUX_MODE7 ); /* (V16) gpmc_a8.gpio1[24] */
    *((U32 *)(PINMUX_BASE + 0x64)) = ( PIN_INPUT | MUX_MODE7 ); /* (U16) gpmc_a9.gpio1[25] */
    *((U32 *)(PINMUX_BASE + 0x78)) = ( PIN_INPUT | MUX_MODE7 ); /* (U18) gpmc_be1n.gpio1[28] */
    *((U32 *)(PINMUX_BASE + 0x7c)) = ( PIN_INPUT | MUX_MODE7 ); /* (V6) gpmc_csn0.gpio1[29] */
    *((U32 *)(PINMUX_BASE + 0x80)) = ( PIN_INPUT | MUX_MODE7 ); /* (U9) gpmc_csn1.gpio1[30] */
    *((U32 *)(PINMUX_BASE + 0x84)) = ( PIN_INPUT | MUX_MODE7 ); /* (V9) gpmc_csn2.gpio1[31] */

    *((U32 *)(PINMUX_BASE + 0x114)) = ( PIN_INPUT | MUX_MODE7 ); /* (J16) gmii1_txen.gpio3[3] */
    *((U32 *)(PINMUX_BASE + 0x118)) = ( PIN_INPUT | MUX_MODE7 ); /* (J17) gmii1_rxdv.gpio3[4] */
    *((U32 *)(PINMUX_BASE + 0x188)) = ( PIN_INPUT_PULLUP | MUX_MODE7 ); /* (C17) I2C0_SDA.gpio3[5] */
    *((U32 *)(PINMUX_BASE + 0x18c)) = ( PIN_INPUT | MUX_MODE7 ); /* (C16) I2C0_SCL.gpio3[6] */
    *((U32 *)(PINMUX_BASE + 0x12c)) = ( PIN_INPUT | MUX_MODE7 ); /* (K18) gmii1_txclk.gpio3[9] */
    *((U32 *)(PINMUX_BASE + 0x130)) = ( PIN_INPUT | MUX_MODE7 ); /* (L18) gmii1_rxclk.gpio3[10] */
    *((U32 *)(PINMUX_BASE + 0x234)) = ( PIN_INPUT | MUX_MODE7 ); /* (F15) USB1_DRVVBUS.gpio3[13] */
    *((U32 *)(PINMUX_BASE + 0x19c)) = ( PIN_INPUT | MUX_MODE7 ); /* (C12) mcasp0_ahclkr.gpio3[17] */
    *((U32 *)(PINMUX_BASE + 0x1a0)) = ( PIN_INPUT | MUX_MODE7 ); /* (B12) mcasp0_aclkr.gpio3[18] */
    *((U32 *)(PINMUX_BASE + 0x1a4)) = ( PIN_INPUT | MUX_MODE7 ); /* (C13) mcasp0_fsr.gpio3[19] */
    *((U32 *)(PINMUX_BASE + 0x1ac)) = ( PIN_INPUT | MUX_MODE7 ); /* (A14) mcasp0_ahclkx.gpio3[21] */

    *((U32 *)(PINMUX_BASE + 0x190)) = ( PIN_INPUT | MUX_MODE0 ); /* (A13) mcasp0_aclkx.mcasp0_aclkx */
    *((U32 *)(PINMUX_BASE + 0x194)) = ( PIN_INPUT | MUX_MODE0 ); /* (B13) mcasp0_fsx.mcasp0_fsx */
    *((U32 *)(PINMUX_BASE + 0x198)) = ( PIN_INPUT | MUX_MODE0 ); /* (D12) mcasp0_axr0.mcasp0_axr0 */
    *((U32 *)(PINMUX_BASE + 0x1a8)) = ( PIN_INPUT | MUX_MODE0 ); /* (D13) mcasp0_axr1.mcasp0_axr1 */

    *((U32 *)(PINMUX_BASE + 0x10c)) = ( PIN_INPUT | MUX_MODE4 ); /* (H17) gmii1_crs.mcasp1_aclkx */
    *((U32 *)(PINMUX_BASE + 0x110)) = ( PIN_INPUT | MUX_MODE4 ); /* (J15) gmii1_rxer.mcasp1_fsx */
    *((U32 *)(PINMUX_BASE + 0x128)) = ( PIN_INPUT | MUX_MODE3 ); /* (K17) gmii1_txd0.mcasp1_axr2 */
    *((U32 *)(PINMUX_BASE + 0x144)) = ( PIN_INPUT | MUX_MODE4 ); /* (H18) rmii1_refclk.mcasp1_axr3 */

    *((U32 *)(PINMUX_BASE + 0x14c)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (M18) mdio_clk.mdio_clk */
    *((U32 *)(PINMUX_BASE + 0x148)) = ( PIN_INPUT | MUX_MODE0 ); /* (M17) mdio_data.mdio_data */

    *((U32 *)(PINMUX_BASE + 0x1b0)) = ( PIN_INPUT | MUX_MODE0 ); /* (A15) xdma_event_intr0.xdma_event_intr0 */
    *((U32 *)(PINMUX_BASE + 0x1b4)) = ( PIN_INPUT | MUX_MODE0 ); /* (D14) xdma_event_intr1.xdma_event_intr1 */

    *((U32 *)(PINMUX_BASE + 0x174)) = ( PIN_OUTPUT | MUX_MODE4 ); /* (E16) uart0_txd.eCAP1_in_PWM1_out */

    *((U32 *)(PINMUX_BASE + 0xe0)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (U5) lcd_vsync.lcd_vsync */
    *((U32 *)(PINMUX_BASE + 0xe4)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (R5) lcd_hsync.lcd_hsync */
    *((U32 *)(PINMUX_BASE + 0xe8)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (V5) lcd_pclk.lcd_pclk */
    *((U32 *)(PINMUX_BASE + 0xec)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (R6) lcd_ac_bias_en.lcd_ac_bias_en */
    *((U32 *)(PINMUX_BASE + 0xa0)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (R1) lcd_data0.lcd_data0 */
    *((U32 *)(PINMUX_BASE + 0xa4)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (R2) lcd_data1.lcd_data1 */
    *((U32 *)(PINMUX_BASE + 0xa8)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (R3) lcd_data2.lcd_data2 */
    *((U32 *)(PINMUX_BASE + 0xac)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (R4) lcd_data3.lcd_data3 */
    *((U32 *)(PINMUX_BASE + 0xb0)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (T1) lcd_data4.lcd_data4 */
    *((U32 *)(PINMUX_BASE + 0xb4)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (T2) lcd_data5.lcd_data5 */
    *((U32 *)(PINMUX_BASE + 0xb8)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (T3) lcd_data6.lcd_data6 */
    *((U32 *)(PINMUX_BASE + 0xbc)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (T4) lcd_data7.lcd_data7 */
    *((U32 *)(PINMUX_BASE + 0xc0)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (U1) lcd_data8.lcd_data8 */
    *((U32 *)(PINMUX_BASE + 0xc4)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (U2) lcd_data9.lcd_data9 */
    *((U32 *)(PINMUX_BASE + 0xc8)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (U3) lcd_data10.lcd_data10 */
    *((U32 *)(PINMUX_BASE + 0xcc)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (U4) lcd_data11.lcd_data11 */
    *((U32 *)(PINMUX_BASE + 0xd0)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (V2) lcd_data12.lcd_data12 */
    *((U32 *)(PINMUX_BASE + 0xd4)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (V3) lcd_data13.lcd_data13 */
    *((U32 *)(PINMUX_BASE + 0xd8)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (V4) lcd_data14.lcd_data14 */
    *((U32 *)(PINMUX_BASE + 0xdc)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (T5) lcd_data15.lcd_data15 */

    *((U32 *)(PINMUX_BASE + 0x70)) = ( PIN_INPUT | MUX_MODE3 ); /* (T17) gpmc_wait0.rmii2_crs_dv */
    *((U32 *)(PINMUX_BASE + 0x74)) = ( PIN_INPUT | MUX_MODE3 ); /* (U17) gpmc_wpn.rmii2_rxer */
    *((U32 *)(PINMUX_BASE + 0x40)) = ( PIN_OUTPUT | MUX_MODE3 ); /* (R13) gpmc_a0.rmii2_txen */
    *((U32 *)(PINMUX_BASE + 0x54)) = ( PIN_OUTPUT | MUX_MODE3 ); /* (V15) gpmc_a5.rmii2_txd0 */
    *((U32 *)(PINMUX_BASE + 0x50)) = ( PIN_OUTPUT | MUX_MODE3 ); /* (R14) gpmc_a4.rmii2_txd1 */
    *((U32 *)(PINMUX_BASE + 0x6c)) = ( PIN_INPUT | MUX_MODE3 ); /* (V17) gpmc_a11.rmii2_rxd0 */
    *((U32 *)(PINMUX_BASE + 0x68)) = ( PIN_INPUT | MUX_MODE3 ); /* (T16) gpmc_a10.rmii2_rxd1 */
    *((U32 *)(PINMUX_BASE + 0x108)) = ( PIN_INPUT | MUX_MODE1 ); /* (H16) gmii1_col.rmii2_refclk */

    *((U32 *)(PINMUX_BASE + 0x100)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (G17) mmc0_clk.mmc0_clk */
    *((U32 *)(PINMUX_BASE + 0x104)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (G18) mmc0_cmd.mmc0_cmd */
    *((U32 *)(PINMUX_BASE + 0xfc)) = ( PIN_INPUT | MUX_MODE0 ); /* (G16) mmc0_dat0.mmc0_dat0 */
    *((U32 *)(PINMUX_BASE + 0xf8)) = ( PIN_INPUT | MUX_MODE0 ); /* (G15) mmc0_dat1.mmc0_dat1 */
    *((U32 *)(PINMUX_BASE + 0xf4)) = ( PIN_INPUT | MUX_MODE0 ); /* (F18) mmc0_dat2.mmc0_dat2 */
    *((U32 *)(PINMUX_BASE + 0xf0)) = ( PIN_INPUT | MUX_MODE0 ); /* (F17) mmc0_dat3.mmc0_dat3 */

    *((U32 *)(PINMUX_BASE + 0x16c)) = ( PIN_INPUT | MUX_MODE3 ); /* (E17) uart0_rtsn.I2C1_SCL */
    *((U32 *)(PINMUX_BASE + 0x168)) = ( PIN_INPUT | MUX_MODE3 ); /* (E18) uart0_ctsn.I2C1_SDA */

    *((U32 *)(PINMUX_BASE + 0x21c)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (F16) USB0_DRVVBUS.USB0_DRVVBUS */

    *((U32 *)(PINMUX_BASE + 0x150)) = ( PIN_INPUT | MUX_MODE0 ); /* (A17) spi0_sclk.spi0_sclk */
    *((U32 *)(PINMUX_BASE + 0x154)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (B17) spi0_d0.spi0_d0 */
    *((U32 *)(PINMUX_BASE + 0x158)) = ( PIN_INPUT | MUX_MODE0 ); /* (B16) spi0_d1.spi0_d1 */
    *((U32 *)(PINMUX_BASE + 0x15c)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (A16) spi0_cs0.spi0_cs0 */
    *((U32 *)(PINMUX_BASE + 0x160)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (C15) spi0_cs1.spi0_cs1 */

    *((U32 *)(PINMUX_BASE + 0x180)) = ( PIN_INPUT | MUX_MODE0 ); /* (D16) uart1_rxd.uart1_rxd */
    *((U32 *)(PINMUX_BASE + 0x184)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (D15) uart1_txd.uart1_txd */
    *((U32 *)(PINMUX_BASE + 0x178)) = ( PIN_INPUT | MUX_MODE0 ); /* (D18) uart1_ctsn.uart1_ctsn */
    *((U32 *)(PINMUX_BASE + 0x17c)) = ( PIN_OUTPUT | MUX_MODE0 ); /* (D17) uart1_rtsn.uart1_rtsn */}

  • Hello,
    Let's take a step back and look at your HW implementation.

    Please post the RMII portion of your schematic. Please make sure you include both the PHY and MAC portions as well as interface clocking.
  • There is no GOOD_Rx frames in CPSW_STATS, and Rx_CRC_ERROR indicates the EMAC/PHY is a false connection shown in your previous log - "Negotiated connection: HalfDuplex 100 Mbs". The phy link/connection is probably illegally passed because you set the same phy address to two ports. We have to find out why the ENETPHY_DisablePhy(1) occurs when you set correct phy address for each port.

    >>the first thing i hit, before i get a disable to my phy is the log message "ENETPHY_FindingState: Timed Out looking for a Phy!\n" and >>then i get a _ENETPHY_DisablePhy because CSL_MDIO_isPhyAlive fails, even though MDIOALIVE and MDIOLINK are both 0x00000002 >>(which would >>make the phy mask of 1 fail)
    >>when i get the timeout message my MDIOALIVE is set to 2, but the MDIOLINK is not

    It's expected that port 0/phy Num 0 is disabled when MDIOALIVE and MDIOLINK are both 0x00000002, and after timeout, MDIOLINK is not 2. The port 1/phy num1 should not be disabled with MDIOALIVE and MDIOLINK are both 0x00000002. Were you able to trace abd find out if it's really caused by PhyMask? If so, you can try to comment out the phymask check for port 1 and see if you have any good frame in CPSW_STATS.

    for(phynum=0; phynum<32; phynum++)
    {
    if(0u!= (PhyMask & j))
    {
    if( CSL_MDIO_isPhyAlive((CSL_mdioHandle) ((ENETPHY_DEVICE *) hPhyDev)->miibase, phynum))
    {
    ENETPHY_DisablePhy(hPhyDev,phynum);
    }
    }

    Regards,
    Garrett
  • Also can you dump all the PHY registers from 0x0 to 0x1D? we would like to check if the link parameters are set up correctly.

    Regards,
    Garrett
  • i used:

    ENETPHY_UserAccessRead(hPhyDev, i, 1, &PhyReg[i]);

    to read registers 0-0x1E (extra!) at the top of the routine _ENETPHY_FoundState

    i'm trying to understand how this code runs. based on what i can see it looks like inside of the ENETPHY_Tic routine there is a switch statement that runs several routines based on the current state. so we always go from INIT to FINDING to FOUND, and it is inside FOUND that the _ENETPHY_DisablePhy occurs. based on the code it appears that if the PhyMask is set to something that has a Phy address on it, it will check to see if the phy is alive and IF IT IS it will disable it. this seems to me to be working the way the code intended as it finds a phy at the address, it is alive, and it disables it. i agree that disabling the phy seems like the wrong thing to do but according to the code it appears that it found a phy that is alive and it is disabling it.  is the goal not to get to "FOUND" state? because it seems to me that if we ever have a phy that is ALIVE it will always get disabled.

    so when i set the first port address back to 0 it looks for a phy nonstop and the port that has a valid phy address still negotiates to half duplex. it behaves as if we told it there are 2 phy's on this board and it needs to keep looking for it. is this the intended behavior?

  • here is the schematic page

  • Michael,

    >>is the goal not to get to "FOUND" state? because it seems to me that if we ever have a phy that is ALIVE it will always get disabled.
    It needs to go to "FOUND" state. There is ENETPHY_ResetPhy(hPhyDev,PhyNum) below ENETPHY_DisablePhy which is as explained by my colleague Dave - "The DisablePHY function may be used to reset the PHY via EMAC_RESET after the MAC stabilizes the RMII interface. This prevents the PHY from latching an incorrect configuration on the shared RMII pins."
     
    The emac example for BBB is designed with two ports and the timeout log below was confusing when the example is ported to your board with one PHY. I think the messages is for port 0 only, which is not present.
          ENETPHY_FindingState: Timed Out looking for a Phy!
          ENETPHY_FindingState: Timed Out looking for a Phy!

    From the MDIOALIVE and MDIOLINK, we are sure that port 1 has link up, so now let's focus on half duplex connection. Is the port connected to a PC? Have you tried to set the 'Link Speed & Duplex' of the PC NIC to 100Mbps Full Duplex instead of 'Auto Negotiation'? I am looking into each bit of the PHY registers...

    Regards, Garrett

  • Michael,
    Please provide the total trace-lengths for all RMII signals. Since you are using a common clock, please also provide the clock trace-lengths (RMII CLOCK to PHY) and (RMII CLOCK to MAC) as provided by OSC1.
  • i guess when you were trying to get me to find out why it is calling phy disable i got confused and thought maybe it shouldn't be calling it.

    i know trying to do static IP and pinging the board is the intention of the demo but i have it hooked up to a router and i am trying to get DHCP since i have no intention of ever hooking this device up to a PC.

    is there a way to disable the drivers from looking at port 0 for a phy? i can't have it looking for a PHY at all times forever.
  • Michael,
    Did you add DHCP client code in the demo? The BBB demo by default doesn't support DHCP client. To simplify the debug, I would recommend you directly connect your board to a separated ethernet card in your PC.
    FYI - DHCP example code -e2e.ti.com/.../294840

    It should be able to disable the port 0 from application layer.
  • yes, DHCP is running (as i've stated) and it eventually fails because no packets are leaving my board. i am not running the demo i just took the driver setup from that demo to set up my hardware. i have no problem setting up DHCP from the NDK we've been using the NDK for many years now with very few issues. if i could get the drivers working i think i would be good for this on my project.

    so how do i disable port 0? all the examples seem to be nearly identical and there is no documentation on this that i found so i don't know how to disable port 0 "from the application layer".
  • here is the reply from our board layout guy:

    MDIO_DATA – 46.4 + 6.4 = 52.8mm

    MDIO_CLK – 45.9 + 4.2 = 50.1mm

    RMII2_RXD0 – 30.5 + 2.0 = 32.5mm

    RMII2_RXD1 – 31.8 + 2.2 = 34.0mm

    RMII2_CRS_DV – 34.2 + 4.0 = 36.2mm

    RMII2_RXER – 32.1 + 2.1 = 34.2mm

    RMII2_TXD0 – 28.6 + 5.7 = 34.3mm

    RMII2_TXD1 – 28.4 + 6.8 = 35.2mm

    RMII2_TXEN – 32.5 + 4.8 = 37.3mm

    RMII2_REFCLK (50MHZ_CLOCK) – 51.1mm (OSC1 is placed next to the PHY chip). There is no 22 ohm resistor in this trace.
  • >>so how do i disable port 0? all the examples seem to be nearly identical and there is no documentation on this that i found so i don't know how to disable port 0 >>"from the application layer".

    You can add 'cfg.numPorts = 1' in the following emac soc configuration, also the address port[0] would be physical PHY address 1

         EMAC_socGetInitCfg(0, &cfg);
        cfg.port[0].phy_addr = EMAC_CPSW_PORT0_PHY_ADDR; // = 1
        cfg.port[1].phy_addr = EMAC_CPSW_PORT1_PHY_ADDR; // don't care

        cfg.macModeFlags = EMAC_CPSW_CONFIG_MODEFLG_FULLDUPLEX| EMAC_CPSW_CONFIG_MODEFLG_IFCTLA;

        cfg.numPorts = 1;
        EMAC_socSetInitCfg(0, &cfg);

    How does you Board_init configuration look like? Do you have BOARD_INIT_PINMUX_CONFIG enabled? If so, it may overwrite your pinmux_init(). Can you dump all pinmux registers so we can check?

    Thanks, Garrett

  • thank you for telling me how to disable one port. i thought there might be a command to disable a specific port. i didn't think it would be that simple.

    i don't do any of the board init config from the drivers. to set the pinmux i only call my pimux_init, to set the clocks i call my clock init (which i pulled from the drivers)

    here is the dump for the RMII2 and MDIO pinmux:

  • I find no issues with your RMII2/MDIO pinmux, however I don't see RMII2_CRS_DV, RMII2_RXER, or RMII2_REFLCK dumps. Could you please provide these?
  • oops, missed a picture:

    there is some extra stuff highlighted in there

  • Thanks, these look good too.

    Could you verify that the 50Mhz (OSC1) clock is running?
  • it is. the scope verifies 50MHz

  • Thanks,
    Could you provide the part number for OSC1?
  • Abracon ASV-50.000MHZ-EJ-T.

    www.abracon.com/.../ASV.pdf