SPI模块的HAL访问Linux内核驱动程序

1、在hardware/libhardware/modules下创建spihal文件夹。

2、在spihal中创建spihal.c、Android.mk文件。

spihal.c

#define	LOG_TAG "SpiStub"
#include <hardware/hardware.h>
#include <hardware/spihal.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include "spidev.h"

#define	DEVICE_NAME "/dev/spidev1.0"
#define	MODULE_NAME "spidev1.0"
#define	MODULE_AUTHOR "HSL"

/* 函数声明 */
static int hal_spi_init(struct spi_device_t *dev);
static int hal_spi_read(struct spi_device_t *dev, unsigned char *data, int size);
static int hal_spi_write(struct spi_device_t *dev, unsigned char *data, int size);
static int hal_spi_open(const struct hw_module_t *module, char const *name, struct hw_device_t **device);
static int hal_spi_close(struct hw_device_t *device);

/* 定义变量 */
static uint8_t mode = 0;
static uint8_t bits = 8;
static uint32_t speed = 600*1000;
static uint16_t delay = 0;
struct spi_ioc_transfer spi_tr;

/* 定义初始化spi */
static int hal_spi_init(struct spi_device_t *dev)
{
	/* mode */
	if(ioctl(dev->fd, SPI_IOC_WR_MODE, &mode) < 0)
	{
		ALOGE("SpiStub: SPI wr_mode error\n");
	}
	else
		ALOGE("SpiStub: SPI wr_mode ok\n");
	
	if(ioctl(dev->fd, SPI_IOC_RD_MODE, &mode) < 0)
	{
		ALOGE("SpiStub: SPI rd_mode error\n");
	}
	else
		ALOGE("SpiStub: SPI rd_mode ok\n");
	
	/* bits */
	if(ioctl(dev->fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0)
	{
		ALOGE("SpiStub: SPI wr_bits_per_word error\n");
	}
	else
		ALOGE("SpiStub: SPI wr_bit_per_word ok\n");

	if(ioctl(dev->fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0)
	{
		ALOGE("SpiStub: SPI rd_bit_per_word error\n");
	}
	else
		ALOGE("SpiStub: SPI rd_bit_per_word ok\n");

	/* speed */
	if(ioctl(dev->fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
	{
		ALOGE("SpiStub: SPI wr_max_speed_hz error\n");
	}
	else
		ALOGE("SpiStub: SPI wr_max_speed_hz ok\n");

	if(ioctl(dev->fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0)
	{
		ALOGE("SpiStub: SPI rd_max_speed_hz error\n");
	}
	else
		ALOGE("SpiStub: SPI rd_max_speed_hz ok\n");

	return 0;
}
/* 定义spi读函数 */
static int hal_spi_read(struct spi_device_t *dev, unsigned char *data, int size)
{
	spi_tr.rx_buf = (unsigned long)data;
	spi_tr.len = size;
	spi_tr.delay_usecs = delay;
	
	if((ioctl(dev->fd, SPI_IOC_MESSAGE(1), &spi_tr)) < 0)
	{
		ALOGE("SpiStub: SPI read  error!\n");
		return -1;
	}
	return 0;
}
/* 定义spi写函数 */
static int hal_spi_write(struct spi_device_t *dev, unsigned char *data, int size)
{
	spi_tr.tx_buf = (unsigned long)data;
	spi_tr.len = size;
	spi_tr.delay_usecs = delay;

	if((ioctl(dev->fd, SPI_IOC_MESSAGE(1), &spi_tr)) < 1)
	{
		ALOGE("SpiStub: SPI write error!\n");
		return -1;
	}
	return 0;
}
/* 定义spi设备打开函数 */
static int hal_spi_open(const struct hw_module_t *module, char const *name, struct hw_device_t **device)
{
	struct spi_device_t *dev;
	dev = (struct spi_device_t *)malloc(sizeof(struct spi_device_t));
	if(!dev)
	{
		ALOGE("SpiStub: failed malloc space!\n");
		return -1;
	}
	memset(dev, 0, sizeof(struct spi_device_t));

	dev->common.tag = HARDWARE_DEVICE_TAG;
	dev->common.version = 0;
	dev->common.module = (struct hw_module_t *)module;
	dev->common.close = hal_spi_close;

	dev->spi_init = hal_spi_init;
	dev->spi_read = hal_spi_read;
	dev->spi_write = hal_spi_write;
	if((dev->fd = open(DEVICE_NAME, O_RDWR | O_NONBLOCK)) < 0)
	{
		ALOGE("SpiStub: failed spi open .\n");
		free(dev);
		return -1;
	}
	ALOGE("SpiStub: open /dev/spi1.0 successfuly .\n");
	
	*device = &(dev->common);

	return 0;
}
/* 定义spi设备关闭函数 */
static int hal_spi_close(struct hw_device_t *device)
{
	struct spi_device_t *dev = (struct spi_device_t *)device;
	if(dev)
	{
		ALOGE("SpiStub: close /dev/spi1.0\n");
		close(dev->fd);
		free(dev);
	}
	return 0;
}
/* 模块方法表 */
static struct hw_module_methods_t spi_module_methods =
{
	open:hal_spi_open
};
/* 模块实例变量 */
struct spi_module_t HAL_MODULE_INFO_SYM =
{
	common:
	{
		.tag = HARDWARE_MODULE_TAG,
		.version_major = 1,
		.version_minor = 0,
		.id = SPI_HARDWARE_MODULE_ID,
		.name = MODULE_NAME,
		.author = MODULE_AUTHOR,
		.methods = &spi_module_methods,
	}
};

<pre class="html" name="code">

Android.mk

 LOCAL_PATH := $(call my-dir)
      include $(CLEAR_VARS)
      LOCAL_MODULE_TAGS := optional
      LOCAL_PRELINK_MODULE := false
      LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
      LOCAL_SHARED_LIBRARIES := liblog
      LOCAL_SRC_FILES := spihal.c
      LOCAL_MODULE := spi_ts.default
      include $(BUILD_SHARED_LIBRARY)

3、把源码kernel_imx/drivers/spi下spidev.c文件复制到自己创建spihal文件夹下以便调用。

4、在hardware/libhardware/include/hardware目录下创建spihal.h文件

spihal.h

#ifndef __SPIHAL_H__
#define	__SPIHAL_H__

#include <hardware/hardware.h>
#include <fcntl.h>
#include <errno.h>

__BEGIN_DECLS

/* 定义模块ID */
#define	SPI_HARDWARE_MODULE_ID "spi_ts"
/* 在HAL层规定不能直接使用hw_module_t结构体,因此做一个封装 */
struct spi_module_t
{
	struct hw_module_t common;
};

/* 定义一个spi控制结构体 */
struct spi_device_t
{
	struct hw_device_t common;
	int fd;//设备文件描述符
	int (*spi_init)(struct spi_device_t *dev);//spi初始化
	int (*spi_read)(struct spi_device_t *dev,unsigned char *data, int size);//从spi里读数据
	int (*spi_write)(struct spi_device_t *dev,unsigned char *data, int size);//往spi里发数据
};

__END_DECLS

#endif

5、在源码主目录下编译

      执行命令:mmm  hardware/libhardware/include/hardware/spihal

6、把生成的该库放到开发板的/system/lib/hw目录下

     加执行权限 chown root spi_ts.default.so

                       chmod 777 spi_ts.default.so

注意:在Android.mk中生成的库名字(LOCAL_MODULE := spi_ts.default)一定要和模块ID相对应(#define SPI_HARDWARE_MODULE_ID "spi_ts")否则在运行的时候JNI层无法访问HAL层的库    

 

你可能感兴趣的:(linux,android,C语言,ARM,hal)