LWIP 无操作系统的移植

导读:
本文移植是以STM32F4开发板为例,PHY物理层采用的LAN8720。除了少数代码需要更改之外,对于其他的开发板是通用的步骤。
详细内容可以参考 STM32F4 LWIP开发手册
第一部分:移植前准备
第二部分:移植过程

移植前准备

1.准备好基础工程

我选择具有内存管理功能的模板。在ST以太网驱动库中 DMA缓存区 采用数组实现,数组实现存放与RAM中太浪费内存,而我采用了内存管理使用外部SRAM来分配空间。
如下:(stm324x7_eth.c)中就是数组,可以注释掉。
ETH_DMADESCTypeDef  DMARxDscrTab[ETH_RXBUFNB] __attribute__ ((aligned (4))); /* Ethernet Rx DMA Descriptor */
ETH_DMADESCTypeDef  DMATxDscrTab[ETH_TXBUFNB] __attribute__ ((aligned (4))); /* Ethernet Tx DMA Descriptor */
uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __attribute__ ((aligned (4))); /* Ethernet Receive Buffer */
uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __attribute__ ((aligned (4))); /* Ethernet Transmit Buffer */

2.下载ST以太网驱动库

STM32F4x7_ETH_LwIP_v1.1.0中的STM32F4x7_ETH_Driver里面一共三个文件:
    1.stm32f4x7_eth.h 头文件
    2.stm32f4x7_eth.c 驱动
    3.stm32f4x7_eth_conf.h 以太网配置文件(需要重命名,原名:stm32f4x7_eth_conf_template.h)

3.下载LWIP文件

lwip-1.4.1.zip 是LWIP源码
contrib-1.4.1.zip 含官方例程和一些头文件

移植

1.st以太网驱动库的移植

  1. 将以太网库的3个文件包含进工程。
  2. 遇到找不到main.h直接注释掉
  3. 因为我们采用默认的软件延时函数,所以直接注释掉USE_Delay//#define USE_DELAY
  4. 将官方对于DP83848 PHY改为LAN8720(用户使用的PHY)

下面将讲解一下需要的配置conf.h

//前部分和原来的内容一致,最下面PHY方面是关于LAN8720的,ST驱动库需要读取外部PHY来读取速度和双工状态
#ifndef __STM32F4x7_ETH_CONF_H
#define __STM32F4x7_ETH_CONF_H
#include "stm32f4xx.h"

#define USE_ENHANCED_DMA_DESCRIPTORS

//如果使用自己定义的延时函数的话就注销掉下面一行代码,否则使用
//默认的低精度延时函数

//#define USE_Delay     //使用默认延时函数,因此注销掉
#ifdef USE_Delay
    #include "main.h"               
    #define _eth_delay_    Delay     //Delay为用户自己提供的高精度延时函数

#else
    #define _eth_delay_    ETH_Delay //默认的_eth_delay功能函数延时精度差
#endif

#ifdef  CUSTOM_DRIVER_BUFFERS_CONFIG
    //重新定义以太网接收和发送缓冲区的大小和数量
    #define ETH_RX_BUF_SIZE    ETH_MAX_PACKET_SIZE //接收缓冲区的大小
    #define ETH_TX_BUF_SIZE    ETH_MAX_PACKET_SIZE //发送缓冲区的大小
    #define ETH_RXBUFNB        20                  //接收缓冲区数量
    #define ETH_TXBUFNB        5                   //发送缓冲区数量
#endif

//*******************PHY配置块*******************
#ifdef USE_Delay
    #define PHY_RESET_DELAY    ((uint32_t)0x000000FF)   //PHY复位延时
    #define PHY_CONFIG_DELAY   ((uint32_t)0x00000FFF)   //PHY配置延时
    #define ETH_REG_WRITE_DELAY ((uint32_t)0x00000001)  //向以太网寄存器写数据时的延时
#else
    #define PHY_RESET_DELAY    ((uint32_t)0x000FFFFF)   //PHY复位延时
    #define PHY_CONFIG_DELAY   ((uint32_t)0x00FFFFFF)   //PHY配置延时
    #define ETH_REG_WRITE_DELAY ((uint32_t)0x0000FFFF)  //向以太网寄存器写数据时的延时
