Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
【RSOC-2024】DAY5 星火一号上云
发布于 2024-07-29 22:17:52 浏览:395
订阅该版
[tocm] # RT-Thread软件包与RT-Thread组件 ## 软件包 ### 定义与特性 RT-Thread软件包是运行于RT-Thread物联网操作系统平台上的通用软件组件,由描述信息、源代码或库文件组成。这些软件包面向不同应用领域,为开发者提供了众多可重用的选择,极大地促进了RT-Thread生态的繁荣。RT-Thread提供了开放的软件包平台,存放了官方及开发者提供的软件包。这些软件包具有很强的可重用性和模块化程度,方便应用开发者在最短时间内打造出所需的软件。 ### 分类与功能 RT-Thread软件包涵盖了多个领域,包括但不限于: - **物联网相关**:包括Paho MQTT、WebClient、mongoose等,用于实现物联网设备的通信和数据交换。 - **安全相关**:如mbedtls、libsodium等,提供加密通信和数据安全保护。 - **脚本语言相关**:如JerryScript、MicroPython等,允许在嵌入式设备上运行高级脚本语言。 - **多媒体相关**:如Openmv、mupdf等,提供机器视觉和文档解析等功能。 - **工具类**:如CmBacktrace、EasyFlash等,辅助开发和调试过程。 ## 组件 ### 定义与特性 RT-Thread组件是构成RT-Thread操作系统的基础单元,它们提供了各种系统服务和功能。这些组件包括但不限于文件系统、网络协议栈、图形库等中间件组件,以及实时内核本身。RT-Thread组件的设计考虑了模块化、可裁剪和可扩展性,以适应不同应用场景和资源受限的嵌入式设备。 ### 主要组件示例 - **实时内核**:RT-Thread的核心组件,提供了多任务调度、线程管理、同步机制等实时操作系统的基础功能。 - **FinSH**:RT-Thread的命令行组件,提供了一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。 - **虚拟文件系统(DFS)**:为应用程序提供统一的POSIX文件和目录操作接口,支持多种类型的文件系统和存储设备。 - **网络接口设备(netdev)**:用于网卡管理和控制,使得RT-Thread系统能够适配更多种类的网卡并实现网络通信。 ## 虚拟文件系统 ### 定义 RT-Thread的虚拟文件系统DFS是一个在操作系统层面上实现的,用于抽象和管理存储设备上数据的文件系统框架。它使得应用程序能够以一种统一的方式访问和操作存储在各种存储设备上的数据。 ### 主要特点 - **统一的POSIX接口**:DFS为应用程序提供了统一的POSIX(Portable Operating System Interface of UNIX)文件和目录操作接口,如read、write、poll/select等。这使得RT-Thread能够方便地兼容和移植来自Unix/Linux的应用程序。 - **支持多种文件系统**:DFS支持多种类型的文件系统,包括但不限于FatFS、RomFS、DevFS、Jffs2、NFS、UFFS等。这些文件系统各有特点,适用于不同的应用场景和存储设备。 - **支持多种存储设备**:DFS支持多种类型的存储设备,如SD Card、SPI Flash、Nand Flash等。这使得RT-Thread能够灵活地应用于各种嵌入式设备中。 - **文件描述符的统一性**:在RT-Thread中,DFS实现了文件描述符的统一性。普通文件、设备文件、网络文件描述符都被视为同一种文件描述符,可以使用poll/select接口进行统一轮询,降低编程的复杂度。 ** 目录架构如下图所示 ** ![screenshot_pkLMsQs.png](https://oss-club.rt-thread.org/uploads/20240730/0e4e89134445c240a45c94715ac64411.png) # RT-Thread DFS架构层次 ## POSIX接口层 POSIX接口层定义了操作系统应该为应用程序提供的接口标准,即POSIX标准接口。这是应用程序与DFS进行交互的入口。通过POSIX接口,应用程序可以执行文件操作,如打开、关闭、读取、写入、定位文件指针等,而无需关心底层文件系统的具体实现和存储设备的细节。 ## 虚拟文件系统层 虚拟文件系统层是DFS的核心,它负责将不同的文件系统和存储设备抽象为统一的接口,供上层应用程序调用。在这一层,用户可以将具体的文件系统(如FatFS、RomFS等)注册到DFS中,并使用该文件系统的所有功能。虚拟文件系统层还提供了统一的文件访问接口,使得应用程序能够以一致的方式访问不同文件系统上的数据。 ## 设备抽象层 设备抽象层将物理设备(如SD Card、SPI Flash等)抽象成符合文件系统能够访问的设备(如块设备)。不同文件系统类型是独立于存储设备驱动而实现的,因此设备抽象层的作用是将底层存储设备的驱动接口和文件系统对接起来。通过设备抽象层,文件系统能够正确地访问存储设备上的数据,而无需关心存储设备的具体类型和驱动实现。 这三个层次共同构成了RT-Thread的虚拟文件系统(DFS)架构,为应用程序提供了高效、灵活的文件访问能力。通过这一架构,RT-Thread能够支持多种文件系统和存储设备,满足不同应用场景的需求。 ![screenshot_pkLMBWQ.md.png](https://oss-club.rt-thread.org/uploads/20240730/a39040bcfc8103c9bced333b769f2ac6.png.webp) # MQTT协议 MQTT(消息队列遥测传输)协议是一种基于发布/订阅范式的轻量级消息协议,它工作在TCP/IP协议族上,专为硬件性能低下的远程设备以及网络状况不佳的环境设计。MQTT协议简单、开放、易于实现,支持大量计算能力有限且工作在低带宽、不可靠网络的远程传感器和控制设备通讯。其特点包括使用发布/订阅消息模式、对负载内容屏蔽的消息传输、三种消息发布服务质量以及小型传输开销小等,这些特点使得MQTT在物联网、小型设备、移动应用等领域有广泛应用。 # 举例(温湿度传感器——AHT10) - **1、添加板载AHT21软件包** ![screenshot_pkq7wX8.md.png](https://oss-club.rt-thread.org/uploads/20240730/01a8b12be1c65a5d88959070224b7d85.png.webp) -**2、开启I2C,并关联AHT10** -**3、注册云平台(选用阿里云)** -**4、env配置** 开启片上外设 ![screenshot_pkLQuXn.md.png](https://oss-club.rt-thread.org/uploads/20240730/41baa5ab1d20e9473f9d1cc87f42b7d2.png.webp) 配置DFS ![screenshot_pkLQDAK.md.png](https://oss-club.rt-thread.org/uploads/20240730/55a4bd8cafb335303c0dc9448e27f76e.png.webp) 提高至4096 ![screenshot_pkLQ2jA.md.png](https://oss-club.rt-thread.org/uploads/20240730/5d40b7b742ea8c920d447935f1d01ab6.png.webp) - 1 ```c //温湿度采集 #define LOG_TAG "app_aht21" #define LOG_LVL LOG_LVL_DBG static float humidity, temperature; static aht10_device_t dev; static int count; static const char *i2c_bus_name = "i2c3"; static void thread1_entry(void *p) //创建线程 { while (1) { /* 读取湿度 */ humidity = aht10_read_humidity(dev); rt_kprintf("Humidity: %.2f%%\n", humidity); write_data_to_file(temperature, humidity); /* 读取温度 */ temperature = aht10_read_temperature(dev); rt_kprintf("Temperature: %.2fC\n", temperature); write_data_to_file(temperature, humidity); } } static int aht10_example(void *p) { dev = aht10_init(i2c_bus_name); if (!test_dev) { LOG_I("test_dev create failed\n"); } // 创建线程 rtthread_t thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, 1024, 25, 10); if(!thread1) LOG_I("thread1 create failed"); else return RT_Eok; rt_thread_startup(thread1); rt_delay(100); return 0; } ``` - 2 ```c static void example_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) { iotx_mqtt_topic_info_t *topic_info = (iotx_mqtt_topic_info_pt) msg->msg; switch (msg->event_type) { case IOTX_MQTT_EVENT_PUBLISH_RECEIVED: EXAMPLE_TRACE("Message Arrived:"); EXAMPLE_TRACE("Topic : %.*s", topic_info->topic_len, topic_info->ptopic); EXAMPLE_TRACE("Payload: %.*s", topic_info->payload_len, topic_info->payload); EXAMPLE_TRACE("\n"); break; default: break; } } static int example_subscribe(void *handle) { int res = 0; const char *fmt = "/%s/%s/user/get"; char *topic = NULL; int topic_len = 0; topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1; topic = HAL_Malloc(topic_len); if (topic == NULL) { EXAMPLE_TRACE("memory not enough"); return -1; } memset(topic, 0, topic_len); HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME); res = IOT_MQTT_Subscribe(handle, topic, IOTX_MQTT_QOS0, example_message_arrive, NULL); if (res < 0) { EXAMPLE_TRACE("subscribe failed"); HAL_Free(topic); return -1; } HAL_Free(topic); return 0; } static void example_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) { EXAMPLE_TRACE("msg->event_type : %d", msg->event_type); } static int example_publish(void *handle) // 向Topic主题发布属性函数 { int res = 0; // 定义一个整型变量res,用于存储函数执行的结果,初始化为0 // 定义一个指向常量字符的指针,该常量字符是一个包含温度占位符的JSON字符串 const char *ALI_TOPIC_TLS_POST_payload = "{\"params\" : { \"temperature\":%.3lf } }"; // 定义几个变量用于存储主题名称和消息体的相关信息 char *topic = NULL; // 主题名称 int topic_len = 0; // 主题名称的长度 int payload_len = 0; // 消息体的长度 char *payload = NULL; // 消息体的内容 // 计算消息体需要的长度(包括JSON字符串的长度和额外空间) payload_len = strlen(ALI_TOPIC_TLS_POST_payload) + 4; // +4可能是为了安全起见,确保有足够的空间(考虑小数点、千分位和字符串结束符) // 分配内存给消息体 payload = HAL_Malloc(payload_len); if (payload == NULL) { // 如果内存分配失败 EXAMPLE_TRACE("memory not enough"); // 打印错误信息 return -1; // 返回-1表示失败 } memset(payload, 0, payload_len); // 将分配的内存初始化为0 // 这里有一个问题:temp变量在使用前需要被定义和初始化,但在给出的代码片段中没有看到 // 假设temp是一个已经定义并初始化的double类型变量,包含当前的温度值 HAL_Snprintf(payload, payload_len, ALI_TOPIC_TLS_POST_payload, temp); // 将温度值格式化到消息体中 temp = temp + 0.1; // 更新温度值(这在实际使用中可能不是最佳实践,因为它改变了外部状态) // 跳过了一个未使用的湿度更新注释 // 计算主题名称的长度(由固定字符串和动态的产品密钥及设备名称组成) topic_len = strlen(ALI_TOPIC_TLS_POST) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1; // 分配内存给主题名称 topic = HAL_Malloc(topic_len); if (topic == NULL) { // 如果内存分配失败 EXAMPLE_TRACE("memory not enough"); // 打印错误信息 HAL_Free(payload); // 释放已分配的消息体内存 return -1; // 返回-1表示失败 } memset(topic, 0, topic_len); // 将分配的内存初始化为0 // 格式化主题名称字符串 HAL_Snprintf(topic, topic_len, ALI_TOPIC_TLS_POST, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME); // 向MQTT主题发布消息 res = IOT_MQTT_Publish_Simple(0, topic, IOTX_MQTT_QOS0, payload, strlen(payload)); if (res < 0) { // 如果发布失败 EXAMPLE_TRACE("publish failed, res = %d", res); // 打印错误信息 HAL_Free(topic); // 释放已分配的主题名称内存 HAL_Free(payload); // 释放已分配的消息体内存 return -1; // 返回-1表示失败 } // 释放已分配的主题名称和消息体内存 HAL_Free(topic); HAL_Free(payload); return 0; // 返回0表示成功 } ``` - 3 ```c static int mqtt_example_main(int argc, char *argv[]) { void *pclient = NULL; int res = 0; iotx_mqtt_param_t mqtt_params; HAL_GetProductKey(DEMO_PRODUCT_KEY); HAL_GetDeviceName(DEMO_DEVICE_NAME); HAL_GetDeviceSecret(DEMO_DEVICE_SECRET); EXAMPLE_TRACE("mqtt example"); //清零操作 memset(&mqtt_params, 0x0, sizeof(mqtt_params)); mqtt_params.read_buf_size = 1024; mqtt_params.handle_event.h_fp = example_event_handle; pclient = IOT_MQTT_Construct(&mqtt_params); if (NULL == pclient) { EXAMPLE_TRACE("MQTT construct failed"); return -1; } pclient = IOT_MQTT_Construct(&mqtt_params); if (NULL == pclient) { EXAMPLE_TRACE("MQTT construct failed"); return -1; } while(1) { if(0 == count%20000) example_publish(pclient); count++; } IOT_MQTT_Yield(pclient, 200); rt_thread_delay(1000); } static int mqtt_entry(void) //创建mqtt线程 { rtthread_t thread = rt_thread_create("mqtt_entry", mqtt_example_main, RT_NULL, 4096, 14, 10); if (!thread) rt_thread_startup(thread1); return 0; } ```
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
留矽兮
这家伙很懒,什么也没写!
文章
4
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部