Android驱动程序开发实例精讲-0_Android系统HAL驱动开发经典案例详解(基于Android4.0)

本文详细介绍了基于Android 4.0的LED驱动开发,涵盖从架构分析到驱动程序、HAL硬件抽象层、JNI/Service服务层以及APP应用程序层的全过程。通过LED点灯功能,阐述了Linux驱动、HAL接口、JNI调用和Android应用程序的交互。内容包括驱动程序的编写、HAL层源码分析、JNI服务层代码及APP界面设计,旨在帮助读者理解Android HAL架构和驱动开发原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android系统HAL驱动开发经典案例详解(基于Android4.0)

 

目的:通过学习一个LED点灯的简单功能,掌握Linux驱动程序与HAL硬件抽象层之间的调用方法,同时掌握JNI层的编写思想,学会使用Eclipse编写Android应用程序,深入体会Android HAL架构。本章内容主要参考文献:《Android深度探索(卷1) HAL与驱动开发》、《TQ210开发板Android_HAL_LED_V1.2.pdf》

目录:

一、架构分析

1.1 功能介绍

1.2 HAL架构

1.3 接口定义

二、驱动程序

2.1 驱动功能简介

2.2 驱动源码分析

2.3 利用可执行文件测试驱动

2.3.1 源文件

2.3.2 利用交叉编译器编译

2.3.3 使用原生C程序测试驱动

三、HAL硬件抽象层

3.1 HAL简介

3.2 HAL层源码与分析

3.3 HAL源码编译

四、Jni/Service服务层

4.1 直接使用JNI调用驱动程序

4.2 JNI/Service程序代码

五、APP应用程序层

5.1 activity_main.xml

5.2 LedServer.java

5.3 MainActivity.java

 

一、架构分析

1.1 功能介绍

Linux版本:3.0.8

Android版本:4.0

开发板:FriendlyARM smart210

功能介绍:应用程序界面如下图所示,为求方便,截图来自模拟器,实际开发板界面和下图是一样的。CheckBox复选框分别对应开发板上四个LED灯,选中复选框,按动led_hal_jni按键后,相应LED就会亮起来。功能很简单,代码中几乎不会涉及任何逻辑算法,主要是为了方便理清整个程序架构,体会Android系统通过HAL硬件抽象层与实际硬件之间交互的编程思想。

 

 

1.2 HAL架构

想要点亮一个灯当然简单,可以直接烧写ARM裸机程序,也可以在跑Linux系统的板子上通过写/dev/leds这样的设备文件来达到目的。Android系统为了解决一些调用接口和版权方面的问题提出了一个HAL架构。目前最新的HAL架构是下面这个样子的。

 

 

可以看出,Android应用程序直接调用的是JNI或者Service程序库文件(.so),程序库文件是通过一个ID来定位到相应的HAL的库文件(.so),最终和硬件打交道的是HAL模块。需要注意的是,HAL及其以上层均属于应用程序范畴,也就是都运行在了用户空间,只有Linux驱动程序运行在了Linux内核空间。

 

1.3 接口定义

 

从Android HAL架构来看,一套完整的点灯的程序应该包括四个层次。为了方便程序维护,层与层之间应该尽可能的降低耦合程度,每个层对其他层开放的仅仅是一个操作接口即可。每个层的源文件位置和其向其他层提供的关键接口表述如下,这里指的关键接口实际上就是“调用函数”。各个源文件的具体内容会在下文给出。如果你能亲自动手写完整套程序再回过头来看这部分接口定义,应该能体会得更深些。

1、底层驱动。

源文件位置:$(linux_source)/drivers/char/mini210_led.c    

对应开发板上的驱动设备文件为:/dev/leds

关键接口定义:

//发送IO命令

ioctl(file_handler, cmd, arg);

//调用方法如下

./ioctl_test /dev/leds 1 2   //表示点亮第二盏灯

//发送写命令

write(fd,buf,strlen(buf));

//调用方法如下

./write_test /dev/s3c6410_leds "1111" // 点亮所有灯

这里的ioctl_test和write_test是两个可执行文件,它们分别是由ioctl_test.c和write_test.c源文件通过交叉编译器或Android原生代码编译出来的,这两个源文件是为了验证驱动程序专门写的,后文会贴出具体代码。

 

2、HAL层。

源文件位置:

//这个.c文件也可以放到其他目录

$(Android_source)/device/friendly-arm/mini210/libled/led_hal.c 

//这个.h文件最好放到指定位置,以免包含头文件的时候发生错误

$(Android_source)/hardware/libhardware/include/hardware/led_hal.h

生成模块位置:Android_source/out/target/product/mini210/lib/hw/led_hal.default.so

关键接口定义:

int led_on(struct led_control_device_t *dev, int32_t LED_NUMBER)  //表示LED_NUMBER灯亮

{

... ...

ioctl(fd,IOCTL_GPIO_ON,LED_NUMBER);

... ...

}

int led_off(struct led_control_device *dev, int32_t LED_NUMBER)   //表示LED_NUMBER灯灭

{

... ...

ioctl(fd,IOCTL_GPIO_OFF,LED_NUMBER);

... ...

}

 

3、jni/service层

源文件位置:$(Android_source)/packages/apps/led/jni/LedHalService.cpp

生成模块位置:Android_source/out/target/product/mini210/lib/libled_hal_jni.so

关键接口定义:

jboolean Java_com_example_leds_MainActivity_ledSetOn (JNIEnv* env, jobject obj,jint number)

{

... ...

return sLedDevice->set_on(sLedDevice,number);

... ...

}

jboolean Java_com_example_leds_MainActivity_ledSetOff (JNIEnv* env, jobject obj,jint number)

{

... ...

return sLedDevice->set_off(sLedDevice,number);

... ...

}

类名定义:

//注意这里的kClassName决定了调用该JNI模块的应用程序的包名与类名。

int register_android_server_LedService(JNIEnv *env)

{

... ...

static const char* const kClassName = "com/example/leds/LedService";

... ...

}

 

二、驱动程序

2.1 驱动功能简介

mini210_led.c主要提供了mini210_leds_ioctl和mini210_leds_write两个接口。应用程序通过向/dev/leds发送I/O指令或写命令就可以实现控制LED灯的功能了。

2.2 驱动源码分析

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/miscdevice.h>

#include <linux/fs.h>

#include <linux/types.h>

#include <linux/moduleparam.h>

#include &l
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值