上一章节有介绍过这颗IC,是freescale的一个低精度的重力传感器吧。我认为,可以区分8个方向。x,y,z三轴。精度6bit,采样值范围[-32,+32].还有测量shake和tap等数据。
这边的驱动没有自己写.只是有看懂它原先的驱动是如何实现和工作的.
它的驱动引入了一个 hwmon device的注册。具体的作用是在sys/class/hwmon下生成了一个目录hwmonx。
它可以添加你设备的一些属性attr,以此来方便用户去read那些属性的状态。网上也有说借此来导出内核的信息非常方便,几乎所有的sensor都喜欢这样用。我们可以借用内核导出x,y,z三轴的值,来方便查看数据.介于此,我们可以添加相关的属性,当访问这些属性文件时,实则是在调用对应的接口函数。比如读相应的寄存器,再显示给用户界面。
另外一个:传感器元件,都有一个特性。周期性的采样数据并上报数据。
我们再实现触摸屏驱动的时候,当你有手触摸时,立即便会上报一次数据,否则则没有.按键也是一样。
像有的温度传感器,基本上是每次间隔一定的时间,才能采样一次准确的数据。并不是立刻就能获得数据的.需要一定的时间。
所以这边引入了一个input子系统的扩展:input_polled_dev.

我们依旧把它作为输入子系统来实现。上报x,y,z三轴的绝对坐标.

所以整个驱动的框架没变。新多出来的功能是 属性导出功能,hwmon设备的引入,和input_polled_dev的引入。

程序我都有注释过,初始化完毕后,当有触发过中断时,程序便会更新一次TILT状态寄存器。此时我们可以去读我们需要的数据。根据读到的数据做出相应的判断.比如说是否旋转屏幕。想一想手机的自动旋转功能,当我们把屏幕横着放时,画面会对应做旋转,这里面也是通过sensor来识别当前的位置,根据位置做出画面的相应调整。

常用的传感器很多很多。温度传感器,压力传感器,靠近传感器,声音传感器,加速度传感器等等。
我们今天实现的只是很小的一类中的特定一个传感器而已。

驱动实例:

/** Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* version 2 as published by the Free Software Foundation.** This program is distributed in the hope that it will be useful, but* WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU* General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA* 02110-1301 USA*/#ifndef __LINUX_MMA7660_H
#define __LINUX_MMA7660_H#include <linux/types.h>#ifdef __KERNEL__/* MMA7760 Registers */
#define MMA7660_XOUT            0x00    // 6-bit output value X
#define MMA7660_YOUT            0x01    // 6-bit output value Y
#define MMA7660_ZOUT            0x02    // 6-bit output value Z
#define MMA7660_TILT            0x03    // Tilt status
#define MMA7660_SRST            0x04    // Sampling Rate Status
#define MMA7660_SPCNT           0x05    // Sleep Count
#define MMA7660_INTSU           0x06    // Interrupt Setup
#define MMA7660_MODE            0x07    // Mode
#define MMA7660_SR              0x08    // Auto-Wake/Sleep and Debounce Filter
#define MMA7660_PDET            0x09    // Tap Detection
#define MMA7660_PD              0x0a    // Tap Debounce Countstruct mma7660_platform_data {/* eint connected to chip */int irq;/* parameters for input device */int poll_interval;int input_fuzz;int input_flat;
};#endif /* __KERNEL__ */#endif /* __LINUX_MMA7660_H */

这边因为是挂在IIC总线上,同样,IIC设备的实例化我们还是按照老方法来做:

static struct mma7660_platform_data mma7660_pdata = {.irq            = IRQ_EINT(11),.poll_interval  = 100,.input_fuzz     = 4,.input_flat     = 4,
};
static struct i2c_board_info smdkv210_i2c_devs0[] __initdata = {{ I2C_BOARD_INFO("24c08", 0x50), },  {I2C_BOARD_INFO("mma7660", 0x4c),.platform_data = &mma7660_pdata,},};

