ARM AArch64 プロセッサ向け TOPPERS/SSP カーネル「名古屋のIoTは名古屋のOSで」

「名古屋のIoTは名古屋のOSで」ARM AArch64 プロセッサ向け TOPPERS/SSP カーネル
http://dev.toppers.jp/trac_user/contrib/wiki/ssp_aarch64

動作させてみた。

# 第一段階 docker または Ubuntu xenialの用意
Ubuntu xenialのdockerを利用している。
Ubuntu xenialでも動作する。

## Windows

## Macintosh
Dockerどっかー使い方おかしかったんでしょうか。TOPPERS/SSP on RaspberryPi with Macintosh編：９つの関門
https://qiita.com/kaizen_nagoya/items/cbf40186ae4da48ec4c7

## Linux

# 第二段階　
git
http://github.com/nmiri-nagoya-nsaito/docker-toppers


```
$ git clone https://github.com/nmiri-nagoya-nsaito/docker-toppers.git
```
## gitの導入

Macintosh: brew install git
Debian/Ubuntu: apt-get install git

# 第三段階　docker-compose build --no-cache

```
$ cd docker-toppers
$ docker-compose build --no-cache
$ ./start_shell.sh 
```

```sh:start_shell.sh 
#!/usr/bin/env bash

set -eu

SERVICE=cli

if [ "x$(docker-compose ps -q ${SERVICE})" = "x" ]; then
  docker-compose build ${SERVICE}
fi
docker-compose up -d ${SERVICE}
docker exec -i -t `docker-compose ps -q ${SERVICE}` bash --login

exit 0
```

```sh:setup_user.sh
#!/usr/bin/env bash

set -eu

echo export LANG=ja_JP.UTF-8 >> ${HOME}/.profile
echo export LANGUAGE=ja_JP:ja >> ${HOME}/.profile
echo LV="-Au8" >> ${HOME}/.profile
cat << EOS >> ${HOME}/.vimrc
:set fenc=utf-8
:set fencs=iso-2022-jp,euc-jp,cp932,utf-8
:set enc=utf-8
EOS

exit 0
```

# 第四段階　workdir共有

```
$ cd workdir
$ svn co http://dev.toppers.jp/svn_user/contrib/ssp_aarch64/trunk ssp_aarch64
```

# 第五段階　コンパイル

```
$ ssp_aarch64/build_ssp.sh 
```

# 第六段階　実行

```
$ cd ssp/build
$ qemu-system-aarch64 -M virt -cpu cortex-a53 -nographic -kernel sup
```

# 第七段階　キーボードから命令
キーボードから何も入力しなければ、Sample program starts.と表示しているだけで画面は動きません。
キーボードからa, b, c, d, eなどと打つと次のように出力します。

```asm:prc_support.S
Sample program starts.
Unknown command.
Unknown command.
Unknown command.
#act_tsk(1)
task1 is running (001).   |
task1 is running (002).   |
task1 is running (003).   |
task1 is running (004).   |
task1 is running (005).   |
task1 is running (006).   |
task1 is running (007).   |
task1 is running (008).   |
task1 is running (009).   |
task1 is running (010).   |
task1 is running (011).   |
#sta_alm(1, 5000)
task1 is running (012).   |
task1 is running (013).   |
task1 is running (014).   |
task1 is running (015).   |
task1 is running (016).   |
task1 is running (017).   |
task1 is running (018).   |
task1 is running (019).   |
sta_cyc(1)
task1 is running (020).   |
task1 is running (021).   |
task1 is running (022).   |
task1 is running (023).   |
task1 is running (024).   |
Cyclic handler is raised.
task1 is running (025).   |
#1#snd_dtq(dtqid=1 , value=1)
Alarm handler is raised.
task1 is running (026).   |
task1 is running (027).   |
task1 is running (028).   |
task1 is running (029).   |
#1#terminate task
task2 is running (001).     +
Cyclic handler is raised.
Unknown command.
task2 is running (002).     +
Unknown command.
task2 is running (003).     +
task2 is running (004).     +
task2 is running (005).     +
task2 is running (006).     +
Cyclic handler is raised.
task2 is running (007).     +
```

