Other Parts Discussed in Thread: TMDSHSECDOCK, , C2000WARE, TMS320F28386S-Q1
TI Development Kit used:
TMDSCNCD28388D with TMDSHSECDOCK
C2000Ware used:
C2000Ware_4_03_00_00
TI example projects used:
driverlib\f2838x\examples\cm\ethernet\CCS\ethernet_c28x_config.projectspec
libraries\communications\Ethernet\third_party\lwip\examples\enet_lwip_udp
Our custom board microcontroller:
TMS320F28386S-Q1 (F28386S)
Our custom board PHY:
DP83826ERHB
Our board uses a F28386S MCU with a TI DP83826ERHB PHY. It is designed to use RMII ethernet.
After first exercising a TI example successfully on a TI development board kit, I tried to modify
the same example to work on our custom board which uses a F28386S with the same (?) PHY using an RMII ethernet
configuration. The modified example does not work. I am including a zip file of my CCS workspace.
On our board, the CPU1 c28x program partially ran before it stopped itself due to a clock misconfiguration.
It stopped at ESTOP0 within an if-block in Device_init() of project "device.c" line 115.
A code comment there states the check to verify crystal freq is only for XTAL as the PLL source.
My board designer tells me we are using Oscillator 2 as an internal source, not XTAL, so I followed
symbol DEVICE_SETCLOCK_CONFIG to its #define in device.h line 236 using control-click in CCS.
Here I noted several things related to clocks and the clock source which had to be changed
to match our board.
I made some changes, under the assumption that I should maintain a 200Mhz sysclk freq and 125Mhz auxclk.
CHANGES MADE:
File "device.h" (project "ethernet_c28x_config):
(line 230)
I began by changing the DEVICE_OSCSRC_FREQ #define on line 230 from 25000000U to 10000000U
because my board designer told me the internal OSC2 clock runs at 10 MHz, and we use that
instead of an external oscillator.
(line 236)
#define DEVICE_SETCLOCK_CFG (SYSCTL_OSCSRC_XTAL | SYSCTL_IMULT(32) | \
SYSCTL_REFDIV(2) | SYSCTL_ODIV(2) | \
SYSCTL_SYSDIV(1) | SYSCTL_PLL_ENABLE | \
SYSCTL_DCC_BASE_1)
was changed to use OSC2, like this (note the change to IMULT value to maintain 200MHZ SYSCLK freq):
#define DEVICE_SETCLOCK_CFG (SYSCTL_OSCSRC_OSC2 | SYSCTL_IMULT(80) | \
SYSCTL_REFDIV(2) | SYSCTL_ODIV(2) | \
SYSCTL_SYSDIV(1) | SYSCTL_PLL_ENABLE | \
SYSCTL_DCC_BASE_1)
I then changed the next #define, for symbol DEVICE_SYSCLK_FREQ, to match the change to SYSCTL_IMULT
above in order to maintain 200 MHZ:
(line 245)
#define DEVICE_SYSCLK_FREQ ((DEVICE_OSCSRC_FREQ * 32) / (2 * 2 * 1))
was changed to this:
#define DEVICE_SYSCLK_FREQ ((DEVICE_OSCSRC_FREQ * 80) / (2 * 2 * 1))
(line 252)
I left alone the definition of symbol DEVICE_LSPCLK_FREQ, assuming 50 MHZ is still appropriate
(but I really don't know).
For AUXCLK, I made similar changes to adjust for our internal clock frequency and to maintain
125MHZ for AUXCLK:
(line 258)
#define DEVICE_AUXSETCLOCK_CFG (SYSCTL_AUXPLL_OSCSRC_XTAL | SYSCTL_AUXPLL_IMULT(40) | \
SYSCTL_REFDIV(2U) | SYSCTL_ODIV(4U) | \
SYSCTL_AUXPLL_DIV_1 | SYSCTL_AUXPLL_ENABLE | \
SYSCTL_DCC_BASE_0)
was changed to use OSC2, like this (note the change to IMULT to maintain 125MHZ AUXCLK freq)
#define DEVICE_AUXSETCLOCK_CFG (SYSCTL_AUXPLL_OSCSRC_OSC2 | SYSCTL_AUXPLL_IMULT(100) | \
SYSCTL_REFDIV(2U) | SYSCTL_ODIV(4U) | \
SYSCTL_AUXPLL_DIV_1 | SYSCTL_AUXPLL_ENABLE | \
SYSCTL_DCC_BASE_0)
I then changed the next #define, for symbol DEVICE_AUXCLK_FREQ, to match the change to SYSCTL_AUXPLL_IMULT
above in order to maintain 125MHZ:
(line 267)
#define DEVICE_AUXCLK_FREQ ((DEVICE_OSCSRC_FREQ * 40) / (2 * 4 * 1))
was changed to this:
#define DEVICE_AUXCLK_FREQ ((DEVICE_OSCSRC_FREQ * 100) / (2 * 4 * 1))
After making these clock related changes, I rebuilt the example and loaded both programs again and ran them.
I ran the CPU1 program, then the ARM program. This time, the CPU1 software ran to completion (as it had on
the TI board), but pings from Windows failed every time (Request timed out).
When I paused the C28x program, I saw it is in abort() at exit.c:95, called by exit() at exit.c:80.
This is expected, because the program reached its exit brace in main() as it should have done.
When I paused the CM program, I saw it is in Ethernet_resetModule() at ethernet.c:3113
(called by Ethernet_initInterface at ethernet.c:733, called by Ethernet_init at enet_lwip_udp.c:595,
called by main().
After some investigation, I found the example is using an "MII" approach to ethernet on the TI board, but
that our board uses an RMII architecture. I did some reading about the differences between the two. I saw
that I would need to change additional code in the example. So next, I attempted to make those needed changes...
Attempt to reconfigure the code for RMII (instead of default MII) ethernet:
1. Project "enet_lwip_udp", Source file "enet_lwip_udp.c"
Here I changed Ethernet_init():566 to use
ETHERNET_SS_PHY_INTF_SEL_RMII instead of ETHERNET_SS_PHY_INTF_SEL_MII when assigning phyMode, like this:
initInterfaceConfig.phyMode = ETHERNET_SS_PHY_INTF_SEL_RMII; // jct rmii
I also added this line immediately after it:
initInterfaceConfig.clockSel = ETHERNET_SS_CLK_SRC_EXTERNAL; //jct rmii
2. Project "ethernet_c28x_config", Source file "cm_common_config_c28x.c":
My board designer provided me the pins our board uses for ethernet with RMII:
ETHERNET
MDC GPIO42
MDIO GPIO43
RX_ER GPIO76
TX0 GPIO75
TX1 GPIO74
REF_CLK GPIO73
RX1 GPIO72
RX0 GPIO71
CRS_DV GPIO70
TX_EN GPIO69
RMII_INRPT GPIO68
PHY_RESET GPIO67
The main() function uses GPIO_setPinConfig() to assign specific pins for MII
ethernet and those pins are different from what my board designer provided (for RMII) on our board).
So between source lines 95 and 129 (in main()), I changed the GPIO_setPinConfig() calls to use the
pin numbers provided by my board design engineer for our board's RMII ethernet.
On lines 131-136 is a series of statements to "bring the external PHY out of Power down" and
on lines 138-144 is a series of statements to "bring the external PHY out of Reset".
My board designer has a line from GPIO 68 connecting to the PHY's PWRDN/INT pin, so I changed the pin
number from GPIO 108 to GPIO 68 in lines 131-136. The comment here in the example states this is to
drive this pin high to bring the external PHY out of Power down.
My board designer shows a PHY_RESET for Ethernet as GPIO67 (not GPIO 119 as used in the example) so
I changed the pin from GPIO 119 to 67 in lines 138-144. The comment here in the example states this is to
drive this pin high to bring the external PHY out of Reset
After making the above changes, I still cannot ping our board when the software is running. The main
loop of the example executes, but never enters its if-block because the board is not reachable via ethernet
(a client cannot connect to it over UDP). Are additional (or different) changes required to the example?
If not, then perhaps our board has a design flaw, or the PHY is not sending us a clock. I believe the PHY
is the same part number used on the TI development board we are using (the unmodified/MII example works on
that board). If this code looks correct, what avenues should I explore next?