目次: Zephyr
新しい形式のコンテキストスイッチを実装しました。以前書いたとおり、SMP対応は下記の手順で進めています。再掲しておきましょう。
やっと最初の項目が終わったところです。いよいよCONFIG_SMPを有効にします。大量のビルドエラーが発生しますので、1つずつやっつけます。
環境や利用するバージョンによりますが、最初に目にするのはarch_curr_cpu() に関するコンパイルエラーだと思われます。
../include/sys/arch_interface.h:367:28: warning: 'arch_curr_cpu' declared 'static' but never defined [-Wunused-function] static inline struct _cpu *arch_curr_cpu(void); ^~~~~~~~~~~~~
この関数は、現在のCPU(= 実行中のCPU)の情報を返します。RISC-Vにはmhartidという自身のHART IDを取得できるCSR(Control and Status Registers)が規格で定められており、この手の処理は楽に実装できます。
// zephyr/include/arch/riscv/arch_inlines.h
static inline uint32_t z_riscv_hart_id(void)
{
uint32_t hartid;
__asm__ volatile ("csrr %0, mhartid" : "=r"(hartid));
return hartid;
}
static inline struct _cpu *arch_curr_cpu(void)
{
#ifdef CONFIG_SMP
uint32_t hartid = z_riscv_hart_id();
return &_kernel.cpus[hartid];
#else
return &_kernel.cpus[0];
#endif
}
他のアーキテクチャを見る限りarch_inlines.hに定義するのが良さそうですが、RISC-V向けには存在しません。新たに追加しましょう。ヘッダファイルを追加したら、親玉のarch_inlines.hに #includeを追加します。
// zephyr/include/arch/arch_inlines.h
...
#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
#include <arch/x86/arch_inlines.h>
#elif defined(CONFIG_ARC)
#include <arch/arc/arch_inlines.h>
#elif defined(CONFIG_XTENSA)
#include <arch/xtensa/arch_inlines.h>
#elif defined(CONFIG_RISCV) //★この2行を追加する
#include <arch/riscv/arch_inlines.h> //★
#endif
このヘッダは明示的に #includeしなくても常にインクルードされます。
メインCPU以外のCPU(2つ目以降のCPU)を起動するための関数です。SMPモードの他、非SMPモード(※)でも使います。今はCPU 1つで動かすので、とりあえず空関数を定義します。
関数はどこに定義しても動きますが、他アーキテクチャの実装を見るとSMP関連の関数は1つのCソースファイルにまとめた方が良さそうなので、新たにcpu_smp.cを作成します。
// zephyr/arch/riscv/core/CMakeLists.txt
zephyr_library_sources(
cpu_idle.c
cpu_smp.c ★足す★
fatal.c
irq_manage.c
isr.S
prep_c.c
reset.S
swap.S
thread.c
)
// zephyr/arch/riscv/core/cpu_smp.c
void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
arch_cpustart_t fn, void *arg)
{
}
ZephyrというかCMakeのルールですけども、新たにソースコードを追加した場合、CMakeLists.txtにファイル名を追加しコンパイル対象に指定する必要があります。特定のCONFIG_* が定義されたときだけコンパイルすることも可能ですが、今回は不要です。
(※)Zephyrのマルチプロセッサモードには、SMPモードと非SMPモードがあります。SMPモードは、互いのプロセッサ間でIPI(Inter-Processor Interrupt)を用いて制御します。非SMPモードでは、互いのプロセッサのことは何も考慮せず動作します。
これはSMP用のタイマーの初期化関数です。タイマーのハードウェア構成はアーキテクチャによって様々で、一様に「こう実装すべき」という指針はありません。今はCPU 1つで動かすので、とりあえず空関数を定義します。
// zephyr/drivers/timer/riscv_machine_timer.c
...
void smp_timer_init(void)
{
}
今回はRISC-VのPrivilege modeのタイマーが実装対象です。タイマードライバはriscv_machine_timer.cになります。
長くなってきたので、続きは次回。
< | 2020 | > | ||||
<< | < | 10 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
合計:
本日:
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2023.
Powered by PHP 8.2.15.
using GD bundled (2.1.0 compatible)(png support.)