microcreat 发表于 2010-8-27 21:05:29

请教关于platform驱动

#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/ioctl.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <asm/arch/at91sam9260.h>

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/arch/io.h>
#include <asm/arch/gpio.h>

#define DEV_NAME      "AT91SAM9260_LED_SCREEN"

#define LED_SCREEN_MAGIC      'L'
#define LED_SCREEN_ON         _IOW(LED_SCREEN_MAGIC,0,int)
#define LED_SCREEN_OFF          _IOW(LED_SCREEN_MAGIC,1,int)
#define LED_SCREEN_MINOR      125
#define LED_SCREEN_MAJOR      10      
#define LED_SCREEN_CON          0
#define LED_SCREEN_DAT          4
#define LED_SCREEN_UP         8

#define LED_SCREEN_PIN_BASE   PIN_BASE + 0x20

int major;
dev_t devNu;
struct cdev led_screen_cdev;
void   *led_screen_base;


ssize_t led_screen_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset);
ssize_t led_screen_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset);
int led_screen_open(struct inode *inode,struct file *filp);
int led_screen_release(struct inode *inode,struct file *filp);
int led_screen_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg);
static int led_screen_probe(struct platform_device *pdev);
static int led_screen_remove(struct platform_device *pdev);

static unsigned long led_table [] =
{
    //AT91_PIN_PA6,
    AT91_PIN_PB0,
};


struct resource led_screen_resource[] = {
      ={
            .start =LED_SCREEN_PIN_BASE,
            .end   =LED_SCREEN_PIN_BASE + 31,
            .flags =IORESOURCE_MEM,
            }
      };
      
struct file_operations led_screen_opt ={
      .owner   =THIS_MODULE,
      .ioctl   =led_screen_ioctl,
      .open      =led_screen_open,
      .read      =led_screen_read,
      .write   =led_screen_write,
      .release   =led_screen_release,
};

static struct miscdevice misc_led_screen ={
      .minor   =MISC_DYNAMIC_MINOR,
      .name      ="led_screen",
      .fops      =&led_screen_opt,
};

struct platform_device led_screen_Device= {
      .name            ="led_screen",
      .id                =-1,
      .num_resources   =ARRAY_SIZE(led_screen_resource),
      .resource          =led_screen_resource,
      .dev               =
            {
            .release       =led_screen_release,
            }
      };

struct platform_driver led_screen_Driver   ={
      .probe             =led_screen_probe,
      .remove            =led_screen_remove,
      .driver            =      
            {
            .owner         =THIS_MODULE,
            .name          ="led_screen",
            }
      };
               
int led_screen_open(struct inode *inode,struct file *filp)
{
      at91_set_gpio_value(led_table,1);
                //writel(AT91_PIOB,led_screen_base+LED_SCREEN_CON);
      //writel(0,led_screen_base+LED_SCREEN_UP);
      //writel(0,led_screen_base+LED_SCREEN_DAT);
      printk("\n LED_SCREEN open success! \n");
      return 0;
}

ssize_t led_screen_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
{
      return 0;
}

ssize_t led_screen_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
{
      return 0;
}

int led_screen_release(struct inode *inode,struct file *filp)
{
      at91_set_gpio_value(led_table,1);
                printk("\nled_screen_release!\n");
                return 0;
}

int led_screen_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
      printk ( "cmd = %d", cmd );
                at91_set_gpio_value(led_table,cmd);
                printk("\nled_screen_ioctl!\n");
                return 0;
}

static int led_screen_probe(struct platform_device *pdev)
{
      struct resource *res;
      struct device *dev;
      int size;
      int ret;

                at91_set_gpio_output(led_table,1);
      at91_set_gpio_value(led_table,0);
               
      dev=&pdev->dev;
      printk("\nMatch success!\n");
               
      res = platform_get_resource(pdev,IORESOURCE_MEM,0);
      if(res==NULL)
      {
            dev_err(dev,"no memory resource specified\n");
            return -ENOENT;
      }
      size = res->end-res->start +1;

      led_screen_base = ioremap(res->start,size);
               
      if(led_screen_base==NULL)
      {
      dev_err(dev,"fail to ioremap() region\n");
      ret=-EINVAL;
      goto err_req;
      }
               
      ret=misc_register(&misc_led_screen);
      //ret=platform_driver_register();
      if(ret)
      {
            dev_err(dev,"cannot register ledmiscdev!\n");
            goto err_misc;
      }

      err_misc:
                iounmap(led_screen_base);

                err_req:
            return ret;      
}

static int led_screen_remove(struct platform_device *pdev)
{
      //iounmap(ledbase);这一句有问题,加上就会出现oops
      misc_deregister(&misc_led_screen);
      return 0;
}
      
int __init led_screen_init(void)
{

      major = LED_SCREEN_MAJOR;
      printk("\n LED_SCREEN is %d\n",major);
      devNu = MKDEV(LED_SCREEN_MAJOR,LED_SCREEN_MINOR);
   
      platform_device_register(&led_screen_Device);
      platform_driver_register(&led_screen_Driver);
      
      return 0;
}

