首页>>电子报>>电子报热点
详细内容

从接口定义和实现两个方面,深入理解AWbus-lite(一)

       在使用AWBus-lite对设备进行管理时,无论设备处于 AWBus-lite拓扑结构中的哪个位置,只要其能够提供某种标准服务,就可以使用相应的通用接口对其进行操作。本文将从接口的定义和实现两个方面,深入理解AWbus-lite工作的原理。
       在基于AWBus-lite总线拓扑结构的设备管理框架中,无论一个设备处于AWBus-lite总线拓扑结构中的哪个位置,只要其能够提供某种标准服务,就可以使用相应的通用接口对其进行访问。那么,这究竟是怎样实现的呢?本文将深入探讨AWBus-lite,为您揭开AWBus-lite的神秘面纱,使您对AWBus-lite有更加深入的了解,在具有这些足够的了解后,你将有能力独立开发一些设备的驱动,当后续遇到一些AWorks暂不支持的设备时,可以自行开发设备相应的驱动。
1 通用接口的定义
       合理的接口应该是简洁的、易阅读的、职责明确的,为了便于维护,通用接口由广州致远电子有限公司进行统一的定义,用户通常不需要自行定义通用接口。目前,常用的功能都已经被标准化,定义了相应的通用接口。
       作为一种了解,下面以LED为例,从接口的命名、参数和返回值三个方面阐述在AWorks中定义接口的一般方法。
1.1 接口命名
       在AWorks中,所有通用接口均以“aw_”开头,紧接着是操作对象的名字,对于LED控制接口来说,所有接口都应该以“aw_led_”作为前缀。
       在接口的前缀定义好之后,应该考虑需要定义哪些功能性接口,然后根据功能完善接口名。对于LED来说,核心的操作是控制LED的状态,点亮或熄灭LED,为此,可以定义一个设置(set)LED状态的函数,比如:“aw_led_set”。
       使用该接口可以设置LED的状态,显然,为了区分是点亮还是熄灭LED,需要通过一个额外的参数来指定具体的操作。
       每次开灯或关灯都需要传递额外的参数给aw_led_set()接口,显得比较繁琐。为了简化操作,可以为常用的开灯和关灯操作定义专用的接口,这样就不需要额外的参数来对开灯和关灯操作进行具体的区分了。比如,使用on和off分别表示开灯和关灯,则可以定义开灯的接口名为:“aw_led_on”,关灯的接口名为“aw_led_off”。
       在一些特殊的应用场合中,比如,LED闪烁,用户可能并不关心具体的操作是开灯还是关灯,它仅仅需要LED的状态发生翻转。此时,可以定义一个用于翻转(toggle)LED状态的专用接口,比如:“aw_led_toggle”
1.2 接口参数
       在AWorks中,通用接口的第一个参数往往用于表示要操作的具体对象。显然,在一个系统中,可能存在多个LED,为了区分各个LED,可以为每个LED分配一个唯一编号,即ID号。ID号是一个从0开始的整数,例如,系统中有两个LED,则编号分别为0、1。基于此,为了指定要操作的具体LED,通用接口的第一个参数可以设定为int类型的id。
       对于aw_led_set接口,其除了使用id确定需要控制的LED外,还需要使用一个参数来区分是点亮LED还是熄灭LED,这是一个二选一的操作,对应参数的类型可以使用布尔类型: aw_bool_t。当值为真(AW_TRUE)时,则点亮LED;当值为假(AW_FALSE)时,则熄灭LED。基于此,可以定义aw_led_set()接口的原型为(还未定义返回值):
aw_led_set(intid,aw_bool_ton);
       对于aw_led_on、aw_led_off和aw_led_toggle接口来说,它们的职责单一,仅仅需要指定控制的LED,即可完成点亮、熄灭或翻转操作,无需其它额外的参数。对于这类接口,参数仅仅需要id,这些接口的原型可以定义如下(还未定义返回值):
aw_led_on(intid);
aw_led_off(intid);
aw_led_toggle(intid);
1.3 返回值
       对于用户来说,调用通用接口后,应该可以获取到本次执行的结果,是执行成功还是执行失败,或是一些其它的有用信息。比如,在调用接口时,如果指定的id超过了有效范围,由于没有与无效id对应的LED设备,操作必定会失败,此时必须返回通过返回值告知用户操作失败,且操作失败的原因是id不在有效范围内,无与之对应的LED设备。
       在AWorks中,接口通常返回一个aw_err_t类型的返回值来表示接口执行的结果,返回值的含义已被标准化:若返回值为AW_OK,则表示操作成功;若返回值为负数,则表示操作失败,此时,用户可根据具体的返回值,查找aw_errno.h文件中定义的宏,根据宏的含义确定失败的原因;若返回值为正数,其含义与具体接口相关,由具体接口定义,无特殊说明则表示不会返回正数。AW_OK是在aw_common.h文件中定义的宏,其定义如下:
#defineAW_OK 0
       错误号在aw_errno.h文件中定义。比如,在调用LED通用接口时,若id不在有效范围内,则该id没有对应的LED设备,此时接口应该返回-AW_ENODEV。注意:AW_ENODEV的前面有一个负号,以表示负值。
       基于此,将所有LED通用接口的返回值类型定义为aw_err_t,LED控制接口的完整定义详见表1,其对应的类图详见图1。
表1 LED通用接口(aw_led.h)
36-6-4_看图王.jpg

36-6-5_看图王.jpg

