历史上的今天
返回首页

历史上的今天

今天是:2025年01月17日(星期五)

正在发生

2019年01月17日 | 2416开发记录七: platform驱动之LED(misc)

2019-01-17 来源:eefocus

platform驱动的简单介绍


前几篇介绍了最简单的LED驱动写法,在linux2.6中提出了platform驱动,具体为什么要这么做后面博客再解释吧。 


这里的platform驱动只是一个框架,并没有体现platform驱动的意义,因为在driver中没有使用device定义的资源。后面会再写一个真正的platfom。本篇算是入门练手,体会下吧。 


pltform机制本身使用并不复杂,由两部分组成:platform_device和platform_driver。通过platform机制开发底层驱动的大致流程为:定义platform_deive->注册platform_device->定义platform_driver->注册platform_driver 


好了,按照要求我们如果想编写一个platform驱动就需要编写两个模块了。一个设备模块dev。一个驱动模块driver。另外再编写一个应用程序来验证下。


platform_device

//my2416PlatformLedDev.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/* 参考arch/arm/plat-s3c24xx/devs.c */



/*1. 根据芯片手册来获取资源*/

static struct resource led_resource[] = {

 [0] = {

  .start = S3C2410_GPBCON,//使用2416开发板的GPB1,暂时我只是定义了资源,但是在driver中并没有使用定义的资源(因为第一次写还不熟悉,后面会再写一个led的platform驱动来使用device定义的资源,这样才能发挥platform驱动的真正意义:platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动中使用这些资源时通过platform device提供的标准结构进行申请并使用。这样提高了驱动和资源的独立性,并且具有较好的可移植性和安全性(这些标准接口是安全的))

  .end   = S3C2410_GPBDAT,

  .flags = IORESOURCE_MEM,

 },

 //[1] = {

 // .start = 5,

 // .end   = 5,

 // .flags = IORESOURCE_IRQ,

 //},

};


void led_release(struct device *dev)


}


/*1.构建平台设备结构体,将平台资源加入进来*/

struct platform_device led_device = {

 .name    = "myplatformled", /* 使用名为"myplatformled"的平台驱动 ,加载驱动之后在sys/bus/platform/devices/目录下生成myplatformled设备*/

 .id    = -1,

 .dev = {

  .release = led_release,

 },

 .num_resources   = ARRAY_SIZE(led_resource),

 .resource   = led_resource,

};


/*2。把我们的设备资源挂在到虚拟总线的设备连表中去*/

int led_dev_init(void)

{

 platform_device_register(&led_device);   

 return 0;

}


void led_dev_exit(void)

{

 platform_device_unregister(&led_device);

}


module_init(led_dev_init);

module_exit(led_dev_exit);


MODULE_LICENSE("GPL"); 



对应的makefile文件为


#Makefile for .c

ARCH=arm

CROSS_COMPILE=arm-linux-

ifneq ($(KERNELRELEASE),)

    obj-m := my2416PlatformLedDev.o

else

#bbblack kernel

KERNELDIR ?= /home/zyd/soft/s3c2416/20140409_HELPER2416/Helper2416/source/s3c-linux.jyx

PWD := $(shell pwd)

modules:

    make -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules

modules_install:

    make -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules_install

app: app.c

    $(CROSS_COMPILE)gcc -o app app.c

clean:

    $(MAKE) -C $(KDIR) M=$(PWD) clean

endif


playform driver

//my2416PlatformLedDriver.c

#include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

 #include

#include


#define DEVICE_NAME "myleds"//加载驱动之后会在/dev/目录下发现myleds,应用程序可以使用


#define LED_ON 0 //根据原理图,0点亮led,1熄灭led

