外设服务 Periph Service¶
小技巧
如果图片看不清楚。你可以 在图片上点击鼠标右键 –> 在新标签页中打开图片 ,然后你可以放大、缩小、移动图片。
概述¶
外设服务 Periph Servcie,是为 OTA Service、Input Key Servcie 等 外设子服务 提供一个框架 —— 前者是父类,后者是子类。
但是当前的代码实现,后者实现时并没有完全覆盖(或继承)前者的方法 —— 用户有些 API 需要调用后者的,有些 API 仍然需要调用前者的。
大致的原则:优先调用外设子服务的API;否则调用外设服务的API(这时需要注意外设子服务是如何实现的)。
类图¶
我们用类图的形式,描述外设服务 Periph Servcie 的实现(实际上代码是用 C 语言实现的):
private data 部分,是结构体
periph_service_impl_t
的主要字段。public method 部分,是 Periph Servcie 的提供的 API 函数。这些函数的实现大部分都很简单:
periph_service_create()
的实现略微复杂一点,看这里 API 。periph_service_destroy()
执行回调函数.service_destroy
。periph_service_start()
执行回调函数.service_start
。periph_service_stop()
执行回调函数.service_stop
。periph_service_ioctl()
执行回调函数.service_ioctl
。periph_service_set_callback()
设置回调函数.callback_func
及 上下文user_cb_ctx
。periph_service_callback()
执行回调函数.callback_func
。periph_service_set_data()
设置变量.user_data
。实际上大部分时候都是在periph_service_create()
里设置.user_data
。 此函数可能有缺陷 。periph_service_get_data()
获取变量.user_data
。
序列图¶
对像说明:
- xxx_app.c: 某个用户程序
- xxx_service.c: 某个外设子服务
- xxx_service_task(): 外设子服务的内部任务
- periph_service.c:外设服务
流程说明:
- xxx_app.c 调用某个外设子服务
xxx_service_create()
。少数处设子服务(Wi-Fi Service)会将事件处理回调函数作为参数的字段传入。 - xxx_service.c 调用
periph_service_create()
, 并会将.service_destroy
,.service_start
,.service_stop
,.service_ioctl
, 等回调函数作为参数的字段传入。 同时也会将自已的地址,作为.user_data
参数字段传入。 若外设子服务需要创建内部任务,则会将内部任务函数作为.task_func
参数字段传。 - periph_service.c 将上述回调函数和
.user_data
保存下来。若.task_func
不为空(实际上是.task_stack > 0
),则创建内部任务。 - xxx_app.c 调用其它函数,设置外设子服务参数。
- 若有需要,xxx_app.c 调用
periph_service_set_callback()
设置事件回调函数.callback_func
(Wi-Fi Service 由 wifi_service.c调用)。 periph_service_set_data()
此函数有缺陷,且实际上没有调用过。
- xxx_app.c 调用
periph_service_start()
。 - 若
.service_start
不为空,则会被执行。
- 内部任务 xxx_service_task() 收到外部事件。
- 内部任务 xxx_service_task() 调用
periph_service_callback()
。 - 若
.callback_func
不为空, 则会被执行。
- xxx_app.c 调用
periph_service_stop()
。 - 若
.service_stop
不为空,则会被执行。
xxx_app.c 调用
xxx_service_destory()
, 销毁某个外设子服务。xxx_service.c 中止内部任务 xxx_service_task() 。
xxx_service.c 调用
periph_service_destroy()
。Wi-Fi Servcie 与 Display Service 是 40,41,42 流程。
xxx_app.c 调用
periph_service_destroy()
, 销毁某个外设子服务。若
.service_destroy
不为空, 则会被 periph_service.c 调用。xxx_service.c 中止内部任务 xxx_service_task() 。
Input Key Service 与 OTA Service 是 50, 51, 52 流程。
注解
上述流程只表示一般做法。各外设子服务的实现,并不完全与上述流程保持一致。
API¶
periph_service_create()
periph_service_destroy()
periph_service_start()
periph_service_stop()
periph_service_ioctl()
periph_service_set_callback()
periph_service_callback()
periph_service_set_data()
periph_service_get_data()
与外设子服务的映射¶
完全映射¶
同时包括了 回调函数映射 与 API映射 。
说明:
黑色粗体与紫色粗体文字 :用户可调用的 API 函数。
无调用 :提供了API, 但在 ESP_ADF 中没有调用过。
内部API,用户不可调用 :供外设子服务调用的API。
空函数:内部实现为空,或基本为空。
.task_func
: 这不是 callback, 只是periph_service_create()
的参数的一个字段。若这个字段非空,则会创建一个外设子服务的内部任务。periph_service_set_data()
:没有任何地方调用。实际上也 不能被调用 ,该函数修改的.user_data
字段,在periph_service_create()
中已经被赋值了。periph_service_get_data()
:为各外设子服务提供的内部 API,用户不应该调用。wifi_service_destroy()
:调用这个函数可能会 出现异常 。wifi_service_create()
调用periph_service_create()
时,把wifi_service_destroy()
作为参数字段.service_destory
传递给后者了。按通用的作法periph_service_destroy()
中会调用回调函数.service_destory
,即wifi_service_destroy()
。但wifi_service_destroy()
的实现中,又会调用periph_service_destroy()
。幸运的是,没有地方调用
wifi_service_destroy()
,Wi-Fi Service 的periph_service_destroy()
方法,好像也没有地方调用。你可以自已修订这个bug: 把
.service_destroy = wifi_service_destroy,
修改为.service_destroy = NULL,
” 。