OSDN Git Service

12cbf776fb939474b01ce320000fc3eaa85ee265
[toppersasp4lpc/asp.git] / asp / arch / arm_m_gcc / prc_config.h
1 /*
2  *  TOPPERS/ASP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Advanced Standard Profile Kernel
5  * 
6  *  Copyright (C) 2008 by Embedded and Real-Time Systems Laboratory
7  *              Graduate School of Information Science, Nagoya Univ., JAPAN
8  * 
9  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
10  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
12  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14  *      スコード中に含まれていること.
15  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18  *      の無保証規定を掲載すること.
19  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
21  *      と.
22  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
23  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
24  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
25  *        報告すること.
26  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
27  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
28  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
29  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
30  *      免責すること.
31  * 
32  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
33  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
34  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
35  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
36  *  の責任を負わない.
37  * 
38  *  @(#) $Id: prc_config.h 1304 2008-08-27 07:28:36Z ertl-honda $
39  */
40
41 /*
42  *              プロセッサ依存モジュール(ARM-M用)
43  *
44  *  このインクルードファイルは,target_config.h(または,そこからインク
45  *  ルードされるファイル)のみからインクルードされる.他のファイルから
46  *  直接インクルードしてはならない.
47  */
48
49 #ifndef TOPPERS_PRC_CONFIG_H
50 #define TOPPERS_PRC_CONFIG_H
51
52 #ifndef TOPPERS_MACRO_ONLY
53
54 /*
55  *  プロセッサの特殊命令のインライン関数定義
56  */
57 #include "prc_insn.h"
58
59 /*
60  *  非タスクコンテキスト用のスタック初期値
61  */
62 #define TOPPERS_ISTKPT(istk, istksz) ((STK_T *)((istk) + (istksz)/(sizeof(STK_T))))
63
64 /*
65  *  タスクコンテキストブロックの定義
66  */
67 typedef struct task_context_block {
68         void    *sp;            /* スタックポインタ */
69         FP              pc;                     /* プログラムカウンタ */
70 } TSKCTXB;
71
72 #endif /* TOPPERS_MACRO_ONLY */
73
74 #ifndef TOPPERS_MACRO_ONLY
75 /*
76  *  コンテキストの参照
77  *
78  */
79 Inline bool_t
80 sense_context(void)
81 {
82         /*
83          *  PSPが有効ならタスクコンテキスト,MSPが有効なら非タスクコンテキスト
84          *  とする. 
85          */
86         if ((get_control() & CONTROL_PSP) == CONTROL_PSP){
87                 return false;
88         }
89         else {
90                 return true;
91         }
92 }
93
94 #endif /* TOPPERS_MACRO_ONLY */
95
96 /*
97  *  TOPPERS標準割込み処理モデルの実現
98  *
99  *  割込み優先度マスクとしては,BASEPRIを用いる.全割込みを禁止する
100  *  機能として,FAULTMASKやPRIMASKがあるが,カーネル管理外の割込みを
101  *  サポートするため,これらはCPUロックのために用いない.
102  *  そのため,BASEPRIを用いて擬似的にCPUロックフラグを実現する.
103  *
104  *  まず,CPUロック状態を管理すための変数(lock_flag)を用意する.
105  *
106  *  CPUロックフラグがクリアされている間は,BASEPRIをモデル上の割込み
107  *  優先度マスクの値に設定する.この間は,モデル上の割込み優先度マス
108  *  クは,BASEPRIを用いる.
109  * 
110  *  それに対してCPUロックフラグがセットされいる間は,BASEPRIを,カーネ
111  *  ル管理外のものを除くすべての割込み要求をマスクする値(TIPM_LOCK)と,
112  *  モデル上の割込み優先度マスクとの高い方に設定する.この間のモデル上
113  *  の割込み優先度マスクは,そのための変数(saved_iipm, 内部表現で保持)
114  *  を用意して保持する.
115  */
116
117 /*
118  *  割込み優先度マスクの外部表現と内部表現の変換
119  *
120  *  アセンブリ言語のソースファイルからインクルードする場合のために,
121  *  CASTを使用
122  *  割込み優先度のビット幅(TBITW_IPRI)が 8 の場合は,内部優先度 255
123  *  は,外部優先度 -1 に対応する.
124  */
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)) /* 外部表現を内部表現に */
127
128 /*
129  *  CPUロック状態での割込み優先度マスク
130  */
131 #define TIPM_LOCK    TMIN_INTPRI
132
133 /*
134  *  CPUロック状態での割込み優先度マスクの内部表現
135  *
136  *  TIPM_LOCKは,CPUロック状態でのBASEPRIの値.カーネル管理外のものを
137  *  除くすべての割込みをマスクする値に定義する.  
138  */
139 #define IIPM_LOCK    INT_IPM(TIPM_LOCK)
140
141 /*
142  *  TIPM_ENAALL(割込み優先度マスク全解除)の内部表現
143  *
144  *  BASEPRIに '0' を設定することで,全割込みを許可する.
145  */
146 #define IIPM_ENAALL  (0)
147
148
149 #ifndef TOPPERS_MACRO_ONLY
150
151 /*
152  *  CPUロックフラグ実現のための変数
153  * 
154  *  これらの変数は,CPUロック状態の時のみ書き換えてもよいとする.
155  *  インライン関数中で,アクセスの順序が変化しないよう,volatile を指定. 
156  */
157 extern volatile bool_t  lock_flag;    /* CPUロックフラグの値を保持する変数 */
158 extern volatile uint32_t saved_iipm;  /* 割込み優先度をマスクする変数 */
159
160 /*
161  *  CPUロック状態への移行
162  *
163  *  BASEPRI(ハードウェアの割込み優先度マスク)を,saved_iipmに保存し,
164  *  カーネル管理外のものを除くすべての割込みをマスクする値(TIPM_LOCK)
165  *  に設定する.また,lock_flagをtrueにする.
166  *
167  *  BASEPRIが,最初からTIPM_LOCKと同じかそれより高い場合には,それを
168  *  saved_iipmに保存するのみで,TIPM_LOCKには設定しない.これは,モデル
169  *  上の割込み優先度マスクが,TIPM_LOCKと同じかそれより高いレベルに設定
170  *  されている状態にあたる.
171  *
172  *  この関数は,CPUロック状態(lock_flagがtrueの状態)で呼ばれることは
173  *  ないものと想定している.
174  */
175 Inline void
176 x_lock_cpu(void)
177 {
178         uint32_t iipm;
179
180         /*
181          *  current_iipm()の返り値を直接saved_iipmに保存せず,一時変数iipm
182          *  を用いているのは,current_iipm()を呼んだ直後に割込みが発生し,
183          *  起動された割込み処理でsaved_iipmが変更される可能性があるためで
184          *  ある.
185          */
186         iipm = get_basepri();
187         if ((IIPM_LOCK < iipm) || (IIPM_ENAALL == iipm)) {
188                 set_basepri(IIPM_LOCK);
189         }
190         saved_iipm = iipm;
191         lock_flag = true;
192         /* クリティカルセクションの前後でメモリが書き換わる可能性がある */
193         Asm("":::"memory");
194 }
195
196 #define t_lock_cpu()    x_lock_cpu()
197 #define i_lock_cpu()    x_lock_cpu()
198
199 /*
200  *  CPUロック状態の解除
201  *
202  *  lock_flagをfalseにし,IPM(ハードウェアの割込み優先度マスク)を,
203  *  saved_iipmに保存した値に戻す.
204  *
205  *  この関数は,CPUロック状態(lock_flagがtrueの状態)でのみ呼ばれるも
206  *  のと想定している.
207  */
208 Inline void
209 x_unlock_cpu(void)
210 {
211         /* クリティカルセクションの前後でメモリが書き換わる可能性がある */
212         Asm("":::"memory");
213         lock_flag = false;
214         set_basepri(saved_iipm);
215 }
216
217 #define t_unlock_cpu()    x_unlock_cpu()
218 #define i_unlock_cpu()    x_unlock_cpu()
219
220 /*
221  *  CPUロック状態の参照
222  */
223 Inline bool_t
224 x_sense_lock(void)
225 {
226         return(lock_flag);
227 }
228
229 #define t_sense_lock()    x_sense_lock()
230 #define i_sense_lock()    x_sense_lock()
231
232 /*
233  *  chg_ipmで有効な割込み優先度の範囲の判定
234  *
235  *  TMIN_INTPRIの値によらず,chg_ipmでは,-(1 << TBITW_IPRI)〜TIPM_ENAALL(=0)
236  *  の範囲に設定できることとする(ターゲット定義の拡張).
237  *  割込み優先度のビット幅(TBITW_IPRI)が 8 の場合は,-256 〜 0 が指定可能である.
238  *   
239  */
240 #define VALID_INTPRI_CHGIPM(intpri) \
241                                 ((-((1 << TBITW_IPRI) - 1) <= (intpri) && (intpri) <= TIPM_ENAALL))
242
243 /*
244  * (モデル上の)割込み優先度マスクの設定
245  *
246  *  CPUロックフラグがクリアされている時は,ハードウェアの割込み優先度マ
247  *  スクを設定する.CPUロックフラグがセットされている時は,saved_iipm
248  *  を設定し,さらに,ハードウェアの割込み優先度マスクを,設定しようと
249  *  した(モデル上の)割込み優先度マスクとTIPM_LOCKの高い方に設定する.
250  */
251 Inline void
252 x_set_ipm(PRI intpri)
253 {
254         uint8_t   iipm = INT_IPM(intpri);
255
256         if (intpri == TIPM_ENAALL){
257                 iipm = IIPM_ENAALL;
258         }
259
260         if (!lock_flag) {
261                 set_basepri(iipm);
262         }
263         else {
264                 saved_iipm = iipm;
265                 set_basepri(iipm < IIPM_LOCK ? iipm : IIPM_LOCK);
266         }
267 }
268
269 #define t_set_ipm(intpri)    x_set_ipm(intpri)
270 #define i_set_ipm(intpri)    x_set_ipm(intpri)
271
272 /*
273  * (モデル上の)割込み優先度マスクの参照
274  *
275  *  CPUロックフラグがクリアされている時はハードウェアの割込み優先度マ
276  *  スクを,セットされている時はsaved_iipmを参照する.
277  */
278 Inline PRI
279 x_get_ipm(void)
280 {
281         uint8_t iipm;
282
283         if (!lock_flag) {
284                 iipm = get_basepri();
285         }
286         else {
287                 iipm = saved_iipm;
288         }
289
290         if (iipm == IIPM_ENAALL) {
291                 return(TIPM_ENAALL);
292         }
293         else {
294                 return(EXT_IPM(iipm));
295         }
296 }
297
298 #define t_get_ipm()    x_get_ipm()
299 #define i_get_ipm()    x_get_ipm()
300
301 /*
302  *  SVCハンドラ(prc_support.S)
303  */
304 extern void svc_handler(void);
305
306 /*
307  *  スタートアップルーチン(start.S)
308  */
309 extern void _start(void);
310
311 /*
312  *  最高優先順位タスクへのディスパッチ(prc_support.S)
313  *
314  *  dispatchは,タスクコンテキストから呼び出されたサービスコール処理か
315  *  ら呼び出すべきもので,タスクコンテキスト・CPUロック状態・ディスパッ
316  *  チ許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さな
317  *  ければならない.
318  */
319 extern void dispatch(void);
320
321 /*
322  *  ディスパッチャの動作開始(prc_support.S)
323  *
324  *  start_dispatchは,カーネル起動時に呼び出すべきもので,すべての割込
325  *  みを禁止した状態(割込みロック状態と同等の状態)で呼び出さなければ
326  *  ならない.
327  */
328 extern void start_dispatch(void) NoReturn;
329
330 /*
331  *  現在のコンテキストを捨ててディスパッチ(prc_support.S)
332  *
333  *  exit_and_dispatchは,ext_tskから呼び出すべきもので,タスクコンテキ
334  *  スト・CPUロック状態・ディスパッチ許可状態・(モデル上の)割込み優先
335  *  度マスク全解除状態で呼び出さなければならない.
336  */
337 extern void exit_and_dispatch(void) NoReturn;
338
339 /*
340  *  カーネルの終了処理の呼出し(prc_support.S)
341  *
342  *  call_exit_kernelは,カーネルの終了時に呼び出すべきもので,非タスク
343  *  コンテキストに切り換えて,カーネルの終了処理(exit_kernel)を呼び出
344  *  す.
345  */
346 extern void call_exit_kernel(void) NoReturn;
347
348 /*
349  *  タスクコンテキストの初期化
350  *
351  *  タスクが休止状態から実行できる状態に移行する時に呼ばれる.この時点
352  *  でスタック領域を使ってはならない.
353  *
354  *  activate_contextを,インライン関数ではなくマクロ定義としているのは,
355  *  この時点ではTCBが定義されていないためである.
356  */
357 extern void    start_r(void);
358
359 #define activate_context(p_tcb)                                         \
360 {                                                                       \
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;                             \
364 }
365
366 /*
367  *  calltexは使用しない
368  */
369 #define OMIT_CALLTEX
370
371 /*
372  *  割込み番号・割込みハンドラ番号
373  *
374  *  割込みハンドラ番号(inhno)と割込み番号(intno)は,割り込み発生時に
375  *  EPSRに設定される例外番号とする. 
376  */
377
378 /*
379  *  割込み番号の範囲の判定
380  */
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)
384
385 /*
386  *  割込みハンドラの設定
387  *
388  *  ベクトル番号inhnoの割込みハンドラの起動番地int_entryに設定する.割込み
389  *  ハンドラテーブル
390  */
391 Inline void
392 x_define_inh(INHNO inhno, FP int_entry)
393 {
394
395 }
396
397 /*
398  *  割込みハンドラの出入口処理の生成マクロ
399  *
400  */
401 #define INT_ENTRY(inhno, inthdr)    inthdr
402 #define INTHDR_ENTRY(inhno, inhno_num, inthdr) extern void inthdr(void);
403
404 /*
405  *  割込み要求禁止フラグ
406  */
407
408 /*
409  *  割込み属性が設定されているかを判別するための変数(kernel_cfg.c)
410  */
411 extern const uint32_t   bitpat_cfgint[];
412
413 /*
414  *  割込み要求禁止フラグのセット
415  *
416  *  割込み属性が設定されていない割込み要求ラインに対して割込み要求禁止
417  *  フラグをクリアしようとした場合には,falseを返す.  
418  */
419 Inline bool_t
420 x_disable_int(INTNO intno)
421 {
422         uint32_t tmp;
423
424         /*
425          *  割込み属性が設定されていない場合
426          */
427         if ((bitpat_cfgint[intno >> 5] & (1 << (intno & 0x1f))) == 0x00) {
428                 return(false);
429         }
430
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);
435         }else {
436                 tmp = intno - 16;
437                 sil_wrw_mem((void *)NVIC_CLRENA0 + (tmp >> 5), (1 << (tmp & 0x1f)));
438         }
439
440         return(true);
441 }
442
443 #define t_disable_int(intno) x_disable_int(intno)
444 #define i_disable_int(intno) x_disable_int(intno)
445
446 /*
447  *  割込み要求禁止フラグの解除
448  *
449  *  割込み属性が設定されていない割込み要求ラインに対して割込み要求禁止
450  *  フラグをクリアしようとした場合には,falseを返す.
451  */
452 Inline bool_t
453 x_enable_int(INTNO intno)
454 {
455         uint32_t tmp;
456
457         /*
458          *  割込み属性が設定されていない場合
459          */
460         if ((bitpat_cfgint[intno >> 5] & (1 << (intno & 0x1f))) == 0x00) {
461                 return(false);
462         }
463
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);
468         }else {
469                 tmp = intno - 16;
470                 sil_wrw_mem((void *)((uint32_t *)NVIC_SETENA0 + (tmp >> 5)),
471                                         (1 << (tmp & 0x1f)));
472         }
473     
474         return(true);
475 }
476
477 #define t_enable_int(intno) x_enable_int(intno)
478 #define i_enable_int(intno) x_enable_int(intno)
479
480 /*
481  *  割込み要求ラインの属性の設定
482  */
483 extern void x_config_int(INTNO intno, ATR intatr, PRI intpri);
484
485 /*
486  *  割込みハンドラ入口で必要なIRC操作
487  */
488 Inline void
489 i_begin_int(INTNO intno)
490 {
491 }
492
493 /*
494  *  割込みハンドラの出口で必要なIRC操作
495  */
496 Inline void
497 i_end_int(INTNO intno)
498 {
499 }
500
501 /*
502  *  CPU例外ハンドラ関係
503  */ 
504
505 /*
506  *  CPU例外ハンドラ番号
507  */
508 #define VALID_EXCNO_DEFEXC(excno)    (TMIN_EXCNO <= (excno) && (excno) <= TMAX_EXCNO)
509
510 /*
511  *  CPU例外ハンドラの許可
512  */
513 extern void enable_exc(EXCNO excno);
514
515 /*
516  *  CPU例外ハンドラの禁止
517  */
518 extern void disable_exc(EXCNO excno);
519
520 /*
521  *  CPU例外ハンドラの設定
522  */
523 Inline void
524 x_define_exc(EXCNO excno, FP exc_entry)
525 {
526         /*
527          *  一部の例外は許可を行う必要がある
528          */
529         enable_exc(excno);
530 }
531
532 /*
533  *  CPU例外ハンドラの入口処理の生成マクロ
534  */
535 #define EXC_ENTRY(excno, exchdr)    exchdr
536 #define EXCHDR_ENTRY(excno, excno_num, exchdr) extern void exchdr(void *p_excinf);
537
538 /*
539  *  CPU例外の発生した時のコンテキストの参照
540  *
541  *  CPU例外の発生した時のコンテキストが,タスクコンテキストの時にfalse,
542  *  そうでない時にtrueを返す.
543  */
544 Inline bool_t
545 exc_sense_context(void *p_excinf)
546 {
547         uint32_t exc_return;
548
549         exc_return = *((uint32_t *)p_excinf + P_EXCINF_OFFSET_EXC_RETURN);
550         if ((exc_return & EXC_RETURN_PSP) == EXC_RETURN_PSP){
551                 return false;
552         }
553         else {
554                 return true;
555         }
556 }
557
558 /*
559  *  CPU例外の発生した時のIPM(ハードウェアの割込み優先度マスク,内部表
560  *  現)の参照
561  */
562 Inline uint32_t
563 exc_get_iipm(void *p_excinf)
564 {
565         return(*((uint32_t *)p_excinf + P_EXCINF_OFFSET_BASEPRI));
566 }
567
568 /*
569  *  CPU例外の発生した時のコンテキストと割込みのマスク状態の参照
570  *
571  *  CPU例外の発生した時のシステム状態が,カーネル実行中でなく,タスクコ
572  *  ンテキストであり,割込みロック状態でなく,CPUロック状態でなく,(モ
573  *  デル上の)割込み優先度マスク全解除状態である時にtrue,そうでない時
574  *  にfalseを返す(CPU例外がカーネル管理外の割込み処理中で発生した場合
575  *  にもfalseを返す).
576  *
577  *  PU例外の発生した時のBASEPRI(ハードウェアの割込み優先度マスク)
578  *  がすべての割込みを許可する状態であることをチェックすることで,カー
579  *  ネル実行中でないこと,割込みロック状態でないこと,CPUロック状態でな
580  *  いこと,(モデル上の)割込み優先度マスク全解除状態であることの4つの
581  *  条件をチェックすることができる(CPU例外が発生した時のlock_flagを参
582  *  照する必要はない).
583  */
584 Inline bool_t
585 exc_sense_intmask(void *p_excinf)
586 {
587         return(!exc_sense_context(p_excinf)
588                    && (exc_get_iipm(p_excinf) == IIPM_ENAALL));
589 }
590
591 /*
592  *  CPU例外の発生した時のコンテキストと割込み/CPUロック状態の参照
593  *
594  *  CPU例外の発生した時のシステム状態が,カーネル実行中でなく,タスクコ
595  *  ンテキストであり,割込みロック状態でなく,CPUロック状態でない時に
596  *  true,そうでない時にfalseを返す(CPU例外がカーネル管理外の割込み処
597  *  理中で発生した場合にもfalseを返す).
598  *
599  *  CPU例外の発生した時のBASEPRI(ハードウェアの割込み優先度マ
600  *  スク)がTIPM_LOCKより低いことをチェックすることで,カーネル実行中で
601  *  ないこと,割込みロック状態でないこと,CPUロック状態でないことの3つ
602  *  の条件をチェックしている(CPU例外が発生した時のlock_flagは参照して
603  *  いない).これにより,(モデル上の)割込み優先度マスクをTIPM_LOCK以
604  *  上に設定してタスクを実行している時にもfalseが返ってしまうが,判断を
605  *  正確にするためのオーバヘッドが大きいことから,許容することにする.
606  */
607 Inline bool_t
608 exc_sense_unlock(void *p_excinf)
609 {
610         return(!exc_sense_context(p_excinf)
611                    && ((exc_get_iipm(p_excinf) > IIPM_LOCK)
612                            || exc_get_iipm(p_excinf) == IIPM_ENAALL));
613 }
614
615 /*
616  *  CPU例外エントリ(prc_support.S)
617  */
618 extern void exc_entry(void);
619
620 /*
621  *  割込みエントリ(prc_support.S)
622  */
623 extern void int_entry(void);
624
625 /*
626  *  プロセッサ依存の初期化
627  */
628 extern void prc_initialize(void);
629
630 /*
631  *  プロセッサ依存の終了時処理
632  */
633 extern void prc_terminate(void);
634
635 /*
636  *  atexitの処理とデストラクタの実行
637  */
638 Inline void
639 call_atexit(void)
640 {
641         extern void    software_term_hook(void);
642         void (*volatile fp)(void) = software_term_hook;
643
644         /*
645          *  software_term_hookへのポインタを,一旦volatile指定のあるfpに代
646          *  入してから使うのは,0との比較が最適化で削除されないようにするた
647          *  めである.
648          */
649         if (fp != 0) {
650                 (*fp)();
651         }
652 }
653
654 /*
655  * 登録されていない例外が発生すると呼び出される
656  */
657 extern void default_exc_handler(void *p_excinf);
658
659 /*
660  * 未登録の割込みが発生した場合に呼び出される
661  */
662 extern void default_int_handler(void *p_excinf);
663
664 #endif /* TOPPERS_MACRO_ONLY */
665 #endif /* TOPPERS_PRC_CONFIG_H */