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

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

日々

link permalink

link 編集する

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 のソースコード上には存在しないように見えます。これは一体何者なんでしょう?

続きはまた今度。

[編集者: すずき]
[更新: 2020年 2月 19日 22:10]

コメント一覧

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



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

管理用メニュー

link 記事を新規作成

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDF ファイル RSS 1.0
QR コード QR コード

最終更新: 3/15 02:33

カレンダー

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

最近のコメント 5件

  • link 13年11月28日
    すずき 「ご指摘ありがとうございます。投稿の古さに...」
    (更新:03/08 17:39)
  • link 13年11月28日
    yut 「古いので、見てもらえるか不明ですので、、...」
    (更新:03/08 13:16)
  • link 13年11月28日
    yut シムズ 「古い投稿に対して、申し訳ありません。\n...」
    (更新:03/08 13:14)
  • link 19年09月01日
    すずき 「私も正直びっくりです。間違って違う製品を...」
    (更新:09/04 23:39)
  • link 19年09月01日
    hdk 「車向けの製品の中でも、車載コンピューター...」
    (更新:09/02 23:20)

最近の記事 3件

link もっとみる
  • link 20年03月10日
    すずき 「[誕生日] 37歳になりました。おめでとう俺、ありがとう俺。30代...」
    (更新:03/15 02:33)
  • link 20年03月14日
    すずき 「[GCC を調べる - その 7 - machine mode] ...」
    (更新:03/15 02:21)
  • link 20年03月06日
    すずき 「[GCC を調べる - その 6 - GCC の regist] ...」
    (更新:03/11 22:47)

こんてんつ

open/close wiki
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 過去日記について

その他の情報

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