Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ZephyrRTOSのLongan Nanoへの移植

soburi
June 24, 2022

ZephyrRTOSのLongan Nanoへの移植

800円で買えるRISC-V開発ボードのLongan NanoへZephyrRTOSを移植します。

soburi

June 24, 2022
Tweet

More Decks by soburi

Other Decks in Technology

Transcript

  1. ZephyrRTOSの
    Longan Nanoへの移植
    常田 裕士 RISC-V勉強会 2022/6/24

    View Slide

  2. 自己紹介
    ▪ 常田 裕士
    ▪ 某F社勤務 昔はガラケー、今はカーナビ関連(主にLinuxを動くようにするお仕事)
    ▪ KiCadで雑に基板を作るチュートリアル (v6.0予習版)
    https://speakerdeck.com/tokitahiroshi/kicaddeza-niji-ban-wozuo-
    rutiyutoriaru-ver6-dot-x-yu-xi-ban
    ▪ インターフェース誌 2022年6月号
    第2特集 C/C++でPython拡張
    第1部 ハードウェア効率化…C/C++で拡張モジュール作り
    https://interface.cqpub.co.jp/magazine/202106/
    ▪ 技術書典とかコミケとか。来年はNT金沢出しに行きたい。

    View Slide

  3. 本日のアウトライン
    ▪ ZephyrRTOSとLongan NanoおよびGD32Vについて
    ▪ 移植の概要
    ▪ 移植のポイント
    ▪ ベース移植
    ▪ ドライバを作る
    ▪ GD32V固有の厄介事
    ▪ 学び

    View Slide

  4. ZephyrRTOSと
    Longan Nanoおよび
    GD32Vについて

    View Slide

  5. ZephyrRTOS
    ▪ LinuxFoundationがやっている組み込み向けのRTOS
    もともとはWindRiverが作った。割と素性は良い。
    ▪ LinuxからKconfigとDeviceTreeの仕組みを借りてきている。
    他にもいろいろLinuxにAPIなどは似せようとしている。
    ▪ POSIX互換レイヤーもある。
    ▪ 「組み込み用のLinux」と言っても当たらずとも遠からじ、みた
    いな雰囲気。
    ▪ 最近はNordicSemiが自社の開発環境に組み込んで、
    使い倒している。(メインの開発環境にしようとしている)
    画像は
    https://ja.wikipedia.org/wiki/Zephy
    r_(オペレーティングシステム)
    より

    View Slide

  6. 成長中
    ▪ ソースコード公開してから順調にソースもコミュニティも成長している。
    ▪ 海外での注目度に比べて、国内でのプレゼンスが低い感じはする。
    ▪ 最近は車載系向けの機能安全やMISRA-C準拠も進んでいる。

    View Slide

  7. Zephyrの主要企業
    ▪ プラットフォーム屋さん、半導体屋さんを
    中心に豪華メンバーが集まっている。

    View Slide

  8. Longan Nano
    ▪ 小さなカラーLCDが付いて800円。秋葉原でも入手可能。
    ▪ RISC-Vコア搭載のSoC, GigaDevice GD32Vを使用
    ▪ もともとGigaDeviceにGD32というARMのマイコンのラインがあった。
    GD32は某S社のマイコンとピンコンパチ
    ▪ このGD32のARMのプロセッサ部をRISC-Vに差し替えたのが
    GD32V。RISC-VのコアはNuclei社(武漢)のIPを使用。
    画像はhttps://www.switch-
    science.com/catalog/5946/ より

    View Slide

  9. 実は評価は高いチップ
    ▪ https://www.embedded-world.de/en/news/press-
    releases/winner-embedded-awards-0dhccwe30m_pireport
    ▪ 2020年Embedded Worldのハードウエア部門で優勝
    ▪ https://riscv.or.jp/2021/04/kageyama-gigadevice/
    ▪ 日本のRISC-V協会からもアナウンスあり。

    View Slide

  10. Longan Nano の ZephyrRTOS対応の経緯
    ▪ 2020年3月、技術書典 応援祭の出し物にすべくLongan Nanoへの
    ZephyrRTOS移植を実施、この時点で初期版はほぼ完成していた。
    あわせて出し物として作成した(怪)文書をgithubにアップロード
    ▪ 2021年5月、フランス人の開発者@martoni氏 から問い合わせを受ける。上記
    githubに置いた文書を仏語に翻訳して参照してもらっていた。需要が確認でき、まだ
    誰もパッチ投稿していなかったので、昨年作成したコードを整理してPRを提出。
    ▪ 2021年12月、upstreamへのマージ完了。

    View Slide

  11. 移植の概要

    View Slide

  12. ZephyrへのCPUアーキ追加
    ▪ ソースの共通化のグループで
    arch→soc→boards
    の構造がある。矢印の順で細分化される。
    ▪ socに追加するのは比較的レアケース。新しいSoCを作らないと
    作成する必要がない。(SoCメーカーと非関係者がやると色々心
    配される)
    Zephyr
    arch
    boards
    drivers
    dts
    kernel
    soc
    subsys

    View Slide

  13. archディレクトリの役割
    ▪ archはx86, arm, riscvなどCPUアーキテクチャ毎の共通ソース。
    ▪ 主に基本的な割り込みの定義と処理
    ▪ 割り込みに関連して、コンテクストスイッチの処理もここで実装
    ▪ リセットの処理、CPU例外の処理、アイドル処理
    ▪ コード量はそこまで多くない。ほとんどアセンブラ
    ▪ 命令セットを作らないと追加する必要がないので滅多に増えない。
    ▪ 最近mipsが出来た。

    View Slide

  14. soc階層の役割
    ▪ socはSoCの定義。stm32, nrf5x など。ICかIPコア。
    ▪ SoC固有の初期化処理、起動処理を行って、
    共通の初期化処理__initializeを呼び出す
    ▪ SoC固有のペリフェラルや機能の設定。
    ▪ archよりはかなり少なくなるが、まだ、アセンブラソースは残る。
    ▪ リンカの設定

    View Slide

  15. boardsの階層の役割
    ▪ この階層では実装の.cのコードはほぼ登場しない。socの定義とドライバを組み合わせ
    て開発ボードのconfigurationを行う。
    ▪ デバッガの設定
    ▪ boardsは開発ボードのピンや接続しているペリフェラルを定義。ここのレイヤーは頻繁
    に追加される。

    View Slide

  16. main()までの道
    ▪ mainまで動けば、基本動作部分の
    移植完了と言える。
    ▪ OSとしての共通動作は既に実装され
    ている。SoC固有のブート処理、初期
    化処理を作るのが移植のメインの作業。
    ▪ 面倒だが、難しいというわけではない。
    ▪ この勉強会の高橋浩和さんの「RISC-
    V OSを作ろう」の1,2回あたりの内容
    を参考にすると追いかけやすいはず。
    ▪ mainが動いたら、SoCが持っているペ
    リフェラルのドライバを作っていく。
    EntryPoint 割り込みハンドラの設定
    __initialize スタックの初期化、マルチコアの処理
    _PrepC BSS初期化, dataセクションをRAMにコピー
    z_cstart
    SoC初期化処理(主にclockの設定)
    ドライバ初期化
    割込コントローラー
    タイマー
    mainスレッドの作成
    main()
    archレイヤーで実装され
    ている共通処理(作らない)
    socレイヤーで実装する処

    View Slide

  17. 移植のポイント #1
    ベース部分の移植

    View Slide

  18. Longan Nano (GD32V)対応で行ったこと。
    ▪ 最低限動作させるために必要だったこと
    ▪ ブート部分の移植
    ▪ 変則的なmcauseを正しくハンドリングする
    ▪ Machine Timerのドライバ修正
    ▪ 割込コントローラを動かす
    ▪ やらなくてよいこと(Zephyrですでに実装済みのもの)
    ▪ context switchやタスクなど、スケジューラに関する処理は実装済み、対応不要
    ▪ BSS初期化などSoC固有でない初期化処理
    ▪ 割り込みハンドラ共通部の実装
    ▪ 素直なRISC-Vプロセッサならこの辺は不要となる場合もある。
    (SiFive FreedomやQEMU環境ではほとんどやっていない。)
    ⇔QEMUと違うなら対応が必要。

    View Slide

  19. ブートの処理 #1
    ▪ ブートコードを移植する。
    ▪ RISC-V共通のブート実装はあるが、
    SoC固有の「オマジナイ」的な処理があ
    ればファイルを分けて自前で実装する必
    要がある。
    /* Disable Global Interrupt */
    csrc mstatus, MSTATUS_MIE
    /* Jump to logical address first to ensure correct operation of RAM region */
    la a0, __nuclei_start
    li a1, 1
    slli a1, a1, 29
    bleu a1, a0, _start0800
    srli a1, a1, 2
    bleu a1, a0, _start0800
    la a0, _start0800
    add a0, a0, a1
    jr a0
    EntryPointのアドレスを見てRAM/FLASH実行の判定
    (オマジナイ)
    soc/riscv/riscv-privilege/gd32vf103/entry.S

    View Slide

  20. ブートの処理 #2
    ▪ 標準にないCSRの設定などをやる。
    ▪ Nuclei社の拡張CSRのMMISC_CTLを設定
    (0x200=NMIハンドラのアドレスにmtvecの値を共
    有する)
    ▪ mtvecに割り込みハンドラを設定
    ▪ mtvecの下位2ビットを3に設定して、Nuclei社の
    ECLIC割り込みコントローラを使う設定を行う。(ISA
    では0, 1しか定義していない。)
    ▪ mcountinhibitを無効にする。(電力消費を抑える)
    ▪ 最後に__resetに飛ぶ。(__resetはそのまま
    __initialize)を呼ぶ。
    /* Set the the NMI base to share with mtvec by setting CSR_MMISC_CTL */
    li t0, 0x200
    csrs CSR_MMISC_CTL, t0
    /* Initial the CSR MTVEC for the Trap ane NMI base addr */
    la t0, trap_entry
    csrw mtvec, t0
    /* Direct Mode: All exceptions set pc to BASE. */
    csrc mtvec, 0x3
    /* Disable performance counter */
    csrsi mcountinhibit, 0x5
    /* Jump to __reset */
    tail __reset
    soc/riscv/riscv-privilege/gd32vf103/entry.S

    View Slide

  21. ブートの処理 #3
    ▪ archの共通部分で実装している __irq_wrapperが
    64bit alignになっていないので、簡単なラッパを作る。
    ▪ mtvecに渡せるアドレスが64bit alignを要求している
    ので、レジスタ定義もMODEのビット数を増やしている。
    (ただし実質的には使っていない) soc/riscv/riscv-privilege/gd32vf103/entry.S
    .align 6
    trap_entry:
    tail __irq_wrapper
    The RISC-V Instruction Set Manual
    Volume II: Privileged Architecture より
    Nuclei ISA Specより
    Field Bit Description
    ADDR 31:6 mtvec address
    MODE 5:0
    •MODE field determine interrupt mode:
    • 000011: CLIC interrupt mode
    • Others: CLINT interrupt mode

    View Slide

  22. MCAUSEを正しくハンドリングする
    ▪ RISC-VのInstruction Set Manualの定義
    では上位1ビット除いた残りのビットすべてが
    ExceptionCodeとして使われる。
    が、Nucleiのコアだと11ビット目までが
    ExceptionCodeで、
    上位ビットは別の用途で使われている。
    ▪ MCAUSEのマスク値を
    defineできるようにソース修正した。
    The RISC-V Instruction Set Manual
    Volume II: Privileged Architecture より
    Nuclei ISA Specより
    Field Bit Description
    INTERRUPT 31
    Current trap type:
    •0: Exception or
    NMI
    •1: Interrupt
    MINHV 30
    Indicate processer
    is reading
    interrupt vector
    table
    MPP 29:28
    privilege mode
    before interrupt
    MPIE 27
    Interrupt enable
    before interrupt
    Reserved 26:24 Reserved 0
    MPIL 23:16
    Previous interrupt
    level
    Reserved 15:12 Reserved 0
    EXCCODE 11:0
    Exception/Interrup
    t Encoding

    View Slide

  23. 影響箇所
    ▪ SOC_MCAUSE_EXP_MASKの値を
    configurableにした
    ▪ 割り込みハンドラの__irq_wrapperの中
    で、mcauseの値を見て、処理の分岐を
    行っている。
    ▪ ECALL割り込みが正しく処理できなかった
    ので、コンテキストスイッチができなかった。
    /* Get IRQ causing interrupt */
    csrr a0, mcause
    li t0, SOC_MCAUSE_EXP_MASK
    and a0, a0, t0
    /*
    * Clear pending IRQ generating the interrupt at SOC level
    * Pass IRQ number to __soc_handle_irq via register a0
    */
    jal ra, __soc_handle_irq
    /*
    * If the exception is the result of an ECALL, check whether to
    * perform a context-switch or an IRQ offload. Otherwise call _Fault
    * to report the exception.
    */
    csrr t0, mcause
    li t2, SOC_MCAUSE_EXP_MASK
    and t0, t0, t2
    /*
    * If mcause == SOC_MCAUSE_ECALL_EXP, handle system call from
    * kernel thread.
    */
    li t1, SOC_MCAUSE_ECALL_EXP
    beq t0, t1, is_kernel_syscall
    arch/riscv/core/isr.S

    View Slide

  24. SoCの初期化処理
    ▪ C言語で書ける初期化処理を登録する。
    ▪ クロックの設定などは、これで行う場合が多い。
    ▪ SYS_INITマクロで呼び出す関数を優先度を指定して登録する。
    ▪ リンカで初期化処理専用のセクションにまとめられて、実行される。
    ▪ SoCベンダー提供のコードのクロック初期化処理の関数を呼ぶようにした。
    SYS_INIT(gigadevice_gd32v_soc_init, PRE_KERNEL_1,
    CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
    soc/riscv/riscv-privilege/gd32vf103/soc.c

    View Slide

  25. ECLICのドライバを作成する
    ▪ ECLICはNuclei社のプロセッサ固有の機能で、
    PLICを拡張したような割り込みコントローラ。
    ▪ PLICと違って、Machine Timerの割り込み、
    ソフトウェア割り込みもECLIC経由で上がってくる。
    (右図)
    ▪ 実質的にはSoC本体の初期化の一部。ファイル
    構成としてはドライバの下だが、SoC側の処理と
    考えた方がよさそう。

    View Slide

  26. 割り込み処理の呼び出し
    ▪ arch_irq_(enable|disable|is_enabled|prior
    ity_set) として割り込みの共通I/Fが定義されてい
    るので、この実装を入れ替える。
    ▪ PLICの代替になるので、PLICと排他的にマクロで切
    り分け。
    ▪ 抽象化が何もされてないので、ドライバというよりかは
    初期化処理の実装の単なるファイル分割。
    ▪ SOCの初期化処理と同様、 SYS_INITマクロで登
    録する。
    void nuclei_eclic_irq_enable(uint32_t irq)
    {
    ECLIC_CTRL[irq].INTIE.b.IE = 1;
    }
    SYS_INIT(nuclei_eclic_init, PRE_KERNEL_1,
    CONFIG_INTC_INIT_PRIORITY);
    drivers/interrupt_controller/intc_nuclei_eclic.c
    arch/riscv/core/isr.S
    void arch_irq_enable(unsigned int irq)
    {
    uint32_t mie;
    #if defined(CONFIG_RISCV_HAS_PLIC)
    unsigned int level = irq_get_level(irq);
    if (level == 2) {
    irq = irq_from_level_2(irq);
    riscv_plic_irq_enable(irq);
    return;
    }
    #endif
    #if defined(CONFIG_NUCLEI_ECLIC)
    nuclei_eclic_irq_enable(irq);
    return;
    #endif

    View Slide

  27. Machine Timerを動かす
    ▪ スケジューラを動かすのにタイマー割り込みを使う。
    ▪ RISC-VではCPUのクロックを使ったタイマー(Machine Timer)を持っている。
    Zephyrにもドライバがある。
    ▪ GD32Vでは、CPUクロックを4分周したクロックがこのタイマーに入力されている。
    ▪ ZephyrRTOSのRISC-V Machine Timerのドライバは、CPUの周波数と
    TickCount数から時間を設定している。動くには動くが、1/4倍速になってしまうので、
    入力を1/4、出力をx4して帳尻を合わせる改造を行った。

    View Slide

  28. Clock diagram
    ▪ クロックの系統が分かれていて、4分周しているみたい。

    View Slide

  29. 実際には…
    ▪ 実際に開発すると、タイマーを動かさないと割り込みは発生しないし、
    タイマーの割り込みを設定するためには、割り込みコントローラーのドライバが必要、
    という循環した依存関係がある。
    ▪ どうしてもモグラ叩き的になる。これは仕方ない。
    ▪ 開発初期の段階では、割り込みコントローラの処理などは、共通の起動処理にて実
    装、システムがある程度立ち上がってきたらドライバとして分割、というような開発の流
    れになる。

    View Slide

  30. 補足: Zephyrにおける割り込み処理
    ▪ Zephyrでは、IRQ_CONNECTのマクロを使って割り込みハンドラを指定する。
    ▪ ビルド中にIRQ_CONNECTの宣言の情報を収集し、pythonのスクリプトで解析し
    て、isr_tables.cとして割り込みハンドラのテーブルを生成する。
    (つまり、2パスでコンパイルしている)
    ▪ mtvecに登録した__irq_wrapperの中で、このテーブルを参照して登録した割り込
    みハンドラを呼び出している。
    割り込み発生
    __irq_wrapper
    テーブルを参照する
    isr_table.c
    2回コンパイルして
    テーブルを作る
    IRQ_CONNECT
    IRQ_CONNECT
    割り込みハンドラ

    View Slide

  31. 移植のポイント #2
    ドライバの作成

    View Slide

  32. ドライバを作る
    ▪ 初期移植だと右図の
    「動作確認に必要」あたりまで欲
    しい。
    ▪ 「Arduino程度」になると結構使
    える。
    贅沢品
    CAN, Watchdog, QSPI, etc…
    Arduino程度
    SPI, I2C, PWM, GPIO(入力)
    動作確認に必要
    UART, GPIO(出力)
    OSを動かすのに必要
    Machine Timer
    SoCの一部
    割り込みコントローラ

    View Slide

  33. Zephyrのデバイス/ドライバ
    ▪ デバイス=システムに乗っているハードウェア、ドライバ=それを動かすためのプログラム
    ▪ DeviceTreeの定義で「システムにどのようなデバイスがあって、どのドライバで動かすの
    か」を決める。
    ▪ ドライバとデバイスの関係は、オブジェクト指向のクラスとインスタンスみたいなもの。
    データと処理をまとめた単位が複数個存在する。
    ▪ デバイスの種別ごとにAPIがある。ドライバはこのAPIに適合する形でデータと関数を実
    装する。
    デバイス
    デバイスごとに
    データを確保する
    ドライバ
    同一種のデバイ
    スの処理は共通
    N 1

    View Slide

  34. DeviceTreeとソースコードとの連携
    ▪ DeviceTreeはもともとLinuxの仕組み。
    ▪ ARMの無秩序なパッチが多くて、Linus氏がブチ切れて導入された…と記憶
    ▪ https://srad.jp/story/11/06/22/0911201/
    ▪ デバイスの依存関係を専用の言語で記述して、実行時に解決する仕組み。
    ▪ 依存性注入の手法。結果、ドライバとデバイスが依存しなくなる。
    ▪ ZephyrRTOSでは、DeviceTreeはビルド時にC言語のマクロとして展開される。
    ▪ RTOSの場合、メモリはstaticに確保するのが原則。(mallocが無いかもしれない)
    マクロに展開されたDeviceTreeの情報を使って、デバイス毎のデータ領域を静的に
    確保するのがZephyrのドライバのお作法。
    ▪ ここだけ抑えれば、ドライバはただの関数の集まり。

    View Slide

  35. DeviceTreeからマクロが生成される
    ▪ Zephyrのビルドの過程でDeviceTree
    のファイルからdevicetree_unfixed.h
    のヘッダファイルを生成する
    ▪ 専用のマクロ群で簡単に扱えるように
    なっている。
    ▪ マクロ自体は複雑。
    エラー出るとデバッグは面倒。 dts/riscv/gigadevice/gd32vf103.dtsi から抜粋、編集
    / {
    soc {
    usart0: serial@40013800 {
    compatible = "gd,gd32-usart";
    reg = <0x40013800 0x400>;
    interrupts = <56 0>;
    interrupt-parent = <&eclic>;
    rcu-periph-clock = <0x60e>;
    status = “okay";
    label = "UART_0";
    };
    usart1: serial@40004400 {
    compatible = "gd,gd32-usart";

    生成されたdevicetree_unfixed.h
    #define DT_N_S_soc_S_serial_40013800_PATH "/soc/serial@40013800"
    #define DT_N_S_soc_S_serial_40013800_FULL_NAME "serial@40013800"
    #define DT_N_S_soc_S_serial_40013800_PARENT DT_N_S_soc
    #define DT_N_S_soc_S_serial_40013800_CHILD_IDX 3

    View Slide

  36. DeviceTreeの情報を使って、デバイス毎のデータを宣言する
    ▪ ドライバの実装側からは DT_DRV_COMPAT の宣言で対応する
    種別を指定する
    ▪ デバイス毎に必要なデータを宣言するマクロを定義する。
    ▪ 引数を使って、名前が被らないようにする
    ▪ 定数値はconfig, 可変値はdata。
    ▪ DEVICE_DT_INST_DEFINEでデバイスを登録する。起動時
    に初期化処理が行われる。
    ▪ 初期化関数とAPIの関数ポインタテーブルを登録する
    ▪ DT_INST_FOREACH_STATUS_OKAY は、DeviceTreeで
    有効なデバイスのマクロを展開して変数宣言を行う
    ▪ DT_INST_PROP系のマクロで、デバイスツリーの値を取得できる。
    ▪ これで全部staticに処理できる。
    drivers/serial/usart_gd32.c
    #define DT_DRV_COMPAT gd_gd32_usart
    #define GD32_USART_INIT(n)
    static struct gd32_usart_data usart_gd32_data_##n = {
    .baud_rate = DT_INST_PROP(n, current_speed),
    };
    static const struct gd32_usart_config usart_gd32_config_##n = {
    .reg = DT_INST_REG_ADDR(n),
    };
    DEVICE_DT_INST_DEFINE(n, &usart_gd32_init,
    NULL,
    &usart_gd32_data_##n,
    &usart_gd32_config_##n, PRE_KERNEL_1,
    CONFIG_SERIAL_INIT_PRIORITY,
    &usart_gd32_driver_api);
    DT_INST_FOREACH_STATUS_OKAY(GD32_USART_INIT)

    View Slide

  37. ドライバを使う
    ▪ ドライバで登録したデバイスは
    DEVICE_DT_GET(node_id)のマクロで取得でき
    る。
    ▪ ZephyrのDevice Driver APIの各関数を
    取得したデバイスをして実行する
    ▪ デバイスの種別に合ったAPIを使うこと。
    static const struct device *uart_dev =
    DEVICE_DT_GET(UART_DEVICE_NODE);
    void main(void)
    {
    if (!device_is_ready(uart_dev)) {
    printk("UART device not found!");
    return;
    }
    /* configure interrupt and callback to receive data */
    uart_irq_callback_user_data_set(uart_dev, serial_cb, NULL);
    uart_irq_rx_enable(uart_dev);
    }
    samples/drivers/uart/echo_bot/src/main.c から抜粋

    View Slide

  38. 現在のGD32Vの対応状況
    ▪ 同時期にGD32(ARM)の対応も並行して行われていたため、
    最終的にARM移植する際に作成したUARTドライバ/GPIOドライバに相乗りした。
    ▪ Arduinoレベルはだいたい完了
    ▪ GPIO、I2C、SPI、PWM
    ▪ まだすべてのデバイスは動作していない。
    ▪ Watchdog (PR済み)
    ▪ Timer (未作成)
    ▪ Longan NanoとしてもLCD対応中

    View Slide

  39. GD32V固有の厄介事

    View Slide

  40. ARM/RISC-Vの命名規約が合わない
    ▪ 歴史的な経緯でRISC-VとARMのディレクトリ構成のルールが違っている。
    ディレクトリ構成はCMakeの定義名に反映されるので、命名規約が合わない。
    (ARMはSoCメーカー名ベースでディレクトリを掘っている, RISC-Vにはriscv-privilegeという中
    間ディレクトリがあって名前がぐちゃぐちゃになっている。 riscv-privilegeって分類?)
    ▪ ARMのGD32シリーズとRISCVのGD32Vシリーズでドライバを共通化しているため、
    SoCの識別ルールが統一されていないとやりづらい。
    ▪ SOC_FAMILY > SOC_SERIES > SOC
    例) nordic_nrf > nrf51 > nrf51822
    GD32Vでは) riscv-privilege > gd32vf103 > gd32vf103 (同じにする必要はない…)
    ▪ 決めの問題なので、意思決定できる人が決めないと決まらない。
    寝てる間にDiscordで電話会議が行われていて、いつの間にか方針が決まってた。
    (連絡は来てたが見逃した。結論は「近い将来ディレクトリ構成を直そう。」)
    ▪ 名前は地味に紛糾する。

    View Slide

  41. クローンチップであることによる足枷
    ▪ クローン元のドライバには相乗りできない。
    ▪ クローン元の会社さんも開発リソースを投入してZephyrにContributeしている。
    ▪ ほぼ同じソースで動くのはわかっているが、仁義としてダメ。
    ▪ 実際、RISC-VのIPコアを開発しているNuclei社の開発者はこの移植のdiscussionに
    参加しているが、SoCベンダさんの開発者は一切タッチしていない。
    ▪ 故に、部外者の私が移植を行う余地があったとも言える。
    ▪ GD32にアンタッチャブル感があったので、ひょっとしたら派手に横紙破りをやった格好?
    ▪ したがって、GD32Vの開発は「コミュニティドリブン」で進んでいる、という建て付け。
    ▪ アクティブな開発者が新しい実装を試す実験場にしてる?!
    Please, do not mention STM32 at Zephyr. Everybody knows that
    there are GigaDevices that can replace STM32.
    というアドバイスをメールで頂戴した。

    View Slide

  42. RISC-V IPのSDKが別個に提供されている
    ▪ IPベンダーのNuclei社からRISC-V部のSDKが提供が
    提供されている。
    ▪ SoCベンダーのGigaDevice社はNuclei社から提供され
    たSDKを取り込んで、
    SoCのSDKを作成しているのだが、版数が古い。
    ▪ 現状は独自にレジスタの定義ファイルを作成するなどして、
    Nuclei社のSDKに依存しないようにしている。
    ▪ Nuclei社のコアを使った別のSoCの移植が行われるまで
    は問題にはならないはず。
    Nuclei GigaDevice
    Nuclei社が最
    新版を提供し
    ている…

    View Slide

  43. 学び

    View Slide

  44. やってみてわかったこと
    ▪ 実際パッチ出す人はそんなに多くない。
    ▪ 英語苦手でもGrammary神とGoogle先生が居れば何とかなる。
    ▪ DeepLは裏切る
    ▪ Zephyrの移植自体は難易度はそこまで高くはない。
    が、守備範囲がそれなりに広いので大変なのは大変。
    ▪ 出せばだいたい何とかなるので、みんなパッチ出そう。

    View Slide

  45. 参考文献
    ▪ Zephyr Project Documentation
    ▪ https://docs.zephyrproject.org/3.1.0/
    ▪ The RISC-V Instruction Set Manual
    Volume II: Privileged Architecture
    ▪ https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-
    privileged-20211203.pdf
    ▪ Nuclei ISA Spec
    ▪ https://doc.nucleisys.com/nuclei_spec/
    ▪ Nuclei Bumblebee Datasheet
    ▪ https://raw.githubusercontent.com/nucleisys/Bumblebee_Core_Doc/master/Bumblebe
    e%20Core%20Brief%20Manual.pdf
    ▪ Longan Nano のZephyr 対応事例紹介 増補版
    ▪ https://techbookfest.org/product/6326080979861504?productVariantID=5338792099
    577856&utm_campaign=share&utm_medium=social&utm_source=twitter

    View Slide


  46. View Slide