30

SPI フラッシュ ストレージを備えたデバイスがあり、そのフラッシュ デバイスの UBIFS ファイルシステムを rootfs として使用したいと考えています。私が直面している問題は、SPI モジュールが初期化される前に UBI モジュールが初期化されることです。このため、UBI が読み込まれると、(カーネル コマンド ライン経由で) UBI デバイスに接続できないため、rootfs がありません。以下のコンソール出力はこれを示しています。

関数ポインターのリストを単に呼び出す関数がinit/main.cあることを確認するために、ソースを十分に掘り下げてきました。これらの関数ポインタは、カーネルに組み込まれているモジュールdo_initcalls()のすべての関数を指しています。module_init()これらの関数ポインタはカーネル バイナリの特別なセクションに配置されるため、この順序はコンパイル時に選択されます。ただし、その順序がどのように決定されるかはまだわかりません。

    [    0.482500] UBI error: ubi_init: UBI error: cannot initialize UBI, error -19
    [    0.492500] atmel_spi atmel_spi.0: Using dma0chan0 (tx) and  dma0chan1 (rx) for DMA transfers
    [    0.500000] atmel_spi atmel_spi.0: Atmel SPI Controller at 0xf0000000 (irq 13)
    [    0.507500] m25p80 spi0.1: mx25l25635e (32768 Kbytes)
    [    0.512500] Creating 7 MTD partitions on "jedec_flash":
    [    0.520000] 0x000000000000-0x000000020000 : "loader"
    [    0.527500] 0x000000020000-0x000000060000 : "u-boot"
    [    0.537500] 0x000000060000-0x000000080000 : "u-boot-env"
    [    0.547500] 0x000000080000-0x000000280000 : "kernel0"
    [    0.557500] 0x000000280000-0x000000480000 : "kernel1"
    [    0.567500] 0x000000480000-0x000001240000 : "fs"
    [    0.575000] 0x000001240000-0x000002000000 : "play"
    [    0.590000] AT91SAM9 Watchdog enabled (heartbeat=15 sec, nowayout=0)
    [    0.607500] TCP cubic registered
    [    0.615000] VFS: Cannot open root device "ubi0:root0" or unknown-block(0,0)
    [    0.622500] Please append a correct "root=" boot option; here are the available partitions:
    [    0.630000] 1f00             128 mtdblock0  (driver?)
    [    0.635000] 1f01             256 mtdblock1  (driver?)
    [    0.640000] 1f02             128 mtdblock2  (driver?)
    [    0.645000] 1f03            2048 mtdblock3  (driver?)
    [    0.650000] 1f04            2048 mtdblock4  (driver?)
    [    0.655000] 1f05           14080 mtdblock5  (driver?)
    [    0.660000] 1f06           14080 mtdblock6  (driver?)
    [    0.665000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
4

3 に答える 3

39

カーネルによって初期化されるモジュールのinitルーチン(カーネルに静的にリンクされている場合)は、起動シーケンスのいつ実行する必要があるかを示すinitcall()マクロでラップされます。

マクロとその順序のリストについては、インクルードファイル:include / linux/init.hを参照してください。

そこに指定されている順序は次のとおりです。

  • Early_initcall
  • pure_initcall
  • core_initcall
  • postcore_initcall
  • arch_initcall
  • subsys_initcall
  • fs_initcall
  • rootfs_initcall
  • device_initcall
  • late_initcall

これらのほとんどには「initcall_sync()フェーズがあり、そのフェーズ内のすべてのモジュール初期化ルーチンの完了を待機するために使用されます。マクロは、によって順番に呼び出される各フェーズの関数ポインターのテーブルを作成するために使用され do_initcalls()ます。

「module_init()」を使用して初期化関数をラップする場合、デフォルトでは、initcall()は呼び出しを初期化の「デバイス」フェーズに置きます。そのフェーズでは、アイテムはリンク順で並べ替えられます。これは、リンカが検出した関数の順序によってテーブルが作成されることを意味します。

モジュールの初期化関数をラップするinitcallマクロを変更することで、初期化を以前のフェーズに移動できる場合がありますが、さまざまなモジュール間に順序の依存関係があるため、注意が必要です。初期化の順序を(フェーズ内で)変更する別の方法は、カーネル内のモジュールのリンク順序を調整することです。

于 2012-06-19T23:40:42.897 に答える
2

@Tim Birdはすでに回答しています-モジュールの順序を変更する方法を示したいと思います:-

pure_initcall(fn)         --> Loaded first
core_initcall(fn)         
core_initcall_sync(fn)    
postcore_initcall(fn)     
postcore_initcall_sync(fn)
arch_initcall(fn)         
arch_initcall_sync(fn)    
subsys_initcall(fn)       
subsys_initcall_sync(fn)  
fs_initcall(fn)           
fs_initcall_sync(fn)      
rootfs_initcall(fn)       
device_initcall(fn)       
device_initcall_sync(fn)  
late_initcall(fn)         
late_initcall_sync(fn)    --> Loaded last

Usage - Replace fn by the module init function pointer, example for i2c core driver:
.......
postcore_initcall(i2c_init);  // To delay i2c core loading use subsys_initcall(i2c_init)                
module_exit(i2c_exit);
.......
于 2017-06-01T22:50:27.533 に答える
0

間違っているかもしれませんので、これが正しいかどうかを確認してください。
必要なすべてのドライバーをモジュール (M) としてコンパイルし、ロードするモジュールを正しい順序で /etc/modules に配置してみてください。これで問題が解決する可能性があります。正確には、rootfs がマウントされる前にこれを行っているため、上記の手順は initram ディスクで行う必要があります。(同様のシナリオがあり、fsを復号化できるように、いくつかのモジュールを正しい順序でロードする必要があります)


これがCiaoCiao
Sergioに役立つことを願っています

于 2012-04-29T14:41:23.050 に答える