【龙印】龙芯1c的gpio作为输入时的linux驱动

时间:2021-05-02 23:37:42
本文为在用龙芯1c做3D打印机过程中的笔记。龙芯1c做的3d打印机简称“龙印”

和GPIO作为输出一样,作为输入也经常用到。比如3d打印机中需要读取行程开关的状态来判断滑车是否已经接触到限位块了,还有比如按键的状态,按键是被按下了,还是弹起了等等。

linux源码中已经封装了gpio的接口,驱动中只需调用就行。当然也可以根据1c的芯片手册自己封装或者重新实现。感兴趣的可以看看“arch\mips\loongson\ls1x\gpio.c”

不多说了,上源码

驱动源文件“ls1c_test_gpio_input.c”

/* * drivers\misc\ls1c_test_gpio_input.c
* 把龙芯1c的GPIO设为输入,并读取io的值
*/arch\mips\loongson\ls1x


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/ls1c_3dprinter_motor.h>
#include <linux/delay.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/kfifo.h>


#define TEST_GPIO (49) // CAMHSYNC/GPIO49



static ssize_t gpio_input_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
{
int gpio_value = 0;

gpio_value = gpio_get_value(TEST_GPIO);
if(copy_to_user(buf, &gpio_value, sizeof(gpio_value)))
{
return 0;
}

return sizeof(gpio_value);
}


static struct file_operations ls1c_gpio_input_ops = {
.owner = THIS_MODULE,
.read = gpio_input_read,
};


static struct miscdevice ls1c_gpio_input_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "ls1c_test_gpio_input",
.fops = &ls1c_gpio_input_ops,
};


static int __init gpio_input_init(void)
{
int ret = 0;

// 申请io资源
ret = gpio_request(TEST_GPIO, "ls1c_test_gpio_input");
if (0 > ret)
{
printk(KERN_ERR "[%s] request gpio %d fail.\n", __FUNCTION__, TEST_GPIO);
return ret;
}

// 设为输入模式
gpio_direction_input(TEST_GPIO);

// 注册设备
ret = misc_register(&ls1c_gpio_input_miscdev);
if (ret)
{
printk(KERN_ERR "[%s] could not register miscdev!\n", __FUNCTION__);
goto fail_free_gpio;
}

return 0;

fail_free_gpio:
gpio_free(TEST_GPIO);

return ret;
}


static void __exit gpio_input_exit(void)
{
misc_deregister(&ls1c_gpio_input_miscdev);
gpio_free(TEST_GPIO);
}


module_init(gpio_input_init);
module_exit(gpio_input_exit);


MODULE_AUTHOR("简单平安");
MODULE_DESCRIPTION("ls1c gpio input test");
MODULE_LICENSE("GPL");



在“drivers\misc\Kconfig”中增加
config LS1C_TEST_GPIO_INPUT
    tristate "ls1c test gpio input"
    depends on LS1C_MACH
    help
     Say Y here if you want to build a test gpio input driver for ls1c
    
在“drivers\misc\Makefile”中增加
obj-$(CONFIG_LS1C_TEST_GPIO_INPUT)         += ls1c_test_gpio_input.o


配置
make menuconfig
Device Drivers  --->
  [*] Misc devices  --->
    <*>   ls1c test gpio input


测试用的应用程序

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(void)
{
    int fd = 0;
    int ret = 0;
    int gpio_value = 0;

    fd = open("/dev/ls1c_test_gpio_input", O_RDWR);
    if (-1 == fd)
    {
        printf("[%s] open device file.\n", __FUNCTION__);
        return -1;
    }

    while (1)
    {
        gpio_value = 0;
        ret = read(fd, &gpio_value, sizeof(gpio_value));
        if (sizeof(gpio_value) != ret)
        {
            printf("[%s] read fail. ret=%d\n", __FUNCTION__, ret);
            return -1;
        }
        printf("[%s] gpio_value=%d\n", __FUNCTION__, gpio_value);
        
        sleep(3);
    }
}

这里选的是gpio49来测试,按下和弹起按键,或者通过行程开关也可以测试。

我测试时有如下打印,根据自己的情况,打印可能不一样,仅供参考

【龙印】龙芯1c的gpio作为输入时的linux驱动