LwIP在stm32上的无操作系统移植

2023-05-16

LwIP是一个轻型IP协议,有无操作系统的支持都可以运行。这里的移植是无操作系统移植。
LwIP虽然是一个轻型的IP协议,但是TCP/IP基本功能都有。而且占用的资源不多,非常适合用于嵌入式系统。
移植的平台:STM32F103VE+MDK 4.7+ LWIP-1.4.1
下载LwIP-1.4.1源码以及contrib-1.4.1_官网地址: http://download.savannah.gnu.org/releases/lwip/
下载ST官方LWIP参考实例下载地址: http://www.st.com/web/en/catalog/tools/FM147/CL1794/SC961/SS1743/PF257862?s_searchtype=keyword
我的移植实例+LwIP-1.4.1+contrib-1.4.1_+ST官方lwIP移植实例+串口网络调试助手: http://download.csdn.net/detail/mcu_tian/9265095
1:移植工程描述
     将Lwip-1.4.1移植到野火stm32开发板上,无操作系统,轮询网络接口, 使用TCP接口对数据进行收发。将stm32与PC通过路由器连接在一个局域网内进行通信测试。
2:在进行移植之前必须知道LwIP源码的框架结构
LwIP-1.4.1包含了协议栈的核心源码。
其目录结构如下:
src 目录下的 api 文件夹保存的文件中,包含了适用于具有操作系统平台调用的应用
层接口函数。core文件夹下的文件内容为 LwIP 协议栈对于各种协议的实现。netif下的文
件则保存了与硬件底层关系比较紧密的函数。这三个文件夹下的都是c 源文件,它们的头
文件都被保存到 include 文件夹中。在实际应用中,可根据需要进行裁剪(前期移植不管了,就将这些源码全部添加到工程中)。
3:工程文件准备
A:将LwIP-1.4.1的src文件夹的所有文件和文件夹复制到自己的工程中。
B:将contrib-1.4.1_ 目录\contrib-1.4.1_\contrib\ports old\6502\include\arch的 cc.h、perf.h 和 sys_arch.h 这三个文件复制到Lwip文件夹中的自己创建的arch文件夹中。其中 cc.h 包含了 LwIP 对于基本数据类型的定义。sys_arch.h 定义了与系统
有关的信号量、邮箱及线程。
C:ST库文件。将版本3.5版本固件库复制到stmlib工程文件下。
D:串口和systicks的bsp文件复制到bsp文件夹。
E:将以太网模块驱动enc28j60文件夹复制到工程app文件夹下(这里用的是野火的模块以及程序)
F:将st工程模板中的project文件夹中src文件夹中的netconf.c和 inc文件夹的netconf.h复制到工程user文件夹中
G:将stm32f10x_conf.h,stm32f10x_it.h,stm32f10x_it.c复制到工程user文件夹下。
4:硬件链接
以太网模块enc28j60与开发板SIP2链接。
5:建立工程,设置相关头文件路径,将源文件添加进工程。在创建main.c main.h以及iptest.c iptest.h(测试功能模块)。如下图所示:
6:移植
LwIP协议栈给底层的驱动提供了接口, 如初始化网卡、发送数据包、接收数据包等最底层的操作。这些接口定义位于\lwip-
1.4.1\src\netif 目录下的 ethernetif.c 文件,该文件已经被添加进了工程中,接口的具体实现 因使用的网络接口不同而有所区别。
移植的主要工作就是将 ethernetif.c中的功能实现。在官方源码中 ethernetif.c提供了模板,我们只需要参照st实例根据我们的硬件去实现这些函数功能即可。
需要我们进行修改的函数为low_level_init,low_level_output,low_level_input这三个函数(橙色标记为修改部分),以及定义相关的数据结构和宏即可。
low_level_init主要功能是进行底层硬件的初始化,具体看注释
static void low_level_init(struct netif *netif)
{
  struct ethernetif *ethernetif = netif->state;
  /* set MAC hardware address length */
  netif->hwaddr_len = ETHARP_HWADDR_LEN;
  /* set MAC hardware address */
  netif->hwaddr[0] = MacAddr[0]; //根据硬件mac地址,初始化netif结构体的硬件地址信息。该模块mac地址可以由用户定义。
  netif->hwaddr[1] = MacAddr[1]; //本实例的mac地址定义在 全局变量数组uint8_t MacAddr[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
  netif->hwaddr[2] = MacAddr[2];
  netif->hwaddr[3] = MacAddr[3];
  netif->hwaddr[4] = MacAddr[4];
  netif->hwaddr[5] = MacAddr[5];
  /* 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 | NETIF_FLAG_LINK_UP;
  /* Do whatever else is needed to initialize interface. */ 
  //下面调用的两个函数都是根据特定硬件进行初始化的,具体根据硬件的不同而实现不同。
   enc28j60Init(MacAddr); //初始化以太网模块,并设置mac值(根据不同的芯片不同)
   enc28j60clkout(2);//设置模块时钟。注意这里必须初始化,在复位之后为0,此值禁止clk。(根据不同的芯片可能不同)
}
定义接收发送缓冲区uint8_t SendDataBuf[1500 + 20];uint8_t RecvDataBuf[1500 + 20];
缓冲区的长度为mtu(1500)+ 地址 +类型 +CRC等(小于20)
low_level_output函数的主要功能将数据包发送出去
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
  struct ethernetif *ethernetif = netif->state;
  struct pbuf *q ;
  uint32_t i = 0;
 // initiate transfer();
