STM32F4XX LWIP+freeRTOS移植(一)

有疑问请加扣扣技术交流群:460189483

源码下载地址:https://download.csdn.net/download/u014453443/10698059

TM32F429IGT6原子开发板进行验证的,PHY芯片为LAN8720

原子哥的程序都是ucos_ii+lwip的工程,没有freeRTOS+lwip的工程,这里对比二种系统的差异,来进行lwip的freeRTOS的移植

LWIP 无操作系统移植实验的LWIP 文件夹可以发现有一个arch 文件夹,在arch 中有5 个文件cc.h、cpu.h、perf.h、sys_arch.h和sys_arch.c。根据sys_arch.txt 中的描述,cc.h 主要完成了协议栈内部使用的数据类型的定义,如果使用操作系统的话还有临界代码区保护等等。

lwip_comm文件夹,这个文件中有lwip_comm.c、lwip_comm.h 和lwipopts.h这三个文件,lwip_comm.c 和lwip_comm.h 是将LWIP 源码和前面的以太网驱动库结合起来的桥梁!这两个文件非常重要,这两个文件有ALIENTEK 提供。lwipopts.h 是用来裁剪和配置LWIP的文件,以后我们想要使用LWIP 的什么功能的话就在这个文件中配置就行了。

综上所述,ucos_ii+lwip的工程涉及到LWIP的总计8个文件,分别是cc.h、cpu.h、perf.h、sys_arch.h、sys_arch.c、lwip_comm.c 、lwip_comm.h和lwipopts.h。要变更为freeRTOS+lwip,只需要更改cc.h、sys_arch.h、sys_arch.c三个文件即可,其他与ucos_ii+lwip的保持一致即可(将里面ucos_ii的函数替换为freeRTOS的即可)。这几个文件作用如下:

最主要是重写sys_arch.c,sys_arch.h,cc.h这三个文件即可,是参照lwip教程的实验2进行修改进行,要重写的函数基本上都在lwip_sys.h这个文件中定义好了,只要将里面的函数都实现了即可!

1. cc.h的重写

第一步:包含的头文件要改变,includes.h是指包含ucos_ii系统的所有头文件,要使用freeRTOS必须包含FreeRTOS.h

下面如图是使用ucos_ii系统时的头文件

变更为如下所示的头文件,因为在sys_arch.c中要使用到freeRTOS的任务句柄,所以也要包含task.h

第二步:要改变的区域就是临界区代码保护区域,ucos_ii的内容如下:

因为ucos_ii的临界区保护有2种类型,类型根据OS_CRITICAL_METHOD来决定,一般都是用的3,而且ucos_ii的临界区保护不分任务级与中断级,所有保护函数只有一个,而freeRTOS是区分任务级与中断级的,这一点一定要注意!

使用freeRTOS时,这一部分的代码更改如下:

其中,SCB_ICSR_REG定义的寄存器是用于区分当前是任务级还是中断级的,主要在Enter_Critical()与Exit_Critical()中使用,

Enter_Critical()与Exit_Critical()这两个函数是在sys_arch.c中实现的,所以此处加extern声明为外部函数,Enter_Critical()用于声明进入保护临界区,Exit_Critical()声明退出保护临界区,cc.h的内容更改完成

2. sys_arch.h中的重写

在使用ucos_ii时,该文件内容如下:

头文件中includes.h包含的是ucos_ii的头文件,需要更改为FreeRTOS.h,sys_arch.c中要使用FreeRTOS的消息队列和信号量,还必须要包含queue.h和semphr.h;ucos_ii没有消息队列,所以这里使用了自定义的消息队列结构,freeRTOS中本身就有消息队列,可以直接使用,所以变更如下:

经过对比,有些童鞋可能疑问为什么ucos_ii系统中对sys_sem_t、sys_mutex_t、sys_mbox_t数据结构的定义是用的指针,而freeRTOS系统中没有用指针,其实你定义为指针,或者非指针,都可以,对系统没有什么影响,不同之处在于sys_arch.c中函数的实现,如果使用的是指针,那么对变量引用一定要 (*变量)->变量  这样才可以,如果定义为非指针 变量->变量 这样就可以了,大家完全可以按照自己的喜好来定义。

