RTThread嵌入式系统有着丰富的网络组件,虽然官方提供的文档也很详细,但是各个组件之间的耦关系并不是很明确,这就对于我这种初学者有了很大的难度。这两天我从开始学习设备驱动UART设备->基于UART设备的AT组件->基于AT组件的AT设备和AT Socket->netdev网卡层->SAL套接字抽象层。经过这几天不断的学习,终于简单的弄明白了,它们之间的耦合关系。好记性不烂笔头,我觉得为了防止我忘记,还是需要记录一下比较好。
本文章所有内容都是基于正点原子的STM32L475开发板,因为RTThread对此开发板提供了大量的丰富的文档和例程,所以学起来也比较方面,网卡模块使用的是ESP8266,内置lwip协议,采用AT指令基于L475的UART2进行数据传输。

1.设备驱动UART2

1.RTThread驱动大体流程

RTThread提供了基于HAL库的驱动,所以,也不需要自己去写UART的驱动,是需要在env工具中打开使能UART2即可。我这个L475的打开路径如下所示:

打开以后,在rtconfig.h文件中有找到这个选项:

MDK工程中就会多drv_usart.c,serial.c文件。其中drv_usart.c文件是基于STM32HAL库编写的底层UART驱动文件,不同系列的芯片代码可能不一样,然后serial.c文件是RTThread的串口驱动的框架文件,向下给drv_usart.c提供统一UART操作函数结构体struct rt_uart_ops,然后drv_usart.c将此结构的具体内容实现,然后通过serial.c的rt_hw_serial_register把此结构体注册给serial.c文件使用,然后serial.c文件根据此结构体的不同内容进行封装成RTThread的device的格式通过rt_device_register注册给RTThread内核的设备管理,这样我们就不需要关系底层的具体硬件驱动代码实现,是需要RTThread提供的deviceAPI来访问不同的设备。
其中从硬件底层驱动代码到生成device的关系如下:

其中rt_hw_serial_register函数和struct rt_uart_ops结构体的内容是serial.c文件提供的,serial.c规定底层硬件驱动代码的功能和把底层功能进行按照rt_device的要求进行封装,然后将封装后的内容注册到内核中,统一管理使用。rt_device函数和struct rt_device结构体是device.c文件提供。

2.UART具体硬件驱动

UART的每一个硬件驱动定义在uart_config.h的文件中,路径libraries\HAL_Drivers\config\l4\uart_config.h。它定义了基于HAL库串口使用的串口基本东西,比如串口1的寄存器地址,串口1的中断服务函数名字,和注册到内核驱动的串口名字,通过此名字可以查找到具体的驱动。

串口所使用的的IO引脚是在STMl4xx_hal_msp.c文件中定义的,让初始化串口是,这个里面针对串口IO的回调函数就会执行,然后就初始化了具体的引脚。路径board\CubeMX_Config\Src\stm32l4xx_hal_msp.c。这个文件是通过STM32CubeMX软件生成的,生成以后我们可以根据具体情况自己修改。

然后,串口API操作函数可以通过文件RTThread官网文档来查看。

2.AT组件

1.AT基本框架

AT组件是RTThread针对采用AT命令的设备推出的框架,我们使用AT模块主要也就是使用AT框架的AT Client功能,在env工具中打开:

然后在构建工程就可以添加到MDK中了。
如果我们自己使用AT框架,只需要通过int at_client_init(const char *dev_name, rt_size_t recv_bufsz)此函数初始化AT框架就可以了,dev_name参数是AT组件与AT模块进行数据通信是所使用的的设备名字,比如我的ESP8266使用的是UART2,这个参数就是UART2传入即可,然后recv_bufsz是一次接受AT命令消息的大小,可以自由设置,小的话接受的AT消息可能不全。
初始化完成以后我们就可以通过调用at.h里面声明的不用的函数名来操作AT设备了,具体函数操作意思,可以通过点击RTThread官网文档来查看。

2.2AT设备框架

AT设备框架主要是struct at_device结构体,路径packages\at_device-v2.0.2\inc\at_device.h。它包含了这个设备所有的功能,包括设备操作函数,at_socket操作函数,这俩是在设备类中包含,所使用的AT组件结构体,注册成网卡的结构体,at_socket结构体。在具体的设备文件驱动中,需要根据设备的实际情况初始化响应的内容。其中的user_data变量存放这个此AT设备全部信息结构体的地址。
需要先使用at_device_class_register函数将此设备的操作函数注册到AT设备类链表中,然后再使用at_device_register函数注册到AT设备链表中。
在AT设备驱动文件中,需要先定义struct at_device_ops结构体变量,然后按照at_device_ops的要求实现具体内容,将其添加到定义的at_device_calss结构体变量中,然后注册到AT设备类链表中。最后AT设备驱动中需要定义struct at_device结构体变量,然后按照它的要求实现具体内容,然后注册到设备链表中。

