本文导读
在使用AWBus-lite对设备进行管理时,无论设备处于 AWBus-lite拓扑结构中的哪个位置,只要其能够提供某种标准服务,就可以使用相应的通用接口对其进行操作。本文将从接口的定义和实现两个方面,深入理解AWbus-lite工作的原理。
本文为《面向AWorks框架和接口的编程(上)》第三部分软件篇——第13章——第1~2小节:通用接口的定义和接口的实现。本章导读
在基于AWBus-lite总线拓扑结构的设备管理框架中,无论一个设备处于AWBus-lite总线拓扑结构中的哪个位置,只要其能够提供某种标准服务,就可以使用相应的通用接口对其进行访问。那么,这究竟是怎样实现的呢?本章将继续深入探讨AWBus-lite,为您揭开AWBus-lite的神秘面纱,使您对AWBus-lite有更加深入的了解,在具有这些足够的了解后,你将有能力独立开发一些设备的驱动,当后续遇到一些AWorks暂不支持的设备时,可以自行开发设备相应的驱动。
13.1 通用接口的定义
合理的接口应该是简洁的、易阅读的、职责明确的,为了便于维护,通用接口由广州致远电子有限公司进行统一的定义,用户通常不需要自行定义通用接口。目前,常用的功能都已经被标准化,定义了相应的通用接口。
作为一种了解,下面以LED为例,从接口的命名、参数和返回值三个方面阐述在AWorks中定义接口的一般方法。
13.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”
13.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_on、aw_led_off和aw_led_toggle接口来说,它们的职责单一,仅仅需要指定控制的LED,即可完成点亮、熄灭或翻转操作,无需其它额外的参数。对于这类接口,参数仅仅需要id,这些接口的原型可以定义如下(还未定义返回值):
13.1.3 返回值
对于用户来说,调用通用接口后,应该可以获取到本次执行的结果,是执行成功还是执行失败,或是一些其它的有用信息。比如,在调用接口时,如果指定的id超过了有效范围,由于没有与无效id对应的LED设备,操作必定会失败,此时必须返回通过返回值告知用户操作失败,且操作失败的原因是id不在有效范围内,无与之对应的LED设备。
在AWorks中,接口通常返回一个aw_err_t类型的返回值来表示接口执行的结果,返回值的含义已被标准化:若返回值为AW_OK,则表示操作成功;若返回值为负数,则表示操作失败,此时,用户可根据具体的返回值,查找aw_errno.h文件中定义的宏,根据宏的含义确定失败的原因;若返回值为正数,其含义与具体接口相关,由具体接口定义,无特殊说明则表示不会返回正数。AW_OK是在aw_common.h文件中定义的宏,其定义如下:
错误号在aw_errno.h文件中定义,几个常见错误号的定义详见表6.2。比如,在调用LED通用接口时,若id不在有效范围内,则该id没有对应的LED设备,此时接口应该返回-AW_ENODEV。注意:AW_ENODEV的前面有一个负号,以表示负值。
基于此,将所有LED通用接口的返回值类型定义为aw_err_t,LED控制接口的完整定义详见表13.1,其对应的类图详见图13.1。
表13.1 LED通用接口(aw_led.h)
图13.1 LED接口类图
这些接口都已经在aw_led.h文件中完成了定义,无需用户再自行定义。上述从接口命名、参数和返回值三个方面详细阐述了一套接口定义的方法,旨在让用户了解接口的由来,加深对接口的理解。实际中,定义接口并不是一件容易的事情,需要尽可能考虑到所有的情况,接口作为与用户交互的途径,一旦定义完成,如非必要,都应该避免再对接口进行修改。否则,所有依赖于该接口的应用程序都将受到影响。因此,当前并不建议用户自定义通用接口,通用接口的定义应由广州致远电子有限公司统一规划、定义、维护和管理。
13.2 接口的实现
作为一种范例,下面以实现LED接口为例,详细介绍AWorks中实现接口的一般方法。
13.2.1 实现接口初探
在AWorks中,硬件设备和驱动统一由AWBus-lite进行管理,因此,对于LED这一类硬件设备,其实现是属于AWBus-lite的一部分。LED有4个通用接口函数,其中的aw_led_on()和aw_led_off()接口可以直接基于aw_led_set()接口实现,详见程序清单13.1。
程序清单13.1 aw_led_on()和aw_led_off()接口的实现
实现接口的核心是实现aw_led_set()和aw_led_toggle()这两个接口。对于不同的底层硬件设备,LED实际控制方式是不同的,比如,最常见的,通过GPIO直接控制一个LED,简单范例详见程序清单13.2。
程序清单13.2 aw_led_set()的实现(GPIO控制LED)
也有可能是通过串口控制一个LED设备。例如,通过发送字符串命令控制LED的状态,命令格式为:set
程序清单13.3 aw_led_set()的实现(UART控制LED)
总之,底层硬件设备是多种多样的,不同类型的LED设备对应的控制方式也会不同。
定义通用接口的目的在于屏蔽底层硬件的差异性,即无论底层硬件如何变化,用户都可以使用通用接口控制LED。显然,如果直接类似程序清单13.2和程序清单13.3这样实现一个通用接口,那么随着LED设备种类的增加,同一个接口的实现代码将有越来越多不同的版本。
在一个应用程序中,一个接口不能同时具有多种不同的实现,因此,这样的做法有着非常明显的缺点:多个不同种类的LED设备不能在一个应用中共存,更换硬件设备,就必须更换通用接口的实现,使用何种设备就加入相应设备的控制代码进行编译。 例如,系统中有几个直接通过GPIO控制的LED,同时也存在几个通过UART控制的LED,那么,类似程序清单13.2和程序清单13.3这样直接实现通用接口的方法,就无法组织代码了,因为不可能同时将程序清单13.2和程序清单13.3所示的代码加入工程编译。显然,需要更好的办法来解决这个问题。
13.2.2 LED抽象方法
在使用几种控制方式不同的LED硬件设备时,虽然它们对应的aw_led_set()和aw_led_toggle()接口的具体实现方法并不相同,但它们要实现的功能却是一样的,这是它们的共性:均要实现设置LED状态和翻转LED状态的功能。由于一个接口的实现代码只能有一份,因此,这些功能的实现不能直接作为通用接口的实现代码。为此,可以在通用接口和具体实现之间增加一个抽象层,以对共性进行抽象,将两种功能的实现抽象为如下两个方法:
相对于通用接口来说,抽象方法多了一个p_cookie参数。在面向对象的编程语言中(如C++),对象中的方法都能通过隐式指针p_this访问对象自身,引用自身的一些私有数据。而在C语言中则需要显式的声明,这里的p_cookie就有类似的作用,当前设置为void *类型主要是由于具体对象的类型还并不确定。
为了节省内存空间,同时方便管理,可以将所有抽象方法放在一个结构体中,形成一张虚函数表,比如:
由于LED的实现属于AWBus-lite的一部分,因此,命名使用"awbl_"作为前缀。这里定义了一个虚函数表,包含了两个方法,分别用于设置LED的状态和翻转LED。针对不同的硬件设备,都可以根据自身特性实现这两个方法。GPIO控制LED的伪代码详见程序清单13.4,UART控制LED的伪代码详见程序清单13.5。
程序清单13.4 抽象方法的实现(GPIO控制LED)
程序清单13.5 抽象方法的实现(UART控制LED)
显然,__g_led_gpio_drv_funcs和__g_led_uart_drv_funcs分别是使用GPIO和UART控制LED的具体实现,它们在形式上是两个不同的结构体常量,在同一系统中是可以共存的。
13.2.3 抽象的LED服务
当对不同的LED硬件设备抽象了相同的pfn_led_set和pfn_led_toggle方法后,在通用接口aw_led_set()和aw_led_toggle()的实现中,就无需再处理与硬件相关的具体事务,只需要找到相应设备提供的相应方法,然后调用这些具体硬件设备提供的方法即可。
在调用设备提供的方法时,由于方法的第一个参数为p_cookie,p_cookie代表了具体的设备对象,调用方法时,需要传递一个p_cookie给下层,用于在具体实现时,访问设备对象中的具体成员,起到“p_this”的作用。由于在aw_led_set()接口的实现中,并不需要直接操作具体设备,因此,无需知道p_cookie的具体类型,仅需起到一个传递的作用:在调用相应的方法时,传递给下层驱动使用。
既然要传递p_cookie,那么,必然要获得一个p_cookie并保存下来,显然,p_cookie代表了具体设备,只能由具体设备提供,同时,抽象方法也是由具体设备提供的,为此,可以将抽象方法和p_cookie定义在一起,形成一个新的类型,以便在具体设备提供的抽象方法的实现时,将p_cookie一并提供,即:
为了便于描述,将其称之为 “LED服务”。其中包含了由驱动实现的抽象方法和传递给驱动函数的p_cookie。其中,p_servfuncs为指向驱动虚函数表的指针,比如,指向__g_led_gpio_drv_funcs或__g_led_uart_drv_funcs,p_cookie为指向具体设备的指针,即传递给驱动函数的第一个参数。此时,在aw_led_set()接口的实现中,无需再完成底层硬件相关的操作,仅需调用LED服务中包含的pfn_led_set方法即可,其范例程序详见程序清单13.6。
程序清单13.6 aw_led_set()实现(1)
程序中,使用了一个全局变量__gp_led_serv指向当前一个有效的LED服务,显然,其只有在赋值后才能使用,暂不考虑其如何赋值,仅用以展示pfn_led_set方法的调用形式。
实际中,具体的LED设备往往不止一个。比如,使用GPIO控制的LED设备和使用UART控制的LED设备,它们都可以向系统提供LED服务,这就需要系统具有管理多个LED服务的能力。由于LED设备的数目无法确定,可能动态变化,因此,选用单向链表进行动态管理。为此,在struct awbl_led_service中增加一个p_next成员,用于指向下一个LED服务。即:
此时,系统中的多个LED服务使用链表的形式进行管理。那么,在通用接口的实现中,如何确定具体该使用哪个LED服务呢?在定义通用接口时,使用了ID号区分不同的LED,ID号是唯一的,显然,某一ID的LED必然属于某一确定的硬件设备,若一个硬件设备在提供LED服务时,包含了该硬件设备中所有LED的ID号信息,那么,在通用接口的实现中,就可以根据ID找到对应的LED服务,然后使用驱动中提供的方法完成LED的操作。为此,可以在LED服务中再增加一个ID信息,以表示对应硬件设备中所有LED的ID号。
在一个LED硬件设备中,可能包含多个LED,例如,MiniPort-LED扩展板,包含了8个LED,但一般来讲,一个LED硬件设备中所有LED的编号是连续分配的,基于此,仅需知道一个硬件设备中LED的起始编号和结束编号,就可以获得该硬件设备中所有LED对应的编号,例如,一个硬件设备中LED的起始编号为2、结束编号为9,则表示在该硬件设备中,各个LED的编号分别为:2、3、4、5、6、7、8、9,共计8个LED。为此,可以定义一个LED服务信息结构体类型,专门用于提供LED服务相关的信息,例如:
由此可见,在LED服务信息中,当前仅包含起始编号和结束编号两个信息。LED服务信息是与具体设备相关的,因此,可以在LED服务中新增一个指向LED服务信息的指针,以便在具体设备在提供p_cookie和抽象方法的实现时,将设备支持的LED编号信息一并提供,LED服务的完整定义详见程序清单13.7。
程序清单13.7 完整的LED服务类型定义(awbl_led.h)
由于在LED服务中新增了LED编号信息,那么,在通用接口的实现中,就可以根据设备提供的LED编号信息,找到id对应的LED服务。基于此,aw_led_set()函数的实现详见程序清单13.8。
程序清单13.8 aw_led_set()实现(2)
程序中,调用了__led_id_to_serv()函数以获取ID号对应的LED服务。__led_id_to_serv()函数通过遍历LED服务链表,将id与各个LED服务中的ID信息进行对比,直到找到id对应的LED服务(即id处于该LED服务的起始编号和结束编号之间),具体实现范例详见程序清单13.9。
程序清单13.9 获取ID号对应的LED服务
其中,__gp_led_serv_head是一个模块内部使用的全局变量,初始值为NULL,表示初始时系统中无任何有效的LED服务。同理,可实现aw_led_toggle()接口,详见程序清单13.10。
程序清单13.10 aw_led_toggle()实现
至此,实现了所有通用接口。显然,由于当前并不存在任何有效的LED服务,因此,__gp_led_serv_head的值为NULL,致使__led_id_to_serv()的返回值为NULL,最终导致通用接口的返回值始终为-AM_ENODEV。
13.2.4 Method机制
为了使通用接口能够操作到具体有效的LED,必须通过某种方法,将当前系统中所有LED设备提供的LED服务加入到以__gp_led_serv_head为头的LED服务链表中。
AWbus-lite提供了一种特殊的“Method机制”,其是一种系统上层和硬件底层相互“交流”的一种方式,可用于系统发现各个硬件设备提供的服务。AWBus-lite提供了Method相关的宏,详见表13.2。
表13.2 Method相关的宏(awbus_lite.h)
1. 定义一个Method类型
AWBL_METHOD_DEF()用于定义一个Method类型,其原型为:
其中,method为定义的Method类型名,string为一个描述字符串,描述字符串仅在定义时对method类型进行描述,可以是任意字符串,其它地方不会被使用到。
Method类型具有唯一性,不可定义两个相同的Method类型。Method类型可以看作一个“唯一标识”,用于标记某一类操作,在底层驱动的实现中,凡是能够完成该类操作的设备,都可以使用该“唯一标识”标记一个入口函数,该入口函数即用于完成相应的操作,这样一来,系统就可以通过该“唯一标识”查找所有被标记的入口函数,并依次调用它们,完成某种特定功能。例如,对于LED,为了获取当前系统中所有设备提供的LED服务,可以定义一个获取LED服务的Method类型,范例程序详见程序清单13.11。
程序清单13.11 定义Method类型范例程序
如此一来,即定义了一个名为awbl_ledserv_get的Method类型,该Method类型即表示了一类操作:获取LED服务。后续在底层设备驱动的实现中,只要一个设备能够提供LED服务,则表示系统可以从中获取到一个LED服务,此时,该驱动就可以提供一个入口函数,用于获取LED服务,并使用该Method类型对入口函数进行标记。这样,在系统启动时,就可以通过查找系统中所有被该Method类型标记的入口函数,然后一一调用它们,以此获得所有设备提供的LED服务。
2. 定义一个具体的Method对象
定义Method对象的本质就是使用Method类型标记一个入口函数,使系统知道该入口函数可以完成某种特定的功能,以便系统在合适的时机调用。为便于描述,在AWBus-lite中,将使用Method类型标记的入口函数称之为一个Method对象。AWBus-lite提供了定义Method对象的辅助宏,其原型为:
其中,name为使用AWBL_METHOD_DEF()定义的Method类型名,handler为用于完成某种特定功能的入口函数。例如,定义awbl_ledserv_get类型的目的是获取LED服务,因此,该类型的Method对象对应的handler应该能够获取到一个LED服务。handler的类型为awbl_method_handler_t,其定义如下(awbus_lite.h):
由此可见,awbl_method_handler_t是一个函数指针类型,其指向的函数有两个形参:p_dev和p_arg,返回值为标准的错误号。p_dev指向设备自身,同样起到一个p_this的作用,该handler运行在哪个设备上,传入p_dev的值就应该为指向该设备的指针;p_arg为void *类型的参数,其具体类型与该入口函数需要完成的功能相关,如果功能为获取一个LED服务,p_arg的实际类型就为struct awbl_led_service **,即一个指向LED服务的指针的地址,以便在函数内部改变指向LED服务的指针的值,使其指向设备提供的LED服务,从而完成LED服务的获取。例如,在GPIO控制LED的设备中,其能够提供LED服务,则应在对应的驱动中,定义一个具体的Method对象,便于系统得到LED服务。范例详见程序清单13.12。
程序清单13.12 定义Method对象范例程序
其中,__g_led_gpio_dev_methods为该设备能够提供的Method对象列表,一个设备提供的Method对象统一存放在一个列表中。该列表的具体使用以及入口函数的具体实现,将在LED驱动的实现中进一步介绍。这里仅用于展示系统上层获取LED服务的原理。
3. Method对象列表结束标记
在程序清单13.12中,将Method对象定义在了一个列表中,AWBL_METHOD_END用于定义一个特殊的标志,表示Method对象列表的结束。其原型为:
该宏无需传入任何参数,其仅用于标识一个Method对象列表的结束。例如,GPIO控制的LED设备只能提供一个Method对象,用于系统上层获取LED服务,那么,在该对象之后,应该使用AWBL_METHOD_END表示列表结束。范例程序详见程序清单13.13。
程序清单13.13 AWBL_METHOD_END使用范例程序
4. 导入(声明)一个在外部定义的Method类型
当需要使用一个已定义的Method类型时,若Method类型是在其它文件中定义的,此时就需要在使用前对该Method类型进行声明,类似于C语言中的extern。其原型为:
其中,name为使用AWBL_METHOD_DEF()定义的Method类型名。例如,在程序清单13.13中,定义了Method对象列表,其中使用到了Method类型:awbl_ledserv_get。在使用前,需要对该Method类型进行声明,范例程序详见程序清单13.14。
程序清单13.14 AWBL_METHOD_IMPORT()使用范例程序
5. 得到一个已定义的Method类型的ID
Method类型相当于一个“唯一标识”,有时候,需要判断某一Method对象是否为指定的Method类型。为了便于比较判断,或将“Method类型”作为参数传递给其它接口函数,可以通过该宏获得一个Method类型对应的ID,ID作为一个常量,可以用于比较或参数传递。获取Method类型的ID对应的宏原型为:
其中,method为使用AWBL_METHOD_DEF()定义的Method类型名,返回值为该Method类型的ID,其类型为:awbl_method_id_t,该类型的具体定义用户无需关心,ID可以用作比较,只要两个Method类型的ID相同,就表示两个Method类型是相同的,ID也可以作为参数传递给其它接口,以指定一种Method类型。
例如,在AWbus-lite中,提供了一个工具函数,用于查找设备中是否存在指定类型的Method对象,其函数原型为(awbus_lite.h):
其中,p_dev指定了要查找的设备,即在该设备中查找是否存在指定类型的Method对象,method用于指定Method类型的ID。若查找到该ID对应的method对象,则返回该method对象的入口函数,否则,返回NULL。
例如,有一个p_dev指向的设备,要查找其是否能够提供LED服务,则可以通过该接口实现,范例程序详见程序清单13.15。
程序清单13.15 AWBL_METHOD_ CALL()使用范例程序
程序中,使用AWBL_METHOD_ CALL()得到Method类型awbl_ledserv_get的ID,然后传递给awbl_dev_method_get()函数以查找设备中是否存在相应的Method对象,若存在,则得到了一个有效的入口函数,最后使用该入口函数即可得到一个LED服务。
13.2.5 LED服务链表的初始化
通过程序清单13.15所示的一个流程,若一个设备能够提供LED服务,则可以从中获取到相应的LED服务。若对每个设备都执行一遍上述流程,并在获得一个设备提供的LED服务后,就将其添加到以__gp_led_serv_head为头的LED服务链表中,则可以收集到系统中所有的LED服务,完成LED服务链表的初始构建。为了便于对所有设备执行某一操作,AWBus-lite提供了一个用于遍历所有设备的接口,其函数原型为:
其中,pfunc_action表示要在每个设备上执行的操作,p_arg为传递给pfunc_action的附加参数,flags为遍历设备的标志,返回值为标准错误号。
pfunc_action的类型为awbl_iterate_func_t,该类型的具体定义如下(awbus_lite.h):
由此可见,awbl_iterate_func_t是一个函数指针类型,其指向的函数有两个形参:p_dev和p_arg,返回值为标准的错误号。p_dev指向当前遍历到的设备,同样起到一个p_this的作用,当前遍历到哪个设备,在哪个设备上运行pfunc_action函数,传入的p_dev就为指向该设备的指针;p_arg为遍历时提供的附加参数,其值与调用awbl_dev_iterate()函数时传入的p_arg参数相同。
flags为遍历设备的标志,其决定了需要遍历哪些设备,以及pfunc_action函数的返回值是否能够终止遍历过程。可用标志详见表13.3。
表13.3 遍历设备标志宏(awbus_lite.h)
其中,AWBL_ITERATE_INSTANCES和AWBL_ITERATE_ORPHANS标志用于指定需要遍历的设备,即在哪些设备上执行pfunc_action函数。在硬件设备列表中,定义了当前系统中所有的硬件设备,当设备具有与之匹配的驱动时,才能够变成一个实例,被系统正常使用,而如果一个设备没有与之匹配的驱动,该设备将变成一个孤儿设备,由于没有与之匹配的驱动,因此系统暂时无法使用孤儿设备。AWBL_ITERATE_INSTANCES表示表示需要遍历所有实例,即具有相应驱动的设备。AWBL_ITERATE_ORPHANS表示需要遍历所有的孤儿设备。若要遍历所有的实例和孤儿设备,可以使用或运算同时设定这两个标志。
AWBL_ITERATE_INTRABLE标志用于指定pfunc_action 的返回值是否可以终止遍历,若设定了该标志,则在某一设备上运行pfunc_action函数的返回值将可以决定是否终止整个遍历过程:返回值为AW_OK时,不终止遍历,继续遍历其它设备;否则,遍历过程被终止,不会再继续遍历其它设备。若未设定该标志,则遍历过程不受返回值影响,直到遍历完所有需要遍历的设备后结束。
为了获得所有设备提供的LED服务,需要遍历所有实例,并在pfunc_action中执行如程序清单13.15所示的流程,并将各个设备提供的LED服务添加到以__gp_led_serv_head为头的LED服务链表中。完整的范例程序详见程序清单13.16。
程序清单13.16 获取所有设备提供的LED服务
程序中,由于孤儿设备没有对应的驱动,无法正常使用,显然无法提供LED服务,因此仅需遍历所有实例,遍历标志设定为了:AWBL_ITERATE_INSTANCES。该程序的目的是完成LED服务链表的初始构建,是一种初始化操作,因此,将其入口函数命名为了awbl_led_init(),若需使用LED,则应确保在系统启动时,该函数被自动调用。通常情况下,并不需要由用户手动调用该函数,而是将该函数的调用放在模板工程下的aw_prj_config.c文件中,具体位于aw_prj_early_init()函数中,该函数在系统启动时会被自动调用,从而使系统在启动时自动调用awbl_led_init()函数,详见详见程序清单13.17。
程序清单13.17 awbl_led_init()在系统启动时被自动调用的原理
在aw_prj_params.h工程配置文件中,只要使能了某一LED设备,比如,AW_DEV_GPIO_LED,则表示要使用LED,此时,将自动完成AW_COM_AWBL_LED的定义,以此确保当使用LED时,awbl_led_init()会在系统启动过程中被自动调用。核心的原理性程序详见程序清单13.18。
程序清单13.18 自动定义AW_COM_AWBL_LED宏的原理(aw_prj_params.h)
至此,完成了LED服务链表的初始化,若系统中存在LED服务,则链表将不为空,在LED通用接口的实现中,只要传入的id正确,__led_id_to_serv()的返回值就不为NULL,进而返回一个有效的LED服务,接着,通过LED服务中实现的抽象方法,即可完成LED相关的操作,例如,设置LED状态、翻转LED状态等。
-
接口
+关注
关注
33文章
8902浏览量
153059 -
总线
+关注
关注
10文章
2938浏览量
89223 -
周立功
+关注
关注
38文章
130浏览量
38063
原文标题:AWorks软件篇 — 深入理解 AWbus-lite(接口的定义和实现)
文章出处:【微信号:Zlgmcu7890,微信公众号:周立功单片机】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
设备驱动在AWbus-lite中驱动设备正常工作

