嵌入式系统分层设计和函数表抽象硬件差异应用
/ 扫描Wi-Fi。// 获取ICCID。
1. 头文件与核心结构定义
#ifndef __NET_H
#define __NET_H
#include "stdint.h"
#include "time.h"
// 状态码定义
#define NET_OK 0
#define NET_ERROR 1
// 设备控制命令类型
#define NET_CONTROL_DEVICE_TYPE 0x20 // 设备类型识别
#define NET_CONTROL_CFG_PORCESS 0x21 // 配置数据处理接口
// Wi-Fi扫描结果结构体
struct net_wifi_data{
char mac[18]; // MAC地址
int rssi; // 信号强度
};
struct net_wifi{
uint8_t cnt; // 扫描到的Wi-Fi数量
struct net_wifi_data wifi[5]; // 最多存储5个Wi-Fi信息
};
// 基站信息结构体
struct net_bts{
uint8_t cnt; // 基站数量
char bts[3][30]; // 最多3个基站信息(字符串格式)
};
// 网络数据处理接口抽象
struct net_process{
uint32_t (*recv)(uint8_t **buf); // 接收数据回调
uint32_t (*send)(uint8_t *buf, uint32_t len); // 发送数据回调
void (*process)(uint32_t tick); // 周期性数据处理回调
};
// AT指令接口函数声明
uint8_t net_ate0(void);
uint8_t net_at(void);
uint8_t net_at_cgsn(char *imei); // 获取IMEI
uint8_t net_at_cimi(char *imsi); // 获取IMSI
uint8_t net_at_csq(uint8_t *csq); // 获取信号强度
uint8_t net_at_iccid(uint8_t *iccid); // 获取ICCID
uint8_t net_at_wifi(struct net_wifi *wifi); // 扫描Wi-Fi
uint8_t net_at_bts(struct net_bts *bts); // 获取基站信息
uint8_t net_at_sleep(void); // 进入低功耗模式
uint8_t net_at_sleep_wakeup(void); // 唤醒设备
#endif
2. 设备驱动实现(UMA503模块)
// UMA503设备私有数据结构
struct dev_net_uma503{
struct uma503_cfg uma503_cfg; // 硬件配置参数
struct net_process *process; // 数据处理接口
struct net_func net_func; // AT指令实现函数表
struct net_socket_func net_socket_func; // 套接字实现函数表
};
// UMA503设备实例初始化
static struct dev_net_uma503 dev = {
.net_func = {
// 绑定AT指令具体实现函数
.net_at_header = uma503_at_header,
.net_at_cgsn_header = uma503_at_cgsn_header, // IMEI获取
.net_at_cimi_header = uma503_at_cimi_header, // IMSI获取
// ... 其他AT指令实现
},
.net_socket_func = {
// 绑定套接字操作实现函数
.net_socket_init = uma503_socket_init,
.net_socket_ip_init = uma503_socket_ip_init,
// ... 其他套接字操作
},
};
// 设备初始化函数
rt_err_t dev_uma503_init(rt_device_t dev) {
struct dev_net_uma503 *p = (struct dev_net_uma503 *)dev->user_data;
// 绑定数据收发接口
p->uma503_cfg.recv = p->process->recv;
p->uma503_cfg.send = p->process->send;
// 初始化硬件
ret = uma503_init(&p->uma503_cfg);
// 注册AT指令和套接字接口到全局
net_register_func(&p->net_func);
net_socket_register_func(&p->net_socket_func);
return ret;
}
// RT-Thread设备操作函数(简化示例)
rt_err_t dev_uma503_control(rt_device_t dev, int cmd, void *args) {
struct dev_net_uma503 *p = dev->user_data;
switch (cmd) {
case NET_CONTROL_DEVICE_TYPE:
// 设备类型识别(通过字符串匹配)
if(rt_strstr(str, "UMA503") != RT_NULL) ret = RT_EOK;
break;
case NET_CONTROL_CFG_PORCESS:
// 绑定数据处理回调
p->process = (struct net_process *)args;
p->process->process = uma503_at_process; // 绑定周期处理函数
ret = RT_EOK;
break;
}
return ret;
}
// 注册设备到RT-Thread
int rt_hw_uma503_init(void) {
rt_device_register(&device, "uma503", RT_DEVICE_FLAG_RDWR);
return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_uma503_init); // 自动初始化
3. 套接字抽象层(net_socket.h)
// 套接字操作接口抽象
struct net_socket_func {
uint8_t (*net_socket_init)(void);
uint8_t (*net_socket_ip_init)(struct net_socket *socket);
// ... 其他操作(open/close/send等)
};
// 全局套接字接口指针
static struct net_socket_func *net_socket_func;
// 注册具体实现
void net_socket_register_func(struct net_socket_func *p) {
net_socket_func = p;
}
// 套接字操作代理函数(示例)
uint8_t net_socket_open(struct net_socket *socket) {
if(net_socket_func->net_socket_open == NULL)
return NET_ERROR;
return net_socket_func->net_socket_open(socket); // 调用实际实现
}
二、设计优点
1. 模块化与抽象
-
硬件抽象层(HAL):
通过struct net_func
和struct net_socket_func
将AT指令和套接字操作抽象为函数表,使上层代码与具体硬件解耦。例如,更换4G模块时只需实现新的函数表,无需修改业务逻辑。 -
统一接口:
所有网络操作(如net_at_cgsn
)和套接字操作(如net_socket_open
)通过代理函数调用,接口统一且易于维护。
2. 可扩展性
-
动态注册机制:
通过net_register_func
和net_socket_register_func
动态绑定实现,支持多硬件兼容(如同时支持UMA503和SIM7600模块)。 -
命令扩展性:
dev_uma503_control
通过cmd
参数支持未来新增控制命令(如配置网络频段)。
3. 与RT-Thread深度集成
-
设备驱动框架:
符合RT-Thread的设备驱动模型(rt_device
),支持自动初始化(INIT_DEVICE_EXPORT
),便于集成到RT-Thread生态。 -
线程安全:
隐含依赖RT-Thread的线程调度和同步机制(如信号量),但代码中未显式处理,需结合RT-Thread内核特性。
4. 防御性编程
-
空指针检查:
所有代理函数(如net_at_cgsn
)均检查函数指针是否为NULL
,避免未注册实现时崩溃。
四、总结
代码亮点
-
高度模块化:通过函数表抽象硬件差异,符合嵌入式系统分层设计思想。
-
灵活扩展:动态注册机制支持多硬件、多协议扩展。
-
与RT-Thread无缝集成:利用RT-Thread设备框架简化驱动开发。
更多推荐
所有评论(0)