配置rt-thread中的lwip模块

配置rt-thread中的lwip模块


本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

 

环境:

开发环境:MDK5.23

rt-thread版本:2.1.0

lwip版本:1.4.1

单片机型号:stm32f407

phy芯片型号:dp83848


配置步骤:
PHY的时钟是50M,产生这个时钟有两个方法:
  • 用50M有源晶振给PHY
  • 单片机产生50M信号给PHY
本文用单片机产生50M信号给PHY,使用的引脚是单片机的PA8。

步骤1: 配置单片机主频为100M

步骤2:修改rtconfig.h文件,启动lwip
/* SECTION: lwip, a lighwight TCP/IP protocol stack */
#define RT_USING_LWIP
#define RT_USING_LWIP141
步骤3:修改stm32f4xx_eth.h文件,打开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)
步骤4:修改stm32f4xx_eth.c文件,设置为RMII模式
/* STM32F ETH dirver options */
#define RMII_MODE                       /* MII_MODE or RMII_MODE */
#define RMII_TX_GPIO_GROUP        1     /* 1:GPIOB or 2:GPIOG */
步骤5:修改stm32f4xx_eth.c文件中的GPIO_Configuration()函数,使用PA8输出50M时钟
/*
 * 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 */
}
步骤6:修改stm32f4xx_eth.c文件中的phy_monitor_thread_entry()函数。
本函数存在bug,还是使用LAN8700寄存器,应该使用DP83848的寄存器。
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) */
}
修改处:
//            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;
            }
配置完成 后应该可以ping通。

你可能感兴趣的:(rtos,STM32)