NXP

LPC3250 Perpheral IO Mapping

2019-07-12 12:05发布

LPC3250 IO空间图

机器描述

    在board-smartarm3250.c中实现: MACHINE_START (LPC3XXX, "SmartARM3250 board with the LPC3250 Microcontroller")           /* Maintainer: Kevin Wells, NXP Semiconductors */           .phys_io= UART5_BASE,           .io_pg_offst= ((io_p2v (UART5_BASE))>>18) & 0xfffc,           .boot_params= 0x80000100,          .map_io= lpc32xx_map_io,       //CPU IO映射入口           .init_irq= lpc32xx_init_irq,           .timer= &lpc32xx_timer,           .init_machine= smartarm3250_board_init, MACHINE_END      

IO映射实现

   LPC3250移植代码对已经安排了外设的片内IO空间进行了映射,包括IRAM、AHB总线上的外设、FAB和APB总线上的外设。在arch-lpc32xx.c中实现:   static struct map_desc lpc32xx_io_desc[] __initdata = { {                                                                                      //AHB0总线空间IO映射           .virtual= io_p2v(AHB0_START),           .pfn= __phys_to_pfn(AHB0_START),           .length= AHB0_SIZE,           .type= MT_DEVICE }, {                                                                                      //AHB1总线空间IO映射           .virtual= io_p2v(AHB1_START),           .pfn= __phys_to_pfn(AHB1_START),           .length= AHB1_SIZE,           .type= MT_DEVICE }, {                                                                                      //FAB和APB总线空间IO映射           .virtual= io_p2v(FABAPB_START),           .pfn= __phys_to_pfn(FABAPB_START),           .length= FABAPB_SIZE,           .type= MT_DEVICE }, {                                                                                     //IRAM空间IO映射           .virtual= io_p2v(IRAM_BASE),           .pfn= __phys_to_pfn(IRAM_BASE),           .length= (SZ_64K * 4),           .type= MT_DEVICE }, };   void __init lpc32xx_map_io(void) {           iotable_init (lpc32xx_io_desc, ARRAY_SIZE (lpc32xx_io_desc)); }  

涉及到的宏定义

platform.h文件中定义所使用的宏定义。以AHB0为例: /* * AHB 0 physical base addresses */          #define SLC_BASE          0x20020000 #define SSP0_BASE        0x20084000 #define SPI1_BASE        0x20088000 #define SSP1_BASE        0x2008C000 #define SPI2_BASE        0x20090000 #define I2S0_BASE        0x20094000 #define SD_BASE           0x20098000 #define I2S1_BASE        0x2009C000 #define MLC_BASE         0x200A8000   #define AHB0_START      SLC_BASE #define AHB0_SIZE        ((MLC_BASE - SLC_BASE) + SZ_4K)  

延伸阅读

    添加用户的特定IO映射

   如果要用户外扩了设备,需要添加IO映射,可以修改.map_io为用户自定义io_map函数,在自定义io_map函数中调用CPU的io_map函数。下面是基于PXA270的mainstone系统。    首先声明一个map_desc结构,然后在自定义io_map函数中调用iotable_init函数对用户空间映射进行初始化:   610    static struct map_desc mainstone_io_desc[] __initdata = { 611        {       /* CPLD */ 612                .virtual        =  MST_FPGA_VIRT, 613                .pfn            = __phys_to_pfn(MST_FPGA_PHYS), 614                .length         = 0x00100000, 615                .type           = MT_DEVICE 616        } 617    }; 618 619    static void __init mainstone_map_io(void) 620    { 621        pxa_map_io(); 622        iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc)); 623 624        /*      for use I SRAM as framebuffer.  */ 625        PSLR |= 0xF04; 626        PCFR = 0x66; 627    } 628 629    MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") 630        /* Maintainer: MontaVista Software Inc. */ 631        .phys_io        = 0x40000000, 632        .boot_params    = 0xa0000100,   /* BLOB boot parameter setting */ 633        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc, 634        .map_io         = mainstone_map_io,            //IO空间映射 635        .init_irq       = mainstone_init_irq, 636        .timer          = &pxa_timer, 637        .init_machine   = mainstone_init, 638    MACHINE_END

    _phys_to_pfn

    _phys_to_pfn在arch/arm/include/asm/memory.h文件中定义: 120   /* 121    * Convert a physical address to a Page Frame Number and back 122    */ 123   #define __phys_to_pfn(paddr)   ((paddr) >> PAGE_SHIFT) 124   #define __pfn_to_phys(pfn)      ((pfn) << PAGE_SHIFT)       而下面这是LPC3250的io_p2v实现: /* Start of virtual addresses for IO devices */ #define IO_BASE         0xF0000000   #define io_p2v(x) (IO_BASE | (((x) & 0xff000000) >> 4) | ((x) & 0x000fffff)) #define io_v2p(x) ((((x) & 0x0ff00000) << 4) | ((x) & 0x000fffff))    

    PAGE_SHIFT

    见arch/arm/include/asm/page.h文件:   13   /* PAGE_SHIFT determines the page size */   14   #define PAGE_SHIFT             12   15   #define PAGE_SIZE               (1UL << PAGE_SHIFT)   16   #define PAGE_MASK               (~(PAGE_SIZE-1))  

    io_p2v

   每个处理器都有自己的io_p2v实现,下面是PXA270处理器的,见arch/arm/mach-pxa/include/mach/hardware.h文件:   28   /*   29    * Intel PXA2xx internal register mapping:   30    *   31    * 0x40000000 - 0x41ffffff <--> 0xf2000000 - 0xf3ffffff   32    * 0x44000000 - 0x45ffffff <--> 0xf4000000 - 0xf5ffffff   33    * 0x48000000 - 0x49ffffff <--> 0xf6000000 - 0xf7ffffff   34    * 0x4c000000 - 0x4dffffff <--> 0xf8000000 - 0xf9ffffff   35    * 0x50000000 - 0x51ffffff <--> 0xfa000000 - 0xfbffffff   36    * 0x54000000 - 0x55ffffff <--> 0xfc000000 - 0xfdffffff   37    * 0x58000000 - 0x59ffffff <--> 0xfe000000 - 0xffffffff   38    *   39    * Note that not all PXA2xx chips implement all those addresses, and the   40    * kernel only maps the minimum needed range of this mapping.   41    */   42    #define io_p2v(x) (0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))   43    #define io_v2p(x) (0x3c000000 + ((x) & 0x01ffffff) + (((x) & 0x0e000000) << 1))  

    添加外扩设备寄存器   

  18    #define MST_FPGA_PHYS           PXA_CS2_PHYS   19    #define MST_FPGA_VIRT           (0xf0000000)   20    #define MST_P2V(x)             ((x) - MST_FPGA_PHYS + MST_FPGA_VIRT)   21    #define MST_V2P(x)              ((x) - MST_FPGA_VIRT + MST_FPGA_PHYS)   22   23    #ifndef __ASSEMBLY__   24    # define __MST_REG(x)           (*((volatile unsigned long *)MST_P2V(x)))   25    #else   26    # define __MST_REG(x)           MST_P2V(x)   27    #endif   28   29    /* board level registers in the FPGA */   30   31    #define MST_LEDDAT1             __MST_REG(0x08000010)   32    #define MST_LEDDAT2             __MST_REG(0x08000014)   33    #define MST_LEDCTRL             __MST_REG(0x08000040)   34    #define MST_GPSWR               __MST_REG(0x08000060)   35    #define MST_MSCWR1              __MST_REG(0x08000080)   36    #define MST_MSCWR2              __MST_REG(0x08000084)   37    #define MST_MSCWR3              __MST_REG(0x08000088)   38    #define MST_MSCRD               __MST_REG(0x08000090)   39    #define MST_INTMSKENA           __MST_REG(0x080000c0)   40    #define MST_INTSETCLR           __MST_REG(0x080000d0)   41    #define MST_PCMCIA0             __MST_REG(0x080000e0)   42    #define MST_PCMCIA1             __MST_REG(0x080000e4)