自己动手写Linux驱动代码
Posted Wu_Being
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己动手写Linux驱动代码相关的知识,希望对你有一定的参考价值。
相关代码修改 git status
wucb0122@wucb0122-ubuntu14:~/my_project/kernel-4.4$
wucb0122@wucb0122-ubuntu14:~/my_project/kernel-4.4$ git status
HEAD detached at 388a8ce
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: arch/arm/boot/dts/proj_xxx/chipxxx.dtsi
modified: drivers/misc/Makefile
Untracked files:
(use "git add <file>..." to include in what will be committed)
arch/arm/boot/dts/proj_xxx/chipxxx.dtsi_bak
drivers/misc/ts_square_wave.c
drivers/misc/ts_test.c
no changes added to commit (use "git add" and/or "git commit -a")
- 修改编译配制
wucb0122@wucb0122-ubuntu14:~/my_project/kernel-4.4$ git diff drivers/misc/Makefile
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f26ac5c..6ea2403 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -68,3 +68,4 @@ obj-$(CONFIG_QPNP_MISC) += qpnp-misc.o
obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o
obj-$(CONFIG_BOARD_ID_DETECTION) +=board_id_detect.o
+obj-y += ts_square_wave.o
- 配制相关gpio设备树信息(61号gpio)
wucb0122@wucb0122-ubuntu14:~/my_project/kernel-4.4$ git diff arch/arm/boot/dts/proj_xxx/chipxxx.dtsi
diff --git a/arch/arm/boot/dts/proj_xxx/chipxxx.dtsi b/arch/arm/boot/dts/proj_xxx/chipxxx.dtsi
index 9934d37..803f9ce 100644
--- a/arch/arm/boot/dts/proj_xxx/chipxxx.dtsi
+++ b/arch/arm/boot/dts/proj_xxx/chipxxx.dtsi
@@ -2509,6 +2509,17 @@
+
+ ts-square_wave
+ compatible = "ts,square_wave";
+ ts_square_wave,gpio= <&tlmm 61 0>;
+ status = "okay";
+ ;
;
#include "chipxxx-ion.dtsi"
wucb0122@wucb0122-ubuntu14:~/my_project/kernel-4.4$
wucb0122@wucb0122-ubuntu14:~/my_project/kernel-4.4$
- 驱动代码 ts_square_wave.c
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/pm_wakeup.h>
#include <linux/workqueue.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#endif
#define GPIO_LOW 0
#define GPIO_HIGH 1
struct dev_data
int irq;
int gpio;
struct work_struct ts_work;
struct workqueue_struct *ts_workqueue;
struct wakeup_source *ws;
;
static struct dev_data * ts_dev_data;
static int is_charging(void)//充电状态的检测
return 1;
static int is_powerfull(void)//检测电池电量
return 0;
static int feature_accessory_func(void)//空函数
return 0;
irqreturn_t interrupt_handler(int irq, void *dev_id)
printk("ts: enter %s......\\n", __func__);
if (is_charging())
//__pm_stay_awake(ws);//如果正在充电,保持唤醒
if (is_powerfull())
gpio_set_value(ts_dev_data->gpio, GPIO_HIGH);
else //如果电池电量不足100%释放方波
schedule_work(&ts_dev_data->ts_work);
else
//__pm_relax(ws);//如果不是充电,就释放wakeup_source
feature_accessory_func();
gpio_set_value(ts_dev_data->gpio, GPIO_LOW);
return IRQ_HANDLED;
// 工作队列处理函数 释放方波
static void work_handler(struct work_struct *work)
printk("ts: enter %s .......\\n", __func__);
disable_irq(ts_dev_data->irq);
free_irq(ts_dev_data->irq, NULL);
if (is_charging())
if (is_powerfull())
gpio_set_value(ts_dev_data->gpio, GPIO_HIGH);
else //如果电池电量不足100%释放方波
msleep(500);
gpio_direction_output(ts_dev_data->gpio, GPIO_HIGH);
msleep(500);
gpio_direction_output(ts_dev_data->gpio, GPIO_LOW);
schedule_work(&ts_dev_data->ts_work);
else
//__pm_relax(ws);//如果不是充电,就释放wakeup_source
gpio_set_value(ts_dev_data->gpio, GPIO_LOW);
static int ts_square_wave_probe(struct platform_device *pdev)
int ret = -1;
struct device_node *ts_node = pdev->dev.of_node;
printk("ts: %s-%d: enter\\n", __FUNCTION__, __LINE__);
// 分配空间,并从设备树获取值(对应设备树 ts_square_wave,gpio= <&tlmm 61 0>; )
ts_dev_data = kmalloc(sizeof(struct dev_data), GFP_KERNEL);
ts_dev_data->gpio = of_get_named_gpio_flags(ts_node, "ts_square_wave,gpio", 0, NULL);
printk("ts: we have get the gpio number gpio = %d\\n", ts_dev_data->gpio);
if (!gpio_is_valid(ts_dev_data->gpio))
printk("ts: invalid gpio : %d\\n", ts_dev_data->gpio);
return -1;
// 设置该脚要gpio,并命名为"ts_square_wave_gpio"
ret = gpio_request(ts_dev_data->gpio, "ts_square_wave_gpio");
if (ret != 0)
gpio_free(ts_dev_data->gpio);
printk("ts: invalid gpio : %d\\n", ts_dev_data->gpio);
return -EIO;
// 设置gpio为中断脚,并设置中断,中断处理函数interrupt_handler,中断名"ts_square_wave_irq"
ts_dev_data->irq = gpio_to_irq(ts_dev_data->gpio);
printk("ts: we have get the irq number irq = %d\\n", ts_dev_data->gpio);
ret = request_irq(ts_dev_data->irq, interrupt_handler, IRQF_TRIGGER_RISING, "ts_square_wave_irq", NULL);
// 注册 wakeup_source
ts_dev_data->ws = wakeup_source_register("ts_square_wave_lock");
//__pm_stay_awake(ts_dev_data->ws); //申请wakeup_source
//__pm_relax(ts_dev_data->ws); //释放wakeup_source
// 创建工作队列
ts_dev_data->ts_workqueue = create_singlethread_workqueue("ts_square_wave_queue");
if (ts_dev_data->ts_workqueue)
// 初始化work_struct类型的变量(主要是指定处理函数 work_handler)
INIT_WORK(&ts_dev_data->ts_work, work_handler);
//schedule_work(&ts_dev_data->ts_work);
return 0; //return Ok
static int ts_square_wave_remove(struct platform_device *pdev)
return 0;
#ifdef CONFIG_OF
static const struct of_device_id of_ts_square_wave_match[] =
.compatible = "ts,square_wave" , // 对应设备树 compatible = "ts,square_wave";
/* Sentinel */
;
#endif
static struct platform_driver ts_square_wave_driver =
.probe = ts_square_wave_probe,
.remove = ts_square_wave_remove,
.driver =
.name = "ts_square_wave",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = of_ts_square_wave_match,
#endif
,
;
static int __init ts_init(void)
printk(KERN_INFO "ts: ts_init: enter %s.\\n", __FUNCTION__);
return platform_driver_register(&ts_square_wave_driver);
return 0;
static void __exit ts_exit(void)
platform_driver_unregister(&ts_square_wave_driver);
printk("ts: ts_exit: ts_square_wave_driver.\\n");
subsys_initcall(ts_init);
module_exit(ts_exit);
MODULE_AUTHOR("WuChengbing");
MODULE_DESCRIPTION("Output square wave by detecting is_charging and no is_powerfull.");
MODULE_LICENSE("GPL");
- 调试获取函数实现接口
cat d/wakeup_sources
cat proc/interrupts
cat sys/bus/platform/driver
Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《自己动手写Linux驱动代码》:
https://blog.csdn.net/u014134180/article/details/80602593
以上是关于自己动手写Linux驱动代码的主要内容,如果未能解决你的问题,请参考以下文章
android 自定义View绘制电池电量(电池内带数字显示)