onps栈移植说明(2)——编译器及os适配层移植
2. 字节对齐及基础数据类型定义
协议栈源码(码云/github)port/include/port/datatype.h中根据目标系统架构(16位 or 32位)及所使用的编译器定义基础数据类型及字节对齐方法。这个文件中最重要的移植工作就是依据目标编译器手册定义字节对齐方法。因为网络协议栈最关键的地方就是底层通讯报文结构必须字节对齐,而不是通常情形下的缺省四字节对齐。
#define PACKED __attribute__((packed)) //* 缺省提供了gcc编译器的字节对齐方法
#define PACKED_FIELD(x) PACKED x
#define PACKED_BEGIN
#define PACKED_END
协议栈源码提供了常用的gcc编译器的字节对齐方法。PACKED宏及PACKED_BEGIN/PACKET_END组合体宏通常用于结构体字节对齐定义。二者选其一实现即可。PACKED_FIELD宏用于定义单个变量字节对齐。注意,字节对齐定义是整个协议栈能否正常运转的关键。所以,必须确保该定义能正常工作。
协议栈源码提供了32位系统下的基础数据类型定义样例,具体移植时可参考该样例进行调整:
//* 系统常用数据类型定义(不同的编译器版本,各数据类型的位宽亦不同,请根据后面注释选择相同位宽的类型定义)
typedef unsigned long long ULONGLONG; //* 64位无符号长整型
typedef long long LONGLONG; //* 64位有符号长整型
typedef signed long LONG; //* 32位的有符号长整型
typedef unsigned long ULONG; //* 32位的无符号长整型
typedef float FLOAT; //* 32位的浮点型
typedef double DOUBLE; //* 64位的双精度浮点型
typedef signed int INT; //* 32位的有符号整型
typedef unsigned int UINT; //* 32位的无符号整型
typedef signed short SHORT; //* 16位的有符号短整型
typedef unsigned short USHORT; //* 16位的无符号短整型
typedef char CHAR; //* 8位有符号字节型
typedef unsigned char UCHAR; //* 8位无符号字节型
typedef unsigned int in_addr_t; //* internet地址类型
其中in_addr_t比较特殊,用于socket编程,其为IPv4地址类型,其必须是无符号4字节整型数。
3. OS适配层
对于 os 适配层,主要的移植工作就几块:1)提供多任务(线程)建立函数;2)提供系统级的秒级、毫秒级延时函数及运行时长统计函数;3)提供同步(互斥)锁相关操作函数;4)提供信号量操作函数;5)提供一组临界区保护也就是中断禁止/使能函数。os 适配层的移植工作涉及 os_datatype.h、os_adapter.h、os_adapter.c 三个文件。
3.1 os_datatype.h
这个文件负责完成与目标操作系统相关的数据类型定义,主要就是互斥锁、信号量、tty这三种数据类型的定义。互斥锁用于线程同步,信号量用于线程间通讯,tty则用于ppp模块。我们需要在这个文件里定义能够唯一的标识它们的访问句柄供协议栈使用。
typedef INT HMUTEX; //* 线程互斥(同步)锁句柄
#define INVALID_HMUTEX -1 //* 无效的线程互斥(同步)锁句柄
#if SUPPORT_PPP
typedef INT HTTY; //* tty终端句柄
#define INVALID_HTTY -1 //* 无效的tty终端句柄
#endif
typedef INT HSEM; //* 信号量,适用与不同线程间通讯
#define INVALID_HSEM -1 //* 无效的信号量句柄
注意,上面给出的只是一般性定义,使用时请依据目标os的实际情形进行调整。另外,如果你的目标系统不需要ppp模块,HTTY及INVALID_HTTY无须定义。
源码工程提供的os_datatype.h文件为样例文件。基于协议栈的通用性考虑,样例文件提供的与os相关的数据类型定义存在冗余。除上述三种数据类型必须定义外,其它预留的类型如目标系统已提供,建议直接使用目标系统的定义,os_datatype.h文件中的冗余定义直接注释掉即可;如不存在,则直接使用样例文件中的通用定义即可。
3.2 os_adapter.h
协议栈业务逻辑的完成离不开os的支持,这个文件的主要作用就是提供与os相关的接口函数声明,然后在os_adapter.c中实现这些函数。所以,这个文件中要调整的地方并不多,只有两处。一个是协议栈内部工作线程控制块:
typedef struct _STCB_PSTACKTHREAD_ { //* 协议栈内部工作线程控制块,其用于线程建立
void(*pfunThread)(void *pvParam); //* 线程入口函数
void *pvParam; //* 传递给入口函数的用户参数
} STCB_PSTACKTHREAD, *PSTCB_PSTACKTHREAD;
这个结构体与目标os高度相关,其用于保存协议栈内部工作线程列表。协议栈内部设计了一个one-shot定时器。该定时器被用于一些需要等待一小段时间才能进行后续处理或定期执行的业务模块。这个定时器是以线程的方式实现的。协议栈的核心业务逻辑均与这个one-shot定时器线程有关。协议栈被目标系统加载时该线程将由os_thread_onpstack_start()函数自动启动。这个函数要启动的线程列表就被保存在STCB_PSTACKTHREAD结构体数组中。这个数组是一个静态存储时期的变量,变量名为lr_stcbaPStackThread,在os_adapter.c中定义。STCB_PSTACKTHREAD结构体需要定义哪些成员变量由目标os提供的线程启动函数的入口参数决定。我们会将线程启动用到的入口参数值定义在lr_stcbaPStackThread数组中,然后由os_thread_onpstack_start()将这些参数值传递给线程启动函数启动相应工作线程。
另外一个地方是临界区保护函数:
#define os_critical_init() //* 临界区初始化
#define os_enter_critical() //* 进入临界区(关中断)
#define os_exit_critical() //* 退出临界区(开中断)
一般的os临界区保护函数基本都是进入临界区关中断,离开临界区开中断。代码非常简单,所以这里直接给出了三个函数宏原型,移植时请依据目标系统具体情形添加对应的开、关中断代码即可。
3.3 os_adapter.c
这个文件的核心工作就是编码实现 os_adapter.h 文件声明的所有与 os 相关的接口函数。os_adapter.h中有这些函数的详细功能说明,移植时按照说明实现具体功能即可,不再赘述。
//* 当前线程休眠指定的秒数,参数 unSecs 指定要休眠的秒数
OS_ADAPTER_EXT void os_sleep_secs(UINT unSecs);
//* 当前线程休眠指定的毫秒数,单位:毫秒
OS_ADAPTER_EXT void os_sleep_ms(UINT unMSecs);
//* 获取系统启动以来已运行的秒数(从 0 开始)
OS_ADAPTER_EXT UINT os_get_system_secs(void);
//* 线程同步锁初始化,成功返回同步锁句柄,失败则返回INVALID_HMUTEX
OS_ADAPTER_EXT HMUTEX os_thread_mutex_init(void);
//* 线程同步区加锁
OS_ADAPTER_EXT void os_thread_mutex_lock(HMUTEX hMutex);
//* 线程同步区解锁
OS_ADAPTER_EXT void os_thread_mutex_unlock(HMUTEX hMutex);
//* 删除线程同步锁,释放该资源
OS_ADAPTER_EXT void os_thread_mutex_uninit(HMUTEX hMutex);
//* 信号量初始化,参数unInitVal指定初始信号量值, unCount指定信号量最大数值
OS_ADAPTER_EXT HSEM os_thread_sem_init(UINT unInitVal, UINT unCount);
//* 投递信号量
OS_ADAPTER_EXT void os_thread_sem_post(HSEM hSem);
//* 等待信号量到达,参数unWaitSecs指定要等待的超时时间(单位为秒):
//* 0,一直等下去直至信号量到达,收到信号则返回值为0,出错则返回值为-1;
//* 大于0,等待指定时间,如果指定时间内信号量到达,则返回值为0,超时则返回值为1,出错则返回值为-1
OS_ADAPTER_EXT INT os_thread_sem_pend(HSEM hSem, INT nWaitSecs);
//* 信号量去初始化,释放该资源
OS_ADAPTER_EXT void os_thread_sem_uninit(HSEM hSem);
//* 启动协议栈内部工作线程
OS_ADAPTER_EXT void os_thread_onpstack_start(void *pvParam);
#if SUPPORT_PPP
//* 打开 tty 设备,返回 tty 设备句柄,参数 pszTTYName 指定要打开的 tty 设备的名称
OS_ADAPTER_EXT HTTY os_open_tty(const CHAR *pszTTYName);
//* 关闭 tty 设备,参数 hTTY 为要关闭的 tty 设备的句柄
OS_ADAPTER_EXT void os_close_tty(HTTY hTTY);
//* 向 hTTY 指定的 tty 设备发送数据,返回实际发送的数据长度
//* hTTY:设备句柄
//* pubData:指针,指向要发送的数据的指针
//* nDataLen:要发送的数据长度
OS_ADAPTER_EXT INT os_tty_send(HTTY hTTY, UCHAR *pubData, INT nDataLen);
//* 从参数 hTTY 指定的 tty 设备等待接收数据,阻塞型
//* hTTY:设备句柄
//* pubRcvBuf:指针,指向数据接收缓冲区的指针,用于保存收到的数据
//* nRcvBufLen:接收缓冲区的长度
//* nWaitSecs:等待的时长,单位:秒。0 一直等待;直至收到数据或报错,大于 0,等待指定秒数;小于 0,不支持
OS_ADAPTER_EXT INT os_tty_recv(HTTY hTTY, UCHAR *pubRcvBuf, INT nRcvBufLen, INT nWaitSecs);
//* 复位 tty 设备,这个函数名称体现了 4g 模块作为 tty 设备的特殊性,其功能从本质上看就是一个 modem,modem 设备出现通讯
//* 故障时,最好的修复故障的方式就是直接复位,复位可以修复绝大部分的因软件问题产生的故障
OS_ADAPTER_EXT void os_modem_reset(HTTY hTTY);
#endif
onps栈移植说明(2)——编译器及os适配层移植的更多相关文章
- onps栈移植说明(3)——添加网卡
4. 添加网卡 移植的最后一步就是编写网卡驱动然后将网卡添加到协议栈.网卡驱动其本质上完成的是数据链路层的工作,在整个通讯链路上处于通讯枢纽位置,通讯报文的发送和接收均由其实际完成.针对网卡部分的移植 ...
- onps栈移植说明(1)——onps栈的配置及裁剪
onps栈的移植涉及几个部分:1)系统配置及裁剪:2)基础数据类型定义:3)RTOS适配层实现:4)编写网卡驱动并注册网卡.本文作为onps栈移植的指导性文件将给出一般性的移植说明及建议,具体的移植样 ...
- 基于Linux的kfifo移植到STM32(支持os的互斥访问)
基于Linux的kfifo移植到STM32(支持os的互斥访问) 关于kfifo kfifo是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现:它提供一个 ...
- onps栈使用说明(1)——API接口手册
1. 底层API 由协议栈底层提供的api,用于涉及底层操作的一些功能实现,这些api接口函数的原型定义分布于不同的文件,它们被统一include进了onps.h中: open_npstack_loa ...
- uc/os iii移植到STM32F4---IAR开发环境
也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...
- 【课程分享】深入浅出嵌入式linux系统移植开发 (环境搭建、uboot的移植、嵌入式内核的配置与编译)
深入浅出嵌入式linux系统移植开发 (环境搭建.uboot的移植.嵌入式内核的配置与编译) 亲爱的网友,我这里有套课程想和大家分享,假设对这个课程有兴趣的,能够加我的QQ2059055336和我联系 ...
- onps栈使用说明(2)——ping、域名解析等网络工具测试
1. ping测试 协议栈提供ping工具,其头文件为"net_tools/ping.h",将其include进你的目标系统中即可使用这个工具. -- #include " ...
- uC/OS - III 移植 IAR平台
关于移植uC/OS-III 网上已经有很多教程了此处只是做个记录 首先下载源码然后解压得到下面的文件: 然后在模版工程里新建各种文件夹: 最后全部都添加进工程: OK了,编译一下,惊呆了,竟然 0错误 ...
- 自己写个 Drools 文件语法检查工具——栈的应用之编译器检测语法错误
一.背景 当前自己开发的 Android 项目是一个智能推荐系统,用到 drools 规则引擎,于我来说是一个新知识点,以前都没听说过的东东,不过用起来也不算太难,经过一段时间学习,基本掌握.关于 d ...
随机推荐
- QQ高级功能
本篇文章为微信公众号:酿俗 教学内容请跟着小编一起探索吧! 第一步解锁微信豆影藏内容 随后下载需要的材料,注意!手机可能会提示有病毒!这里使用这些功能报病毒很正常 其实并没有病毒只是手机厂商的安全系统 ...
- 第三十一篇:vue3和vue2的不同
好家伙 1.为什么会有vue3? Vue2和Vue3的区别 - 简书 (jianshu.com) 貌似是因为他的对手太优秀,所以他也必须进步 2.什么是api? 从文件操作开始谈API. 以C语言为例 ...
- ifort + mkl + impi (全套intel)编译安装量子化学软件GAMESS 2022 R1版本
说明:linux下编译软件都需要先配置好该软件依赖的系统环境.系统环境可以通过软件的安装说明了解,例如:readme.md等文件或网页.这个前提条件很重要!后面正式编译出错基本都可以归结到系统环境配置 ...
- KingbaseES rownum 与 limit 的 执行计划区别
数据准备 --创建基础数据表100W行 create table test07 as select * from (select generate_series(1, 1000000) id, (ra ...
- KingbaseES中的参数查看与修改
KingbaseES数据库的配置参数都在kingbase.conf文件中,这些参数有些是直接修改就可以生效,有些需要重启数据库才能生效,而有些根本就不能修改.数据库把这些参数分为以下几类: inter ...
- linux下搭建ftp文件服务器
linux下搭建ftp文件服务器 一.搭建步骤(以在centos7中搭建为例) 1.首先检查一下系统中是否已经安装了vsftpd软件 # 查看是否安装vsftpd rpm -q vsftpd rpm ...
- 使用ESP8266nodeMCU 向微信推送模板数据
使用HTTPS协议向微信公众号推送消息,(使用ESP8266的低成本实现) 前几天被朋友问到这个东西的实现方式,花了一下午时间研究一下,特此记录.没有排版比较乱. 一丶前往微信公众平台注册微信微信公众 ...
- 第六章:Django 综合篇 - 11:分页 Paginator
分页功能是几乎所有的网站上都需要提供的功能,当你要展示的条目比较多时,必须进行分页,不但能减小数据库读取数据压力,也有利于用户浏览. Django又很贴心的为我们提供了一个Paginator分页工具, ...
- 在 Kubernetes 容器集群,微服务项目最佳实践
转载自:https://mp.weixin.qq.com/s/WYu3gDwKKf06f_FYbO9YRg 本文主要介绍我个人在使用 Kubernetes 的过程中,总结出的一套「Kubernetes ...
- Maven+SpringMVC+Dubbo 简单的入门demo配置
转载自:https://cloud.tencent.com/developer/article/1010636 之前一直听说dubbo,是一个很厉害的分布式服务框架,而且巴巴将其开源,这对于咱们广大程 ...