同样,我们可以看到,在iic0上挂了两个设备,一个是24c08,一个是mma7660,因为slave addr的不同,我们可以访问到不同的从设备。
驱动代码:

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/input-polldev.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/mma7660.h>
#include <mach/hardware.h>#define MMA7660_NAME                "mma7660"   #define POLL_INTERVAL               100
#define INPUT_FUZZ                  4
#define INPUT_FLAT                  4#define __need_retry(__v)   (__v & (1 << 6))
#define __is_negative(__v)  (__v & (1 << 5))static const char *mma7660_bafro[] = {"Unknown", "Front", "Back"
};
static const char *mma7660_pola[] = {"Unknown","Left", "Right","Rsvd", "Rsvd","Down", "Up","Rsvd",
};static const struct i2c_device_id mma7660_id[] =
{{"mma7660",0},{}
};struct mma7660_dev
{int poll_interval;int input_fuzz;int input_flat;struct device       *hwmon_dev;     //hwmon devstruct input_polled_dev *ip_dev;    //input poll devstruct i2c_client   * mma_iic_client; //iic clientstruct mma7660_platform_data *pdata;  // platform data
};static int                  last_tilt = 0;
static int                  oper_mode;static struct input_dev *i_dev = NULL;
static struct mma7660_dev *mma7660_struct = NULL;static int mma7660_read_tilt(struct i2c_client *client, int *tilt);static void mma7660_worker(struct work_struct *work)
{
#if 0int bafro, pola, shake, tap;
#endifint val = 0;mma7660_read_tilt(mma7660_struct->mma_iic_client, &val);#if 0bafro = val & 0x03;if(bafro != (last_tilt & 0x03)) {printk("%s\n", mma7660_bafro[bafro]);}pola = (val >> 2) & 0x07;if(pola != ((last_tilt >> 2) & 0x07)){printk("%s\n", mma7660_pola[pola]);}shake = (val >> 5) & 0x01;if(shake && shake != ((last_tilt >> 5) & 0x01)){printk("Shake\n");}tap = (val >> 7) & 0x01;if(tap && tap != ((last_tilt >> 7) & 0x01)){printk("Tap\n");}
#endif/* Save current status */last_tilt = val;
}DECLARE_WORK(mma7660_work, mma7660_worker);static irqreturn_t mma7660_interrupt(int irq, void *dev_id)
{schedule_work(&mma7660_work);return IRQ_HANDLED;
}/*read the data from  reg TILT */
static int mma7660_read_tilt(struct i2c_client *client, int *tilt)
{int val;do {val = i2c_smbus_read_byte_data(client, MMA7660_TILT);if(val < 0){dev_err(&client->dev, "Read register %02x failed, %d\n",MMA7660_TILT, val);return -EIO;}}while(__need_retry(val));//when bit6 is 1,can't read value,so do this to wait the TILT reg ready to read*tilt = (val & 0xff);return 0;
}
static int mma7660_read_xyz(struct i2c_client *client, int idx, int *xyz)
{int val;do {val = i2c_smbus_read_byte_data(client, idx + MMA7660_XOUT);if(val < 0) {dev_err(&client->dev, "Read register %02x failed, %d\n",idx + MMA7660_XOUT, val);return -EIO;}}while(__need_retry(val));*xyz = __is_negative(val) ? (val | ~0x3f) : (val & 0x3f);return 0;
}static int mma7660_initial(struct i2c_client *client)
{int val;//1.set mode to stand by mode first by set bit0 (mode bit)to 0i2c_smbus_write_byte_data(client, MMA7660_MODE, 0x00);mdelay(10);// 2.set mode to test mode,it should  set in stand by mode by set the bit 2(ton bit) to 1 i2c_smbus_write_byte_data(client, MMA7660_MODE, 0x04);mdelay(10);//3.in test mode can set the reg MMA7660_XOUT,MMA7660_YOUT,MMA7660_ZOUT//3.1 clear the bit6(alert bit)i2c_smbus_write_byte_data(client, MMA7660_XOUT, 0x3f);//3.2 clear the bit6(alert bit)i2c_smbus_write_byte_data(client, MMA7660_YOUT, 0x3f);//3.3 clear the bit6(alert bit)i2c_smbus_write_byte_data(client, MMA7660_ZOUT, 0x3f);val = i2c_smbus_read_byte_data(client, MMA7660_ZOUT);if(val != 0x3f) {printk("2.test write and read reg 0x02 but get wrong data: %d, no dev!!!\n",val);return -ENODEV;}//reset to stand by modei2c_smbus_write_byte_data(client, MMA7660_MODE, 0x00);mdelay(10);//AMSR[2:0]bit0-bit2 :samples rate: 001----64 samples/sec  in Active and Auto-Sleep Mode//AWSR[1:0]:bit4-bit3: samples rate: 01-----16 Samples/Second  Auto-Wake Mode//bit7-bit5 :samples rate 001----- 3samples/sec TILTi2c_smbus_write_byte_data(client, MMA7660_SR, ((2<<5) | (1<<3) | 1));//sleep count:160,when reach to the timeout time,will go in auto wake mode,psi2c_smbus_write_byte_data(client, MMA7660_SPCNT, 0xA0);//Tap detection threshold is ±4 counts//X-axis,Y-axis,Z-axis  is enabled for tap detectioni2c_smbus_write_byte_data(client, MMA7660_PDET, 4);//Tap detection debounce filtering requires 16 adjacent tap detection tests to be the same to trigger a tap event and set the Tap//bit in the TILT (0x03) register, and optionally set an interrupt if PDINT is set in the INTSU (0x06) register. Tap detection//response time is nominally 1.04 ms.i2c_smbus_write_byte_data(client, MMA7660_PD, 15);/* Enable interrupt except exiting Auto-Sleep *///FBINT bit 0 ---1: Front/Back position change causes an interrupt//PLINT bit 1---1:Up/Down/Right/Left position change causes an interrupt//PDINT bit 2---1: Successful tap detection causes an interrupt//ASINT bit 3---0:  Exiting Auto-Sleep does not cause an interrupt//GINT bit4---0:There is not an automatic interrupt after everymeasurement//SHINTX bit 5---1:Shake detected on the X-axis causes an interrupt, and sets the Shake bit in the TILT register//SHINTY bit6---1: Shake detected on the Y-axis causes an interrupt, and sets the Shake bit in the TILT register//SHINTZ bit7---1: Shake detected on the Z-axis causes an interrupt, and sets the Shake bit in the TILT register.i2c_smbus_write_byte_data(client, MMA7660_INTSU, 0xe7);/* IPP, Auto-wake, auto-sleep and standby *///Active mode: bit0 set to 1 ,bit 2 set o 0//  AWE bit3----1:Auto-Wake is enabled//ASE bit4----1: Auto-Sleep is enabled//SCPS bit5---0: The prescaler is divide-by-1. The 8-bit internal Sleep Counter input clock is the samples per second set by//AMSR[2:0], so the clock range is 120 Hz to 1 Hz depending on AMSR[2:0] setting. Sleep Counter timeout range is//256 times the prescaled clock//IPP bit6---1: Interrupt output INT is push-pull//IAH bit7---0: Interrupt output INT is active lowi2c_smbus_write_byte_data(client, MMA7660_MODE, 0x59);mdelay(10);/* Save current tilt status */mma7660_read_tilt(client, &last_tilt);return 0;
}/* attr*/
static ssize_t mma7660_show_regs(struct device *dev,struct device_attribute *attr, char *buf)
{int reg, val;int i, len = 0;for(reg = 0; reg < 0x0b; reg++){val = i2c_smbus_read_byte_data(mma7660_struct->mma_iic_client, reg);len += sprintf(buf + len, "REG: 0x%02x = 0x%02x ...... [ ", reg, val);for(i = 7; i >= 0; i--){len += sprintf(buf + len, "%d", (val >> i) & 1);if((i % 4) == 0){len += sprintf(buf + len, " ");}}len += sprintf(buf + len, "]\n");}return len;
}static ssize_t mma7660_write_reg(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
{unsigned int reg, val;int ret;ret = sscanf(buf, "%x %x", &reg, &val);if(ret == 2){if (reg >= 0 && reg <= 0x0a){i2c_smbus_write_byte_data(mma7660_struct->mma_iic_client, reg, val);val = i2c_smbus_read_byte_data(mma7660_struct->mma_iic_client, reg);printk("REG: 0x%02x = 0x%02x\n", reg, val);}}return count;
}static ssize_t mma7660_show_xyz_g(struct device *dev,struct device_attribute *attr, char *buf)
{int axis[3];int i;for (i = 0; i < 3; i++){mma7660_read_xyz(mma7660_struct->mma_iic_client, i, &axis[i]);}return sprintf(buf, "%3d, %3d, %3d\n", axis[0], axis[1], axis[2]);
}static ssize_t mma7660_show_axis_g(struct device *dev,struct device_attribute *attr, char *buf)
{int n = to_sensor_dev_attr(attr)->index;int val;mma7660_read_xyz(mma7660_struct->mma_iic_client, n, &val);return sprintf(buf, "%3d\n", val);
}static ssize_t mma7660_show_tilt(struct device *dev,struct device_attribute *attr, char *buf)
{int val = 0, len = 0;mma7660_read_tilt(mma7660_struct->mma_iic_client, &val);len += sprintf(buf + len, "%s", mma7660_bafro[val & 0x03]);len += sprintf(buf + len, ", %s", mma7660_pola[(val >> 2) & 0x07]);if(val & (1 << 5)){len += sprintf(buf + len, ", Tap");}if(val & (1 << 7)){len += sprintf(buf + len, ", Shake");}len += sprintf(buf + len, "\n");return len;
}static SENSOR_DEVICE_ATTR(registers, S_IRUGO | S_IWUGO,mma7660_show_regs, mma7660_write_reg, 0);
static SENSOR_DEVICE_ATTR(x_axis_g, S_IRUGO, mma7660_show_axis_g, NULL, 0);
static SENSOR_DEVICE_ATTR(y_axis_g, S_IRUGO, mma7660_show_axis_g, NULL, 1);
static SENSOR_DEVICE_ATTR(z_axis_g, S_IRUGO, mma7660_show_axis_g, NULL, 2);
static SENSOR_DEVICE_ATTR(all_axis_g, S_IRUGO, mma7660_show_xyz_g, NULL, 0);
static SENSOR_DEVICE_ATTR(tilt_status, S_IRUGO, mma7660_show_tilt, NULL, 0);static struct attribute* mma7660_attrs[] =
{&sensor_dev_attr_registers.dev_attr.attr,&sensor_dev_attr_x_axis_g.dev_attr.attr,&sensor_dev_attr_y_axis_g.dev_attr.attr,&sensor_dev_attr_z_axis_g.dev_attr.attr,&sensor_dev_attr_all_axis_g.dev_attr.attr,&sensor_dev_attr_tilt_status.dev_attr.attr,NULL
};static const struct attribute_group mma7660_group = {.attrs      = mma7660_attrs,
};
//Input interfaces
static void mma7660_report_abs(void)
{int axis[3];int i;for(i = 0; i < 3; i++){mma7660_read_xyz(mma7660_struct->mma_iic_client, i, &axis[i]);}input_report_abs(mma7660_struct->ip_dev->input, ABS_X, axis[0]);input_report_abs(mma7660_struct->ip_dev->input, ABS_Y, axis[1]);input_report_abs(mma7660_struct->ip_dev->input, ABS_Z, axis[2]);input_sync(mma7660_struct->ip_dev->input);//printk("3-Axis ... %3d, %3d, %3d\n", axis[0], axis[1], axis[2]);
}static void mma7660_dev_poll(struct input_polled_dev *dev)
{mma7660_report_abs();
}/*****int (*probe)(struct i2c_client *, const struct i2c_device_id *)*****/static int mma7660_probe(struct i2c_client *uc_i2c_client, const struct i2c_device_id * uc_i2c_id_table)
{int err=0;//check iicif(!i2c_check_functionality(uc_i2c_client->adapter,I2C_FUNC_I2C)) {err = -ENODEV;goto FAIL_CHECK_FUNC;}//check platdataif(!uc_i2c_client->dev.platform_data){   err = -ENODATA;goto FAIL_NO_PLATFORM_DATA;}//allooc buf  mma7660_struct = kzalloc(sizeof(struct mma7660_dev),GFP_KERNEL);if(!mma7660_struct){err=-ENOMEM;goto FAIL_KZALLOC;}//initial startmma7660_struct->mma_iic_client = uc_i2c_client;mma7660_struct->pdata = uc_i2c_client->dev.platform_data;mma7660_struct->poll_interval =((mma7660_struct->pdata->poll_interval >0) ? mma7660_struct->pdata->poll_interval : POLL_INTERVAL);mma7660_struct->input_flat =((mma7660_struct->pdata->input_flat >0) ? mma7660_struct->pdata->input_flat : INPUT_FLAT);mma7660_struct->input_fuzz =((mma7660_struct->pdata->input_fuzz >0) ? mma7660_struct->pdata->input_fuzz : INPUT_FUZZ);if(mma7660_struct->pdata->irq){mma7660_struct->mma_iic_client->irq = mma7660_struct->pdata->irq;}else{err = -ENODATA;printk("3.the platformdata no irq data\n");goto FAIL_NO_IRQ_DATA;}//initial the deverr = mma7660_initial(mma7660_struct->mma_iic_client);if(err < 0){goto FAIL_MMA7660_INIT;}err = sysfs_create_group(&mma7660_struct->mma_iic_client->dev.kobj, &mma7660_group);if(err){printk("4.create sysfs group failed!\n");goto FAIL_CREATE_GROUP;}// register to hwmon device mma7660_struct->hwmon_dev = hwmon_device_register(&mma7660_struct->mma_iic_client->dev);if(IS_ERR(mma7660_struct->hwmon_dev)){err = PTR_ERR(mma7660_struct->hwmon_dev);printk("5.hwmon register failed!\n");goto FAIL_HWMON_REGISTER;}//alloc the input poll device  mma7660_struct->ip_dev = input_allocate_polled_device();if(!mma7660_struct->ip_dev){err = -ENOMEM;printk("6.alloc poll device failed!\n");goto FAIL_ALLLOC_INPUT_PDEV;}mma7660_struct->ip_dev->poll = mma7660_dev_poll;mma7660_struct->ip_dev->poll_interval =mma7660_struct->pdata->poll_interval;i_dev = mma7660_struct->ip_dev->input;i_dev->name = MMA7660_NAME;i_dev->id.bustype = BUS_I2C;i_dev->id.vendor = 0x12FA;i_dev->id.product = 0x7660;i_dev->id.version = 0x0100;i_dev->dev.parent = &mma7660_struct->mma_iic_client->dev; set_bit(EV_ABS, i_dev->evbit);set_bit(ABS_X, i_dev->absbit);set_bit(ABS_Y, i_dev->absbit);set_bit(ABS_Z, i_dev->absbit);input_set_abs_params(i_dev, ABS_X, -512, 512, mma7660_struct->input_fuzz, mma7660_struct->input_flat);input_set_abs_params(i_dev, ABS_Y, -512, 512, mma7660_struct->input_fuzz, mma7660_struct->input_flat);input_set_abs_params(i_dev, ABS_Z, -512, 512, mma7660_struct->input_fuzz, mma7660_struct->input_flat);err = input_register_polled_device(mma7660_struct->ip_dev);if(err){       printk("7.register poll device failed!");goto FAIL_INPUT_REGISTER_PDEV;}//register interrupt handle err = request_irq(mma7660_struct->pdata->irq, mma7660_interrupt,IRQF_TRIGGER_FALLING, MMA7660_NAME, NULL);if(err){printk("8.request irq failed!\n");goto FAIL_REQUEST_IRQ;}printk("mma7660 driver probe success!\n");return 0;FAIL_REQUEST_IRQ:input_unregister_polled_device(mma7660_struct->ip_dev);
FAIL_INPUT_REGISTER_PDEV:input_free_polled_device(mma7660_struct->ip_dev);
FAIL_ALLLOC_INPUT_PDEV:hwmon_device_unregister(mma7660_struct->hwmon_dev);
FAIL_HWMON_REGISTER:sysfs_remove_group(&mma7660_struct->mma_iic_client->dev.kobj,&mma7660_group);
FAIL_CREATE_GROUP:
FAIL_MMA7660_INIT:
FAIL_NO_IRQ_DATA:kfree(mma7660_struct);
FAIL_KZALLOC:
FAIL_NO_PLATFORM_DATA:
FAIL_CHECK_FUNC:return err;}
/*****int (*remove)(struct i2c_client *)*****/
static int mma7660_remove(struct i2c_client *uc_i2c_client)
{disable_irq(mma7660_struct->pdata->irq);free_irq(mma7660_struct->pdata->irq,NULL);input_unregister_polled_device(mma7660_struct->ip_dev);input_free_polled_device(mma7660_struct->ip_dev);hwmon_device_unregister(mma7660_struct->hwmon_dev);sysfs_remove_group(&mma7660_struct->mma_iic_client->dev.kobj,&mma7660_group);return 0;
}
static int mma7660_suspend(struct i2c_client *client, pm_message_t state)
{int ret;oper_mode = i2c_smbus_read_byte_data(client, MMA7660_MODE);ret = i2c_smbus_write_byte_data(client, MMA7660_MODE, 0);if(ret){printk("%s: set mode (0) for suspend failed, ret = %d\n",MMA7660_NAME, ret);}return 0;
}static int mma7660_resume(struct i2c_client *client)
{int ret;ret = i2c_smbus_write_byte_data(client, MMA7660_MODE, oper_mode);if (ret) {printk("%s: set mode (%d) for resume failed, ret = %d\n",MMA7660_NAME, oper_mode, ret);}return 0;
}static struct i2c_driver mma7660_drv =
{.driver ={.name = MMA7660_NAME,   .owner= THIS_MODULE,},.probe   = mma7660_probe,.remove  = mma7660_remove,.suspend = mma7660_suspend,.resume  = mma7660_resume,//match use.id_table = mma7660_id,
};int __init  mma7660_init(void)
{i2c_add_driver(&mma7660_drv);   return 0;
}void __exit mma7660_exit(void)
{i2c_del_driver(&mma7660_drv);
}module_init(mma7660_init);
module_exit(mma7660_exit);
MODULE_LICENSE("GPL");

整个驱动最难理解的地方应该还是在probe函数里面。当初始化完成以后,大部分的函数都是在做读操作而已。我们可以根据芯片手册来了解它的配置。同时比较难理解的是它本次采用的驱动框架。其他没什么难的,和之气的输入子系统都是一样的。

实验现象:

linux驱动开发:mma7660 sensor的配置相关推荐

  1. Linux驱动开发环境配置(内核源码树构造)

    来源:季义钦BLOG 作者:季义钦 初次接触Linux驱动程序开发,买了一本<Linux设备驱动程序>,第一件事当然就是构建开发环境了!!! 它上面有一个Hello World的列子: / ...

  2. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  3. linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写

    摘要:媒介 Device Tree是一种用去描绘硬件的数据布局,类似板级描绘说话,发源于OpenFirmware(OF).正在现在遍及应用的kernel 2.6.x版本中,对分歧仄台.分歧硬件,往] ...

  4. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html IT168 技术文档]在开始步入Lin ...

  5. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之Pinctrl子系统和GPIO子系统的使用

    文章目录 前言 1.Pinctrl子系统 1.1.为什么有Pinctrl子系统 1.2.重要的概念 1.3.代码中怎么引用pinctrl 2.GPIO子系统 2.1.为什么有GPIO子系统 2.2.在 ...

  6. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之按键驱动框架

    文章目录 前言 1.APP怎么读取按键值 1.1.查询方式 1.2.休眠-唤醒方式 1.3.poll方式 1.3.异步通知方式 1.5. 驱动程序提供能力,不提供策略 2.按键驱动程序框架--查询方式 ...

  7. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之LED模板驱动程序的改造:设备树

    文章目录 前言 1.驱动的三种编写方法 2.怎么使用设备树写驱动程序 2.1.设备树节点要与platform_driver能匹配 2.2.修改platform_driver的源码 3.实验和调试技巧 ...

  8. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之设备树模型

    文章目录 前言 1.设备树的作用 2.设备树的语法 2.1.设备树的逻辑图和dts文件.dtb文件 2.1.1.1Devicetree格式 1DTS文件的格式 node的格式 properties的格 ...

  9. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之LED驱动框架--面向对象、分层设计思想

    文章目录 前言 1.LED驱动程序框架 1.1.对于LED驱动,我们想要什么样的接口? 1.2.LED驱动要怎么写,才能支持多个板子?分层写 1.3.程序分析 驱动程序 应用程序 Makefile 1 ...

  10. 嵌入式linux应用层中断函数,嵌入式LINUX驱动开发(中断处理函数)

    嵌入式LINUX驱动开发(中断处理函数) 2020年08月11日 | 萬仟网网络运营 | 我要评论 嵌入式LINUX驱动学习之7中断相关(一)中断处理函数一.函数.头文件及说明二.编译举例:一.函数. ...

