您的位置:首页 > 其它

IMX6Q学习笔记———编写LED驱动和测试程序以及相关管脚配置

2017-08-13 11:04 507 查看
刚接触IMX6Q不久,通过一个简单的LED驱动和测试程序的编写来了解管脚配置过程。

LED驱动

找到以前编写驱动的基本框架,如下:

static long xxx_ioctl(struct file *filp, unsigned int cmd,unsigned long arg)
static struct file_operations xxx_dev_fops
static struct miscdevice xxx_dev
static int __init xxx_dev_init(void)
static void __exit xxx_dev_exit(void)
module_init(xxx_dev_init);
module_exit(xxx_dev_exit);
MODULE_LICENSE("GPL");


找LED灯对应的管脚

在底板寻找LED,然后在底板看不到LED灯

在核心板找LED。如图:



现在知道,它连着GPIO_2,搜GPIO_2再找在CPU里的位置,如图:



现在确认LED是连在GPIO_2这个引脚,去文档(IMX6DQRM)查找关于GPIO_2的功能模式,如图:



现在我们知道GPIO_2有以下5个功能,作为LED亮灭的功能选择第三个功能,

GPIO1_IO02,搜索SW_PAD_CTL_PAD_GPIO02,结果如下:



知道它的偏移量是604H

知道偏移量是604,source insight打开的文件里找到iomux-mx6q.h,搜索604,如图:



现在知道这个IO功能,要使用时该怎么定义了:_MX6Q_PAD_GPIO_2__GPIO_1_2

添加管脚功能

在文件board-mxq.h中搜索X6Q_PAD_GPIO_2,看到:



说明原本已经默认定义了中个GPIO_2这个管脚的功能是作为GPIO口来使用,所有我们不用再添加进去了,如果没有则添加。

查看宏定义

在文件board-mx6q.c中,我们可以看到,如图:



所以,后面我们编写代码在申请管脚时,可以直接

ret = gpio_request(SABRESD_USR_DEF_RED_LED, “LED”);

或者你可以在你的驱动代码里重新define:#define my_led IMX_GPIO_NR(1, 2)

编写驱动程序

先编写初始化代码:



ret = gpio_request(my_led, “LED”);申请管脚

gpio_direction_output(my_led, 1);设定输出方向

gpio_set_value(my_led, 1);设定初值为1,即是亮

ret = misc_register(&my_led_dev);注册一个混杂设备。

下面的IOCTL不写了,依个人情况而定

附驱动代码:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <mach/gpio.h>

#define DEVICE_NAME "leds"
#define my_led  IMX_GPIO_NR(1, 2)

static long s5pv210_leds_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
switch(cmd) {
case 0:
case 1:
if (arg > 5) {
return -EINVAL;
}

gpio_set_value(my_led, !cmd);
//printk(DEVICE_NAME": %d %d\n", arg, cmd);
break;

default:
return -EINVAL;
}

return 0;
}

static struct file_operations s5pv210_led_dev_fops = {
.owner          = THIS_MODULE,
.unlocked_ioctl = s5pv210_leds_ioctl,
};

static struct miscdevice s5pv210_led_dev = {
.minor          = MISC_DYNAMIC_MINOR,
.name           = DEVICE_NAME,
.fops           = &s5pv210_led_dev_fops,
};

static int __init s5pv210_led_dev_init(void) {
int ret;
int i;
gpio_free(my_led);

ret = gpio_request(my_led, "LED");<
4000
span class="hljs-comment">//第一个参数,为要申请的引脚,第二个为你要定义的名字
if (ret) {

return ret;
}

gpio_direction_output(my_led, 1);//设定是什么设备,第二为改引脚为输入还是输出
gpio_set_value(my_led, 1);//初始化值

ret = misc_register(&s5pv210_led_dev);

printk(DEVICE_NAME"\tinitialized\n");

return ret;
}

static void __exit s5pv210_led_dev_exit(void) {
int i;

gpio_free(my_led);

misc_deregister(&s5pv210_led_dev);
}

module_init(s5pv210_led_dev_init);
module_exit(s5pv210_led_dev_exit);

MODULE_LICENSE("GPL");


附测试程序代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int num, fd, cmd, I;
fd = open("/dev/zsq_beep, O_RDWR);//选择设备名称,和模式
if(fd < 0)
printf("can't open!\n");
while(1)
{
scanf("%d",&num);
switch(num)//选择输入的值,来控制IOCTL函数的CMD值

case 0:
ioctl(fd, 0, 4);//LED灯灭
break;
case 1:
ioctl(fd, 1, 4);//LED灯亮
break;
default:
for(i=0;i<num;i++)//LED灯闪烁num次
{
ioctl(fd, 0, 4);
sleep(1);//间隔1秒
ioctl(fa, 1, 4);
sleep(1);//间隔1秒
}
break;
return 0;
}
return 0;
}


这就是基本的过程。

本人原创文章,欢迎附带本文链接转载。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息