3. sys_arch.c中的重写

sys_arch.c中要重写的函数与ucos_ii一样的,也是实现这几个函数而已,现将两个系统的函数拿来做一下对比,根据原子教程,要实现的函数如下所示:

如果大家想知道这些函数的原型定义,可以在文件lwip_sys.h中找到

第一个:sys_sem_new函数,用于创建消息邮箱,lwip_sys.h中函数原型如下:

使用ucos_ii系统时,实现方法如下:

因为是二级指针,所以要给mbox分配内存,分配内存使用的是原子的内存池的方法,从192k的内部sram中分配,然后使用ucos_II的队列创建函数创建队列,大小为size,如果创建失败就释放掉分配的内存,并返回队列创建的状态信息

使用freeRTOS时变更如下:

使用freeRTOS的队列创建函数创建队列,队列长度为size,消息类型长度为指针长度(4字节),这样就创建了一个存放指针的消息队列,如果创建失败,返回错误,与ucos_ii相比,缺省了内存分配环节,这是因为xQueueCreate函数是动态创建消息队列,由freeRTOS系统自动分配内存,分配失败了不需要自己释放!

第二个:sys_mbox_free函数,用于删除一个消息邮箱,lwip_sys.h中函数原型如下:

使用ucos_ii系统时,实现方法如下:

先创建一个消息队列指针,保存要删除的消息队列,然后调用ucos_ii的函数删除这个消息队列,然后调用原子的sh释放函数释放掉消息队列的内存,将消息队列指针赋值为nu'll,这两个函数都比较好理解。

使用freeRTOS时变更如下:

第三个:sys_mbox_post函数,用于向消息邮箱发送消息,阻塞式发送,不成功一直等待,lwip_sys.h中函数原型如下:

ucos_ii系统时,该函数实现方法如下:

该函数比较好理解,就是向消息邮箱发送消息,如果不成功则一直发送,直到成功为止!

注意pvNullPointer是一个空指针的处理方法,如下值:

freeRTOS系统时,实现方法如下:

此处的空指针处理方法,NullMessage与上面不一样,仅仅是定义了一下,并没有赋值的操作,如下,可以赋值试试:

与ucos相比,分中断中发送消息与任务中发送消息,如果返回pdPASS表示发送成功,xHigherPriorityTaskWoken主要用于中断中发送完消息后,进行判断是否要进行任务切换!

其实如果细心的朋友一定会发现,在这个函数原型中有一句话,说明该函数仅仅用于在任务中发送消息,如下:

所以其实上面的在中断中发送消息,并进行任务切换的操作是多余的,本着严谨的态度还是写上了,只是永远不会执行到!

第四个:sys_mbox_trypost函数,尝试向消息邮箱发送消息,不阻塞式发送,lwip_sys.h中函数原型如下:

在ucos_ii系统中的实现方式如下:

此函数比较简单,只是尝试向消息邮箱发送消息,失败就返回错误,不阻塞!

在freeRTOS中的实现方式如下:

因为该函数没有讲是在任务中还是中断中使用,所以一定要将中断考虑进去,比较简单!

第五个:sys_arch_mbox_fetch函数,从消息邮箱中等待一个新消息,阻塞式等待,lwip_sys.h中函数原型如下:

在ucos_ii系统中的实现方法如下:其中timeout的单位是毫秒

此函数调用OSQPend从消息队列中获取消息,如ucos_timeout=0,就阻塞式等待直到新消息的到来,如果ucos_timeout不为0,等待ucos_timeout个时钟节拍后自动退出,返回OS_ERR_TIMEOUT,函数最终返回SYS_ARCH_TIMEOUT!通过判断消息地址是不是pvNullPointer来判断消息是不是NULL,该指针上面有说明。

freeRTOS的实现方式如下:

