驱动模型 从底层驱动到HAL到JNI到app到云端服务器

本文介绍了如何通过手机APP实现对硬件设备的云端控制。首先,硬件原理图中蜂鸣器连接到GPD0_1管脚,通过驱动和HAL层进行控制。接着,JNI层实现Java和C++的交互,使得APP可以调用底层驱动。在APP端,通过二维码扫描将指令发送到云端服务器,服务器再将命令发送回硬件端,完成远程控制。整个流程涉及Android应用开发、物联网通信和底层驱动技术。
摘要由CSDN通过智能技术生成
app通过二维码开关扫描请求云服务器对蜂鸣器的开或关
        概述:arm端建立服务与云端连接等待云服务器的命令,手机扫描二维码通过二维码里面的设备号和开或者关信息发送到云端服务器,云端服务器根据设备号找到对应的arm端发送相应的开或关命令,从而实现手机APP云端控制
1.硬件原理图  
蜂鸣器连接(GPD0_1)管脚
2.芯片手册
蜂鸣器的控制地址为 int id = 0xe02000a0;
配置为输出端口 (*(int *)id)&(~(0xf<<4)); (*(int *)id)&(0x1<<4);
蜂鸣器数据地址为 int add = 0xe02000a4;
蜂鸣器启动  (*(int *) add )|(0x1<<1));
蜂鸣器停止 (*(int *) add )&(~(0x1<<1));


