コグノスケ


link 未来から過去へ表示  link 過去から未来へ表示(*)

link もっと前
2020年2月17日 >>> 2020年2月17日
link もっと後

2020年2月17日

Zephyrのブート処理 - ドライバの初期化まで

目次: Zephyr

前回はリセット直後からC言語の関数と出会うところまでを紹介しました。今回はドライバの初期化までを紹介します。

最初のC言語の関数 _PrepC

// zephyr/arch/riscv/core/prep_c.c

void _PrepC(void)
{
        z_bss_zero();
#ifdef CONFIG_XIP
        z_data_copy();
#endif
#if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
        soc_interrupt_init();
#endif
        z_cstart();
        CODE_UNREACHABLE;
}

ブート後に最初に出会うC言語の関数 _PrepC() ですが、実はまだグローバル変数の初期化が終わっていませんので、この関数で初期化しています。z_bss_zero() は、ゼロ初期化される変数の領域(BSS)を0で初期化します。z_data_copy() は、変数領域をROMからRAMにコピーします。

XIP(Execution In Place)が有効な場合、コード領域はFlash ROMなどに配置され、CPUはROMから直接コードを読み出して実行します。コード領域はそれで良いですが、変数の初期値もROMにおかれていて、そのままでは変数に書き込みできません。そのためROMからRAMにコピーする必要があります。

最後のz_start() まで来ると、やっと普通のC言語の世界です。

Zephyrの初期化処理

// zephyr/kernel/init.c

FUNC_NORETURN void z_cstart(void)
{

        ...

        /* perform basic hardware initialization */
        z_sys_device_do_config_level(_SYS_INIT_LEVEL_PRE_KERNEL_1);    //★level = 0
        z_sys_device_do_config_level(_SYS_INIT_LEVEL_PRE_KERNEL_2);


// zephyr/include/init.h

#define _SYS_INIT_LEVEL_PRE_KERNEL_1    0
#define _SYS_INIT_LEVEL_PRE_KERNEL_2    1
#define _SYS_INIT_LEVEL_POST_KERNEL     2
#define _SYS_INIT_LEVEL_APPLICATION     3

初期化関数z_cstart() は、色々ごちゃごちゃやっているのですが、真ん中あたりでドライバの初期化が行われます。レベルをPRE_KERNEL_1 (level 0), PRE_KERNEL_2 (level 1) の順に指定して、z_sys_device_do_config_level() という関数を呼びます。ちなみにPOST_KERNEL (level 2), APPLICATION (level 3) はもっと後で、カーネルの初期化が終わった後に使われます。

初期化される対象はデバイスドライバ以外(後述の、メモリ割り当てシステムドライバなど)もありますけど、仕組みは同じみたいです。

ドライバの初期化処理

// zephyr/kernel/device.c

extern struct device __device_init_start[];
extern struct device __device_PRE_KERNEL_1_start[];
extern struct device __device_PRE_KERNEL_2_start[];
extern struct device __device_POST_KERNEL_start[];
extern struct device __device_APPLICATION_start[];
extern struct device __device_init_end[];

...

void z_sys_device_do_config_level(s32_t level)
{
        struct device *info;
        static struct device *config_levels[] = {
                __device_PRE_KERNEL_1_start,
                __device_PRE_KERNEL_2_start,
                __device_POST_KERNEL_start,
                __device_APPLICATION_start,
                /* End marker */
                __device_init_end,
        };

        for (info = config_levels[level]; info < config_levels[level+1];
                                                                info++) {
                int retval;
                const struct device_config *device_conf = info->config;
                ...

実装は上記のようになっています。level 0の場合は __device_PRE_KERNEL_1_start[] という配列を先頭から処理します。他のレベルも同様ですね。

ドライバの初期化情報
======== <-- config_levels[0]
__device_PRE_KERNEL_1_start[0]
__device_PRE_KERNEL_1_start[1]
...
__device_PRE_KERNEL_1_start[n]
======== <-- config_levels[1]
__device_PRE_KERNEL_2_start[0]
__device_PRE_KERNEL_2_start[1]
...
__device_PRE_KERNEL_2_start[n]
======== <-- config_levels[2]
__device_POST_KERNEL_start[0]
__device_POST_KERNEL_start[1]
...
__device_POST_KERNEL_start[n]
======== <-- config_levels[3]
__device_APPLICATION_start[0]
__device_APPLICATION_start[1]
...
__device_APPLICATION_start[n]
======== <-- __device_init_end

このようにメモリ上にstruct deviceがレベル順に並んでいることを期待しているようです。しかし配列の実体はCのソースコード上には存在しないように見えます。これは一体何者なんでしょう?

続きはまた今度。

編集者:すずき(2023/09/24 12:02)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2020年2月17日 >>> 2020年2月17日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<02>>>
------1
2345678
9101112131415
16171819202122
23242526272829

最近のコメント5件

  • link 21年3月13日
    すずきさん (03/05 15:13)
    「あー、このプログラムがまずいんですね。ご...」
  • link 21年3月13日
    emkさん (03/05 12:44)
    「キャストでvolatileを外してアクセ...」
  • link 24年1月24日
    すずきさん (02/19 18:37)
    「簡単にできる方法はPowerShellの...」
  • link 24年1月24日
    KKKさん (02/19 02:30)
    「追伸です。\nネットで調べたらマイクロソ...」
  • link 24年1月24日
    KKKさん (02/19 02:25)
    「私もエラーで困ってます\n手動での回復パ...」

最近の記事3件

  • link 24年3月25日
    すずき (03/26 03:20)
    「[Might and Magic Book One TASのその後] 目次: Might and Magicファミコン版以前(...」
  • link 21年10月4日
    すずき (03/26 03:14)
    「[Might and Magicファミコン版 - まとめリンク] 目次: Might and Magicファミコン版TASに挑...」
  • link 24年3月19日
    すずき (03/20 02:52)
    「[モジュラージャックの規格] 古くは電話線で、今だとEthernetで良く見かけるモジュラージャックというコネクタとレセプタク...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 03/26 03:20