LWIP的移植

最近在项目的开发中用到了LWIP协议,于是要将LWIP协议移植到STM32上,当然STM32的官方例程有相关的例程,我也正式在这个例程的基础上进行的移植,现在将在移植过程中遇到的一些总结如下,对自己是个记录,也希望对后面要用到的朋友有所帮助。

使用平台:STM32F207的平台,8M的外部晶振, 配合LAN8720A的PHY芯片。

软件平台: 使用的是STM32F207的HAl库。我自己要使用的是tcp client的功能

移植过程:

1.参照STM32F207的tcp client例程,将与LWIP相关的库文件都添加到自己的工程中,如下图所示,但是下图中显示的并不是库的全部,准确的可参照官方例程。

2.系统时钟的修改: 对于系统时钟的配置一定要注意,例程使用的是25M的外部晶振为基础,还是8M的外部晶振为基础,我这里使用的是8M的外部晶振,所以将系统时钟配置成8M

/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 120000000
* HCLK(Hz) = 120000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 8000000
* PLL_M = 8
* PLL_N = 240
* PLL_P = 2
* PLL_Q = 5
* VDD(V) = 3.3
* Flash Latency(WS) = 3
* @param None
* @retval None
*/
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 240;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 5;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
}

3.对于Main函数的修改,main函数需要保留这样几个函数; 这就是最基本的配置了

void main(void)

{

     /* STM32F207xx HAL library initialization */
     HAL_Init();

    /* Configure the System clock to have a frequency of 120 MHz */
    SystemClock_Config();   

    /* Initialize the LwIP stack */
   lwip_init();

   /* Configure the Network interface */
   Netif_Config();

  while(1)

 {

     ethernetif_input(&gnetif);

}

}

4.上面描述了main函数的配合,下面对于具体的每个函数加以说明

      lwip_init(); 这个函数对于里面的内容不用做任何的修改,照搬过来就好了

      Netif_Config();  这个函数就是配置的关键了,这个函数中有几个重要的函数,如下

 

  netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input); 这个函数会将之前设置的ip,子网掩码,网关初始化到netif结构体的相关成员变量上

ethernetif_init函数会对硬件底层进行初始化,包括对PHY的初始化,具体的初始化,在这个函数里面的low_level_init函数,如下

static void low_level_init(struct netif *netif)
{
uint32_t regvalue = 0;
uint8_t macaddress[6]= { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 };


EthHandle.Instance = ETH;
EthHandle.Init.MACAddr = macaddress;                                                 //对MAC地址的设置
EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
EthHandle.Init.Speed = ETH_SPEED_100M;
EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;       //在这里区分是RMII接口,还是MII的接口
EthHandle.Init.RxMode = ETH_RXPOLLING_MODE;
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
EthHandle.Init.PhyAddress = 0x00;                                                       //这里是设置PHY的,因为这里用的LAN8720A,所以这里需要设置成0x00,如果是DP83848,则需要设置成0x01

/* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
if (HAL_ETH_Init(&EthHandle) == HAL_OK)
{
/* Set netif link flag */
netif->flags |= NETIF_FLAG_LINK_UP;
}

/* Initialize Tx Descriptors list: Chain Mode */
HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);

/* Initialize Rx Descriptors list: Chain Mode */
HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);

/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;

/* set MAC hardware address */
netif->hwaddr[0] = MAC_ADDR0;
netif->hwaddr[1] = MAC_ADDR1;
netif->hwaddr[2] = MAC_ADDR2;
netif->hwaddr[3] = MAC_ADDR3;
netif->hwaddr[4] = MAC_ADDR4;
netif->hwaddr[5] = MAC_ADDR5;

/* maximum transfer unit */
netif->mtu = 1500;

/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;

/* Enable MAC and DMA transmission and reception */
HAL_ETH_Start(&EthHandle);

/**** Configure PHY to generate an interrupt when Eth Link state changes ****/
/* Read Register Configuration */
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MICR, &regvalue);

regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);

/* Enable Interrupts */
HAL_ETH_WritePHYRegister(&EthHandle, PHY_MICR, regvalue );

/* Read Register Configuration */
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MISR, &regvalue);

regvalue |= PHY_MISR_LINK_INT_EN;

/* Enable Interrupt on change of link status */
HAL_ETH_WritePHYRegister(&EthHandle, PHY_MISR, regvalue);

HAL_ETH_WritePHYRegister(&EthHandle, 0x19, regvalue );                     //其中使用LAN8720A的时候,还需要将这里设置一下,添加后面的三句
regvalue |= 0x01 << 5;
HAL_ETH_WritePHYRegister(&EthHandle, 0x19, regvalue );
}

 

其中对于管脚的设置在HAL_ETH_Init函数中的HAL_ETH_MspInit函数,具体如下

void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
{
uint32_t timeOver =0;
GPIO_InitTypeDef GPIO_InitStructure;

/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();

/* Ethernet pins configuration ************************************************/
/**ETH GPIO Configuration
PC1 ------> ETH_MDC
PA1 ------> ETH_REF_CLK
PA2 ------> ETH_MDIO
PA7 ------> ETH_CRS_DV
PC4 ------> ETH_RXD0
PC5 ------> ETH_RXD1
PB11 ------> ETH_TX_EN
PB12 ------> ETH_TXD0
PB13 ------> ETH_TXD1
PE0 ETH_RST
*/


GPIO_InitStructure.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

/* Configure PA1, PA2 , PA7 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.Pin = GPIO_PIN_0;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);

HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_RESET);
timeOver = 0xFF;
while (timeOver--);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_SET);

/* Enable ETHERNET clock */
__HAL_RCC_ETH_CLK_ENABLE();

}

 

另外最后需要注意的地方就是在stm32f2xx_hal_conf.h文件中将相关的宏定义打开,这样移植工作就完成了。

posted @ 2018-04-24 16:44  坤少>  阅读(1241)  评论(0编辑  收藏  举报