图1 LED接口类图
       这些接口都已经在aw_led.h文件中完成了定义,无需用户再自行定义。上述从接口命名、参数和返回值三个方面详细阐述了一套接口定义的方法,旨在让用户了解接口的由来,加深对接口的理解。实际中,定义接口并不是一件容易的事情,需要尽可能考虑到所有的情况,接口作为与用户交互的途径,一旦定义完成,如非必要,都应该避免再对接口进行修改。否则,所有依赖于该接口的应用程序都将受到影响。因此,当前并不建议用户自定义通用接口,通用接口的定义应由广州致远电子有限公司统一规划、定义、维护和管理。
2 接口的实现
       作为一种范例,下面以实现LED接口为例,详细介绍AWorks中实现接口的一般方法。
2.1 实现接口初探
       在AWorks中,硬件设备和驱动统一由AWBus-lite进行管理,因此,对于LED这一类硬件设备,其实现是属于AWBus-lite的一部分。LED有4个通用接口函数,其中的aw_led_on()和aw_led_off()接口可以直接基于aw_led_set()接口实现,详见程序清单1。
       程序清单1 aw_led_on()和aw_led_off()接口的实现
1 aw_err_t aw_led_on(intid)
2 {
3  retumaw_led_set(id,AW_TRUE);
4 }
5
6 aw_err_t aw_led_off(intid)
7 {
8  retumaw_led_set(id,AW_FALSE);
9 }
       实现接口的核心是实现aw_led_set()和aw_led_toggle()这两个接口。对于不同的底层硬件设备,LED实际控制方式是不同的,比如,最常见的,通过GPIO直接控制一个LED,简单范例详见程序清单2。
程序清单2 aw_led_set()的实(GPIO控制LED)
1 static const int g_led_pins[]={PIO2_6,PIO2_5};
2 int aw_led_set(intid,aw_bool_t on)
3 {
4  if(id>sizeof(g_led_pins)/sizeof(g_led_pins[0])){
5  retum-AW_ENODEV; //无此ID对应的LED
6  }
7  aw_gpio_set(g_led_pins[id],!on);//假定GPIO输出低电平点亮LED
8  retum AW_OK;
9 }
       也有可能是通过串口控制一个LED设备。例如,通过发送字符串命令控制LED的状态,命令格式为:set <id> <on>,其中,id为LED编号,on为设置LED的状态,要点亮LED0,则发送字符串:"set 0 1"。这种情况下,aw_led_set()的实现范例详见程序清单3。
程序清单3 aw_led_set()的实现(UART控制LED)
1 int aw_led_set(intid,aw_bool_t on)
2 {
3  char buf[15];
4  aw_snpnintf(buf,15,"set%d%d",id,on);
5  aw_serial_write(COM1,buf,strlen(buf));
6  retum AW_OK;
7 }
       总之,底层硬件设备是多种多样的,不同类型的LED设备对应的控制方式也会不同。
       定义通用接口的目的在于屏蔽底层硬件的差异性,即无论底层硬件如何变化,用户都可以使用通用接口控制LED。显然,如果直接类似程序清单2和程序清单3这样实现一个通用接口,那么随着LED设备种类的增加,同一个接口的实现代码将有越来越多不同的版本。
       在一个应用程序中,一个接口不能同时具有多种不同的实现,因此,这样的做法有着非常明显的缺点:多个不同种类的LED设备不能在一个应用中共存,更换硬件设备,就必须更换通用接口的实现,使用何种设备就加入相应设备的控制代码进行编译。 例如,系统中有几个直接通过GPIO控制的LED,同时也存在几个通过UART控制的LED,那么,类似程序清单2和程序清单3这样直接实现通用接口的方法,就无法组织代码了,因为不可能同时将程序清单2和程序清单3所示的代码加入工程编译。显然,需要更好的办法来解决这个问题。
2.2 LED抽象方法
       在使用几种控制方式不同的LED硬件设备时,虽然它们对应的aw_led_set()和aw_led_toggle()接口的具体实现方法并不相同,但它们要实现的功能却是一样的,这是它们的共性:均要实现设置LED状态和翻转LED状态的功能。由于一个接口的实现代码只能有一份,因此,这些功能的实现不能直接作为通用接口的实现代码。为此,可以在通用接口和具体实现之间增加一个抽象层,以对共性进行抽象,将两种功能的实现抽象为如下两个方法:
aw_err_t(*pfn_led_set)(void*p_cookie,int id,aw_ bool_t on);
aw_err_t(*pfn_led_toggle)(void*p_cookie,int id);
       相对于通用接口来说,抽象方法多了一个p_cookie参数。在面向对象的编程语言中(如C++),对象中的方法都能通过隐式指针p_this访问对象自身,引用自身的一些私有数据。而在C语言中则需要显式的声明,这里的p_cookie就有类似的作用,当前设置为void *类型主要是由于具体对象的类型还并不确定。
为了节省内存空间,同时方便管理,可以将所有抽象方法放在一个结构体中,形成一张虚函数表,比如:
struct awbl_led_servfuncs{
 aw_err_t(*pfn_led_set) (void*p_cookie,int id,bool_t on);
 aw_err_t(*pfn_led_toggle)(void*p_cookie,int id);
};
       由于LED的实现属于AWBus-lite的一部分,因此,命名使用"awbl_"作为前缀。这里定义了一个虚函数表,包含了两个方法,分别用于设置LED的状态和翻转LED。
(未完待续)
◇云南 刘光乾

电话直呼
在线客服
在线留言
发送邮件
企业位置
联系我们:
028-65113930
028-65113931
028-65113932
编辑
点击这里给我发消息
点击这里给我发消息
读者服务部
点击这里给我发消息
广告部
点击这里给我发消息
音响节
点击这里给我发消息
发行部
点击这里给我发消息
还可输入字符200(限制字符200)
技术支持: 建站ABC | 管理登录