单片机
返回首页

TQ210搭载Android4.0.3系统构建之LED从驱动到HAL到JNI到应用程序(HAL篇)

2025-02-14 来源:cnblogs

开发板:TQ210


OS:Android 4.0.3


以下所有内容都是在TQ210开发板上实现,并且很多内容也是天嵌公司提供,我将一些内容进行了删减、替换,然后加入了一些自己的理解,同时也是记录自己学习的旅程。


HAL层头文件  放在hardware/libhardware/include/hardware/目录下


led_unders_led_hal.h


#ifndef ANDROID_LED_UNDERS_H    //保证头文件只被加载一次

#define ANDROID_LED_UNDERS_H


#include   //包含hw_module_t hw_device_t hw_module_methods_t...

#include   // 包含int long...

#include //包含__begin_decls


__BEGIN_DECLS  //按照C语言的方式编译和连接

#define LED_UNDERS_HARDWARE_MODULE_ID 'led_unders'  //led_unders模块ID


struct led_module_t   //led模块类型 ,继承hw_module_t

{

struct hw_module_t common;

};


struct led_control_device_t  //led设备类型,继承hw_device_t

{

struct hw_device_t common;

int (*led_on)(struct led_control_device_t *dev,int32_t number);  //打开led

int (*led_off)(struct led_control_device_t *dev,int32_t number);//关闭led

};


__END_DECLS


#endif




led_unders_led_hal.c


#include

#include

#include //包含malloc memset...

#include //包含__android_log_print


#include

#include


#define DEV_FILE_NAME  '/dev/led_unders'   //设备文件名

#define IOCTL_GPIO_ON 1   //打开LED

#define IOCTL_GPIO_OFF 0 //关闭LED


static int fd=-1;  //文件操作符


static int open_led()  //打开LED

{

fd=open(DEV_FILE_NAME,O_RDWR);

if(fd<0)

{

__android_log_print(ANDROID_LOG_DEBUG,'msg','open_led failed.n');

return -1;

}

__android_log_print(ANDROID_LOG_DEBUG,'msg','open_led success.n');

return 0;

}


static int close_led(struct hw_device_t *device) //关闭LED

{

if(fd!=-1)

{

close(fd);

fd=-1;

if(device) free(device);

}

return 0;


}



static int led_on(struct led_control_device_t *dev,int32_t number)  //点亮LED

{

if(fd==-1) return -1;

return ioctl(fd,IOCTL_GPIO_ON,number);

}


static int led_off(struct led_control_device_t *dev,int32_t number) //关闭LED

{

if(fd==-1) return -1;

return ioctl(fd,IOCTL_GPIO_OFF,number);

}


//led初始化函数

static int led_init(const struct hw_module_t *module,const char *name,struct hw_device_t **device)

{

struct led_control_device_t *dev;  //定义led设备指针

dev=(struct led_control_device_t *)malloc(sizeof(struct led_control_device_t)); //分配内存地址空间

if(dev==NULL) 

{

__android_log_print(ANDROID_LOG_DEBUG,'msg','malloc failed.n');

return 0;

}

memset(dev,0,sizeof(*dev)); //将内存块初始化为0

dev->common.tag=HARDWARE_DEVICE_TAG;  //设备标志,由HWDT组成

dev->common.version=0;  //设备版本

dev->common.module=module; //指向设备所属于的模块

dev->common.close=(int (*)(struct hw_device_t *))close_led; //关闭函数


*device=(struct hw_device_t *)&dev->common;   //指向设备

dev->led_on=led_on;   //操作函数赋值

dev->led_off=led_off;


if(open_led()==-1) //打开led设备

{

free(dev);

dev=NULL;

return -1;

}

return 0;

}



static struct hw_module_methods_t  led_module_methods= //模块拥有的打开方法

{

open:led_init

};



const struct led_module_t HAL_MODULE_INFO_SYM=  //HAL_MODULE_INFO_SYM名称不能修改,用于导出的HMI找到模块,相当于模块的入口

{

common:

{

tag:HARDWARE_MODULE_TAG, //在hardware.h中定义的,由HWMT组成

version_major:1,   //模块主版本号

version_minor:0,  //模块次版本号

id:LED_UNDERS_HARDWARE_MODULE_ID,  //模块id,用于构成模块全名

name:'led_unders stub',   //模块名称

author:'undergrowth',   //模块作者

methods:&led_module_methods,   //模块所拥有的方法

       }

};

 

Android.mk


LOCAL_PATH :=$(call my-dir)

include $(CLEAR_VARS)

LOCAL_PRELINK_MODULE :=false

LOCAL_SRC_FILES :=led_unders_led_hal.c

LOCAL_SHARED_LIBRARIES :=libutils

LOCAL_MODULE :=led_unders.$(TARGET_BOARD_PLATFORM)

LOCAL_MODULE_TAGS :=optional

LOCAL_MODULE_PATH :=$(LOCAL_PATH)

include $(BUILD_SHARED_LIBRARY)


说说个人对HAL的一些理解:

HAL是GOOGLE2008年I/O大会上提出来的,目的为了硬件厂商保护他们的proprietary,当然也正是这个原因,linux的维护者才将andorid的驱动从内核中删掉,因为linux遵循GPL协议,需要完全开放源代码,而Google遵循Apache 2.0,只需提供驱动的二进制代码即可,很明显,Google没有遵守linux的协议,就被linux干掉了。


       因为之前一直在做linux下的驱动开发,个人感觉HAL和驱动的测试代码很像,不同之处在于,你需要遵循一定的规则编写你的测试代码就形成了HAL层代码,建议最好看看hardware/libhardware/hardware.c和hardware/libhardware/include/hardware/hardware.h两个文件,这个是HAL的基础,对于编写HAL层代码有很大的帮助。


      对于HAL的更多介绍 就不多说了 这位老兄写的还不错 推荐  http://blog.csdn.net/k229650014/article/details/5801397


     可能碰到的错误:


  1.


fd=open(DEV_FILE_NAME,O_RDWR);

if(fd<0)

{

__android_log_print(ANDROID_LOG_DEBUG,'msg','open_led failed.n');

return -1;

}

  调试的时候 发现open_led failed.  即打开文件失败 但是用驱动测试代码测试 设备文件是没有问题的  而是用HAL打开 就出现问题 无法打开 

 原因:权限不够


  解决方法:  添加设备文件的权限   eg: chmod 777 /dev/led_unders   即可解决


2.调试的时候 发现load:countn't find symbol hmi


 查看hardware.c源码发现 是因为hmi为空值  于是查看led_unders_led_hal.c  发现 


HAL_MODULE_INFO_SYM写成了HAL_MODULE_INFO_SYS  改过来即可


附:生成的led_unders.tq210.so文件放在/system/lib/hw/目录下


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 家用电器遥控器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外开关

  • DS1669数字电位器

  • HA1377 桥式放大器 BCL 电容 17W(汽车音频)

    相关电子头条文章