michaelzjh 发表于 2011-9-19 11:48:26

请大家指点:OK6410 GPC0~4点不亮LED

开发环境:linux 2.6.36,gcc:4.3.2
参考飞凌leds例程编写了驱动程序my_ok6410_leds和测试程序leds_test,将编译得到驱动模块my_ok6410_leds.ko,通过指令insmod将模块加载到开发板上。使用指令cat /proc/devices和lsmod可以查看到刚加载的模块信息,包括设备名和设备编号。然后在开发板上运行测试程序,发现LED灯点不亮,但是调试信息输出没有异常,使用万用表测量 开发板GPC0~4对应的管脚,一直是低电平,没有变化。请大家指点一下哪里出现问题了。

michaelzjh 发表于 2011-9-19 11:49:30

回复 1# michaelzjh


    贴驱动源码(参考飞凌leds的驱动例程):
#include <linux/init.h>
#include <linux/miscdevice.h>

#include <linux/device.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/errno.h>
//#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>

#include <mach/map.h>
#include <mach/regs-clock.h>

#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-c.h>
#include <mach/hardware.h>

#include <plat/gpio-cfg.h>

#define DEVICE_NAME "my_ok6410_leds"
#define MYLEDS_MAJOR 267


static long my_ok6410_leds_ioctl(
                struct file *file,
                unsigned int cmd,
                unsigned long arg)
{
        unsigned tmp;
        switch(cmd){
        case 0:
                break;
        case 1:
                if(arg>4){
                        return -EINVAL;       
                }
                tmp=__raw_readl(S3C64XX_GPCDAT);
                if(cmd)
                        tmp &=(~(1<<arg));
                else
                        tmp |=(1<<arg);
                __raw_writel(tmp,S3C64XX_GPCDAT);
                break;
        default:
                return -EINVAL;
                break;
        }
        return 0;
}

static struct file_operations my_ok6410_leds_fops={
        .owner = THIS_MODULE,
        .unlocked_ioctl = my_ok6410_leds_ioctl,   
};

static struct cdev cdev_myleds;
struct class *myleds_class;

static int __init my_ok6410_leds_init(void)
{
        int ret;
        unsigned tmp;
        dev_t devno;
        printk(KERN_NOTICE "enter my_ok6410_leds_init\n");

        devno=MKDEV(MYLEDS_MAJOR,0);
        ret=register_chrdev_region(devno,1,DEVICE_NAME);
        if(ret<0)
        {
                printk(KERN_NOTICE "can not register myleds device\n");
                return ret;
        }
       
        cdev_init(&cdev_myleds,&my_ok6410_leds_fops);
        cdev_myleds.owner=THIS_MODULE;

        ret=cdev_add(&cdev_myleds,devno,1);
        if(ret)
        {
                printk(KERN_NOTICE "can not add myleds device\n");
                return ret;

        }
        myleds_class=class_create(THIS_MODULE,"myleds_class");
        if(IS_ERR(myleds_class)){
                printk("Err: Failed in creating class\n");
                return -1;
        }
        device_create(myleds_class,NULL,MKDEV(MYLEDS_MAJOR,0),NULL,DEVICE_NAME);
       
        //gpc0-3 pull up
        tmp =__raw_readl(S3C64XX_GPCPUD);
        tmp &= (~0xFFFF);
        tmp |=0xaa;
        __raw_writel(tmp,S3C64XX_GPCPUD);

        //gpc0-3 output mode
        tmp = __raw_readl(S3C64XX_GPCCON);
        tmp &= (~0xFFFF);
        tmp |= 0x1111;
        __raw_writel(tmp,S3C64XX_GPCCON);
       
        //gpc0-3 output 0
        tmp = __raw_readl(S3C64XX_GPCDAT);
        tmp |= 0x10;
        __raw_writel(tmp,S3C64XX_GPCDAT);

        printk(DEVICE_NAME " initialized\n");

        return 0;
       
}

static void __exit my_ok6410_leds_exit(void)
{
        cdev_del(&cdev_myleds);
        unregister_chrdev_region(MKDEV(MYLEDS_MAJOR,0),1);
        printk(KERN_NOTICE "my_ok6410_leds_exit\n");
}

module_init(my_ok6410_leds_init);
module_exit(my_ok6410_leds_exit);

MODULE_LICENSE("GPL");

michaelzjh 发表于 2011-9-19 11:51:10

回复 2# michaelzjh


    测试程序源码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

int main(){
        int fd,ret;
        char *i;
        fd=open("/dev/my_ok6410_leds",0);
        if(fd<0){
                printf("open device error\n");       
                exit(0);
        }
        else{
                printf("succeeded to open device\n");
                while(1){
                        ioctl(fd,1,0);
                        ioctl(fd,0,1);
                        ioctl(fd,0,2);
                        ioctl(fd,0,3);
                        if(ret==0)
                                printf("led1 is on!\n");
                        sleep(2);
                        ioctl(fd,0,0);
                        ioctl(fd,1,1);
                        ioctl(fd,0,2);
                        ioctl(fd,0,3);
                        if(ret==0)
                                printf("led2 is on!\n");
                        sleep(2);
                        ioctl(fd,0,0);
                        ioctl(fd,0,1);
                        ioctl(fd,1,2);
                        ioctl(fd,0,3);
                        if(ret==0)
                                printf("led3 is on!\n");
                        sleep(2);
                        ioctl(fd,0,0);
                        ioctl(fd,0,1);
                        ioctl(fd,0,2);
                        ioctl(fd,1,3);
                        if(ret==0)
                                printf("led4 is on!\n");
                        sleep(2);
                }
                close(fd);
        }
        return 0;

}

michaelzjh 发表于 2011-9-19 11:56:41

动态加载驱动时的输出:
enter my_ok6410_leds_init
my_ok6410_leds initialized
指令cat /proc/devices 终端输出:
Character devices:
10 misc
267 my_ok6410_leds
12 input
lsmod指令终端输出:
my_ok6410_leds 1378 2 -Live 0xbf000000
调试信息输出:
succeeded to open device
led1 is on!
led2 is on!
led3 is on!
led4 is on!
led1 is on!
led2 is on!
led3 is on!
led4 is on!
.....

michaelzjh 发表于 2011-9-19 12:02:23

请大家指点一下哪里有问题?
使用的是GPIO管脚GPC0~4

michaelzjh 发表于 2011-9-19 17:05:55

自己搞好了。
谢谢飞凌的支持。
解决方法是在驱动程序里多添加 printk输出信息,然后观察输出。

飞凌-fatfish 发表于 2011-9-20 08:15:06

呵呵,看来电话支持中说对了。
以后是不是该出一点调试教程了。。。

beamdave 发表于 2011-9-21 16:53:42

yiyishiwo 发表于 2011-9-22 08:54:09

飞凌-chongzi 发表于 2011-9-22 17:32:50

如果灯号大于4就返回EINVAL读出GPCDAT,如果CMD为0就点亮第arg个灯,如果为1就关闭第arg个灯写回寄存器

myem007 发表于 2011-10-7 00:08:54

页: [1]
查看完整版本: 请大家指点:OK6410 GPC0~4点不亮LED