3.AT_SOCKET

at_socket其实算是at_device的一部分,开启at_device的时候就默认使用了at_socket功能,它简化了我们使用AT设备进行网络开发的步骤,可以直接使用BSD套接字的方法直接在AT设备上进行网络编程。
在AT设备SOCKET驱动文件中,也需要定义struct at_socket_ops变量,然后根据AT基本组件按照at_socket的要求实现其内容,将其添加到定义的at_device_class结构体变量中,最后将at_device_class注册到AT设备类链表中。

3.netdev网卡

netdev网卡是管理每一个网络接口设备,统一提供给上层SAL组件所使用的框架,其具体内容可以参照RTThread netdev官方文档。每一个网络接口设备都使用一个struct netdev结构体变量来管理,包含了设备名字,设备IP、网关等一系列的信息。一般在网卡设备初始化中将其注册为网卡。net_dev的sal_user_data变量保存了该网卡进行BSD编程的操作函数信息。
在AT设备驱动文件中,一部分是根据at_device结构体实现AT设备基本操作函数,另一部分就是根据AT基础组件操作函数AT设备将其网卡相关的功能进行封装,然后将其注册成为网卡设备。先定义一个struct netdev_ops结构体变量,然后根据其要求实现其内容,在使用netdev_register函数将其注册。

4.SAL套接字抽象层

SAL套接字抽象层是根据不同的网络协议栈封装成统一的BSD操作函数,提供使用,包括了LWIP、AT、WIZNET,其具体信息根据RTThread SAL官方文档查看。
其中SAL.h文件里面包含了不同协议栈适配SAL抽象层所需要注册的内容,AT协议栈是在af_net_at.c中进行适配,然后只需要在AT设备文件中在注册netdev前调用sal_at_netdev_set_pf_info()函数就可以将AT协议栈适配到SAL抽象层了,就可以通过sal_socket.h文件进行网络编程了。

5.程序调用过程

5.1注册过程

INIT_DEVICE_EXPORT(esp8266_device_class_register);RTThread自动初始化组件注册at_device_class=> class = (struct at_device_class *) rt_calloc(1, sizeof(struct at_device_class)); 分配内存=> esp8266_socket_class_register(class); => class->socket_num = AT_DEVICE_ESP8266_SOCKETS_NUM; ESP8266最大支持的socket数量=> class->socket_ops = &esp8266_socket_ops保存at_socket_ops到class=> class->device_ops = &esp8266_device_ops; 保存at_device_ops到class=> at_device_class_register(class, AT_DEVICE_CLASS_ESP8266); 注册到AT设备类链表
at_device_register()运行设备前注册设备=> device->sockets = (struct at_socket *) rt_calloc(class->socket_num, sizeof(struct at_socket));根据支持的最大
socket数据分配响应的空间。=> device->class = class;保存AT设备类首地址到at_device结构体中=> device->user_data = user_data; 保存用户数据=> rt_slist_append(&at_device_list, &(device->list)); 保存当前设备结构体到AT设备链表=> class->device_ops->init(device); 初始化当前设备=> at_client_init(esp8266->client_name, esp8266->recv_line_num);初始化AT基本组件=> device->client = at_client_get(esp8266->client_name);保存AT基本组件信息到at_device中=> at_obj_set_urc_table();设置URC回调函数 针对配置的URC=> esp8266_socket_init(device);初始化esp8266 socket=> at_obj_set_urc_table()也是设备URC回调函数,针对收发消息的URC=> device->netdev = esp8266_netdev_add(esp8266->device_name); 将esp8266注册成网卡=> netdev = (struct netdev *) rt_calloc(1, sizeof(struct netdev));分配内存=> netdev->ops = &esp8266_netdev_ops;设备网卡操作函数=> sal_at_netdev_set_pf_info(netdev);将AT协议栈操作函数适配到SAL抽象层=> netdev_register(netdev, netdev_name, RT_NULL)注册网卡=> esp8266_netdev_set_up(device->netdev);打开网卡=> device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);根据名字获取at_device=> esp8266_net_init(device);初始化at_device=> esp8266_init_thread_entry(device);根据env设置的是否是线程初始化esp8266,当前不是线程初始化=> AT+RST ATE0 等ESP基本功能初始化=> netdev_low_level_set_status(netdev, RT_TRUE);设置网卡状态