#define LED_OFF 1

 //定义GPIO管脚

 static unsigned long led_table [] =

  {

      S3C2410_GPB(1),  //不能是S3C2410_GPB5;  因为没有这样定义,可以通过#define S3C2410_GPB5 S3C2410_GPB(5)

      //S3C2410_GPF(1),

      //S3C2410_GPF(2),

      //S3C2410_GPF(3),

 };

 //设置管脚模式

 static unsigned int led_cfg_table [] =

  {

      S3C2410_GPIO_OUTPUT, //随内核版本中定义类型的变化,在arch/arm/mach-sc2410/include/mach/Regs-gpio.h文件中定义

      //S3C2410_GPIO_OUTPUT,

      //S3C2410_GPIO_OUTPUT,

      //S3C2410_GPIO_OUTPUT,

 };

 static int my2416_leds_ioctl(struct file* filp, unsigned int cmd,unsigned long arg)

 {

   switch(cmd)

   {

      case LED_ON:

         s3c2410_gpio_setpin(S3C2410_GPB(1), LED_ON);

         break;

      case LED_OFF:

         //s3c2410_gpio_setpin(led_table[arg], !cmd);

         s3c2410_gpio_setpin(S3C2410_GPB(1), LED_OFF);

         break;

      default:

         printk("LED control:no cmd\n");

         printk("LED control are LED_ON or LED_OFF\n");

         return(-EINVAL);

   }

   return 0;

 }

 //dev_fops操作指令集

 static struct file_operations my2416Led_fops =

 {

      .owner =THIS_MODULE,

      .unlocked_ioctl =my2416_leds_ioctl,//这里必须是unlocked_ioctl而不是ioctl。

 };

 //第三步:混杂设备定义

 static struct miscdevice my2416Ledmisc =

  {

      .minor = MISC_DYNAMIC_MINOR,

      .name = DEVICE_NAME,//加载驱动之后会在/dev/目录下发现myleds,应用程序可以使用

      .fops = &my2416Led_fops,

 };

/*3。实现probe函数*/

static int led_probe(struct platform_device *dev)

{

   int ret;


   int i;

   ////这里只定义了一个io口GPB1

   for (i = 0; i < 1; i++)

   {

       s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);

       s3c2410_gpio_setpin(led_table[i], 0);

   }

   ret = misc_register(&my2416Ledmisc);


   printk (DEVICE_NAME"\tinitialized\n");


   return ret;

}


int led_remove(struct platform_device *dev)

{

   misc_deregister(&my2416Ledmisc);

}


/*1。构建平台驱动结构体,不知道的时候可以看别人的*/

static struct platform_driver led_driver = {

 .probe  = led_probe,     /* 平台总线下增加一个平台设备时,调用枚举函数 */

 .remove  = led_remove,    /* 平台总线下去掉一个平台设备时,调用remove函数 */

 .driver  = {

  .name = "myplatformled",       /* 能支持名为"myplatformled"的平台设备 */

  .owner = THIS_MODULE,

 },

};


/*2。注册,把我们的驱动加入到平台设备驱动连表中去*/

static int led_drv_init(void)

{

   int ret;

   //网上的例子有    通常采用函数platform_device *platform_device_alloc(const char *name, int id)动态申请,通常name就是需要申请的设备名,而id为-1。然后采用int platform_device_add(struct platform_device *pdev)或者int platform_device_register(struct platform_device *pdev)

   //这里只使用了platform_device_register也成功了,具体为什么以后再分析。

    注册定义好的设备即可。

   ret=platform_driver_register(&led_driver);

   return ret;

}


static void __exit led_drv_exit(void)

 {

    platform_driver_unregister(&led_driver);

 }


module_init(led_drv_init);

module_exit(led_drv_exit);


MODULE_LICENSE("GPL"); 


对应的makefile文件如下


#Makefile for .c

ARCH=arm

CROSS_COMPILE=arm-linux-

ifneq ($(KERNELRELEASE),)

    obj-m := my2416PlatformLedDriver.o

else

#bbblack kernel

KERNELDIR ?= /home/zyd/soft/s3c2416/20140409_HELPER2416/Helper2416/source/s3c-linux.jyx

PWD := $(shell pwd)

modules:

    make -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules

modules_install:

    make -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules_install

app: app.c

    $(CROSS_COMPILE)gcc -o app app.c

clean:

    $(MAKE) -C $(KDIR) M=$(PWD) clean

endif


测试应用程序

#include

#include

#include

#include

#include

