3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Just Standard Profile Kernel
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
9 * TOPPERS/JSP for Blackfin
11 * Copyright (C) 2004,2006,2006 by Takemasa Nakamura
12 * Copyright (C) 2004 by Ujinosuke
14 * 上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation
15 * によって公表されている GNU General Public License の Version 2 に記
16 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
17 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
19 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
20 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
22 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
23 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
24 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
26 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
27 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
29 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
30 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
31 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
33 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
34 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
36 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
37 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
38 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
39 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
46 * プロセッサ依存モジュール アセンブリ言語部(BLACKfin用)
47 * Copyright (C) 2004,2006,2006 by Takemasa Nakamura
50 // 32bit レジスタに即値をロードするマクロ
52 #define LOADLABEL( reg, value32 ) reg##.h = value32; reg##.l = value32;
53 #define LOADVALUE( reg, value32 ) reg##.h = ( value32 >> 16 ) &0xFFFF; reg##.l = value32 & 0xFFFF;
54 #elif defined(__ECC__)
55 #define LOADVALUE( reg, value32 ) reg##.h = hi(value32); reg##.l = lo(value32);
56 #define LOADLABEL LOADVALUE
58 #error "Compiler is not supported"
64 #include "jsp_kernel.h"
70 * dispatch は,割込み禁止状態で呼び出さなければならな
71 * い.exit_and_dispatch も,割込み禁止状態で呼び出す。
80 #elif defined(__ECC__)
83 #error "Compiler is not supported"
88 .global _exit_and_dispatch;
89 .extern ldf_stack_end;
92 .extern _runtsk, _schedtsk;
94 .type _dispatch, STT_FUNC;
95 #elif defined(__ECC__)
97 #error "Compiler is not supported"
100 [--sp] = (r7:4, p5:3);
103 LOADLABEL( p0, _runtsk )
104 LOADLABEL( p1, _schedtsk)
105 p2 = [p0]; // p2 を runtsk に
106 [p2+TCB_sp] = sp; // タスクスタックを保存
107 LOADLABEL( r1, dispatch_r ) // 実行再開番地を保存
112 [p0] = r0; // runtsk = schedtsk
114 if !cc jump dispatcher_1; // runtskが無ければ割り込み待ちに。
115 p3 = r0; // p3はschedtsk
116 sp = [p3+TCB_sp]; // タスクスタック復帰
117 p5 = [p3+TCB_pc]; // 実行再開番地復帰
118 jump (p5); // 実行再開番地へ飛ぶ
120 // ready タスクがない場合の割込み待ち
122 LOADLABEL( r0, ldf_stack_end) // イベントスタックポインタを設定
124 LOADLABEL( p4, _reqflg )
127 raise 14; // 割り込み待ち状態に移行
130 * 割り込み待ちはIVG14の割り込み状態で行う。ここでIVG14に遷移するのは
131 * どのスタックを使うかという問題の解決と,割込みハンドラ内で
132 * のタスクディスパッチの防止という2つの意味がある.
134 * 割込みを待つ間は,runtsk を NULL(=0)に設定しなければなら
135 * ない.このように設定しないと,割込みハンドラから iget_tid
136 * を呼び出した際の動作が仕様に合致しなくなる.
138 * 割り込み待ち状態はidleになるため、実際には割り込みではなくwakeup
139 * イベントが捕捉され、それに伴う割り込みを処理することになる。
140 * したがって割り込み待ちをおこなうためには、対応するSIC_IWRのビットを
142 * これはアプリケーションプログラマの責任で行う。
144 r0 = [p4]; // reqflag取得
146 if !cc jump wait_for_intr; // reqflgが0なら割り込み待ち
148 [p4] = r0; // reqflgをクリア
152 // タスクの再開番地。タスク例外の処理をおこない、
154 // このアドレスへは必ず dispatcherから飛んでくる。
155 // したがって、p3は必ずschedtskの内容になっている。
158 r2 = [p3+TCB_texptn]; // schedtsk->texptn
159 cc = r2 == 0; // texptrnが0ならcc => 1
160 // r0 = [p3+TCB_enatex];
161 // LOADVALUE( r1, TCB_enatex_mask )
162 r0 = b[p3+TCB_enatex](z);
163 r1 = TCB_enatex_mask;
164 r0 = r0 & r1; // enatexが0なら、az => 1
165 cc |= az; // cc = ( !enatex || ! texptn ) = !( enatex && texptn )
166 if cc jump dispatch_r_1(bp); // if ( !enatex || !texptn ) 即リターン
167 sp += -12; // ダミー引数領域確保
169 sp += 12; // ダミー引数領域開放
172 (r7:4, p5:3) = [sp++];
177 .size _dispatch, .-_dispatch
178 #elif defined(__ECC__)
180 #error "Compiler is not supported"
186 * start.asm は kernel_startをCPUロック状態、タスク優先順位で呼ぶ。
187 * kernel_startはそのままexit_and_dispatchを呼ぶ。
188 * _exit_and_dispatchは、それまでのスタック状態などを単に廃棄し、
192 // dispatcher以降で使うポインタを設定
193 LOADLABEL( p0, _runtsk )
194 LOADLABEL( p1, _schedtsk)
196 _exit_and_dispatch.end:
200 * _activate_rへはかならずdispatcherから飛んでくる。そのため、CPUロックを
208 cli r0; // 現在のマスクを取り出す。
209 // 管理外割り込みを使わないときにも、割り込み禁止のためcliが必要
211 r2 = UNMANAGED_INT(z);
212 r0 = r0 & r2; // 管理外割り込みのみ取り出す
215 r1 = r1 | r0; // 管理外割り込みを考慮したマスク
218 p0 = [sp++]; // タスクエントリーを取り出す
219 r0 = [sp++]; // ext_tskの番地を取り出す
220 rets = r0; // ext_tskをダミーの戻り番地にする
221 r0 = [sp++]; // ext_infを取り出す : r0 は引数1
230 * interrupt_handlerへはivgXXEntryからジャンプしてくる。p0レジスタには
232 * 割り込みとのネスト関係を調べ、ネストしていないならイベントスタックをセットする。
239 #include "saverestore.h"
241 .global interrupt_dispatcher;
242 .global task_context;
243 .extern _device_dispatcher, _enadsp;
247 .type interrupt_dispatcher, STT_FUNC;
248 #elif defined(__ECC__)
250 #error "Compiler is not supported"
252 interrupt_dispatcher:
253 // save all task context register
254 save_regs; // ユーザーレジスタの退避
260 lc0 = r0; // 性能低下抑制のためにLCxをクリア
262 LOADVALUE( p1, __IPEND ) // IPENDレジスタのアドレス
263 r0 = [p1]; // IPENDの値を取得
265 r0 = r0 & r1; // IVG15とGID以外を調べる
266 r0.L = ones r0; // 処理中のイベントの数を数える
267 r0 += -1; // イベントの数-1。ネストしていなければ0になる。
268 cc = az; // ネストしてなければ真
269 if !cc jump call_interrupt; // もしネストしていればハンドラを呼ぶ
270 // ネストしていない割り込みなら、スタックを切り替える
271 r6 = sp; // タスクスタックポインタを退避
272 LOADLABEL( r0, ldf_stack_end) // イベントスタックポインタを設定
276 cli r1; // IMASKの古い値を第二パラメータに
277 [--sp] = reti; // ここで割り込み可能になる
278 r7 = astat; // ccにはネスト情報が入っている。それを退避
279 r0 = p0; // 割り込み順位を第一パラメータに
280 LOADLABEL( p0, _device_dispatcher)
281 sp += -12; // ダミー引数確保 (A)
282 call (p0); // C言語で書かれたデバイスディスパッチャを呼ぶ
283 sp += 12; // ダミー引数開放 (A)
285 reti = [sp++]; // ここで再び割り込み禁止
286 if !cc jump get_back; // もしネストしているならば、このまま帰る
289 sp = r6; // スタックをタスクスタックに設定
291 LOADLABEL( p2, _reqflg) // reqflgのアドレス
292 r0 = [p2]; // reqflgの値を取得
293 cc = r0; // ディスパッチかタスク例外の要求は出ているか
294 if !cc jump get_back(bp); // 出ていないならば割り込まれたタスクに戻る
298 [p2] = r0; // reqflgをクリアする.
299 r0 = reti; // タスクの戻り番地を取り出す
301 r0 = r1 | r0; // セルフ・ネストであると偽装する
302 [--sp] = r0; // 戻り番地をスタックにつむ
303 LOADLABEL( p0, task_context)
305 cli r0; // 現在のCPUロック状態を取得
306 [--sp] = r0; // ロック状態を退避
308 r1 = 0xC01F(z); // タスクコンテキストははCPUロック状態で実行する
310 r2 = UNMANAGED_INT(z);
311 r0 = r0 & r2; // 管理外割り込みのマスク状態を抽出
312 r1 = r0 | r1; // タスクコンテキストはCPUロック状態で実行する
314 sti r1; // CPUロック (B)
316 reti = p0; // ラベル"task_context"を割り込みからの戻り番地にする
317 rti; // 割り込みから戻る。コンテキストはタスクになる
319 task_context: // ここはタスクコンテキストで、CPUロック状態である
320 LOADLABEL( p0, _enadsp)
321 LOADLABEL( p1, _runtsk)
324 r2 = [p0]; // load enadsp
325 cc = r2; // ディスパッチ可能か?
326 if !cc jump go_tex; // もしディスパッチ禁止なら例外チェックに
328 LOADLABEL( p0, _schedtsk) // ディスパッチ可能の場合
330 r0 = [p0]; // schedtsk
331 cc = r0 == r1; // schedtsk == runtsk か?
332 if cc jump go_tex(bp); // もし schedtsk == runtsk ならば、タスク例外に行く
334 sp += -12; // ダミー引数領域確保 (C)
335 call _dispatch; // レッツゴー
336 sp += 12; // ダミー引数領域開放 (C)
337 jump return_as_task; // タスクに戻る
341 r0 = [p1 + TCB_texptn]; // runtsk->texptrnを取得 ( UINT )
342 cc = r0 == 0; // texptnが0なら1
343 // r0 = [p1 + TCB_enatex]; // runtsk->enatexを取得
344 // LOADVALUE( r1, TCB_enatex_mask)
345 r0 = b[p1 + TCB_enatex](z); // runtsk->enatexを取得
346 r1 = TCB_enatex_mask;
347 r1 = r0 & r1; // タスク例外が許可されていなければ1
348 cc |= az; // 例外が許可されていないか、texptnが0ならば即帰る
349 if cc jump return_as_task(bp); // 許可されていなければタスクに戻る
350 sp += -12; // ダミー引数領域確保 (D)
351 call _call_texrtn; // 条件がそろったのでタスク例外処理を行う。
352 sp += 12; // ダミー引数領域開放 (D)
354 return_as_task: // タスクコンテキスト状態での戻り
355 r0 = [sp++]; // 退避していたロック状態
356 reti = [sp++]; // 戻り番地を復帰。以後rtiまで割込み禁止
357 cli r1; // 現在のロック状態を取り出す
358 // 管理外割り込みを使わない場合もこのcliは保護のため必要
360 r2 = UNMANAGED_INT(z);
361 r1 = r1 & r2; // 実行中のマスクから管理外割り込みの状態を抽出
362 r2 = ~ r2; // UNMANAGED_INTの逆マスク
363 r0 = r0 & r2; // 退避中のロック状態から管理外割り込みマスクをクリア
364 r0 = r0 | r1; // 退避していたロック状態をアップデート
366 sti r0; // CPUロックを解除(B)(F)
369 get_back: // 非タスクコンテキスト状態での戻り
370 restore_regs; // 退避したレジスタを全て戻す
376 .size interrupt_dispatcher, .-interrupt_dispatcher
377 #elif defined(__ECC__)
378 interrupt_dispatcher.end:
380 #error "Compiler is not supported"
399 .type expEntry, STT_FUNC;
400 .type nmiEntry, STT_FUNC;
401 .type ivTMREntry, STT_FUNC;
402 .type ivHWEntry, STT_FUNC;
403 .type ivg7Entry, STT_FUNC;
404 .type ivg8Entry, STT_FUNC;
405 .type ivg9Entry, STT_FUNC;
406 .type ivg10Entry, STT_FUNC;
407 .type ivg11Entry, STT_FUNC;
408 .type ivg12Entry, STT_FUNC;
409 .type ivg13Entry, STT_FUNC;
410 .type ivg14Entry, STT_FUNC;
411 #elif defined(__ECC__)
414 #error "Compiler is not supported"
421 * 割り込みとのネスト関係を調べ、ネストしていないならイベントスタックをセットする。
422 * p0 : ユーザー定義の例外ハンドラのアドレス
431 save_regs; // ユーザーレジスタの退避
433 LOADLABEL( p0, _exc_vector) // ユーザー定義例外ハンドラの格納アドレス
434 LOADVALUE( p1, __IPEND ) // IPENDレジスタのアドレス
440 lc0 = r0; // 性能低下抑制のためにLCxをクリア
443 p0 = [p0]; // p0 = exc_vector
444 r0 = [p1]; // IPENDの値を取得
446 r0 = r0 & r1; // IVG15とGID以外を調べる. r0.Hは必ず0
447 r0.L = ones r0; // 処理中のイベントの数を数える
448 r0 += -1; // イベントの数-1。ネストしていなければ0になる。
449 cc = r0 == 0; // ネストしてなければ真
450 if !cc jump call_exception; // もしネストしていればハンドラを呼ぶ
451 // ネストしていないイベントなら、スタックを切り替える
452 r6 = sp; // タスクスタックポインタを退避
453 LOADLABEL( r0, ldf_stack_end) // イベントスタックポインタを設定
457 r7 = astat; // ccにはネスト情報が入っている。それを退避
458 r0 = p1; // 第一引数はIPENDのアドレス
459 sp += -12; // ダミー引数領域確保 (E)
460 call (p0); // C言語で書かれた例外ハンドラを呼ぶ
461 sp += 12; // ダミー引数領域開放 (E)
463 if !cc jump get_back_x; // もしネストしているならば、このまま帰る
466 sp = r6; // スタックをタスクスタックに設定
468 LOADLABEL( p2, _reqflg )
469 r0 = [p2]; // reqflgの値を取得
470 cc = r0; // ディスパッチかタスク例外の要求は出ているか
471 if !cc jump get_back_x; // 出ていないならば割り込まれたタスクに戻る
475 [p2] = r0; // reqflgをクリアする.
476 r0 = retx; // タスクの戻り番地を取り出す
478 r0 = r1 | r0; // セルフ・ネストであると偽装する
479 [--sp] = r0; // 戻り番地をスタックにつむ
480 LOADLABEL( p0, task_context)
482 cli r0; // 現在のCPUロック状態を取得
483 [--sp] = r0; // ロック状態を退避
484 r1 = 0xC01F(z); // タスクコンテキストははCPUロック状態で実行する
487 r2 = UNMANAGED_INT(z);
488 r0 = r0 & r2; // 管理外割り込みのマスク状態を抽出
489 r1 = r0 | r1; // タスクコンテキストはCPUロック状態で実行する
491 sti r1; // CPUロック (F)
493 retx = p0; // ラベル"taskiv_context"を例外からの戻り番地にする
494 rtx; // 例外から戻る。コンテキストはタスクになる
497 restore_regs; // 退避したレジスタを全て戻す
503 .size expEntry, .-expEntry
504 #elif defined(__ECC__)
507 #error "Compiler is not supported"
512 // イベントハンドラのエントリーコード群。
513 // EVTのエントリには対応する以下のコードのラベルが格納される。
514 // それぞれのコードはイベント中にをp0に格納した後、
515 // interrupt_dispatcherにジャンプする
516 // evtvectorはユーザーハンドラへのポインタの配列
524 jump.x interrupt_dispatcher;
526 .size ivHWEntry, .-ivHWEntry
527 #elif defined(__ECC__)
530 #error "Compiler is not supported"
537 jump.x interrupt_dispatcher;
539 .size ivTMREntry, .-ivTMREntry
540 #elif defined(__ECC__)
543 #error "Compiler is not supported"
550 jump.x interrupt_dispatcher;
552 .size ivg7Entry, .-ivg7Entry
553 #elif defined(__ECC__)
556 #error "Compiler is not supported"
562 jump.x interrupt_dispatcher;
564 .size ivg8Entry, .-ivg8Entry
565 #elif defined(__ECC__)
568 #error "Compiler is not supported"
574 jump.x interrupt_dispatcher;
576 .size ivg9Entry, .-ivg8Entry
577 #elif defined(__ECC__)
580 #error "Compiler is not supported"
586 jump.x interrupt_dispatcher;
588 .size ivg10Entry, .-ivg10Entry
589 #elif defined(__ECC__)
592 #error "Compiler is not supported"
598 jump.x interrupt_dispatcher;
600 .size ivg11Entry, .-ivg11Entry
601 #elif defined(__ECC__)
604 #error "Compiler is not supported"
610 jump.x interrupt_dispatcher;
612 .size ivg12Entry, .-ivg12Entry
613 #elif defined(__ECC__)
616 #error "Compiler is not supported"
622 jump.x interrupt_dispatcher;
624 .size ivg13Entry, .-ivg13Entry
625 #elif defined(__ECC__)
628 #error "Compiler is not supported"
631 ivg14Entry: // dispatch()の割り込み待ち部
632 // USE_HW_ERRORは互換性の為だけに残してある。
633 #if !defined(USE_TIC_CORE) && !defined(USE_HW_ERROR) && !defined(QUICK_HW_ERROR)
634 LOADLABEL( p5, _idle_cycle );
635 r0 = cycles; // idle命令前のクロックを取得
636 csync; // コアタイマーでティックを刻むときにはidle命令を使えない。
639 r1 = cycles; // idle命令後のクロックを取得
640 r1 = r1 - r0; // idle命令滞在時間を算出
641 r0 = [p5]; // 累積idle_cycle値を読み出す
643 [p5] = r0; // 累積idle_cycle値を保存
645 [--sp] = reti; // 割込みネスト許可
646 r1 = 0xffff(z); // CPU アンロック用パターン
648 cli r0; // 現在のマスクを取り出す
649 r2 = UNMANAGED_INT(z);
650 r0 = r0 & r2; // 管理外割り込みのみ取り出す
653 r1 = r1 | r0; // 管理外割り込みを考慮したマスク
656 r1 = 0xC01F(z); // CPU ロック用パターン
657 cli r0; // 現在のマスクを取り出す
658 // 管理外割り込みを使わない場合も、保護のため必要
660 r2 = UNMANAGED_INT(z);
661 r0 = r0 & r2; // 管理外割り込みのみ取り出す
662 r1 = r1 | r0; // 管理外割り込みを考慮したマスク
665 reti=[sp++]; // 割込みネスト禁止
668 .size ivg14Entry, .-ivg14Entry
669 #elif defined(__ECC__)
672 #error "Compiler is not supported"
680 .size nmiEntry, .-nmiEntry
681 #elif defined(__ECC__)
684 #error "Compiler is not supported"
694 .global _sil_dly_nse;
698 r0 = r0 - r1; // dilay - SIL_DLY_TIM1
699 cc = an; // 結果が0より大きければ
700 if !cc jump _sil_dly_nse_1; // ループ
705 cc = an; // 結果が0より大きければ
706 if !cc jump _sil_dly_nse_1; // ループ