rtthread-nano AT组件管理Air724
cAir724ug 网卡管理
air720_device_class_register
AT 设备类注册
-> Air724 socket 类注册,注册socket数量与socket 操作函数
-> 注册AT设备类到设备链表
air720_device_register
AT设备注册(air720_device_register )
-> 根据设备类型查找设备类(at_device_class_get)
-> 为设备SOCKET 对象分配空间
-> 模组初始化(device-> ops - >init-)
1. 初始化AT客户端,创建AT指令解析线程 at_client_init 2. 设置URC TABLE 3. 将网卡设备添加到netdev网卡链表 4. 网卡开机
at_device_register /* AT设备注册 */
|-> class = at_device_class_get(class_id) /* 模组ID唯一 */
|-> class->device_ops->init(device) /* AT设备操作函数初始化模组 */
|-> air720_init /* 注意操作函数在air720_device_class_register注册到设备链表*/
|-> air720->power_status = RT_FALSE; /* default power is off. */
|-> air720->sleep_status = RT_FALSE; /* default sleep is disabled. */
|-> at_client_init /* components/net/at/src/at_client.c */
|-> at_client_para_init /* components/net/at/src/at_client.c */
|-> rt_thread_create(client_parser) /* 线程名字为"at_clnt0",创建AT解析线程 components/net/at/src/at_client.c */
|-> client_parser /* AT解析线程的具体实现 components/net/at/src/at_client.c */
|-> rt_device_find /* 寻找串口设备 rt-thread/src/device.c */
|-> rt_device_open /* 打开串口设备 rt-thread/src/device.c */
|-> rt_thread_startup(client->parser) /* rt-thread/src/thread.c */
|-> air720_socket_init /* 增加socket相关的URC*/
|-> air720_netdev_add("air720") /* 设置AIR724网卡相关信息与操作函数,注册网卡到链表 */
|-> netdev_get_by_name("air720") /* rt-thread/components/net/netdev/src/netdev.c */
|-> netdev->ops = &air720_netdev_ops; /* 网络设备操作集 */
|-> sal_at_netdev_set_pf_info /* 设置AT网络接口设备协议簇信息 */
|-> netdev_register /* rt-thread/components/net/netdev/src/netdev.c */
|-> netdev->status_callback = RT_NULL; /* rt-thread/components/net/netdev/src/netdev.c */
|-> netdev->addr_callback = RT_NULL; /* rt-thread/components/net/netdev/src/netdev.c */
|-> air720->power_pin
|-> air720->power_status_pin
|-> air720->wakeup_pin
|-> air720_netdev_set_up /* 网卡开机,注册网络 */
|-> at_device_get_by_name /* packages/at_device-v2.0.4/src/at_device.c */
|-> air720_net_init /* 网络初始化,附着网络 */
|-> rt_thread_create(air720_init_thread_entry) /* 线程名字为"air720_net_init",执行各种AT指令初始化网络 */
|-> rt_thread_startup(air720_init_thread_entry) /* 启动网络初始化线程 */
|-> air720_power_on
|-> ATE0 [disable echo] -> ATI [get module version] -> AT+CPIN? [check SIM card] -> AT+CREG? [check the GSM network is registered] -> AT+CGREG? [check the GPRS network is registered] -> AT+CSQ [check signal strength]
-> AT+CGATT? -> AT+CIPSHUT -> AT+CIPMUX=1 [multiple connections] -> AT+CIPQSEND=1 [fast send mode] -> AT+CSTT
-> AT+CIICR -> AT+CIFSR
|-> netdev_low_level_set_status /* rt-thread/components/net/netdev/src/netdev.c */
/* Air724网络初始化线程 */
air720_init_thread_entry /* packages/at_device-v2.0.4/class/air/at_device_ec200x.c */
|-> air720_power_on
|-> at_obj_exec_cmd() /* 发送各种AT指令初始化EC200x rt-thread/components/net/at/src/at_client.c */
|-> ec200x_netdev_set_info
|-> at_device_get_by_name /* packages/at_device-v2.0.4/src/at_device.c */
|-> netdev_low_level_set_status /* rt-thread/components/net/netdev/src/netdev.c */
|-> netdev->flags |= NETDEV_FLAG_LINK_UP; /* 网络设备的状态改为连接 */
|-> netdev_low_level_set_link_status /* rt-thread/components/net/netdev/src/netdev.c */
|-> netdev_low_level_set_dhcp_status /* rt-thread/components/net/netdev/src/netdev.c */
|-> netdev_low_level_set_ipaddr /* 设置本地的IP地址 rt-thread/components/net/netdev/src/netdev.c */
|-> netdev_low_level_set_dns_server /* 设置DNS服务器 rt-thread/components/net/netdev/src/netdev.c */
|-> air720_netdev_check_link_status /* 创建链路检测线程*/
|-> rt_thread_create(check_link_status_entry) /* 线程名字为"air724_link",创建网络连接状态检查线程 */
|-> rt_thread_startup(check_link_status_entry)
check_link_status_entry
|-> at_obj_exec_cmd("AT+CGREG?") /* 发送AT指令检查网络状态 */
|-> at_obj_exec_cmd("AT+CSQ?") /* 发送AT指令检查信号状态 */
|-> netdev_low_level_set_link_status /* rt-thread/components/net/netdev/src/netdev.c */
整个网卡注册流程共建立如下三个线程
线程1: client_parser 解析AT指令,处理URC 数据
线程2: air720_init_thread_entry 模组开机,搜寻网络并初始化
线程3: check_link_status_entry 一直轮询设备状态
AT client 对象信息
struct at_client
{
rt_device_t device;
at_status_t status;
char end_sign;
/* the current received one line data buffer */
char *recv_line_buf;
/* The length of the currently received one line data */
rt_size_t recv_line_len;
/* The maximum supported receive data length */
rt_size_t recv_bufsz;
rt_sem_t rx_notice;
rt_mutex_t lock;
at_response_t resp;
rt_sem_t resp_notice;
at_resp_status_t resp_status;
struct at_urc_table *urc_table;
rt_size_t urc_table_size;
rt_thread_t parser;
};
AT Socket
struct at_socket
{
/* AT socket magic word */
uint32_t magic;
int socket;
/* device releated information for the socket */
void *device;
/* type of the AT socket (TCP, UDP or RAW) */
enum at_socket_type type;
/* current state of the AT socket */
enum at_socket_state state;
/* sockets operations */
const struct at_socket_ops *ops;
/* receive semaphore, received data release semaphore */
rt_sem_t recv_notice;
rt_mutex_t recv_lock;
rt_slist_t recvpkt_list;
/* timeout to wait for send or received data in milliseconds */
int32_t recv_timeout;
int32_t send_timeout;
/* A callback function that is informed about events for this AT socket */
at_socket_callback callback;
/* number of times data was received, set by event_callback() */
uint16_t rcvevent;
/* number of times data was ACKed (free send buffer), set by event_callback() */
uint16_t sendevent;
/* error happened for this socket, set by event_callback() */
uint16_t errevent;
#ifdef SAL_USING_POSIX
rt_wqueue_t wait_head;
#endif
rt_slist_t list;
/* user-specific data */
void *user_data;
};
/* AT socket operations function */
struct at_socket_ops
{
int (*at_connect)(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client);
int (*at_closesocket)(struct at_socket *socket);
int (*at_send)(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type);
int (*at_domain_resolve)(const char *name, char ip[16]);
void (*at_set_event_cb)(at_socket_evt_t event, at_evt_cb_t cb);
};
AT device class
struct at_device_class
{
uint16_t class_id; /* AT device class ID */
const struct at_device_ops *device_ops; /* AT device operaiotns */
#ifdef AT_USING_SOCKET
uint32_t socket_num; /* The maximum number of sockets support */
const struct at_socket_ops *socket_ops; /* AT device socket operations */
#endif
rt_slist_t list; /* AT device class list */
};
Netdev
/* network interface device object */
struct netdev
{
rt_slist_t list;
char name[RT_NAME_MAX]; /* network interface device name */
ip_addr_t ip_addr; /* IP address */
ip_addr_t netmask; /* subnet mask */
ip_addr_t gw; /* gateway */
#if NETDEV_IPV6
ip_addr_t ip6_addr[NETDEV_IPV6_NUM_ADDRESSES]; /* array of IPv6 addresses */
#endif /* NETDEV_IPV6 */
ip_addr_t dns_servers[NETDEV_DNS_SERVERS_NUM]; /* DNS server */
uint8_t hwaddr_len; /* hardware address length */
uint8_t hwaddr[NETDEV_HWADDR_MAX_LEN]; /* hardware address */
uint16_t flags; /* network interface device status flag */
uint16_t mtu; /* maximum transfer unit (in bytes) */
const struct netdev_ops *ops; /* network interface device operations */
netdev_callback_fn status_callback; /* network interface device flags change callback */
netdev_callback_fn addr_callback; /* network interface device address information change callback */
#ifdef RT_USING_SAL
void *sal_user_data; /* user-specific data for SAL */
#endif /* RT_USING_SAL */
void *user_data; /* user-specific data */
};
/* The network interface device operations */
struct netdev_ops
{
/* set network interface device hardware status operations */
int (*set_up)(struct netdev *netdev);
int (*set_down)(struct netdev *netdev);
/* set network interface device address information operations */
int (*set_addr_info)(struct netdev *netdev, ip_addr_t *ip_addr, ip_addr_t *netmask, ip_addr_t *gw);
int (*set_dns_server)(struct netdev *netdev, uint8_t dns_num, ip_addr_t *dns_server);
int (*set_dhcp)(struct netdev *netdev, rt_bool_t is_enabled);
#ifdef RT_USING_FINSH
/* set network interface device common network interface device operations */
int (*ping)(struct netdev *netdev, const char *host, size_t data_len, uint32_t timeout, struct netdev_ping_resp *ping_resp);
void (*netstat)(struct netdev *netdev);
#endif
/* set default network interface device in current network stack*/
int (*set_default)(struct netdev *netdev);
};
**AT device **
struct at_device
{
char name[RT_NAME_MAX]; /* AT device name */
rt_bool_t is_init; /* AT device initialization completed */
struct at_device_class *class; /* AT device class object */
struct at_client *client; /* AT Client object for AT device */
struct netdev *netdev; /* Network interface device for AT device */
#ifdef AT_USING_SOCKET
rt_event_t socket_event; /* AT device socket event */
struct at_socket *sockets; /* AT device sockets list */
#endif
rt_slist_t list; /* AT device list */
void *user_data; /* User-specific data */
};
/* AT device operations */
struct at_device_ops
{
int (*init)(struct at_device *device);
int (*deinit)(struct at_device *device);
int (*control)(struct at_device *device, int cmd, void *arg);
};