AWBus-lite的拓扑结构及应用设计

深入理解和实现RTOS_连载
深入理解和实现RTOS_连载
深入理解STM32
对栈的深入理解
为什么要深入理解栈
基于AWBus-lite总线拓扑结构的设备管理框架

辨别PCB线路板好坏可以从两个方面入手

有几种电平转换电路,适用于不同的场景
一.起因一般在消费电路的元器件之间,不同的器件IO的电压是不同的,常规的有5V,3.3V,1.8V等。当器件的IO电压一样的时候,比如都是5V,都是3.3V,那么其之间可以直接通讯,比如拉中断,I2Cdata/clk脚双方直接通讯等。当器件的IO电压不一样的时候,就需要进行电平转换,不然无法实现高低电平的变化。二.电平转换电路常见的有几种电平转换电路,适用于

瑞萨RA8系列教程 | 基于 RASC 生成 Keil 工程
对于不习惯用 e2 studio 进行开发的同学,可以借助 RASC 生成 Keil 工程,然后在 Keil 环境下愉快的完成开发任务。

共赴之约 | 第二十七届中国北京国际科技产业博览会圆满落幕
作为第二十七届北京科博会的参展方,芯佰微有幸与800余家全球科技同仁共赴「科技引领创享未来」之约!文章来源:北京贸促5月11日下午,第二十七届中国北京国际科技产业博览会圆满落幕。本届北京科博会主题为“科技引领创享未来”,由北京市人民政府主办,北京市贸促会,北京市科委、中关村管委会,北京市经济和信息化局,北京市知识产权局和北辰集团共同承办。5万平方米的展览云集