#include

#include



#define DEVICE_NAME "/dev/myleds"


#define LED_ON 0

#define LED_OFF 1


int main()

{

    int fd;

    int ret;

    char *i;

    char count=0;


    printf("My2416 led dev test!\n");


    fd=open(DEVICE_NAME,O_RDWR);

    printf("fd=%d\n",fd);

    if(fd==-1)

    {

        printf("open device %s error\n",DEVICE_NAME);

    }

    else

    {

        for(count=0;count<10;count++)

        {

            ioctl(fd,LED_OFF);

            sleep(1);

            ioctl(fd,LED_ON);

            sleep(1);

        }

        ret=close(fd);

        printf("ret =%d\n",ret);

        printf("Close ledapp succeed!\n");

    }

    return 0;

}



驱动加载的说明


首先加载设备,这里编译出来的是my2416PlatformLedDev.ko,加载之后在/sys/bus/platform/device目录下生成myplatformled。也就是和.name = “myplatformled”名称一致。


然后加载驱动,这里编译出来是my2416PlatformLedDriver.ko,加载之后在/sys/bus/platform/driver目录下生成myplatformled。也就是和.name = “myplatformled”名称一致。同时在/dev目录下生成myleds。应用程序就是使用的/dev/myleds。来操作设备的。


这里只是一个简单的platform驱动,只是在device中定义了资源,但是再driver中并没有使用资源(没有调用platform_get_resource函数。)因此这里并没有体现出platform的意义。后面会修改程序,做一个真正的platform驱动来。


下面几篇先介绍一下platform的基本知识,为写一个真正的platform驱动作个理论基础吧。

推荐阅读

史海拾趣

Allegro公司的发展小趣事

Allegro Microsystems, Inc.是一家专注于开发、制造和销售磁性、混合和传感器集成电路的公司。以下是关于Allegro公司发展的五个相关故事:

  1. 创立与早期发展: Allegro公司成立于1967年,最初名为RMS Electronics。该公司最初专注于生产磁性元件和感应器,以满足汽车和工业市场的需求。随着时间的推移,Allegro迅速发展,并在磁性传感器技术领域取得了重要进展。

  2. 成为行业领导者: 在20世纪90年代,Allegro开始将重点转向混合集成电路的开发,这进一步加强了公司在汽车电子和工业自动化市场的地位。Allegro通过不断创新和技术投资,逐渐成为全球领先的磁性传感器和混合集成电路制造商之一。

  3. 技术创新与专利保护: Allegro公司在磁性传感器和混合集成电路领域积累了丰富的专利技术。该公司不断进行研发和技术创新,推出了许多行业领先的产品,如电流传感器、霍尔效应传感器等。Allegro不仅积极保护自己的知识产权,还与其他公司合作,共同推动技术的进步。

  4. 全球化发展: 随着全球汽车和工业市场的不断发展,Allegro公司积极拓展国际业务,并在全球范围内建立了广泛的销售网络和生产基地。公司在美国、欧洲和亚洲设有多个研发中心和制造工厂,以满足不同地区客户的需求。

  5. 可持续发展与未来展望: Allegro公司致力于可持续发展和社会责任,采取了多项措施来减少对环境的影响,如提高能源效率、减少废物排放等。未来,Allegro将继续投入研发和创新,推出更多高性能、低功耗的产品,以满足不断增长的市场需求,并在全球范围内维持其领先地位。

Automatic Connector公司的发展小趣事

在电子连接器行业,品质是决定企业生死存亡的关键。Automatic Connector公司深知这一点,因此在生产过程中严格执行品质管理标准。公司引进了先进的生产设备和质量检测仪器,确保每一件产品都符合高标准的质量要求。同时,公司还建立了完善的售后服务体系,及时解决客户在使用过程中遇到的问题。凭借卓越的品质和优质的服务,Automatic Connector赢得了客户的信赖和好评。

Advanced Semiconductor, Inc.公司的发展小趣事

