|
【RT-Thread】AT组件源代码解析[url=]RTThread物联网操作系统[/url] 2022-03-21 18:33+ E5 Z! W Y+ b. X
收录于话题##论坛精选#[color=rgba(0, 0, 0, 0.5)]4个
7 h& H7 `, h$ N; p* ~1 xAT组件的核心处理逻辑是将收到的 AT 模组的应答信息放到一个环形缓冲区中,然后从这个环形缓冲区中每次读一行数据("rn")进行处理,然后判断属于哪一类的消息,调用不同的函数。/ y) c( o) i# C8 m$ X! ^9 s
本文以 EC200x 模组为例,详细分析了 AT 组件的实现过程和代码的调用逻辑,帮助在使用 AT 组件过程中遇到问题的开发者快速定位问题出现的位置。 + ]6 \( C4 f0 `5 F
1 、AT 组件
* E2 j; @! a9 M `4 f1.1 AT 组件调试信息级别设置# Y/ H u/ U- J& s
可以通过修改 env 中的如下内容来控制是否启用 AT 组件的 debug log 功能,开启后可以看到日志级别为 debug 的相关日志。使能该选项后将在 rtconfig.h 中生成 #define AT_DEBUG,AT 组件日志级别的控制是在 rt-thread/components/net/at/include/at_log.h 文件中实现的 1RT-Thread Components
' Q4 m6 X/ |$ H4 a2 -> Network# [$ }$ d1 {0 P2 R; V+ L" B
3 -> AT commands
, p, q) Q: F" d0 b4 -> Enable debug log output /* 选中表示修改日志级别为 debug */* z9 J; K8 L' B6 B: G) E' r1 q, K
/ [% B: Y! H, w特别注意:打开上述功能后,ec200x 线程(在 packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c 文件中由 ec200x_netdev_check_link_status() 函数创建)会提示栈溢出,使用的栈空间约为 1598Bytes,建议将 ec200x_netdev_check_link_status() 函数中的 EC200X_LINK_THREAD_STACK_SIZE 宏更改为 1024 +1024 即 2048 个字节,以解决栈溢出的问题。 1.2 AT 命令打印使能设置在调试时可以通过修改 env 中的如下内容来控制是否使能 AT 组件的收发 AT 指令的显示,开启后可以看到每次执行的 AT 指令以及返回的执行结果。 1RT-Thread Components& ^0 d3 D/ Z- w9 s) z, M1 {
2 -> Network
. n2 q) z/ a0 q) g. }3 -> AT commands+ w* h5 [" A# g; f) g
4 -> Enable print RAW format AT command communication data /* 选中表示打印执行的AT指令 */
$ E. T; }" j& r9 `* }. j9 n. h7 i- D! p/ U5 `
上述选项选中后,在执行测试时,打印的 AT 指令示例如下 1[D/AT] recvline: 0000-0020: 41 54 0D 0D 0A AT...% g F& f( G7 l$ W2 Q l$ ]
2[D/AT] recvline: 0000-0020: 4F 4B 0D 0A OK..4 W/ U7 y$ K' Z- w, o H
3[D/AT] sendline: 0000-0020: 41 54 45 30 ATE0
4 }( D* p" O7 N9 A4 U1 g% _7 t" C 4[D/AT] recvline: 0000-0020: 41 54 45 30 0D 0D 0A ATE0...! n) G( R- u% k! U
5[D/AT] recvline: 0000-0020: 4F 4B 0D 0A OK..
2 M U; U6 h1 Y" ]! F# S# h 6[D/AT] sendline: 0000-0020: 41 54 2B 49 50 52 3F AT+IPR?* E7 j0 [+ ~: W& Y+ b+ ?+ a
701-01 00:40:19 D/at.clnt: execute command (AT+IPR?) timeout (300 ticks)!* f1 {6 {2 G2 B
8[D/AT] recvline: 0000-0020: 0D 0A ... J" l: G6 Z0 {' y- N
9[D/AT] recvline: 0000-0020: 2B 49 50 52 3A 20 31 31 35 32 30 30 0D 0A +IPR: 115200..% _& n1 S# {4 r
10[D/AT] recvline: 0000-0020: 0D 0A ..- j& L. j- g+ |4 b; P# n9 s
11[D/AT] recvline: 0000-0020: 4F 4B 0D 0A OK..+ L5 }) J) I3 u @) P% i
12[D/AT] recvline: 0000-0020: 0D 0A ..
- {$ @; s, a$ f1 f13[D/AT] recvline: 0000-0020: 52 44 59 0D 0A RDY..) Q* M' \9 t5 |' W3 u1 x& Z7 T
1401-01 00:40:22 I/at.dev.ec200x: ec200x device initialize retry...8 ]: l& S, \# v! y; S1 H
15[D/AT] sendline: 0000-0020: 41 54 45 30 ATE08 C, C) V, o- ~- X6 V4 }) Y Y* e4 J
1601-01 00:40:24 D/at.clnt: execute command (ATE0) timeout (300 ticks)!6 u+ {7 t4 I; Q% z( I
17[D/AT] recvline: 0000-0020: 0D 0A ..
( R$ e" @! z+ R5 X' R+ Q+ n18[D/AT] recvline: 0000-0020: 4F 4B 0D 0A OK..
" _+ e0 ?1 M( P+ o( @19[D/AT] recvline: 0000-0020: 0D 0A ..
" A" v; l" T; Y+ m20[D/AT] recvline: 0000-0020: 4F 4B 0D 0A OK..$ c0 l: t* ?( L$ @( N. r, j
211.3 GPRS 网络注册状态检查AT组件中会自动创建一个 GPRS 网络注册状态检查的线程,使用 "AT+CGREG?" 指令进行 GPRS 网络注册状态的检查,并根据指令返回的结果修改网卡设备的标志位,该指令返回结果中的 <stat> 等于 1 或者 5,表示模块已在 UMTS/LTE 网络注册上 PS 业务。, s5 l- l+ P8 Q
GPRS 网络注册状态检查线程的名字是模拟网卡的名字,在本例中为 "ec200x",线程的入口函数是 ec200x_check_link_status_entry(packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c),该线程没间隔 60s 发送一条 AT 指令进行 GPRS 网络注册状态的检查,并根据返回的结果在函数 netdev_low_level_set_link_status 中修改 netdev->flags。各种情况的执行结果分析如下所示 ; F" ?: e; @2 \
特别注意:GPRS 网络注册状态检查线程会检查模组的 power_status,power_status 在 ec200x_init() 函数中默认初始化为 RT_FALSE,然后在名为 "ec200x_net" 的线程的 ec200x_init_thread_entry() 线程入口函数中调用 ec200x_power_on() 函数来修改 power_status 的值。ec200x_power_on() 函数中 power_status 的值修改为 RT_TRUE 依赖于 power_pin 引脚的定义,因此在 env 中必须定义 power_pin 的编号,默认为 -1,定义规则在文件 drivers/drv_gpio.c 中。另外还需要注意的是在代码中 power_pin 为低电平表示模组处于上电状态,power_pin 为高电平表示模组处于断电状态。 power_pin 编号的定义在禁用网卡(netdev_set_down)与启用网卡(netdev_set_up)的实现中也至关重要,网卡的禁用与启用最终实际调用的函数为 ec200x_power_off() 和 ec200x_power_on(),因此必须定义power_pin 的编号,网卡禁用与启用的示例代码如下 1/* "ec200x" 名字来源于设备注册时使用的名字,在文件 packages/at_device-v2.0.4/samples/at_sample_ec200x.c 中定义 */9 [0 U* T4 U0 C7 g0 g: Y: U0 c+ d5 [
2struct at_device * dev = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, "ec200x");/* 根据名字查找 AT 设备 */6 J0 m6 Y0 P( v$ [- W3 R9 u4 I
3
, S% Z, ] D. H6 S0 P4netdev_set_up(dev->netdev); /* 启用相应的网卡设备 */
. i4 z5 v s! f3 h8 b% W n5netdev_set_down(dev->netdev); /* 禁用相应的网卡设备 */
9 f. e7 f' @. s5 d* m9 }1.4 EC200x 是否能连接外网日志输出- C! w( A9 F( S4 k/ n5 s
rt-thread/components/net/sal_socket/src/sal_socket.c 中 check_netdev_internet_up_work() 函数会自动连接 "link.rt-thread.org" 的 8101 端口进行数据收发测试,从而判断是否可以连接外网。该文件中默认的打印级别为 DBG_INFO,为了方便看出是否可以连接外网,将 check_netdev_internet_up_work() 函数结尾的部分的测试结果打印由 LOG_D 修改为 LOG_I。 该函数的执行的过程大致为在 ec200x 初始化线程 ec200x_init_thread_entry() 中将将外网检查任务提交到 sys_work 工作队列中,系统工作队列处理线程 _workqueue_thread_entry() 会不断的检测是否有需要运行的任务,如果有则执行相应的任务,即执行外网连接检查任务。 外网连接检查任务提交到工作队列的执行过程如下 1ec200x_init_thread_entry /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
' V5 M9 x) B3 Y% _ 2 |-> ec200x_power_on /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
1 b3 L2 u& }- ^3 W( W N 3 |-> at_obj_exec_cmd() /* 发送各种AT指令初始化EC200x rt-thread/components/net/at/src/at_client.c */
7 k7 b" Z: s% @+ A& q8 C 4 |-> ec200x_netdev_set_info /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
' ?! Q! v) S7 g$ S# _4 R 5 |-> at_device_get_by_name /* packages/at_device-v2.0.4/src/at_device.c */
7 o) @4 ~! z+ f; [ 6 |-> netdev_low_level_set_status /* rt-thread/components/net/netdev/src/netdev.c */
" o+ b+ U6 m. n: Y# `( X, L 7 |-> netdev->flags |= NETDEV_FLAG_LINK_UP; /* 网络设备的状态改为连接 */- f- H. R8 Y7 G8 Q
8 |-> netdev_low_level_set_link_status /* rt-thread/components/net/netdev/src/netdev.c */ \" u4 v9 s% Z7 v
9 |-> netdev_low_level_set_dhcp_status /* rt-thread/components/net/netdev/src/netdev.c */
' @% @, Z1 i4 _0 q2 m. {10 |-> netdev_low_level_set_ipaddr /* 设置本地的IP地址 rt-thread/components/net/netdev/src/netdev.c */) [3 S0 D. t; n8 z" h) i
11 |-> sal_check_netdev_internet_up /* rt-thread/components/net/sal_socket/src/sal_socket.c */
; {- l+ ~3 g$ o4 ?% C12 |-> rt_delayed_work_init(net_work, check_netdev_internet_up_work) /* 初始化外网连接检查任务 rt-thread/components/drivers/src/workqueue.c *// `" q8 a; [/ t. N
13 |-> (&work->work)->work_func = check_netdev_internet_up_work/ B3 E; [$ k4 ]7 F
14 |-> rt_work_submit(&(net_work->work), RT_TICK_PER_SECOND); /* rt-thread/components/drivers/src/workqueue.c */9 ]1 P- w4 ?' j
15 |-> rt_workqueue_submit_work(sys_workq, work, time) /* 将任务提交到系统工作队列里面 rt-thread/components/drivers/src/workqueue.c */
! l8 n _2 h1 B+ p& s16 |-> netdev_low_level_set_dns_server /* 设置DNS服务器 rt-thread/components/net/netdev/src/netdev.c */
% K; g0 _3 p$ k3 E0 B0 L" g2 r17 |-> ec200x_netdev_check_link_status /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */- P @3 M5 O3 M& \6 V; ]9 b
18 |-> rt_thread_create(ec200x_check_link_status_entry) /* 线程名字为"ec200x",创建 GPRS 网络注册状态检查线程 packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */8 F5 Q1 S9 @; t8 s8 Z+ s1 {( e
19 |-> rt_thread_startup(ec200x_check_link_status_entry) /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
! R1 e) y6 e& ?5 }20
0 d3 {4 v: [+ N# G- g- O21/* GPRS 网络注册状态检查线程 */
) K; ? B3 `" l* q) m3 w4 V; T7 M22ec200x_check_link_status_entry /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
0 l" k7 L0 v0 A" m- Z7 j3 F8 O23 |-> ec200x_check_link_status /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */ & l- D5 [& `7 J9 v
24 |-> at_obj_exec_cmd("AT+CGREG?") /* 发送AT指令检查网络状态 */
; Z' B9 h7 @+ j25 |-> netdev_low_level_set_link_status /* rt-thread/components/net/netdev/src/netdev.c */. p5 t$ p" b9 M9 J" v
5 T! h( L! T1 C; u. L; o1 A系统工作队列初始化和任务执行过程如下 1rt_work_sys_workqueue_init /* rt-thread/components/drivers/src/workqueue.c */6 M2 W) ?0 \/ F- M) }( S* L* X3 D
2 |-> rt_workqueue_create("sys_work") /* 创建系统工作队列 rt-thread/components/drivers/src/workqueue.c */1 ]/ X0 u2 T J; }7 r. O
3 |-> rt_thread_create(_workqueue_thread_entry) /* 线程名字为"sys_work",创建队列线程 rt-thread/components/drivers/src/workqueue.c */
6 J8 G# }' O) C 4) T3 S. [# g3 N/ m1 S: r, B2 j
5_workqueue_thread_entry /* 系统工作队列处理线程 rt-thread/components/drivers/src/workqueue.c */
: y6 Z9 ?/ D, C3 k1 K+ E8 q- x 6 |-> if(rt_list_isempty)
- W* s8 j% h' @) W8 B! |( W 7 |-> rt_thread_suspend(rt_thread_self()); /* 挂起自身 */# N9 H+ n1 O- }3 k
8 |-> rt_schedule(); /* 任务列表为空,挂起自身,切换线程 */' `* j5 t9 y1 E/ C" D0 e( L
9 |-> rt_hw_interrupt_disable /* 任务列表不为空,依次往下执行,关闭中断 */ E- U9 K( d) O, b6 V. U1 t
10 |-> rt_list_entry /* 找到要处理的任务节点 */
4 m# b% \1 K7 R11 |-> rt_list_remove /* 将找到的任务节点从任务列表中移除 */
8 |) u( |1 a: V7 _& _" C0 }% n# k# O12 |-> rt_hw_interrupt_enable /* 使能中断 */+ m ?/ h( \- E
13 |-> work->work_func(work, work->work_data); /* 执行任务 */; C3 X3 ]& W9 W8 p
j- }% y% \8 N
外网连接检查任务的执行过程如下 1check_netdev_internet_up_work /* 外网连接检查任务 rt-thread/components/net/sal_socket/src/sal_socket.c *// e# f* K# S+ Q2 ^( Q# C" R
2 |-> 与 "link.rt-thread.org" 的 8101 端口建立连接,进行收发数据测试
3 a" c! H5 s/ I% s3 |-> 打印测试结果
2 N" | Z& [$ _) Z$ M4 |-> 收发测试成功 LOG_I("Set network interface device(%s) internet status up.", netdev->name);
/ a5 D5 u: ?( t# q5 |-> netdev->flags |= NETDEV_FLAG_INTERNET_UP;, @+ x0 k$ @) P9 f5 l; w7 o
6 |-> 收发测试失败 LOG_I("Set network interface device(%s) internet status down.", netdev->name);
. G8 ]$ J" l) K4 { n& a0 O! C* r7 |-> netdev->flags &= ~NETDEV_FLAG_INTERNET_UP;1.5 AT 设备注册过程 1at_device_register /* packages/at_device-v2.0.4/samples/at_sample_ec200x.c */+ P3 x* X+ L1 _3 _; U; X
2 |-> class = at_device_class_get(class_id) /* packages/at_device-v2.0.4/src/at_device.c */
( h* M& M/ \6 }6 l 3 |-> class->device_ops->init(device) /* packages/at_device-v2.0.4/src/at_device.c */
" Y) ?9 ^' C9 s+ v4 c$ M 4 |-> ec200x_init /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
* A% J5 P2 q' G. m7 v6 U 5 |-> ec200x->power_status = RT_FALSE; /* default power is off. packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
) n! j' n) |& b4 J& A8 K 6 |-> ec200x->sleep_status = RT_FALSE; /* default sleep is disabled. packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
) v7 T! U, T' I8 d& e: ^ 7 |-> at_client_init /* components/net/at/src/at_client.c */8 @) E% J7 l- U! t! `
8 |-> at_client_para_init /* components/net/at/src/at_client.c */
2 K0 w) | {+ M; e- O8 T! H5 ? 9 |-> rt_thread_create(client_parser) /* 线程名字为"at_clnt0",创建AT解析线程 components/net/at/src/at_client.c */
) s( c0 X. Q0 `9 |10 |-> client_parser /* AT解析线程的具体实现 components/net/at/src/at_client.c */
* I9 C7 C' ?" B, D- ^11 |-> rt_device_find /* 寻找串口设备 rt-thread/src/device.c */
# f. q% K; u$ \6 p/ ?6 W12 |-> rt_device_open /* 打开串口设备 rt-thread/src/device.c */
+ X7 e; H3 y+ d4 E5 G) I9 \13 |-> rt_thread_startup(client->parser) /* rt-thread/src/thread.c */# ]' U+ E9 Y& ]$ ^9 p
14 |-> ec200x_socket_init /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */
8 } {, r o- o& c& R3 t15 |-> ec200x_netdev_add("ec200x") /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
: a1 Y* ^6 z0 D& L1 T16 |-> netdev_get_by_name("ec200x") /* rt-thread/components/net/netdev/src/netdev.c */
5 ~9 }- O- H4 N17 |-> netdev->ops = &ec200x_netdev_ops; /* 网络设备操作集 packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
5 r5 m* m+ A: U$ D+ v% k+ ^% A18 |-> sal_at_netdev_set_pf_info /* rt-thread/components/net/sal_socket/impl/af_inet_at.c */% U% U' C, V" |9 a1 w4 b+ Y
19 |-> netdev_register /* rt-thread/components/net/netdev/src/netdev.c */
& J R x1 \( ?) n4 `# Z( ~7 V( R20 |-> netdev->status_callback = RT_NULL; /* rt-thread/components/net/netdev/src/netdev.c */
1 O& D% x7 \& V4 ]21 |-> netdev->addr_callback = RT_NULL; /* rt-thread/components/net/netdev/src/netdev.c */
. `$ X4 l1 R$ c5 v. ^22 |-> ec200x->power_pin /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
1 e% \/ e9 ~- `( H23 |-> ec200x->power_status_pin /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
& ?# Y2 x6 z ~9 Q24 |-> ec200x->wakeup_pin /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */) F1 [" ~5 L+ }3 K' W! {( P, t
25 |-> ec200x_netdev_set_up /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */! ?& X4 Y- _5 z0 t0 C4 M; r$ l4 T
26 |-> at_device_get_by_name /* packages/at_device-v2.0.4/src/at_device.c */
5 o2 R+ J- I( ]( P. G; |6 e$ V$ b27 |-> ec200x_net_init /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
" O# V/ Y t2 Z5 ~28 |-> rt_thread_create(ec200x_init_thread_entry) /* 线程名字为"ec200x_net",执行各种AT指令初始化网络 packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */0 m5 a3 I' m' o5 V
29 |-> rt_thread_startup(ec200x_init_thread_entry) /* 启动网络初始化线程 packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
9 H, ?* n" W, e& P1 A7 |, R' |30 |-> netdev_low_level_set_status /* rt-thread/components/net/netdev/src/netdev.c */6 a0 F+ w: e+ `2 T9 f X) v2 A
1.6 AT 设备类注册过程1ec200x_device_class_register /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */: O" r3 _: U" F- v
2 |-> ec200x_socket_class_register /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */5 }: \5 ^6 |& {: w" F" j
3 |-> class->socket_num = AT_DEVICE_EC200X_SOCKETS_NUM; /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */
3 g6 d0 f% m; H4 |-> class->socket_ops = &ec200x_socket_ops; /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */8 V1 d# n& E1 C# K( Q7 g# p/ A* F
5 |-> class->device_ops = &ec200x_device_ops; /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */. }- Y% h1 y9 W, G$ R; h
6 |-> at_device_class_register " |& t, j+ s& ^( W2 F
7/* packages/at_device-v2.0.4/src/at_device.c */
S. V- ^( t. J# f& V
' a8 X8 M% W. } @1.7 网卡的启用与禁用1.7.1 启用网卡的执行过程 1/* 启用网卡 */
3 u* s: x K7 }" [( A4 y 2netdev_set_up(netdev) /* components/net/netdev/src/netdev.c */5 T( l, {; P% H% q
3 |-> netdev->ops->set_up(netdev) /* netdev->ops = &ec200x_netdev_ops; packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
0 U. F5 ?# a. b# ? 4 |-> ec200x_netdev_set_up ------------------------------| /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
( `; Q- e/ d- K* b' \0 b& W* z* x) z9 b 5 |-> ec200x_net_init | /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
# G4 }8 ?" |) M0 l9 H+ J; V" I( d 6 |-> ec200x_init_thread_entry | /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */" o& G/ D) t! {
7 |& c: d" x, r5 r* _
8/* module init */ |/ p8 ]6 ]) D7 z) W1 x( c
9ec200x_init | /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
. I: }* ^5 `; S7 Q- s6 h4 G10 |-> at_client_init | /* components/net/at/src/at_client.c *// X. Y1 O& }1 l& v3 P4 ]
11 |-> ec200x_socket_init | /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */+ M/ U( b0 f$ C7 B. h# O9 `/ G' R
12 |-> ec200x_netdev_add | /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */8 ^" `6 D" c5 h2 z- K7 m5 j
13 |-> netdev_register | /* rt-thread/components/net/netdev/src/netdev.c */
' C. t+ `# F" F v( C14 |-> ec200x_netdev_set_up ----------------------------------| /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */' G/ v$ ^$ S- s. f
15 |-> ec200x_net_init /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */6 g$ W) Y5 W2 S9 T& T
16 |-> ec200x_init_thread_entry /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */2 y0 f: U' k/ u) }0 ~2 |
1.7.2 禁用网卡的执行过程 1/* 禁用网卡 */
q. ]# \* e0 y2 T& D 2netdev_set_down(netdev) /* components/net/netdev/src/netdev.c *// e! r G# L( V" i) H/ J) C
3 |-> netdev->ops->set_down(netdev); /* components/net/netdev/src/netdev.c */$ d& N/ G4 I8 i0 y7 C
4 |-> ec200x_netdev_set_down ----------------------------| /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
8 X. G, J0 l% E: D 5 |-> ec200x_power_off | /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */$ j1 ^% H. C8 Q* d
6 |-> netdev_low_level_set_status(netdev, RT_FALSE) | /* rt-thread/components/net/netdev/src/netdev.c */% H5 X: p! B1 C- U, j
7 |-> netdev->flags &= ~NETDEV_FLAG_UP | /* rt-thread/components/net/netdev/src/netdev.c */
) v0 T, P6 q1 [0 v& A: W% `+ R, Z 8 |-> netdev_auto_change_default | /* rt-thread/components/net/netdev/src/netdev.c */
?/ A1 {5 G; A$ R7 k4 | 9 |
+ n1 [8 s1 C9 [& b; N1 j9 F! {$ J/ U2 ^10/* module deinit */ |# L: X$ Q+ r; ?1 s+ o
11ec200x_deinit | /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */
" i# ~2 ]; u' @/ ]/ w5 k12 |-> ec200x_netdev_set_down --------------------------------| /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c */- F* ?# r. q, B
13 |-> ec200x_power_off /* packages/at_device-v2.0.4/class/ec200x/at_device_ec200x.c *// E M' X: L' [. \3 t! r
* y+ o6 Y3 ~4 Y+ g$ \
1.8 socket 编程源码分析1.8.1 socket 执行过程 1#define socket(domain, type, protocol) sal_socket(domain, type, protocol) /* rt-thread/components/net/sal_socket/include/socket/sys_socket/sys/socket.h */
1 |3 i+ u/ t7 O4 ^4 I8 ^/ F5 ` 2 |-> sal_socket /* rt-thread/components/net/sal_socket/src/sal_socket.c */
3 l$ M. S# `7 R 3 |-> socket_new /* rt-thread/components/net/sal_socket/src/sal_socket.c */
# @6 l3 U; D0 b h* O 4 |-> socket_alloc /* rt-thread/components/net/sal_socket/src/sal_socket.c */
! x. p$ _% s) n; d, K: h1 G0 d 5 |-> sock = st->sockets[idx]; /* rt-thread/components/net/sal_socket/src/sal_socket.c */& F @- X" z( B! f
6 |-> sock->socket = idx + SAL_SOCKET_OFFSET; /* rt-thread/components/net/sal_socket/src/sal_socket.c */
# e. M/ l& a* P2 @5 q8 d8 X 7 |-> sock->magic = SAL_SOCKET_MAGIC; /* rt-thread/components/net/sal_socket/src/sal_socket.c */
) G0 s3 H" J A W- p 8 |-> sock->netdev = RT_NULL; /* rt-thread/components/net/sal_socket/src/sal_socket.c */
4 d2 `' ?2 |6 n% {; D1 [ 9 |-> sock->user_data = RT_NULL; /* rt-thread/components/net/sal_socket/src/sal_socket.c */4 f1 b, _* N p3 {# M; u' T
10 |-> sal_get_socket /* rt-thread/components/net/sal_socket/src/sal_socket.c */8 b# y: T* I9 y
11 |-> socket_init /* rt-thread/components/net/sal_socket/src/sal_socket.c */4 c' }6 |$ `4 s! C
12 |-> sock->netdev = netdev; /* rt-thread/components/net/sal_socket/src/sal_socket.c */, e9 O Z9 j1 m! E: N$ H
13 |-> SAL_NETDEV_SOCKETOPS_VALID /* rt-thread/components/net/sal_socket/src/sal_socket.c */
1 h3 M6 c/ t6 L0 b14 |-> pf->skt_ops->socket /* rt-thread/components/net/sal_socket/src/sal_socket.c */& U+ l& A, I! b# z1 ^
15 |-> at_socket /* rt-thread/components/net/at/at_socket/at_socket.c */
4 @# Y# V. [- \( Y4 H0 H16 |-> alloc_socket /* rt-thread/components/net/at/at_socket/at_socket.c */
: Z) p# U) P& n' R$ g17 |-> sock->type = socket_type; /* rt-thread/components/net/at/at_socket/at_socket.c */
" F6 @* o$ w! L- w0 N- ^18 |-> sock->state = AT_SOCKET_OPEN; /* rt-thread/components/net/at/at_socket/at_socket.c */
' T, ?8 ` U _2 [19 |-> sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); /* 设置接收回调函数 rt-thread/components/net/at/at_socket/at_socket.c */
" ^/ p) a9 x0 @& C6 z20 |-> ec200x_socket_set_event_cb /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */
: E. |& W% U7 T% e9 m. A21 |-> at_evt_cb_set[event] = cb; /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */1 ]- m5 k- M! P; A' p. R! u- q
22 |-> sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); /* 设置关闭套接字回调函数 rt-thread/components/net/at/at_socket/at_socket.c */& C J2 w9 h: b1 }$ @
23 |-> ec200x_socket_set_event_cb /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */: c4 Y8 G0 I" B
24 |-> at_evt_cb_set[event] = cb; /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */# r v$ `9 _' m; w3 j
1.8.2 connect 函数执行过程 1#define connect(s, name, namelen) sal_connect(s, name, namelen) /* rt-thread/components/net/sal_socket/include/socket/sys_socket/sys/socket.h */6 v' I# N* v7 g8 w$ N" T Q
2 |-> sal_connect /* rt-thread/components/net/sal_socket/src/sal_socket.c */
" Z* u' ]; @8 d5 D6 u, E. _1 } 3 |-> SAL_SOCKET_OBJ_GET /* rt-thread/components/net/sal_socket/src/sal_socket.c */
* u; {+ [, j9 x9 G 4 |-> SAL_NETDEV_IS_UP /* rt-thread/components/net/sal_socket/src/sal_socket.c */
" y" M7 S6 E' ^ j+ @% M6 Q 5 |-> SAL_NETDEV_SOCKETOPS_VALID /* rt-thread/components/net/sal_socket/src/sal_socket.c */
1 l- z# C; v" A 6 |-> pf->skt_ops->connect /* rt-thread/components/net/sal_socket/src/sal_socket.c */
- x% ~- V5 c' G* E 7 |-> at_connect /* rt-thread/components/net/at/at_socket/at_socket.c */
8 `* F0 `8 C5 ~7 g 8 |-> at_get_socket /* rt-thread/components/net/at/at_socket/at_socket.c */
" }( B' F' Z: d2 U) p 9 |-> sock->ops->at_connect /* rt-thread/components/net/at/at_socket/at_socket.c *// V2 X- I; {: c( P+ X, _0 l
10 |-> ec200x_socket_connect /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */
( d3 J' O6 {0 @- v1.8.3 send 函数执行过程 1#define send(s, dataptr, size, flags) sal_sendto(s, dataptr, size, flags, NULL, NULL) /* rt-thread/components/net/sal_socket/include/socket/sys_socket/sys/socket.h */2 Q, H X1 H* K% [5 d8 t
2#define sendto(s, dataptr, size, flags, to, tolen) sal_sendto(s, dataptr, size, flags, to, tolen) /* rt-thread/components/net/sal_socket/include/socket/sys_socket/sys/socket.h */
2 K, e! g8 [ F- k. d$ q( H5 I 3 |-> sal_sendto /* rt-thread/components/net/sal_socket/src/sal_socket.c */% a* e1 S3 |: ?; b+ s2 z
4 |-> SAL_SOCKET_OBJ_GET /* rt-thread/components/net/sal_socket/src/sal_socket.c */$ g5 ~7 X/ X0 o3 F" K" k
5 |-> SAL_NETDEV_IS_UP /* rt-thread/components/net/sal_socket/src/sal_socket.c */
3 M6 k+ G- ?, M6 p) W 6 |-> SAL_NETDEV_SOCKETOPS_VALID /* rt-thread/components/net/sal_socket/src/sal_socket.c */
+ f4 I2 b, O4 V0 x' h2 t 7 |-> pf->skt_ops->sendto /* rt-thread/components/net/sal_socket/src/sal_socket.c */
/ _) V& h$ O) y4 f% A3 d& k5 \+ { 8 |-> at_sendto /* rt-thread/components/net/at/at_socket/at_socket.c */& D' Z& |' T- Z/ c6 P9 a( f
9 |-> at_get_socket /* rt-thread/components/net/at/at_socket/at_socket.c */
, V# E" j6 O. C8 T1 B10 |-> sock->ops->at_send /* rt-thread/components/net/at/at_socket/at_socket.c */
: D0 B- F7 r6 y+ j. k0 X5 X11 |-> ec200x_socket_send /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */1.8.4 recv 函数执行过程recv() 函数执行时,EC200x 接收的 URC 函数将数据放到 recvpkt_list 中,然后 recv() 函数从 recvpkt_list 中取出数据。 1#define recv(s, mem, len, flags) sal_recvfrom(s, mem, len, flags, NULL, NULL) /* rt-thread/components/net/sal_socket/include/socket/sys_socket/sys/socket.h */
; ]1 A. l6 d, n- G' I- ^ 2#define recvfrom(s, mem, len, flags, from, fromlen) sal_recvfrom(s, mem, len, flags, from, fromlen) /* rt-thread/components/net/sal_socket/include/socket/sys_socket/sys/socket.h */4 p4 ^: c, H* Q9 \, p
3 |-> sal_recvfrom /* rt-thread/components/net/sal_socket/src/sal_socket.c */7 Y5 H5 |6 r' L, f- k8 K& V
4 |-> SAL_SOCKET_OBJ_GET /* rt-thread/components/net/sal_socket/src/sal_socket.c */; J: N3 |* y/ [
5 |-> SAL_NETDEV_IS_UP /* rt-thread/components/net/sal_socket/src/sal_socket.c */
" [; p4 h q7 {/ m: I3 x# ` 6 |-> SAL_NETDEV_SOCKETOPS_VALID /* rt-thread/components/net/sal_socket/src/sal_socket.c */# G) a7 E& V' ]6 }
7 |-> pf->skt_ops->recvfrom /* rt-thread/components/net/sal_socket/src/sal_socket.c */
$ v6 I' M' B9 B( m1 E: }+ d* f8 M5 h 8 |-> at_recvfrom /* rt-thread/components/net/at/at_socket/at_socket.c */
' u9 s% E- J2 k# Y 9 |-> at_get_socket /* rt-thread/components/net/at/at_socket/at_socket.c */8 Q- I" b6 K% _& U* I4 B
10 |-> at_recvpkt_get(&(sock->recvpkt_list)...) /* 从链表中获取数据 rt-thread/components/net/at/at_socket/at_socket.c */
) N7 \! G' n5 ^ H5 h+ D7 ~11" Q# U" m6 f5 x: R, A4 z
12/* EC200x 接收的 URC 函数 */* v0 z. g+ c) C; b" X% s
13urc_recv_func /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */
- x" \' n6 g! A$ ~4 e14 |-> recv_buf = (char *) rt_calloc(1, bfsz); /* 申请空间,供 at_recv_pkt 使用,挂载在 rlist 列表中 */7 @2 \) f' I- O8 o9 x+ G
15 |-> at_client_obj_recv /* rt-thread/components/net/at/src/at_client.c */
4 [" C+ l2 G) @& A- u2 q' ~16 |-> at_client_getchar /* rt-thread/components/net/at/src/at_client.c */9 ]9 W4 b" R! N6 J9 l' w
17 |-> at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz); /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */
5 k$ F3 o0 j+ w& k) X7 M5 i18 |-> at_recv_notice_cb /* rt-thread/components/net/at/at_socket/at_socket.c */
# P" M! p4 C: J6 N; f# W' i6 i" O19 |-> at_recvpkt_put(&(sock->recvpkt_list), buff, bfsz); /* rt-thread/components/net/at/at_socket/at_socket.c */
' K+ P- V( f8 y/ N6 }) J6 R6 g20 |-> pkt->buff = (char *) ptr; /* 将buff指向之前申请到的空间 rt-thread/components/net/at/at_socket/at_socket.c */
7 A2 I4 p$ I/ B+ B2 ~- A* U6 P* S21 |-> rt_slist_append /* 挂载到链表中 */
2 ?( O* ]6 X) S- G1.8.5 closesocket 函数执行过程
, B4 ?0 ], L# r- m. V. J Y; k6 d 1#define closesocket(s) sal_closesocket(s) /* rt-thread/components/net/sal_socket/include/socket/sys_socket/sys/socket.h */
& f6 y; O4 F6 P$ o/ t 2 |-> sal_closesocket /* rt-thread/components/net/sal_socket/src/sal_socket.c */
7 C8 A6 B) u8 |4 ~ 3 |-> SAL_SOCKET_OBJ_GET /* rt-thread/components/net/sal_socket/src/sal_socket.c */1 H9 y* z/ C% t+ O) t5 V
4 |-> SAL_NETDEV_SOCKETOPS_VALID /* rt-thread/components/net/sal_socket/src/sal_socket.c */
# H5 O- b( h* G$ {2 q, T( g 5 |-> pf->skt_ops->closesocket /* rt-thread/components/net/sal_socket/src/sal_socket.c */
2 e. g) U" x( b* J' U/ d) E 6 |-> at_closesocket /* rt-thread/components/net/at/at_socket/at_socket.c */. w" A9 T4 R) T) `
7 |-> sock->ops->at_closesocket /* rt-thread/components/net/at/at_socket/at_socket.c */
; Q) ^4 P6 r0 ^9 l 8 |-> ec200x_socket_close /* packages/at_device-v2.0.4/class/ec200x/at_socket_ec200x.c */6 ]. O6 ?5 Q) P1 F8 q5 \
9 |-> free_socket /* rt-thread/components/net/at/at_socket/at_socket.c */( L. N9 Q5 C6 U+ e
10 |-> socket_delete /* rt-thread/components/net/sal_socket/src/sal_socket.c */% H' |4 Q% s( t
11 |-> sock = sal_get_socket(socket); /* rt-thread/components/net/sal_socket/src/sal_socket.c */" {+ }% ?/ j1 d" p& {
12 |-> sock->magic = 0; /* rt-thread/components/net/sal_socket/src/sal_socket.c */9 M& _5 J, |/ ~/ ?
13 |-> sock->netdev = RT_NULL; /* rt-thread/components/net/sal_socket/src/sal_socket.c */# X" G" a1 {9 y+ s( `1 ?+ Z0 W. o2 T
14 |-> socket_free /* rt-thread/components/net/sal_socket/src/sal_socket.c */
! J& @: a$ p8 C9 D15 |-> rt_free(sock); /* rt-thread/src/memheap.c */5 W, \1 | S% r8 g5 D0 _" U
16 |-> rt_memheap_free /* rt-thread/src/memheap.c */
. d3 o# U0 E S( J! z1 H
4 x6 |) V( a4 {, {* \
1 `: T2 \7 V2 X9 f
4 A8 F9 c1 l* y |
|