onps栈的移植涉及几个部分:1)系统配置及裁剪;2)基础数据类型定义;3)RTOS适配层实现;4)编写网卡驱动并注册网卡 。本文作为onps栈移植的指导性文件将给出一般性的移植说明及建议 , 具体的移植样例工程及说明请移步码云下载:
- 《onps网络协议栈移植及使用说明v1.0》
- 目标os为rt-thread的移植样例工程(STM32F407VET6及STM32F103RCT6两个平台)
- 目标os为ucos-ii的移植样例工程(硬件平台同上)
1. onps栈的配置及裁剪协议栈源码(码云/github)port/include/port/sys_config.h文件是协议栈的配置文件 。它提供了一系列的配置宏用于裁剪、配置协议栈 。我们可以根据目标系统的具体情况对协议栈进行裁剪,调整配置,以减少或增加对系统资源的占用率 。配置文件主要涉及几方面的内容:
1)打开或关闭某个功能模块;
2)指定mmu(内存管理单元)管理的内存大?。?
3)协议层相关配置项 , 如缺省ttl值、路由表大小、arp缓存表大小等;
onps栈在数据链路层支持两种类型的网络接口:ethernet有线以太网络接口;ppp点对点拨号网络接口 。用户必须选择其中至少一个接口:
#define SUPPORT_PPP1 //* 是否支持ppp:1,支持;0,不支持#define SUPPORT_ETHERNET 1 //* 是否支持ethernet:1,支持;0,不支持
注意,你的目标系统要么支持ppp,要么支持ethernet,要么二者都支持,不能两个都选择不支持,否则协议栈将无法正常工作 。另外协议栈还提供了几个常用的网络工具供用户选择使用,用户可以根据具体应用情形选择打开或关闭相关工具://* 网络工具配置项,0:不支持;1:支持 , 协议栈将编译连接工具代码到目标系统//* ===============================================================================================#define NETTOOLS_PING1 //* ping工具 , 确定目标网络地址是否能到达#define NETTOOLS_DNS_CLIENT 1 //* dns查询客户端,通过指定的dns服务器查询请求域名对应的ip地址#define NETTOOLS_SNTP1 //* sntp客户端,通过指定的ntp服务器进行网络校时//* ===============================================================================================
考虑协议栈的目标系统可能无法提供pc下常见的文件存储系统,所以协议栈的调试日志等信息是通过标准输出提供的:#define SUPPORT_PRINTF 1 //* 是否支持调用printf()输出相关调试或系统信息#if SUPPORT_PRINTF#define PRINTF_THREAD_MUTEX 1 //* 是否支持使用printf线程互斥锁 , 确保不同线程的调试输出信息不被互相干扰,值为1则支持互斥锁#define DEBUG_LEVEL1 //* 共5个调试级别://* 0 输出协议栈底层严重错误//* 1 输出所有系统错误(包括0级错误)//* 2 输出协议栈重要的配置、运行信息 , 同时包括0、1级信息//* 3 输出网卡的原始通讯通讯报文(ppp为收发 , ethnernet为发送) , 以及0、1、2级信息//* 4 输出ethernet网卡接收的原始通讯报文 , 被协议栈丢弃的非法(校验和错误、通讯链路不存在等原因)通讯报文,以及0、1、2、3级信息(除ethernet发送的原始报文)#endif
基本上所有单片机系统均会提供几个串行口 , 我们只需选择其中一个将其作为printf函数的标准输出口 , 我们就可以使能协议栈支持日志输出功能,通过printf()函数输出的日志信息对目标系统进行调试 。如果你的目标系统支持某个串口作为printf()函数的标准输出口,建议将SUPPORT_PRINTF宏置1,打开协议栈的日志输出功能 。PRINTF_THREAD_MUTEX宏用于解决多线程环境下日志输出的冲突问题 。如果你的目标系统互斥资源够用,建议打开该功能,否则你在标准输出口看到的日志会出现乱序问题 。协议栈在很多情形下需要动态申请不同大小的内存以供接下来的逻辑处理过程使用 。所以,为了最大限度地提高协议栈运行过程中的内存利用率并尽可能地减少内存碎片,我们还单独设计了一个独立的内存管理单元(mmu) 。考虑协议栈的目标系统为资源受限的单片机系统,这种系统的内存资源往往都是极度紧张的,因此我们提供了配置宏让用户决定分配多少字节的内存空间给协议栈的mmu:
//* 内存管理单元(mmu)相关配置项,其直接影响协议栈能分配多少个socket给用户使用//* ===============================================================================================#define BUDDY_PAGE_SIZE32//* 系统能够分配的最小页面大小 , 其值必须是2的整数次幂#define BUDDY_ARER_COUNT 9//* 指定buddy算法管理的内存块数组单元数量#define BUDDY_MEM_SIZE8192 //* buddy算法管理的内存总大小 , 其值由BUDDY_PAGE_SIZE、BUDDY_ARER_COUNT两个宏计算得到://* 32 * (2 ^ (9 - 1)),即BUDDY_MEM_SIZE = BUDDY_PAGE_SIZE * (2 ^ (BUDDY_ARER_COUNT - 1))//* 之所以在此定义好要管理的内存大?。?原因是buddy管理的内存其实就是一块提前分配好的静态存储时期的字节型//* 一维数组,以此来确保协议栈不占用宝贵的堆空间//* ===============================================================================================
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 开源网络协议栈onps诞生记
- <一>从指令角度了解函数堆栈调用过程
- stm32h750移植lvgl
- 3 Python全栈工程师之从网页搭建入门到Flask全栈项目实战 - 入门Flask微框架
- 都卷Java,你看看你得学多少技术栈才能工作!
- flutter系列之:flutter中可以建索引的栈布局IndexedStack
- SpringBoot+Vue3 AgileBoot - 手把手一步一步带你Run起全栈项目
- C++ 使用栈求解中缀、后缀表达式的值
- 1 Python全栈工程师之从网页搭建入门到Flask全栈项目实战 - ES6标准入门和Flex布局
- windows C++ 异常调用栈简析