3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
6 * Copyright (C) 2008-2011 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: core_config.h 2198 2011-07-25 16:57:14Z ertl-honda $
42 * プロセッサ依存モジュール(ARM-M用)
44 * このインクルードファイルは,target_config.h(または,そこからインク
45 * ルードされるファイル)のみからインクルードされる.他のファイルから
49 #ifndef TOPPERS_CORE_CONFIG_H
50 #define TOPPERS_CORE_CONFIG_H
52 #ifndef TOPPERS_MACRO_ONLY
55 * プロセッサの特殊命令のインライン関数定義
57 #include "core_insn.h"
62 #define TARGET_INHATR TA_NONKERNEL /* ターゲット定義の割込みハンドラ属性 */
67 #define CHECK_STKSZ_ALIGN 8 /* スタックサイズのアライン単位 */
68 #define CHECK_FUNC_ALIGN 1 /* 関数のアライン単位 */
69 #define CHECK_FUNC_NONNULL /* 関数の非NULLチェック */
70 #define CHECK_STACK_ALIGN 8 /* スタック領域のアライン単位 */
71 #define CHECK_STACK_NONNULL /* スタック領域の非NULLチェック */
72 #define CHECK_MPF_ALIGN 4 /* 固定長メモリプール領域のアライン単位 */
73 #define CHECK_MPF_NONNULL /* 固定長メモリプール領域の非NULLチェック */
74 #define CHECK_MB_ALIGN 4 /* 管理領域のアライン単位 */
79 #define TOPPERS_ISTKPT(istk, istksz) ((STK_T *)((char_t *)(istk) + (istksz)))
84 typedef struct task_context_block {
85 void *sp; /* スタックポインタ */
86 FP pc; /* プログラムカウンタ */
89 #endif /* TOPPERS_MACRO_ONLY */
91 #ifndef TOPPERS_MACRO_ONLY
100 * PSPが有効ならタスクコンテキスト,MSPが有効なら非タスクコンテキスト
103 if ((get_control() & CONTROL_PSP) == CONTROL_PSP){
111 #endif /* TOPPERS_MACRO_ONLY */
114 * TOPPERS標準割込み処理モデルの実現
116 * 割込み優先度マスクとしては,BASEPRIを用いる.全割込みを禁止する
117 * 機能として,FAULTMASKやPRIMASKがあるが,カーネル管理外の割込みを
118 * サポートするため,これらはCPUロックのために用いない.
119 * そのため,BASEPRIを用いて擬似的にCPUロックフラグを実現する.
121 * まず,CPUロック状態を管理すための変数(lock_flag)を用意する.
123 * CPUロックフラグがクリアされている間は,BASEPRIをモデル上の割込み
124 * 優先度マスクの値に設定する.この間は,モデル上の割込み優先度マス
127 * それに対してCPUロックフラグがセットされいる間は,BASEPRIを,カーネ
128 * ル管理外のものを除くすべての割込み要求をマスクする値(TIPM_LOCK)と,
129 * モデル上の割込み優先度マスクとの高い方に設定する.この間のモデル上
130 * の割込み優先度マスクは,そのための変数(saved_iipm, 内部表現で保持)
135 * 割込み優先度マスクの外部表現と内部表現の変換
137 * アセンブリ言語のソースファイルからインクルードする場合のために,
139 * 割込み優先度のビット幅(TBITW_IPRI)が 8 の場合は,内部優先度 255
142 #define EXT_IPM(iipm) (CAST(PRI,((iipm >> (8 - TBITW_IPRI)) - (1 << TBITW_IPRI)))) /* 内部表現を外部表現に */
143 #define INT_IPM(ipm) (((1 << TBITW_IPRI) - CAST(uint8_t, -(ipm))) << (8 - TBITW_IPRI)) /* 外部表現を内部表現に */
146 * CPUロック状態での割込み優先度マスク
148 #define TIPM_LOCK TMIN_INTPRI
151 * CPUロック状態での割込み優先度マスクの内部表現
153 * TIPM_LOCKは,CPUロック状態でのBASEPRIの値.カーネル管理外のものを
154 * 除くすべての割込みをマスクする値に定義する.
156 #define IIPM_LOCK INT_IPM(TIPM_LOCK)
159 * TIPM_ENAALL(割込み優先度マスク全解除)の内部表現
161 * BASEPRIに '0' を設定することで,全割込みを許可する.
163 #define IIPM_ENAALL (0)
166 #ifndef TOPPERS_MACRO_ONLY
171 * これらの変数は,CPUロック状態の時のみ書き換えてもよいとする.
172 * インライン関数中で,アクセスの順序が変化しないよう,volatile を指定.
174 extern volatile bool_t lock_flag; /* CPUロックフラグの値を保持する変数 */
175 extern volatile uint32_t saved_iipm; /* 割込み優先度をマスクする変数 */
180 * BASEPRI(ハードウェアの割込み優先度マスク)を,saved_iipmに保存し,
181 * カーネル管理外のものを除くすべての割込みをマスクする値(TIPM_LOCK)
182 * に設定する.また,lock_flagをtrueにする.
184 * BASEPRIが,最初からTIPM_LOCKと同じかそれより高い場合には,それを
185 * saved_iipmに保存するのみで,TIPM_LOCKには設定しない.これは,モデル
186 * 上の割込み優先度マスクが,TIPM_LOCKと同じかそれより高いレベルに設定
189 * この関数は,CPUロック状態(lock_flagがtrueの状態)で呼ばれることは
198 * get_basepri()の返り値を直接saved_iipmに保存せず,一時変数iipm
199 * を用いているのは,get_baespri()を呼んだ直後に割込みが発生し,
200 * 起動された割込み処理でsaved_iipmが変更される可能性があるためで
203 iipm = get_basepri();
205 * BASEPRIレジスタは値が小さいほど優先度が高いが,IIPM_ENAALL が
206 * '0'であるため,単純に優先度比較だけでは不十分である.
208 if ((IIPM_LOCK < iipm) || (IIPM_ENAALL == iipm)) {
209 set_basepri(IIPM_LOCK);
213 /* クリティカルセクションの前後でメモリが書き換わる可能性がある */
217 #define t_lock_cpu() x_lock_cpu()
218 #define i_lock_cpu() x_lock_cpu()
223 * lock_flagをfalseにし,IPM(ハードウェアの割込み優先度マスク)を,
224 * saved_iipmに保存した値に戻す.
226 * この関数は,CPUロック状態(lock_flagがtrueの状態)でのみ呼ばれるも
232 /* クリティカルセクションの前後でメモリが書き換わる可能性がある */
235 set_basepri(saved_iipm);
238 #define t_unlock_cpu() x_unlock_cpu()
239 #define i_unlock_cpu() x_unlock_cpu()
250 #define t_sense_lock() x_sense_lock()
251 #define i_sense_lock() x_sense_lock()
254 * chg_ipmで有効な割込み優先度の範囲の判定
256 * TMIN_INTPRIの値によらず,chg_ipmでは,-(1 << TBITW_IPRI)〜TIPM_ENAALL(=0)
257 * の範囲に設定できることとする(ターゲット定義の拡張).
258 * 割込み優先度のビット幅(TBITW_IPRI)が 8 の場合は,-256 〜 0 が指定可能である.
261 #define VALID_INTPRI_CHGIPM(intpri) \
262 ((-((1 << TBITW_IPRI) - 1) <= (intpri) && (intpri) <= TIPM_ENAALL))
265 * (モデル上の)割込み優先度マスクの設定
267 * CPUロックフラグがクリアされている時は,ハードウェアの割込み優先度マ
268 * スクを設定する.CPUロックフラグがセットされている時は,saved_iipm
269 * を設定し,さらに,ハードウェアの割込み優先度マスクを,設定しようと
270 * した(モデル上の)割込み優先度マスクとTIPM_LOCKの高い方に設定する.
273 x_set_ipm(PRI intpri)
275 uint8_t iipm = INT_IPM(intpri);
277 if (intpri == TIPM_ENAALL){
286 set_basepri(iipm < IIPM_LOCK ? iipm : IIPM_LOCK);
290 #define t_set_ipm(intpri) x_set_ipm(intpri)
291 #define i_set_ipm(intpri) x_set_ipm(intpri)
294 * (モデル上の)割込み優先度マスクの参照
296 * CPUロックフラグがクリアされている時はハードウェアの割込み優先度マ
297 * スクを,セットされている時はsaved_iipmを参照する.
305 iipm = get_basepri();
311 if (iipm == IIPM_ENAALL) {
315 return(EXT_IPM(iipm));
319 #define t_get_ipm() x_get_ipm()
320 #define i_get_ipm() x_get_ipm()
323 * SVCハンドラ(core_support.S)
325 extern void svc_handler(void);
328 * スタートアップルーチン(start.S)
330 extern void _start(void);
333 * 最高優先順位タスクへのディスパッチ(core_support.S)
335 * dispatchは,タスクコンテキストから呼び出されたサービスコール処理か
336 * ら呼び出すべきもので,タスクコンテキスト・CPUロック状態・ディスパッ
337 * チ許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さな
340 extern void dispatch(void);
343 * ディスパッチャの動作開始(core_support.S)
345 * start_dispatchは,カーネル起動時に呼び出すべきもので,すべての割込
346 * みを禁止した状態(割込みロック状態と同等の状態)で呼び出さなければ
349 extern void start_dispatch(void) NoReturn;
352 * 現在のコンテキストを捨ててディスパッチ(core_support.S)
354 * exit_and_dispatchは,ext_tskから呼び出すべきもので,タスクコンテキ
355 * スト・CPUロック状態・ディスパッチ許可状態・(モデル上の)割込み優先
356 * 度マスク全解除状態で呼び出さなければならない.
358 extern void exit_and_dispatch(void) NoReturn;
361 * カーネルの終了処理の呼出し(core_support.S)
363 * call_exit_kernelは,カーネルの終了時に呼び出すべきもので,非タスク
364 * コンテキストに切り換えて,カーネルの終了処理(exit_kernel)を呼び出
367 extern void call_exit_kernel(void) NoReturn;
372 * タスクが休止状態から実行できる状態に移行する時に呼ばれる.この時点
375 * activate_contextを,インライン関数ではなくマクロ定義としているのは,
376 * この時点ではTCBが定義されていないためである.
378 extern void start_r(void);
380 #define activate_context(p_tcb) \
382 (p_tcb)->tskctxb.sp = (void *)((char_t *)((p_tcb)->p_tinib->stk) \
383 + (p_tcb)->p_tinib->stksz); \
384 (p_tcb)->tskctxb.pc = (void *) start_r; \
395 * 割込みハンドラ番号(inhno)と割込み番号(intno)は,割り込み発生時に
402 #define VALID_INTNO(intno) ((TMIN_INTNO <= (intno)) && ((intno) <= TMAX_INTNO))
403 #define VALID_INTNO_DISINT(intno) VALID_INTNO(intno)
404 #define VALID_INTNO_CFGINT(intno) VALID_INTNO(intno)
409 * ベクトル番号inhnoの割込みハンドラの起動番地int_entryに設定する.割込み
413 x_define_inh(INHNO inhno, FP int_entry)
419 * 割込みハンドラの出入口処理の生成マクロ
422 #define INT_ENTRY(inhno, inthdr) inthdr
423 #define INTHDR_ENTRY(inhno, inhno_num, inthdr) extern void inthdr(void);
430 * 割込み属性が設定されているかを判別するための変数(kernel_cfg.c)
432 extern const uint32_t bitpat_cfgint[];
437 * 割込み属性が設定されていない割込み要求ラインに対して割込み要求禁止
438 * フラグをクリアしようとした場合には,falseを返す.
441 x_disable_int(INTNO intno)
448 if ((bitpat_cfgint[intno >> 5] & (1 << (intno & 0x1f))) == 0x00) {
452 if (intno == IRQNO_SYSTICK) {
453 tmp = sil_rew_mem((void *)SYSTIC_CONTROL_STATUS);
454 tmp &= ~SYSTIC_TICINT;
455 sil_wrw_mem((void *)SYSTIC_CONTROL_STATUS, tmp);
458 sil_wrw_mem((void *)((uint32_t *)NVIC_CLRENA0 + (tmp >> 5)),
459 (1 << (tmp & 0x1f)));
465 #define t_disable_int(intno) x_disable_int(intno)
466 #define i_disable_int(intno) x_disable_int(intno)
471 * 割込み属性が設定されていない割込み要求ラインに対して割込み要求禁止
472 * フラグをクリアしようとした場合には,falseを返す.
475 x_enable_int(INTNO intno)
482 if ((bitpat_cfgint[intno >> 5] & (1 << (intno & 0x1f))) == 0x00) {
486 if (intno == IRQNO_SYSTICK) {
487 tmp = sil_rew_mem((void *)SYSTIC_CONTROL_STATUS);
488 tmp |= SYSTIC_TICINT;
489 sil_wrw_mem((void *)SYSTIC_CONTROL_STATUS, tmp);
492 sil_wrw_mem((void *)((uint32_t *)NVIC_SETENA0 + (tmp >> 5)),
493 (1 << (tmp & 0x1f)));
499 #define t_enable_int(intno) x_enable_int(intno)
500 #define i_enable_int(intno) x_enable_int(intno)
505 extern void x_config_int(INTNO intno, ATR intatr, PRI intpri);
511 i_begin_int(INTNO intno)
516 * 割込みハンドラの出口で必要なIRC操作
519 i_end_int(INTNO intno)
530 #define VALID_EXCNO_DEFEXC(excno) (TMIN_EXCNO <= (excno) && (excno) <= TMAX_EXCNO)
535 extern void enable_exc(EXCNO excno);
540 extern void disable_exc(EXCNO excno);
546 x_define_exc(EXCNO excno, FP exc_entry)
555 * CPU例外ハンドラの入口処理の生成マクロ
557 #define EXC_ENTRY(excno, exchdr) exchdr
558 #define EXCHDR_ENTRY(excno, excno_num, exchdr) extern void exchdr(void *p_excinf);
561 * CPU例外の発生した時のコンテキストの参照
563 * CPU例外の発生した時のコンテキストが,タスクコンテキストの時にfalse,
567 exc_sense_context(void *p_excinf)
571 exc_return = *((uint32_t *)p_excinf + P_EXCINF_OFFSET_EXC_RETURN);
572 if ((exc_return & EXC_RETURN_PSP) == EXC_RETURN_PSP){
581 * CPU例外の発生した時のIPM(ハードウェアの割込み優先度マスク,内部表
585 exc_get_iipm(void *p_excinf)
587 return(*((uint32_t *)p_excinf + P_EXCINF_OFFSET_BASEPRI));
591 * CPU例外の発生した時のコンテキストと割込みのマスク状態の参照
593 * CPU例外の発生した時のシステム状態が,カーネル実行中でなく,タスクコ
594 * ンテキストであり,割込みロック状態でなく,CPUロック状態でなく,(モ
595 * デル上の)割込み優先度マスク全解除状態である時にtrue,そうでない時
596 * にfalseを返す(CPU例外がカーネル管理外の割込み処理中で発生した場合
599 * PU例外の発生した時のBASEPRI(ハードウェアの割込み優先度マスク)
600 * がすべての割込みを許可する状態であることをチェックすることで,カー
601 * ネル実行中でないこと,割込みロック状態でないこと,CPUロック状態でな
602 * いこと,(モデル上の)割込み優先度マスク全解除状態であることの4つの
603 * 条件をチェックすることができる(CPU例外が発生した時のlock_flagを参
607 exc_sense_intmask(void *p_excinf)
609 return(!exc_sense_context(p_excinf)
610 && (exc_get_iipm(p_excinf) == IIPM_ENAALL));
614 * CPU例外エントリ(core_support.S)
616 extern void core_exc_entry(void);
619 * 割込みエントリ(core_support.S)
621 extern void core_int_entry(void);
626 extern void core_initialize(void);
631 extern void core_terminate(void);
634 * 登録されていない例外が発生すると呼び出される
636 extern void default_exc_handler(void *p_excinf);
639 * 未登録の割込みが発生した場合に呼び出される
641 extern void default_int_handler(void *p_excinf);
643 #endif /* TOPPERS_MACRO_ONLY */
644 #endif /* TOPPERS_CORE_CONFIG_H */