• <tbody id="wslfv"><pre id="wslfv"></pre></tbody>
    <span id="wslfv"></span>
    <tbody id="wslfv"><pre id="wslfv"></pre></tbody>
    <th id="wslfv"><track id="wslfv"><rt id="wslfv"></rt></track></th>

    <li id="wslfv"><acronym id="wslfv"></acronym></li>
    更多課程 選擇中心

    嵌入式培訓
    達內IT學院

    400-111-8989

    一位嵌入式Linux菜鳥設備驅動學習之路

    • 發布:嵌入式培訓
    • 來源:嵌入式教程
    • 時間:2018-01-09 16:01

    一位嵌入式Linux菜鳥設備驅動學習之路

    1.設備驅動的作用

    計算機系統由硬件、軟件組成,而對于實際開發來說,硬、軟件間耦合性應盡量低,即應用開發工程師不需關心 硬件,而硬件開發工程師無暇顧及軟件。為了降低硬、軟耦合性,產生了設備驅動工程師。

    2.操作系統驅動設計架構

    在無操作系統時,硬件工程師可以自定義API供應用開發工程師使用;而使用操作系統后,需按操作系統定義的架構設計驅動,如此才能良好的嵌入內核中。

    對圖1.1而言:

    優點:驅動編寫簡單

    缺點:對于每一個硬件設備,應用工程師要花精力去了解硬件工程師提供的API

    對圖1.4而言:

    優點:對于應用工程師,任何硬件設備均體現為操作系統提供的API,無需知道硬件如何實現

    缺點:驅動設計變得及其復雜

    疑問:有了操作系統后,驅動變得十分復雜,那為什么還要引入操作系統?

    解答:

    1.為上層應用開發提供便利,只需如操作文件似的使用open、write、read等函數即可實現對各種硬件設備的使用,不論設備的具體類型和工作方式。

    2.沒有操作系統,難以實現多任務并發應用程序(對于這點,目前仍然體會不到2016.12.8)

    3.LINUX操作系統驅動架構

    縱觀Linux內核的源代碼,設備驅動并非各類教學視頻中所介紹的簡單形式。在實際Linux驅動中,Linux內核盡量做得更多,以便底層驅動做得更少,而且也特別強調跨平臺性。Linux勢必為不同驅動子系統設計不同的框架。

    為了使Linux驅動盡量具有可重用性。如同一DM9000網卡驅動最好不改一行就可以在任何一個平臺跑起來。Linux采用Linux總線、設備和驅動模型把開發板硬件信息從驅動剝離出來,驅動只管驅動、設備只管開發板具體硬件資源、總線負責匹配設備和驅動,如此驅動以標準方式拿到板極信息。

    看到現在,不禁有個疑問,自己制作的全新硬件或者現成開發板如mini2440、JZ2440的硬件資源(即板極信息)是如何讓內核知曉的?(下面分析均基于s3c2440)

    在linux/arch/arm/mach-s3c2440/mach-smdk2440.c中有板極信息初始化函數

    smdk2440_machine_init

    static void __init smdk2440_machine_init(void)

    {

    s3c24xx_fb_set_platdata(&smdk2440_fb_info);

    s3c_i2c0_set_platdata(NULL);

    platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));

    smdk_machine_init();

    }

    逐步分析關鍵函數platform_add_devices

    //縮進表示函數間調用關系

    smdk2440_machine_init

    platform_add_devices(smdk2440_devices

    for (i = 0; i < num; i++)

    platform_device_register(devs[i]);

    device_initialize(&pdev->dev);

    platform_device_add(pdev);/*

    上面主要是遍歷設備所占用的資源,找到對應的父資源,如果沒有定義,那么根據資源的類型,分別賦予iomem_resource和ioport_resource,然后調用insert_resource插入資源。*/

    從上面可知,通過調用platform_add_devices將smdk2440_devices定義的s3c2440中所有的platform設備注冊到了linux設備模型核心中

    static struct platform_device *smdk2440_devices[] __initdata = {

    &s3c_device_usb,

    &s3c_device_lcd,

    &s3c_device_wdt,

    &s3c_device_i2c0,

    &s3c_device_iis,

    };

    前面提到Linux采用Linux總線、設備和驅動模型來使硬件信息從驅動中剝離出來,目前設備信息已經注冊進內核,而platform驅動則是由各個驅動程序模塊分別注冊到內核,那他們兩者該如何聯系起來?這就跟linux設備模型核心有關系了。

    為了解設備與驅動間的聯系流程,以linux/input/keyboard/gpio-keys.c按鍵為例:

    module_init(gpio_keys_init);

    platform_driver_register(&gpio_keys_device_driver);

    driver_register(&drv->driver);

    bus_add_driver(drv);

    driver_attach(drv);

    bus_for_each_dev(drv->bus, NULL, drv,

    driver_match_device(drv, dev)

    /*匹配驅動與設備的name是否相同*/ platform_match(dev, drv)

    driver_probe_device(drv, dev);

    really_probe(dev, drv);

    /*

    gpio_keys_probe詳細分析參考:http://www.cnblogs.com/cyc2009/p/4127496.html*/gpio_keys_probe(struct

    setup_timer(&bdata->timer

    INIT_WORK

    gpio_keys_report_event

    input_event

    input_handle_event

    input_sync(input);

    input_allocate_device();

    input_register_device();

    input_attach_handler();

    handler->connect(handler, dev,id);

    /*

    input子系統介紹參考:

    http://blog.csdn.net/sdvch/article/details/44619699

    */ gpio_keys_isr(int irq, void *dev_id)

    schedule_work(&bdata->work);

    具體的file_operations成員函數在Evdev.c中實現,通過核心層Input將事件傳送至事件驅動層Evdev,執行具體的open、read、write、ioctl等函數

    module_init(evdev_init);

    input_register_handler(&evdev_handler);

    evdev_pass_event(struct evdev_client *client

    Linux內核input子系統框架如下:

    到目前,似乎摸著了驅動框架的邊緣,但是回過頭去看,內核支持許多硬件,內核如何知道應該執行smdk2440_machine_init,而不是其他板子的初始化函數,而且smdk2440_machine_init是何時何處調用的尚未可知?因此,回過頭去了解內核的啟動流程。

    首先,關注MACHINE_START、MACHINE_END兩個宏中間的內容

    MACHINE_START(S3C2440, "SMDK2440")

    /* Maintainer: Ben Dooks <ben@fluff.org> */

    .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展開可知,定義了一個machine_desc結構體類型的變量__mach_desc_S3C2440

    static const struct machine_desc __mach_desc_S3C2440 __used

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

    .nr = MACH_TYPE_S3C2440,

    .name = "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,

    };

    內核的第一個C函數為start_kernel,從這出發進行分析:

    start_kernel(linux/init/main.c)

    setup_arch(&command_line);

    mdesc = setup_machine(machine_arch_type);

    lookup_machine_type(nr);

    init_arch_irq = mdesc->init_irq;

    system_timer = mdesc->timer;

    init_machine = mdesc->init_machine; /*由此可知,setup_machine函數通過機器碼machine_arch_type,來通知內核要執行哪個開發板的初始化函數*/

    雖然,上面講mdesc->init_machine賦值給了init_machine,但是并未執行,搜索代碼后發現,init_machine被customize_machine調用。

    static int __init customize_machine(void)

    {

    /* customizes platform devices, or adds new ones */

    if (init_machine)

    init_machine();

    return 0;

    }

    arch_initcall(customize_machine);

    繼續跟隨start_kernel往下看

    start_kernel(init/main.c)

    setup_arch(&command_line);

    rest_init

    kernel_thread(kernel_init, NULL, CLONE_FS

    kernel_init

    do_basic_setup

    do_initcalls

    /*

    在do_initcalls處將調用customize_machine,從而過渡至smdk2440_machine_init

    */

    預約申請免費試聽課

    填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

    上一篇:15道嵌入式研發測試題—年薪10萬的企業面試題
    下一篇:嵌入式機器學習處理器的技術挑戰和機會

    裸編程怎么做?裸編程具體做法

    嵌入式編程中你必須知道的小知識

    嵌入式C語言編程小知識總結

    有哪些工具可以讓嵌入式開發事半功倍?

    • 掃碼領取資料

      回復關鍵字:視頻資料

      免費領取 達內課程視頻學習資料

    • 視頻學習QQ群

      添加QQ群:1143617948

      免費領取達內課程視頻學習資料

    Copyright ? 2021 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

    選擇城市和中心
    黑龍江省

    吉林省

    河北省

    湖南省

    貴州省

    云南省

    廣西省

    海南省

    欧美一级高清片,一级欧美免费大片视频,欧美三级在线电影免费 百度 好搜 搜狗
    <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>