#endif

//LAN8720 PHY芯片的状态寄存器
#define PHY_SR              ((uint16_t)31)      //LAN8720的PHY状态寄存器地址
#define PHY_SPEED_STATUS    ((uint16_t)0x0004)  //LAN8720 PHY速度值掩码
#define PHY_DUPLEX_STATUS   ((uint16_t)0x00010) //LAN8720 PHY连接状态值掩码  
#endif 

修改eth.c

注释掉四个数组,采用内存分配使用外部SRAM

2.添加LAN8720和MAC/DMA驱动


  1. LAN8720.c复制到工程中

出现错误:..\OBJ\MALLOC.axf: Error: L6218E: Undefined symbol lwip_pkt_handle (referred from lan8720.o).
这个函数在后面添加的文件中,暂时提示没有定义,不要心急!

3.添加LWIP源文件

  1. 工程中创建LWIP文件夹,复制lwip-1.4.1文件夹来
  2. 工程中增加文件分组 LWIP-API,LWIP-NETIF,LWIP-CORE
  3. 添加源文件和头路径

4.添加中间文件(起桥梁作用)

以上几个步骤仅仅是添加了LWIP源文件和st以太网驱动。将以太网驱动和st驱动连接起来需要一种中间文件。
1. 添加arch,添加5个文件。其中cc.h根据组件定义了一些变量 u8_t。LWIP内部也采用printf来调试信息。cpu.h 定义大小端模式,stm32为小端。 perf.h。sys_arch.c .h全局变量获取当前系统时间。
2. 添加LWIP通用文件-ALLETEK编写的。
3. 添加ethernetif.h文件(LWIP源码是没有的ALIENTEK提供)

5.修改LWIP源码

中间文件连接底层驱动和LWIP,需要进行一些修改。

1.修改LWIP文件名

core中的sys.c和sys.h与原来的文件重名,这里修改为lwip_sys。注意修改.c中#include “lwip_sys.h”

修改完毕后报错:..\LWIP\arch\sys_arch.c(37): error: #5: cannot open source input file “timer.h”: No such file or directory

  • lwip需要提供一种系统时钟,有一些周期性事务来处理。因为现在没有操作系统,则需要自己实现定时器,并且添加到HARDWARE中。 所以这里我们使用定时器3,并且设置周期为10ms。添加“timer.c”文件到工程中,内容为定时器3。中断服务函数中,进行lwip_loacltime+=10;//10ms中断,所以+10。具体代码看DEMO

添加timer后报错:..\OBJ\MALLOC.axf: Error: L6407E: Sections of aggregate size 0x3524 bytes could not fit into .ANY selector(s).

  • 这里提示空间不足,解决办法在malloc.h中,修改可以管理的内部Ram的大小
#define MEM1_MAX_SIZE           60*1024  //从100k修改为60k,这里是malloc可以管理的大小,不宜过大。
  • 之后会报错一些函数没有定义,暂时不去管它。

2.修改ethernetif.c

暂时不讲解源代码,所以直接用例程的替代。

3.修改mem.c memp.c

在LWIP内部采用动态内存管理技术,LWIP内存堆ram_heap和内存池memp_memory。我们用MALLOC进行动态内存分配(也可以使用attribute),注释掉数组。
* mem.c 注释181,182行。定义一个指针

/** the heap. we need one struct mem at the end and some room for alignment */
u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
u8_t * ram_heap; //定义指针
  • memp.c中是169~173
  • memp_get_memorysize()用于获取memp_memory数组的大小。memp_memory会在lwip_comm.c中使用动态内存管理来分配内存

4.修改icmp.c, ping使用的icmp协议

  • st有一个默认硬件帧校验
    LWIP 无操作系统的移植_第1张图片

6.LWIP的裁剪与配置

  • LWIP中opt.h是可以裁剪和配置LWIP的。但是不建议opt.h中修改,其中的配置都是条件编译。那么在其他地方定义就行了。
  • 在lwip_common下的lwipopts.h进行了配置。
  • 开发板连接路由器是会DHCP自动分配地址的。如果DHCP设置为0,是使用静态IP地址的。

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