cancel
Showing results for 
Search instead for 
Did you mean: 

No activity on STM32F407 PHY SMI interface.

Mark Greally
Associate II
Posted on October 12, 2017 at 12:21

Hi

I am trying to probe data going between the STM32F407 MAC and LAN8720A. I have a 50MHz clock from MCO1 to the PHY and seems to be working as the LED's are recognizing the network. I believe the clock signal is idle until there is data transfer between them but when I do a write (or read) I do not see and signal on the MDIO or MDC lines. As I am only interestes in the SMI at the moment I have configured the alternate function (ETH) 0b1011 for PA2 and PC1 as follows:

GPIOA->MODER |= (1 << 5); // Set PA2 as alternate function - MDIO

GPIOC->MODER |= (1 << 3); // Set PC1 as alternate function - MDC

GPIOA->AFR[0] |= (0xB << 8); // AF11 - 0b1011 = 0xB

GPIOC->AFR[0] |= (0xB << 4);

The write is as follows:

uint32_t ETH_WritePHYRegister(uint16_t PHYAddress, uint16_t PHYReg, uint16_t PHYValue)

{

volatile uint32_t tmpreg = 0;

uint32_t tmpDataReg = 0;

__IO uint32_t timeout = 0;

tmpreg = ETH_MACMIIAR; // keeps previous clock setting

/* Keep only the CSR Clock Range CR[2:4] bits value */

tmpreg &= 0b00000000000000000000000000011100; 

/* Prepare the MII register address value */

tmpreg |=(((uint32_t)PHYAddress<<11) & ETH_MACMIIAR_PA); /* Set the PHY device address */ // ETH_MACMIIAR_PA = 0x0000F800

tmpreg |=(((uint32_t)PHYReg<<6) & ETH_MACMIIAR_MR); /* Set the PHY register address */ 

tmpreg |= ETH_MACMIIAR_MW; /* Set the write mode */ // ETH_MACMIIAR_MW = 0x2

tmpreg |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ // ETH_MACMIIAR_MB = 0x1

/* Give the value to the MII data register */

ETH_MACMIIDR = PHYValue;

/* Write the result value into the MII Address register */

ETH_MACMIIAR = tmpreg;

/* Check for the Busy flag */

do

{

timeout++;

tmpreg = ETH_MACMIIAR;

} while (timeout < 5);

//} while ((tmpreg = 0b10011) && (timeout < (uint32_t)PHY_WRITE_TO));

/* Return ERROR in case of timeout */

if(timeout == PHY_WRITE_TO) // PHY_WRITE_TO = 0x0000FFFFU

{

return ETH_ERROR; // 1

}

/* Return SUCCESS */

return ETH_SUCCESS; // 0

}

I expect when I get to '

ETH_MACMIIAR = tmpreg;' that I would see some activity on the MDC and MDIO lines but there is nothing happening. Is there something additional required to initiate a write??

Thanks.

7 REPLIES 7
Posted on October 12, 2017 at 13:15

You need to have clock present on the MAC clock input, enabled in RCC (all 3 bits), and the RMII mode set in SYSCFG.

JW

Mark Greally
Associate II
Posted on October 12, 2017 at 14:49

I have added the following MAC clock enable:

RCC->AHB1ENR |= (1 << 25); // Ethernet MAC clock enable

RCC->AHB1ENR |= (1 << 26); // Ethernet Transmission clock enable

RCC->AHB1ENR |= (1 << 27); // Ethernet Reception clock enable

As I am using a MII, SYSCFG_PMC defaults to zero so I have not set it. Still nothing appearing. Do certain registers perhaps need to be reset after?

Mark Greally
Associate II
Posted on October 12, 2017 at 16:30

Its a SMSC LAN8720A.

I just checked the connections and the clock is not present on PC1 so this is RMII. The data sheet states: This configuration must be done while the MAC is under reset and before enabling the MAC clocks. So I run the config function first which includes setting this bit. When this is done I then enable the clocks. Still no joy.

void main (void) { 

SMI_Init();

clockEnable();

MCO1Enable();

}

void SMI_Init(void)

{

SYSCFG_PMC |= (1 << 23); // RMII interface is selected

GPIOA->MODER |= (1 << 3); // Set PA1 as alternate function

GPIOA->MODER |= (1 << 5); // Set PA2 as alternate function

GPIOA->MODER |= (1 << 15); // Set PA7 as alternate function

GPIOC->MODER |= (1 << 7); // Set PC3 as alternate function

GPIOC->MODER |= (1 << 9); // Set PC4 as alternate function

GPIOC->MODER |= (1 << 11); // Set PC5 as alternate function

GPIOA->AFR[0] |= (0xB << 4); // AF11 on PA1

GPIOA->AFR[0] |= (0xB << 8); // AF11 on PA2

GPIOA->AFR[0] |= (0xB << 28); // AF11 on PA7

GPIOC->AFR[0] |= (0xB << 12); // AF11 on PC3

GPIOC->AFR[0] |= (0xB << 16); // AF11 on PC4

GPIOC->AFR[0] |= (0xB << 20); // AF11 on PC5

}

void clockEnable(void)

{

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // enable the clock to GPIOA

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // enable the clock to GPIOC

RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // enable the clock to GPIOD

RCC->APB2ENR |= (1 << 14); // Enable clock for SYSCFG

RCC->AHB1ENR |= (1 << 25); // Ethernet MAC clock enable

RCC->AHB1ENR |= (1 << 26); // Ethernet Transmission clock enable

RCC->AHB1ENR |= (1 << 27); // Ethernet Reception clock enable

}

void MCO1Enable(void)

{

// Enable MCO1 clock on PA8

GPIOA->MODER |= (1 << 17); // same as *GPIOAMODER = (1 << 17);

GPIOA->OSPEEDR = 0x30000; // very high speed. OSPEEDR8

GPIOA->PUPDR = 0x0; // No pull-up, pull-down

GPIOA->AFR[0] = 0x0; // AF0

GPIOA->AFR[1] = 0x0; // AF0

RCC->CFGR = 0b11111101011000001001010000001010;

}
Posted on October 12, 2017 at 15:04

50MHz sounded like RMII. I don't know the PHY you are using.

Do you have the input clock present on the TX_CLK and RX_CLK pins (PA1/PC3), and those pins configured as AF/ETH?

JW

Mark Greally
Associate II
Posted on October 12, 2017 at 18:06

That was jest a redefined but works the same. So I changed enabled the 

APB2ENR register before SYSCFG is enabled like the following.

RCC->APB2ENR |= (1 << 14);

SYSCFG->PMC |= (1 << 23);0690X00000603xfQAA.jpg

The settings seem to be ok but still not working.

Posted on October 12, 2017 at 17:29

Verify in debugger if all those registers are set as you want them.

(I am aiming at whether all modules' clock are enabled in RCC, namely SYSCFG)

JW

PS.

SYSCFG_PMC

Why not SYSCFG->PMC?

Mark Greally
Associate II
Posted on October 17, 2017 at 15:15

It turns out that some settings were getting reset further on in the code. The resets were removed and everything is working as it should now.