为了进一步扩大市场份额,ASI积极寻求与全球各大电子企业的合作。通过与这些企业的战略合作,ASI不仅获得了更多的订单和市场份额,还进一步提升了自身的技术水平和创新能力。同时,ASI也积极参与国际半导体行业的交流和合作,与全球同行共同推动半导体技术的发展。

Anpec(茂达)公司的发展小趣事

随着市场的不断变化和客户需求的日益多样化,茂达电子开始积极扩展产品线。除了原有的电源转换及电源管理IC外,公司还成功研发了放大器及驱动IC、离散式功率元件等系列产品。这些新产品的推出,不仅丰富了茂达电子的产品线,也为客户提供了更多样化的选择。

A1 PROS公司的发展小趣事

在2000年,A1 PROS在韩国正式成立,初创期的它,主要专注于黑白CCD芯片的研发与生产。当时,随着数字技术的兴起,电子摄像头逐渐普及,市场对高质量的图像传感器需求日益增长。A1 PROS凭借其核心团队在半导体技术方面的深厚积累,成功研发出多款性能优越的黑白CCD芯片,并很快在市场上占据了一席之地。

为了拓展业务,A1 PROS积极寻求合作伙伴。2003年,它与台湾的昱生电子有限公司建立了合作关系,后者成为A1 PROS在台湾地区的主要经销商。这一合作不仅帮助A1 PROS打开了台湾市场,也为后续进军更广阔的亚洲市场奠定了基础。

Eureka Microelectronics Inc公司的发展小趣事

为了支持公司的持续发展和业务扩张,Eureka成功完成了多轮融资。这些融资不仅为公司提供了充足的资金支持,也吸引了众多投资者的关注。借助这些资金,Eureka加大了在研发、生产、销售等方面的投入,进一步提升了公司的竞争力和市场地位。同时,公司也积极开展战略合作,与上下游企业建立了紧密的合作关系,共同推动产业链的发展。

问答坊 | AI 解惑

jffs2文件系統挂載出錯,求助

瘋狂的出jffs2_scan_eraseblock錯誤。 我使用的是 8M Nor Flash 但是 沒有分區,請問 分區的作用是什麽? 這個問題最可能的原因是什麽,仰仗各位的經驗了。…

查看全部问答>

出现: hr -2147221164 {没有注册类别 } HRESULT

        if (dlgPush.DoModal())         {                 //得到pCERDA接口                 HRESULT hr = CoCr ...…

查看全部问答>

jedec_probe探测SST39vf3201的疑问

CPU:NXP LPC2478 Flash:NOR SST39VF3201:4MB,4k扇区,地址:0x81000000 想在4M的NOR flash上作jffs2根文件系统,自己写了MTD驱动: #define FLASH_BASE_ADDR                0x81000000 #define F ...…

查看全部问答>

求bin、com、exe二进制文件之间的区别

求bin、com、exe等二进制文件之间的区别…

查看全部问答>

我现在从事MIS系统的开发,想向硬件开发上深入一下,大家给点意建!!!

我已经从事MIS开发二年多了,主要是J2EE.这类开发是纯软件的,感觉现在做起来很辛苦而且市场越来越不理想了.     现在的软件产品能体现出大利润的我发现都要和硬件结合,于是我想在这方面深入一下,业内的朋友能不能给点议建?   &nbs ...…

查看全部问答>

南京招聘:有嵌入式及硬件基础知识的Delphi BCB程序员,从事监控主站开发

南京招聘:有嵌入式及硬件基础知识的Delphi BCB程序员,从事监控主站开发 要求:      1:熟悉Delphi开发环境。      2:熟练使用SQL-Server编程语言      3:了解一定的硬件知识和 ...…

查看全部问答>

求DXP常用元件封装库 pcblib格式的

求DXP常用元件封装库 pcblib格式的 邮箱是xubbwd@126.com…

查看全部问答>

请教:液晶显示屏选型

本帖最后由 dontium 于 2015-1-23 13:32 编辑 打算利用TMS320LF2407A作主控芯片,作一些有关控制和AD采样方面的课题,要求在液晶显示屏上能实时显示信号波形和幅值。不知用什么显示屏适合,望大虾指点!! 谢了先 …

查看全部问答>