【龙印】龙芯1c的gpio输出高低电平的linux驱动
2016-08-31 17:14
507 查看
本文为在用龙芯1c做3D打印机过程中的笔记。龙芯1c做的3d打印机简称“龙印”
控制GPIO输出高低电平是很简单,也经常用到。比如控制led,通过光耦或者功率三极管控制3d打印机的风扇和加热装置,还能控制3d打印机的步进电机。
以步进电机驱动模块A4988为例,A4988的使能,方向,步进这三个脚都是用GPIO控制的。
据此,还是决定写个简单的gpio作为输出的驱动和测试程序。
这里选gpio50,这个io口在智龙v2.0上已经接有一个led,点亮后是绿色的,如下
![](http://img.blog.csdn.net/20160831171713679?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
再看看原理图
![](http://img.blog.csdn.net/20160831171932977?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
gpio50就是CAMDATA0,有图可知,在gpio50输出低电平,led就会亮,输出高电平,就灭。
不多说了,上源码
驱动“ls1c_test_gpio_output.c”
/*
* drivers\misc\ls1c_test_gpio_output.c
* 把龙芯1c上的一个IO口设为输出,并输出高低电平
* 如果IO口上接有led,则led会亮灭,也可以用万用表测试io口的电压
*/
#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>
//智龙v2.0上gpio50接有一个led
#define TEST_GPIO (50) // CAMDATA0/GPIO50
#define GPIO_VALUE_HIGH (1) // gpio输出高电平
#define GPIO_VALUE_LOW (0) // gpio输出低电平
static DEFINE_MUTEX(gpio_output_lock);
static int gpio_output_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int gpio_output_close(struct inode *inode, struct file *filp)
{
// 如果gpio接有led,那么在文件关闭的时候把led也灭掉
gpio_set_value(TEST_GPIO, GPIO_VALUE_HIGH);
return 0;
}
static ssize_t gpio_output_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
{
int ret = 0;
int gpio_value = 0;
if (mutex_lock_interruptible(&gpio_output_lock))
{
return -ERESTARTSYS;
}
ret = copy_from_user(&gpio_value, buf, sizeof(gpio_value));
mutex_unlock(&gpio_output_lock);
if (ret)
{
printk(KERN_ERR "[%s] write gpio_value fail.\n", __FUNCTION__);
return -1;
}
printk(KERN_DEBUG "[%s] gpio_value=%d\n", __FUNCTION__, gpio_value);
gpio_set_value(TEST_GPIO, gpio_value);
return sizeof(gpio_value);
}
static struct file_operations ls1c_gpio_output_ops = {
.owner = THIS_MODULE,
.open = gpio_output_open,
.release = gpio_output_close,
.write = gpio_output_write,
};
static struct miscdevice ls1c_gpio_output_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "ls1c_test_gpio_output",
.fops = &ls1c_gpio_output_ops,
};
static int __init gpio_output_init(void)
{
int ret = 0;
// 申请gpio资源
ret = gpio_request(TEST_GPIO, "ls1c_test_gpio_output");
if (0 > ret)
{
printk(KERN_ERR "[%s] request gpio %d fail\n", __FUNCTION__, TEST_GPIO);
return ret;
}
// 把gpio设为输出模式,并输出高电平
gpio_direction_output(TEST_GPIO, GPIO_VALUE_HIGH);
// 注册设备
ret=misc_register(&ls1c_gpio_output_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_output_exit(void)
{
misc_deregister(&ls1c_gpio_output_miscdev);
gpio_free(TEST_GPIO);
}
module_init(gpio_output_init);
module_exit(gpio_output_exit);
MODULE_AUTHOR("简单平安");
MODULE_DESCRIPTION("ls1c gpio output test");
MODULE_LICENSE("GPL");
在“drivers\misc\Kconfig”中增加
config LS1C_TEST_GPIO_OUTPUT
tristate "ls1c test gpio output"
depends on LS1C_MACH
help
Say Y here if you want to build a test gpio output driver for ls1c
在“drivers\misc\Makefile”中增加
obj-$(CONFIG_LS1C_TEST_GPIO_OUTPUT) += ls1c_test_gpio_output.o
配置
make menuconfig
Device Drivers --->
[*] Misc devices --->
<*> ls1c test gpio output
测试用的应用程序“main.c”
#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_output", O_RDWR);
if (-1 == fd)
{
printf("[%s] open device file.\n", __FUNCTION__);
return -1;
}
while (1)
{
gpio_value = 0;
ret = write(fd, &gpio_value, sizeof(gpio_value));
if (sizeof(gpio_value) != ret)
{
close(fd);
printf("[%s] write fail. ret=%d\n", __FUNCTION__, ret);
return -1;
}
sleep(3);
gpio_value = 1;
ret = write(fd, &gpio_value, sizeof(gpio_value));
if (sizeof(gpio_value) != ret)
{
close(fd);
printf("[%s] write fail. ret=%d\n", __FUNCTION__, ret);
return -1;
}
sleep(3);
}
}
运行的串口打印如下
![](http://img.blog.csdn.net/20160831175251837?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
linux源码中已经封装了gpio的接口,驱动中只需调用就行。当然也可以根据1c的芯片手册自己封装或者重新实现。感兴趣的可以看看“arch\mips\loongson\ls1x\gpio.c”
控制GPIO输出高低电平是很简单,也经常用到。比如控制led,通过光耦或者功率三极管控制3d打印机的风扇和加热装置,还能控制3d打印机的步进电机。
以步进电机驱动模块A4988为例,A4988的使能,方向,步进这三个脚都是用GPIO控制的。
据此,还是决定写个简单的gpio作为输出的驱动和测试程序。
这里选gpio50,这个io口在智龙v2.0上已经接有一个led,点亮后是绿色的,如下
再看看原理图
gpio50就是CAMDATA0,有图可知,在gpio50输出低电平,led就会亮,输出高电平,就灭。
不多说了,上源码
驱动“ls1c_test_gpio_output.c”
/*
* drivers\misc\ls1c_test_gpio_output.c
* 把龙芯1c上的一个IO口设为输出,并输出高低电平
* 如果IO口上接有led,则led会亮灭,也可以用万用表测试io口的电压
*/
#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>
//智龙v2.0上gpio50接有一个led
#define TEST_GPIO (50) // CAMDATA0/GPIO50
#define GPIO_VALUE_HIGH (1) // gpio输出高电平
#define GPIO_VALUE_LOW (0) // gpio输出低电平
static DEFINE_MUTEX(gpio_output_lock);
static int gpio_output_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int gpio_output_close(struct inode *inode, struct file *filp)
{
// 如果gpio接有led,那么在文件关闭的时候把led也灭掉
gpio_set_value(TEST_GPIO, GPIO_VALUE_HIGH);
return 0;
}
static ssize_t gpio_output_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
{
int ret = 0;
int gpio_value = 0;
if (mutex_lock_interruptible(&gpio_output_lock))
{
return -ERESTARTSYS;
}
ret = copy_from_user(&gpio_value, buf, sizeof(gpio_value));
mutex_unlock(&gpio_output_lock);
if (ret)
{
printk(KERN_ERR "[%s] write gpio_value fail.\n", __FUNCTION__);
return -1;
}
printk(KERN_DEBUG "[%s] gpio_value=%d\n", __FUNCTION__, gpio_value);
gpio_set_value(TEST_GPIO, gpio_value);
return sizeof(gpio_value);
}
static struct file_operations ls1c_gpio_output_ops = {
.owner = THIS_MODULE,
.open = gpio_output_open,
.release = gpio_output_close,
.write = gpio_output_write,
};
static struct miscdevice ls1c_gpio_output_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "ls1c_test_gpio_output",
.fops = &ls1c_gpio_output_ops,
};
static int __init gpio_output_init(void)
{
int ret = 0;
// 申请gpio资源
ret = gpio_request(TEST_GPIO, "ls1c_test_gpio_output");
if (0 > ret)
{
printk(KERN_ERR "[%s] request gpio %d fail\n", __FUNCTION__, TEST_GPIO);
return ret;
}
// 把gpio设为输出模式,并输出高电平
gpio_direction_output(TEST_GPIO, GPIO_VALUE_HIGH);
// 注册设备
ret=misc_register(&ls1c_gpio_output_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_output_exit(void)
{
misc_deregister(&ls1c_gpio_output_miscdev);
gpio_free(TEST_GPIO);
}
module_init(gpio_output_init);
module_exit(gpio_output_exit);
MODULE_AUTHOR("简单平安");
MODULE_DESCRIPTION("ls1c gpio output test");
MODULE_LICENSE("GPL");
在“drivers\misc\Kconfig”中增加
config LS1C_TEST_GPIO_OUTPUT
tristate "ls1c test gpio output"
depends on LS1C_MACH
help
Say Y here if you want to build a test gpio output driver for ls1c
在“drivers\misc\Makefile”中增加
obj-$(CONFIG_LS1C_TEST_GPIO_OUTPUT) += ls1c_test_gpio_output.o
配置
make menuconfig
Device Drivers --->
[*] Misc devices --->
<*> ls1c test gpio output
测试用的应用程序“main.c”
#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_output", O_RDWR);
if (-1 == fd)
{
printf("[%s] open device file.\n", __FUNCTION__);
return -1;
}
while (1)
{
gpio_value = 0;
ret = write(fd, &gpio_value, sizeof(gpio_value));
if (sizeof(gpio_value) != ret)
{
close(fd);
printf("[%s] write fail. ret=%d\n", __FUNCTION__, ret);
return -1;
}
sleep(3);
gpio_value = 1;
ret = write(fd, &gpio_value, sizeof(gpio_value));
if (sizeof(gpio_value) != ret)
{
close(fd);
printf("[%s] write fail. ret=%d\n", __FUNCTION__, ret);
return -1;
}
sleep(3);
}
}
运行的串口打印如下
linux源码中已经封装了gpio的接口,驱动中只需调用就行。当然也可以根据1c的芯片手册自己封装或者重新实现。感兴趣的可以看看“arch\mips\loongson\ls1x\gpio.c”
相关文章推荐
- 基于迅为4412的一个GPIO输出高低电平的驱动
- 【龙印】龙芯1c的gpio作为输入时的linux驱动
- Hi3518EV200平台直接操作GPIO输入或输出高低电平
- 开发板上使用GPIO向电磁继电器发送高低电平控制台灯亮灭(我的第一个linux驱动程序开发)
- 树莓派-通过Web控制GPIO针脚输出高低电平
- 【龙印】龙芯1c上双路16位AD芯片TM7705的linux驱动
- 树莓派-通过Web控制GPIO针脚输出高低电平(改进版)
- (2)ARM40-A5板应用程序——GPIO输出高低电平
- Hi3518EV200平台直接操作GPIO输入或输出高低电平
- linux kernel下动态设置一个GPIO输出电平高低
- 我的第一个简单的linux打印输出驱动(文件自动注册有问题)
- Davinci DM6446开发攻略——LINUX GPIO驱动源码移植
- 很好的linux下GPIO驱动详解文章
- 很好的linux下GPIO驱动详解文章
- 关于GPIO的上电复位后默认输出电平的影响
- Davinci DM6446开发攻略——LINUX GPIO驱动源码移植
- linux驱动之gpio2
- Davinci DM6446开发攻略——LINUX GPIO驱动源码移植
- 慢慢学Linux驱动开发,第三篇,关于printk的输出总结
- Davinci DM6446开发攻略——LINUX GPIO驱动源码移植