基于定时器、RTC、WDT本质上均是计数器的共性,本次将这三种通用外设统一为TIM。以TIM为例,来展示如何开发通用驱动外设代码。对于AMetal所提供的标准层驱动文件,均存放于ametal\interface路径下。
如下图所示,开发通用外设驱动主要包含以下步骤:了解通用外设标准接口层、外设硬件层开发、外设驱动层开发、外设用户配置文件开发、外设例程文件开发。
了解通用外设标准层
1、通用外设标准接口相关类型定义
以WDT为例,如下所示为WDT的标准接口文件中对每个结构体和handle的详细介绍。
以此类推,对于定时器和RTC,其标准接口文件中均定义了驱动函数结构体、标准服务结构体和外设标准服务操作句柄。
struct am_xxx_drv_funcs结构体
该驱动函数结构体表明了驱动层应该提供对应的函数;
typedef struct am_xxx_serv结构体
该标准服务结构体定义了标准的通用外设服务,从而包含了需要驱动层为标准接口层提供的全部内容。驱动层就只需定义这样一个结构体变量,然后赋好相应的值,再以某种方式提供给标准接口层即可。
am_xxx_handle_t的定义
这是一个标准的操作句柄,本质上就是标准服务结构体指针类型,驱动层的初始化函数需要返回该类型的handle给用户。当用户在使用标准接口层函数时,就可以将获取到的handle传递给标准层。那么,标准接口层就可以通过该handle访问到驱动层提供的函数了。
2、标准接口函数
以WDT为例,如下所示为WDT标准接口函数,通过内联函数来实现。这些函数就只是简单地调用驱动层提供的函数,本身并没有做什么事情。每个函数都有对应详细的注释,传入参数和返回值。从中可以看到,在调用驱动层提供的函数时,就是将外设标准服务操作句柄(本质上为标准服务结构体)中的p_drv成员作为第一个参数传递。
外设HW层开发
HW 层对应到具体的外设,其提供的API基本上是直接操作寄存器的内联函数,效率最高,内联函数直接定义在.h 文件中。根据芯片手册,来添加外设的寄存器列表;并编写寄存器相关操作的内联函数。以某款芯片的WDT为例,如下所示为WDT的寄存器列表,从而来明确各个寄存器的功能。
根据寄存器列表,了解了各个寄存器需要配置的各项功能和其他寄存器位该如何配合等。如下所示为WDT寄存器结构体定义。
接下来需要编写每个寄存器的功能操作函数即可完成外设硬件层的开发。以WDT的控制寄存器cr为例,来编写该寄存器的硬件层函数接口,如下所示:
对于定时器、RTC的硬件层驱动开发亦是通过芯片手册来编写寄存器操作函数来完成驱动。
外设驱动层开发
1、定义设备信息结构体和设备结构体
在AMetal中,每个设备都应该有与之对应的设备结构体和设备信息结构体。设备结构体主要用于内存分配,与设备相关的变量都应该定义在设备结构体中。设备信息结构体主要包含该设备的一些相关信息。
2、驱动函数实现
驱动函数主要包括两部分:提供给标准层的驱动函数和初始化、解初始化函数。
以WDT为例,如下所示为WDT外设的驱动层应该给标准接口层提供的函数,按照芯片手册中对应操作说明来完成看门狗的驱动层函数。
如下所示为WDT初始化函数和解初始化函数;初始化函数主要是为了初始化设备中的标准服务和硬件相关设置;解初始化函数是为了释放内存资源和硬件资源。
对于定时器和RTC的驱动层开发,其大致流程亦是如此。
外设用户配置文件开发
开发完驱动层我们知道,用户使用一个外设的过程是,先调用驱动初始化函数,该函数返回一个handle,后续的所有操作,用户直接使用该handle作为参数调用标准接口层函数即可。
以某款芯片的 WDT为例,如下所示为WDT的用户配置文件,主要包含设备信息结构体、设备实例结构体及其平台初始化函数与解初始化函数。定义好变量和函数后,在头文件中添加函数声明。用户在使用时,只需调用外设实例初始化函数,并保存其返回的handle,后续直接使用该handle作为标准接口的第一个参数来调用标准接口函数即可。
对于定时器和RTC的用户配置文件,配置其对应的设备信息,添加平台初始化函数与解初始化函数即可。
外设例程文件开发
外设的例程文件主要分为HW层示例和STD示例。
对于STD示例,调用标准层函数和实例初始化函数返回的handle作为参数传入,来实现外设功能。
对于HW示例,可参考驱动层函数来添加硬件层示例功能函数,最终实现外设功能。
至此,我们完成了一个通用外设驱动的开发。
来源:立功科技
全部0条评论
快来发表一下你的评论吧 !