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

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

日々

link permalink

link 編集する

Zephyr のエントリアドレス

Zephyr を qemu_riscv32 ボード向けにコンフィグし、ビルドディレクトリ下で ninja run を実行すると、最終的に下記のコマンドが実行され、QMEU が起動します。

QEMU の起動コマンド
$ /usr/bin/qemu-system-riscv32 -nographic -machine sifive_e -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel zephyr/build/zephyr/zephyr.elf -s -S

GDB で追うとわかりますが、QEMU の実行開始アドレスは 0x1000 です。0x1000 には 0x20400000 にジャンプするコードだけが置かれています。

0x1000 にあるコード

   0x1000:      lui     t0,0x20400
=> 0x1004:      jr      t0
   0x1008:      unimp
   0x100a:      unimp

HiFive1 実機であれば 0x20400000 は QSPI Flash がマッピングされているアドレスです(SiFive FE310-G000 Manual v2p3 を参照)。QEMU の場合は ELF ファイル build/zephyr/zephyr.elf のセクション情報通りに配置されます。

0x1000 にあるコード
$ riscv64-zephyr-elf-readelf -a build/zephyr/zephyr.elf  | less

...

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] vector            PROGBITS        20400000 000094 000010 00  AX  0   0  4
  [ 2] exceptions        PROGBITS        20400010 0000a4 000258 00  AX  0   0  4
  [ 3] text              PROGBITS        20400268 0002fc 002ad4 00  AX  0   0  4
  [ 4] sw_isr_table      PROGBITS        20402d3c 002dd0 000200 00  WA  0   0  4
  [ 5] devconfig         PROGBITS        20402f3c 002fd0 000060 00   A  0   0  4
  [ 6] rodata            PROGBITS        20402f9c 003030 000215 00   A  0   0  4
  [ 7] datas             PROGBITS        80000000 003248 000018 00  WA  0   0  4
  [ 8] initlevel         PROGBITS        80000018 003260 000060 00  WA  0   0  4
  [ 9] _k_mutex_area     PROGBITS        80000078 0032c0 000014 00  WA  0   0  4
  [10] bss               NOBITS          80000090 0032e0 00013c 00  WA  0   0  8
  [11] noinit            NOBITS          800001d0 0032e0 000e00 00  WA  0   0 16

...

ジャンプ先の 0x20400000 には vector というセクションが対応していることがわかります。ELF ファイルを逆アセンブルしてみると、

0x20400000 にあるコード

zephyr/zephyr.elf:     file format elf32-littleriscv


Disassembly of section vector:

20400000 <__start>:

        /*
         * Set mtvec (Machine Trap-Vector Base-Address Register)
         * to __irq_wrapper.
         */
        la t0, __irq_wrapper
20400000:       00000297                auipc   t0,0x0
20400004:       01028293                addi    t0,t0,16 # 20400010 <__irq_wrapper>
        csrw mtvec, t0
20400008:       30529073                csrw    mtvec,t0

        /* Jump to __initialize */
        tail __initialize
2040000c:       4b40106f                j       204014c0 <__initialize>

以上のように __start という関数が居るようです。実装は zephyr/soc/riscv/riscv-privilege/common/vector.S にあります。

Zephyr とデバイスツリー

このエントリポイントアドレスはどのように決まるのでしょう?Zephyr では、ボード用のデバイスツリー zephyr/boards/riscv/qemu_riscv32/qemu_riscv32.dts にある Flash の先頭アドレスを変えると ELF のエントリポイント(0x20400000)も追従します。

ボード用のデバイスツリーの chosen ノード

        chosen {
                zephyr,console = &uart0;
                zephyr,shell-uart = &uart0;
                zephyr,sram = &dtim;
                zephyr,flash = &flash0;
        };

この chosen 以下を検知しているようです。スクリプト scripts/dts/gen_defines.py を見ると、SPI のときだけ特殊処理になっていて、それ以外は reg の値を先頭アドレスとみなしています。

Flash のサイズを見ている箇所

# zephyr/scripts/dts/gen_defines.py

...

def write_flash_node(edt):
    # Writes output for the top-level flash node pointed at by
    # zephyr,flash in /chosen

    node = edt.chosen_node("zephyr,flash")

    out_comment(f"/chosen/zephyr,flash ({node.path if node else 'missing'})")

    if not node:
        # No flash node. Write dummy values.
        out("FLASH_BASE_ADDRESS", 0)
        out("FLASH_SIZE", 0)
        return

    if len(node.regs) != 1:
        err("expected zephyr,flash to have a single register, has "
            f"{len(node.regs)}")

    if node.on_bus == "spi" and len(node.bus_node.regs) == 2:
        reg = node.bus_node.regs[1]  # QSPI flash
    else:
        reg = node.regs[0]

    out("FLASH_BASE_ADDRESS", hex(reg.addr))
    if reg.size:
        out("FLASH_SIZE", reg.size//1024)

...

Flash のアドレスは DT_FLASH_BASE_ADDRESS というマクロで参照できます。エントリーポイントを最終的に決めるのはリンカースクリプトです。SoC で独自のリンカースクリプトを実装することもできるようになっていますが、RISC-V の多くの SoC は、下記のスクリプトを使っています。

エントリーポイントを決めている箇所

// zephyr/include/arch/riscv/common/linker.ld

MEMORY
{
#ifdef CONFIG_XIP
    ROM (rx)  : ORIGIN = DT_FLASH_BASE_ADDRESS, LENGTH = KB(DT_FLASH_SIZE)
#endif
    RAM (rwx) : ORIGIN = CONFIG_SRAM_BASE_ADDRESS, LENGTH = KB(CONFIG_SRAM_SIZE)
    /* Used by and documented in include/linker/intlist.ld */
    IDT_LIST  (wx)      : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
}

Zephyr のエントリポイントがどうやって決まるのか、少しわかった気がします。

[編集者: すずき]
[更新: 2020年 2月 16日 18:21]

コメント一覧

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



link もっと前
   2020年 2月 1日 -
      2020年 2月 1日  
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 サイトの情報