道生物联与巍泰技术联合发布 RTK 无线定位系统:TurMass™ 技术与厘米级高精度定位的深度融合
道生物联与巍泰技术联合推出全新一代 RTK 无线定位系统——WTS-100(V3.0 RTK)。该系统以巍泰技术自主研发的 RTK(实时动态载波相位差分)高精度定位技术为核心,深度融合道生物联国产新兴窄带高并发 TurMass™ 无线通信技术,为室外大规模定位场景提供厘米级高精度、广覆盖、高并发、低功耗、低成本的一站式解决方案,助力行业智能化升级。

智能家居中的清凉“智”选,310V无刷吊扇驱动方案--其利天下
炎炎夏日,如何营造出清凉、舒适且节能的室内环境成为了大众关注的焦点。吊扇作为一种经典的家用电器,以其大风量、长寿命、低能耗等优势,依然是众多家庭的首选。而随着智能控制技术与无刷电机技术的不断进步,吊扇正朝着智能化、高效化、低噪化的方向发展。那么接下来小编将结合目前市面上的指标,详细为大家讲解其利天下有限公司推出的无刷吊扇驱动方案。▲其利天下无刷吊扇驱动方案一

电源入口处防反接电路-汽车电子硬件电路设计
一、为什么要设计防反接电路电源入口处接线及线束制作一般人为操作,有正极和负极接反的可能性,可能会损坏电源和负载电路;汽车电子产品电性能测试标准ISO16750-2的4.7节包含了电压极性反接测试,汽车电子产品须通过该项测试。二、防反接电路设计1.基础版:二极管串联二极管是最简单的防反接电路,因为电源有电源路径(即正极)和返回路径(即负极,GND),那么用二极

