主题 : 求助,IO驱动问题 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 38961
精华: 0
发帖: 26
金钱: 135 两
威望: 27 点
综合积分: 52 分
注册时间: 2011-03-03
最后登录: 2011-06-23
楼主  发表于: 2011-03-30 22:00

 求助,IO驱动问题

我用的Tiny6410的核心板,2.6.36的内核,仿照友善的led驱动程序,把GPI2、GPI3,GPI4、GPI5,GPI6、GPI7,GPI10、GPI11,GPI12、GPI13分别作为红绿双色LED的控制端,改写的驱动程序中的ioctl函数如下:
static long status_led_ioctl(    struct file *file, unsigned int ledstatus, unsigned long ledno)
{
    unsigned tmp;

    if (ledno >= 5)
    {
        return -EINVAL;
    }
    
    if (ledno >= 3)
    {
        ledno += 1;
    }

    printk("ioctl executed~~~~~~~~~~~~");
    if (ledstatus == LED_FAULT)
    {
        printk("LED_FAULT ledstatus: %d", ledstatus);
        tmp = readl(S3C64XX_GPIDAT);
        tmp &= ~(1 << (2+ledno*2));
        tmp |= (1 << (2+ledno*2+1));
        writel(tmp, S3C64XX_GPIDAT);
        return 0;
    }
    if (ledstatus == LED_RUN)
    {
        printk("LED_RUN ledstatus: %d", ledstatus);
        tmp = readl(S3C64XX_GPIDAT);
        tmp |= (1 << (2+ledno*2));
        tmp &= ~(1 << (2+ledno*2+1));
        writel(tmp, S3C64XX_GPIDAT);
        return 0;
    }
    if (ledstatus == LED_OFF)
    {
        printk("LED_OFF ledstatus: %d", ledstatus);
        tmp = readl(S3C64XX_GPIDAT);
        tmp |= (1 << (2+ledno*2));
        tmp |= (1 << (2+ledno*2+1));
        writel(tmp, S3C64XX_GPIDAT);
        return 0;
    }
    
    return -EINVAL;
}

测试程序主要部分如下:
#define LED_RUN            1
#define LED_FAULT        2
#define LED_OFF            3

static int    ledctrlfd;

static void Error(const char *Msg)
{
    fprintf (stderr, "%s\n", Msg);
    fprintf (stderr, "strerror() is %s\n", strerror(errno));
    //exit(1);
}

int main(int argc, char **argv)
{
        int    iter;
        unsigned ledstatus;

        ledctrlfd    = open(DEVICE_NAME, 0);
        if (ledctrlfd < 0)
        {
            Error(strerror(errno));
            return 0;
        }
        
        ledstatus    = LED_RUN;
        for (iter = 0; iter < 5; iter++)
        {
            printf("ledstatus: %d\n", ledstatus);
            if (ioctl(ledctrlfd, ledstatus, iter) != 0)
            {
                Error(strerror(errno));
            }
                                                               sleep(1);
        }
        sleep(1);
        ledstatus = LED_OFF;
                for (iter = 0; iter < 5; iter++)
                {
                        printf("ledstatus: %d\n", ledstatus);
            if (ioctl(ledctrlfd, ledstatus, iter) != 0)
            {
                Error(strerror(errno));
            }
                                                               sleep(1);
                }
                sleep(1);
        ledstatus = LED_FAULT;
                for (iter = 0; iter < 5; iter++)
                {
                        printf("ledstatus: %d\n", ledstatus);
            if (ioctl(ledctrlfd, ledstatus, iter) != 0)
            {
                Error(strerror(errno));
            }
                                                               sleep(1);
                }
                sleep(1);
                ledstatus = LED_OFF;
                for (iter = 0; iter < 5; iter++)
                {
                        printf("ledstatus: %d\n", ledstatus);
            if (ioctl(ledctrlfd, ledstatus, iter) != 0)
            {
                Error(strerror(errno));
            }
                                                               sleep(1);
                }
                sleep(1);

                
        close(ledctrlfd);
    return 0;
}

结果就是每次ioctl的ledstatus参数设置为LED_FAULT时,ioctl就出错,错误信息是Bad address
求教各位大侠,这到底是怎么一回事。
级别: 新手上路
UID: 38961
精华: 0
发帖: 26
金钱: 135 两
威望: 27 点
综合积分: 52 分
注册时间: 2011-03-03
最后登录: 2011-06-23
1楼  发表于: 2011-03-30 22:04
ledstatus为LED_RUN和LED_OFF时执行都正常。。
级别: 新手上路
UID: 38961
精华: 0
发帖: 26
金钱: 135 两
威望: 27 点
综合积分: 52 分
注册时间: 2011-03-03
最后登录: 2011-06-23
2楼  发表于: 2011-03-31 09:45
发现一个想不通的事。。。把驱动和测试程序里面LED_FAULT的值改成5就好了。。。真想不通。盼解答
级别: 新手上路
UID: 30328
精华: 0
发帖: 16
金钱: 85 两
威望: 17 点
综合积分: 32 分
注册时间: 2010-10-14
最后登录: 2018-12-15
3楼  发表于: 2015-07-16 15:28
我也用到GPIO I port作为gpio口操作led,但是怎么搞 io都不能拉高拉低。在uboot操作寄存器却是可以的,内核驱动却不行。
真是撞见鬼了。