<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > linux驅動(dòng)移植的數據結構

linux驅動(dòng)移植的數據結構

作者: 時(shí)間:2016-11-23 來(lái)源:網(wǎng)絡(luò ) 收藏
對于嵌入式 Linux 系統來(lái)說(shuō),有各種體系結構的處理器和硬件平臺,并且用戶(hù)需要根據需求自己定制硬件板。只要是硬件平臺有些變化,即使非常小,可能也需要做一些移植工作。內核移植是嵌入式Linux系統中最常見(jiàn)的一項工作。

內核移植工作主要是修改跟硬件平臺相關(guān)的代碼,一般不涉及 Linux 內核通用的程序。移植的難度也取決于兩種硬件平臺的差異。Linux 對于特定的硬件平臺的軟件就叫作 BSP(Board Support Package)。

本文引用地址:http://dyxdggzs.com/article/201611/320472.htm

由于 Linux 內核具備可移植性的特點(diǎn),并且已經(jīng)支持了各種體系結構的很多種目標板,我們很容易從中找到跟自己硬件類(lèi)似的目標板。參考內核已經(jīng)支持的目標板來(lái)移植 BSP,就如同使用模板開(kāi)發(fā)程序。

因此,移植linux內核的過(guò)程大多數情況下就是移植BSP的過(guò)程。三星公司提供了smdk24xx開(kāi)發(fā)板的BSP。對于mini2440開(kāi)發(fā)板來(lái)說(shuō),移植linux內核,只要修改smdk24xx開(kāi)發(fā)板的BSP使該linux支持mini2440開(kāi)發(fā)板就可以了。

linux內核源代碼的ARCH目錄存放的是體系結構相關(guān)的代碼,對于每個(gè)架構的CPU,arm目錄下都有一個(gè)對應的目錄,比如arch/arm、arch/i386。而arm架構的處理器種類(lèi)又有很多,所以,在arch/arm目錄下對于每種arm架構處理器也有一個(gè)對應的子目錄,比如arch/arm/mach-s3c2440、arch/arm/mach-s3c2410等。在arch/arm目錄下有一個(gè)plat-s3c24xx目錄,根據目錄名它應該是與s3c24xx系列處理器的平臺設備相關(guān)的一個(gè)目錄。注意,所謂的“平臺設備”并不是與字符設備、塊設備和網(wǎng)絡(luò )設備并列的概念,而是linux系統描述設備的一個(gè)附加手段。在plat-s3c24xx目錄下有一個(gè)common-smdk.c文件,根據文件名,它應該是三星公司的smdk24xx系列開(kāi)發(fā)板都需要的一個(gè)文件。在移植驅動(dòng)的時(shí)候經(jīng)常需要修改arch/arm/plat-s3c24xx/common-smdk.c文件。對于arch/arm/mach-s3c2440目錄,它是專(zhuān)門(mén)用來(lái)保存 S3C2410 系列處理器平臺相關(guān)程序,其中 Kconfig 和 Makefile 是用于內核配置編譯的。其他文件分為 2 類(lèi),一類(lèi)是處理器通用的,例如:clock.c clock.h cpu.c cpu.h s3c2410.c s3c2410.h等;另一類(lèi)是目標板相關(guān)的,例如:bast.h bast-irq.c mach-bast.c等。在這些文件中,實(shí)現了處理器和目標板相關(guān)的一些定義和初始化函數。還有些相關(guān)的定義包含在 include/asm-arm/arch-s3c2410/下的頭文件中。

linux內核中對于每種支持的開(kāi)發(fā)板都會(huì )使用宏MACHINE_START、MACHINE_END來(lái)定義一個(gè)machine_desc結構。MACHINE_START、MCHINE_END的定義如下:

(1)

#define MACHINE_START(_type,_name)

static const struct machine_desc __mach_desc_##_type

__used

__attribute__((__section__(".arch.info.init"))) = {

.nr = MACH_TYPE_##_type,

.name = _name,

#define MACHINE_END

};

在arch/arm/mach-s3c2410/mach-smdk2440.c中可以找到SMDK2440開(kāi)發(fā)板的定義如下:

MACHINE_START(S3C2440, "SMDK2440")

.phys_io = S3C2410_PA_UART,

.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

.boot_params = S3C2410_SDRAM_PA + 0x100,

.init_irq = s3c24xx_init_irq,

.map_io = smdk2440_map_io,

.init_machine = smdk2440_machine_init,

.timer = &s3c24xx_timer,

MACHINE_END

把MACHINE_START、MACHINE_END擴展開(kāi)來(lái)就是定義了一個(gè)名為_(kāi)_mach_desc_S3C2440的結構體變量:

const struct machine_desc __mach_desc_S3C2440__used

__attribute__((__section__(".arch.info.init"))) =

{

.nr = MACH_TYPE_S3C2440, //開(kāi)發(fā)板的機器類(lèi)型ID

.name = "SMDK2440", //開(kāi)發(fā)板名稱(chēng)

.phys_io = S3C2410_PA_UART, //起始IO物理地址

.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

.boot_params = S3C2410_SDRAM_PA + 0x100, //內核啟動(dòng)參數的地址

.init_irq = s3c24xx_init_irq, //中斷初始化函數

.map_io = smdk2440_map_io, //IO映射函數(在這里修改時(shí)鐘頻率)

.init_machine = smdk2440_machine_init,

.timer = &s3c24xx_timer,

};

