驱动里调用I2c和Gpio,驱动里调用驱动

一. 简介

  • 来源:应项目需求,需将3个I2c和6个GPIO封装成一个驱动供上层应用层调用,遂有了此文。
  • 开发板:Halley2
  • Linux版本:3.10.14
  • 开发环境:Manhattan(基于君正官方提供的开发环境,很好用)。
  • 经验:说实话,这是我第一个“正经”开发的驱动。

二. 编写驱动前的准备

  • 先明确需求,3个I2c的设备地址和片上内存都为一个字节,6个Gpio分别为5输入1输出
  • 留给上层接口的选择,刚开始在read/write上琢磨,但是总觉得这样操作好啰嗦,后来受应用层操作I2c的方式的影响,就索性自定义一个结构体用ioctl来传参了,虽操作也是有点啰嗦,但能接受,Bingo。
  • 网上搜索相关资料,了解到驱动里使用I2c的一些基操,见本文最后的参考文章。

三. 头文件的编写

  • 留给上层使用的结构体,因需求的原因,一切从简,只支持单字节读写,自己可扩展
  • 一些关于器件的宏定义,由ioctl函数参数的第二个参数指定
struct sakway_msg_t{
   
	#define SAKWAY_I2C_MSG_WRITE	0
	#define SAKWAY_I2C_MSG_READ		1
	int 			rw_flag;			// 读写标志位,可由上面宏来替代
	short			chip_addr;			// 片上内存地址(默认单字节)
	unsigned char 	wmsg;				// 写入的内容
	unsigned char 	index;				// 指定获取GPIO输入状态的GPIO下标,如下表
	unsigned char *	rmsg;				// 读取的内容
};
/*	input
 *	index 		0		1		2		3		4
 *	gpio		PA04	PA12	PC24	PC25	PD02
 */
#define SAKWAY_CMD_DRV_TEMP			0	// 温度传感器	--	0x92
#define SAKWAY_CMD_DRV_MCUG			1	// 单片机G传感器	--	0x34
#define SAKWAY_CMD_DRV_MCUF			2	// 单片机F传感器	--	0x38

#define SAKWAY_CMD_GPIO_GET			3	// 获取5个Gpio的输入状态,由结构体里的rmag来得值
#define SAKWAY_CMD_GPIO_SET			4	// 设置1个Gpio的输出状态,由结构体里的wmsg来传值

四. 源文件的编写

  • 先是相关结构体的封装
#define I2C_TEMP_ADDR			0x48	// 内部温度传感器的设备地址
#define I2C_MCUG_ADDR			0x34	// GD单片机的I2c设备地址
#define I2C_MCUF_ADDR			0x38	// FM单片机的I2c设备地址

typedef struct sakway_t SAKWAY;

struct sakway_hw_t{
   
	unsigned int io_in[5];			// 输入GPIO
	unsigned int io_out;			// 输出GPIO
	unsigned int io[0];
	int i2c_id;						// 指定要操作的I2c器件
	#define SAKWAY_I2C_ID_CPLD			0u
	#define SAKWAY_I2C_ID_MCUG			1u
	#define SAKWAY_I2C_ID_MCUF			2u
	struct i2c_client *i2c_clit[3];		// 三个I2c设备
	struct i2c_adapter *i2c_adper;		// 适配器
	struct i2c_driver *i2c_drv;			// 这个没用上,可删
};

struct sakway_t{
   
	SAKWAY *this;
	struct sakway_hw_t *hw;	
	struct mutex lock;					// 锁
	unsigned int majoy_id;
};
  • I2c和Gpio的初始化,及读写分配
// I2c写操作
static int __sakway_write_reg(SAKWAY* this, short reg_addr,unsigned char reg_value){
   
	char write_buf[4];
	int status;
	struct i2c_msg msg = 
	{
   
		this->hw->i2c_clit[this->hw->i2c_id]->addr, 0, 2, write_buf
	};
	
	memset(write_buf, 0, 4);
	
	write_buf[0] = reg_addr&0x00ff;
	write_buf[1] = reg_value;
	msg.len = 2;
	
	mutex_lock(&(this->lock));
	status = i2c_transfer(this->hw->i2c_adper, &msg, 1);
	mutex_unlock(&(this->lock));
	return (status == 1)? 0 : -1;
}
// I2c读操作
static int __sakway_read_reg(SAKWAY* this, short reg_addr,unsigned char *reg_value){
   
	char buf[4];
	int status;
	struct i2c_msg msg[2] = {
   
		{
   
			this->hw->i2c_clit[this->hw->i2c_id]->addr, 0, 2, buf
		},
		{
   
			this->hw->i2c_clit[this->hw->i2c_id]->addr, I2C_M_RD, 1, reg_value
		}
	};
	memset(buf, 0, 4);
	buf[0] = reg_addr&0x00ff;
	msg[0].len = 1;
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值