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_support.S 2202 2011-07-26 13:27:11Z ertl-honda $
42 * プロセッサ依存モジュール アセンブリ言語部(ARM-M用)
45 #define TOPPERS_MACRO_ONLY
46 #define UINT_C(val) (val) /* uint_t型の定数を作るマクロ */
47 #define ULONG_C(val) (val) /* ulong_t型の定数を作るマクロ */
48 #define CAST(type, val) (val) /* 型キャストを行うマクロ */
50 #include "kernel_impl.h"
62 .type dispatch, function
66 * このルーチンは,タスクコンテキスト・CPUロック状態・ディパッチ許可状態
67 * ・(モデル上の)割込み優先度マスク全開状態で呼び出される.
69 stmfd sp!,{r4-r11,lr} /* レジスタの保存 */
70 #if defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)
71 /* CORTEX-M4Fコア固有の処理 */
72 mrs r0, control /* CONTROL レジスタを読む */
73 tst r0, #CONTROL_FPCA /* FPコプロセッサを使用したか */
75 vstmdb sp!,{s16-s31} /* 使用したのなら保存 */
76 bic r1,r0, #CONTROL_FPCA /* タスク切り替えまで浮動小数点レジスタを使わないのでFPCAをクリア */
77 msr control, r1 /* これでディスパッチャ内部での割り込み受付は、FPレジスタを保存しない */
80 push {r0} /* FPCAビットを保存 */
81 #endif /* defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)*/
82 ldr r0, =p_runtsk /* p_runtskを読み込む */
84 str sp, [r1,#TCB_sp] /* タスクスタックを保存 */
85 ldr lr, =dispatch_r /* 実行再開番地を保存 */
92 .type dispatch_r, function
94 #if defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)
95 /* CORTEX-M4Fコア固有の処理 */
96 pop {r0} /* FPCAビットを保存 */
97 tst r0, #CONTROL_FPCA /* FPコプロセッサを使用したタスクか */
99 vldmia sp!,{s16-s31} /* 使用したのならレジスタを復帰。これでFPCAビットは1になる */
101 #endif /* defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)*/
102 ldmfd sp!,{r4 - r11,lr} /* レジスタの復帰 */
105 * dispatcherから呼び出されるため,TCBのアドレスはr1に入っている
107 ldrb r0,[r1,#TCB_enatex]
108 tst r0,#TCB_enatex_mask
109 beq dispatch_r_1 /* enatex が false ならリターン */
110 ldr r0,[r1,#TCB_texptn] /* texptn が 0 ならリターン */
113 ldr r1, =ipmflg /* ipmflgが false ならリターン */
116 bne call_texrtn /* タスク例外ルーチンの呼び出し */
117 dispatch_r_1: /* タスクへのcall_textnから戻る */
124 * 割込みエントリと処理の内容は同等だが,ログの種類が異なるため,
130 .global core_exc_entry
131 .type core_exc_entry, function
134 * 例外/割込みが発生すると,発生時にアクティブなスタックにスクラ
136 * この内容に加えて,CPU例外ハンドラへの情報として,basepri の値と,
137 * EXC_RETURNの情報を加えて保存する.basepriの値は,CPU例外からの
138 * リターン時に割込み優先度マスクの値を元に戻すためにも用いられる.
165 * 割込み発生時の割込み優先度マスクをスタックに保存するため取得
167 mrs r2, basepri /* baepriの値を取得 */
171 * カーネル内のクリティカルセクションの実行中,全割込みロック状態,
172 * CPUロック状態,カーネル管理外の割込みハンドラ実行中のいずれかで
173 * 発生したCPU例外を,カーネル管理外のCPU例外と呼ぶ
174 * CPUロック状態はbasepriがIIPM_LOCKで判断する.
175 * 全割込みロック状態はFAULTMASKが'1'の場合
177 cmp r2, #IIPM_LOCK /* CPUロック状態ならカーネル管理外例外処理へ */
178 beq core_nonkernel_exc_entry
179 mrs r2, FAULTMASK /* 全割込みロック状態ならカーネル管理外例外処理へ */
180 cbnz r2, core_nonkernel_exc_entry
183 * スタックを変更する必要があるかチェック
184 * EXC_RETURN(割込み時にLRに設定される値)をチェックして,例外発生時に
185 * アクティブなスタックを特定することで多重割込みか判定する.
187 tst lr, #EXC_RETURN_PSP /* 割込み元がMSPなら多重割込み */
188 beq core_exc_entry_1 /* 多重割込みならcore_exc_entry_1へ */
189 mrs r0, psp /* 一段目の割込みの場合はPSP上に */
190 stmfd r0!,{r2} /* 割込み発生時の割込み優先度マスクを積む */
191 stmfd r0!,{lr} /* EXC_RETURN を積む */
192 msr psp, r0 /* CPU例外ハンドラへの引数となる */
193 push {lr} /* MSP上にもEXC_RETURN を積む */
195 core_exc_entry_1: /* 多重割込みの場合 */
196 push {r2} /* 割込み発生時の割込み優先度マスクを積む */
197 push {lr} /* EXC_RETURN を積む */
198 mov r0, sp /* CPU例外ハンドラへの引数となる */
204 mrs r3, ipsr /* ハンドラアドレスを取得 */
205 ldr r1, =_kernel_exc_tbl
206 ldr r2, [r1, r3, lsl #2]
210 mov r0, r3 /* 例外番号をパラメータに */
211 bl log_exc_enter /* log_exc_enterを呼び出す */
213 push {r3} /* 例外番号をスタックへ */
214 #endif /* LOG_EXC_ENTER */
222 pop {r0} /* 例外番号を引数に */
223 bl log_exc_leave /* log_exc_leaveを呼び出す */
224 #endif /* LOG_EXC_ENTER */
229 * カーネル管理外のCPU例外の出入口処理
231 core_nonkernel_exc_entry:
232 tst lr, #EXC_RETURN_PSP /* 割込み元がMSPなら多重割込み */
233 beq core_nonkernel_exc_entry_1 /* 多重割込みなら */
234 mrs r0, psp /* 一段目の割込みの場合はPSP上に */
235 stmfd r0!,{r2} /* 割込み発生時の割込み優先度マスクを積む */
236 stmfd r0!,{lr} /* EXC_RETURN を積む */
237 msr psp, r0 /* CPU例外ハンドラへの引数となる */
238 push {lr} /* MSP上にもEXC_RETURN を積む */
239 b core_nonkernel_exc_entry_2
240 core_nonkernel_exc_entry_1: /* 多重割込みの場合 */
241 push {r2} /* 割込み発生時の割込み優先度マスクを積む */
242 push {lr} /* EXC_RETURN を積む */
243 mov r0, sp /* CPU例外ハンドラへの引数となる */
245 core_nonkernel_exc_entry_2:
246 mrs r3, ipsr /* CPU例外ハンドラのアドレスを取得 */
247 ldr r1, =_kernel_exc_tbl
248 ldr r2, [r1, r3, lsl #2]
263 * 割込みハンドラ実行にLRにセットされるEXC_RETURNをチェックして,戻り
264 * 先でMSPが使われていれば,割込み先が非タスクコンテキストと判定する.
266 pop {r3} /* lrをスタックから取得 */
267 tst r3, #EXC_RETURN_PSP /* 戻り先がPSPなら */
268 bne core_nonkernel_ret_exc_1
269 pop {r1} /* 元の割込み優先度マスク(basepri) */
270 b core_nonkernel_ret_exc_2 /* の値をMSPから取得 */
272 core_nonkernel_ret_exc_1:
274 * PSP上からEXC_RETURNを削除
279 * 元の割込み優先度マスク(basepri)の値をPSPから取得
284 core_nonkernel_ret_exc_2:
285 msr basepri, r1 /* 割込み優先度マスクを割込み前に状態へ */
294 .global core_int_entry
295 .type core_int_entry, function
298 * 割込み発生時の割込み優先度マスクをスタックに保存するため取得
300 mrs r2, basepri /* baepriの値を取得 */
304 * EXC_RETURN(割込み時にLRに設定される値)をチェックして,例外発生時に
305 * アクティブなスタックを特定することで多重割込みか判定する.
307 tst lr, #EXC_RETURN_PSP /* 割込み元がMSPなら多重割込み */
308 beq core_int_entry_1 /* 多重割込みならcore_int_entry_1へ */
309 mrs r0, psp /* 一段目の割込みの場合はPSP上に */
310 stmfd r0!,{r2} /* 割込み発生時の割込み優先度マスクを積む */
311 stmfd r0!,{lr} /* EXC_RETURN を積む */
312 msr psp, r0 /* CPU例外ハンドラへの引数となる */
313 push {lr} /* MSP上にもEXC_RETURN を積む */
315 core_int_entry_1: /* 多重割込みの場合 */
316 push {r2} /* 割込み発生時の割込み優先度マスクを積む */
317 push {lr} /* EXC_RETURN を積む */
318 mov r0, sp /* 未定義の割込みが発生した場合の情報とする */
324 mrs r3, ipsr /* ハンドラアドレスを取得 */
325 ldr r1, =_kernel_exc_tbl
326 ldr r2, [r1, r3, lsl #2]
330 * NVIC優先度マスクが自動的に設定されるため優先度マスクの点では必要な
331 * いが,x_get_ipm()がbasepriを参照するため,basepriも更新する.
333 ldr r1, =_kernel_int_iipm_tbl
334 ldr lr, [r1, r3, lsl #2]
339 mov r0, r3 /* 例外番号をパラメータに */
340 bl log_inh_enter /* log_exc_enterを呼び出す */
342 push {r3} /* 例外番号をスタックへ */
343 #endif /* LOG_EXC_ENTER */
351 pop {r0} /* 例外番号を引数に */
352 bl log_exc_leave /* log_exc_leaveを呼び出す */
353 #endif /* LOG_INH_LEAVE */
360 * ret_exc/ret_intは,CPU例外/割込みハンドラから戻った直後に実行する
366 * 割込みロック状態とする.この時点では,CPUロック状態にはならない
367 * (basepriとlock_flagとsaved_iipmは更新しない).
369 * 割込みロック状態とするのは,戻り先のコンテキストのチェックと,
370 * 戻り先が非タスクコンテキストであった場合のリターンをアトミック
371 * に行うためである.bsepriをCPUロックの値にすることでもアトミッ
372 * クなチェックと復帰は可能であるが,割込みからリターンしても,
373 * basepri の設定内容は元に戻らないため,使用することができない.
374 * 一方,FAULTMASKは,割込みからのリターン処理によって,'0'にクリ
382 * 割込みハンドラ実行にLRにセットされるEXC_RETURNをチェックして,戻り
383 * 先でMSPが使われていれば,割込み先が非タスクコンテキストと判定する.
385 pop {r3} /* lrをスタックから取得 */
386 tst r3, #EXC_RETURN_PSP /* 戻り先がPSPなら ret_int_1 へ */
388 pop {r1} /* 元の割込み優先度マスク(basepri)をr1へ */
389 b ret_int_2 /* の値をMSPから取得 */
396 * PSP上から,EXC_RETURN(r0)と元の割込み優先度マスク(basepri)(r1)
406 * カーネル管理内の割込みは禁止した状態で実行する必要があるため,
407 * FAULTMASKを'1'にした状態で実行する.
408 * reqflgをチェックする前に割込みを禁止するのは,reqflgをチェック
409 * した直後に割込みハンドラが起動され,その中でディスパッチが要求
410 * された場合に,すぐにディスパッチされないという問題が生じるため
413 ldr r0, =reqflg /* reqflgがfalseならそのまま戻る */
415 cbnz r2, ret_int_3 /* trueならret_int_3へ */
419 * ここには割込みロック状態(FAULTMASKがセット)された状態で来る.
420 * Threadモードからのリターンにより自動的に割込みロック解除状態になる.
421 * 割込み優先度マスクは割込み前に状態に戻す.
423 msr basepri, r1 /* 割込み優先度マスクを割込み前に状態へ */
428 * ここでは,戻り先がタスクであり,PSP上にスクラッチレジスタと割
429 * 込み優先度マスク(basepri)が保存された状態になっている.また,
430 * プロセッサは,Handlerモード・割込みロック状態となっている.
431 * また,r0には,reqflgのアドレス,r3には割込み受付時のlrの値が保
435 * タスク例外ハンドラやディスパッチをする際にThreadモードへ遷移する
436 * ダミーのスタックフレームを作成して,bx命令でHandlerモードからリ
437 * ターンする.また,遅延ディスパッチする場合も,再び割り込んだタス
438 * クに戻る際には,svc命令で,svc_handlerを呼び出す.
439 * スタックフレームは,Configureation and Control Register(CCR)の
440 * STKALIGNが'1'の場合は,8byte境界にアラインされる.
441 * 参考 : DDI0403B_arm_architecture_v7m_reference_manual(P.220)
442 * そのため,この時点のスタックは割込みや例外発生時に作成された
443 * スタックフレームから,8byte境界のサイズにしておくと,svc_handler
444 * 等でスタックフレームのアライメントの有無の確認を省略できる.
445 * ただし,システム起動後は,動的にCCRのSTKALIGNの設定を変更するのは
447 * この時点は標準のスタックフレームは,割込み・例外発生時と同等であ
448 * るため,タスクスタック(PSP)は8byte境界になっている.
450 mov r1, #0 /* reqflgをfalseに */
456 * カーネルの管理内の割込みを禁止するようにbasepriを設定し,
457 * lock_flag と saved_iipm を更新する.saved_iipmは,戻り先の割込み
458 * 優先度マスク(の内部表現)に設定する.
459 * この時点でCPUロック状態とするのは,dispatcherへ分岐する時と,
460 * call_texrtnを呼び出す時に,CPUロック状態になっている必要がある
462 * なお,この処理の後,Threadモードへの移行処理を行なうため,割込み
463 * ロック状態(FAULTMASKを"1")は保持する.
465 ldr r1, =IIPM_LOCK /* CPUロック状態 */
467 mov r1, #0x01 /* lock_flag を trueに */
472 * 割込み優先度マスクを,全解除状態(TIPM_ENAALL)に設定する
473 * すでにCPUロック状態なので,saved_iipmをIIPM_ENAALLとする.
482 * dispatcherやcall_texrnを呼び出す場合は,Threadモードである必
483 * 要があるため,PSPスタック上にダミーの例外フレームを置いて,
484 * 擬似的に割込みハンドラからリターンする.
485 * リターンと同時にFAULTMASKが自動的にクリアされ,カーネル管理外の
488 ldr r0, =ret_int_4 /* PC */
489 ldr r1, =EPSR_T /* xPSR(Tビットが'1'である必要がある) */
492 #if defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)
493 tst r3,#FP_EXC_FRAME /* r3はLR。例外フレームには浮動小数点コンテキストを含んでいるか */
494 beq ret_int_m4f_1 /* このbitは0の時浮動小数点コンテキストが含まれていることを示す */
496 stmfd r2!,{r3} /* LRは、後でsvc_handlerから擬似リターンするときに使う */
497 stmfd r2!,{r3} /* アライメントのために2度プッシュ */
499 ret_int_m4f_1: /* 例外フレームが浮動小数点コンテキストを含んでいるときの処理 */
500 vstmdb r2!,{s16-s31} /* preserved FPレジスタを保存。ここでlazystackingは解消される */
501 stmfd r2!,{r3} /* LRは、後でsvc_handlerから擬似リターンするときに使う */
502 stmfd r2!,{r3} /* アライメントのために2度プッシュ */
503 orr r3,#FP_EXC_FRAME /* r3はLR。EXC_RETURNをFPなしフレームに強制する */
505 /* この先はショート例外フレームである */
506 #endif /* defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)*/
508 stmfd r2!, {r0-r1} /* ダミーフレームをスタック上に積む */
509 sub r2, #(EXC_FRAME_SIZE - (4*2)) /* r0-r3,r12,lrの内容は設定する必要がない */
511 bx r3 /* Threadモードへ移行 */
515 * 上記の処理により,Threadモードで実行される.
516 * dspflgがfalseである場合と,p_runtskとp_schedtskが同じ場合には,
517 * ディスパッチを行わない.このチェックが必要なのは,タスク例外処
518 * 理ルーチンの呼出しが必要な場合に,ディスパッチが必要なくても,
519 * reqflgをtrueにするためである.
521 ldr r0, =p_runtsk /* ディスパッチを行わない場合でも,r1にp_runtsk の値(TCB) */
522 ldr r1, [r0] /* が入っている必要があるので,先に読み込む */
525 cbz r2, ret_int_r_1 /* dspflgがfalseならret_int_r_1へ */
528 cmp r1, r2 /* p_runtskとp_schedtskが同じなら */
529 beq ret_int_r_1 /* ret_int_r_1へ */
530 stmfd sp!, {r4-r11} /* 残りのレジスタを保存 */
531 str sp, [r1,#TCB_sp] /* タスクスタックを保存 */
532 ldr lr, =ret_int_r /* 実行再開番地を保存 */
534 b dispatcher /* ディスパッチャへ */
537 * 割込みによりプリエンプトされたタスクへのリターン処理
539 * Threadモードで,ディスパッチャや割込みの出口処理から呼び出される.
540 * 割込みによりプリエンプトされたタスクへリターンするには,いったん
541 * Handlerモードに移行し,PCに0xfffffffdを代入してリターンする必要
542 * がある.そのため,SVCにより,SVCハンドラを呼び出し,Handlerモー
548 .type ret_int_r, function
550 pop {r4-r11} /* レジスタの復帰 */
553 * enatexがtrueで,texptnが0でなければ,タスク例外処理ルーチンを
555 * dispatcherから呼び出されるため,TCBのアドレスはr1に入っている
557 ldrb r0, [r1,#TCB_enatex]
558 tst r0, #TCB_enatex_mask
559 beq ret_int_r_2 /* enatex が false なら ret_int_r_2へ */
560 ldr r0, [r1,#TCB_texptn] /* texptn が 0 ならリターン */
562 ldr r1, =ipmflg /* ipmflgが false ならリターン */
565 bl call_texrtn /* タスク例外ルーチンの呼び出し */
577 .type svc_handler, function
580 * 割込み処理からのリターンにより,CPUロック解除状態に移行するよ
583 cpsid f /* 割込みロック状態へ */
585 add r0, #EXC_FRAME_SIZE /* スタックを捨てる */
586 #if defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)
588 ldmfd r0!,{lr} /* LRフレームはアライメントのために二度積まれている */
589 tst lr,#FP_EXC_FRAME /* 例外フレームには浮動小数点コンテキストを含んでいるか */
590 bne svc_handler_m4f_1 /* 当該ビットが1なら含んでいない */
591 vldmia r0!,{s16-s31} /* 含んでいるならpreserved FPレジスタを復帰する */
593 #endif /* defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)*/
596 ldr r1, =lock_flag /* CPUロック解除状態へ */
598 ldr r1, =IIPM_ENAALL /* 割込み優先度マスクを全解除状態に設定 */
608 .globl start_dispatch
611 * このルーチンは,カーネル起動時に,すべての割込みを禁止した状態
612 * (割込みロック状態と同等)で呼び出される.また,割込みモード(非
613 * タスクコンテキストと同等)で呼び出されることを想定している.
615 * core_initializeで,lock_flagをtrueに,saved_iipmをIIPM_ENAALLに
616 * 初期化しているため,カーネル管理外の割込みを許可することで,
617 * CPUロック状態・(モデル上の)割込み優先度マスク全解除状態になる.
618 * また,task_initializeでdisdspをfalseに初期化しているため,ディ
621 ldr r0,=istkpt /* MSPを初期化 */
622 ldr r1,[r0] /* start_dispatch呼び出し時に呼び出し用に */
623 msr msp, r1 /* 使用しているため初期化する */
624 ldr r1, =IIPM_LOCK /* カーネル管理内の割込みを禁止 */
626 cpsie f /* カーネル管理外の割込みを許可 */
627 mov r0, #CONTROL_PSP /* PSPを有効に */
629 isb /* control の操作後に必要 */
632 * 現在のコンテキストを捨ててディスパッチ
637 .globl exit_and_dispatch
639 /* ディスパッチャ本体(dispatcher)へ */
647 * このルーチンは,タスクコンテキスト・CPUロック状態・ディスパッチ
648 * 許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さ
651 * すなわち,Threadモード・lock_flagがtrue・disdspがfalse・dspflg
652 * がtrue・saved_iipmがIIPM_ENAALLとなっている.実行再開番地へもこ
656 ldr r1, =p_runtsk /* p_runtskをパラメータに */
659 #endif /* LOG_DSP_ENTER */
661 ldr r0, =p_schedtsk /* p_schedtskをp_runtskに */
665 cbz r1, dispatcher_1 /* p_runtskがNULLならdispatcher_1へ */
666 ldr sp, [r1,#TCB_sp] /* タスクスタックを復帰 */
668 mov r0, r1 /* p_runtskをパラメータに */
669 mov r4, r1 /* r1はスクラッチレジスタなので保存 */
672 #endif /* LOG_DSP_LEAVE */
673 ldr pc, [r1,#TCB_pc] /* 実行再開番地を復帰 */
676 * CPUロック状態の解除と,非タスクコンテキスト実行状態への
679 mov r0, #CONTROL_MSP /* MSPを有効に */
681 isb /* control の操作後に必要 */
682 ldr r2, =reqflg /* r2 <- reqflg */
683 ldr r1, =IIPM_LOCK /* 割込みロック状態の割込み優先度マスクの値 */
685 ldr r4, =lock_flag /* CPUロック解除状態へ */
689 * 割込みを許可し,非タスクコンテキスト実行状態とし割込みを待つ.
691 * ここで非タスクコンテキスト実行状態に切り換えるのは,ここで発生
692 * する割込み処理にどのスタックを使うかという問題の解決と,割込み
693 * ハンドラ内でのタスクディスパッチの防止という2つの意味がある.
695 * プロセッサを割込み待ちに移行させる処理と,割込み許可とは,不可
697 * これを不可分に行なわない場合,割込みを許可した直後に割込
698 * みが入り,その中でタスクが実行可能状態になると,実行すべきタス
699 * クがあるにもかかわらずプロセッサが割込み待ちになってしまう.
700 * ARM-Mでは,PRIMASKをセットした状態でWFIを呼び出すことで実現できる.
701 * この状態で割込みが入ると,割込みは実行されず,WFIからリターンす
702 * ることになるので,一旦割込みを許可して割込みハンドラを実行する.
704 * 割込み待ちの間は,p_runtskをNULL(=0)に設定しなければならな
705 * い.このように設定しないと,割込みハンドラからiget_tidを呼び出
709 #ifdef TOPPERS_CUSTOM_IDLE
710 toppers_asm_custom_idle
712 cpsid i /* PRIMASK をセット */
713 msr basepri, r0 /* 全割込み許可 */
715 cpsie i /* PRIMASK をクリア(割込みを受け付ける) */
716 msr basepri, r1 /* CPUロック状態へ */
717 #endif /* TOPPERS_CUSTOM_IDLE */
719 ldr r6, [r2] /* reqflgがfalseならdispatcher_2へ */
722 str r0, [r2] /* reqflgをfalseに */
725 * CPUロック状態に戻す.割込み待ちの間に実行した割込みハンドラによ
726 * り,saved_iipmが書き換えられる可能性があるため,元の値に戻す必
727 * 要がある.dispatcherが実行される時は,saved_iipmがIIPM_ENAALL
728 * となっているため,ここではsaved_iipmをIIPM_ENAALL(=0)に戻せ
731 mov r0, #CONTROL_PSP /* PSPを有効に */
733 isb /* control の操作後に必要 */
734 mov r2, #1 /* lock_flagをtrueへ */
737 ldr r4, =saved_iipm /* saved_iipm を0に */
746 * スタックを非タスクコンテキスト用に切り替え.
752 .globl call_exit_kernel
753 .type call_exit_kernel, function
756 msr control, r0 /* MSPを有効に */
757 isb /* control の操作後に必要 */
758 b exit_kernel /* カーネルの終了処理を呼ぶ */
764 * dispatcherから呼び出されるため,TCBのアドレスはr1に入っている
771 .type start_r, function
773 #if defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)
774 /* CORTEX-M4Fが浮動小数点演算を行ったか記録するための処理。*/
775 mrs r4, control /*CONTROLレジスタの値を取得 */
776 bic r4, #CONTROL_FPCA /* FPCAビットをクリアして、FPコプロセッサ使用履歴をクリアする */
779 #endif /* defined(__ARM_ARCH_7EM__) & !defined(__SOFTFP__)*/
780 /* 以下、CORTEX-M3, M4F共通 */
782 ldr r4, =lock_flag /* CPUロック解除状態へ */
784 msr basepri, r0 /* 割込み許可 */
785 ldr lr, =ext_tsk /* 戻り番地設定 */
786 ldr r2, [r1, #TCB_p_tinib] /* p_runtsk->p_tinibをr2に */
787 ldr r0, [r2, #TINIB_exinf] /* exinfを引数レジスタr0に */
788 ldr r1, [r2, #TINIB_task] /* タスク起動番地にジャンプ */
798 .type sil_dly_nse, function
800 sub r0, r0, #SIL_DLY_TIM1
805 sub r0, r0, #SIL_DLY_TIM2