YanaKernel0Aを、C言語(とアセンブリ言語)で実装しています。
とりあえず、MIPSに続いて、ARMについても、サンプルを実行できました。
次のアーカイブ・ファイルは、責任や保証を求めずに、個人的に用いてください。
次のような環境で、サンプルを実行できました。
yana@cygwin ~/yanakernel0ainc/sample/arm/portoff
$ CC="arm-elf-gcc -O2" make
rm -f *.map *.o echo0 echo1 echo2 echo3
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o echo
0.o echo0.c
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o star
t.o ../common/start.S
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o yk0a
_external.o ../common/yk0a_external.S
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o yk0a
_core.o ../../../kernel/arm/yk0a_core.c
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o yk0a
_glue.o ../../../kernel/arm/yk0a_glue.S
../../../kernel/arm/yk0a_glue.S: Assembler messages:
../../../kernel/arm/yk0a_glue.S:31: Warning: writeback of base register is UNPRE
DICTABLE
../../../kernel/arm/yk0a_glue.S:48: Warning: writeback of base register is UNPRE
DICTABLE
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o yk0a
_internal.o ../../../kernel/arm/yk0a_internal.S
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -Wl,-Map,ech
o0.map -Wl,--cref -Wl,-e,start -Wl,-Ttext,0x00001000 echo0.o start.o yk0a_exter
nal.o yk0a_core.o yk0a_glue.o yk0a_internal.o -nostdlib -lgcc -o echo0
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o echo
1.o echo1.c
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -Wl,-Map,ech
o1.map -Wl,--cref -Wl,-e,start -Wl,-Ttext,0x00001000 echo1.o start.o yk0a_exter
nal.o yk0a_core.o yk0a_glue.o yk0a_internal.o -nostdlib -lgcc -o echo1
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o echo
2.o echo2.c
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -Wl,-Map,ech
o2.map -Wl,--cref -Wl,-e,start -Wl,-Ttext,0x00001000 echo2.o start.o yk0a_exter
nal.o yk0a_core.o yk0a_glue.o yk0a_internal.o -nostdlib -lgcc -o echo2
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -c -o echo
3.o echo3.c
arm-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-protot
ypes -march=armv4 -mabi=aapcs -I. -I../common -I../../../kernel/arm -Wl,-Map,ech
o3.map -Wl,--cref -Wl,-e,start -Wl,-Ttext,0x00001000 echo3.o start.o yk0a_exter
nal.o yk0a_core.o yk0a_glue.o yk0a_internal.o -nostdlib -lgcc -o echo3
yana@cygwin ~/yanakernel0ainc/sample/arm/portoff
$ gxemul -q -Etestarm echo0
NOTE: This is a LEGACY emulation mode.
console{c0000000 00000001 200000d7}
yana@cygwin ~/yanakernel0ainc/sample/arm/portoff
$ gxemul -q -Etestarm echo1
NOTE: This is a LEGACY emulation mode.
console{c0000000 00000001 200000db}
yana@cygwin ~/yanakernel0ainc/sample/arm/portoff
$ gxemul -q -Etestarm echo2
NOTE: This is a LEGACY emulation mode.
console{c0000000 00000002 00000000}
yana@cygwin ~/yanakernel0ainc/sample/arm/portoff
$ gxemul -q -Etestarm echo3
NOTE: This is a LEGACY emulation mode.
console{c0000000 00000003 00000000}
yana@cygwin ~/yanakernel0ainc/sample/arm/portoff
$
次のような環境で、サンプルを実行できました。
yana@cygwin ~/yanakernel0ainc/sample/mips/portoff
$ CC="mips-elf-gcc -O2" make
rm -f *.map *.o echo0 echo1 echo2 echo3
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o ec
ho0.o echo0.c
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o st
art.o ../common/start.S
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o yk
0a_external.o ../common/yk0a_external.S
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o yk
0a_core.o ../../../kernel/mips/yk0a_core.c
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o yk
0a_glue.o ../../../kernel/mips/yk0a_glue.S
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o yk
0a_internal.o ../../../kernel/mips/yk0a_internal.S
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -Wl,-Map,e
cho0.map -Wl,--cref -Wl,-e,start -Wl,-Ttext,0x80001000 echo0.o start.o yk0a_ext
ernal.o yk0a_core.o yk0a_glue.o yk0a_internal.o -nostdlib -lgcc -o echo0
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o ec
ho1.o echo1.c
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -Wl,-Map,e
cho1.map -Wl,--cref -Wl,-e,start -Wl,-Ttext,0x80001000 echo1.o start.o yk0a_ext
ernal.o yk0a_core.o yk0a_glue.o yk0a_internal.o -nostdlib -lgcc -o echo1
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o ec
ho2.o echo2.c
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -Wl,-Map,e
cho2.map -Wl,--cref -Wl,-e,start -Wl,-Ttext,0x80001000 echo2.o start.o yk0a_ext
ernal.o yk0a_core.o yk0a_glue.o yk0a_internal.o -nostdlib -lgcc -o echo2
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -c -o ec
ho3.o echo3.c
mips-elf-gcc -O2 -g -ffreestanding -std=c89 -Wall -Wpointer-arith -Wstrict-proto
types -march=mips32 -mabi=eabi -I. -I../common -I../../../kernel/mips -Wl,-Map,e
cho3.map -Wl,--cref -Wl,-e,start -Wl,-Ttext,0x80001000 echo3.o start.o yk0a_ext
ernal.o yk0a_core.o yk0a_glue.o yk0a_internal.o -nostdlib -lgcc -o echo3
yana@cygwin ~/yanakernel0ainc/sample/mips/portoff
$ gxemul -q -Eoldtestmips -C4kc echo0
NOTE: This is a LEGACY emulation mode.
console{c0000000 00000001 00000010}
yana@cygwin ~/yanakernel0ainc/sample/mips/portoff
$ gxemul -q -Eoldtestmips -C4kc echo1
NOTE: This is a LEGACY emulation mode.
console{c0000000 00000001 00000014}
yana@cygwin ~/yanakernel0ainc/sample/mips/portoff
$ gxemul -q -Eoldtestmips -C4kc echo2
NOTE: This is a LEGACY emulation mode.
console{c0000000 00000002 00000000}
yana@cygwin ~/yanakernel0ainc/sample/mips/portoff
$ gxemul -q -Eoldtestmips -C4kc echo3
NOTE: This is a LEGACY emulation mode.
console{c0000000 00000003 00000000}
yana@cygwin ~/yanakernel0ainc/sample/mips/portoff
$
まず、この実装では、次のような資源をカーネルの内部で使用しています。
次に、カーネルの内部から外部へのインターフェースは、プロセッサの外部のメモリではなく、プロセッサの内部のレジスタを使用しています。
カーネルの外部から内部へのインターフェースは、プロセッサの内部のレジスタと、ルーチン「yk0a_initialize」とルーチン「yk0a_exception_interrupt_procedure」を使用しています。
ここで、プロセッサについてですが、カーネルの内部と外部で1個のプロセッサを使用しています。
ルーチン「yk0a_initialize」を実行すると、カーネルの内部の処理の後で、カーネルの外部に戻ります。
ルーチン「yk0a_exception_interrupt_procedure」を実行すると、カーネルの内部の処理の後で、実行可能状態のTaskがなければ、割り込みを待ち、実行可能状態のTaskがあれば、カーネルの外部に戻ります。
カーネルの内部の処理時間ということでは、ルーチン「yk0a_initialize」には、マクロ「YK0A_SETUP_PORT_SIZE」に比例する部分と、マクロ「YK0A_SETUP_PRIORITY_SIZE」に比例する部分と、マクロ「YK0A_SETUP_TASK_SIZE」に比例する部分があります。
ルーチン「yk0a_exception_interrupt_procedure」には、マクロ「YK0A_SETUP_PRIORITY_SIZE」に比例する部分(関数「yk0a_schedule_update」)があります。
なお、関数「yk0a_schedule_update」については、マクロ「YK0A_SETUP_PRIORITY_SIZE」でループしていますが、ARMとMIPSの命令「CLZ」などのビット処理に変更できそうです。
また、メモリについてですが、カーネルの内部と外部で共有しているのは、ルーチン「yk0a_initialize」とルーチン「yk0a_exception_interrupt_procedure」を実行する部分だけです。
例えば、カーネルのスタックを、例外ハンドラや割り込みハンドラなどが読み書きすることはありませんし、Taskのスタックを、カーネルが読み書きすることもありません。
カーネルの内部のメモリ容量ということでは、コンパイラなどに依存しますが、使用例を整理しました。
なお、カーネルのスタックについては、再帰や再入などで使用するわけではありませんし、逆アセンブルして、上限を確認しました。
|
|
.text |
.bss - stack |
stack |
|---|---|---|---|
|
yk0a_exception_forward |
|
|
case0: 8 |
|
yk0a_interrupt_bit_flag |
|
|
case1: 16 |
|
yk0a_core_initialize |
|
|
case2: 24 |
|
yk0a_core_exception_interrupt_procedure |
|
|
case3: 32+max(case0, case1) |
|
yk0a_core.c |
2824 |
yk0a_interrupt_mask: 4 yk0a_port_control: 16 * YK0A_SETUP_PORT_SIZE yk0a_schedule_link: 4 yk0a_schedule_queue: 8 * YK0A_SETUP_PRIORITY_SIZE yk0a_task_control: 92 * YK0A_SETUP_TASK_SIZE |
max(case2, case3)=48 |
|
yk0a_glue.S |
128 |
0 |
0 |
|
|
.text + .rodata |
.sbss + .bss - stack |
stack |
|---|---|---|---|
|
yk0a_exception_forward |
|
|
case0: 0 |
|
yk0a_interrupt_bit_flag |
|
|
case1: 0 |
|
yk0a_core_initialize |
|
|
case2: 0 |
|
yk0a_core_exception_interrupt_procedure |
|
|
case3: 8+max(case0, case1) |
|
yk0a_core.c |
3080 |
yk0a_port_control: 16 * YK0A_SETUP_PORT_SIZE yk0a_schedule_link: 4 yk0a_schedule_queue: 8 * YK0A_SETUP_PRIORITY_SIZE yk0a_task_control: 156 * YK0A_SETUP_TASK_SIZE |
max(case2, case3)=8 |
|
yk0a_glue.S |
476 |
0 |
0 |
あと、割り込みコントローラについてですが、ARMの場合は、カーネルの内部と外部で1個の割り込みコントローラを使用しています。
MIPSの場合は、割り込みコントローラを使用していませんが、プロセッサのレジスタ「Status」のフィールド「IM」とレジスタ「Cause」のフィールド「IP」を読み書きしています。
割り込みが発生すると、ルーチン「yk0a_exception_interrupt_procedure」を実行して、カーネルの内部で、割り込みの要求ビットを取得してから、取得したビットで割り込みを無効にして、取得したビットでFlagを設定します。
なお、カーネルの内部で割り込みを無効にするのは、割り込みの発生が続かないようにするためですので、発生した割り込みを無効にするような割り込みコントローラでは、カーネルの内部で割り込みコントローラを読み書きしないように変更できそうです。
(C) 2009-2011 Yana
Direction: Yana
HTML: Yana
Program: Yana
2011-03-11 release 4
2010-03-11 release 3
2009-09-11 release 2
2009-07-11 release 1
2009-05-11 release 0