void __exit led_screen_exit(void)
{
      platform_driver_unregister(&led_screen_Driver);
      platform_device_unregister(&led_screen_Device);
      
}

module_init(led_screen_init);
module_exit(led_screen_exit);

我现在是这个驱动
但是用insmod的时候能打开LED灯
rmmod的时候能关闭
但是open和ioctl的时候就不能控制LED了!我这个驱动是哪里有问题呢!

microcreat 发表于 2010-8-28 13:46:30

沉的好快啊!
顶下!

simonccn 发表于 2010-8-29 09:01:57

open和ioctl的时候,printk的打印信息能出来吗,用dmesg来看看

microcreat 发表于 2010-8-29 18:43:23

open的能出来,但是ioctl不能哈!

microcreat 发表于 2010-8-31 09:57:38

现在我程序修改了!但是open的时候感觉没有和驱动的open联系上!


#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/arch/io.h>
#include <asm/arch/gpio.h>
#include <linux/delay.h>
#include <asm/arch/at91sam9260.h>
#include <asm/arch/at91_pio.h>
#include <linux/miscdevice.h>

#define DEV_NAME "led_screen"
#define PORTB_BASE            0xfffff600// PORTB


ssize_t screen_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset);
ssize_t screen_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset);
int screen_open(struct inode *inode,struct file *filp);
int screen_release(struct inode *inode,struct file *filp);
int screen_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg);
static int led_screen_probe ( struct platform_device *dev );
void led_screen_release(struct device * dev);

// 这个是GPIO的物理地址的基址
static void __iomem *led_screen_base;
static struct resource        *led_screen_mem;

// 控制LED屏的GPIO口
static unsigned long led_screen_table [] =
{
    //AT91_PIN_PA6,
    AT91_PIN_PB0,
};

struct resource led_screen_resource[] = {      
        ={            
                .start =PORTB_BASE,            
                .end   =PORTB_BASE + 512,            
                .flags =IORESOURCE_MEM,            
                }      
        };

struct platform_device led_screen_device= {      
          .name            =DEV_NAME,      
                .id                =-1,      
                .num_resources   =ARRAY_SIZE(led_screen_resource),      
                .resource          =led_screen_resource,      
                .dev               ={            
                                 .release       =led_screen_release,            
                        }      
        };

int screen_open(struct inode *inode,struct file *filp)
{
                printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
               
                writel( 0x0000000f, led_screen_base + PIO_SODR );

                return 0;
}


ssize_t screen_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
{
      return 0;
}

ssize_t screen_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
{
      return 0;
}

int screen_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
      return 0;
}

int screen_release(struct inode *inode,struct file *filp)
{
      return 0;
}

struct file_operations led_screen_opt ={
      .owner   =THIS_MODULE,
      .ioctl   =screen_ioctl,
      .open      =screen_open,
      .read      =screen_read,
      .write   =screen_write,
      .release   =screen_release,
};

static struct miscdevice led_screen_misc ={
      .minor   =MISC_DYNAMIC_MINOR,
      //.name      ="screen",
      .name      =   DEV_NAME,
                .fops      =&led_screen_opt,
};

void led_screen_release(struct device * dev)
{
                printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
}

static int led_screen_probe ( struct platform_device *dev )
{
    struct resource *res;
        int ret = 0;
        int size;

        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

        res = platform_get_resource( dev, IORESOURCE_MEM, 0 );
        if (res == NULL)
                {
                printk("no memory resource specified\n");
                return -ENOENT;
                }
   
        size = (res->end-res->start)+1;
       led_screen_mem = request_mem_region(res->start, size, dev->name);
        if (NULL == led_screen_mem)
                {               
                printk("failed to get memory region\n");               
                ret = -ENOENT;               
                goto err_req;       
                }

        led_screen_base = ioremap(res->start, size);
        if (led_screen_base == 0)
                {               
                printk("failed to ioremap() region\n");               
                ret = -EINVAL;               
                goto err_req;       
                }

        printk("resource is ok!\n");

        /*ret=misc_register(&led_screen_misc);
    if(ret)
      {
      printk("cannot register led_screen_misc miscdev!\n");
                iounmap(led_screen_base);
      return ret;
      }
    */
    writel( 0x0000000f, led_screen_base + PIO_PER );         
        writel( 0x0000000f, led_screen_base + PIO_PUER );               
        writel( 0x0000000f, led_screen_base + PIO_ODSR );         
        writel( 0x0000000f, led_screen_base + PIO_OER );
        writel( 0x0000000f, led_screen_base + PIO_CODR );

    //at91_set_gpio_output(led_screen_table,1);
        //at91_set_gpio_value(led_screen_table,0);

        printk("resource is ok!\n");
       
        return ret;

        err_req:       
                release_resource(led_screen_mem);       
                kfree(led_screen_mem);
                printk("resource is fail!\n");
               
          return ret;
}

static int led_screen_remove ( struct platform_device *dev )
{
        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
        return 0;
}