3.编写驱动
          buzz_drv.c代码编写
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h> /* for class_create() and device_create() */
#include <linux/cdev.h> /* for cdev */
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/io.h>
static int num = 1;
static int major = 0;
struct buzz_cdev {
struct cdev cdev;
struct class *buzz_class;
struct device *buzz_device;
//...
int buzz_val;
};
struct buzz_cdev *buzz_dev =NULL;
/* buzz 控制寄存器的物理地址*/
#define BUZZ_PHY_GPC0BASE 0xe02000a0
/*(GPD0_1)管脚 所有为8 一个int4位*/
#define BUZZ_PHY_GPC0LEN 8
/* buzz 控制寄存器的虚拟地址 */
volatile unsigned long *gpd0con =NULL;
volatile unsigned long *gpd0dat = NULL;
/*打开外设 */
static int buzz_open (struct inode *inode, struct file *file)
{
//外设的初始化
gpd0con = ioremap(BUZZ_PHY_GPC0BASE, BUZZ_PHY_GPC0LEN);
if(!gpd0con){
printk(KERN_ERR "ioremap buzz physical address failed.!\n");
return -ENOMEM;
}
gpd0dat = gpd0con +1; //指针+1,表示4个字节 dpd0_1管脚
/*将GPd0_1配置成输出功能 */
*gpd0con = *gpd0con & ~(0xff<<4);
*gpd0con = *gpd0con & (0x1<<4);
return 0;
}
static ssize_t buzz_read (struct file * file, char __user *buf, size_t count, loff_t *offsize)
{
printk("func: %s() line: %d\n", __func__, __LINE__);
return count;
}
static ssize_t buzz_write(struct file *file, const char __user *buf,
size_t bytes, loff_t *off)
{
int ker_val, ret=-1;
ret = copy_from_user(&ker_val, buf, sizeof(int));
if(ret < 0) {
printk("buzz_write() failed!\n");
goto out;
}
if(ker_val == 1) { //打开蜂鸣器
*gpd0dat |= 1<<1;
} else { //关闭蜂鸣器
*gpd0dat &= ~(1<<1);
}
return bytes;
out:
return ret;
}
static int buzz_close(struct inode * inode, struct file * file)
{
// *gpd0dat &= ~(1<<1); //关闭蜂鸣器
iounmap(gpd0con);
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE, /* 模块的自动计数 */
.open = buzz_open,
.read = buzz_read,
.write = buzz_write,
.release = buzz_close,
};
static int buzz_setup_cdev(void)
{
int err, devno = MKDEV(major,0);
/* 初始化cdev*/
cdev_init(&buzz_dev->cdev,&fops);
buzz_dev->cdev.owner = THIS_MODULE;
buzz_dev->cdev.ops = &fops;
/* 向系统注册*/
err = cdev_add(&buzz_dev->cdev, devno, 1);
if(err < 0) {
printk(KERN_ERR "Added cdev device failed.\n");
return err;
}
return 0;
}
static int __init buzz_init(void)
{
dev_t devno = MKDEV(major, 0);
int ret = -1;
buzz_dev = (struct buzz_cdev *)kmalloc(sizeof(struct buzz_cdev), GFP_KERNEL);
if(!buzz_dev) {
ret = -ENOMEM;
goto out_err_0;
}
/* 向系统申明占用设备号或让系统自动分配设备号*/
if(major) {
ret = register_chrdev_region(devno, 1, "buzz");
} else {
ret = alloc_chrdev_region(&devno,0,1,"buzz");
major = MAJOR(devno);
}
if(ret < 0) {
printk(KERN_ERR "register chrdev device number failed\n");
goto out_err_1;
}
ret = buzz_setup_cdev();
if( ret < 0) {
goto out_err_2;
}
/* 自动创建设备节点*/
buzz_dev->buzz_class = class_create(THIS_MODULE, "buzz_class");
if(IS_ERR(buzz_dev->buzz_class)) {
printk("class_create() failed");
goto out_err_3;
}
buzz_dev->buzz_device = device_create(buzz_dev->buzz_class, NULL,
MKDEV(major, 0), NULL, "buzz"); //正常情况下系统会自动创建/dev/buzz
if(IS_ERR(buzz_dev->buzz_device)) {
printk("device_create() failed");
goto out_err_4;
}
printk("buzz driver has installed.\n");
/* 正常返回*/
return 0;
out_err_4:
class_destroy(buzz_dev->buzz_class);
out_err_3:
cdev_del(&buzz_dev->cdev);
out_err_2:
unregister_chrdev_region(MKDEV(major, 0),1);
out_err_1:
kfree(buzz_dev);
out_err_0:
return ret;
}
static void __exit buzz_exit(void)
{
device_destroy(buzz_dev->buzz_class,MKDEV(major, 0));
class_destroy(buzz_dev->buzz_class);
cdev_del(&buzz_dev->cdev);
unregister_chrdev_region(MKDEV(major, 0),1);
return;
}
module_param(num, int, S_IRWXU);
module_init(buzz_init); /* 驱动的入口*/
module_exit(buzz_exit); /* 驱动的出口*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("buzz@farsight.com.cn");
MODULE_DESCRIPTION("This is cdev demo driver");
         Makefile编写

ifeq ($(KERNELRELEASE),)
KERNELDIR = /home/george/src_210/linux-3.0.8-FS210
PWD =$(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.so *.o *.ko .tmp_versions *.mod.c *.order *.symvers
else
obj-m :=buzz_drv.o
endif

创建自己的sh文件如infrare.sh:                                                                                        # ! /system/bin/sh
           insmod /device.ko                                                                                                              insmod /control.ko                                                                                                              mknod /dev/controler c 240 0
修改init.rc最后写入自己的脚本                                                                                            service infrare /system/bin/sh /data/infrare.sh                                                                               user root                                                                                                                             soneshot
这样就可以使用自己的驱动了另外在init.rc中的总结init中可以执行insmod命令但是不能执行mknod的,解释是这样的init.rc里所有可用的command都定义在system/core/init/keyword.h里,默认是不包含mknod的。事实上,Android的init进程会通过kenel的uevent来自动创建设备节点(见system/core/init/devices.c里的make_device()函数)。


4.硬件抽象层
         buzz_hal.h
#ifndef __BUZZ_HAL_H__
#define __BUZZ_HAL_H__
#include <hardware/hardware.h>
#define BUZZ_HAL_MODULE_ID "buzz_hal"
//扩展device对象和module对象
struct buzz_hw_module_t{ //自由定义
//继承父类
struct hw_module_t common; //一定要在第一个位置,必须叫做common
//进行扩展--可选的
//char *name ;
//void (*test)();
};
struct buzz_hw_device_t{
//继承父类
struct hw_device_t common; //一定要在第一个位置,必须叫做common
//进行扩展--可选的
int (*open)(void);
int (*switch_on)(int on);
};
#endif
         buzz_hal.c


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "buzz_hal.h"
#define LOG_TAG "buzz_hal_log"
#include <utils/Log.h>
static int buzz_fd = -1;
//去操作硬件
int buzz_hal_device_close(struct hw_device_t* device)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
if(device != NULL)
{
free(device);
}
close(buzz_fd);
return 0;
}
int buzz_hal_device_open(void)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
buzz_fd = open("/dev/buzz", O_RDWR);
if(buzz_fd < 0)
{
LOGE("open buzz : %s\n", strerror(errno));
return -1;
}
return 0;
}
int buzz_hal_device_switch(int on)
{
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值