Configure the lwip module in rt-thread

Configure the lwip module in rt-thread


This article blog link:http://blog.csdn.net/jdh99 , author: jdh, reprint please specify.

 

surroundings:

Development environment: MDK5.23

rt-thread version: 2.1.0

lwip version: 1.4.1

Single chip microcomputer model: stm32f407

phy chip model: dp83848


Configuration steps:
The PHY clock is 50M, and there are two ways to generate this clock:
  • Use 50M active crystal for PHY
  • The single-chip microcomputer generates 50M signals to the PHY
This article uses a single-chip microcomputer to generate a 50M signal to the PHY, and the pin used is the single-chip PA8.

Step 1: Configure the main frequency of the single-chip microcomputer as 100M

Step 2: Modify the rtconfig.h file and start lwip
/* SECTION: lwip, a lighwight TCP/IP protocol stack */
#define RT_USING_LWIP
#define RT_USING_LWIP141
Step 3: Modify the stm32f4xx_eth.h file and open the related macro definition of dp83848
/**
  * @}
  */

/** @defgroup PHY_status_register
  * @{
  */
/* The PHY status register value change from a PHY to another so the user have
   to update this value depending on the used external PHY */
/**
  * @brief  For LAN8700
  */
/*#define PHY_SR                           31 */        /*!< Tranceiver Status Register */

/**
  * @brief  For DP83848
  */
#define PHY_SR                           16     /*!< Tranceiver Status Register */

/* The Speed and Duplex mask values change from a PHY to another so the user have to update
   this value depending on the used external PHY */
/**
  * @brief  For LAN8700
  */
/*#define PHY_Speed_Status            ((uint16_t)0x0004)*/      /*!< Configured information of Speed: 10Mbps */
/*#define PHY_Duplex_Status           ((uint16_t)0x0010)*/      /*!< Configured information of Duplex: Full-duplex */

/**
  * @brief  For DP83848
  */
#define PHY_Speed_Status            ((uint16_t)0x0002)    /*!< Configured information of Speed: 10Mbps */
#define PHY_Duplex_Status           ((uint16_t)0x0004)    /*!< Configured information of Duplex: Full-duplex */
#define IS_ETH_PHY_ADDRESS(ADDRESS) ((ADDRESS) <= 0x20)
#define IS_ETH_PHY_REG(REG) ((REG) <= 0x1F)
Step 4: Modify the stm32f4xx_eth.c file and set it to RMII mode
/* STM32F ETH dirver options */
#define RMII_MODE                       /* MII_MODE or RMII_MODE */
#define RMII_TX_GPIO_GROUP        1     /* 1:GPIOB or 2:GPIOG */
Step 5: Modify the GPIO_Configuration() function in the stm32f4xx_eth.c file, and use PA8 to output 50M clock
/*
 * GPIO Configuration for ETH
 */
static void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* Enable SYSCFG clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    /* config MDIO and MDC. */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH); /* config ETH_MDIO */
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH); /* config ETH_MDC */
    /* config PA2: MDIO */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /* config PC1: MDC */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* Ethernet pins configuration ************************************************/
#if defined(MII_MODE)
/*
    ETH_MDIO ------------> PA2
    ETH_MDC -------------> PC1

    ETH_MII_CRS ---------> PA0
    ETH_MII_COL ---------> PA3

    ETH_MII_RX_CLK ------> PA1
    ETH_MII_RX_ER -------> PB10
    ETH_MII_RX_ER -------> PI10
    ETH_MII_RX_DV -------> PA7
    ETH_MII_RXD0 --------> PC4
    ETH_MII_RXD1 --------> PC5
    ETH_MII_RXD2 --------> PB0
    ETH_MII_RXD3 --------> PB1

    ETH_MII_TX_EN -------> PB11
    ETH_MII_TX_EN -------> PG11
    ETH_MII_TX_CLK ------> PC3
    ETH_MII_TXD0 --------> PB12
    ETH_MII_TXD0 --------> PG13
    ETH_MII_TXD1 --------> PB13
    ETH_MII_TXD1 --------> PG14
    ETH_MII_TXD2 --------> PC2
    ETH_MII_TXD3 --------> PB8
    ETH_MII_TXD3  -------> PE2
*/

#error insert MII GPIO initial.
#elif defined(RMII_MODE)
/*
    ETH_MDIO ------------> PA2
    ETH_MDC -------------> PC1

    ETH_RMII_REF_CLK ----> PA1

    ETH_RMII_CRS_DV -----> PA7
    ETH_RMII_RXD0 -------> PC4
    ETH_RMII_RXD1 -------> PC5

    ETH_RMII_TX_EN ------> PG11
    ETH_RMII_TXD0 -------> PG13
    ETH_RMII_TXD1 -------> PG14

    ETH_RMII_TX_EN ------> PB11
    ETH_RMII_TXD0 -------> PB12
    ETH_RMII_TXD1 -------> PB13
    
    PA8输出MCO1 50M
*/
    // PA8输出时钟 start
    /* Configure MCO (PA8) */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* Output PLL clock divided by 2 (50MHz) on MCO pin (PA8) to clock the PHY */
    RCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_2);

    SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
    
    // end

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH); /* RMII_REF_CLK */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH); /* RMII_CRS_DV */

    /* configure PA1:RMII_REF_CLK, PA7:RMII_CRS_DV. */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_7;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH); /* RMII_RXD0 */
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH); /* RMII_RXD1 */

    /* configure PC4:RMII_RXD0, PC5:RMII_RXD1. */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

