3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
6 * Copyright (C) 2008 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
9 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
10 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
22 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
23 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
24 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
26 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
27 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
28 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
29 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
33 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
34 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
35 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38 * @(#) $Id: prc_config.h 1304 2008-08-27 07:28:36Z ertl-honda $
42 * プロセッサ依存モジュール(ARM-M用)
44 * このインクルードファイルは,target_config.h(または,そこからインク
45 * ルードされるファイル)のみからインクルードされる.他のファイルから
49 #ifndef TOPPERS_PRC_CONFIG_H
50 #define TOPPERS_PRC_CONFIG_H
52 #ifndef TOPPERS_MACRO_ONLY
55 * プロセッサの特殊命令のインライン関数定義
62 #define TOPPERS_ISTKPT(istk, istksz) ((STK_T *)((istk) + (istksz)/(sizeof(STK_T))))
67 typedef struct task_context_block {
68 void *sp; /* スタックポインタ */
69 FP pc; /* プログラムカウンタ */
72 #endif /* TOPPERS_MACRO_ONLY */
74 #ifndef TOPPERS_MACRO_ONLY
83 * PSPが有効ならタスクコンテキスト,MSPが有効なら非タスクコンテキスト
86 if ((get_control() & CONTROL_PSP) == CONTROL_PSP){
94 #endif /* TOPPERS_MACRO_ONLY */
97 * TOPPERS標準割込み処理モデルの実現
99 * 割込み優先度マスクとしては,BASEPRIを用いる.全割込みを禁止する
100 * 機能として,FAULTMASKやPRIMASKがあるが,カーネル管理外の割込みを
101 * サポートするため,これらはCPUロックのために用いない.
102 * そのため,BASEPRIを用いて擬似的にCPUロックフラグを実現する.
104 * まず,CPUロック状態を管理すための変数(lock_flag)を用意する.
106 * CPUロックフラグがクリアされている間は,BASEPRIをモデル上の割込み
107 * 優先度マスクの値に設定する.この間は,モデル上の割込み優先度マス
110 * それに対してCPUロックフラグがセットされいる間は,BASEPRIを,カーネ
111 * ル管理外のものを除くすべての割込み要求をマスクする値(TIPM_LOCK)と,
112 * モデル上の割込み優先度マスクとの高い方に設定する.この間のモデル上
113 * の割込み優先度マスクは,そのための変数(saved_iipm, 内部表現で保持)
118 * 割込み優先度マスクの外部表現と内部表現の変換
120 * アセンブリ言語のソースファイルからインクルードする場合のために,
122 * 割込み優先度のビット幅(TBITW_IPRI)が 8 の場合は,内部優先度 255
125 #define EXT_IPM(iipm) (CAST(PRI,((iipm >> (8 - TBITW_IPRI)) - (1 << TBITW_IPRI)))) /* 内部表現を外部表現に */
126 #define INT_IPM(ipm) (((1 << TBITW_IPRI) - CAST(uint8_t, -(ipm))) << (8 - TBITW_IPRI)) /* 外部表現を内部表現に */
129 * CPUロック状態での割込み優先度マスク
131 #define TIPM_LOCK TMIN_INTPRI
134 * CPUロック状態での割込み優先度マスクの内部表現
136 * TIPM_LOCKは,CPUロック状態でのBASEPRIの値.カーネル管理外のものを
137 * 除くすべての割込みをマスクする値に定義する.
139 #define IIPM_LOCK INT_IPM(TIPM_LOCK)
142 * TIPM_ENAALL(割込み優先度マスク全解除)の内部表現
144 * BASEPRIに '0' を設定することで,全割込みを許可する.
146 #define IIPM_ENAALL (0)
149 #ifndef TOPPERS_MACRO_ONLY
154 * これらの変数は,CPUロック状態の時のみ書き換えてもよいとする.
155 * インライン関数中で,アクセスの順序が変化しないよう,volatile を指定.
157 extern volatile bool_t lock_flag; /* CPUロックフラグの値を保持する変数 */
158 extern volatile uint32_t saved_iipm; /* 割込み優先度をマスクする変数 */
163 * BASEPRI(ハードウェアの割込み優先度マスク)を,saved_iipmに保存し,
164 * カーネル管理外のものを除くすべての割込みをマスクする値(TIPM_LOCK)
165 * に設定する.また,lock_flagをtrueにする.
167 * BASEPRIが,最初からTIPM_LOCKと同じかそれより高い場合には,それを
168 * saved_iipmに保存するのみで,TIPM_LOCKには設定しない.これは,モデル
169 * 上の割込み優先度マスクが,TIPM_LOCKと同じかそれより高いレベルに設定
172 * この関数は,CPUロック状態(lock_flagがtrueの状態)で呼ばれることは
181 * current_iipm()の返り値を直接saved_iipmに保存せず,一時変数iipm
182 * を用いているのは,current_iipm()を呼んだ直後に割込みが発生し,
183 * 起動された割込み処理でsaved_iipmが変更される可能性があるためで
186 iipm = get_basepri();
187 if ((IIPM_LOCK < iipm) || (IIPM_ENAALL == iipm)) {
188 set_basepri(IIPM_LOCK);
192 /* クリティカルセクションの前後でメモリが書き換わる可能性がある */
196 #define t_lock_cpu() x_lock_cpu()
197 #define i_lock_cpu() x_lock_cpu()
202 * lock_flagをfalseにし,IPM(ハードウェアの割込み優先度マスク)を,
203 * saved_iipmに保存した値に戻す.
205 * この関数は,CPUロック状態(lock_flagがtrueの状態)でのみ呼ばれるも
211 /* クリティカルセクションの前後でメモリが書き換わる可能性がある */
214 set_basepri(saved_iipm);
217 #define t_unlock_cpu() x_unlock_cpu()
218 #define i_unlock_cpu() x_unlock_cpu()
229 #define t_sense_lock() x_sense_lock()
230 #define i_sense_lock() x_sense_lock()
233 * chg_ipmで有効な割込み優先度の範囲の判定
235 * TMIN_INTPRIの値によらず,chg_ipmでは,-(1 << TBITW_IPRI)〜TIPM_ENAALL(=0)
236 * の範囲に設定できることとする(ターゲット定義の拡張).
237 * 割込み優先度のビット幅(TBITW_IPRI)が 8 の場合は,-256 〜 0 が指定可能である.
240 #define VALID_INTPRI_CHGIPM(intpri) \
241 ((-((1 << TBITW_IPRI) - 1) <= (intpri) && (intpri) <= TIPM_ENAALL))
244 * (モデル上の)割込み優先度マスクの設定
246 * CPUロックフラグがクリアされている時は,ハードウェアの割込み優先度マ
247 * スクを設定する.CPUロックフラグがセットされている時は,saved_iipm
248 * を設定し,さらに,ハードウェアの割込み優先度マスクを,設定しようと
249 * した(モデル上の)割込み優先度マスクとTIPM_LOCKの高い方に設定する.
252 x_set_ipm(PRI intpri)
254 uint8_t iipm = INT_IPM(intpri);
256 if (intpri == TIPM_ENAALL){
265 set_basepri(iipm < IIPM_LOCK ? iipm : IIPM_LOCK);
269 #define t_set_ipm(intpri) x_set_ipm(intpri)
270 #define i_set_ipm(intpri) x_set_ipm(intpri)
273 * (モデル上の)割込み優先度マスクの参照
275 * CPUロックフラグがクリアされている時はハードウェアの割込み優先度マ
276 * スクを,セットされている時はsaved_iipmを参照する.
284 iipm = get_basepri();
290 if (iipm == IIPM_ENAALL) {
294 return(EXT_IPM(iipm));
298 #define t_get_ipm() x_get_ipm()
299 #define i_get_ipm() x_get_ipm()
302 * SVCハンドラ(prc_support.S)
304 extern void svc_handler(void);
307 * スタートアップルーチン(start.S)
309 extern void _start(void);
312 * 最高優先順位タスクへのディスパッチ(prc_support.S)
314 * dispatchは,タスクコンテキストから呼び出されたサービスコール処理か
315 * ら呼び出すべきもので,タスクコンテキスト・CPUロック状態・ディスパッ
316 * チ許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さな
319 extern void dispatch(void);
322 * ディスパッチャの動作開始(prc_support.S)
324 * start_dispatchは,カーネル起動時に呼び出すべきもので,すべての割込
325 * みを禁止した状態(割込みロック状態と同等の状態)で呼び出さなければ
328 extern void start_dispatch(void) NoReturn;
331 * 現在のコンテキストを捨ててディスパッチ(prc_support.S)
333 * exit_and_dispatchは,ext_tskから呼び出すべきもので,タスクコンテキ
334 * スト・CPUロック状態・ディスパッチ許可状態・(モデル上の)割込み優先
335 * 度マスク全解除状態で呼び出さなければならない.
337 extern void exit_and_dispatch(void) NoReturn;
340 * カーネルの終了処理の呼出し(prc_support.S)
342 * call_exit_kernelは,カーネルの終了時に呼び出すべきもので,非タスク
343 * コンテキストに切り換えて,カーネルの終了処理(exit_kernel)を呼び出
346 extern void call_exit_kernel(void) NoReturn;
351 * タスクが休止状態から実行できる状態に移行する時に呼ばれる.この時点
354 * activate_contextを,インライン関数ではなくマクロ定義としているのは,
355 * この時点ではTCBが定義されていないためである.
357 extern void start_r(void);
359 #define activate_context(p_tcb) \
361 (p_tcb)->tskctxb.sp = (void *)((char_t *)((p_tcb)->p_tinib->stk) \
362 + (p_tcb)->p_tinib->stksz); \
363 (p_tcb)->tskctxb.pc = (void *) start_r; \
374 * 割込みハンドラ番号(inhno)と割込み番号(intno)は,割り込み発生時に
381 #define VALID_INTNO(intno) ((TMIN_INTNO <= (intno)) && ((intno) <= TMAX_INTNO))
382 #define VALID_INTNO_DISINT(intno) VALID_INTNO(intno)
383 #define VALID_INTNO_CFGINT(intno) VALID_INTNO(intno)
388 * ベクトル番号inhnoの割込みハンドラの起動番地int_entryに設定する.割込み
392 x_define_inh(INHNO inhno, FP int_entry)
398 * 割込みハンドラの出入口処理の生成マクロ
401 #define INT_ENTRY(inhno, inthdr) inthdr
402 #define INTHDR_ENTRY(inhno, inhno_num, inthdr) extern void inthdr(void);
409 * 割込み属性が設定されているかを判別するための変数(kernel_cfg.c)
411 extern const uint32_t bitpat_cfgint[];
416 * 割込み属性が設定されていない割込み要求ラインに対して割込み要求禁止
417 * フラグをクリアしようとした場合には,falseを返す.
420 x_disable_int(INTNO intno)
427 if ((bitpat_cfgint[intno >> 5] & (1 << (intno & 0x1f))) == 0x00) {
431 if (intno == IRQNO_SYSTICK) {
432 tmp = sil_rew_mem((void *)SYSTIC_CONTROL_STATUS);
433 tmp &= ~SYSTIC_TICINT;
434 sil_wrw_mem((void *)SYSTIC_CONTROL_STATUS, tmp);
437 sil_wrw_mem((void *)NVIC_CLRENA0 + (tmp >> 5), (1 << (tmp & 0x1f)));
443 #define t_disable_int(intno) x_disable_int(intno)
444 #define i_disable_int(intno) x_disable_int(intno)
449 * 割込み属性が設定されていない割込み要求ラインに対して割込み要求禁止
450 * フラグをクリアしようとした場合には,falseを返す.
453 x_enable_int(INTNO intno)
460 if ((bitpat_cfgint[intno >> 5] & (1 << (intno & 0x1f))) == 0x00) {
464 if (intno == IRQNO_SYSTICK) {
465 tmp = sil_rew_mem((void *)SYSTIC_CONTROL_STATUS);
466 tmp |= SYSTIC_TICINT;
467 sil_wrw_mem((void *)SYSTIC_CONTROL_STATUS, tmp);
470 sil_wrw_mem((void *)((uint32_t *)NVIC_SETENA0 + (tmp >> 5)),
471 (1 << (tmp & 0x1f)));
477 #define t_enable_int(intno) x_enable_int(intno)
478 #define i_enable_int(intno) x_enable_int(intno)
483 extern void x_config_int(INTNO intno, ATR intatr, PRI intpri);
489 i_begin_int(INTNO intno)
494 * 割込みハンドラの出口で必要なIRC操作
497 i_end_int(INTNO intno)
508 #define VALID_EXCNO_DEFEXC(excno) (TMIN_EXCNO <= (excno) && (excno) <= TMAX_EXCNO)
513 extern void enable_exc(EXCNO excno);
518 extern void disable_exc(EXCNO excno);
524 x_define_exc(EXCNO excno, FP exc_entry)
533 * CPU例外ハンドラの入口処理の生成マクロ
535 #define EXC_ENTRY(excno, exchdr) exchdr
536 #define EXCHDR_ENTRY(excno, excno_num, exchdr) extern void exchdr(void *p_excinf);
539 * CPU例外の発生した時のコンテキストの参照
541 * CPU例外の発生した時のコンテキストが,タスクコンテキストの時にfalse,
545 exc_sense_context(void *p_excinf)
549 exc_return = *((uint32_t *)p_excinf + P_EXCINF_OFFSET_EXC_RETURN);
550 if ((exc_return & EXC_RETURN_PSP) == EXC_RETURN_PSP){
559 * CPU例外の発生した時のIPM(ハードウェアの割込み優先度マスク,内部表
563 exc_get_iipm(void *p_excinf)
565 return(*((uint32_t *)p_excinf + P_EXCINF_OFFSET_BASEPRI));
569 * CPU例外の発生した時のコンテキストと割込みのマスク状態の参照
571 * CPU例外の発生した時のシステム状態が,カーネル実行中でなく,タスクコ
572 * ンテキストであり,割込みロック状態でなく,CPUロック状態でなく,(モ
573 * デル上の)割込み優先度マスク全解除状態である時にtrue,そうでない時
574 * にfalseを返す(CPU例外がカーネル管理外の割込み処理中で発生した場合
577 * PU例外の発生した時のBASEPRI(ハードウェアの割込み優先度マスク)
578 * がすべての割込みを許可する状態であることをチェックすることで,カー
579 * ネル実行中でないこと,割込みロック状態でないこと,CPUロック状態でな
580 * いこと,(モデル上の)割込み優先度マスク全解除状態であることの4つの
581 * 条件をチェックすることができる(CPU例外が発生した時のlock_flagを参
585 exc_sense_intmask(void *p_excinf)
587 return(!exc_sense_context(p_excinf)
588 && (exc_get_iipm(p_excinf) == IIPM_ENAALL));
592 * CPU例外の発生した時のコンテキストと割込み/CPUロック状態の参照
594 * CPU例外の発生した時のシステム状態が,カーネル実行中でなく,タスクコ
595 * ンテキストであり,割込みロック状態でなく,CPUロック状態でない時に
596 * true,そうでない時にfalseを返す(CPU例外がカーネル管理外の割込み処
597 * 理中で発生した場合にもfalseを返す).
599 * CPU例外の発生した時のBASEPRI(ハードウェアの割込み優先度マ
600 * スク)がTIPM_LOCKより低いことをチェックすることで,カーネル実行中で
601 * ないこと,割込みロック状態でないこと,CPUロック状態でないことの3つ
602 * の条件をチェックしている(CPU例外が発生した時のlock_flagは参照して
603 * いない).これにより,(モデル上の)割込み優先度マスクをTIPM_LOCK以
604 * 上に設定してタスクを実行している時にもfalseが返ってしまうが,判断を
605 * 正確にするためのオーバヘッドが大きいことから,許容することにする.
608 exc_sense_unlock(void *p_excinf)
610 return(!exc_sense_context(p_excinf)
611 && ((exc_get_iipm(p_excinf) > IIPM_LOCK)
612 || exc_get_iipm(p_excinf) == IIPM_ENAALL));
616 * CPU例外エントリ(prc_support.S)
618 extern void exc_entry(void);
621 * 割込みエントリ(prc_support.S)
623 extern void int_entry(void);
628 extern void prc_initialize(void);
633 extern void prc_terminate(void);
636 * atexitの処理とデストラクタの実行
641 extern void software_term_hook(void);
642 void (*volatile fp)(void) = software_term_hook;
645 * software_term_hookへのポインタを,一旦volatile指定のあるfpに代
646 * 入してから使うのは,0との比較が最適化で削除されないようにするた
655 * 登録されていない例外が発生すると呼び出される
657 extern void default_exc_handler(void *p_excinf);
660 * 未登録の割込みが発生した場合に呼び出される
662 extern void default_int_handler(void *p_excinf);
664 #endif /* TOPPERS_MACRO_ONLY */
665 #endif /* TOPPERS_PRC_CONFIG_H */