smart3250中的靜態I/O映射情況

根據網絡大蝦們的指導,基本上搞清楚了smart3250中的靜態I/O映射情況。寫個blog供以後參考。

****************************網絡摘錄**************************************

內核提供了在系統啓動時通過map_desc結構體靜態創建I/O資源到內核地址空間的線性映射表(即page table)的方式,這種映射表是一種一一映射的關係。程序員可以自己定義該I/O內存資源映射後的虛擬地址。創建好了靜態映射表,在內核或驅動中訪問該 I/O資源時則無需再進行ioreamp動態映射,可以直接通過映射後的I/O虛擬地址去訪問它。

machine_desc結構體的成員包含了體系架構相關部分的幾個最重要的初始化函數,包括map_io,init_irq, init_machine以及phys_io , timer成員等。這裏的map_io成員即內核提供給用戶的創建外設I/O資源到內核虛擬地址靜態映射表的接口函數。Map_io成員函數會在系統初始化過程中被調用,流程如下:

Start_kernel -> setup_arch() --> paging_init() --> devicemaps_init()中被調用Machine_desc結構體通過MACHINE_START宏來初始化。

****************************網絡摘錄**************************************

在board-smartarm3250.c文件中的MACHINE_START

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,

       .map_io          = smartarm3250_map_io,

       .init_irq   = lpc32xx_init_irq,

       .timer             = &lpc32xx_timer,

       .init_machine  = smartarm3250_board_init,

MACHINE_END

 

map_io方法對應的函數

static void __init smartarm3250_map_io(void)

{

    lpc32xx_map_io();

    iotable_init(smartarm3250_io_desc, ARRAY_SIZE(smartarm3250_io_desc));

}

 

先追蹤第一個函數

void __init lpc32xx_map_io(void)

{

       iotable_init (lpc32xx_io_desc, ARRAY_SIZE (lpc32xx_io_desc));

}

 

 

以下是lpc32xx_io_desc的定義:

static struct map_desc smartarm3250_io_desc[] __initdata = {

    {   /* nCS2, CAN SJA1000 */

        .virtual  = io_p2v(EMC_CS2_BASE),

        .pfn      = __phys_to_pfn(EMC_CS2_BASE),

        .length   = SZ_1M,

        .type     = MT_DEVICE

    },

    {   /* nCS1, CF Card */

        .virtual  = io_p2v(EMC_CS1_BASE),

        .pfn      = __phys_to_pfn(EMC_CS1_BASE),

        .length   = SZ_1M,

        .type     = MT_DEVICE

    }

 

};

 

現在追蹤第二個函數

arch-lpc32xx.c文件中

smartarm3250_io_desc結構體的定義

static struct map_desc lpc32xx_io_desc[] __initdata = {

       {

              .virtual    = io_p2v(AHB0_START),

              .pfn        = __phys_to_pfn(AHB0_START),

              .length            = AHB0_SIZE,

              .type              = MT_DEVICE

       },

       {

              .virtual    = io_p2v(AHB1_START),

              .pfn        = __phys_to_pfn(AHB1_START),

              .length            = AHB1_SIZE,

              .type              = MT_DEVICE

       },

       {

              .virtual    = io_p2v(FABAPB_START),

              .pfn        = __phys_to_pfn(FABAPB_START),

              .length            = FABAPB_SIZE,

              .type              = MT_DEVICE

       },

       {

              .virtual    = io_p2v(IRAM_BASE),

              .pfn        = __phys_to_pfn(IRAM_BASE),

              .length            = (SZ_64K * 4),

              .type              = MT_DEVICE

       },

};

由上可知,smartarm3250開發板靜態映射的物理地址有如下

基地址名稱

實際物理地址

大小

範圍

EMC_CS2_BASE

0xE2000000

SZ_1M(0x00100000)

0xE2000000-0xE2100000

EMC_CS1_BASE

0xE1000000

SZ_1M(0x00100000)

0xE1000000-0xE1100000

AHB0_START

0x20020000

AHB0_SIZE()

(MLC_BASE - SLC_BASE) + SZ_4K

(0x200A8000-0x20020000)+ 0x00001000

 

 

0x20020000-0x200A9000

AHB1_START

0x31000000

AHB1_SIZE()

(EMC_BASE - DMA_BASE) + SZ_4K

 

(0x31080000-0x31000000)+ 0x00001000

 

 

0x31000000-0x31081000

FABAPB_START

0x40004000

FABAPB_SIZE()

(I2C2_BASE - CLK_PM_BASE) + SZ_4K

 

(0x400A8000- 0x40004000)+ 0x00001000

 

 

 

0x40004000-0x400A9000

IRAM_BASE

0x08000000

SZ_64K * 4()

0x00040000

0x08000000-0x08040000

這些基地址的實際物理地址在include/mach/platform.h中可以找到

以上地址可以在驅動程序中直接調用如下兩個函數:

__raw_readl(register_address);

__raw_writel(register_content,register_address);

這樣在linux中控制單片機和用裸機程序控制單片機就沒什麼分別了。

以上地址中,還有未映射的地址部分。如果要在linux中用到,可以在驅動中的probe方法裏,調用ioremap()函數,之後就能用了。

上面說介紹的物理地址都是經過io_p2v(x)映射的。

#define IO_BASE         0xF0000000

#define io_p2v(x) (IO_BASE | (((x) & 0xff000000) >> 4) | ((x) & 0x000fffff))

這個宏的意思是:

假設一個數,如0xABCDE123從前到後的16進制值順序爲12345678,即A對應1,B對應2,以此類推。

那麼經過這個宏後變爲:

AABDE123,即這個數的後5個數不會變,第一個數分裂爲2個,去掉原來的第三個數。然後組合起來。

由上可知,如果想讓映射後的地址與原來的物理地址一一對應,不產生衝突,所有被映射的地址的8位16進制數的第3個數應相同。lpc3250中,這個第3個數是0

====

http://blog.csdn.net/yongan1006/article/details/7094662

發佈了6 篇原創文章 · 獲贊 13 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章