你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

Stm32mp157A-DK1评估Linux LED驱动-5 platform设备

[复制链接]
寒门过河卒 发布时间:2021-7-1 15:32
之前的程序说到底只是对字符设备的一种简化写法,使用设备树进行寄存器的地址定义然后使用gpio子系统对寄存器进行设置。但是这些程序都是直接写了一个驱动对Linux进行操作,在实际的工程应用中这种做法的风险很大,如果有多个应用程序希望对同一个设备进行操作,此时会发生两种可能,一种是误操作,一种时堵塞。在实际应用中会有一个中间层负责调度,从而解决这个问题。
QQ图片20210701153020.png
接下来我们要做的就是把新字符设备的驱动例程拆分为两部分:驱动程序、设备程序中间通过platform接口进行链接。
新建文件leddevice.c,用于存放设备程序,其中主要为寄存器相关程序。
头文件需要添加 :
#include<linux/platform_device.h>
然后将寄存器相关复制进去:
#definePERIPH_BASE                       (0x40000000)    //查阅手册第158页,外设总线地址为AB1-AB5其地址为0x4000 0000 – 0X5FFF FFFF。
#defineMPU_AHB4_PERIPH_BASE                   (PERIPH_BASE+ 0x10000000)     //查阅手册第158页,gpios总线AHB4,地址为0X5000 0000 - 0x5001 FFFF。
#defineRCC_BASE                          (MPU_AHB4_PERIPH_BASE + 0x0000) //查阅手册第162页,gpios时钟,地址为0X50000000-0X5000 0FFFF 。
#defineRCC_MP_AHB4ENSETR                       (RCC_BASE+ 0XA28) //查阅手册第866页,RCC_MP_AHB4ENSETR寄存器的偏移地址为0XA28,其负责GPIOA-K的时钟开关
#defineGPIOI_BASE                                        (MPU_AHB4_PERIPH_BASE+ 0x2000) //查阅手册第162页,GPIOA地址为0X5000 2000-0X5000 23FF 。
//接下来是GPIO相关的寄存器,查阅手册第1086页,可以查阅到各个寄存器的偏移地址。
#defineGPIOI_MODER                            (GPIOI_BASE + 0x0000)         
#defineGPIOI_OTYPER                            (GPIOI_BASE + 0x0004)
#defineGPIOI_OSPEEDR                          (GPIOI_BASE + 0x0008)
#defineGPIOI_PUPDR                             (GPIOI_BASE + 0x000C)      
#defineGPIOI_BSRR                         (GPIOI_BASE+ 0x0018)
之后定义platform结构体用来调用寄存器:
staticstruct platform_device leddevice = {
       .name = "xhy-led",
       .id = -1,
       .dev = {
              .release = &led_release,
       },
       .num_resources =ARRAY_SIZE(led_resources),
       .resource = led_resources,
       };
结构体中调用的与两个,一个release和一个resources。&led_release为总线释放:
staticvoid led_release(struct device *dev)
{
       printk("led devicereleased!\r\n");
}
resource时一个resources数组用于存放寄存器地址。
staticstruct resource led_resources[] = {
       [0] = {
              .start      = RCC_MP_AHB4ENSETR,
              .end       = (RCC_MP_AHB4ENSETR + REGISTER_LENGTH - 1),
              .flags      = IORESOURCE_MEM,
       },     
       [1] = {
              .start       = GPIOI_MODER,
              .end = (GPIOI_MODER + REGISTER_LENGTH - 1),
              .flags      = IORESOURCE_MEM,
       },
       [2] = {
              .start       = GPIOI_OTYPER,
              .end = (GPIOI_OTYPER + REGISTER_LENGTH - 1),
              .flags      = IORESOURCE_MEM,
       },
       [3] = {
              .start       = GPIOI_OSPEEDR,
              .end = (GPIOI_OSPEEDR + REGISTER_LENGTH - 1),
              .flags      = IORESOURCE_MEM,
       },
       [4] = {
              .start       = GPIOI_PUPDR,
              .end = (GPIOI_PUPDR + REGISTER_LENGTH - 1),
              .flags      = IORESOURCE_MEM,
       },
       [5] = {
              .start       = GPIOI_BSRR,
              .end = (GPIOI_BSRR + REGISTER_LENGTH - 1),
              .flags      = IORESOURCE_MEM,
       },
};

& s5 _4 G5 `" k
接下来时接口程序:leddevice_init和leddevice_exit,分别是platform的egister和unregister:
staticint __init leddevice_init(void)
{
       returnplatform_device_register(&leddevice);
}
staticvoid __exit leddevice_exit(void)
{
       platform_device_unregister(&leddevice);
}
设备层的程序写好后需要由驱动程序来调用设备程序,驱动程序中的设备寄存器地址设置删除掉,.release由于在设备程序中已定义所以也需要删除。
接口程序和设备驱动一样为platform的egister和unregister,两程序一模一样。
对应设备程序的platform结构体这里也需要定义一个platform结构体:
staticstruct platform_driver led_driver = {
       .driver            ={
              .name     = "xhy-led",                 
       },
       .probe           =led_probe,
       .remove         =led_remove,
};//platform驱动结构体
.name和设备程序中一至,这里定义了两个函数:led_probe和led_remove,
其中led_remove存放原来的leddevice_exit程序,也就是取消映射以及设备的注销。led_probe放原来的leddevice_init用于对设备的初始化。
这里需要改动的时在寄存器映射之前需要从设备程序的leddevice中读取6个寄存器的地址,之后才能把地址映射出来:‘
4 V) P4 `: i1 s* e1 p
for (i =0; i < 6; i++) {
              ledsource =platform_get_resource(dev, IORESOURCE_MEM, i); /* 依次MEM类型资源 */
              if (!ledsource) {
                     dev_err(&dev->dev,"No MEM resource for always on\n");
                     return -ENXIO;
              }
              ressize =resource_size(ledsource);      
       }      
        /*寄存器地址映射 */
      MPU_AHB4_PERIPH_RCC_PI= ioremap(ledsource[0]->start, ressize[0]);
       GPIOI_MODER_PI =ioremap(ledsource[1]->start, ressize[1]);
      GPIOI_OTYPER_PI= ioremap(ledsource[2]->start, ressize[2]);
       GPIOI_OSPEEDR_PI =ioremap(ledsource[3]->start, ressize[3]);
       GPIOI_PUPDR_PI =ioremap(ledsource[4]->start, ressize[4]);
       GPIOI_BSRR_PI =ioremap(ledsource[5]->start, ressize[5]);
platform.rar (34.85 KB, 下载次数: 0)
收藏 评论0 发布时间:2021-7-1 15:32

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版