This is a port of the mruby/c tutorial Chapter 03 to the mbed environment.

Dependencies:   mbed

For details, refer to the following.

http://www.s-itoc.jp/activity/research/mrubyc/mrubyc_tutorial/436

Note:There is a change in rtt0.h from the original source in the mruby/c. It was necessary for inclusion in C ++ source.

Committer:
tk_takateku
Date:
Wed Feb 15 01:03:35 2017 +0000
Revision:
0:33feccbba3ff
Commit before publishing

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tk_takateku 0:33feccbba3ff 1 /*! @file
tk_takateku 0:33feccbba3ff 2 @brief
tk_takateku 0:33feccbba3ff 3 Realtime multitask monitor for mruby/c
tk_takateku 0:33feccbba3ff 4
tk_takateku 0:33feccbba3ff 5 <pre>
tk_takateku 0:33feccbba3ff 6 Copyright (C) 2016 Kyushu Institute of Technology.
tk_takateku 0:33feccbba3ff 7 Copyright (C) 2016 Shimane IT Open-Innovation Center.
tk_takateku 0:33feccbba3ff 8
tk_takateku 0:33feccbba3ff 9 This file is distributed under BSD 3-Clause License.
tk_takateku 0:33feccbba3ff 10 </pre>
tk_takateku 0:33feccbba3ff 11 */
tk_takateku 0:33feccbba3ff 12
tk_takateku 0:33feccbba3ff 13 /***** Feature test switches ************************************************/
tk_takateku 0:33feccbba3ff 14 /***** System headers *******************************************************/
tk_takateku 0:33feccbba3ff 15 #include <stdint.h>
tk_takateku 0:33feccbba3ff 16 #include <string.h>
tk_takateku 0:33feccbba3ff 17 #include <assert.h>
tk_takateku 0:33feccbba3ff 18
tk_takateku 0:33feccbba3ff 19
tk_takateku 0:33feccbba3ff 20 /***** Local headers ********************************************************/
tk_takateku 0:33feccbba3ff 21 #include "alloc.h"
tk_takateku 0:33feccbba3ff 22 #include "static.h"
tk_takateku 0:33feccbba3ff 23 #include "load.h"
tk_takateku 0:33feccbba3ff 24 #include "class.h"
tk_takateku 0:33feccbba3ff 25 #include "vm.h"
tk_takateku 0:33feccbba3ff 26 #include "rrt0.h"
tk_takateku 0:33feccbba3ff 27 #include "hal/hal.h"
tk_takateku 0:33feccbba3ff 28
tk_takateku 0:33feccbba3ff 29
tk_takateku 0:33feccbba3ff 30 /***** Constat values *******************************************************/
tk_takateku 0:33feccbba3ff 31 const int TIMESLICE_TICK = 10; // 10 * 1ms(HardwareTimer) 255 max
tk_takateku 0:33feccbba3ff 32
tk_takateku 0:33feccbba3ff 33
tk_takateku 0:33feccbba3ff 34 /***** Macros ***************************************************************/
tk_takateku 0:33feccbba3ff 35 /***** Typedefs *************************************************************/
tk_takateku 0:33feccbba3ff 36 /***** Function prototypes **************************************************/
tk_takateku 0:33feccbba3ff 37 /***** Local variables ******************************************************/
tk_takateku 0:33feccbba3ff 38 static MrbcTcb *q_domant_;
tk_takateku 0:33feccbba3ff 39 static MrbcTcb *q_ready_;
tk_takateku 0:33feccbba3ff 40 static MrbcTcb *q_waiting_;
tk_takateku 0:33feccbba3ff 41 static MrbcTcb *q_suspended_;
tk_takateku 0:33feccbba3ff 42 static volatile uint32_t tick_;
tk_takateku 0:33feccbba3ff 43
tk_takateku 0:33feccbba3ff 44
tk_takateku 0:33feccbba3ff 45 /***** Global variables *****************************************************/
tk_takateku 0:33feccbba3ff 46 /***** Signal catching functions ********************************************/
tk_takateku 0:33feccbba3ff 47 /***** Local functions ******************************************************/
tk_takateku 0:33feccbba3ff 48
tk_takateku 0:33feccbba3ff 49 //================================================================
tk_takateku 0:33feccbba3ff 50 /*! Insert to task queue
tk_takateku 0:33feccbba3ff 51
tk_takateku 0:33feccbba3ff 52 @param Pointer of target TCB
tk_takateku 0:33feccbba3ff 53
tk_takateku 0:33feccbba3ff 54 引数で指定されたタスク(TCB)を、状態別Queueに入れる。
tk_takateku 0:33feccbba3ff 55 TCBはフリーの状態でなければならない。(別なQueueに入っていてはならない)
tk_takateku 0:33feccbba3ff 56 Queueはpriority_preemption順にソート済みとなる。
tk_takateku 0:33feccbba3ff 57 挿入するTCBとQueueに同じpriority_preemption値がある場合は、同値の最後に挿入される。
tk_takateku 0:33feccbba3ff 58
tk_takateku 0:33feccbba3ff 59 */
tk_takateku 0:33feccbba3ff 60 static void q_insert_task(MrbcTcb *p_tcb)
tk_takateku 0:33feccbba3ff 61 {
tk_takateku 0:33feccbba3ff 62 MrbcTcb **pp_q;
tk_takateku 0:33feccbba3ff 63
tk_takateku 0:33feccbba3ff 64 switch( p_tcb->state ) {
tk_takateku 0:33feccbba3ff 65 case TASKSTATE_DOMANT: pp_q = &q_domant_; break;
tk_takateku 0:33feccbba3ff 66 case TASKSTATE_READY:
tk_takateku 0:33feccbba3ff 67 case TASKSTATE_RUNNING: pp_q = &q_ready_; break;
tk_takateku 0:33feccbba3ff 68 case TASKSTATE_WAITING: pp_q = &q_waiting_; break;
tk_takateku 0:33feccbba3ff 69 case TASKSTATE_SUSPENDED: pp_q = &q_suspended_; break;
tk_takateku 0:33feccbba3ff 70 default:
tk_takateku 0:33feccbba3ff 71 assert(!"Wrong task state.");
tk_takateku 0:33feccbba3ff 72 return;
tk_takateku 0:33feccbba3ff 73 }
tk_takateku 0:33feccbba3ff 74
tk_takateku 0:33feccbba3ff 75 // case insert on top.
tk_takateku 0:33feccbba3ff 76 if((*pp_q == NULL) ||
tk_takateku 0:33feccbba3ff 77 (p_tcb->priority_preemption < (*pp_q)->priority_preemption)) {
tk_takateku 0:33feccbba3ff 78 p_tcb->next = *pp_q;
tk_takateku 0:33feccbba3ff 79 *pp_q = p_tcb;
tk_takateku 0:33feccbba3ff 80 assert(p_tcb->next != p_tcb);
tk_takateku 0:33feccbba3ff 81 return;
tk_takateku 0:33feccbba3ff 82 }
tk_takateku 0:33feccbba3ff 83
tk_takateku 0:33feccbba3ff 84 // find insert point in sorted linked list.
tk_takateku 0:33feccbba3ff 85 MrbcTcb *p = *pp_q;
tk_takateku 0:33feccbba3ff 86 while( 1 ) {
tk_takateku 0:33feccbba3ff 87 if((p->next == NULL) ||
tk_takateku 0:33feccbba3ff 88 (p_tcb->priority_preemption < p->next->priority_preemption)) {
tk_takateku 0:33feccbba3ff 89 p_tcb->next = p->next;
tk_takateku 0:33feccbba3ff 90 p->next = p_tcb;
tk_takateku 0:33feccbba3ff 91 assert(p->next != p);
tk_takateku 0:33feccbba3ff 92 return;
tk_takateku 0:33feccbba3ff 93 }
tk_takateku 0:33feccbba3ff 94
tk_takateku 0:33feccbba3ff 95 p = p->next;
tk_takateku 0:33feccbba3ff 96 }
tk_takateku 0:33feccbba3ff 97 }
tk_takateku 0:33feccbba3ff 98
tk_takateku 0:33feccbba3ff 99
tk_takateku 0:33feccbba3ff 100 //================================================================
tk_takateku 0:33feccbba3ff 101 /*! Delete from task queue
tk_takateku 0:33feccbba3ff 102
tk_takateku 0:33feccbba3ff 103 @param Pointer of target TCB
tk_takateku 0:33feccbba3ff 104
tk_takateku 0:33feccbba3ff 105 Queueからタスク(TCB)を取り除く。
tk_takateku 0:33feccbba3ff 106
tk_takateku 0:33feccbba3ff 107 */
tk_takateku 0:33feccbba3ff 108 static void q_delete_task(MrbcTcb *p_tcb)
tk_takateku 0:33feccbba3ff 109 {
tk_takateku 0:33feccbba3ff 110 MrbcTcb **pp_q;
tk_takateku 0:33feccbba3ff 111
tk_takateku 0:33feccbba3ff 112 switch( p_tcb->state ) {
tk_takateku 0:33feccbba3ff 113 case TASKSTATE_DOMANT: pp_q = &q_domant_; break;
tk_takateku 0:33feccbba3ff 114 case TASKSTATE_READY:
tk_takateku 0:33feccbba3ff 115 case TASKSTATE_RUNNING: pp_q = &q_ready_; break;
tk_takateku 0:33feccbba3ff 116 case TASKSTATE_WAITING: pp_q = &q_waiting_; break;
tk_takateku 0:33feccbba3ff 117 case TASKSTATE_SUSPENDED: pp_q = &q_suspended_; break;
tk_takateku 0:33feccbba3ff 118 default:
tk_takateku 0:33feccbba3ff 119 assert(!"Wrong task state.");
tk_takateku 0:33feccbba3ff 120 return;
tk_takateku 0:33feccbba3ff 121 }
tk_takateku 0:33feccbba3ff 122
tk_takateku 0:33feccbba3ff 123 if( *pp_q == NULL ) return;
tk_takateku 0:33feccbba3ff 124 if( *pp_q == p_tcb ) {
tk_takateku 0:33feccbba3ff 125 *pp_q = p_tcb->next;
tk_takateku 0:33feccbba3ff 126 p_tcb->next = NULL;
tk_takateku 0:33feccbba3ff 127 return;
tk_takateku 0:33feccbba3ff 128 }
tk_takateku 0:33feccbba3ff 129
tk_takateku 0:33feccbba3ff 130 MrbcTcb *p = *pp_q;
tk_takateku 0:33feccbba3ff 131 while( p ) {
tk_takateku 0:33feccbba3ff 132 if( p->next == p_tcb ) {
tk_takateku 0:33feccbba3ff 133 p->next = p_tcb->next;
tk_takateku 0:33feccbba3ff 134 p_tcb->next = NULL;
tk_takateku 0:33feccbba3ff 135 return;
tk_takateku 0:33feccbba3ff 136 }
tk_takateku 0:33feccbba3ff 137
tk_takateku 0:33feccbba3ff 138 p = p->next;
tk_takateku 0:33feccbba3ff 139 }
tk_takateku 0:33feccbba3ff 140 }
tk_takateku 0:33feccbba3ff 141
tk_takateku 0:33feccbba3ff 142
tk_takateku 0:33feccbba3ff 143 //================================================================
tk_takateku 0:33feccbba3ff 144 /*! Find requested task
tk_takateku 0:33feccbba3ff 145
tk_takateku 0:33feccbba3ff 146 @param Pointer of vm
tk_takateku 0:33feccbba3ff 147 @return Pointer of MrbcTcb. zero is not found.
tk_takateku 0:33feccbba3ff 148 */
tk_takateku 0:33feccbba3ff 149 static inline MrbcTcb* find_requested_task(mrb_vm *vm)
tk_takateku 0:33feccbba3ff 150 {
tk_takateku 0:33feccbba3ff 151 MrbcTcb *tcb;
tk_takateku 0:33feccbba3ff 152
tk_takateku 0:33feccbba3ff 153 for( tcb = q_ready_; tcb != NULL; tcb = tcb->next ) {
tk_takateku 0:33feccbba3ff 154 if( tcb->vm == vm ) break;
tk_takateku 0:33feccbba3ff 155 }
tk_takateku 0:33feccbba3ff 156
tk_takateku 0:33feccbba3ff 157 return tcb;
tk_takateku 0:33feccbba3ff 158 }
tk_takateku 0:33feccbba3ff 159
tk_takateku 0:33feccbba3ff 160
tk_takateku 0:33feccbba3ff 161 //================================================================
tk_takateku 0:33feccbba3ff 162 /*! 一定時間停止(cruby互換)
tk_takateku 0:33feccbba3ff 163
tk_takateku 0:33feccbba3ff 164 */
tk_takateku 0:33feccbba3ff 165 static void c_sleep(mrb_vm *vm, mrb_value *v)
tk_takateku 0:33feccbba3ff 166 {
tk_takateku 0:33feccbba3ff 167 MrbcTcb *tcb = find_requested_task(vm);
tk_takateku 0:33feccbba3ff 168
tk_takateku 0:33feccbba3ff 169 if( tcb == NULL ) return;
tk_takateku 0:33feccbba3ff 170
tk_takateku 0:33feccbba3ff 171 switch( v[1].tt ) {
tk_takateku 0:33feccbba3ff 172 case MRB_TT_FIXNUM:
tk_takateku 0:33feccbba3ff 173 mrbc_sleep_ms(tcb, GET_INT_ARG(0) * 1000);
tk_takateku 0:33feccbba3ff 174 break;
tk_takateku 0:33feccbba3ff 175
tk_takateku 0:33feccbba3ff 176 case MRB_TT_FLOAT:
tk_takateku 0:33feccbba3ff 177 mrbc_sleep_ms(tcb, (uint32_t)(GET_FLOAT_ARG(0) * 1000));
tk_takateku 0:33feccbba3ff 178 break;
tk_takateku 0:33feccbba3ff 179
tk_takateku 0:33feccbba3ff 180 default:
tk_takateku 0:33feccbba3ff 181
tk_takateku 0:33feccbba3ff 182 // TODO 引数なしの場合は永久停止
tk_takateku 0:33feccbba3ff 183 break;
tk_takateku 0:33feccbba3ff 184 }
tk_takateku 0:33feccbba3ff 185 }
tk_takateku 0:33feccbba3ff 186
tk_takateku 0:33feccbba3ff 187
tk_takateku 0:33feccbba3ff 188 //================================================================
tk_takateku 0:33feccbba3ff 189 /*! 一定時間停止(ms単位)
tk_takateku 0:33feccbba3ff 190
tk_takateku 0:33feccbba3ff 191 */
tk_takateku 0:33feccbba3ff 192 static void c_sleep_ms(mrb_vm *vm, mrb_value *v)
tk_takateku 0:33feccbba3ff 193 {
tk_takateku 0:33feccbba3ff 194 MrbcTcb *tcb = find_requested_task(vm);
tk_takateku 0:33feccbba3ff 195
tk_takateku 0:33feccbba3ff 196 if( tcb == NULL ) return;
tk_takateku 0:33feccbba3ff 197
tk_takateku 0:33feccbba3ff 198 mrbc_sleep_ms(tcb, GET_INT_ARG(0));
tk_takateku 0:33feccbba3ff 199 }
tk_takateku 0:33feccbba3ff 200
tk_takateku 0:33feccbba3ff 201
tk_takateku 0:33feccbba3ff 202 //================================================================
tk_takateku 0:33feccbba3ff 203 /*! 実行権を手放す
tk_takateku 0:33feccbba3ff 204
tk_takateku 0:33feccbba3ff 205 */
tk_takateku 0:33feccbba3ff 206 static void c_relinquish(mrb_vm *vm, mrb_value *v)
tk_takateku 0:33feccbba3ff 207 {
tk_takateku 0:33feccbba3ff 208 MrbcTcb *tcb = find_requested_task(vm);
tk_takateku 0:33feccbba3ff 209
tk_takateku 0:33feccbba3ff 210 if( tcb == NULL ) return;
tk_takateku 0:33feccbba3ff 211
tk_takateku 0:33feccbba3ff 212 mrbc_relinquish(tcb);
tk_takateku 0:33feccbba3ff 213 }
tk_takateku 0:33feccbba3ff 214
tk_takateku 0:33feccbba3ff 215
tk_takateku 0:33feccbba3ff 216 //================================================================
tk_takateku 0:33feccbba3ff 217 /*! プライオリティー変更
tk_takateku 0:33feccbba3ff 218
tk_takateku 0:33feccbba3ff 219 */
tk_takateku 0:33feccbba3ff 220 static void c_change_priority(mrb_vm *vm, mrb_value *v)
tk_takateku 0:33feccbba3ff 221 {
tk_takateku 0:33feccbba3ff 222 MrbcTcb *tcb = find_requested_task(vm);
tk_takateku 0:33feccbba3ff 223
tk_takateku 0:33feccbba3ff 224 if( tcb == NULL ) return;
tk_takateku 0:33feccbba3ff 225
tk_takateku 0:33feccbba3ff 226 mrbc_change_priority(tcb, GET_INT_ARG(0));
tk_takateku 0:33feccbba3ff 227 }
tk_takateku 0:33feccbba3ff 228
tk_takateku 0:33feccbba3ff 229
tk_takateku 0:33feccbba3ff 230 //================================================================
tk_takateku 0:33feccbba3ff 231 /*! 実行停止
tk_takateku 0:33feccbba3ff 232
tk_takateku 0:33feccbba3ff 233 */
tk_takateku 0:33feccbba3ff 234 static void c_suspend_task(mrb_vm *vm, mrb_value *v)
tk_takateku 0:33feccbba3ff 235 {
tk_takateku 0:33feccbba3ff 236 MrbcTcb *tcb = find_requested_task(vm);
tk_takateku 0:33feccbba3ff 237
tk_takateku 0:33feccbba3ff 238 if( tcb == NULL ) return;
tk_takateku 0:33feccbba3ff 239
tk_takateku 0:33feccbba3ff 240 mrbc_suspend_task(tcb);
tk_takateku 0:33feccbba3ff 241 }
tk_takateku 0:33feccbba3ff 242
tk_takateku 0:33feccbba3ff 243
tk_takateku 0:33feccbba3ff 244 //================================================================
tk_takateku 0:33feccbba3ff 245 /*! 実行再開
tk_takateku 0:33feccbba3ff 246
tk_takateku 0:33feccbba3ff 247 */
tk_takateku 0:33feccbba3ff 248 static void c_resume_task(mrb_vm *vm, mrb_value *v)
tk_takateku 0:33feccbba3ff 249 {
tk_takateku 0:33feccbba3ff 250 MrbcTcb *tcb = find_requested_task(vm);
tk_takateku 0:33feccbba3ff 251
tk_takateku 0:33feccbba3ff 252 if( tcb == NULL ) return;
tk_takateku 0:33feccbba3ff 253
tk_takateku 0:33feccbba3ff 254 // TODO: 未デバグ。引数で与えられたTCBのタスクを実行再開する。
tk_takateku 0:33feccbba3ff 255 mrbc_resume_task(tcb);
tk_takateku 0:33feccbba3ff 256 }
tk_takateku 0:33feccbba3ff 257
tk_takateku 0:33feccbba3ff 258
tk_takateku 0:33feccbba3ff 259 //================================================================
tk_takateku 0:33feccbba3ff 260 /*! TCBを得る
tk_takateku 0:33feccbba3ff 261
tk_takateku 0:33feccbba3ff 262 */
tk_takateku 0:33feccbba3ff 263 static void c_get_tcb(mrb_vm *vm, mrb_value *v)
tk_takateku 0:33feccbba3ff 264 {
tk_takateku 0:33feccbba3ff 265 MrbcTcb *tcb = find_requested_task(vm);
tk_takateku 0:33feccbba3ff 266
tk_takateku 0:33feccbba3ff 267 if( tcb == NULL ) return;
tk_takateku 0:33feccbba3ff 268
tk_takateku 0:33feccbba3ff 269 // TODO: 未実装。TCBポインタをオブジェクトとして返す。
tk_takateku 0:33feccbba3ff 270 }
tk_takateku 0:33feccbba3ff 271
tk_takateku 0:33feccbba3ff 272
tk_takateku 0:33feccbba3ff 273 /***** Global functions *****************************************************/
tk_takateku 0:33feccbba3ff 274
tk_takateku 0:33feccbba3ff 275 //================================================================
tk_takateku 0:33feccbba3ff 276 /*! Tick timer interrupt handler.
tk_takateku 0:33feccbba3ff 277
tk_takateku 0:33feccbba3ff 278 */
tk_takateku 0:33feccbba3ff 279 void mrbc_tick(void)
tk_takateku 0:33feccbba3ff 280 {
tk_takateku 0:33feccbba3ff 281 MrbcTcb *tcb;
tk_takateku 0:33feccbba3ff 282 int flag_preemption = 0;
tk_takateku 0:33feccbba3ff 283
tk_takateku 0:33feccbba3ff 284 tick_++;
tk_takateku 0:33feccbba3ff 285
tk_takateku 0:33feccbba3ff 286 // 実行中タスクのタイムスライス値を減らす
tk_takateku 0:33feccbba3ff 287 tcb = q_ready_;
tk_takateku 0:33feccbba3ff 288 if((tcb != NULL) &&
tk_takateku 0:33feccbba3ff 289 (tcb->state == TASKSTATE_RUNNING) &&
tk_takateku 0:33feccbba3ff 290 (tcb->timeslice > 0)) {
tk_takateku 0:33feccbba3ff 291 tcb->timeslice--;
tk_takateku 0:33feccbba3ff 292 if( tcb->timeslice == 0 ) tcb->vm->flag_preemption = 1;
tk_takateku 0:33feccbba3ff 293 }
tk_takateku 0:33feccbba3ff 294
tk_takateku 0:33feccbba3ff 295 // 待ちタスクキューから、ウェイクアップすべきタスクを探す
tk_takateku 0:33feccbba3ff 296 tcb = q_waiting_;
tk_takateku 0:33feccbba3ff 297 while( tcb != NULL ) {
tk_takateku 0:33feccbba3ff 298 MrbcTcb *t = tcb;
tk_takateku 0:33feccbba3ff 299 tcb = tcb->next;
tk_takateku 0:33feccbba3ff 300
tk_takateku 0:33feccbba3ff 301 if( t->wakeup_tick == tick_ ) {
tk_takateku 0:33feccbba3ff 302 q_delete_task(t);
tk_takateku 0:33feccbba3ff 303 t->state = TASKSTATE_READY;
tk_takateku 0:33feccbba3ff 304 t->timeslice = TIMESLICE_TICK;
tk_takateku 0:33feccbba3ff 305 q_insert_task(t);
tk_takateku 0:33feccbba3ff 306 flag_preemption = 1;
tk_takateku 0:33feccbba3ff 307 }
tk_takateku 0:33feccbba3ff 308 }
tk_takateku 0:33feccbba3ff 309
tk_takateku 0:33feccbba3ff 310 if( flag_preemption ) {
tk_takateku 0:33feccbba3ff 311 tcb = q_ready_;
tk_takateku 0:33feccbba3ff 312 while( tcb != NULL ) {
tk_takateku 0:33feccbba3ff 313 if( tcb->state == TASKSTATE_RUNNING ) tcb->vm->flag_preemption = 1;
tk_takateku 0:33feccbba3ff 314 tcb = tcb->next;
tk_takateku 0:33feccbba3ff 315 }
tk_takateku 0:33feccbba3ff 316 }
tk_takateku 0:33feccbba3ff 317 }
tk_takateku 0:33feccbba3ff 318
tk_takateku 0:33feccbba3ff 319
tk_takateku 0:33feccbba3ff 320 //================================================================
tk_takateku 0:33feccbba3ff 321 /*! initialize
tk_takateku 0:33feccbba3ff 322
tk_takateku 0:33feccbba3ff 323 */
tk_takateku 0:33feccbba3ff 324 void mrbc_init(void)
tk_takateku 0:33feccbba3ff 325 {
tk_takateku 0:33feccbba3ff 326 mrbc_init_alloc();
tk_takateku 0:33feccbba3ff 327 init_static();
tk_takateku 0:33feccbba3ff 328 hal_init();
tk_takateku 0:33feccbba3ff 329
tk_takateku 0:33feccbba3ff 330
tk_takateku 0:33feccbba3ff 331 // TODO 関数呼び出しが、c_XXX => mrbc_XXX の daisy chain になっている。
tk_takateku 0:33feccbba3ff 332 // 不要な複雑さかもしれない。要リファクタリング。
tk_takateku 0:33feccbba3ff 333 mrbc_define_method(0, mrbc_class_object, "sleep", c_sleep);
tk_takateku 0:33feccbba3ff 334 mrbc_define_method(0, mrbc_class_object, "sleep_ms", c_sleep_ms);
tk_takateku 0:33feccbba3ff 335 mrbc_define_method(0, mrbc_class_object, "relinquish", c_relinquish);
tk_takateku 0:33feccbba3ff 336 mrbc_define_method(0, mrbc_class_object, "change_priority", c_change_priority);
tk_takateku 0:33feccbba3ff 337 mrbc_define_method(0, mrbc_class_object, "suspend_task", c_suspend_task);
tk_takateku 0:33feccbba3ff 338 mrbc_define_method(0, mrbc_class_object, "resume_task", c_resume_task);
tk_takateku 0:33feccbba3ff 339 }
tk_takateku 0:33feccbba3ff 340
tk_takateku 0:33feccbba3ff 341
tk_takateku 0:33feccbba3ff 342 //================================================================
tk_takateku 0:33feccbba3ff 343 /*! specify running VM code.
tk_takateku 0:33feccbba3ff 344
tk_takateku 0:33feccbba3ff 345 @param vm_code pointer of VM byte code.
tk_takateku 0:33feccbba3ff 346 @param tcb Task control block with parameter, or NULL.
tk_takateku 0:33feccbba3ff 347 @retval Pointer of MrbcTcb.
tk_takateku 0:33feccbba3ff 348 @retval NULL is error.
tk_takateku 0:33feccbba3ff 349
tk_takateku 0:33feccbba3ff 350 */
tk_takateku 0:33feccbba3ff 351 MrbcTcb* mrbc_create_task(const uint8_t *vm_code, MrbcTcb *tcb)
tk_takateku 0:33feccbba3ff 352 {
tk_takateku 0:33feccbba3ff 353 // allocate Task Control Block
tk_takateku 0:33feccbba3ff 354 if( tcb == NULL ) {
tk_takateku 0:33feccbba3ff 355 tcb = (MrbcTcb*)mrbc_raw_alloc( sizeof(MrbcTcb) );
tk_takateku 0:33feccbba3ff 356 if( tcb == NULL ) return NULL; // ENOMEM
tk_takateku 0:33feccbba3ff 357
tk_takateku 0:33feccbba3ff 358 static const MrbcTcb init_val = MRBC_TCB_INITIALIZER;
tk_takateku 0:33feccbba3ff 359 *tcb = init_val;
tk_takateku 0:33feccbba3ff 360 }
tk_takateku 0:33feccbba3ff 361 tcb->timeslice = TIMESLICE_TICK;
tk_takateku 0:33feccbba3ff 362 tcb->priority_preemption = tcb->priority;
tk_takateku 0:33feccbba3ff 363
tk_takateku 0:33feccbba3ff 364 // assign VM on TCB
tk_takateku 0:33feccbba3ff 365 if( tcb->state != TASKSTATE_DOMANT ) {
tk_takateku 0:33feccbba3ff 366 tcb->vm = vm_open();
tk_takateku 0:33feccbba3ff 367 if( !tcb->vm ) return 0; // error. can't open VM.
tk_takateku 0:33feccbba3ff 368 // NOTE: memory leak MrbcTcb. but ignore.
tk_takateku 0:33feccbba3ff 369
tk_takateku 0:33feccbba3ff 370 loca_mrb_array(tcb->vm, vm_code);
tk_takateku 0:33feccbba3ff 371 vm_boot(tcb->vm);
tk_takateku 0:33feccbba3ff 372 }
tk_takateku 0:33feccbba3ff 373
tk_takateku 0:33feccbba3ff 374 hal_disable_irq();
tk_takateku 0:33feccbba3ff 375 q_insert_task(tcb);
tk_takateku 0:33feccbba3ff 376 hal_enable_irq();
tk_takateku 0:33feccbba3ff 377
tk_takateku 0:33feccbba3ff 378 return tcb;
tk_takateku 0:33feccbba3ff 379 }
tk_takateku 0:33feccbba3ff 380
tk_takateku 0:33feccbba3ff 381
tk_takateku 0:33feccbba3ff 382 //================================================================
tk_takateku 0:33feccbba3ff 383 /*! execute
tk_takateku 0:33feccbba3ff 384
tk_takateku 0:33feccbba3ff 385 */
tk_takateku 0:33feccbba3ff 386 int mrbc_run(void)
tk_takateku 0:33feccbba3ff 387 {
tk_takateku 0:33feccbba3ff 388 while( 1 ) {
tk_takateku 0:33feccbba3ff 389 MrbcTcb *tcb = q_ready_;
tk_takateku 0:33feccbba3ff 390 if( tcb == NULL ) {
tk_takateku 0:33feccbba3ff 391 // 実行すべきタスクなし
tk_takateku 0:33feccbba3ff 392 hal_idle_cpu();
tk_takateku 0:33feccbba3ff 393 continue;
tk_takateku 0:33feccbba3ff 394 }
tk_takateku 0:33feccbba3ff 395
tk_takateku 0:33feccbba3ff 396 // 実行開始
tk_takateku 0:33feccbba3ff 397 tcb->state = TASKSTATE_RUNNING;
tk_takateku 0:33feccbba3ff 398 int res = 0;
tk_takateku 0:33feccbba3ff 399
tk_takateku 0:33feccbba3ff 400 #ifndef MRBC_NO_TIMER
tk_takateku 0:33feccbba3ff 401 tcb->vm->flag_preemption = 0;
tk_takateku 0:33feccbba3ff 402 res = vm_run(tcb->vm);
tk_takateku 0:33feccbba3ff 403
tk_takateku 0:33feccbba3ff 404 #else
tk_takateku 0:33feccbba3ff 405 while( tcb->timeslice > 0 ) {
tk_takateku 0:33feccbba3ff 406 tcb->vm->flag_preemption = 1;
tk_takateku 0:33feccbba3ff 407 res = vm_run(tcb->vm);
tk_takateku 0:33feccbba3ff 408 tcb->timeslice--;
tk_takateku 0:33feccbba3ff 409 if( res < 0 ) break;
tk_takateku 0:33feccbba3ff 410 if( tcb->state != TASKSTATE_RUNNING ) break;
tk_takateku 0:33feccbba3ff 411 }
tk_takateku 0:33feccbba3ff 412 mrbc_tick();
tk_takateku 0:33feccbba3ff 413 #endif /* ifndef MRBC_NO_TIMER */
tk_takateku 0:33feccbba3ff 414
tk_takateku 0:33feccbba3ff 415 // タスク終了?
tk_takateku 0:33feccbba3ff 416 if( res < 0 ) {
tk_takateku 0:33feccbba3ff 417 hal_disable_irq();
tk_takateku 0:33feccbba3ff 418 q_delete_task(tcb);
tk_takateku 0:33feccbba3ff 419 tcb->state = TASKSTATE_DOMANT;
tk_takateku 0:33feccbba3ff 420 q_insert_task(tcb);
tk_takateku 0:33feccbba3ff 421 hal_enable_irq();
tk_takateku 0:33feccbba3ff 422 vm_close(tcb->vm);
tk_takateku 0:33feccbba3ff 423 tcb->vm = 0;
tk_takateku 0:33feccbba3ff 424
tk_takateku 0:33feccbba3ff 425 if( q_ready_ == NULL && q_waiting_ == NULL &&
tk_takateku 0:33feccbba3ff 426 q_suspended_ == NULL ) break;
tk_takateku 0:33feccbba3ff 427 continue;
tk_takateku 0:33feccbba3ff 428 }
tk_takateku 0:33feccbba3ff 429
tk_takateku 0:33feccbba3ff 430 // タスク切り替え
tk_takateku 0:33feccbba3ff 431 hal_disable_irq();
tk_takateku 0:33feccbba3ff 432 if( tcb->state == TASKSTATE_RUNNING ) {
tk_takateku 0:33feccbba3ff 433 tcb->state = TASKSTATE_READY;
tk_takateku 0:33feccbba3ff 434
tk_takateku 0:33feccbba3ff 435 // タイムスライス終了?
tk_takateku 0:33feccbba3ff 436 if( tcb->timeslice == 0 ) {
tk_takateku 0:33feccbba3ff 437 q_delete_task(tcb);
tk_takateku 0:33feccbba3ff 438 tcb->timeslice = TIMESLICE_TICK;
tk_takateku 0:33feccbba3ff 439 q_insert_task(tcb); // insert task on queue last.
tk_takateku 0:33feccbba3ff 440 }
tk_takateku 0:33feccbba3ff 441 }
tk_takateku 0:33feccbba3ff 442 hal_enable_irq();
tk_takateku 0:33feccbba3ff 443 }
tk_takateku 0:33feccbba3ff 444
tk_takateku 0:33feccbba3ff 445 return 0;
tk_takateku 0:33feccbba3ff 446 }
tk_takateku 0:33feccbba3ff 447
tk_takateku 0:33feccbba3ff 448
tk_takateku 0:33feccbba3ff 449 //================================================================
tk_takateku 0:33feccbba3ff 450 /*! 実行一時停止
tk_takateku 0:33feccbba3ff 451
tk_takateku 0:33feccbba3ff 452 */
tk_takateku 0:33feccbba3ff 453 void mrbc_sleep_ms(MrbcTcb *tcb, uint32_t ms)
tk_takateku 0:33feccbba3ff 454 {
tk_takateku 0:33feccbba3ff 455 hal_disable_irq();
tk_takateku 0:33feccbba3ff 456 q_delete_task(tcb);
tk_takateku 0:33feccbba3ff 457 tcb->timeslice = 0;
tk_takateku 0:33feccbba3ff 458 tcb->state = TASKSTATE_WAITING;
tk_takateku 0:33feccbba3ff 459 tcb->wakeup_tick = tick_ + ms;
tk_takateku 0:33feccbba3ff 460 q_insert_task(tcb);
tk_takateku 0:33feccbba3ff 461 hal_enable_irq();
tk_takateku 0:33feccbba3ff 462
tk_takateku 0:33feccbba3ff 463 tcb->vm->flag_preemption = 1;
tk_takateku 0:33feccbba3ff 464 }
tk_takateku 0:33feccbba3ff 465
tk_takateku 0:33feccbba3ff 466
tk_takateku 0:33feccbba3ff 467 //================================================================
tk_takateku 0:33feccbba3ff 468 /*! 実行権を手放す
tk_takateku 0:33feccbba3ff 469
tk_takateku 0:33feccbba3ff 470 */
tk_takateku 0:33feccbba3ff 471 void mrbc_relinquish(MrbcTcb *tcb)
tk_takateku 0:33feccbba3ff 472 {
tk_takateku 0:33feccbba3ff 473 tcb->timeslice = 0;
tk_takateku 0:33feccbba3ff 474 tcb->vm->flag_preemption = 1;
tk_takateku 0:33feccbba3ff 475 }
tk_takateku 0:33feccbba3ff 476
tk_takateku 0:33feccbba3ff 477
tk_takateku 0:33feccbba3ff 478 //================================================================
tk_takateku 0:33feccbba3ff 479 /*! プライオリティーの変更
tk_takateku 0:33feccbba3ff 480 TODO: No check, yet.
tk_takateku 0:33feccbba3ff 481 */
tk_takateku 0:33feccbba3ff 482 void mrbc_change_priority(MrbcTcb *tcb, int priority)
tk_takateku 0:33feccbba3ff 483 {
tk_takateku 0:33feccbba3ff 484 tcb->priority = (uint8_t)priority;
tk_takateku 0:33feccbba3ff 485 tcb->priority_preemption = (uint8_t)priority;
tk_takateku 0:33feccbba3ff 486 tcb->timeslice = 0;
tk_takateku 0:33feccbba3ff 487 tcb->vm->flag_preemption = 1;
tk_takateku 0:33feccbba3ff 488 }
tk_takateku 0:33feccbba3ff 489
tk_takateku 0:33feccbba3ff 490
tk_takateku 0:33feccbba3ff 491 //================================================================
tk_takateku 0:33feccbba3ff 492 /*! 実行停止
tk_takateku 0:33feccbba3ff 493
tk_takateku 0:33feccbba3ff 494 */
tk_takateku 0:33feccbba3ff 495 void mrbc_suspend_task(MrbcTcb *tcb)
tk_takateku 0:33feccbba3ff 496 {
tk_takateku 0:33feccbba3ff 497 hal_disable_irq();
tk_takateku 0:33feccbba3ff 498 q_delete_task(tcb);
tk_takateku 0:33feccbba3ff 499 tcb->state = TASKSTATE_SUSPENDED;
tk_takateku 0:33feccbba3ff 500 q_insert_task(tcb);
tk_takateku 0:33feccbba3ff 501 hal_enable_irq();
tk_takateku 0:33feccbba3ff 502
tk_takateku 0:33feccbba3ff 503 tcb->vm->flag_preemption = 1;
tk_takateku 0:33feccbba3ff 504 }
tk_takateku 0:33feccbba3ff 505
tk_takateku 0:33feccbba3ff 506
tk_takateku 0:33feccbba3ff 507 //================================================================
tk_takateku 0:33feccbba3ff 508 /*! 実行再開
tk_takateku 0:33feccbba3ff 509
tk_takateku 0:33feccbba3ff 510 */
tk_takateku 0:33feccbba3ff 511 void mrbc_resume_task(MrbcTcb *tcb)
tk_takateku 0:33feccbba3ff 512 {
tk_takateku 0:33feccbba3ff 513 hal_disable_irq();
tk_takateku 0:33feccbba3ff 514
tk_takateku 0:33feccbba3ff 515 MrbcTcb *t = q_ready_;
tk_takateku 0:33feccbba3ff 516 while( t != NULL ) {
tk_takateku 0:33feccbba3ff 517 if( t->state == TASKSTATE_RUNNING ) t->vm->flag_preemption = 1;
tk_takateku 0:33feccbba3ff 518 t = t->next;
tk_takateku 0:33feccbba3ff 519 }
tk_takateku 0:33feccbba3ff 520
tk_takateku 0:33feccbba3ff 521 q_delete_task(tcb);
tk_takateku 0:33feccbba3ff 522 tcb->state = TASKSTATE_READY;
tk_takateku 0:33feccbba3ff 523 q_insert_task(tcb);
tk_takateku 0:33feccbba3ff 524 hal_enable_irq();
tk_takateku 0:33feccbba3ff 525 }
tk_takateku 0:33feccbba3ff 526
tk_takateku 0:33feccbba3ff 527
tk_takateku 0:33feccbba3ff 528 #ifdef MRBC_DEBUG
tk_takateku 0:33feccbba3ff 529 #include "console.h"
tk_takateku 0:33feccbba3ff 530
tk_takateku 0:33feccbba3ff 531 //================================================================
tk_takateku 0:33feccbba3ff 532 /*! DEBUG print queue
tk_takateku 0:33feccbba3ff 533
tk_takateku 0:33feccbba3ff 534 */
tk_takateku 0:33feccbba3ff 535 void pq(MrbcTcb *p_tcb)
tk_takateku 0:33feccbba3ff 536 {
tk_takateku 0:33feccbba3ff 537 MrbcTcb *p;
tk_takateku 0:33feccbba3ff 538
tk_takateku 0:33feccbba3ff 539 p = p_tcb;
tk_takateku 0:33feccbba3ff 540 while( p != NULL ) {
tk_takateku 0:33feccbba3ff 541 console_printf("%08x ", (int)((uint64_t)p & 0xffffffff));
tk_takateku 0:33feccbba3ff 542 p = p->next;
tk_takateku 0:33feccbba3ff 543 }
tk_takateku 0:33feccbba3ff 544 console_printf("\n");
tk_takateku 0:33feccbba3ff 545
tk_takateku 0:33feccbba3ff 546 p = p_tcb;
tk_takateku 0:33feccbba3ff 547 while( p != NULL ) {
tk_takateku 0:33feccbba3ff 548 console_printf(" pri: %2d ", p->priority_preemption);
tk_takateku 0:33feccbba3ff 549 p = p->next;
tk_takateku 0:33feccbba3ff 550 }
tk_takateku 0:33feccbba3ff 551 console_printf("\n");
tk_takateku 0:33feccbba3ff 552
tk_takateku 0:33feccbba3ff 553 p = p_tcb;
tk_takateku 0:33feccbba3ff 554 while( p != NULL ) {
tk_takateku 0:33feccbba3ff 555 console_printf(" nx:%04x ", (int)((uint64_t)p->next & 0xffff));
tk_takateku 0:33feccbba3ff 556 p = p->next;
tk_takateku 0:33feccbba3ff 557 }
tk_takateku 0:33feccbba3ff 558 console_printf("\n");
tk_takateku 0:33feccbba3ff 559 }
tk_takateku 0:33feccbba3ff 560
tk_takateku 0:33feccbba3ff 561
tk_takateku 0:33feccbba3ff 562 void pqall(void)
tk_takateku 0:33feccbba3ff 563 {
tk_takateku 0:33feccbba3ff 564 // console_printf("<<<<< DOMANT >>>>>\n");
tk_takateku 0:33feccbba3ff 565 // pq(q_domant_);
tk_takateku 0:33feccbba3ff 566 console_printf("<<<<< READY >>>>>\n");
tk_takateku 0:33feccbba3ff 567 pq(q_ready_);
tk_takateku 0:33feccbba3ff 568 console_printf("<<<<< WAITING >>>>>\n");
tk_takateku 0:33feccbba3ff 569 pq(q_waiting_);
tk_takateku 0:33feccbba3ff 570 console_printf("<<<<< SUSPENDED >>>>>\n");
tk_takateku 0:33feccbba3ff 571 pq(q_suspended_);
tk_takateku 0:33feccbba3ff 572 }
tk_takateku 0:33feccbba3ff 573 #endif
tk_takateku 0:33feccbba3ff 574