半导体芯片需要做哪些测试
首先我们需要了解芯片制造环节做⼀款芯片最基本的环节是设计->流片->封装->测试,芯片成本构成⼀般为人力成本20%,流片40%,封装35%,测试5%(对于先进工艺,流片成本可能超过60%)。测试其实是芯片各个环节中最“便宜”的一步,在这个每家公司都喊着“CostDown”的激烈市场中,人力成本逐年攀升,晶圆厂和封装厂都在乙方市场中“叱咤风云”,唯独只有测试显

解决方案 | 芯佰微赋能示波器:高速ADC、USB控制器和RS232芯片——高性能示波器的秘密武器!
示波器解决方案总述:示波器是电子技术领域中不可或缺的精密测量仪器,通过直观的波形显示,将电信号随时间的变化转化为可视化图形,使复杂的电子现象变得清晰易懂。无论是在科研探索、工业检测还是通信领域,示波器都发挥着不可替代的作用,帮助工程师和技术人员深入剖析电信号的细节,精准定位问题所在,为创新与发展提供坚实的技术支撑。一、技术瓶颈亟待突破性能指标受限:受模拟前端

硬件设计基础----运算放大器
1什么是运算放大器运算放大器(运放)用于调节和放大模拟信号,运放是一个内含多级放大电路的集成器件,如图所示:左图为同相位,Vn端接地或稳定的电平,Vp端电平上升,则输出端Vo电平上升,Vp端电平下降,则输出端Vo电平下降;右图为反相位,Vp端接地或稳定的电平,Vn端电平上升,则输出端Vo电平下降,Vn端电平下降,则输出端Vo电平上升2运算放大器的性质理想运算

