搜索
bottom↓
回复: 7

请教关于platform驱动

[复制链接]

出0入0汤圆

发表于 2010-8-27 21:05:29 | 显示全部楼层 |阅读模式
#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[] = {
        [0]={
            .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[0],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[0],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[0],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[0],1);
        at91_set_gpio_value(led_table[0],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 led  miscdev!\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了!我这个驱动是哪里有问题呢!

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2010-8-28 13:46:30 | 显示全部楼层
沉的好快啊!
顶下!

出0入0汤圆

发表于 2010-8-29 09:01:57 | 显示全部楼层
open和ioctl的时候,printk的打印信息能出来吗,用dmesg来看看

出0入0汤圆

 楼主| 发表于 2010-8-29 18:43:23 | 显示全部楼层
open的能出来,但是ioctl不能哈!

出0入0汤圆

 楼主| 发表于 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[] = {        
        [0]={            
                .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[0],1);
        //at91_set_gpio_value(led_screen_table[0],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[0],1);
        //at91_set_gpio_value(led_screen_table[0],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[0],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;
}

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

[root@microcreat test]$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!
[root@microcreat test]$./ledtest
main:Aug 31 2010,09:41:28
*********
[root@microcreat test]$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
[root@microcreat test]$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
[root@microcreat test]$


[root@microcreat test]$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!
[root@microcreat test]$ls /sys/bus/platform/devices/
at91_nand      at91_udc       atmel_usart.1  led_screen
at91_ohci      at91_wdt       atmel_usart.2  macb
at91_rtt.0     atmel_usart.0  i2c-gpio       ssc.0
[root@microcreat test]$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
[root@microcreat test]$ls /sys/devices/
platform  system
[root@microcreat test]$ls /sys/devices/platform/
at91_nand      at91_udc       atmel_usart.1  led_screen     uevent
at91_ohci      at91_wdt       atmel_usart.2  macb
at91_rtt.0     atmel_usart.0  i2c-gpio       ssc.0
[root@microcreat test]$ls /sys/class/misc/
fuse        led_screen  watchdog
[root@microcreat test]$
以上可以看到都添加到系统里面去了啊!

出0入0汤圆

发表于 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会有变化。

出0入0汤圆

 楼主| 发表于 2010-9-23 20:12:05 | 显示全部楼层
fd=open("/sys/class/misc/led_screen
有没有这样打开设备的哈 。??

出0入0汤圆

 楼主| 发表于 2010-10-12 23:02:23 | 显示全部楼层
可不可以直接用platform_device和platform_driver写驱动哈!
不用msic_device
但是platform_device没有文件操作函数哈!(open函数等)
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-13 00:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表