本文导读
为了管理系统中各式各样的硬件设备(或虚拟硬件设备),AWorks推出了领先的轻量级总线管理框架:AWBus-lite,实现了硬件设备和驱动的彻底分离,使设备驱动可以最大限度的得到复用。本文介绍了AWBus-lite的基础概念,以及如何使用和配置AWbus-lite。
本文为《面向AWorks框架和接口的编程》第三部分软件篇——第12章AWBus-lite总线框架——第1~4小节:AWBus-lite简介、AWBus-lite拓扑结构、系统硬件资源和访问设备。本章导读
在嵌入式系统中,硬件外设的种类非常繁多,例如,GPIO、ADC、UART、按键、数码管、RTC、LM75、EEPROM、SD卡、U盘等。正确使用各个外设的基础是平台中具有相应的驱动,随着外设种类的不断增加,驱动也随之越来越多,为了高效的管理众多的外设和驱动,AWorks推出了领先的轻量级总线管理框架:AWBus-lite。AWBus-lite作为AWorks中最重要的组件之一,负责管理系统中所有的硬件设备(或虚拟硬件设备),实现硬件外设和驱动的分离,使驱动可以最大限度的得到复用。
本章作为AWBus-lite的入门,主要介绍了AWBus-lite的拓扑结构,以及基本的设备、总线、驱动相关的概念,重点从用户角度出发,讲述如何使用、配置AWBus-lite。
12.1 AWBus-lite简介
随着MCU的快速发展,越来越多的硬件外设集成到了MCU内部(片内外设),这部分外设可以直接通过CPU操作相应的寄存器使用,例如,i.MX28x中的GPIO、ADC、UART等。一些外设在MCU外部(片外外设),必须通过某种总线进行访问,比如PCF85063,需要通过I²C总线访问;SD卡,需要通过SDIO总线访问。
为了使用统一的拓扑结构描述所有的片外和片内外设,在AWBus-lite中,把CPU直接控制的总线统称为PLB(Processor Local Bus,CPU本地总线),集成在MCU内部的外设就挂在该总线上。例如:在一个系统中,硬件设备连接示意图详见图12.1(a),其对应的AWBus-lite软件拓扑结构详见图12.1(b)。
图12.1 AWBus-lite抽象
AWBus-lite提供了一种机制,使得我们可以在软件环境里建立、还原系统的硬件总线拓扑结构。如图12.1所示,图12.1(a)为一个可能的系统总线的物理拓扑结构(仅作示例之用),图12.1(b)为在AWBus-lite中抽象出来的系统总线模型。由此可见,在软件中抽象出来的对象同真实世界的对象一一对应!
图12.1(a)仅作为一种示例,与实际硬件可能存在差异。整个硬件被分为了核心板(i.MX28xPack board)和用户板(User Board)两部分。核心板又分为MCU(i.MX28x)和外围器件(ICs)两个部分,MCU又分为内核(ARM)和片内外设两个部分。
内核的核心是CPU,其可以直接控制片上外设,这里虚拟了一个PLB控制器,其产生了一条PLB总线,由CPU直接控制,片内外设均直接挂在PLB总线上。
片内外设集成在芯片内部,例如,GPIO、I²C、UART等,它们挂在PLB总线上。其中部分片内外设又是总线控制器(比如I²C),它们又可以扩展出一条总线到片外,例如,I²C0扩展出一条总线I²C bus 0,I²C1扩展出一条总线II²C bus 1。扩展的总线可以连接一些外围器件。
这些器件可能处于核心板中,比如
SC18IS602B(一款I²C转SPI芯片,仅用作拓扑结构展示,无需深入了解)、
CAT24C02(EEPROM)、PCF85063(RTC芯片),也可能处于用户板上,比如CAT9555(一款I²C转GPIO芯片,仅用作拓扑结构展示,无需深入了解)。
一些外围器件可能又是总线控制器,则其又可以扩展出一条总线,比如SC18IS602B,其为I²C转SPI芯片,可以扩展出SPI总线,在SPI总线上,又可以挂在其它SPI接口的器件,比如:SC16IS752(一款SPI转UART芯片,仅用作拓扑结构展示,用户无需了解具体细节)。特别地,若连接的芯片又是一个总线控制器,则可以继续扩展总线,从理论上讲,通过添加总线控制器,可以将系统的总线层次无限地增加,即系统的功能外设可无限扩展。
图12.1(b)为对应的软件拓扑结构图,在软件环境中,外设对象与真实硬件设备呈一一对应关系。不过,软件环境中并不区分设备的物理位置,只考虑设备的父总线,比如CAT9555(用户板上)和PCF85063(核心板上)都是挂在I²C bus 1上的,则它们处于同一个层级。
12.2 AWBus-lite拓扑结构
在图12.1中,以一个具体的示例说明了AWbus-lite的基本结构,展示了AWBus-Lite对现实世界的一种抽象。从具体到一般,一个更加抽象的总线拓扑结构详见图12.2。
图12.2 AWBus-lite总线拓扑结构图
其中,Bus Controller 0是由CPU直接控制的总线控制器,通常情况下,其为PLBController,以扩展出一条PLB总线。在总线拓扑结构图中,抽象了3个重要的概念:设备、总线控制器、总线。
-
设备
设备是指挂在某条总线上的硬件外设(或虚拟外设)。例如,图12.1中的GPIO、CAT24C02、CAT9555等。
-
总线控制器
总线控制器是一种特殊的设备,它可以扩展出一条下游总线,这条总线上又能挂其它设备(包括总线控制器)。例如,图12.1中的I²C0、SC18IS602B等。
-
总线
任何设备或总线控制器都必须挂在一条总线上。AWBus-lite不区分CPU的具体类型,把CPU直接控制的总线统称为 PLB,PLB为根总线。其它总线由总线控制器产生,例如,图12.1中的I²C Bus 0、I²C Bus 1、SPI Bus等。
“设备”是最为核心的概念,其它概念都可以基于“设备”进行描述:“设备”挂在“总线”上,特殊“设备”(总线控制器设备)扩展出一条下游总线。能够正常使用一个设备的前提是系统中具有设备相应的驱动,例如,要使用i.MX28x的GPIO去控制一个LED,就必须具有相应的GPIO驱动,以设置GPIO的模式、输出电平等,最终达到控制LED的目的。也就是说,要使系统具有访问和控制设备的能力,就必须具有相应的驱动。这就需要掌握另外一个非常重要的概念:设备驱动。
设备驱动提供了访问和控制设备(包括特殊的设备:总线控制器)的能力,在AWBus-lite中,将设备和驱动进行了很好的分离,使驱动可以最大限度的得到复用。通常情况下,系统中可能存在多个相同类型的设备。例如,在i.MX28x中,存在I²C0和I²C1共计两个I²C总线控制器,它们的操作方法是完全相同的,这种情况下,I²C0和I²C1设备即可复用一份驱动。示意图详见图12.3。
图12.3I²C0和I²C1复用同一份驱动
其它片上外设或外围器件同样如此,多个同类型的设备可以复用一份驱动,这不仅极大的提高了代码复用率,缩小了程序占用的存储空间,也给代码的管理、维护、扩展带来了极大的便利。这是面向对象编程带来的好处,在这里,设备驱动就相当于一个类,而设备就是类的一个实例。
12.3 系统硬件资源
在开发实际应用程序前,首先要规划系统的硬件资源,即要构建出如图12.1(a)所示的硬件物理拓扑结构。接下来,就需要对系统软件进行配置,添加相应的设备,以搭建出与之对应的如图12.1(b)所示的软件拓扑结构。通常情况下,AWorks SDK提供的工程模板已经配置好了系统相应的硬件资源,完成了基础软件拓扑结构的搭建,对于不同的用户需求,可能需要添加或删除一些设备,这种情况下,可以直接在模板工程的基础上对系统硬件资源进行简要的调整。
12.3.1 硬件设备列表
AWBus-lite使用名为
awbus_lite_hwconf_usrcfg.c的硬件配置文件来定义系统的硬件资源,此文件存放于AWorks SDK提供的工程模板中。硬件配置文件的核心功能是为系统提供一个硬件列表,即一个名为:g_awbl_devhcf_list[]的数组,该数组的每一个成员都描述了系统中的一个硬件设备。一个简单的示例片段详见程序清单12.1。
程序清单12.1 硬件设备列表(awbus_lite_hwconf_usrcfg.c)
在AWBus-lite中,以“awbl_”作为命名空间,“awbl”是AWBus-lite的缩写。aw_const是用于定义常量的修饰符,其等效于C语言中的关键字:const。
g_awbl_devhcf_list[]数组为定义的硬件设备列表,g_awbl_devhcf_list_count定义了列表中设备的个数。AW_NELEMENTS()为获取数组元素个数的宏,其定义如下(aw_common.h):
12.3.2 设备描述类型
由数组的定义可知,数组中每个元素的实际类型为struct awbl_devhcf,其描述了一个硬件设备在系统总线拓扑结构中的位置以及设备的配置,具体类型定义详见程序清单12.2。
程序清单12.2 struct awbl_devhcf类型定义(awbus_lite.h)
1. 设备名
设备名为一个字符串,此名字需要与设备驱动的名字一致,系统将根据此名字查找该设备对应的驱动。在系统启动时,最重要的步骤之一就是将设备和设备驱动绑定,以便正确使用各个设备。要使系统能够正确查找到设备相应的驱动,设备名必须与相应的驱动名一致。
为确保一致性,在开发驱动时,往往使用宏定义的形式将驱动名定义在头文件中,在描述一个硬件设备时,直接使用该宏定义作为其设备名即可。
例如,i.MX28x的片上I²C设备驱动,其对应的驱动头文件为:awbl_imx28_i2c.h,在该文件中,定义了驱动名为AWBL_IMX28_I²C_NAME,完整定义如下:
基于此,在描述I²C设备(如描述I²C1设备),对应的设备名应该设定为:
AWBL_IMX28_I²C_NAME。
又如,对于PCF85063设备驱动,其对应的驱动头文件为:awbl_pcf85063.h,在该文件中,定义了驱动名为:AWBL_PCF85063_NAME。其完整的定义如下:
基于此,在描述PCF85063设备时,其设备名应该设定为:
AWBL_PCF85063_NAME。
2. 设备单元号
设备单元号用于区分系统中几个相同的硬件设备,它们的设备名一样,复用同一份驱动。
AWBus-lite建议设备单元号从0开始连续分配。
例如,在i.MX28x中,具有两个I²C片内外设,则I²C0的设备单元号为0,I²C1的设备单元号为1。又如,对于PCF85063设备,若只外接了一个PCF85063,则设备单元号为0,若外接了两个PCF85063,则设备单元号分别为0、1。通常情况下,一个系统中只会使用一个外部RTC,不会连接两个外部RTC芯片,此时,将设备单元号设置为0即可。
注意,在通用接口中,通常有一个用于指定设备的ID,例如,在RTC接口中,使用ID指定要操作的RTC设备。设备单元号与该ID的概念是不同的,设备单元号用于区分几个使用同一驱动的设备,ID用于区分同一类的设备(这些设备不一定使用相同的驱动)。
例如,i.MX28x具有片上RTC外设,其挂在PLB总线上,显然,其驱动方法与挂在I²C总线上的PCF85063是不一样的。若系统同时使用了片上RTC外设和一个片外PCF85063,由于它们并不使用同一份驱动,因此,在描述这两个设备时,设备名是不一样的,设备单元号可各自独立分配,互不影响,均可设置为0。但是,由于这两个设备均可以为系统RTC服务,可以使用RTC通用接口操作这两个设备,为了区分这两个设备,它们的ID必须统一编排,例如,为片上RTC外设分配编号0,为PCF85063分配编号1,不可设置为一样。ID在一个设备对应的设备信息中配置,将在后文详细介绍。
3. 设备父总线的类型
设备父总线的类型指出了设备挂接在哪种类型的总线上,例如,PLB、I²C、SPI、USB、SDIO、PCI等。各总线的类型已经在awbus_lite.h文件中定义,部分常用总线对应的宏定义详见表12.1。
表12.1 总线类型宏定义
例如,i.MX28x的片上I²C1设备,其由CPU直接控制,挂接在PLB总线上,因此,对于I²C1设备,bus_type的值为:AWBL_BUSID_PLB。
对于PCF85063设备,其作为一种I²C从机器件,挂接在I²C总线上,因此,对于PCF85063设备,bus_type的值为:AWBL_BUSID_I²C。
4. 设备父总线的编号
设备父总线的编号用于区分系统中多条类型相同的总线。AWBus-lite建议总线编号从0开始连续分配。
在AWBus-lite中,PLB总线是一条特殊的虚拟总线,只有一条,因此,对于挂在PLB总线上的设备,比如i.MX28x的片上I²C1设备,它们的设备父总线编号总是为0。其它类型的总线可能有多条,例如,i.MX28x具有两个I²C片上外设:I²C0、I²C1,它们作为一种总线控制器,可以各自扩展出一条I²C总线,致使系统中有两条I²C总线,可将它们的总线编号分别设置为0、1。对于PCF85063,若其连接在I²C0总线上,则bus_index的值为0;若其连接在I²C1总线上,则bus_index的值为1。
5. 设备实例内存
设备驱动相当于定义了一个类,而具体的设备相当于这个类的一个实例,显然,实例需要占用一定的内存空间。而在AWBus-lite中,并不使用动态内存分配,因此,需要在描述一个设备的同时,完成设备实例的静态定义,为设备实例分配必要的内存空间。p_dev即为指向静态定义的设备实例的指针,其类型struct awbl_dev是AWBus-lite定义的基础设备类型,其具体定义用户无需关心。实际设备类型均是从基础设备类型派生而来的,例如,PCF85063的设备类型可能定义为:
由于实际设备类型仅用于在描述设备时分配设备实例相关的内存,并不需要操作其中的成员,因此,用户并不需要关心实际设备类型的具体定义(比如,具体包含哪些成员等)。用户只需要了解到实际设备类型是从基础设备类型派生而来的,因而可以将实际设备类型的指针强转为基础设备类型的指针进行使用(之类转换为父类)。
例如,对于i.MX28x的片上I²C1设备,在其对应的驱动头文件awbl_imx28_i2c.h中定义了I²C设备的类型为struct awbl_imx28_i2c_dev,使用该类型定义一个I²C1设备实例,即可完成设备实例的内存分配,例如:
注: aw_local用于将函数作用域限制在文件内部,或将变量的作用域限制在文件或函数内部,同时,将aw_local修饰的变量存放在全局静态区域,在整个程序的生命周期均保持有效。其本质上等效于C语言中的关键字:static。
其地址&__g_imx28_i2c1_dev即可作为设备描述中p_dev的值。虽然其类型与p_dev的类型并不相同,但由于struct awbl_imx28_i2c_dev类型继承自struct awbl_dev类型,是基础设备类型的一个子类,可以将子类转换为父类使用,例如,将p_dev设置为:
同理,对于PCF85063设备,在其对应的驱动头文件awbl_pcf85063.h中定义了PCF85063的设备类型为struct awbl_pcf85063_dev,使用该类型定义一个PCF85063设备实例,即可完成设备实例的内存分配,例如:
其地址&__g_pcf85063_0_dev即可作为设备描述中p_dev的值,例如,将p_dev设置为:
6. 设备信息
设备信息描述了设备的一些配置信息,例如,设备的基地址、中断号等信息。设备信息的具体类型是由设备驱动定义的。用户需要根据实际设备信息的类型定义一个设备信息,并将其地址赋值给设备描述中的p_devinfo。该信息最终会传递给驱动使用,以便正确的驱动相应设备。
-
I²C1设备信息定义范例
对于i.MX28x的片上I²C1设备,在其对应的驱动头文件awbl_imx28_i2c.h中定义了I²C设备信息类型为struct awbl_imx28_i2c_devinfo,其具体定义详见程序清单12.3。
程序清单12.3 I²C设备信息类型定义(awbl_imx28_i2c.h)
I²C设备是一个I²C控制器,可以扩展出一条I²C总线,i2c_master_devinfo即用于提供I²C总线相关的信息,比如:总线的编号、速率、超时时间等。其类型structawbl_i2c_master_devinfo的定义详见程序清单12.4。
程序清单12.4 struct awbl_i2c_master_devinfo类型定义(awbl_i2cbus.h)
其中bus_index表示该I²C控制器扩展出的I²C总线对应的编号,若某一设备(如PCF85063)在硬件上与I²C1连接,则在其设备描述中,父总线的编号应与该值保持一致。speed表示该I²C总线的速率。通常情况下,为了便于配置,将总线编号和速率使用宏的形式定义在aw_prj_param.h文件中,例如,将总线ID定义为1,速率定义为200KHz:
后续使用这两个宏分别作为bus_index和speed的值即可。
timeout表示超时时间,若使用通用I²C接口在该总线上的某一操作(如读数据或写数据)超过了该处定义的超时超时,则相应接口将返回超时错误。特别地,若将该值设置为
(其是在awbl_i2cbus.h文件中定义的宏),则表示永久等待,也可以设置为其它正整数值,例如,500,则表示超时时间为500个tick。
regbase表示I²C设备的基地址,对于i.MX28x,所有片内外设的基地址均在imx28x_regbase.h文件中定义,例如,I²C1的基地址定义如下:
由此可见,I²C1设备的基地址为0x8005A000,该值可以从i.MX28x的用户手册中获得。
inum表示I²C设备的中断号,驱动可以使用该中断号使用系统中断资源,以使I²C设备可以基于中断机制进行数据通信。对于i.MX28x,所有片内外设的中断号均在imx28x_inum.h文件中定义,例如,I²C1设备的中断号定义如下:
由此可见,I²C1设备的中断号为110,该值可以从i.MX28x的用户手册中获得。
clkfreq表示I²C模块的输入时钟频率,在i.MX28x中,默认频率为24MHz,该值通常不需要修改。
pfunc_plfm_init是一个函数指针,指向一个无参数、无返回值的平台初始化函数,用于完成平台相关的初始化操作,比如引脚配置等。例如,在定义一个平台初始化函数,完成I²C1设备的SCL和SDA引脚配置,详见详见程序清单12.5。
程序清单12.5 实现一个平台初始化函数
其中,__imx28_i2c1_plfm_init为实现的平台初始化函数,其可直接作为设备信息中
pfunc_plfm_init的值。
基于上面对各个成员的描述,可以定义一个典型的设备信息,详见程序清单12.6。
程序清单12.6 I²C1设备信息定义
完成设备信息的定义后,其地址
&__g_imx28_i2c1_devinfo即可作为设备描述中p_devinfo的值。
-
PCF85063设备信息定义范例
对于PCF85063设备,在其对应的驱动头文件awbl_pcf85063.h中定义了PCF85063的设备信息类型为awbl_pcf85063_devinfo_t,其具体定义详见程序清单12.7。
程序清单12.7 PCF85063设备信息类型定义(awbl_pcf85063.h)
其中,rtc_servinfo包含了RTC标准服务相关的信息,目前仅包含了RTC的编号,其类型定义详见程序清单12.8。
程序清单12.8 RTC通用服务信息类型定义(awbl_rtc.h)
通过RTC通用接口的介绍可知,在使用通用接口操作RTC时,需要通过rtc_id指定使用的RTC设备,rtc_id通常从0开始编号。rtc_servinfo中的rtc_id即用于指定该设备对应的ID号,如果设置为0,则用户在使用RTC通用接口时,将rtc_id参数设置为0即可操作到此处定义的硬件设备。
addr为PCF85063的7位I²C从机地址,通过查看PCF85063的数据手册可知,PCF85063的7位I²C从机地址为0x51。
基于rtc_id和addr的值,可以完成PCF85063设备信息的定义,详见程序清单12.9。
程序清单12.9 PCF85063设备信息定义范例
完成设备信息的定义后,其地址
&__g_pcf85063_0_devinfo即可作为设备描述中p_devinfo的值。
12.3.3 设备描述宏定义
在g_awbl_devhcf_list[]数组中,每个元素都是以“AWBL_HWCONF_”作为前缀的一个宏。该宏本质上完成了一个设备描述的定义。
例如,对于i.MX28x的片上I2C1设备,其对应的宏为:AWBL_HWCONF_IMX28_I2C0。基于前面介绍的设备描述中各个成员的值,可以完成该宏的定义,详见程序清单12.10。
程序清单12.10 I²C1设备描述宏定义
对于PCF85063设备,其对应的宏为
AWBL_HWCONF_PCF8563_0,基于前面介绍的设备描述中各个成员的值,可以完成该宏的定义,详见程序清单12.11。
程序清单12.11 PCF85063设备描述宏定义
通常情况下,为了保持
awbus_lite_hwconf_usrcfg.c文件的简洁,将设备描述宏的定义(包括设备、设备信息的定义)单独存放到一个头文件中,I²C1设备描述宏定义相关的信息存放在awbl_hwconf_imx28_i2c1.h文件中,PCF85063设备描述宏定义相关的信息存放在awbl_hwconf_pcf85063_0.h文件中。
这些文件已经在模板工程中提供,在硬件设备列表中,只需加入该宏即可,详见程序清单12.1。通过设备的描述可知,I²C1设备挂在PLB总线上,PCF85063设备挂在I²C1总线上,设备描述与拓扑结构的关系详见图12.4。
图12.4 I²C1和PCF85063设备描述与拓扑结构的对应关系
12.3.4 设备的配置与裁剪
设备配置主要是基于工程模板中提供的配置文件,进行设备描述或设备信息的修改。用户若需修改硬件设备的配置,只需找到该硬件设备相应的头文件,修改其中的相关信息即可。
例如,需要修改PCF85063的rtc_id为1,仅需将程序清单12.9中的第3行修改为1。若需调整设备在总线拓扑结构中的位置。一般来讲,一个设备的父总线类型是确定的,不会修改。如PCF85063,其父总线类型必定为:
AWBL_BUSID_I²C。调整设备在总线拓扑结构中的位置往往是修改父总线的编号,如要将PCF85063挂在I²C0上,仅需将程序清单12.11中,第6行对应的父总线编号修改为I²C0对应的总线总线编号,即:IMX28_I²C0_BUSID。
除简单的配置外,另外一种特殊的操作是裁剪,例如,用户不需要使用PCF85063,则可以在硬件列表中删除该设备的描述宏:
AWBL_HWCONF_PCF85063_0。为了便于用户裁剪,避免直接操作g_awbl_devhcf_list[]数组,在awbl_hwconf_pcf85063_0.h文件中,使用了另外一个使能宏来控制
AWBL_HWCONF_PCF85063_0宏的定义,详见程序清单12.12。
程序清单12.12 增加PCF85063设备使能宏(awbl_hwconf_pcf85063_0.h)
程序中,增加了一个使能宏:
AW_DEV_EXTEND_PCF85063_0。若该宏被有效定义,则AWBL_HWCONF_PCF85063_0宏的定义为完整的设备描述,此时,PCF85063设备正常的加入到设备列表中;反之,若使能宏未被定义,则AWBL_HWCONF_PCF85063_0宏将是一个空的宏定义,同时,相关的设备实例,设备信息也不会被定义。此时,在设备列表中,将不存在PCF85063设备的描述,相当于裁剪掉了该设备。同理可以新增一个I²C1设备的使能宏,以便对I²C1设备进行裁剪,详见程序清单12.13。
程序清单12.13 增加I²C1设备使能宏(awbl_hwconf_imx28_i2c1.h)
程序中,新增了AW_DEV_IMX28_I²C_1宏对I²C1设备是否使能进行控制。为便于查找,在AWorks中,类似的设备相关的使能宏均在模板工程下的aw_prj_params.h文件中进行统一的定义,详见程序清单12.14。
程序清单12.14 设备使能宏定义(aw_prj_params.h)
若其中的某一个宏被用户注释掉了,则对应的设备就会被裁剪。通过查看aw_prj_params.h文件,用户可以了解哪些设备被使能了,哪些设备被禁能了,并根据需要,灵活的调整。例如,不再使用PCF85063,则可以注释掉该宏,详见程序清单12.15。
程序清单12.15 设备裁剪范例(aw_prj_params.h)
值得注意的是,部分特殊的片上外设,例如,GPIO、中断控制器等,系统必须使用,不能被裁剪,此时,将不会在相应的配置文件中增加额外的使能宏。
12.3.5 注册设备驱动
在描述一个设备时,通过设备名指定了该设备对应的驱动,要使设备正常工作,系统中必须存在设备对应的驱动。AWorks作为一个完备的软件平台,已经支持众多的芯片和外围器件,提供了许许多多的设备驱动,随着AWorks的进一步发展,提供的驱动还会越来越多。
显然,为了节省系统资源,并不能将所有驱动都加载到系统中,而应该只将使用到的驱动加载到系统中,驱动的加载在aw_prj_config.c文件中的awbl_group_init()函数中完成,该函数在系统启动时被自动调用。
每个驱动都提供了一个驱动注册函数,要使用该驱动,则应在awbl_group_init()函数中调用驱动提供的注册函数。例如,对于PCF85063设备驱动,其提供的驱动注册函数在驱动头文件awbl_pcf85063.h文件中声明,即:
如需使用PCF85063,则应将该驱动加载到系统中,即:
一般来讲,新增的驱动都添加到函数尾部。同理,为了便于裁剪,不直接修改aw_prj_config.c文件,往往使用一个宏对是否注册相应驱动进行控制,只有当宏使能时,才进行相应的驱动注册,详见程序清单12.16。
程序清单12.16 通过宏控制驱动是否注册的原理
程序中,若定义了
AW_DRV_EXTEND_PCF85063_0宏,则会调用驱动注册函数将驱动注册到系统之中;否则,驱动将不会被注册,相应的驱动代码就得到了裁剪。
为便于管理,在AWorks中,类似的驱动相关的使能宏均在模板工程下的aw_prj_params.h文件中进行统一的定义,例如:
实际中,只要使用PCF85063设备,就必须将PCF85063的设备驱动注册到系统之中,为了确保这一关系,模板工程中,做了一个简单的自动定义操作,在设备和设备驱动的使能宏之间进行了恰当的关联,即:
由此可见,只要PCF85063设备被使能,AW_DRV_AWBL_EXTEND_PCF85063_0宏将被自动定义,使相应的驱动也随之注册到系统之中。
这里仅仅只是简单的展示了设备驱动加载的原理,帮助用户更深入的理解AWBus-lite。实际中,模板工程已经对此进行了恰当的处理,当一个设备被使能后,其相应的驱动会被一并使能,用户只需要控制设备的使能/禁能即可。
12.3.6 硬件设备的父总线设备
对于PCF85063,其父总线类型为:
AWBL_BUSID_I²C,即PCF85063挂在某一I²C总线上,显然,I²C总线需要由I²C总线控制器设备产生,比如在i.MX28x中,片上外设I²C0和I²C1均可以产生I²C总线。
这也就意味着,要使用PCF85063设备,除使能PCF85063设备本身外,还必须使能其父总线对应的设备。如在i.MX28x中,I²C0和I²C1设备对应的使能宏在aw_prj_params.h文件中定义为:
基于此,若PCF85063挂在I²C0上,则必须使能AW_DEV_IMX28_I²C_0宏。若挂在I²C1上,则必须使能AW_DEV_IMX28_I²C_1宏。
在i.MX28x中,I²C设备又挂在PLB总线上,PLB总线作为CPU本地总线,不需要额外使能,始终有效。特别地,若父总线设备又挂在另外一条总线上,而不是PLB总线上,则相应的父总线设备对应的控制器同样需要使能,以此类推,确保所有父总线设备均被使能。
例如,在图12.1(b)所示的结构图中,若需要使用SC16IS752设备,则必须使能SC16IS752设备的父总线设备:SC18IS602B设备,同时,还需使能SC18IS602B设备的父总线设备:I²C0设备。
12.4 访问设备
若系统硬件资源定义正确,并且所需的驱动也注册到了系统中,则可以通过AWorks定义的通用接口访问这些硬件设备。
12.4.1 通用接口
AWorks 为每一类设备都定义了一套精简强大的通用接口,不同的平台、不同的硬件,只要是通用接口支持的类型,都可以使用通用接口进行访问。例如,使用RTC通用接口访问RTC设备,使用GPIO通用接口访问GPIO设备,使用LED通用接口访问LED。
无论硬件设备挂在何种总线上,处在AWbus-lite拓扑结构中的何种位置,对同一类硬件设备,均可使用相同的接口对它们进行访问。例如,在一个基于i.MX28x的系统中,使用了两个RTC设备:i.MX28x 片上RTC外设,外围器件PCF85063。它们的编号分别为0、1,使用通用接口对它们进行访问的示意图详见图12.5。
图12.5 使用RTC通用接口访问RTC设备
由此可见,尽管它们处于不同的总线上,但却可以使用相同的接口进行操作。对应用程序来说,硬件设备的具体位置并不会对应用程序产生任何影响。这就将硬件底层和应用层进行了很好的隔离,后续即使将PCF85063更换为其它RTC器件(例如,RX8025T、DS1302等),应用程序也不需要做任何改动。
再以串口为例,查看一种更加复杂的拓扑结构,示意图详见图12.6。
图12.6 使用RTC通用接口访问RTC设备
在图12.6中,SC16IS752是一种SPI转两路UART芯片。这里仅作为访问UART设备的一种示例,以便于用户理解,用户无需深入了解这款芯片,仅需知道SC16IS752是一种SPI转串口芯片即可。
在图12.6中,总共有5个串口:MCU片内有1个串口,两片SC16IS752外扩了4个串口,它们的串口号分别为COM0、COM1、COM2、COM3和COM4。在实际硬件连接中,访问SC16IS752芯片需要经过PLB总线、I²C总线和SPI总线,进而使用其中的UART功能,但对于用户来讲,同样只需要简单的调用串行通用接口即可使用SC16IS752芯片提供的串口功能,和使用片内的UART外设并无区别。
再如,每个MCU都具有一定数量的GPIO,但是,当GPIO不够用时,可能需要通过外围器件对GPIO进行扩展,示意图详见图12.7。
图12.7 使用GPIO通用接口访问GPIO设备
在图12.7中,总共有两个GPIO设备:
-
MCU片内GPIO,引脚编号范围:
PIO0_0~PIO6_24;
-
外扩芯片CAT9555,引脚编号范围:
EXPIO0_0~EXPIO0_7、
EXPIO1_0~EXPIO1_7。
它们同样可以使用相同的接口进行访问。
12.4.2 资源ID
在前面的例子中,一个系统中可能存在多个同类设备,它们之间使用“资源ID”进行区分,通用接口则使用“资源ID”指定要访问的设备。
通常情况下,“资源ID”为int类型的整数,并从0开始顺序编号。为了便于管理以及增强程序的可读性,通常将这些资源ID定义为宏,通过宏名体现其真实的含义。例如,在i.MX28x的I²C0配置文件awbl_hwconf_imx28_i2c0.h中,定义了I²C0设备的设备信息,详见程序清单12.17。
程序清单12.17 I²C0设备信息配置(awbl_hwconf_imx28_i2c0.h)
在设备信息中,IMX28_I²C0_BUSID即为I²C0总线的ID宏,默认情况下,该宏在aw_prj_param.h文件中定义为0,详见程序清单12.18。
程序清单12.18 I²C0设备对应的资源ID宏定义(aw_prj_param.h)
后续要修改I²C0的ID,仅需修改该宏的值即可。
需要注意的是,“资源ID”的类型并不局限于int类型,只要用于区分同种类型下的多个设备,都可以视为一种“资源ID”,可以是指针类型,字符串类型等等。
在同一个系统中,某类设备的资源ID必须统一分配,某一资源ID不能被重复分配至多个设备,确保每个设备资源ID的唯一性。例如,在i.MX28x的GPIO配置文件awbl_hwconf_imx28_gpio.h中,定义了GPIO设备信息,详见程序清单12.19。
程序清单12.19 GPIO设备信息配置(awbl_hwconf_imx28_gpio.h)
其中,PIO0_0 ~ PIO6_24为GPIO资源ID宏,它们的定义详见程序清单12.20。
程序清单12.20 GPIO设备资源ID宏定义(imx28x_pin.h)
由此可见,PIO0_0的值为0,PIO6_24的值为216,因此,i.MX28x的片上GPIO占用的资源ID范围为:0 ~ 216。此时,若使用扩展芯片(比如:CAT9555)对GPIO进行了扩展,则为扩展芯片分配的资源ID范围就必须大于216(不含),以避免范围重叠。
-
mcu
+关注
关注
146文章
16984浏览量
350264 -
总线
+关注
关注
10文章
2866浏览量
87976 -
AWorks
+关注
关注
1文章
16浏览量
5685
原文标题:AWorks软件篇 — AWBus-lite 总线框架
文章出处:【微信号:ZLG_zhiyuan,微信公众号:ZLG致远电子】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论