RT_THREAD之组件学习
CmBacktrace (Cortex Microcontroller Backtrace)是一款针对 ARM Cortex-M 系列 MCU 的错误代码自动追踪、定位,错误原因自动分析的开源库。支持裸机、ucos rh-thread,freertos.适配 Cortex-M0/M3/M4/M7 MCU;支持中英文输出。
ulog:与开源easy log很像,可将程序运行过程中的一些状态信息分标签、级别输出到不同的后端(控制台、文件、网络),逐步取代RTT早期的elog/rt_dbg。资源占用小(ROM<1K, RAM<0.2K),分同步模式(为避免影响线程只能输出到控制台)、异步模式(支持在中断、hardfault下使用(CmBacktrace已经做了适配),需要bug和专门的日志处理线程),用用好主要是注意日志的标签、级别、过滤。
#define LOG_E(...) ulog_e(LOG_TAG, __VA_ARGS__) #define LOG_W(...) ulog_w(LOG_TAG, __VA_ARGS__) #define LOG_I(...) ulog_i(LOG_TAG, __VA_ARGS__) #define LOG_D(...) ulog_d(LOG_TAG, __VA_ARGS__) #define LOG_RAW(...) ulog_raw(__VA_ARGS__) #define LOG_HEX(name, width, buf, size) ulog_hex(name, width, buf, size)
utest简介
utest的初衷是方便RT-Thread开发者使用统一的框架接口编写测试程序,实现单元测试,覆盖测试以及集成测试的目的,utest测试框架依赖ULOG模块日志进行日志输出,utest的断言宏uassert 仅记录通过和失败的数量,不会产生断言并终止程序运行。其功能不等同于 RT_ASSERT。
GSM/GPRS等模组一般都通过AT命令通讯,RTT的AT组件对客户端(也支持多客户端)和服务器都可适配,除了发送命令,解析返回数据(第几行,关键字),还能处理URC数据(自己设计URC数据表:收到的前缀,前缀匹配后的响应函数)
DFS:设备的虚拟文件系统,以文件夹为容器,以文件为单位的抽象数据类型。可实现了数据的存储、分级组织、访问和获取等操作。
-
FatFS 是专为小型嵌入式设备开发的一个兼容微软 FAT(文件名都大写,最多8个字符,后缀最多3个) 格式的文件系统,采用 ANSI C 编写,具有良好的硬件无关性以及可移植性,是 RT-Thread 中最常用的文件系统类型。
-
传统型的 RomFS 文件系统是一种简单的、紧凑的、只读的文件系统,不支持动态擦写保存,按顺序存放数据,因而支持应用程序以 XIP(execute In Place,片内运行) 方式运行,在系统运行时, 节省 RAM 空间。
-
Jffs2 文件系统是一种日志闪存文件系统。主要用于 NOR 型闪存,基于 MTD 驱动层,特点是:可读写的、支持数据压缩的、基于哈希表的日志型文件系统,并提供了崩溃 / 掉电安全保护,提供写平衡支持等。
-
DevFS 即设备文件系统,在 RT-Thread 操作系统中开启该功能后,可以将系统中的设备在 /dev 文件夹下虚拟成文件,使得设备可以按照文件的操作方式使用 read、write 等接口进行操作。
-
NFS 网络文件系统(Network File System)是一项在不同机器、不同操作系统之间通过网络共享文件的技术。在操作系统的开发调试阶段,可以利用该技术在主机上建立基于 NFS 的根文件系统,挂载到嵌入式设备上,可以很方便地修改根文件系统的内容。
-
UFFS 是 Ultra-low-cost Flash File System(超低功耗的闪存文件系统)的简称。它是国人开发的、专为嵌入式设备等小内存环境中使用 Nand Flash 的开源文件系统。与嵌入式中常使用的 Yaffs 文件系统相比具有资源占用少、启动速度快、免费等优势。
只有块设备才可以挂在文件系统,所以需要在指定的外设(SPI/SD)上创块设备。然后格式化文件系统dfs_mkfs()(特定的文件系统),然后挂载文件系统(int dfs_mount(),即)将一个存储设备挂接到一个已存在的路径上(我们对该路径上的文件进行操作))。用完后卸载文件系统dfs_unmount。
文件的常用操作:以/为根路径,以fd文件操作符为基本单位,进行文件的open()打开/创建、读、写、添加、查找、重命名、关闭,同步文件到存储设备int fsync(int fildes)等操作。
目录的操作:创建mkdir、打开opendir、读取opendir、关闭closedir。
文件系统操作常用的 FinSH 命令如下表所示:
FinSH 命令 | 描述 |
---|---|
ls | 显示文件和目录的信息 |
cd | 进入指定目录 |
cp | 复制文件 |
rm | 删除文件或目录 |
mv | 将文件移动位置或改名 |
echo | 将指定内容写入指定文件,当文件存在时,就写入该文件,当文件不存在时就新创建一个文件并写入 |
cat | 展示文件的内容 |
pwd | 打印出当前目录地址 |
mkdir | 创建文件夹 |
mkfs | 格式化文件系统 |
注意:
RT-Thread/FatFs 默认使用 437 编码(美国英语)。如果需要存储中文文件名,可以使用 936 编码(GBK编码)。936 编码需要一个大约 180KB 的字库
NetDev:即网络接口设备,又称网卡,主要作用是解决设备多网卡连接时网络连接问题(比如同时有网口和4G,设定网口为缺省,4G备用),用于统一管理各个网卡信息与网络连接状态,并且提供统一的网卡调试命令接口,RT-Thread 系统中目前支持三种协议栈类型: lwIP 协议栈、AT Socket 协议栈、WIZnet TCP/IP硬件协议栈.网卡的统一操作接口
- up/down: 底层网卡初始化完成之后置为 up 状态,用于判断网卡开启还是禁用。
- link_up/link_down: 用于判断网卡设备是否具有有效的链路连接,连接后可以与其他网络设备进行通信。该状态一般由网卡底层驱动设置。
- internet_up/internet_down: 用于判断设备是否连接到因特网,接入后可以与外网设备进行通信。
- dhcp_enable/dhcp_disable: 用于判断当前网卡设备是否开启 DHCP 功能支持。
统一的调试接口:ping、ifconfig(设置 IP地址、网关和子网掩码时应确保dhcp_disable)、netstat、dns 等命令
SAL:RT-Thread 系统提供了一套 SAL(套接字抽象层)组件,该组件完成对不同网络协议栈或网络实现接口的抽象并对上层提供一组标准的 BSD Socket API.SAL在netDev之上。TLS(Transport Layer Security,传输层安全协议从SSL发展而来) 是建立在传输层 TCP 协议之上的协议,目前常用的 TLS 的实现方式:MbedTLS、OpenSSL、s2n
/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ host = gethostbyname(SAL_TLS_HOST); * 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */ sock = socket(AF_INET, SOCK_STREAM, ROTOCOL_TLS); /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SAL_TLS_PORT); server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 初始化预连接的服务端地址 */ connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); /* 发送数据到 socket 连接 */ ret = send(sock, send_data, strlen(send_data), 0); /* 接收并打印响应的数据,使用加密数据传输 */ bytes_received = recv(sock, recv_data, SAL_TLS_BUFSZ - 1, 0);
//绑定套接字(bind) int bind(int s, const struct sockaddr *name, socklen_t namelen); //监听套接字(listen) int listen(int s, int backlog); //接收连接(accept) int accept(int s, struct sockaddr *addr, socklen_t *addrlen); //建立连接(connect) int connect(int s, const struct sockaddr *name, socklen_t namelen); //TCP 数据发送(send) int send(int s, const void *dataptr, size_t size, int flags); //UDP 数据发送(sendto) int sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); //UDP 数据接收(recvfrom) int recvfrom(int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); //关闭套接字(closesocket) int closesocket(int s); //获取远端地址信息(getpeername) int getpeername(int s, struct sockaddr *name, socklen_t *namelen); //获取本地地址信息(getsockname) int getsockname(int s, struct sockaddr *name, socklen_t *namelen); //配置套接字参数(ioctlsocket) int ioctlsocket(int s, long cmd, void *arg); //获取套接字选项(getsockopt) int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); //设置套接字选项(setsockopt) int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); //关闭套接字(closesocket) int closesocket(int s);
低功耗的通常策略:主控时钟频率的调整、工作电压的改变、总线频率的调整甚至关闭、外围设备工作时钟的关闭,外设电源的关闭,单片机的低功耗模式与唤醒(时钟频率、工作模式),需要注意的是进入低功耗模式时有2个问题:1是os_tick的补偿,以内进入低功耗模式后系统时钟停止,此时要切换低功耗定时器(RTC)计算出唤醒时间或者其它中断的唤醒源,并在唤醒后对os_tick进行补偿;2对于低功耗敏感的功能模式要考虑进出低功耗模式时的状态保持、恢复、和状态改变相关的(如周期延时的时基改变,串口的波特率改变)这些通过注册PM设备,设置挂起和恢复时的回调函数。
硬件上:IO控制关闭模块电源。
软件上:
- CPU的工作模式,不同模式下CPU的频率不同,外设(时钟)关闭
- LWTIME/LWUART低功耗外设的特性
- 唤醒