static struct platform_driver led_screen_driver = {
      .probe   =    led_screen_probe,
                .remove    =    led_screen_remove,
                .driver    =    {
                        .owner    =    THIS_MODULE,
                                                .name   =    DEV_NAME,
                },
};

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

        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

    //at91_set_gpio_output(led_screen_table,1);
        //at91_set_gpio_value(led_screen_table,0);

        ret = platform_device_register ( &led_screen_device );
        if ( ret )
                {
                platform_device_unregister ( &led_screen_device );
      printk ( "platform_device_register is fail!\n" );
                return ret;
                }

        ret=misc_register(&led_screen_misc);
    if(ret)
      {
      printk("cannot register led_screen_misc miscdev!\n");
                iounmap(led_screen_base);
      return ret;
      }
       
        printk ( "platform_device_register is ok!\n" );
        ret = platform_driver_register ( &led_screen_driver );
        if ( ret )
                {
                printk ( "platform_driver_register is fail!\n" );
                platform_driver_unregister ( &led_screen_driver );
                return ret;
                }

        printk ( "platform_driver_register is ok!\n" );
        return ret;
}

static void __exit led_screen_exit ( void )
{
    printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

        //at91_set_gpio_value(led_screen_table,1);
        writel( 0x0000000f, led_screen_base + PIO_SODR );
        platform_driver_unregister ( &led_screen_driver );
        misc_deregister(&led_screen_misc);
        platform_device_unregister ( &led_screen_device );
}

module_init ( led_screen_init );
module_exit ( led_screen_exit );

MODULE_AUTHOR("m");
MODULE_DESCRIPTION("this is led_screen driver modules");
MODULE_LICENSE("Dual BSD/GPL");


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>

int main(void)
{
   int fd;

   printf("%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
   fd=open("/sys/class/misc/led_screen",0);
   if(fd<0)
   {
      printf("can not open /sys/class/misc/led_screen\n");
      goto end1;
   }

   //while(1)
   {
   //ioctl(fd,0,0);
   //sleep(1);
   //ioctl(fd,1,0);
   printf ( "*********\n" );
   //sleep(1);
   }
   close(fd);
end1:
   return 0;
}

希望大侠能帮我看看是!问题出在哪里?

$insmod led_screen.ko
led_screen_init:Aug 31 2010,09:55:58
platform_device_register is ok!
led_screen_probe:Aug 31 2010,09:55:58
resource is ok!
resource is ok!
platform_driver_register is ok!
$./ledtest
main:Aug 31 2010,09:41:28
*********
$rmmod led_screen.ko
led_screen_exit:Aug 31 2010,09:55:58
led_screen_remove:Aug 31 2010,09:55:58
led_screen_release:Aug 31 2010,09:55:58
$dmesg
led_screen_init:Aug 31 2010,09:55:58
platform_device_register is ok!
led_screen_probe:Aug 31 2010,09:55:58
resource is ok!
resource is ok!
platform_driver_register is ok!
led_screen_exit:Aug 31 2010,09:55:58
led_screen_remove:Aug 31 2010,09:55:58
led_screen_release:Aug 31 2010,09:55:58
$


$insmod led_screen.ko
led_screen_init:Aug 31 2010,09:55:58
platform_device_register is ok!
led_screen_probe:Aug 31 2010,09:55:58
resource is ok!
resource is ok!
platform_driver_register is ok!
$ls /sys/bus/platform/devices/
at91_nand      at91_udc       atmel_usart.1led_screen
at91_ohci      at91_wdt       atmel_usart.2macb
at91_rtt.0   atmel_usart.0i2c-gpio       ssc.0
$ls /sys/bus/platform/drivers
at91_nand   at91_wdt      i2c-gpio      rtc-at91sam9
at91_ohci   atmel_usart   led_screen    ssc
at91_udc      gen_nand      macb
$ls /sys/devices/
platformsystem
$ls /sys/devices/platform/
at91_nand      at91_udc       atmel_usart.1led_screen   uevent
at91_ohci      at91_wdt       atmel_usart.2macb
at91_rtt.0   atmel_usart.0i2c-gpio       ssc.0
$ls /sys/class/misc/
fuse      led_screenwatchdog
$
以上可以看到都添加到系统里面去了啊!

simonccn 发表于 2010-8-31 17:47:15

1、fd=open("/sys/class/misc/led_screen",0),0表示的读写权限是什么?
2、在执行你的测试程序时,没看到screen_open()里的printk有打印出来,会不会在创建设备节点时,设备号没对上,打开了其它的设备。
3、如果screen_open()有执行了,那直接对gpio的操作应该起作用,led会有变化。

microcreat 发表于 2010-9-23 20:12:05

fd=open("/sys/class/misc/led_screen
有没有这样打开设备的哈 。??

microcreat 发表于 2010-10-12 23:02:23

可不可以直接用platform_device和platform_driver写驱动哈!
不用msic_device
但是platform_device没有文件操作函数哈!(open函数等)
页: [1]
查看完整版本: 请教关于platform驱动