最新文章

  1. 数据结构_栈和队列的区别
  2. 正则表达式手机固话php,手机和固话正则的记忆方法
  3. context:annotation-config/,context:component-scan/,mvc:annotation-driven/区分
  4. Linux找最大最小值的命令,Linux中awk命令正确的求最大值、最小值、平均值、总和...
  5. Confluent Platform 3.0支持使用Kafka Streams实现实时的数据处理(最新版已经是3.1了,支持kafka0.10了)...
  6. Linux内核深入理解定时器和时间管理(5):clockevents 框架
  7. Python风格总结:模块调用
  8. igzo屏幕优点与缺点_手机贴膜怎么选?选对了可以省个屏幕钱
  9. 打印机质量测试软件,打印机断针测试软件
  10. 复利,世界第八大奇迹
  11. React组件抽象(一): mixin
  12. 【Python语音分析】从绘制好看的波形图和语谱图开始
  13. javax和java的区别
  14. 读--《谁动了我的奶酪》
  15. Kubernetes 企业集群建设规划
  16. 下一个好莱坞巨头——计算机
  17. Nginx之父突然离职,程序员巅峰一代落幕
  18. 零基础CSS入门教程(16)–内边距
  19. 同程艺龙:如何基于RocketMQ打造日均容量1500亿的消息引擎?
  20. LBM方法中的绝热边界实现形式个人总结

热门文章

  1. 腾讯云文档数据库MongoDB怎么样?腾讯云文档数据库MongoDB有什么优点?
  2. 自动控制原理分析工作原理以及方框图做题过程
  3. hi3519叠加OSD
  4. 使用RawImage播放视频不清晰(改变视频比例后不清晰)的问题解决
  5. 固态硬盘与普通硬盘有哪些区别?
  6. 常用的几个框架官网【前端 / 自用】
  7. 信号完整性(SI)电源完整性(PI)学习笔记(三十三)102条使信号完整性问题最小化的通用设计规则
  8. 开发到底要不要转行软件测试?
  9. 构建会员运营管理系统 帮助零售企业数字化转型
  10. 【ruby】ruby图像处理模块“mini_magick”