/* 外部モジュールヘッダ */
#include <IntMng.h>
#include <MemMng.h>
+#include <ProcMng.h>
#include <TimerMng.h>
/* 内部モジュールヘッダ */
MemMngInit( &map, 1 );
/* プロセス管理モジュール初期化 */
- /* [TODO] */
+ ProcMngInit();
/* 割込み管理モジュール初期化 */
IntMngInit();
#******************************************************************************#
#* src/kernel/Makefile *#
-#* 2017/02/17 *#
+#* 2017/03/01 *#
#* Copyright (C) 2016-2017 Mochi. *#
#******************************************************************************#
#******************************************************************************#
IntMng/IntMngHdl.c \
IntMng/IntMngPic.c \
TimerMng/TimerMngInit.c \
- TimerMng/TimerMngPit.c
+ TimerMng/TimerMngPit.c \
+ ProcMng/ProcMngInit.c \
+ ProcMng/ProcMngTss.c \
+ ProcMng/ProcMngTask.c \
+ ProcMng/ProcMngSched.c
# Cフラグ
CFLAGS = -O \
--- /dev/null
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngInit.c */
+/* 2017/03/01 */
+/* Copyright (C) 2017 Mochi. */
+/******************************************************************************/
+/******************************************************************************/
+/* インクルード */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <stdint.h>
+
+/* 外部モジュールヘッダ */
+
+/* 内部モジュールヘッダ */
+#include "ProcMngSched.h"
+#include "ProcMngTask.h"
+#include "ProcMngTss.h"
+
+
+/******************************************************************************/
+/* グローバル関数定義 */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief プロセス管理初期化
+ * @details プロセス管理内サブモジュールの初期化を行う。
+ */
+/******************************************************************************/
+void ProcMngInit( void )
+{
+ /* TSS管理サブモジュール初期化 */
+ ProcMngTssInit();
+
+ /* タスク管理サブモジュール初期化 */
+ ProcMngTaskInit();
+
+ /* スケジューラサブモジュール初期化 */
+ ProcMngSchedInit();
+
+ return;
+}
+
+
+/******************************************************************************/
--- /dev/null
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngSched.c */
+/* 2017/03/02 */
+/* Copyright (C) 2017 Mochi. */
+/******************************************************************************/
+/******************************************************************************/
+/* インクルード */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <MLib/MLib.h>
+#include <MLib/Basic/MLibBasicList.h>
+#include <hardware/IA32/IA32Instruction.h>
+
+/* 外部モジュールヘッダ */
+#include <Cmn.h>
+
+/* 内部モジュールヘッダ */
+#include "ProcMngTask.h"
+#include "ProcMngTss.h"
+
+
+/******************************************************************************/
+/* 定義 */
+/******************************************************************************/
+/** 実行可能タスクグループ数 */
+#define SCHED_RUNGRP_NUM ( 2 )
+
+/** アイドルタスク情報インデックス */
+#define SCHED_IDLE_IDX ( 0 )
+
+/* タスク情報使用フラグ */
+#define SCHED_TASK_INFO_UNUSED ( 0 ) /**< 未使用 */
+#define SCHED_TASK_INFO_USED ( 1 ) /**< 使用中 */
+
+/* スケジューラ実行中レベル */
+#define SCHED_LEVEL_DRIVER ( 0 ) /**< ドライバレベル */
+#define SCHED_LEVEL_SERVER ( 1 ) /**< サーバレベル */
+#define SCHED_LEVEL_USER ( 2 ) /**< ユーザレベル */
+
+/** タスク情報構造体 */
+typedef struct {
+ MLibBasicListNode_t node; /**< 連結リスト情報 */
+ uint8_t used; /**< 使用フラグ */
+ uint8_t reserved[ 3 ]; /**< 予約 */
+ uint32_t taskId; /**< タスクID */
+} schedTaskInfo_t;
+
+/** 実行可能タスクグループ構造体 */
+typedef struct {
+ MLibBasicList_t driverQ; /**< ドライバタスクキュー */
+ MLibBasicList_t serverQ; /**< サーバタスクキュー */
+ MLibBasicList_t userQ; /**< ユーザタスクキュー */
+} schedRunGrp_t;
+
+/** 待ちタスクグループ構造体 */
+typedef struct {
+ MLibBasicList_t waitQ; /**< 待ちキュー */
+} schedWaitGrp_t;
+
+/** スケジューラテーブル構造体 */
+typedef struct {
+ schedTaskInfo_t *pRunningTaskInfo; /**< 実行中タスク情報 */
+ uint32_t runFlg; /**< タスク実行済みフラグ */
+ uint32_t runningGrpIdx; /**< 実行中タスクグループIDX */
+ uint32_t reservedGrpIdx; /**< 予約タスクグループIDX */
+ schedRunGrp_t runGrp[ SCHED_RUNGRP_NUM ]; /**< 実行可能タスクグループ */
+ schedWaitGrp_t waitGrp; /**< 待ちタスクグループ */
+ MLibBasicList_t freeQ; /**< 空タスクキュー */
+ schedTaskInfo_t taskInfo[ PROCMNG_TASK_ID_NUM ];/**< タスク情報 */
+} schedTbl_t;
+
+
+/******************************************************************************/
+/* ローカル関数プロトタイプ宣言 */
+/******************************************************************************/
+/* 実行予約タスクグループエンキュー */
+static void SchedEnqueueToReservedGrp( schedTaskInfo_t *pTaskInfo );
+
+/* 実行可能タスクグループ役割切替 */
+static void SchedSwitchRunGrpRole( void );
+
+/* タスクスイッチ */
+static void SchedSwitchTask( uint32_t nowTaskId,
+ uint32_t nextTaskId );
+
+/* タスクスイッチ終了ポイント(ラベル) */
+void SchedSwitchTaskEnd( void );
+
+
+/******************************************************************************/
+/* 変数定義 */
+/******************************************************************************/
+/** スケジューラテーブル */
+static schedTbl_t gSchedTbl;
+
+
+/******************************************************************************/
+/* グローバル関数定義 */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief スケジュール追加
+ * @details 指定したタスクIDをスケジュールに追加する。
+ *
+ * @param[in] taskId タスクID
+ * - PROCMNG_TASK_ID_MIN タスクID最小値
+ * - PROCMNG_TASK_ID_MAX タスクID最大値
+ *
+ * @retval CMN_SUCCESS 成功
+ * @retval CMN_FAILURE 失敗
+ */
+/******************************************************************************/
+int32_t ProcMngSchedAdd( uint32_t taskId )
+{
+ schedTaskInfo_t *pTaskInfo; /* タスク情報 */
+
+ /* 空タスクキューから空タスク情報取得 */
+ pTaskInfo =
+ ( schedTaskInfo_t * ) MLibBasicListRemoveTail( &( gSchedTbl.freeQ ) );
+
+ /* 取得結果判定 */
+ if ( pTaskInfo == NULL ) {
+ /* 空タスク情報無し */
+
+ return CMN_FAILURE;
+ }
+
+ /* タスク情報設定 */
+ pTaskInfo->used = SCHED_TASK_INFO_USED; /* 使用フラグ */
+ pTaskInfo->taskId = taskId; /* タスクID */
+
+ /* 実行予約タスクグループにエンキュー */
+ SchedEnqueueToReservedGrp( pTaskInfo );
+
+ return CMN_SUCCESS;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief スケジューラ実行
+ * @details スケジューラを実行して次に実行可能なタスクにタスクスイッチする。
+ */
+/******************************************************************************/
+void ProcMngSchedExec( void )
+{
+ uint32_t level; /* 実行中レベル */
+ uint32_t nowTaskId; /* 実行中タスクID */
+ schedRunGrp_t *pRunningGrp; /* 実行中タスクグループ */
+ schedTaskInfo_t *pTaskInfo; /* タスク情報 */
+
+ /* 初期化 */
+ level = SCHED_LEVEL_DRIVER;
+ nowTaskId = gSchedTbl.pRunningTaskInfo->taskId;
+ pRunningGrp = NULL;
+ pTaskInfo = NULL;
+
+ /* 実行中タスク判定 */
+ if ( nowTaskId == PROCMNG_TASK_ID_IDLE ) {
+ /* アイドルタスク */
+
+ /* 実行可能タスクグループ役割切替 */
+ SchedSwitchRunGrpRole();
+
+ } else {
+ /* アイドルタスク以外 */
+
+ /* 実行予約タスクグループにキューイング */
+ SchedEnqueueToReservedGrp( gSchedTbl.pRunningTaskInfo );
+ }
+
+ /* 実行中タスクグループ設定 */
+ pRunningGrp = &gSchedTbl.runGrp[ gSchedTbl.runningGrpIdx ];
+
+ do {
+ /* 実行中レベル判定 */
+ if ( level == SCHED_LEVEL_DRIVER ) {
+ /* ドライバレベル */
+
+ /* ドライバキューからデキュー */
+ pTaskInfo = ( schedTaskInfo_t * )
+ MLibBasicListRemoveTail( &( pRunningGrp->driverQ ) );
+
+ } else if ( level == SCHED_LEVEL_SERVER ) {
+ /* サーバレベル */
+
+ /* サーバキューからデキュー */
+ pTaskInfo = ( schedTaskInfo_t * )
+ MLibBasicListRemoveTail( &( pRunningGrp->serverQ ) );
+
+ } else if ( level == SCHED_LEVEL_USER ) {
+ /* ユーザレベル */
+
+ /* ユーザキューからデキュー */
+ pTaskInfo = ( schedTaskInfo_t * )
+ MLibBasicListRemoveTail( &( pRunningGrp->userQ ) );
+
+ } else {
+ /* 他 */
+
+ /* タスク実行済フラグ判定 */
+ if ( gSchedTbl.runFlg == false ) {
+ /* 実行済みタスク無 */
+
+ /* アイドルタスク設定 */
+ pTaskInfo = &gSchedTbl.taskInfo[ SCHED_IDLE_IDX ];
+ break;
+
+ } else {
+ /* 実行済みタスク有 */
+
+ /* 実行可能タスクグループ役割切替 */
+ SchedSwitchRunGrpRole();
+
+ /* 再スケジューリング */
+ ProcMngSchedExec();
+
+ return;
+ }
+ }
+
+ /* 実行中レベル加算 */
+ level++;
+
+ /* デキュー結果判定 */
+ } while ( pTaskInfo == NULL );
+
+ /* 実行中タスク情報切り替え */
+ gSchedTbl.pRunningTaskInfo = pTaskInfo;
+
+ /* タスクスイッチ */
+ SchedSwitchTask( nowTaskId, pTaskInfo->taskId );
+
+ return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief タスクID取得
+ * @details 現在実行中タスクのタスクIDを取得する。
+ *
+ * @retval PROCMNG_TASK_ID_MIN タスクID最小値
+ * @retval PROCMNG_TASK_ID_MAX タスクID最大値
+ */
+/******************************************************************************/
+uint32_t ProcMngSchedGetTaskId( void )
+{
+ /* タスクID返却 */
+ return gSchedTbl.pRunningTaskInfo->taskId;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief スケジューラ初期化
+ * @details スケジューラサブモジュールの初期化を行う。
+ */
+/******************************************************************************/
+void ProcMngSchedInit( void )
+{
+ uint32_t i; /* カウンタ */
+ MLibRet_t retMLib; /* MLib関数戻り値 */
+ schedTaskInfo_t *pIdleTaskInfo; /* アイドルタスク情報 */
+
+ /* スケジューラテーブル0初期化 */
+ memset( &gSchedTbl, 0, sizeof ( schedTbl_t ) );
+
+ /* 実行可能タスクグループIDX設定 */
+ gSchedTbl.runningGrpIdx = 0;
+ gSchedTbl.reservedGrpIdx = 1;
+
+ /* タスク実行済フラグ初期化 */
+ gSchedTbl.runFlg = false;
+
+ /* アイドルタスク情報初期化 */
+ pIdleTaskInfo = &gSchedTbl.taskInfo[ SCHED_IDLE_IDX ];
+ gSchedTbl.pRunningTaskInfo = pIdleTaskInfo;
+ pIdleTaskInfo->used = SCHED_TASK_INFO_USED;
+ pIdleTaskInfo->taskId = PROCMNG_TASK_ID_IDLE;
+
+ /* 空タスクキュー初期化 */
+ for ( i = 1; i < PROCMNG_TASK_ID_NUM; i++ ) {
+ /* エンキュー */
+ retMLib = MLibBasicListInsertHead( &( gSchedTbl.freeQ ),
+ &( gSchedTbl.taskInfo[ i ].node ) );
+
+ /* エンキュー結果判定 */
+ if ( retMLib != MLIB_SUCCESS ) {
+ /* 失敗 */
+
+ /* [TODO] トレース出力 */
+ }
+ }
+
+ return;
+}
+
+
+/******************************************************************************/
+/* ローカル関数定義 */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief 実行予約タスクグループエンキュー
+ * @details 実行予約タスクグループにタスク情報をキューイングする。
+ *
+ * @param[in] *pTaskInfo タスク情報
+ */
+/******************************************************************************/
+static void SchedEnqueueToReservedGrp( schedTaskInfo_t *pTaskInfo )
+{
+ uint8_t taskType; /* タスクタイプ */
+ MLibRet_t retMLib; /* MLib関数戻り値 */
+ schedRunGrp_t *pReservedGrp; /* 実行予約タスクグループ */
+ MLibBasicList_t *pTaskQ; /* タスクキュー */
+
+ /* 初期化 */
+ taskType = PROCMNG_TASK_TYPE_USER;
+ pTaskQ = NULL;
+ pReservedGrp = &gSchedTbl.runGrp[ gSchedTbl.reservedGrpIdx ];
+ retMLib = MLIB_FAILURE;
+
+ /* タスクタイプ取得 */
+ taskType = ProcMngTaskGetType( pTaskInfo->taskId );
+
+ /* タスクタイプ判定 */
+ if ( taskType == PROCMNG_TASK_TYPE_DRIVER ) {
+ /* ドライバ */
+
+ /* タスクキュー設定 */
+ pTaskQ = &pReservedGrp->driverQ;
+
+ } else if ( taskType == PROCMNG_TASK_TYPE_SERVER ) {
+ /* サーバ */
+
+ /* タスクキュー設定 */
+ pTaskQ = &pReservedGrp->serverQ;
+
+ } else {
+ /* ユーザ */
+
+ /* タスクキュー設定 */
+ pTaskQ = &pReservedGrp->userQ;
+ }
+
+ /* エンキュー */
+ retMLib = MLibBasicListInsertHead( pTaskQ,
+ &( pTaskInfo->node ) );
+
+ /* エンキュー結果判定 */
+ if ( retMLib != MLIB_SUCCESS ) {
+ /* 失敗 */
+
+ /* [TODO] トレース出力 */
+ }
+
+ return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief 実行可能タスクグループ役割切替
+ * @details 実行可能タスクグループの役割を切り替える。
+ */
+/******************************************************************************/
+static void SchedSwitchRunGrpRole( void )
+{
+ /* グループ役割切替 */
+ gSchedTbl.runningGrpIdx ^= 1;
+ gSchedTbl.reservedGrpIdx ^= 1;
+
+ /* タスク実行済みフラグ初期化 */
+ gSchedTbl.runFlg = false;
+
+ return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief タスクスイッチ
+ * @details 現在実行中タスクのコンテキストを保存し、指定されたタスクIDのコ
+ * ンテキストを復元してタスクスイッチする。
+ *
+ * @param[in] nowTaskId 現在実行中のタスクID
+ * @param[in] nextTaskId タスクスイッチ先タスクID
+ */
+/******************************************************************************/
+static void SchedSwitchTask( uint32_t nowTaskId,
+ uint32_t nextTaskId )
+{
+ void *pKernelStack; /* カーネルスタック */
+ ProcMngTaskContext_t context; /* コンテキスト */
+
+ /* 初期化 */
+ memset( &context, 0, sizeof ( ProcMngTaskContext_t ) );
+
+ /* コンテキスト退避 */
+ context.eip = ( uint32_t ) SchedSwitchTaskEnd;
+ context.esp = IA32InstructionGetEsp();
+ ProcMngTaskSetContext( nowTaskId, &context );
+
+ /* コンテキスト復旧 */
+ context = ProcMngTaskGetContext( nextTaskId );
+
+ /* カーネルスタック設定 */
+ pKernelStack = ProcMngTaskGetKernelStack( nextTaskId );
+ ProcMngTssSetEsp0( ( uint32_t ) pKernelStack );
+
+ /* タスクスイッチ */
+ IA32InstructionSwitchTask( ( void * ) context.eip,
+ ( void * ) context.esp );
+
+ /* ラベル */
+ __asm__ __volatile__ ( "SchedSwitchTaskEnd:" );
+
+ return;
+}
+
+
+/******************************************************************************/
--- /dev/null
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngSched.h */
+/* 2017/03/01 */
+/* Copyright (C) 2017 Mochi. */
+/******************************************************************************/
+#ifndef PROCMNG_SCHED_H
+#define PROCMNG_SCHED_H
+/******************************************************************************/
+/* インクルード */
+/******************************************************************************/
+#include <Cmn.h>
+
+/******************************************************************************/
+/* グローバル関数プロトタイプ宣言 */
+/******************************************************************************/
+/* スケジュール追加 */
+extern int32_t ProcMngSchedAdd( uint32_t taskId );
+
+/* タスクID取得 */
+extern uint32_t ProcMngSchedGetTaskId( void );
+
+/* スケジューラ初期化 */
+extern void ProcMngSchedInit( void );
+
+
+/******************************************************************************/
+#endif
--- /dev/null
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngTask.c */
+/* 2017/03/02 */
+/* Copyright (C) 2017 Mochi. */
+/******************************************************************************/
+/******************************************************************************/
+/* インクルード */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <stdint.h>
+#include <string.h>
+#include <hardware/IA32/IA32Instruction.h>
+
+/* 外部モジュールヘッダ */
+#include <MemMng.h>
+#include <ProcMng.h>
+
+/* 内部モジュールヘッダ */
+#include "ProcMngSched.h"
+#include "ProcMngTask.h"
+#include "ProcMngTss.h"
+
+
+/******************************************************************************/
+/* 定義 */
+/******************************************************************************/
+/* タスクID使用フラグ */
+#define TASK_ID_UNUSED ( 0 ) /** 未使用 */
+#define TASK_ID_USED ( 1 ) /** 使用済 */
+
+/* スタックサイズ */
+#define TASK_KERNEL_STACK_SIZE ( 8192 ) /**< カーネルスタックサイズ */
+#define TASK_STACK_SIZE ( 8192 ) /**< スタックサイズ */
+
+/** タスクスタック情報 */
+typedef struct {
+ void *pTopAddr; /**< 先頭アドレス */
+ void *pBottomAddr; /**< 後尾アドレス */
+ size_t size; /**< サイズ */
+} taskStackInfo_t;
+
+/** タスク管理テーブル構造体 */
+typedef struct {
+ uint8_t used; /**< 使用フラグ */
+ uint8_t type; /**< タスクタイプ */
+ uint8_t state; /**< タスク状態 */
+ uint8_t reserved; /**< パディング */
+ ProcMngTaskContext_t context; /**< コンテキスト */
+ void *pEntryPoint; /**< エントリポイント */
+ taskStackInfo_t kernelStackInfo; /**< カーネルスタックアドレス */
+ taskStackInfo_t stackInfo; /**< スタックアドレス */
+} taskTbl_t;
+
+
+/******************************************************************************/
+/* 変数定義 */
+/******************************************************************************/
+/** タスク管理テーブル */
+static taskTbl_t gTaskTbl[ PROCMNG_TASK_ID_NUM ];
+
+
+/******************************************************************************/
+/* グローバル関数定義 */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief タスク追加
+ * @details タスク追加を行う。
+ *
+ * @param[in] taskType タスクタイプ
+ * - PROCMNG_TASK_TYPE_KERNEL カーネル
+ * - PROCMNG_TASK_TYPE_DRIVER ドライバ
+ * - PROCMNG_TASK_TYPE_SERVER サーバ
+ * - PROCMNG_TASK_TYPE_USER ユーザ
+ * @param[in] *pEntryPoint エントリポイント
+ *
+ * @retval PROCMNG_TASK_ID_NULL 失敗
+ * @retval PROCMNG_TASK_ID_MIN タスクID最小値
+ * @retval PROCMNG_TASK_ID_MAX タスクID最大値
+ */
+/******************************************************************************/
+uint32_t ProcMngTaskAdd( uint8_t taskType,
+ void *pEntryPoint )
+{
+ void *pKernelStack; /* カーネルスタック */
+ void *pStack; /* スタック */
+ int32_t ret; /* 関数戻り値 */
+ uint32_t taskId; /* タスクID */
+ taskStackInfo_t *pStackInfo; /* スタック情報 */
+
+ /* 初期化 */
+ pKernelStack = NULL;
+ pStack = NULL;
+ ret = CMN_FAILURE;
+ taskId = PROCMNG_TASK_ID_MIN;
+ pStackInfo = NULL;
+
+ /* 空タスク検索 */
+ for ( ; taskId < PROCMNG_TASK_ID_MAX; taskId++ ) {
+ /* 使用フラグ判定 */
+ if ( gTaskTbl[ taskId ].used == TASK_ID_UNUSED ) {
+ /* 未使用 */
+
+ /* カーネルスタック領域割り当て */
+ pKernelStack = MemMngAreaAlloc( TASK_KERNEL_STACK_SIZE );
+
+ /* スタック領域割り当て */
+ pStack = MemMngAreaAlloc( TASK_STACK_SIZE );
+
+ /* 割り当て結果判定 */
+ if ( ( pKernelStack == NULL ) ||
+ ( pStack == NULL ) ) {
+ /* 失敗 */
+
+ /* [TODO] */
+ /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
+
+ return PROCMNG_TASK_ID_NULL;
+ }
+
+ /* タスク基本設定 */
+ gTaskTbl[ taskId ].used = TASK_ID_USED;
+ gTaskTbl[ taskId ].type = taskType;
+ gTaskTbl[ taskId ].state = 0;
+ gTaskTbl[ taskId ].context.eip = ( uint32_t ) ProcMngTaskStart;
+ gTaskTbl[ taskId ].context.esp = ( uint32_t ) pKernelStack;
+ gTaskTbl[ taskId ].pEntryPoint = pEntryPoint;
+
+ /* カーネルスタック情報設定 */
+ pStackInfo = &( gTaskTbl[ taskId ].kernelStackInfo );
+ pStackInfo->pTopAddr = pKernelStack;
+ pStackInfo->pBottomAddr = pKernelStack + TASK_KERNEL_STACK_SIZE;
+ pStackInfo->size = TASK_KERNEL_STACK_SIZE;
+
+ /* スタック情報設定 */
+ pStackInfo = &( gTaskTbl[ taskId ].stackInfo );
+ pStackInfo->pTopAddr = pStack;
+ pStackInfo->pBottomAddr = pStack + TASK_STACK_SIZE;
+ pStackInfo->size = TASK_STACK_SIZE;
+
+ /* スケジューラ追加 */
+ ret = ProcMngSchedAdd( taskId );
+
+ /* 追加結果判定 */
+ if ( ret == CMN_FAILURE ) {
+ /* 失敗 */
+
+ /* [TODO] */
+ /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
+
+ return PROCMNG_TASK_ID_NULL;
+ }
+
+ return taskId;
+ }
+ }
+
+ return PROCMNG_TASK_ID_NULL;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief コンテキスト取得
+ * @details 指定したタスクIDのコンテキストを取得する。
+ *
+ * @param[in] taskId タスクID
+ * - PROCMNG_TASK_ID_MIN タスクID最小値
+ * - PROCMNG_TASK_ID_MAX タスクID最大値
+ *
+ * @return コンテキスト
+ */
+/******************************************************************************/
+ProcMngTaskContext_t ProcMngTaskGetContext( uint32_t taskId )
+{
+ /* コンテキスト返却 */
+ return gTaskTbl[ taskId ].context;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief カーネルスタックアドレス取得
+ * @details 指定したタスクIDのカーネルスタックアドレスを取得する。
+ *
+ * @param[in] taskId タスクID
+ * - PROCMNG_TASK_ID_MIN タスクID最小値
+ * - PROCMNG_TASK_ID_MAX タスクID最大値
+ *
+ * @return カーネルスタックアドレス
+ */
+/******************************************************************************/
+void *ProcMngTaskGetKernelStack( uint32_t taskId )
+{
+ /* カーネルスタックアドレス返却 */
+ return gTaskTbl[ taskId ].kernelStackInfo.pBottomAddr;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief タスクタイプ取得
+ * @details 指定したタスクIDのタスクタイプを取得する。
+ *
+ * @param[in] taskId タスクID
+ * - PROCMNG_TASK_ID_MIN タスクID最小値
+ * - PROCMNG_TASK_ID_MAX タスクID最大値
+ *
+ * @retval PROCMNG_TASK_TYPE_DRIVER ドライバ
+ * @retval PROCMNG_TASK_TYPE_SERVER サーバ
+ * @retval PROCMNG_TASK_TYPE_USER ユーザ
+ */
+/******************************************************************************/
+uint8_t ProcMngTaskGetType( uint32_t taskId )
+{
+ /* タスクタイプ返却 */
+ return gTaskTbl[ taskId ].type;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief タスク管理初期化
+ * @details タスク管理サブモジュールの初期化を行う。
+ */
+/******************************************************************************/
+void ProcMngTaskInit( void )
+{
+ /* タスク管理テーブル初期化 */
+ memset( gTaskTbl, 0, sizeof ( gTaskTbl ) );
+
+ /* アイドルタスク設定 */
+ gTaskTbl[ PROCMNG_TASK_ID_IDLE ].used = TASK_ID_USED; /* 使用フラグ */
+
+ return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief コンテキスト設定
+ * @details 指定したタスクIDのコンテキストを設定する。
+ *
+ * @param[in] taskId 設定先タスクID
+ * - PROCMNG_TASK_ID_MIN タスクID最小値
+ * - PROCMNG_TASK_ID_MAX タスクID最大値
+ * @param[in] *pContext コンテキスト
+ */
+/******************************************************************************/
+void ProcMngTaskSetContext( uint32_t taskId,
+ ProcMngTaskContext_t *pContext )
+{
+ /* コンテキスト設定 */
+ gTaskTbl[ taskId ].context = *pContext;
+
+ return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief タスク起動開始
+ * @details タスクの起動を開始する。
+ */
+/******************************************************************************/
+void ProcMngTaskStart( void )
+{
+ void *pEntryPoint; /* エントリポイント */
+ void *pStack; /* スタックアドレス */
+ uint8_t taskType; /* タスクタイプ */
+ uint32_t taskId; /* タスクID */
+ uint32_t codeSegSel; /* コードセグメントセレクタ */
+ uint32_t dataSegSel; /* データセグメントセレクタ */
+ taskTbl_t *pTask; /* タスク管理情報 */
+
+ /* 初期化 */
+ taskId = ProcMngSchedGetTaskId(); /* タスクID */
+ pTask = &( gTaskTbl[ taskId ] ); /* タスク管理情報 */
+ pEntryPoint = pTask->pEntryPoint; /* エントリポイント */
+ pStack = pTask->stackInfo.pBottomAddr; /* スタックアドレス */
+ taskType = pTask->type; /* タスクタイプ */
+
+ /* タスクタイプ判定 */
+ if ( taskType == PROCMNG_TASK_TYPE_DRIVER ) {
+ /* ドライバ */
+
+ /* セグメントセレクタ設定 */
+ codeSegSel = MEMMNG_SEGSEL_DRIVER_CODE; /* コード */
+ dataSegSel = MEMMNG_SEGSEL_DRIVER_DATA; /* データ */
+
+ } else if ( taskType == PROCMNG_TASK_TYPE_SERVER ) {
+ /* サーバ */
+
+ codeSegSel = MEMMNG_SEGSEL_SERVER_CODE; /* コード */
+ dataSegSel = MEMMNG_SEGSEL_SERVER_DATA; /* データ */
+
+ } else {
+ /* ユーザ */
+
+ codeSegSel = MEMMNG_SEGSEL_USER_CODE; /* コード */
+ dataSegSel = MEMMNG_SEGSEL_USER_DATA; /* データ */
+ }
+
+ /* iretd命令用スタック設定 */
+ IA32InstructionPush( dataSegSel ); /* ss */
+ IA32InstructionPush( ( uint32_t ) pStack ); /* esp */
+ IA32InstructionPush( 0x00003202 ); /* eflags */
+ IA32InstructionPush( codeSegSel ); /* cs */
+ IA32InstructionPush( ( uint32_t ) pEntryPoint );/* eip */
+
+ /* セグメントレジスタ設定用スタック設定 */
+ IA32InstructionPush( dataSegSel ); /* gs */
+ IA32InstructionPush( dataSegSel ); /* fs */
+ IA32InstructionPush( dataSegSel ); /* es */
+ IA32InstructionPush( dataSegSel ); /* ds */
+
+ /* 汎用レジスタ設定用スタック設定 */
+ IA32InstructionPush( 0 ); /* eax */
+ IA32InstructionPush( 0 ); /* ecx */
+ IA32InstructionPush( 0 ); /* edx */
+ IA32InstructionPush( 0 ); /* ebx */
+ IA32InstructionPush( 0 ); /* esp( 未使用 ) */
+ IA32InstructionPush( 0 ); /* ebp */
+ IA32InstructionPush( 0 ); /* esi */
+ IA32InstructionPush( 0 ); /* edi */
+
+ /* 汎用レジスタ設定 */
+ IA32InstructionPopad();
+
+ /* セグメントレジスタ設定 */
+ IA32InstructionPopDs();
+ IA32InstructionPopEs();
+ IA32InstructionPopFs();
+ IA32InstructionPopGs();
+
+ /* タスクエントリポイントへ移行 */
+ IA32InstructionIretd();
+
+ /* not return */
+}
+
+
+/******************************************************************************/
--- /dev/null
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngTask.h */
+/* 2017/03/01 */
+/* Copyright (C) 2017 Mochi. */
+/******************************************************************************/
+#ifndef PROCMNG_TASK_H
+#define PROCMNG_TASK_H
+/******************************************************************************/
+/* インクルード */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <stdint.h>
+
+/* 外部モジュールヘッダ */
+#include <ProcMng.h>
+
+
+/******************************************************************************/
+/* 定義 */
+/******************************************************************************/
+/** コンテキスト構造体 */
+typedef struct {
+ uint32_t eip; /**< eipレジスタ */
+ uint32_t esp; /**< espレジスタ */
+} ProcMngTaskContext_t;
+
+
+/******************************************************************************/
+/* グローバル関数プロトタイプ宣言 */
+/******************************************************************************/
+/* コンテキスト取得 */
+extern ProcMngTaskContext_t ProcMngTaskGetContext( uint32_t taskId );
+
+/* カーネルスタックアドレス取得 */
+extern void *ProcMngTaskGetKernelStack( uint32_t taskId );
+
+/* タスクタイプ取得 */
+extern uint8_t ProcMngTaskGetType( uint32_t taskId );
+
+/* タスク管理初期化 */
+extern void ProcMngTaskInit( void );
+
+/* コンテキスト設定 */
+extern void ProcMngTaskSetContext( uint32_t taskId,
+ ProcMngTaskContext_t *pContext );
+
+/* タスク起動開始 */
+extern void ProcMngTaskStart( void );
+
+
+/******************************************************************************/
+#endif
--- /dev/null
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngTss.c */
+/* 2017/03/01 */
+/* Copyright (C) 2017 Mochi. */
+/******************************************************************************/
+/******************************************************************************/
+/* インクルード */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <string.h>
+#include <hardware/IA32/IA32.h>
+#include <hardware/IA32/IA32Descriptor.h>
+#include <hardware/IA32/IA32Instruction.h>
+#include <hardware/IA32/IA32Tss.h>
+
+/* 外部モジュールヘッダ */
+#include <MemMng.h>
+
+/* 内部モジュールヘッダ */
+
+
+/******************************************************************************/
+/* 変数定義 */
+/******************************************************************************/
+/** TSS */
+static IA32Tss_t gTss;
+
+
+/******************************************************************************/
+/* グローバル関数定義 */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief TSS管理初期化
+ * @details TSS管理サブモジュールの初期化を行う。
+ */
+/******************************************************************************/
+void ProcMngTssInit( void )
+{
+ uint16_t index; /* GDTエントリ番号 */
+ uint16_t selector; /* セグメントセレクタ */
+
+ /* TSS初期化 */
+ memset( &gTss, 0, sizeof ( IA32Tss_t ) );
+
+ /* TSSディスクリプタ設定 */
+ index = MemMngGdtAdd(
+ &gTss, /* セグメントベース */
+ sizeof ( IA32Tss_t ) - 1, /* セグメントサイズ */
+ IA32_DESCRIPTOR_G_BYTE, /* リミット粒度 */
+ IA32_DESCRIPTOR_S_SYSTEM, /* システムフラグ */
+ IA32_DESCRIPTOR_TYPE_TSS32, /* セグメントタイプ */
+ IA32_DESCRIPTOR_DPL_0, /* セグメント特権レベル */
+ IA32_DESCRIPTOR_DB_UNUSED ); /* オペレーションサイズ */
+
+ /* セグメントセレクタ設定 */
+ selector = IA32_SEGMENT_SELECTOR( index, /* インデックス */
+ IA32_TI_GDT, /* TI */
+ IA32_RPL_0 ); /* RPL */
+
+ /* TR設定 */
+ IA32InstructionLtr( selector );
+
+ return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief ESP0設定
+ * @details TSSのESP0フィールドを設定する。
+ *
+ * @param[in] esp0 ESP0設定値
+ */
+/******************************************************************************/
+void ProcMngTssSetEsp0( uint32_t esp0 )
+{
+ /* esp0設定 */
+ gTss.esp0 = esp0;
+
+ return;
+}
+
+
+/******************************************************************************/
--- /dev/null
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngTss.h */
+/* 2017/03/01 */
+/* Copyright (C) 2017 Mochi. */
+/******************************************************************************/
+#ifndef PROCMNG_TSS_H
+#define PROCMNG_TSS_H
+/******************************************************************************/
+/* グローバル関数プロトタイプ宣言 */
+/******************************************************************************/
+/* TSS管理初期化 */
+extern void ProcMngTssInit( void );
+
+/* ESP0設定 */
+extern void ProcMngTssSetEsp0( uint32_t esp0 );
+
+
+/******************************************************************************/
+#endif
--- /dev/null
+/******************************************************************************/
+/* src/kernel/include/ProcMng.h */
+/* 2017/03/01 */
+/* Copyright (C) 2017 Mochi. */
+/******************************************************************************/
+#ifndef PROCMNG_H
+#define PROCMNG_H
+/******************************************************************************/
+/* 定義 */
+/******************************************************************************/
+/* タスクID */
+#define PROCMNG_TASK_ID_MIN ( 0 ) /** タスクID最小値 */
+#define PROCMNG_TASK_ID_MAX ( 4096 ) /** タスクID最大値 */
+#define PROCMNG_TASK_ID_NULL ( PROCMNG_TASK_ID_MAX + 1 )/** タスクID無 */
+#define PROCMNG_TASK_ID_NUM ( PROCMNG_TASK_ID_MAX + 1 )/** タスクID数 */
+#define PROCMNG_TASK_ID_IDLE ( 0 ) /** アイドルタスク */
+
+/* タスクタイプ */
+#define PROCMNG_TASK_TYPE_DRIVER ( 0 ) /** ドライバ */
+#define PROCMNG_TASK_TYPE_SERVER ( 1 ) /** サーバ */
+#define PROCMNG_TASK_TYPE_USER ( 2 ) /** ユーザ */
+
+
+/******************************************************************************/
+/* グローバル関数プロトタイプ宣言 */
+/******************************************************************************/
+/*---------------*/
+/* ProcMngInit.c */
+/*---------------*/
+/* プロセス管理初期化 */
+extern void ProcMngInit( void );
+
+/*--------------*/
+/* ProcMngSched */
+/*--------------*/
+/* スケジューラ実行 */
+extern void ProcMngSchedExec( void );
+
+
+/******************************************************************************/
+#endif