ElfBoard技术贴|如何调整eMMC存储分区
ELF 2开发板基于瑞芯微RK3588高性能处理器设计,拥有四核ARM Cortex-A76与四核ARM Cortex-A55的CPU架构,主频高达2.4GHz,内置6TOPS算力的NPU,这一设计让它能够轻松驾驭多种深度学习框架,高效处理各类复杂的AI任务。

米尔基于MYD-YG2LX系统启动时间优化应用笔记
1.概述MYD-YG2LX采用瑞萨RZ/G2L作为核心处理器,该处理器搭载双核Cortex-A55@1.2GHz+Cortex-M33@200MHz处理器,其内部集成高性能3D加速引擎Mail-G31GPU(500MHz)和视频处理单元(支持H.264硬件编解码),16位的DDR4-1600/DDR3L-1333内存控制器、千兆以太网控制器、USB、CAN、

运放技术——基本电路分析
虚短和虚断的概念由于运放的电压放大倍数很大,一般通用型运算放大器的开环电压放大倍数都在80dB以上。而运放的输出电压是有限的,一般在10V~14V。因此运放的差模输入电压不足1mV,两输入端近似等电位,相当于“短路”。开环电压放大倍数越大,两输入端的电位越接近相等。“虚短”是指在分析运算放大器处于线性状态时,可把两输入端视为等电位,这一特性称为虚假短路,简称

