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层的库