#if ETH_PAD_SIZE
  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
  for(q = p; q != NULL; q = q->next) {
    /* Send the data from the pbuf to the interface, one pbuf at a
       time. The size of the data in each pbuf is kept in the ->len
       variable. */
   MEMCPY((uint8_t *)&SendDataBuf[i],(uint8_t *)q->payload,q->len);//将pbuf所指向链表的数据复制到数据缓冲区中
     i = i + q->len;
 //   send data from(q->payload, q->len);
  }
  enc28j60PacketSend(i,SendDataBuf);//发送数据包
 // signal that packet should be sent();
#if ETH_PAD_SIZE
  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
  LINK_STATS_INC(link.xmit);
  return ERR_OK;
}
low_level_input该函数的主要功能是将接收到的数据并且分配到一个pbuf链表中
因为该工程是轮询的,在周期调用ethernetif_input的时候,ethernetif_input会调用该函数看是否有接收到的数据。
len = enc28j60PacketReceive(1600, RecvDataBuf); //接收到的数据大小
  if(len == 0){ //若是没有,则返回,若是非零,就执行再去
    return 0;
  }
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);//申请与接收到数据大小相匹配的数据pbuf链表
for (q = p; q != NULL; q = q->next)
        {     
             memcpy((u8_t*)q->payload, (u8_t*)&Data_Buf[i], q->len);//将接收到的数据分配到p指向的pbuf链表中
             i = i + q->len;
        }
        if( i != p->tot_len ){ return 0;}  //相等的时候,表明到了数据尾
    }