这部分的代码是经过优化的,一开始直接尝试进行一次接收,如果有消息就马上返回,节省下了执行下面时间解析的时间,如果消息是空的,再执行等待timeout时间,超时返回!有些人可能疑问freeRTOS系统是分任务级出队函数与中断级出队函数的,为什么我们这里只用到了任务级出队函数,主要是考虑到该函数需要delay timeout时间,应该不会在中断中使用,否则就太傻了吧,中断中使用的应该是下面 sys_arch_mbox_tryfetch这个函数,所以这里只进行了任务级出队函数,大家知道就好!

第六个:sys_arch_mbox_tryfetch函数,尝试从消息邮箱中接收一个新消息,非阻塞式尝试,lwip_sys.h中函数原型如下:

如果接收到消息,返回0,如果没有接收到消息,返回SYS_MBOX_EMPTY

在ucos_ii系统中,该函数的实现方法如下:

这里非常巧妙的调用sys_arch_mbox_fetch函数,将超时时间timeout设置为1毫秒,可能大家会疑惑,sys_arch_mbox_fetch超时时返回的是SYS_ARCH_TIMEOUT,而这里需要返回SYS_MBOX_EMPTY,其实这两个宏定义是一个值,在lwip_sys.h中定义

如果不超时,sys_arch_mbox_fetch返回值是2毫秒,但是按照函数原型应该返回0毫秒才对,这一点没搞懂,希望大神留言!

第7个:sys_mbox_valid函数,检查一个邮箱是否有效,lwip_sys.h中函数原型如下:

返回1表示有效,返回0表示无效

ucos_ii系统中,该函数实现方式如下:

这个就是使用ucos自带的函数实现,通过查看返回值与队列类型来判断,不太理解的可以查看该函数原型

返回值<2表示消息队列为NULL,OSNMsgs是消息队列中的消息数(.OSQEntries的拷贝)OSQSize是消息队列的总的容量

freeRTOS的实现方法如下:

这里的实现比较简单,只是判断该消息队列是否为NULL,感兴趣的可以通过判断队列结构内容来进行判断

第8个:sys_mbox_set_invalid函数,设置一个邮箱无效,lwip_sys.h中函数原型如下:

此函数只是将该一个消息队列设置为无效NULL即可,ucos_ii系统实现方式如下:

freeRTOS的实现方法也很简单,如下:

第9个:sys_sem_new函数,创建一个信号量,lwip_sys.h中函数原型如下:

创建一个信号量,成功返回ERR_OK,失败返回其它,count表示信号量初值,

ucos_ii系统实现方式如下:

就是使用uc内部函数实现信号量的创建,设置初值为count

freeRTOS系统实现方式如下:

freeRTOS中有二值信号量、计数信号量、互斥信号量、递归信号量,此处需要设置初值count,很明显使用计数信号量,第一个参数OXFF表示计数信号量最大计数值,当信号量值等于此值时释放信号量就会失败

第10个:sys_arch_sem_wait函数,等待一个信号量,lwip_sys.h中函数原型如下:

在规定的时间内等待一个信号量,时间是毫秒,如果timeout是0,表示一直等待,成功的话返回值表示等待的时间,如果超时返回SYS_ARCH_TIMEOUT

ucos_ii系统实现方法如下:

比较好理解不解释了,freeRTOS的实现方法如下:

这部分的代码是经过优化的,一开始直接尝试进行一次信号量接收,如果有信号量就马上返回,节省下了执行下面时间解析的时间,如果信号量获取失败,再等待timeout时间,超时返回,或者一直等待,直到有信号量为止!有些人可能疑问freeRTOS系统是分任务级获取信号量函数与中断级获取信号量函数的,为什么我们这里只用到了任务级获取信号量函数,主要是考虑到该函数需要delay timeout时间,应该不会在中断中使用,否则就太傻了吧,所以这里只进行了任务级获取信号量函数,

第11个:sys_sem_signal函数,发送(释放)信号量,lwip_sys.h中函数原型如下:

该函数也比较简单,直接调用系统函数即可,ucos_ii系统实现方法如下:

freeRTOS系统实现方法如下:

这里有一个问题,freeRTOS的信号量释放是区分任务与中断的,ucos不用区分,所以这里接下来会更新,更新如下:

第12个:sys_sem_free函数,删除一个信号量,lwip_sys.h中函数原型如下:

此函数比较简单,就是调用系统函数删除一个信号量,ucos_ii系统实现方法如下:

