zoukankan      html  css  js  c++  java
  • linux驱动(五)内核中静态映射表的建立

    1:我们在linux内核中都是开启mmu的所以都是用的虚拟地址,需要建立VA到PA的映射表;

    我们内核中映射表在arch/arm/mach-s5pv210/mach-smdkc110.c文件中

    建立映射的函数是,smdkc110_map_io建立映射表

    smdkc110_map_io 这个函数调用s5p_init_io函数真正

        s5p_init_io 

            iotable_init

        s3c24xx_init_clocks

        s5pv210_gpiolib_init

        s3c24xx_init_uarts

    smdkc110_map_io 这个函数调用s5p_init_io函数,s5p_init_io

    void __init s5p_init_io(struct map_desc *mach_desc, int size, void __iomem *cpuid_addr)

    我们来看一下s5p_init_io函数的原型需要三个参数:参数1:结构体数组指针,参数2:数组的成员个数;参数三:虚拟地址基地址

    函数s5p_init_io 在调用iotable_init函数建立静态映射表,实际上我们看一下iotable_init函数中跟没有用到之前传的参数2、参数3;

    直接把s5p_iodesc数组名当做数组首地址作为iotable_init函数的第一个参数、ARRAY_SIZE这个时自动计算的这个数组有几个成员组成;

    iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));

     下面我们来分析一下这个man_desc 这个类型的结构体

    struct map_desc {
      unsigned long virtual;      //虚拟地址
      unsigned long pfn;        //物理地址 .pfn = __phys_to_pfn(S5P_PA_CHIPID), 这里把物理地址放入__phys_to_pfn函数中传给.pfn

      unsigned long length;      //长度
      unsigned int type;        //type 
    };

    static struct map_desc s5p_iodesc为一个全局变量,实际上只需要有我们初始化好的这个全局变量数组 

    static struct map_desc s5p_iodesc[] __initdata = {
        {
            .virtual    = (unsigned long)S5P_VA_CHIPID,      //0xFD70_0000
            .pfn        = __phys_to_pfn(S5P_PA_CHIPID),      //0xE000_0000 >> 12
            .length        = SZ_4K,                  //4k
            .type        = MT_DEVICE,                 //0
        }, {
            .virtual    = (unsigned long)S3C_VA_SYS,        //0xFD10_0000
            .pfn        = __phys_to_pfn(S5P_PA_SYSCON),      //0xE010_0000 >> 12
            .length        = SZ_64K,                  //64k
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)S3C_VA_UART,      //0xFE00_0000
            .pfn        = __phys_to_pfn(S3C_PA_UART),      //0xE290_0000 >> 12
            .length        = SZ_4K,  
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)VA_VIC0,
            .pfn        = __phys_to_pfn(S5P_PA_VIC0),
            .length        = SZ_16K,
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)VA_VIC1,
            .pfn        = __phys_to_pfn(S5P_PA_VIC1),
            .length        = SZ_16K,
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)S3C_VA_TIMER,
            .pfn        = __phys_to_pfn(S5P_PA_TIMER),
            .length        = SZ_16K,
            .type        = MT_DEVICE,
        }, {
            .virtual    = (unsigned long)S5P_VA_GPIO,      //0xFD50_0000
            .pfn        = __phys_to_pfn(S5P_PA_GPIO),      //0xE020_0000
            .length        = SZ_4K,                //大小 4k
            .type        = MT_DEVICE,                //0
        },
    };

    我们有了这个map_desc结构体通过iotable_init函数就可以创建我们再map_desc数组中的设置好的物理地址到虚拟地址映射;

    而真正建立虚拟地址到物理地址映射的函数是:create_mapping这个函数;

    static void __init smdkc110_map_io(void)
    {
        s5p_init_io(NULL, 0, S5P_VA_CHIPID);
        s3c24xx_init_clocks(24000000);
        s5pv210_gpiolib_init();
        s3c24xx_init_uarts(smdkc110_uartcfgs, ARRAY_SIZE(smdkc110_uartcfgs));
        s5p_reserve_bootmem(smdkc110_media_devs, ARRAY_SIZE(smdkc110_media_devs));
    #ifdef CONFIG_MTD_ONENAND
        s5pc110_device_onenand.name = "s5pc110-onenand";
    #endif
    #ifdef CONFIG_MTD_NAND
        s3c_device_nand.name = "s5pv210-nand";
    #endif
        s5p_device_rtc.name = "smdkc110-rtc";
    }
    void __init s5p_init_io(struct map_desc *mach_desc,
                int size, void __iomem *cpuid_addr)
    {
        unsigned long idcode;
    
        /* initialize the io descriptors we need for initialization */
        iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
        if (mach_desc)
            iotable_init(mach_desc, size);
    
        idcode = __raw_readl(cpuid_addr);
        s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
    }

     

    void __init iotable_init(struct map_desc *io_desc, int nr)
    {
        int i;
    
        for (i = 0; i < nr; i++)
            create_mapping(io_desc + i);
    }

     关于create_maping函数如何建立映射表参考

    http://blog.csdn.net/huyugv_830913/article/details/5884628

    http://blog.csdn.net/longyue0917/article/details/7424536

    映射表建立函数被调用

    http://blog.csdn.net/tongxinv/article/details/54698188

  • 相关阅读:
    c++ ShellExecuteEx调用java打包的exe程序
    麻省理工学院公开课-第四讲:快速排序 及 随机化 算法
    Win10的IIS与以前版本的一个区别
    干就行了!!!写程序就像珊瑚,分支太多,哪有那么多复用!
    NPoco的使用方法
    为什么前端要写标准代码?
    对于委托、事件、观察者模式最一目了然的代码段
    delphi处理消息的几种方式
    哎呀妈呀,吓死我了,幸好服务器没崩溃。
    Delphi的Hint介绍以及用其重写气泡提示以达到好看的效果
  • 原文地址:https://www.cnblogs.com/biaohc/p/6626062.html
Copyright © 2011-2022 走看看