RTThread从底层AT组件到上层SAL之间的关系相关推荐

  1. 泛型编程、STL的概念、STL模板思想及其六大组件的关系,以及泛型编程(GP)、STL、面向对象编程(OOP)、C++之间的关系

    介绍STL模板的书,有两本比较经典: 一本是<Generic Programming and the STL>,中文翻译为<泛型编程与STL>,这本书由STL开发者 Matth ...

  2. 通过SSIS的“查找”组件进行不同数据源之间数据的合并操作

    通过SSIS的"查找"组件进行不同数据源之间数据的合并操作 原文:通过SSIS的"查找"组件进行不同数据源之间数据的合并操作 为了协助开发还原生产环境中的某些b ...

  3. 组件设计实战--组件之间的关系 (Event、依赖倒置、Bridge)

        一个组件与另一个组件之间的关系可以通过三种方式建立起来:事件.依赖倒置.Bridge.现在我们只考虑单向依赖的关系,即信息提供者和信息消费者.事件是一种松耦合的信息发布方式,事件发布者(信息提 ...

  4. React学习:组件之间的关系、参数传递-学习笔记

    文章目录 React学习:组件之间的关系.参数传递-学习笔记 父到子传递参数 子-父 父-孙 兄弟组件传参 React学习:组件之间的关系.参数传递-学习笔记 父到子传递参数 <!DOCTYPE ...

  5. 【项目实战——emos在线办公系统】:组件之间的相互使用、请假页面、添加请假组件之间的关系梳理、model和v-model

    一.组件方法之间的调用 1.父组件调用子组件 1.在父组件中:首先要引入子组件 import Child from './child'; 2. <child ref="mychild& ...

  6. 计算机底层:ASCII码、区位码、国标码、汉字机内码,还有字形码和输入输出编码之间的关系以及介绍

    计算机底层:ASCII.区位码.国标码.汉字机内码之间的关系,还有字形码和输入输出编码之间的关系以及介绍 键盘上有:数字.字母.符合.这些都称作为字符,而它们的组合就叫做:字符串. ASCII 键盘上 ...

  7. RT-Thread—FAL与EasyFlash组件移植

    一.FAL管理与示例 FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理.操作的抽象层,对上层统一了 Flash 及 ...

  8. 底层节点到节点上层是端到端_nEqual发布全新一代CDP平台宙斯版,解构企业营销数字化的底层逻辑...

    企业数字化的浪潮已经向前奔涌了几年之久,随着包括消费者在内的外部环境和节奏已经全面数字化,企业数字化几乎是一个必行之举.到了今年,成熟的环境和疫情的到来使得行业中绝大多数从业者,都看见了实施数字化后的 ...

  9. 字节跳动推荐平台技术公开,项亮:底层架构有时比上层算法更重要

    允中 发自 凹非寺 量子位 报道 | 公众号 QbitAI 字节跳动已正式吹响进军云计算市场号角. 12月2日,火山引擎全系列云产品亮相,共推出了78项云产品服务,涵盖云基础.视频及内容分发.数据中台 ...

最新文章

  1. spring boot 系列之四:spring boot 整合JPA
  2. Tensorflow实现MNIST数据自编码(1)
  3. boost::posix_time和boost::date_time杂项的测试程序
  4. Solr-4.10.2安装
  5. 动态规划--总体理解
  6. 算法基本和常见排序算法
  7. 25. 单体内置对象
  8. MySQL学习十四创建和操纵表
  9. 金融网络直播室软件的功能介绍
  10. connect holder is null问题记录
  11. 侏罗纪怪兽世界怎么登陆服务器未响应,全金属怪物一直登入不进去怎么办
  12. 直播带货系统是如何实现直播录屏的
  13. 7代服务器cpu型号,七代酷睿都有哪些型号?_笔记本新闻-中关村在线
  14. Ardunio开发实例-LM75温度传感器
  15. SpringMVC处理器映射器HandlerMapping
  16. 用Python学《微积分B》(多元函数的极限)
  17. RSD处理高分5号高光谱(GF5 AHSI)数据(二)——波段编辑复制和删除
  18. Carpenter's Complete Guide to the SAS REPORT Procedure
  19. IJCAI-18 阿里妈妈广告转化预测
  20. 却顾所来径,苍苍横翠微——那一代人的读书功夫

热门文章

  1. PPT制作和美化插件工具
  2. u盘硬盘数据损坏丢失如何恢复?高恢复率高的数据恢复软件
  3. HAC集群中,计划重新初始化数据库使用原集群配置的操作方法
  4. 斗鱼连续6个季度亏损:活跃用户降幅明显,虎牙市值是前者的两倍
  5. shell里面的jq
  6. 大型企业局域网安全解决方案
  7. 程序员吐槽:四年被三家公司裁员补偿,网友:去BAT转转?
  8. 拉勾Java工程师P7训练营 高薪笔记
  9. 概述计算机系统的组成和工作原理,计算机系统的组成1.ppt
  10. risc-v vector扩展1.0版本解读(riscv-v-spec-1.0)