freeRTOS系统实现方法如下:

第13个:sys_sem_valid函数,查询一个信号量是否有效,lwip_sys.h中函数原型如下:

查询一个信号量是否有效,返回1表示有效,返回0表示无效,ucos_ii实现方法如下:

freeRTOS系统没有查询信号量API,简单实现方法如下:

第14个:sys_sem_set_invalid函数,设置一个信号量无效,lwip_sys.h中函数原型如下:

这个函数比较简单,ucos_ii系统实现如下:

freeRTOS系统实现如下:

第15个:sys_thread_new函数,创建进程,lwip_sys.h中函数原型如下:

仅仅用于创建一个新的进程,该进程用于TCP IP内核进程,name表示线程名称,thread表示线程执行函数,arg传递给线程的参数,stacksize线程堆栈大小,prio线程优先级,ucos_ii系统实现方法如下:

freeRTOS系统实现方法如下:

与uc不同的是,多出来一个任务句柄全局变量的定义LWIP_ThreadHandler,是因为函数需要!

第16个:sys_init函数,初始化操作系统模拟层,lwip_sys.h中函数原型如下:

这个函数不需要填写内容,写一个空函数即可

第17个:sys_msleep函数,LWIP的延时函数,lwip_sys.h中函数原型如下:

ucos_ii系统、freeRTOS系统使用的原子的延时函数

第18个:sys_now函数,获取当前系统时间,单位ms,lwip_sys.h中函数原型如下:

ucos_ii系统直接调用系统API获得时间节拍,再转化为毫秒即可,实现方式如下:

freeRTOS系统实现方式如下:

通过调用HAL_GetTick()获得系统时钟节拍,该函数在系统的滴答时钟中断中被周期的调用,来记录系统时间,过程如下:

第18个:Enter_Critical、Exit_Critical函数,cc.h中声明的临界区代码保护函数,ucos_ii系统直接使用的系统临界区保护函数,freeRTOS中因为分任务级与中断级,所以需要做一个判断,freeRTOS实现代码如下:

通过SCB_ICSR_REG&0XFF来判断是在中断还是任务中

