平台设备驱动之平台驱动

发布时间:2023-06-07  

驱动层需要实现的结构体是struct platform_driver,它用来描述一个设备的驱动信息。


结构如下 (includelinuxplatform_device.h)


1 struct platform_driver {

2     int (*probe)(struct platform_device *);//探测

3     int (*remove)(struct platform_device *);//移除

4     void (*shutdown)(struct platform_device *);//关闭

5     int (*suspend)(struct platform_device *, pm_message_t state);//挂起

6     int (*resume)(struct platform_device *);//唤醒

7     struct device_driver driver;

8     struct platform_device_id *id_table;

9 };


其中probe和remove是必需实现的,跟在设备层提到的注册和注销函数有关。其他函数根据需要,自行实现。


struct device_driver中的name成员很重要,必须要和设备层struct platform_device中的name成员相同,这样才能实现驱动层和设备层的绑定。


结构如下   (includelinuxdevice.h)


struct device_driver {

    const char        *name;

    struct bus_type        *bus;


    struct module        *owner;

    const char        *mod_name;    /* used for built-in modules */


    bool suppress_bind_attrs;    /* disables bind/unbind via sysfs */


    int (*probe) (struct device *dev);

    int (*remove) (struct device *dev);

    void (*shutdown) (struct device *dev);

    int (*suspend) (struct device *dev, pm_message_t state);

    int (*resume) (struct device *dev);

    const struct attribute_group **groups;


    const struct dev_pm_ops *pm;


    struct driver_private *p;

};

平台驱动层核心API

int platform_driver_register(struct platform_driver *drv)                  ( driversbaseplatform.c)

void platform_driver_unregister(struct platform_driver *drv)            ( driversbaseplatform.c)

struct resource *platform_get_resource( struct platform_device *dev, unsigned int type, unsigned int num)     ( driversbaseplatform.c)

int platform_get_irq( struct platform_device *dev, unsigned int num)     ( driversbaseplatform.c)

 

 

平台驱动的实现步骤:

1.编写probe函数

2.编写remove函数

3.定义struct platform_drv结构,并填充这个结构(注,此结构是自己定义的,结构中包含的内容也是自己定义的;这个结构其实是将驱动函数中用到的变量,写到了一起,定义成此结构,方便了其它函数的调用) 

4.在模块的初始化函数中调用platform_driver_register(struct platform_driver *drv), 以注册

5.在模块卸载函数中调用platform_driver_unregister(struct platform_driver *drv), 以注销

 

