Learn lumit Step 8 : 代码可复用性
Learn lumit Step 8 :代码可复用性++++++++++++++++++++++++++++++++++++++++++++++++++++++
至此,前面大致介绍了 lumit4510 开发板上 bootloader 启动的基本知识点。
后面,我们将以板上的每一个硬件设备驱动程序为例,分析一下每个硬件驱动是如何
让硬件工作起来的。
在重写这些设备接口的过程中,我们希望能够在最大程度上将与硬件无关的代码
提供给大家,以便移植和重用;而把和硬件相关的最底层的那些实现独立出来,单独
实现为一个类似linux设备驱动的driver。这样,大家需要做的仅仅是根据你自己的
硬件设计修改最底层的接口函数,而绝大部分的上层代码都可以无需修改移植到新的
板子上。
首先,我们以 LED 灯的驱动为例,来说明这个想法。本来这个驱动是非常简单的,
甚至只用几个宏定义就能实现 LED 灯的点亮和熄灭,但在这里我们反过来,把简单的
东西复杂化,为的是建立一种结构和层次来应付更多复杂的问题。
这个项目下有 4 个和 led 相关的文件,分别是 led_driver.c[.h] led_api.c[.h]
顾名思义即可知道 led_driver 是底层的硬件相关实现代码,led_api 是提供给上层的
统一接口,与底层硬件无关。
我们从底层开始介绍 led_driver 的实现,主要是有如下五个函数:
int led_open( void );
int led_read( char * buf, int count );
int led_write( char * buf, int count );
int led_ioctl( unsigned int cmd, unsigned long arg );
int led_release( void );
其中 open, read, write, ioctl, release 是模仿了 linux 设备驱动的写法,尽量
采用了统一的接口,将设备操作虚拟为文件读写来进行。以 led_read 为例:
int led_read( char * buf, int count )
{
int i = 0;
// the count has exceeds the count of our board
if( count > 4 )
return -1;
for( i = 0; i < count; i++ )
buf = led_status;
return 0;
}
我们分析一下 led 设备的读操作,输入参数是读缓冲 buf 指针和要读的字节数 count 。
如果每次读字节数超过 4 个(led),则我们认为错误,返回 -1 ;否则我们将前面 count 个
led 的状态信息,分别写入 buf 指针中,0 表示 OFF,1 表示 ON ,并直接返回 count
表示已经成功读出 count 字节的设备数据。
同样 led 写操作也类似,即将从上层传入的 buf 信息,写入 led 对应的 led_status
内部状态标识数组中,同时修改 IO 寄存器相应位来实现对硬件的驱动,真正点亮或者熄灭
led 小灯。
这里我们还定义了 LED_NUM 表示目前只支持 4 个 led 。
但是对于上层用户来说,这样的驱动接口很不直观,也很难直接用于应用编程中。因此,
我们实现了 led_api 来对 led_driver 进行一次封装,使得 led_api 提供的接口更为直观,
具有更好的代码可读性和可移植性,这两点对于嵌入式程序来说是非常重要的。
led_api 主要实现了如下一系列接口:
int led_init( void );
/* get 4 leds status to low-4-bits of hex value */
int led_get_value( void );
/* set hex value of low-4-bits to 4 leds */
int led_set_value( int value );
int led_all_light( void );
int led_all_dark( void );
int led_all_blink( void );
int led_one_light( int position );
int led_one_dark( int position );
int led_one_blink( int position );
int led_test( void );
其中,led_init 是硬件初始化函数,实际调用的即驱动的 open 操作;led_set_value
和 led_get_value 是以 32 位整型数的每一个 bit 表示一个 led 灯,进行设置和读取的接口;
其他的 led_ 函数,主要就是点亮和熄灭以及闪烁的接口,分为全部和单个两组;在最后是一个
led_test 函数,是为了便于用户调用和理解写的一个接口测试例子,如果对 led_api 不熟悉,
就可以先用 led_test 做一下测试,看看应该如何传递参数和获得返回结果。
对于上层调用来说,使用的是抽象出来的个数为 LED_NUM 的 led 灯。它可以在实际使用中
灵活调整,底层的硬件驱动则保证了当传入的 count 超过 4 的时候,硬件驱动接口返回失败,
表示无法执行对该设备的读/写操作,原因是底层硬件不支持。
因此,当在一个新的开发板上实现 led 接口的时候,只需要对 led_driver 做改动,而无需
修改 led_api 已有的接口,可以直接重用;这样分层结构的好处是,便于为上层的复杂应用提供
更多的接口,更快地实现上层需求,同时底层共用一个统一的驱动接口,大家就可以为 led_api
增添更多的 api 来实现不同的闪烁效果,例如跑马灯等。
当每个人都为 led_api 贡献一个 api 的时候,就避免了其他人在自己系统之上再去实现这个
api 的工作,减少了大量的重复劳动,而可以把工作专注于上层的应用开发和底层的驱动接口实现。
我想,这也是 lumit 开源项目的目标之一。 版主:
Learn-lumit-Step-8是什么文件啊?怎么打不开啊? 就是一个 zip 的压缩文件,你的下载有问题,我这里下载后可以打开。
页:
[1]