# 第八段階　終了
Ctrl-a を押し x を押す．
 
dockerを抜ける場合は exit 

# 算譜(code)

```
/*
 *  TOPPERS/SSP Kernel
 *      Smallest Set Profile Kernel
 *
 *  Copyright (C) 2008 by Embedded and Real-Time Systems Laboratory
 *              Graduate School of Information Science, Nagoya Univ., JAPAN
 *  Copyright (C) 2018 by Naoki Saito
 *             Nagoya Municipal Industrial Research Institute, JAPAN
 *
 *  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
 *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
 *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
 *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
 *      免責すること．
 *
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
 *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
 *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
 *  の責任を負わない．
 *
 */

/*
 *  プロセッサ依存モジュール アセンブリ言語部（ARM64用）
 */

#define TOPPERS_MACRO_ONLY
#define UINT_C(val)	(val)		/* uint_t型の定数を作るマクロ */
#define ULONG_C(val)	(val)		/* ulong_t型の定数を作るマクロ */
#define CAST(type, val)	(val)		/* 型キャストを行うマクロ */

#include "kernel_impl.h"

/*
 *  ディスパッチャの動作開始
 */
    .text
    .align    2
    .globl    start_dispatch
    .type     start_dispatch, function
start_dispatch:
    /*
     *  このルーチンは，カーネル起動時に，すべての割込みを禁止した状態
     * （割込みロック状態と同等）で呼び出される．
     *
     *  ここでは dispatcher を呼び出す前の初期設定を行う．
     *  (1) システム状態の初期化．以下の状態へ移行する．
     *    ・全割込みロック解除状態(カーネル管理外の割込み許可)
     *    ・CPUロック状態(カーネル管理の割込み禁止)
     *    ・割込み優先度マスク全解除状態
     *    ・ディスパッチ許可状態
     *
     *    (1-1) 割込み優先度マスクは gicc_initializeで，GICC_PMR を初期化することにより
     *          すでに（モデル上の）割込み優先度マスク全解除状態になっている．
     *    (1-2) ディスパッチ禁止フラグは task_initialize で disdsp を false に初期化しているため
     *          すでにディスパッチ許可状態になっている．
     *    (1-3) ここではカーネル管理の割込みを禁止する．
     *
     *  (2) スタックポインタの初期化
     *      start_dispatch が呼び出されるとここに戻ってくることはないため
     *      スタックポインタをここで初期化する．
     */
    ldr x0, =_kernel_istkpt // setup stack
    ldr x0, [x0]
    mov sp, x0

    // カーネル管理内の割込み禁止
    msr    daifset, #3

    // dispatcher呼び出し
    b      dispatcher

/*
 *  カーネルの終了処理の呼出し
 *
 *  スタックを非タスクコンテキスト用に切り替え．
 *
 */
    .text
    .align   2
    .globl   call_exit_kernel
    .type    call_exit_kernel, function
call_exit_kernel:
    /*
     *  スタックポインタの初期化
     */
    ldr    x0, =_kernel_istkpt
    ldr    x0, [x0]
    mov    sp, x0

    b      exit_kernel       /* カーネルの終了処理を呼ぶ */


/*
 * 割込み/例外コンテキスト保存処理
 */
.macro __save_context
    /*
     *  x0 - x29 の保存(x0,x1ペアからx28, x29まで)
     */
    stp	   x1, x0, [sp, #-16]!
    stp	   x3, x2, [sp, #-16]!
    stp	   x5, x4, [sp, #-16]!
    stp	   x7, x6, [sp, #-16]!
    stp	   x9, x8, [sp, #-16]!
    stp	   x11, x10, [sp, #-16]!
    stp	   x13, x12, [sp, #-16]!
    stp	   x15, x14, [sp, #-16]!
    stp	   x17, x16, [sp, #-16]!
    stp	   x19, x18, [sp, #-16]!
    stp	   x21, x20, [sp, #-16]!
    stp	   x23, x22, [sp, #-16]!
    stp	   x25, x24, [sp, #-16]!
    stp	   x27, x26, [sp, #-16]!
    stp	   x29, x28, [sp, #-16]!

    /*
     * spsr_el1, x30をペアで保存
     */
    mrs	   x21, spsr_el1
    stp	   x21, x30, [sp, #-16]!

    /*
     * esr_el1, elr_el1 をペアで保存
     */
    mrs	   x21, esr_el1
    mrs	   x22, elr_el1
    stp	   x21, x22, [sp, #-16]!

    /*
     *  SPの調整(16ビットアライメントにする)
     */
    mov    x1, #8
    mov    x2, sp
    and    x1, x2, x1    // 調整量の計算(0 or 8)
    sub    sp, sp, x1    // SPの調整
    stp    xzr, x1, [sp, #-16]!  // 調整量を保存

    /*
     * 追加の格納領域を確保するため，SPを減算しておく
     */
    sub     sp, sp, #16
.endm

/*
 * コンテキスト復帰処理
 */
.macro __restore_context
    /*
     * スタックに保存した一部データの破棄(アライメント調整分を考慮)
     */
    mov    x1, #40
    ldr    x2, [sp, #24]
    add    x1, x1, x2
    add	   sp, sp, x1
    /*
     * ELR/SPSR の復元
     */
    ldp    x21, x22, [sp], #16
    msr    elr_el1, x21
    msr    spsr_el1, x22
    /*
     * x0 - x30 の復元
     */
    ldr    x30, [sp], #8
    ldp    x29, x28, [sp], #16
    ldp    x27, x26, [sp], #16
    ldp    x25, x24, [sp], #16
    ldp    x23, x22, [sp], #16
    ldp    x21, x20, [sp], #16
    ldp    x19, x18, [sp], #16
    ldp    x17, x16, [sp], #16
    ldp    x15, x14, [sp], #16
    ldp    x13, x12, [sp], #16
    ldp    x11, x10, [sp], #16
    ldp    x9, x8, [sp], #16
    ldp    x7, x6, [sp], #16
    ldp    x5, x4, [sp], #16
    ldp    x3, x2, [sp], #16
    ldp    x1, x0, [sp], #16
.endm

/*
 *  割込み/例外の出口処理
 *    前提：CPUロック状態, ネストカウンタデクリメント済み
 */
    .text
    .align 2
    .global ret_int
ret_int:
    // 戻り先のコンテキストを確認し，多段割込みならリターン
    ldr    x1, =_kernel_intnest
    ldrb   w3, [x1]
    cbnz   w3, int_return

ret_int_2:        // 初段の割込みの場合
    // reqflg が false なら呼び出し元へ戻る
    ldr    x0, =reqflg
    ldr    w1, [x0]
    cbz    w1, int_return

ret_int_3:        // reqflg が true の場合
    mov    w1, #0        // reqflg = false
    str    w1, [x0]

    // ディスパッチ禁止なら呼び出し元へ戻る
    ldr    x0, =disdsp
    ldr    w1, [x0]
    cbnz   w1, int_return

    /*
     *  遅延ディスパッチ
     *    search_schedtsk の返値(x0)を引数として run_task を呼び出す
     */
    bl    search_schedtsk
    bl    run_task

    /*
     *  呼び出し元へリターン
     */
int_return:
    __restore_context    // レジスタ復帰
    eret

/*
 *  割込みベクタ
 *    最初に割込み発生前のスタックに戻してからレジスタを保存する
 *    ハードウェアによってPSTATE.{I,F} がセット済であることを前提とする
 */
    .text
    .global vectors
    .align 11
vectors:
    /*
     *  From EL1t
     */

    // Sync EL1
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    mov    x22, #0                  // 例外番号をx22にセット
    b      gic_exc_entry

    // IRQ EL1
    .align 7
    msr    spsel,   #0              // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    b      gic_int_entry

    // FIQ EL1
    .align 7
    msr    spsel, #0                // 例外発生前のスタック(SP_EL0)へ戻す
    __save_context
    b      gic_int_entry

    // SError EL1
    .align 7
    msr    spsel, #0                // 例外発生前のスタック(SP_EL0)へ戻す
    __save_context
    mov    x22, #1                  // 例外番号をx22にセット
    b      gic_exc_entry

    /*
     *  From EL1h
     */

    // Sync EL1
    .align 7
    __save_context
    mov    x22, #2                  // 例外番号をx22にセット
    b      gic_exc_entry

    // IRQ EL1
    .align 7
    __save_context
    b      gic_int_entry

    // FIQ EL1
    .align 7
    __save_context
    b      gic_int_entry

    // Error EL1
    .align 7
    __save_context
    mov    x22, #3                  // 例外番号をx22にセット
    b      gic_exc_entry

    /*
     *  From EL0t
     */

    // Sync EL0
    .align 7
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    mov    x22, #4                  // 例外番号をx22にセット
    b      gic_exc_entry

   // IRQ EL0
    .align 7
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    b      gic_int_entry

    // FIQ EL0
    .align 7
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    b      gic_int_entry

    // Error EL0
    .align 7
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    mov    x22, #5                  // 例外番号をx22にセット
    b      gic_exc_entry

    /*
     *  From EL0 using AArch32
     */

    // AArch32 sync
    .align 7
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    mov    x22, #6                  // 例外番号をx22にセット
    b      gic_exc_entry

    // AArch32 IRQ
    .align 7
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    b      gic_int_entry

    // AArch32 FIQ
    .align 7
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    b      gic_int_entry

    // AArch32 Error
    .align 7
    msr    spsel,  #0               // 例外発生前のスタック(SP_EL0)に戻す
    __save_context
    mov    x22, #7                  // 例外番号をx22にセット
    b      gic_exc_entry
```