至此,sys_arch.c函数的内容全部完成!

  • 20
    点赞
  • 133
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
### 回答1: 这个问题中混杂了很多不同的概念。我会分别解释: 1. stm32f4xx: 这是指STMicroelectronics(意法半导体)推出的一款32位微控制器系列,它们应用广泛,有很多种型号。 2. lwIP: 这是指"lightweight IP",它是一个开源的TCP/IP协议栈。它具有轻量级、可移植、可扩展等优点,所以在一些嵌入式系统中得到应用。 3. FreeRTOS: 这是指"Free Real-time Operating System",它是一个开源的实时操作系统。它具有小巧、快速、可移植等优点,以及很多年的实战经验,所以在很多嵌入式系统中得到应用。 4. 移植: 指将特定系统的软件、驱动程序等适应不同系统,开发时多数情况下需要将软件适配到具体系统中。 综上所述, "stm32f4xx lwip freertos移植"意为适配lwIP协议栈和FreeRTOS操作系统到stm32f4xx处理器平台。 ### 回答2: STM32F4xx是属于嵌入式系统中的一种芯片,它具有高性能、低功耗、丰富外设等优点。在进行网络通信时,常常会使用到LWIP协议栈(LightWeight IP),LWIP是一个轻量级的开源TCP/IP协议栈,具有跨平台、高度可移植等特性。而FreeRTOS是一种优秀的实时操作系统,能够支持多任务、多线程、中断处理等功能,因此,将这两者进行移植,实现STM32F4xx芯片的网络通信,特别是TCP/IP通信,将是一个很有挑战的任务。 移植LWIP协议栈需要进行以下步骤: 第一步:根据STM32F4xx芯片的电路板、内存大小、外设特性等环境,进行LWIP协议栈的移植。主要包括系统初始化、网络驱动、网络协议栈、网络接口等方面的内容。 第二步:通过LWIP的API接口,实现协议的配置,包括IP地址、掩码、网关、DNS服务器等,并根据不同的协议类型(如TCP、UDP、ICMP等)进行配置。 第三步:通过FreeRTOS的API接口,将网络协议栈与操作系统进行整合,实现多任务并发处理、中断处理、定时器计数等功能,并保证系统稳定性和实时性。 在进行STM32F4xx lwip freertos移植时,需要注意以下几个方面: 一、内存管理:STM32F4xx芯片的RAM和Flash比较小,需要合理地分配内存,避免资源浪费和系统崩溃。 二、时钟配置:LWIPFreeRTOS都需要使用操作系统的时钟进行计数和同步。因此,需要把选定的操作系统时钟映射到芯片上的RC/XTAL或内部晶振,保证时钟精度和稳定性。 三、中断处理:由于网络协议栈需要进行中断处理,因此需要注意中断的优先级和中断处理函数的编写。中断处理函数需要精简、高效,不影响系统的实时性和稳定性。 四、网络接口:STM32F4xx芯片支持多种不同的网络接口,在移植中需要根据具体的需求,选择相应的硬件接口进行配置。并根据不同的接口类型,进行网络驱动程序的编写和配置。 总之,STM32F4xx lwip freertos移植并不是一项简单的任务,需要开发者具备深厚的嵌入式开发经验和相关技能。通过合理的规划、持续的优化,可以实现高效稳定的网络通信。 ### 回答3: 随着物联网应用的日益普及,嵌入式系统中使用lwIPFreeRTOS的需求越来越大。STM32F4系列是一种高性能的嵌入式微控制器,它支持lwIPFreeRTOS,因此很适合用于物联网领域的开发。这篇文章将介绍STM32F4xx lwipFreeRTOS移植步骤。 1. 系统架构 在移植前,需要先了解STM32F4xx系列的架构。STM32F4xx系列的主要子系统有: - Cortex-M4内核 - 系统存储器(SRAM)和闪存 - 外设:USART、SPI、I2C、USB、以太网等 - DMA控制器 lwIP是一个轻量级的IP协议组件库,它能够在嵌入式系统中实现TCP/IP协议栈。在STM32F4xx系列中,lwIPFreeRTOS可以运行在主内存中。为了获得更好的性能,建议采用SRAM作为系统存储器,并为lwIPFreeRTOS预留足够的内存空间。 2. 移植步骤 2.1. 配置IDE开发环境 移植lwIPFreeRTOS需要用到IDE工具,比如Keil、IAR和TrueStudio等。在开发过程中,需要配置好编译器、调试器和开发板等相关环境。 2.2. 配置FreeRTOS FreeRTOSSTM32F4xx系列中的线程操作提供支持。在移植过程中,需要设置线程的优先级、任务管理器、内存管理器和时间管理器等。同时,还需要对FreeRTOS进行适当的调优,以获得更好的性能和可靠性。 2.3. 配置lwIP lwIP移植涉及到网络协议栈,需要对其进行详细的配置。首先要配置网络接口,包括MAC和IP地址、子网掩码、网关和DNS服务器等。然后需要配置协议栈参数,包括缓冲区的大小、超时时间和最大传输单元(MTU)等。最后还需要配置协议栈服务,包括DHCP、NAT、HTTP、FTP和SMTP等。 2.4. 配置硬件平台 在移植过程中,需要配置硬件平台,包括外设控制器、DMA控制器和引脚映射等。在使用网卡时,还需要配置PHY芯片。 3. 移植测试 在完成lwIPFreeRTOS移植后,需要进行测试以确保其功能正常。测试方法包括: - 使用ping测试网络连接 - 使用telnet实现远程命令 - 使用HTTP服务器进行数据交互 移植过程中可能会遇到各种问题,比如芯片引脚分配不当、外设驱动程序错误、协议栈配置不正确等。为了快速诊断问题,可以使用调试工具(比如JTAG调试器)或日志文件进行调试。 总之,STM32F4xx lwipFreeRTOS移植并不是一件容易的事,它需要开发人员具备扎实的嵌入式系统和网络编程技能。当然,一旦成功地移植了它们,就可以让设备更好地应用于物联网领域,为用户提供更为方便、高效和安全的服务。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值