轮询和计时
在配置底层函数之后,将Lwip接口与驱动想关联之后,还没有完成,因为我们需要轮询输入函数和计时。
轮询函数将在main函数的最后while(1)循环中调用,例如本工程模板中的 LwIP_Periodic_Handle(LocalTime) (在后面再讲)
和st模板中main函数System_Periodic_Handle()。
关于计时,在工程模板中,我们使用的是stm32 systick时钟产生。
systick计时每10ms产生中断,每次中断跟新在main函数中定义的全局变量LocalTime,每次加10。
systick配置函数在BSP_SysTick.c中定义。
systick中断函数SysTick_Handler 定义在stm32f10x_it.c
void SysTick_Handler(void)
{
  Time_Update();
}
void Time_Update(void) //在netconf.c中定义
{
  LocalTime += SYSTEMTICK_PERIOD_MS;
};
在core文件夹中有opt.h文件,该文件主要用于Lwip的配置,在前期的移植,我们只需要使用默认的即可。
7:LWIP初始化函数 LwIP_Init以及轮询函数LwIP_Periodic_Handle的实现
该函数定义在netconf.c源文件中,在移植的时候将st参考实例中的文件复制过来了,做了稍微的修改。
LwIP_Init 该函数的主要功能是配置协议栈的网络接口结构体链表,内存池,pbuf结构体等。
在这里将IP地址、掩码、网关根据我们连接的路由器进行初始化。
我这里的IP地址设置为192.168.1.254
同时这里不要设置MAC地址,这个是根据st不一样的,因为我们在初始化底层的时候,就对以太网络模块进行mac地址设定。
LwIP_Periodic_Handle根据我们的计时数值LocalTime 在不同的时候执行不同的函数,
如是否有数据接收,在某些特定值时候更新TCP时钟等
8:TCP网络应用测试应用的编写
在进行上面移植操作之后,我们接下来需要验证我们的移植是否成功。
我们编写的测试应用在iptest.c中定义。主要参考的是st模板中的helloworld.c。
主要功能是建立一个TCP服务器端,客户端与服务器建立TCP连接之后,通过串口打印INTRODUCT(宏),
当服务器收到客户端的数据的时候,将接收到的信息通过串口打印出来,同时将接收的数据返回给客户端。
TcpTest_init实现TCP测试服务器整个过程更Linux的方式基本上一样,调用的函数名称都基本上相似
void TcpTest_init(void)
{
  struct tcp_pcb *pcb;
  pcb = tcp_new();      //建立通信的TCP控制块
  tcp_bind(pcb, IP_ADDR_ANY,23); //绑定端口号为23,绑定本地IP。因为只有一个网络接口,不需要指定IP地址。
  pcb = tcp_listen(pcb); //进入监听状态
  tcp_accept(pcb,TcpTest_accept); //设置有请求连接时候的回调函数,当有连接的时候,LWIP就会调用TcpTest_accept函数。
}
TcpTest_accept函数主要是回调函数
static err_t TcpTest_accept(void *arg,struct tcp_pcb *pcb,err_t err)
{
  tcp_arg(pcb,mem_calloc(sizeof(struct name),1));
  tcp_recv(pcb,TcpTest_recv); //设置接收到数据后的回调函数;在建立连接后,当接收到数据之后,就会调用TcpTest_recv函数。
  tcp_write(pcb, INTRODUCT, strlen(INTRODUCT),1); //在建立连接的时候,向客户端发送INTRDUCT(宏)的字符串
  return  ERR_OK;
};
TcpTest_recv在接收到数据之后,将所接收到的数据回写给客户端同时通过串口打印出来。
9:main函数的编写(参考st工程实例)
int main(void)
{
 /****************************************************/
    USART1_Init(); //串口初始化
  ENC_SPI_Init(); //SPI2接口初始化用于后面以太网模块的初始化
  SysTick_Init(); //系统时钟的初始化
  LwIP_Init(); //LWIP的初始化
  TcpTest_init(); //建立TCP服务器
  while(1)
  {
    LwIP_Periodic_Handle(LocalTime); //轮询
  }
}
10:实验结果如图
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LwIP在stm32上的无操作系统移植 的相关文章

  • 处理器指令周期执行时间

    我的猜测是 no operation 内在 ARM 指令应花费 1 168 MHz 来执行 前提是每个NOP在一个时钟周期内执行 我想通过文档验证这一点 有关处理器指令周期执行时间的信息是否有标准位置 我试图确定 STM32f407IGh6
  • 在没有 IDE 的情况下如何使用 CMSIS?

    我正在使用 STM32F103C8T6 并想使用 CMSIS 这本质上只是寄存器定义 没有代码 让我的生活更轻松 同时仍保持在较低水平 问题是我不知道如何安装该库以便在命令行上使用 Makefile 使用 所有文档似乎都与特定于供应商的 I
  • 如何让printf在STM32F103上工作?

    我是 STM32F103 世界的新手 我有一个STM32F103的演示代码 我正在使用arm none eabi来编译它 我尝试了在谷歌上可以找到的内容 但到目前为止没有任何效果 我已经花了三天时间来解决这个问题 任何人都可以给我一个运行良
  • STM32 F072上的软件如何跳转到bootloader(DFU模式)?

    STM32应用笔记2606对此进行了讨论 但没有简单的代码示例 该答案已使用 IAR EWARM 在 STM32F072 Nucleo 板上进行了测试 这个答案使用 STM32标准外设库 仅此而已 请注意 验证您是否成功进入引导加载程序模式
  • 139-基于stm32单片机老人居家监护报警系统Proteus仿真+源程序

    资料编号 139 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 MQ4传感器 电位器模拟 MQ2传感器 电位器模拟 蜂鸣器 电机 制作一个基于stm32单片机老人居家监护报警系统Proteus仿真 2 通过MQ2传
  • 133-基于stm32单片机停车场车位管理系统Proteus仿真+源程序

    资料编号 133 一 功能介绍 1 采用stm32单片机 4位数码管 独立按键 制作一个基于stm32单片机停车场车位管理系统Proteus仿真 2 通过按键进行模拟车辆进出 并且通过程序计算出当前的剩余车位数量 3 将剩余的车位数量显示到
  • 137-基于stm32单片机智能保温杯控制装置Proteus仿真+源程序

    资料编号 137 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DS18B20传感器 电机 制作一个基于stm32单片机智能保温杯控制装置Proteus仿真 2 通过DS18b20传感器检测当前保温杯水的温度 并且
  • STM32F103概要

    The STM32F103x4 STM32F103x6 STM32F103xC STM32F103xD and STM32F103xE are a drop in replacement for STM32F103x8 B medium d
  • SHT10温湿度传感器——STM32驱动

    实验效果 硬件外观 接线 3 3V供电 IIC通讯 代码获取 查看下方 END
  • ESP32 - 具有本机 LwIP 库的 UDP 广播器/接收器

    我正在使用 ESP32 顺便说一句 这是一个很棒的平台 构建一个分布式应用程序 所有参与者都应该以最简单的形式通过 UDP 进行通信 通过广播发送消息并监听周围所有的消息 每个参与者自行过滤相关消息 到目前为止 我有以下初始化例程 int
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • STM32 暂停调试器时冻结外设

    当到达断点或用户暂停代码执行时 调试器可以停止 Cortex 中代码的执行 但是 当皮质停止在暂停状态下执行代码时 调试器是否会冻结其他外设 例如 DMA UART 和定时器 您只能保留时间 r 取决于外围设备 我在进入主函数时调用以下代码
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • STM32 上的 ADC 单次转换

    我正在研究 STM32 F103x 上的 ADC 编程 并从最简单的情况 单次转换开始 测量内部温度传感器 连接到 ADC1 的值 并使用 USART 将其发送到 COM 端口 目标似乎很明确 但是当我尝试将源代码下载到闪存时 它不会向 C
  • NTP请求包

    我试图弄清楚我需要在 NTP 请求包中发送 客户端 什么才能从服务器检索 NTP 包 我正在 Cortex M3 Stellaris LM3S6965 上使用 LWIP 据我了解 我将收到 UDP 标头 然后收到具有不同时间戳的 NTP 协
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • 当端点和 PMA 地址均更改时,CubeMX 生成的 USB HID 设备发送错误数据

    我正在调试我正在创建的复合设备的问题 并在新生成的仅 CubeMX 代码中重新创建了该问题 以使其更容易解决 我添加了少量代码main 让我发送 USB HID 鼠标点击 并在按下蓝色按钮时使 LED 闪烁 uint8 t click re
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE

随机推荐

  • C语言程序设计——前两道题(判断有效三角形和高精度计算的加减法)

    第1题 1 原题 xff1a 假设平面上有1 N x y 个坐标点 xff0c 编程判断这N x y 个点能组成多少个有效三角形 问题分析 xff1a 本题为一道基本编程题 xff0c 要点就是判断三个点能构成三角形的条件 解决方案 xff
  • C语言程序设计之RLE压缩解压算法

    先介绍一下RLE压缩算法 xff1a 游程编码 xff08 Run Length Encoding RLE xff09 又称行程长度编码或者变动长度编码法 xff0c 在控制理论中对于二值图像而言是一种编码方法 xff0c 对连续的黑 xf
  • 浅析洛谷P4924(一道普及/提高-的题目)的解决方法

    题目描述 xff1a Scarlet最近学会了一个数组魔法 xff0c 她会在n n二维数组上将一个奇数阶方阵按照顺时针或者逆时针旋转90 首先 xff0c Scarlet会把1到n 2的正整数按照从左往右 xff0c 从上至下的顺序填入初
  • 判断图的连通性

    上机系统的判分功能目前还没开放 xff0c 所以以下所给代码仅供参考 xff0c 并不能保证完全正确 xff08 自己分别测试了强连通 xff0c 单向连通 xff0c 弱连通 xff0c 不连通的一个样例 xff0c 都过了 xff09
  • BMP格式详解

    BMP xff08 全称Bitmap xff09 是Windows操作系统中的标准图像文件格式 xff0c 可以分成两类 xff1a 设备相关位图 xff08 DDB xff09 和设备无关位图 xff08 DIB xff09 xff0c
  • 标准数独的求解

    上机题目中有一道题目的要求是通过编程实现数独的求解 xff0c 然后想起了初三去后来所在的高中面试提前录取的时候里面的压轴题便是数独 xff0c 当时做了好长时间也没搞出来 xff0c 我还记得监考老师当时和我说 xff1a 做不出来就别勉
  • 利用定义求解传递闭包的关系矩阵

    题目描述 给定有限集合上二元关系的关系矩阵 xff0c 利用传递闭包的定义式 xff08 不是warshall算法 xff09 求其传递闭包的关系矩阵 源代码 span class token macro property span cla
  • 【Android】解决Expecting member declaration

    问题截图 刚刚安装的android studio安装完成就出现异常错误 原因 新建project的时候 xff0c language项选错了 xff0c 应选java 解决错误的办法 新建一个Project的时候 xff0c Languag
  • 矩阵乘法的实现(一般形式及单个矩阵的n次幂)

    目录 一般矩阵乘法实现矩阵的n次幂的实现 一般矩阵乘法实现 题目描述1 给定m k的布尔矩阵A xff0c 和k n的布尔矩阵B xff0c 求布尔矩阵的乘积AB 源代码1 span class token macro property s
  • 根据给出的关系矩阵,判断该关系所具有的特性

    目录 自反性与反自反性的判断对称性与反对称性的判断传递性的判断 自反性与反自反性的判断 关系R是自反的 xff0c 当且仅当其关系矩阵的主对角线上元素都为1 xff1b 关系R是反自反的 xff0c 当且仅当其关系矩阵的主对角线上元素都为0
  • 输出所有满足条件的关系

    目录 for循环解决简单问题调用库函数解决全排列问题 for循环解决简单问题 题目描述 源代码 span class token macro property span class token directive keyword inclu
  • 按字典序输出给定序列

    上机题目里面有不少挨着的相似的题 xff0c 下面所给的这两道偏简单 xff0c 就介绍一下用python和c实现的代码 题目描述 python实现的代码用到了sorted函数 xff0c 该函数在python3里面有三个参数 xff0c
  • 求给定图中某两点之间某一长度的路径条数

    无向图的一道例题 输出c到d长度为以下长度的路径条数 xff1a 源代码 span class token macro property span class token directive keyword include span spa
  • 洛谷题目CF96B Lucky Numbers的分析

    题目描述 xff1a 佩佳喜欢幸运数字 每个人都知道 xff0c 如果正整数的小数表示不包含除4和7以外的数字 xff0c 那么它们是幸运的 例如 xff0c 数字47 744 xff0c 4是幸运的 xff0c 5 xff0c 17 46
  • VMware Player 虚拟机中音乐播放无声音 问题

    虚拟机中安装的Win7 xff0c 音乐播放无声音 解决办法 xff1a VMware Player 右下角 Sound Card gt connect 即可解决
  • 解决M1芯片 MAC 下 Goland(Intellij系列都适用) 无法 Debug 的问题

    解决M1芯片 MAC 下 Goland xff08 Intellij系列都适用 xff09 无法 Debug 的问题 解决M1芯片 MAC 下 Goland xff08 Intellij系列都适用 xff09 无法 Debug 的问题报错信
  • Java例15.13——使用MVC结构计算三角形面积

    MVC是一种通过模型 视图 控制器构造一个软件或组件的理想办法 在例15 13中首先编一个封装三角形的类 xff0c 然后再编写一个窗口 要求窗口使用3个文本框和1个文本区为三角形对象中的数据提供视图 xff0c 其中3个文本框用来显示和更
  • 网卡远程唤醒功能

    远程唤醒功能配置文档 功能简介 网络唤醒功能可以让用户从一个局域网或者是跨网络环境中远程管理一台或者是多台计算机的开关机状态 下面是在ubuntu桌面版上实现远程唤醒功能的设置步骤 第一步 xff1a 计算机BIOS设置 在计算机开机时按F
  • Python 典藏篇-Microsoft Visual C++ 14.0 is required,官方vc++运行库工具一键式解决!

    Python 典藏篇 Microsoft Visual C 43 43 14 0 is required xff0c 官方vc 43 43 运行库工具一键式解决 xff01 前言 xff1a error Microsoft Visual C
  • LwIP在stm32上的无操作系统移植

    LwIP是一个轻型IP协议 xff0c 有无操作系统的支持都可以运行 这里的移植是无操作系统移植 LwIP虽然是一个轻型的IP协议 xff0c 但是TCP IP基本功能都有 而且占用的资源不多 xff0c 非常适合用于嵌入式系统 移植的平台