飞凌嵌入式携手中移物联,谱写全国产化方案新生态
4月22日,飞凌嵌入式“2025嵌入式及边缘AI技术论坛”在深圳成功举办。中移物联网有限公司(以下简称“中移物联”)携OneOS操作系统与飞凌嵌入式共同推出的工业级核心板亮相会议展区,操作系统产品部高级专家严镭受邀作《OneOS工业操作系统——助力国产化智能制造》主题演讲。

ATA-2022B高压放大器在螺栓松动检测中的应用
实验名称:ATA-2022B高压放大器在螺栓松动检测中的应用实验方向:超声检测实验设备:ATA-2022B高压放大器、函数信号发生器,压电陶瓷片,数据采集卡,示波器,PC等实验内容:本研究基于振动声调制的螺栓松动检测方法,其中低频泵浦波采用单频信号,而高频探测波采用扫频信号,利用泵浦波和探测波在接触面的振动声调制响应对螺栓的松动程度进行检测。通过螺栓松动检测

MOS管驱动电路——电机干扰与防护处理
此电路分主电路(完成功能)和保护功能电路。MOS管驱动相关知识:1、跟双极性晶体管相比,一般认为使MOS管导通不需要电流,只要GS电压(Vbe类似)高于一定的值,就可以了。MOS管和晶体管向比较c,b,e—–>d(漏),g(栅),s(源)。2、NMOS的特性,Vgs大于一定的值就会导通,适合用于源极接地时的情况(低端驱动),只要栅极电压达到4V或10V就可以
评论