#   if RMII_TX_GPIO_GROUP == 1
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_ETH); /* RMII_TX_EN */
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_ETH); /* RMII_TXD0 */
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_ETH); /* RMII_TXD1 */

    /* configure PB11:RMII_TX_EN, PB12:RMII_TXD0, PB13:RMII_TXD1 */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
#   elif RMII_TX_GPIO_GROUP == 2
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);

    GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH); /* RMII_TX_EN */
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH); /* RMII_TXD0 */
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH); /* RMII_TXD1 */

    /* configure PG11:RMII_TX_EN, PG13:RMII_TXD0, PG14:RMII_TXD1 */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14;
    GPIO_Init(GPIOG, &GPIO_InitStructure);
#   else
#   error RMII_TX_GPIO_GROUP setting error!
#   endif /*RMII_TX_GPIO_GROUP */
#endif /* RMII_MODE */
}
Step 6: Modify the phy_monitor_thread_entry() function in the stm32f4xx_eth.c file.
There is a bug in this function, and the LAN8700 register should be used instead of the DP83848 register.
static void phy_monitor_thread_entry(void *parameter)
{
    uint8_t phy_addr = 0xFF;
    uint8_t phy_speed_new = 0;

    /* phy search */
    {
        rt_uint32_t i;
        rt_uint16_t temp;

        for(i=0; i<=0x1F; i++)
        {
            temp = ETH_ReadPHYRegister(i, 0x02);

            if( temp != 0xFFFF )
            {
                phy_addr = i;
                break;
            }
        }
    } /* phy search */

    if(phy_addr == 0xFF)
    {
        STM32_ETH_PRINTF("phy not probe!\r\n");
        return;
    }
    else
    {
        STM32_ETH_PRINTF("found a phy, address:0x%02X\r\n", phy_addr);
    }

    /* RESET PHY */
    STM32_ETH_PRINTF("RESET PHY!\r\n");
    ETH_WritePHYRegister(phy_addr, PHY_BCR, PHY_Reset);
    rt_thread_delay(RT_TICK_PER_SECOND * 2);
    ETH_WritePHYRegister(phy_addr, PHY_BCR, PHY_AutoNegotiation);

    while(1)
    {
        uint16_t status  = ETH_ReadPHYRegister(phy_addr, PHY_BSR);
        STM32_ETH_PRINTF("LAN8720 status:0x%04X\r\n", status);

        phy_speed_new = 0;

        if(status & (PHY_AutoNego_Complete | PHY_Linked_Status))
        {
            uint16_t SR;

//            SR = ETH_ReadPHYRegister(phy_addr, 31);
			SR = ETH_ReadPHYRegister(phy_addr, 16);
            STM32_ETH_PRINTF("DP83848 REG 16:0x%04X\r\n", SR);

            SR = (SR >> 2) & 0x07; /* LAN8720, REG31[4:2], Speed Indication. */
            phy_speed_new = PHY_LINK_MASK;

//            if((SR & 0x03) == 2)
			if((SR & 0x02) == 0)
            {
                phy_speed_new |= PHY_100M_MASK;
            }

            if(SR & 0x04)
            {
                phy_speed_new |= PHY_DUPLEX_MASK;
            }
        }

        /* linkchange */
        if(phy_speed_new != phy_speed)
        {
            if(phy_speed_new & PHY_LINK_MASK)
            {
                STM32_ETH_PRINTF("link up ");

                if(phy_speed_new & PHY_100M_MASK)
                {
                    STM32_ETH_PRINTF("100Mbps");
                    stm32_eth_device.ETH_Speed = ETH_Speed_100M;
                }
                else
                {
                    stm32_eth_device.ETH_Speed = ETH_Speed_10M;
                    STM32_ETH_PRINTF("10Mbps");
                }

                if(phy_speed_new & PHY_DUPLEX_MASK)
                {
                    STM32_ETH_PRINTF(" full-duplex\r\n");
                    stm32_eth_device.ETH_Mode = ETH_Mode_FullDuplex;
                }
                else
                {
                    STM32_ETH_PRINTF(" half-duplex\r\n");
                    stm32_eth_device.ETH_Mode = ETH_Mode_HalfDuplex;
                }
                rt_stm32_eth_init((rt_device_t)&stm32_eth_device);

                /* send link up. */
                eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
            } /* link up. */
            else
            {
                STM32_ETH_PRINTF("link down\r\n");
                /* send link down. */
                eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
            } /* link down. */

            phy_speed = phy_speed_new;
        } /* linkchange */

        rt_thread_delay(RT_TICK_PER_SECOND);
    } /* while(1) */
}
Modification:
//            SR = ETH_ReadPHYRegister(phy_addr, 31);
			SR = ETH_ReadPHYRegister(phy_addr, 16);
            STM32_ETH_PRINTF("DP83848 REG 16:0x%04X\r\n", SR);

            SR = (SR >> 2) & 0x07; /* LAN8720, REG31[4:2], Speed Indication. */
            phy_speed_new = PHY_LINK_MASK;

//            if((SR & 0x03) == 2)
			if((SR & 0x02) == 0)
            {
                phy_speed_new |= PHY_100M_MASK;
            }
Configuration is complete after should be able to ping.

Guess you like

Origin blog.csdn.net/jdh99/article/details/79193060