实现代码如下:leds_platform_driver.c

  1 #include

  2 #include

  3 #include

  4 

  5 #include

  6 #include

  7 #include

  8 #include

  9 #include

 10 #include

 11 #include

 12 #include

 13 #include

 14 #include

 15 #include

 16 

 17 

 18 #define uint unsigned int

 19 #define uchar unsigned char

 20 

 21 struct led_info

 22 {

 23     unsigned int pin_bit;

 24 };

 25 

 26 struct gpioreg

 27 {

 28     volatile unsigned long vr_gpbcon;

 29     volatile unsigned long vr_gpbdat;

 30     volatile unsigned long vr_gpbup;

 31 };

 32 

 33 //自己定义的struct platform_drv结构

 34 struct s3c2440_leds_drv{

 35     dev_t dev_nr;

 36     struct cdev *cdev_led;

 37     struct class *led_class;

 38     struct resource *ledres;

 39     struct led_info *led_pdata;

 40     struct device *this_device;

 41     struct gpioreg *vr_gpioreg;

 42     struct file_operations leds_ops;

 43 };

 44 

 45 #define DEVICE_NAME "s3c2440leds"

 46 #define LED_ON 1

 47 #define LED_OFF 0

 48 

 49 static struct s3c2440_leds_drv s3c2440_leds_drv_data;

 50 static int leds_open(struct inode *inode, struct file *file)

 51 {

 52     unsigned int tmp=0, up=0, dat=0;

 53     unsigned int i=0;

 54     uint pin_bit=s3c2440_leds_drv_data.led_pdata->pin_bit;

 55     

 56     tmp=s3c2440_leds_drv_data.vr_gpioreg->vr_gpbcon;

 57     up=s3c2440_leds_drv_data.vr_gpioreg->vr_gpbcon;

 58     dat=s3c2440_leds_drv_data.vr_gpioreg->vr_gpbup;

 59     printk("leds_open:1111rn");

 60 

 61     for(;i<16;i++)

 62     {

 63         if((1< 64         {                          //tmp的2i位置1,2i+1位置0,其他位不变,

 65             tmp&=~(3< 66             tmp|=(1< 67             up|=(1< 68             dat|=(1< 69         }

 70     }

 71     

 72     s3c2440_leds_drv_data.vr_gpioreg->vr_gpbcon=tmp;

 73     s3c2440_leds_drv_data.vr_gpioreg->vr_gpbup=up;

 74     s3c2440_leds_drv_data.vr_gpioreg->vr_gpbdat=dat;

 75     return 0;

 76 }

 77 

 78 static long leds_ioctl(struct file *filp, uint cmd, unsigned long arg)

 79 {

 80     uint tmp=0,i=0,j=0;

 81     uint ledbit[16]={0};

 82     uint pin_bit=s3c2440_leds_drv_data.led_pdata->pin_bit;

 83 

 84     for(i=0;i<16;i++)

 85     {

 86         if((1< 87         {

 88             ledbit[j]=i;

 89             //printk("ledbit[%d]:%drn",j,i)

 90             j++;

 91         }

 92     }

 93     //检查传入的led的编号是否大于led总数

 94     if(arg>=j)

 95         return -EINVAL;

 96     mb();//防止编译器对下面的代码进行优化

 97     tmp=s3c2440_leds_drv_data.vr_gpioreg->vr_gpbdat;

 98     mb();

 99 

100     printk("cmd:%d  tmp:%drn",cmd,tmp);

101     

102     switch(cmd)

103     {

104     case LED_ON:

105         tmp &=~(1<106         s3c2440_leds_drv_data.vr_gpioreg->vr_gpbdat=tmp;

107         return 0;

108 

109     case LED_OFF:

110         tmp|=1<111         s3c2440_leds_drv_data.vr_gpioreg->vr_gpbdat=tmp;

112         return 0;

113 

114     default:

115         printk("ioctl() cmd is errrn");

116         return -EINVAL;

117     }

118 }

119 

120 static int  led_probe(struct platform_device *pdev)

121 {

122     int msize,val,err;

123 //    printk("%s is callrn",_FUNCTION_);

124     printk("led_probe is callrn");

125 

126     //获取平台数据

127     s3c2440_leds_drv_data.led_pdata=pdev->dev.platform_data;

128     

129     if(!s3c2440_leds_drv_data.led_pdata)

130     {

131         printk("get platform_data errorn");

132         return -1;

133     }

134     

135     s3c2440_leds_drv_data.ledres=platform_get_resource(pdev,IORESOURCE_MEM,0);

136     if(!s3c2440_leds_drv_data.ledres)

137     {

138         printk("get resource errorn");

139         return -1;

140     }

141 //

142     msize=s3c2440_leds_drv_data.ledres->end-s3c2440_leds_drv_data.ledres->start+1;

143 //向内核申请资源

144     s3c2440_leds_drv_data.ledres=request_mem_region(

145             s3c2440_leds_drv_data.ledres->start,msize,DEVICE_NAME);

146     if(!s3c2440_leds_drv_data.ledres)

147     {

148         printk("request resource errorn");

149         return -1;

150     }

151 

152     s3c2440_leds_drv_data.vr_gpioreg=ioremap_nocache(

153                 s3c2440_leds_drv_data.ledres->start,msize);

154     if(!s3c2440_leds_drv_data.vr_gpioreg)

155     {

156         printk("ioremap_nocache errorn");

157         release_region(    s3c2440_leds_drv_data.ledres->start,msize);

158         return -1;

159     }

160     memset(    s3c2440_leds_drv_data.vr_gpioreg,0,sizeof(struct gpioreg));

161 //申请设备号

162     val=alloc_chrdev_region(&s3c2440_leds_drv_data.dev_nr,0,1,DEVICE_NAME);

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>