MACH_TYPE_S3C2440可以看作是系統平臺號,它包含在include/asm- arm/mach-types.h頭文件中,不過(guò)這個(gè)頭文件是在配置內核或編譯內核時(shí)自動(dòng)生成的,所以不能更改。。真正系統平臺號

的定義位置在arch/arm/tools/mach-types文件中。

# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number

s3c2440 ARCH_S3C2440 S3C2440 362

arch/arm/tools/mach-types中每一行定義一個(gè)系統平臺號。 “machine_is_xxx”是用來(lái)判斷當前的平臺號是否正確的函數; “CONFIG_xxxx”是在內核配置時(shí)生成的; “MACH_TYPE_xxx”

是系統平臺號的定義; “number”是系統平臺的值。 __mach_desc_S3C2440結構體中的函數將在內核啟動(dòng)過(guò)程中,完成系統平臺的初始化工作

對于具有相同處理器的系統平臺,并不需要對每一個(gè)平臺都編寫(xiě)一個(gè)BSP,如果他們的外圍接口電路基本相同,也許只需修改一些數據的定義,修改幾個(gè)函數的參數就可以了。

(2)linux設計了一個(gè)通用的數據結構resource來(lái)描述各種I/O資源(比如,IO端口,DMA,中斷等)

include/linux/ioport.h

struct resource

{
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};

flags:資源標記,用于標識各種資源,例如IORESOURCE_MEM表示內存資源,IORESOURCE_IRQ表示中斷資源

對于內存資源,start表示內存起始物理地址,end:表示內存末尾物理地址

對于中斷資源,start表示起始中斷號,end表示最后一個(gè)中斷號

常用資源數組來(lái)表示一個(gè)設備所擁有的各類(lèi)資源,比如s3c2440的片內LCD控制器擁有的資源如下

static struct resource s3c_lcd_resource[]=

{

[0]={

.start=S3C24XX_PA_LCD,

.end=S3C24XX_PA_LCD+S3C24XX_SZ_LCD-1,

.flags=IORESOURCE_MEM,

}

[1]={

.start=IRQ_LCD,

.end=IRQ_LCD,

.flags=IORESOURCE_IRQ,

}

};

其中S3C24XX_PA_LCD被定義為0x4D000000,S3C24XX_SZ_LCD被定義為1M。所以,在這里給LCD控制器分配的物理地址空間范圍為0x4D000000~0x4D0FFFFF,這些是LCD控制器各寄存器使用的地址,但實(shí)際上LCD控制器的寄存器地址的范圍為0x4D000000~0x4D000060,使用0x4D000000和0x4D000060給他們賦值也應該是可以的。IRQ_LCD算得是32,它會(huì )將GPG4引腳設為L(cháng)CD_PWREN功能,因為GPG4為L(cháng)CD_PWREN/EINT12復用。

(3)在內核文件include/linux/platform_device.h中,定義了兩個(gè)數據結構來(lái)表示設備和驅動(dòng)程序:platform_device結構用來(lái)描述設備的名稱(chēng)、ID、所占用的資源(比如內存地址/大小、中斷號)等;platform_driver結構用來(lái)描述各種操作函數,比如枚舉函數、移除設備函數、驅動(dòng)名稱(chēng)等。

//平臺設備

struct platform_device

{

const char* name; //設備名

int id;

struct device dev;

u32 num_resources; // 設備所使用的各類(lèi)資源數量

struct resource * resource; // 設備的資源數組

struct platform_device_id *id_entry;

struct pdev_archdata archdata;

};

//平臺驅動(dòng)

struct platform_driver

{

int (*probe)(struct platform_device *); //探測

int (*remove)(struct platform_device *); //移除

void (*shutdown)(struct platform_device *); //關(guān)閉

int (*suspend)(struct platform_device *, pm_message_t state);//掛起

int (*resume)(struct platform_device *); //恢復

//描述驅動(dòng)的名稱(chēng)(name)和屬主(owner)等信息

struct device_driver driver;

struct platform_device_id *id_table;

};

內核啟動(dòng)后,首先構造鏈表將描述設備的platform_device構造組織起來(lái),得到一個(gè)設備的列表;當加載某個(gè)驅動(dòng)程序的platform_driver結構時(shí),使用一些匹配函數來(lái)檢查驅動(dòng)程序能否支持這些設備,常用的檢查方法很簡(jiǎn)單:比較驅動(dòng)程序和設備的名稱(chēng)。

以S3C2440開(kāi)發(fā)板為例,在arch/arm/mach-s3c2440/mach-smdk2440.c中定義了如下設備:

static struct platform_device *smdk2440_devices[] __initdata =

{

&s3c_device_usb, //USB控制器

&s3c_device_lcd, //LCD控制器

&s3c_device_wdt, //看門(mén)狗

&s3c_device_i2c,

&s3c_device_iis,

};

在arch/arm/plat-s3c24xx/common-smdk.c中定義了如下設備:

static struct platform_device __initdata *smdk_devs[] =

{

&s3c_device_nand, //NAND FLASH

&smdk_led4,

&smdk_led5,

&smdk_led6,

&smdk_led7,

};



評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>