谷动谷力

 找回密码
 立即注册
查看: 2218|回复: 0
收起左侧

【RT-Thread】AT组件源代码解析

[复制链接]
发表于 2022-3-21 18:47:09 | 显示全部楼层 |阅读模式
【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 x
AT组件的核心处理逻辑是将收到的 AT 模组的应答信息放到一个环形缓冲区中,然后从这个环形缓冲区中每次读一行数据("rn")进行处理,然后判断属于哪一类的消息,调用不同的函数。/ y) c( o) i# C8 m$ X! ^9 s
本文以 EC200x 模组为例,详细分析了 AT 组件的实现过程和代码的调用逻辑,帮助在使用 AT 组件过程中遇到问题的开发者快速定位问题出现的位置。
+ ]6 \( C4 f0 `5 F
640?wx_fmt=png.jpg

1 、AT 组件

640?wx_fmt=png.jpg 640?wx_fmt=png.jpg 640?wx_fmt=png.jpg
* 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
    21
    1.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。各种情况的执行结果分析如下所示
    640?wx_fmt=png.jpg
    ; 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
  • 回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|深圳市光明谷科技有限公司|光明谷商城|Sunshine Silicon Corpporation ( 粤ICP备14060730号|Sitemap

    GMT+8, 2024-3-28 17:19 , Processed in 0.115414 second(s), 37 queries .

    Powered by Discuz! X3.2 Licensed

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表