```asm:start.S
/*
 *  TOPPERS Software
 *      Toyohashi Open Platform for Embedded Real-Time Systems
 *
 *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
 *                              Toyohashi Univ. of Technology, JAPAN
 *  Copyright (C) 2006-2016 by Embedded and Real-Time Systems Laboratory
 *              Graduate School of Information Science, Nagoya Univ., JAPAN
 *  Copyright (C) 2018 by Naoki Saito
 *             Nagoya Municipal Industrial Research Institute, JAPAN
 *
 *  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
 *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
 *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
 *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
 *      免責すること．
 *
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
 *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
 *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
 *  の責任を負わない．
 *
 *  $Id$
 */

#define TOPPERS_MACRO_ONLY
#include "kernel_impl.h"

    .text
    .align 4
    .global start
    .global vectors
start:
    msr daifset, #3         //割込み禁止(割込みロック相当)

    /*
     *  例外ベクタテーブルのベースアドレス設定
     */
    ldr x0, =vectors
    msr vbar_el1, x0

    /*
     *  スタックポインタとフレームポインタの初期化
     */
    ldr x0, =_kernel_istkpt	// setup stack
    ldr x0, [x0]
    mov sp, x0
    bl sta_ker
    b .
```

# 関連資料(related document)

OSのタスク切り替え処理とAArch64(ARM64)の関数呼び出し規約
https://qiita.com/tkato/items/82f095a8f8c55be07cb5

「名古屋のIoTは名古屋のOSで」TOPPERS/SSPカーネルソース四段活用。落とし方、読み方、コンパイルの仕方、アプリの作り方　７つの壁
https://qiita.com/kaizen_nagoya/items/cdce810943ba063efc47

「名古屋のIoTは名古屋のOSで」TOPPERS/SSPカーネルソース勉強会(0) docker, build_ssp.sh, build_ssp_ruby.sh
https://qiita.com/kaizen_nagoya/items/20e382d58c6dd0e40534

「名古屋のIoTは名古屋のOSで」Raspberry PIのSDカードをRaspbian, TOPPERS/FMP, TOPPERS/SSP起動用に利用する
https://qiita.com/kaizen_nagoya/items/814cccdaa59dc09196e3

「名古屋のIoTは名古屋のOSで」Dockerをどっかーらどうやって使えばいいんでしょう。TOPPERS/FMP on RaspberryPi with Macintosh編 ５つの関門
https://qiita.com/kaizen_nagoya/items/9c46c6da8ceb64d2d7af

### 文書履歴(document history)
ver. 0.10 初稿 20180730
ver. 0.11 アセンブラソース追記 20180731
ver. 0.12 表題、タグ変更 20180802
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.