source: asp3_wo_tecs/trunk/arch/arm_gcc/common/core_support.S@ 302

Last change on this file since 302 was 302, checked in by ertl-honda, 7 years ago

TECSレスのASP3の開発のため以下のtrunkからコピー
http://dev.toppers.jp/svn/asp3/branches/WO_TECS-3.C.0

File size: 32.1 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2004 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2006-2015 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 *
11 * 上記著作権者
12は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
13 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
14 * 変・再é…
15å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
16 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
17 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
18 * スコード中に含まれていること.
19 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
20 * 用できる形で再é…
21å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
22å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
23 * 者
24マニュアルなど)に,上記の著作権表示,この利用条件および下記
25 * の無保証規定を掲載すること.
26 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
27 * 用できない形で再é…
28å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
29 * と.
30 * (a) 再é…
31å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
32マニュアルなど)に,上記の著
33 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
34 * (b) 再é…
35å¸ƒã®å½¢æ…
36‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
37 * 報告すること.
38 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
39 * 害からも,上記著作権者
40およびTOPPERSプロジェクトをå…
41è²¬ã™ã‚‹ã“と.
42 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
43 * 由に基づく請求からも,上記著作権者
44およびTOPPERSプロジェクトを
45 * å…
46è²¬ã™ã‚‹ã“と.
47 *
48 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
49お
50 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
51 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
52 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
53 * の責任を負わない.
54 *
55 * $Id: core_support.S 459 2015-08-29 13:03:42Z ertl-hiro $
56 */
57
58/*
59 * カーネルのコア依存部のアセンブリ言語部(ARM用)
60 */
61
62#define TOPPERS_MACRO_ONLY
63#define TOPPERS_ASM_MACRO
64#define UINT_C(val) (val) /* uint_t型の定数を作るマクロ */
65#define ULONG_C(val) (val) /* ulong_t型の定数を作るマクロ */
66#define CAST(type, val) (val) /* 型キャストを行うマクロ */
67#include "kernel_impl.h"
68#include "offset.h"
69#include "core_asm.inc"
70
71/*
72 * 例外ベクタ
73 */
74 ASECTION(vector)
75 AGLOBAL(vector_table)
76ALABEL(vector_table)
77 ldr pc, reset_vector /* リセット */
78 ldr pc, undef_vector /* 未定義命令 */
79 ldr pc, svc_vector /* ソフトウェア割込み */
80 ldr pc, pabort_vector /* プリフェッチアボート */
81 ldr pc, dabort_vector /* データアボート */
82 ldr pc, reset_vector /* 未使用 */
83 ldr pc, irq_vector /* IRQ */
84 ldr pc, fiq_vector /* FIQ */
85
86/*
87 * 例外ベクタの命令から参ç…
88§ã•ã‚Œã‚‹ã‚¸ãƒ£ãƒ³ãƒ—å…
89ˆã‚¢ãƒ‰ãƒ¬ã‚¹
90 */
91 AGLOBAL(vector_ref_table)
92ALABEL(vector_ref_table)
93ALABEL(reset_vector)
94 ALONG start
95ALABEL(undef_vector)
96 ALONG undef_handler
97ALABEL(svc_vector)
98 ALONG svc_handler
99ALABEL(pabort_vector)
100 ALONG pabort_handler
101ALABEL(dabort_vector)
102 ALONG dabort_handler
103ALABEL(irq_vector)
104 ALONG irq_handler
105ALABEL(fiq_vector)
106 ALONG fiq_handler
107
108/*
109 * タスクディスパッチャ
110 */
111 ATEXT
112 AALIGN(2)
113 AGLOBAL(dispatch)
114ALABEL(dispatch)
115 /*
116 * このルーチンは,タスクコンテキスト・CPUロック状æ…
117‹ãƒ»å‰²è¾¼ã¿å„ªå…
118ˆåº¦
119 * マスクå…
120¨è§£é™¤çŠ¶æ…
121‹ãƒ»ãƒ‡ã‚£ã‚¹ãƒ‘ッチ許可状æ…
122‹ã§å‘¼ã³å‡ºã•ã‚Œã‚‹ï¼Ž
123 */
124 push {lr} /* 戻り番地を保存 */
125#ifdef TOPPERS_SUPPORT_OVRHDR
126 bl ovrtimer_stop
127#endif /* TOPPERS_SUPPORT_OVRHDR */
128 stmfd sp!, {r4-r11} /* 非スクラッチレジスタの保存 */
129 ldr r0, =p_runtsk /* p_runtsk → r0 */
130 ldr r0, [r0]
131 str sp, [r0,#TCB_sp] /* スタックポインタを保存 */
132 adr r1, dispatch_r
133 str r1, [r0,#TCB_pc] /* 実行再開番地を保存 */
134 b dispatcher /* r0にはp_runtskが格納されている */
135
136ALABEL(dispatch_r)
137 ldmfd sp!, {r4-r11} /* 非スクラッチレジスタの復帰 */
138#ifdef TOPPERS_SUPPORT_OVRHDR
139 bl ovrtimer_start
140#endif /* TOPPERS_SUPPORT_OVRHDR */
141 pop {lr} /* 戻り番地を復帰 */
142 bx lr
143
144/*
145 * ディスパッチャの動作開始
146 */
147 AGLOBAL(start_dispatch)
148ALABEL(start_dispatch)
149 /*
150 * このルーチンは,カーネル起動時に,非タスクコンテキストで,NMIを
151 * 除くすべての割込みを禁止した状æ…
152‹ï¼ˆå…
153¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
154‹ã¨åŒç­‰ï¼‰ã§
155 * 呼び出される.
156 *
157 * dispatcher_0へ分岐する前に,タスクコンテキスト・CPUロック状æ…
158‹ãƒ»
159 * 割込み優å…
160ˆåº¦ãƒžã‚¹ã‚¯å…
161¨è§£é™¤çŠ¶æ…
162‹ã«ã—,使用するスタックを,IDが1のタ
163 * スクのスタック領域に切り換えなければならない.
164 */
165
166 /*
167 * タスクコンテキストに切り換える.
168 */
169 ldr r2, =excpt_nest_count /* 例外ネストカウントを0に */
170 mov r0, #0
171 str r0, [r2]
172
173 /*
174 * IDが1のタスクのスタック領域に切り換える.
175 */
176 ldr r0, =tcb_table /* tcb_table[0] → r0 */
177 ldr r2, [r0,#TCB_p_tinib] /* tcb_table[0].p_tinib → r2 */
178 ldr r0, [r2,#TINIB_stk]
179 ldr r1, [r2,#TINIB_stksz]
180 add sp, r0, r1
181
182 /*
183 * CPUロック状æ…
184‹ã«ã—て,ディスパッチャ本体へ分岐する.
185 */
186 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_CPULOCK)
187 b dispatcher_0
188
189/*
190 * 現在のコンテキストを捨ててディスパッチ
191 */
192 AGLOBAL(exit_and_dispatch)
193ALABEL(exit_and_dispatch)
194 /*
195 * このルーチンは,タスクコンテキスト・CPUロック状æ…
196‹ãƒ»å‰²è¾¼ã¿å„ªå…
197ˆåº¦
198 * マスクå…
199¨è§£é™¤çŠ¶æ…
200‹ãƒ»ãƒ‡ã‚£ã‚¹ãƒ‘ッチ許可状æ…
201‹ã§å‘¼ã³å‡ºã•ã‚Œã‚‹ï¼Ž
202 */
203#ifdef LOG_DSP_ENTER
204 ldr r0, =p_runtsk /* p_runtsk → r0 */
205 ldr r0, [r0]
206#endif /* LOG_DSP_ENTER */
207 /* ディスパッチャ本体(dispatcher)へ */
208
209/*
210 * ディスパッチャ本体
211 */
212ALABEL(dispatcher)
213#ifdef LOG_DSP_ENTER
214 /*
215 * 【この時点のレジスタ状æ…
216‹ã€‘
217 * r0:p_runtsk(タスク切換え前)
218 */
219 bl log_dsp_enter
220#endif /* LOG_DSP_ENTER */
221
222ALABEL(dispatcher_0)
223 /*
224 * このルーチンは,タスクコンテキスト・CPUロック状æ…
225‹ãƒ»å‰²è¾¼ã¿å„ªå…
226ˆåº¦
227 * マスクå…
228¨è§£é™¤çŠ¶æ…
229‹ãƒ»ãƒ‡ã‚£ã‚¹ãƒ‘ッチ許可状æ…
230‹ã§å‘¼ã³å‡ºã•ã‚Œã‚‹ï¼Žå®Ÿè¡Œå†é–‹ç•ª
231 * 地へもこの状æ…
232‹ã®ã¾ã¾åˆ†å²ã™ã‚‹ï¼Ž
233 */
234 ldr r0, =p_schedtsk /* p_schedtsk → r4 → p_runtsk */
235 ldr r4, [r0]
236 ldr r1, =p_runtsk
237 str r4, [r1]
238 tst r4, r4 /* p_runtskがNULLならdispatcher_1へ */
239 beq dispatcher_1
240 ldr sp, [r4,#TCB_sp] /* タスクスタックを復帰 */
241#ifdef LOG_DSP_LEAVE
242 mov r0, r4 /* p_runtskをパラメータに渡す */
243 bl log_dsp_leave
244#endif /* LOG_DSP_LEAVE */
245 ldr r0, [r4,#TCB_pc] /* 実行再開番地を復帰 */
246 bx r0 /* p_runtskをr4にå…
247¥ã‚ŒãŸçŠ¶æ…
248‹ã§åˆ†å²ã™ã‚‹ */
249
250 /*
251 * アイドル処理
252 *
253 * 割込みをすべて許可し,CPUロック解除状æ…
254‹ã«ã—て割込みを待
255つ.
256 *
257 * ターゲットによっては,省電力モード等に移行するため,標準の方法
258 * と異なる手順が必
259要な場合がある.そのようなターゲットでは,ター
260 * ゲット依存部でTOPPERS_CUSTOM_IDLEを定義し,アセンブラマクロとし
261 * て,toppers_asm_custom_idleを用意すればよい.
262 */
263ALABEL(dispatcher_1)
264#ifdef TOPPERS_CUSTOM_IDLE
265 toppers_asm_custom_idle
266#else /* TOPPERS_CUSTOM_IDLE */
267 msr cpsr_c, #CPSR_SVC_MODE /* 割込みを許可(スーパバイザモード)*/
268ALABEL(dispatcher_2)
269 b dispatcher_2 /* 割込み待
270ち */
271#endif /* TOPPERS_CUSTOM_IDLE */
272
273/*
274 * カーネルの終了処理の呼出し
275 *
276 * 割込みロック状æ…
277‹ã«ã—,使用するスタックを非タスクコンテキスト用のスタッ
278 * ク領域に切り替え,exit_kernelを呼び出す.
279 */
280 AGLOBAL(call_exit_kernel)
281ALABEL(call_exit_kernel)
282 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_INTLOCK)
283 ldr r0, =istkpt /* 非タスクコンテキストのスタックへ */
284 ldr sp, [r0]
285 b exit_kernel
286
287/*
288 * タスクの実行開始時処理
289 */
290 ATEXT
291 AALIGN(2)
292 AGLOBAL(start_r)
293 /*
294 * ディスパッチャ本体から呼び出されるため,p_runtskはr4にå…
295¥ã£ã¦ã„る.
296 */
297ALABEL(start_r)
298#ifdef TOPPERS_SUPPORT_OVRHDR
299 bl ovrtimer_start
300#endif /* TOPPERS_SUPPORT_OVRHDR */
301 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_UNLOCK)
302 /* CPUロック解除状æ…
303‹ã« */
304 ldr lr, =ext_tsk /* タスク本体からの戻り番地を設定 */
305 ldr r2, [r4,#TCB_p_tinib] /* p_runtsk->p_tinib → r2 */
306 ldr r0, [r2,#TINIB_exinf] /* exinfをパラメータに */
307 ldr r1, [r2,#TINIB_task] /* タスク起動番地にジャンプ */
308 bx r1
309
310/*
311 * 割込みハンドラの出å…
312¥å£å‡¦ç†
313 */
314#ifndef OMIT_IRQ_HANDLER
315 ATEXT
316 AALIGN(2)
317 AGLOBAL(irq_handler)
318ALABEL(irq_handler)
319 /*
320 * ここには,IRQモードで分岐してくる.
321 */
322#if __TARGET_ARCH_ARM < 6
323 /*
324 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
325 */
326 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_IRQ_BIT)
327 stmfd sp!, {r0-r4,r12,lr,pc} /* pcはスペース確保のため */
328
329 /*
330 * IRQモードに戻して,戻り番地とspsr(戻りå…
331ˆã®cpsr)を取得する.
332 */
333 msr cpsr_c, #(CPSR_IRQ_MODE AOR CPSR_IRQ_BIT)
334 sub r2, lr, #4
335 mrs r1, spsr
336
337 /*
338 * スーパバイザモードに切り換え,戻り番地とspsrを保存する.
339 */
340 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_IRQ_BIT)
341 str r2, [sp,#0x1c] /* 戻り番地をスタックに保存 */
342 push {r1} /* spsrをスタックに保存 */
343#else /* __TARGET_ARCH_ARM < 6 */
344 /*
345 * 戻りå…
346ˆï¼ˆlr)とspsr(cpsr_svc)をスーパバイザモードのスタックに
347 * 保存する.
348 */
349 sub lr, lr, #4 /* 戻り番地の算出 */
350 srsfd #CPSR_SVC_MODE!
351
352 /*
353 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
354 */
355 cps #CPSR_SVC_MODE
356 stmfd sp!, {r0-r4,r12,lr}
357#endif /* __TARGET_ARCH_ARM < 6 */
358
359 /*
360 * 例外ネストカウントをインクリメントする.割込みが非タスクコンテキ
361 * ストで発生した場合には,irq_handler_1へ分岐する.
362 */
363 ldr r2, =excpt_nest_count
364 ldr r3, [r2]
365 add r3, r3, #1
366 str r3, [r2]
367 teq r3, #1 /* 割込みが非タスクコンテキストで発生 */
368 bne irq_handler_1 /* ならirq_handler_1に分岐 */
369
370#ifdef TOPPERS_SUPPORT_OVRHDR
371 /*
372 * オーバランタイマを停止する.
373 */
374 bl ovrtimer_stop
375#endif /* TOPPERS_SUPPORT_OVRHDR */
376
377 /*
378 * 非タスクコンテキスト用のスタックに切り換える.
379 */
380 mov r1, sp /* この時点のスタックポインタをr1に */
381 ldr r2, =istkpt /* 非タスクコンテキスト用のスタックに */
382 ldr sp, [r2]
383 push {r1} /* 切換え前のスタックポインタを保存 */
384
385ALABEL(irq_handler_1)
386 /*
387 * 割込みコントローラを操作し,割込み番号を取得する.
388 */
389 bl irc_begin_int
390 cmp r4, #TNUM_INHNO /* スプリアス割込みなら */
391 bhs irq_handler_2 /* irq_handler_2に分岐 */
392
393 /*
394 * CPUロック解除状æ…
395‹ã«ã™ã‚‹ï¼Ž
396 */
397#if __TARGET_ARCH_ARM < 6
398 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_UNLOCK)
399#else /* __TARGET_ARCH_ARM < 6 */
400#ifndef TOPPERS_SAFEG_SECURE
401 cpsie if
402#else /* TOPPERS_SAFEG_SECURE */
403 cpsie f
404#endif /* TOPPERS_SAFEG_SECURE */
405#endif /* __TARGET_ARCH_ARM < 6 */
406
407#ifdef LOG_INH_ENTER
408 /*
409 * ログ出力の呼出し
410 */
411 mov r0, r4 /* 割込み番号をパラメータに渡す */
412 bl log_inh_enter
413#endif /* LOG_INH_ENTER */
414
415 /*
416 * 割込みハンドラの呼出し
417 */
418 ldr r2, =inh_table /* 割込みハンドラテーブルの読込み */
419 ldr r1, [r2,r4,lsl #2] /* 割込みハンドラの番地 → r1 */
420 mov lr, pc /* 割込みハンドラの呼出し */
421 bx r1
422
423#ifdef LOG_INH_LEAVE
424 /*
425 * ログ出力の呼出し
426 */
427 mov r0, r4 /* 割込み番号をパラメータに渡す */
428 bl log_inh_leave
429#endif /* LOG_INH_LEAVE */
430
431 /*
432 * カーネル管理の割込みを禁止する.
433 */
434#if __TARGET_ARCH_ARM < 6
435 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_CPULOCK)
436#else /* __TARGET_ARCH_ARM < 6 */
437#ifndef TOPPERS_SAFEG_SECURE
438 cpsid i
439#else /* TOPPERS_SAFEG_SECURE */
440 cpsid if
441#endif /* TOPPERS_SAFEG_SECURE */
442#endif /* __TARGET_ARCH_ARM < 6 */
443
444 /*
445 * 割込みコントローラを操作する.
446 */
447ALABEL(irq_handler_2)
448 bl irc_end_int
449#endif /* OMIT_IRQ_HANDLER */
450
451 /*
452 * 例外ネストカウントをデクリメントする.
453 */
454 ldr r2, =excpt_nest_count
455 ldr r3, [r2]
456 subs r3, r3, #1
457 str r3, [r2] /* 戻りå…
458ˆãŒéžã‚¿ã‚¹ã‚¯ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãªã‚‰ */
459 bne irq_handler_3 /* irq_handler_3に分岐 */
460
461 /*
462 * タスク用のスタックに戻す.
463 */
464 pop {r1}
465 mov sp, r1
466
467 /*
468 * ディスパッチが必
469要か判定する.
470 */
471ALABEL(ret_int_1)
472 ldr r0, =p_runtsk /* p_runtsk → r0 */
473 ldr r0, [r0]
474 ldr r1, =p_schedtsk /* p_schedtsk → r1 */
475 ldr r1, [r1]
476 teq r0, r1 /* p_runtskとp_schedtskが同じなら */
477 beq irq_handler_4 /* irq_handler_4へ */
478
479 /*
480 * コンテキストを保存する.
481 */
482 tst r0, r0 /* p_runtskがNULLならdispatcher_0へ */
483 beq dispatcher_0
484 stmfd sp!, {r5-r11} /* 非スクラッチレジスタの保存 */
485 str sp, [r0,#TCB_sp] /* スタックポインタを保存 */
486 adr r1, ret_int_r /* 実行再開番地を保存 */
487 str r1, [r0,#TCB_pc]
488 b dispatcher /* r0にはp_runtskが格納されている */
489
490ALABEL(ret_int_r)
491 /*
492 * コンテキストを復帰する.
493 */
494 ldmfd sp!, {r5-r11} /* 非スクラッチレジスタの復帰 */
495
496#ifdef TOPPERS_SUPPORT_OVRHDR
497 /*
498 * オーバランタイマを動作開始する.
499 */
500 bl ovrtimer_start
501#endif /* TOPPERS_SUPPORT_OVRHDR */
502
503 /*
504 * 割込み/CPU例外処理からのリターン
505 *
506 * 割込み/CPU例外処理からのリターンにより,CPUロック解除状æ…
507‹ã«é·
508 * 移するようにする必
509要があるが,ARMはCPSRのビットによってCPUロッ
510 * ク状æ…
511‹ã‚’表しているため,CPSRをå…
512ƒã«æˆ»ã—てリターンすればよい.
513 */
514#ifndef TOPPERS_SUPPORT_OVRHDR
515ALABEL(irq_handler_4)
516#endif /* TOPPERS_SUPPORT_OVRHDR */
517ALABEL(irq_handler_3)
518#if __TARGET_ARCH_ARM < 6
519 ldmfd sp!, {r0} /* 戻りå…
520ˆã®cpsrをspsrに設定 */
521 msr spsr_cxsf, r0
522 ldmfd sp!, {r0-r4,r12,lr,pc}^ /* コンテキストの復帰 */
523 /* ^付きなので,spsr → cpsr */
524#else /* __TARGET_ARCH_ARM < 6 */
525 ldmfd sp!, {r0-r4,r12,lr}
526 rfefd sp!
527#endif /* __TARGET_ARCH_ARM < 6 */
528
529#ifdef TOPPERS_SUPPORT_OVRHDR
530ALABEL(irq_handler_4)
531 /*
532 * オーバランタイマを動作開始する.
533 */
534 tst r0, r0 /* p_runtskがNULLでない場合 */
535 blne ovrtimer_start
536 b irq_handler_3
537#endif /* TOPPERS_SUPPORT_OVRHDR */
538
539/*
540 * CPU例外ハンドラ出å…
541¥å£å‡¦ç†
542 */
543ALABEL(start_exc_entry)
544
545/*
546 * 未定義命令
547 */
548#ifndef OMIT_UNDEF_HANDLER
549 ATEXT
550 AALIGN(2)
551 AGLOBAL(undef_handler)
552ALABEL(undef_handler)
553 /*
554 * ここには,未定義モードで分岐してくる.
555 */
556#if __TARGET_ARCH_ARM < 6
557 /*
558 * IビットとFビットをセットし,スーパバイザモードに切り換え,スク
559 * ラッチレジスタを保存する.
560 */
561 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
562 stmfd sp!, {r0-r4,r12,lr,pc} /* pcはスペース確保のため */
563
564 /*
565 * 未定義モードに戻して,戻り番地とspsrを取得する.
566 */
567 msr cpsr_c, #(CPSR_UND_MODE AOR CPSR_FIQ_IRQ_BIT)
568 mov r2, lr
569 mrs r1, spsr
570
571 /*
572 * スーパバイザモードに切り換え,戻り番地とspsrを保存する.
573 */
574 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
575 str r2, [sp,#0x1c] /* 戻り番地をスタックに保存 */
576 push {r1} /* spsrをスタックに保存 */
577#else /* __TARGET_ARCH_ARM < 6 */
578 /*
579 * 戻りå…
580ˆï¼ˆlr)とspsr(cpsr_svc)をスーパバイザモードのスタックに
581 * 保存する.
582 */
583 srsfd #CPSR_SVC_MODE!
584
585 /*
586 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
587 */
588 cps #CPSR_SVC_MODE
589 stmfd sp!, {r0-r4,r12,lr}
590#endif /* __TARGET_ARCH_ARM < 6 */
591 mov r4, #EXCNO_UNDEF
592 b exc_handler_1
593#endif /* OMIT_UNDEF_HANDLER */
594
595/*
596 * スーパバイザコール
597 */
598#ifndef OMIT_SVC_HANDLER
599 ATEXT
600 AALIGN(2)
601 AGLOBAL(svc_handler)
602ALABEL(svc_handler)
603 /*
604 * ここには,スーパバイザモードで分岐してくる.
605 */
606#if __TARGET_ARCH_ARM < 6
607 /*
608 * IビットとFビットをセットし,スクラッチレジスタを保存する.
609 */
610 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
611 stmfd sp!, {r0-r4,r12,lr,pc} /* pcはスペース確保のため */
612
613 /*
614 * 戻り番地とspsrを取得する.
615 */
616 mov r2, lr
617 mrs r1, spsr
618
619 /*
620 * 戻り番地とspsrを保存する.
621 */
622 str r2, [sp,#0x1c] /* 戻り番地をスタックに保存 */
623 push {r1} /* spsrをスタックに保存 */
624#else /* __TARGET_ARCH_ARM < 6 */
625 /*
626 * 戻りå…
627ˆï¼ˆlr)とspsr(cpsr_svc)をスーパバイザモードのスタックに
628 * 保存する.
629 */
630 srsfd #CPSR_SVC_MODE!
631
632 /*
633 * スーパバイザモードで,スクラッチレジスタを保存する.
634 */
635 cps #CPSR_SVC_MODE /* 不要と思われる */
636 stmfd sp!, {r0-r4,r12,lr}
637#endif /* __TARGET_ARCH_ARM < 6 */
638 mov r4, #EXCNO_SVC
639 b exc_handler_1
640#endif /* OMIT_SVC_HANDLER */
641
642/*
643 * プリフェッチアボート
644 */
645#ifndef OMIT_PABORT_HANDLER
646 ATEXT
647 AALIGN(2)
648 AGLOBAL(pabort_handler)
649ALABEL(pabort_handler)
650 /*
651 * ここには,アボートモードで分岐してくる.
652 */
653#if __TARGET_ARCH_ARM < 6
654 /*
655 * IビットとFビットをセットし,スーパバイザモードに切り換え,スク
656 * ラッチレジスタを保存する.
657 */
658 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
659 stmfd sp!, {r0-r4,r12,lr,pc} /* pcはスペース確保のため */
660
661 /*
662 * アボートモードに戻して,戻り番地とspsrを取得する.
663 */
664 msr cpsr_c, #(CPSR_ABT_MODE AOR CPSR_FIQ_IRQ_BIT)
665 mov r2, lr
666 mrs r1, spsr
667
668 /*
669 * スーパバイザモードに切り換え,戻り番地とspsrを保存する.
670 */
671 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
672 str r2, [sp,#0x1c] /* 戻り番地をスタックに保存 */
673 push {r1} /* spsrをスタックに保存 */
674#else /* __TARGET_ARCH_ARM < 6 */
675 /*
676 * 戻りå…
677ˆï¼ˆlr)とspsr(cpsr_svc)をスーパバイザモードのスタックに
678 * 保存する.
679 */
680 srsfd #CPSR_SVC_MODE!
681
682 /*
683 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
684 */
685 cps #CPSR_SVC_MODE
686 stmfd sp!, {r0-r4,r12,lr}
687#endif /* __TARGET_ARCH_ARM < 6 */
688 mov r4, #EXCNO_PABORT
689 b exc_handler_1
690#endif /* OMIT_PABORT_HANDLER */
691
692/*
693 * データアボート
694 */
695#ifndef OMIT_DABORT_HANDLER
696 ATEXT
697 AALIGN(2)
698 AGLOBAL(dabort_handler)
699ALABEL(dabort_handler)
700 /*
701 * ここには,アボートモードで分岐してくる.
702 *
703 * データアボートが,CPU例外のå…
704¥å£ï¼ˆstart_exc_entryとend_exc_entry
705 * の間)で発生した場合には,fatal_dabort_handlerに分岐する.アボー
706 * トモードのspを汎用レジスタの代わりに使用する.
707 */
708 ldr sp, =start_exc_entry+8
709 cmp lr, sp
710 bcc dabort_handler_1
711 ldr sp, =end_exc_entry+8
712 cmp lr, sp
713 bcc fatal_dabort_handler
714
715ALABEL(dabort_handler_1)
716#if __TARGET_ARCH_ARM < 6
717 /*
718 * IビットとFビットをセットし,スーパバイザモードに切り換え,スク
719 * ラッチレジスタを保存する.
720 */
721 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
722 stmfd sp!, {r0-r4,r12,lr,pc} /* pcはスペース確保のため */
723
724 /*
725 * アボートモードに戻して,戻り番地とspsrを取得する.
726 */
727 msr cpsr_c, #(CPSR_ABT_MODE AOR CPSR_FIQ_IRQ_BIT)
728 mov r2, lr
729 mrs r1, spsr
730
731 /*
732 * スーパバイザモードに切り換え,戻り番地とspsrを保存する.
733 */
734 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
735 str r2, [sp,#0x1c] /* 戻り番地をスタックに保存 */
736 push {r1} /* spsrをスタックに保存 */
737#else /* __TARGET_ARCH_ARM < 6 */
738 /*
739 * 戻りå…
740ˆï¼ˆlr)とspsr(cpsr_svc)をスーパバイザモードのスタックに
741 * 保存する.
742 */
743 srsfd #CPSR_SVC_MODE!
744
745 /*
746 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
747 */
748 cps #CPSR_SVC_MODE
749 stmfd sp!, {r0-r4,r12,lr}
750#endif /* __TARGET_ARCH_ARM < 6 */
751 mov r4, #EXCNO_DABORT
752 b exc_handler_1
753#endif /* OMIT_DABORT_HANDLER */
754
755/*
756 * CPU例外のå…
757¥å£ã§ç™ºç”Ÿã—たデータアボート
758 */
759ALABEL(fatal_dabort_handler)
760#if __TARGET_ARCH_ARM < 6
761 /*
762 * IビットとFビットをセットし,スーパバイザモードに切り換え,スタッ
763 * クポインタを初期化し,スクラッチレジスタを保存する.
764 */
765 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
766 ldr sp, =istkpt
767 ldr sp, [sp]
768 stmfd sp!, {r0-r4,r12,lr,pc} /* pcはスペース確保のため */
769
770 /*
771 * アボートモードに戻して,戻り番地とspsrを取得する.
772 */
773 msr cpsr_c, #(CPSR_ABT_MODE AOR CPSR_FIQ_IRQ_BIT)
774 mov r2, lr
775 mrs r1, spsr
776
777 /*
778 * スーパバイザモードに切り換え,戻り番地とspsrを保存する.
779 */
780 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
781 str r2, [sp,#0x1c] /* 戻り番地をスタックに保存 */
782 push {r1} /* spsrをスタックに保存 */
783#else /* __TARGET_ARCH_ARM < 6 */
784 /*
785 * IビットとFビットをセットし,スーパバイザモードに切り換え,スタッ
786 * クポインタを初期化する.
787 */
788 cpsid if,#CPSR_SVC_MODE
789 ldr sp, =istkpt
790 ldr sp, [sp]
791
792 /*
793 * アボートモードに戻して,戻りå…
794ˆï¼ˆlr)とspsr(cpsr_svc)をスーパ
795 * バイザモードのスタックに保存する.
796 */
797 cps #CPSR_ABT_MODE
798 srsfd #CPSR_SVC_MODE!
799
800 /*
801 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
802 */
803 cps #CPSR_SVC_MODE
804 stmfd sp!, {r0-r4,r12,lr}
805#endif /* __TARGET_ARCH_ARM < 6 */
806
807 /*
808 * 例外ネストカウントの最上位ビットを1にする.
809 */
810 ldr r2, =excpt_nest_count
811 ldr r3, [r2]
812 orr r3, r3, #0x80000000
813 str r3, [r2]
814
815 mov r4, #EXCNO_DABORT
816 b exc_handler_1
817
818/*
819 * FIQ
820 */
821#ifndef OMIT_FIQ_HANDLER
822 ATEXT
823 AALIGN(2)
824 AGLOBAL(fiq_handler)
825ALABEL(fiq_handler)
826 /*
827 * ここには,FIQモードで分岐してくる.
828 */
829#if __TARGET_ARCH_ARM < 6
830 /*
831 * IビットとFビットをセットし,スーパバイザモードに切り換え,スク
832 * ラッチレジスタを保存する.
833 */
834 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
835 stmfd sp!, {r0-r4,r12,lr,pc} /* pcはスペース確保のため */
836
837 /*
838 * FIQモードに戻して,戻り番地とspsrを取得する.
839 */
840 msr cpsr_c, #(CPSR_FIQ_MODE AOR CPSR_FIQ_IRQ_BIT)
841 mov r2, lr
842 mrs r1, spsr
843
844 /*
845 * スーパバイザモードに切り換え,戻り番地とspsrを保存する.
846 */
847 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_FIQ_IRQ_BIT)
848 str r2, [sp,#0x1c] /* 戻り番地をスタックに保存 */
849 push {r1} /* spsrをスタックに保存 */
850#else /* __TARGET_ARCH_ARM < 6 */
851 /*
852 * 戻りå…
853ˆï¼ˆlr)とspsr(cpsr_svc)をスーパバイザモードのスタックに
854 * 保存する.
855 */
856 srsfd #CPSR_SVC_MODE!
857
858 /*
859 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
860 */
861 cps #CPSR_SVC_MODE
862 stmfd sp!, {r0-r4,r12,lr}
863#endif /* __TARGET_ARCH_ARM < 6 */
864 mov r4, #EXCNO_FIQ
865 b exc_handler_1
866#endif /* OMIT_FIQ_HANDLER */
867
868ALABEL(end_exc_entry)
869
870/*
871 * CPU例外ハンドラ出å…
872¥å£å‡¦ç†ã®å…
873±é€šéƒ¨åˆ†
874 *
875 * 【この時点のレジスタ状æ…
876‹ã€‘
877 * r0:CPU例外ハンドラ番号
878 */
879ALABEL(exc_handler_1)
880 /*
881 * CPU例外が発生した状況の判断に用いるために,CPU例外発生前の割
882 * 込み優å…
883ˆåº¦ãƒžã‚¹ã‚¯ã¨ä¾‹å¤–ネストカウントをスタックに保存する.
884 */
885 bl irc_get_intpri
886 push {r0} /* 割込み優å…
887ˆåº¦ãƒžã‚¹ã‚¯ã‚’保存 */
888 ldr r2, =excpt_nest_count
889 ldr r3, [r2]
890 push {r3} /* 例外ネストカウントを保存 */
891 mov r12, sp /* CPU例外の情
892報を記憶している領域の */
893 /* å…
894ˆé ­ç•ªåœ°ã‚’r12に保存 */
895 /*
896 * カーネル管理外のCPU例外か判定する
897 *
898 * カーネル管理外のCPU例外は,カーネル実行中,å…
899¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
900‹ï¼Œ
901 * CPUロック状æ…
902‹ï¼Œã‚«ãƒ¼ãƒãƒ«ç®¡ç†å¤–の割込みハンドラ実行中に発生した
903 * CPU例外である.ARMコアの場合は,戻りå…
904ˆã®CPSRのIビットかFビット
905 * のいずれかがセットされているなら,これ該当する.
906 */
907 ldr r1, [r12,#T_EXCINF_cpsr] /* 例外フレームからcpsrを取得 */
908 ands r1, r1, #CPSR_FIQ_IRQ_BIT
909 bne nk_exc_handler_1 /* カーネル管理外のCPU例外の処理へ */
910
911 /*
912 * 【この時点のレジスタ状æ…
913‹ã€‘
914 * r2:excpt_nest_countの番地
915 * r3:excpt_nest_countの値
916 * r4:CPU例外ハンドラ番号
917 * r12:CPU例外の情
918報を記憶している領域のå…
919ˆé ­ç•ªåœ°
920 */
921
922 /*
923 * 例外ネストカウントをインクリメントする.
924 */
925 add r3, r3, #1
926 str r3, [r2]
927 teq r3, #1 /* CPU例外発生前が非タスクコンテキスト */
928 bne exc_handler_2 /* ならexc_handler_2に分岐 */
929
930#ifdef TOPPERS_SUPPORT_OVRHDR
931 /*
932 * オーバランタイマを停止する.
933 */
934 push {r12}
935 bl ovrtimer_stop
936 pop {r12}
937#endif /* TOPPERS_SUPPORT_OVRHDR */
938
939 /*
940 * 非タスクコンテキスト用のスタックに切り換える.
941 */
942 mov r3, sp /* この時点のスタックポインタをr3に */
943 ldr r2, =istkpt /* 非タスクコンテキスト用のスタックに */
944 ldr sp, [r2]
945 push {r3} /* 切換え前のスタックポインタを保存 */
946
947ALABEL(exc_handler_2)
948 /*
949 * 【この時点のレジスタ状æ…
950‹ã€‘
951 * r4:CPU例外ハンドラ番号
952 * r12:CPU例外の情
953報を記憶している領域のå…
954ˆé ­ç•ªåœ°
955 */
956
957 /*
958 * (必
959要なら)割込みコントローラを操作する.
960 */
961 bl irc_begin_exc
962
963 /*
964 * CPUロック解除状æ…
965‹ã«ã™ã‚‹ï¼Ž
966 *
967 * カーネル管理外のCPU例外ハンドラは別ルーチンで呼び出すため,単純
968 * に割込みを許可するだけでよい.
969 */
970#if __TARGET_ARCH_ARM < 6
971 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_UNLOCK)
972#else /* __TARGET_ARCH_ARM < 6 */
973#ifndef TOPPERS_SAFEG_SECURE
974 cpsie if
975#else /* TOPPERS_SAFEG_SECURE */
976 cpsie f
977#endif /* TOPPERS_SAFEG_SECURE */
978#endif /* __TARGET_ARCH_ARM < 6 */
979
980 /*
981 * ログ出力の呼出し
982 */
983#ifdef LOG_EXC_ENTER
984 push {r12}
985 mov r0, r4 /* CPU例外番号をパラメータに渡す */
986 bl log_exc_enter
987 pop {r12}
988#endif /* LOG_EXC_ENTER */
989
990 /*
991 * CPU例外ハンドラの呼出し
992 */
993 ldr r2, =exc_table /* CPU例外ハンドラテーブルの読込み */
994 ldr r3, [r2,r4,lsl #2] /* CPU例外ハンドラの番地 → r3 */
995 mov r0, r12 /* CPU例外の情
996報を記憶している領域の */
997 /* å…
998ˆé ­ç•ªåœ°ã‚’第1パラメータに渡す */
999 mov r1, r4 /* CPU例外番号を第2パラメータに渡す */
1000 mov lr, pc /* CPU例外ハンドラの呼出し */
1001 bx r3
1002
1003 /*
1004 * ログ出力の呼出し
1005 */
1006#ifdef LOG_EXC_LEAVE
1007 mov r0, r4 /* CPU例外番号をパラメータに渡す */
1008 bl log_exc_leave
1009#endif /* LOG_EXC_LEAVE */
1010
1011 /*
1012 * カーネル管理の割込みを禁止する.
1013 */
1014#if __TARGET_ARCH_ARM < 6
1015 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_CPULOCK)
1016#else /* __TARGET_ARCH_ARM < 6 */
1017#ifndef TOPPERS_SAFEG_SECURE
1018 cpsid i
1019#else /* TOPPERS_SAFEG_SECURE */
1020 cpsid if
1021#endif /* TOPPERS_SAFEG_SECURE */
1022#endif /* __TARGET_ARCH_ARM < 6 */
1023
1024 /*
1025 * 割込みコントローラを操作して,割込み優å…
1026ˆåº¦ãƒžã‚¹ã‚¯ã‚’,CPU例外発
1027 * 生時の値に設定する.
1028 */
1029 bl irc_end_exc
1030
1031 /*
1032 * 例外ネストカウントをデクリメントする.
1033 */
1034 ldr r2, =excpt_nest_count
1035 ldr r3, [r2]
1036 subs r3, r3, #1
1037 str r3, [r2]
1038
1039 /*
1040 * タスク用のスタックに戻す.
1041 */
1042 popeq {r1} /* 戻りå…
1043ˆãŒã‚¿ã‚¹ã‚¯ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãªã‚‰ */
1044 moveq sp, r1 /* タスク用のスタックに戻す */
1045 add sp, sp, #8 /* スタック上の情
1046報を捨てる */
1047 beq ret_int_1 /* ret_int_1に分岐 */
1048
1049 /*
1050 * CPU例外処理からのリターン(irq_handler_3と同じ処理内
1051容)
1052 */
1053#if __TARGET_ARCH_ARM < 6
1054 ldmfd sp!, {r0} /* 戻りå…
1055ˆã®cpsrをspsrに設定 */
1056 msr spsr_cxsf, r0
1057 ldmfd sp!, {r0-r4,r12,lr,pc}^ /* コンテキストの復帰 */
1058 /* ^付きなので,spsr → cpsr */
1059#else /* __TARGET_ARCH_ARM < 6 */
1060 ldmfd sp!, {r0-r4,r12,lr}
1061 rfefd sp!
1062#endif /* __TARGET_ARCH_ARM < 6 */
1063
1064/*
1065 * カーネル管理外のCPU例外の出å…
1066¥å£å‡¦ç†
1067 */
1068ALABEL(nk_exc_handler_1)
1069 /*
1070 * 【この時点のレジスタ状æ…
1071‹ã€‘
1072 * r1:CPU例外発生前のCPSRのFビットとIビットの値
1073 * r2:excpt_nest_countの番地
1074 * r3:excpt_nest_countの値
1075 * r4:CPU例外ハンドラ番号
1076 * r12:CPU例外の情
1077報を記憶している領域のå…
1078ˆé ­ç•ªåœ°
1079 */
1080
1081 /*
1082 * 例外ネストカウントをインクリメントする.
1083 */
1084 add r3, r3, #1
1085 str r3, [r2]
1086 teq r3, #1 /* CPU例外発生前が非タスクコンテキスト */
1087 bne nk_exc_handler_2 /* ならnk_exc_handler_2に分岐 */
1088
1089 /*
1090 * 非タスクコンテキスト用のスタックに切り換える.
1091 */
1092 mov r3, sp /* この時点のスタックポインタをr3に */
1093 ldr r2, =istkpt /* 非タスクコンテキスト用のスタックに */
1094 ldr sp, [r2]
1095 push {r3} /* 切換え前のスタックポインタを保存 */
1096
1097ALABEL(nk_exc_handler_2)
1098 /*
1099 * システム状æ…
1100‹ï¼ˆã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã¯é™¤ãï¼‰ã‚’,CPU例外発生時の状æ…
1101‹ã¸
1102 */
1103 orr r1, r1, #CPSR_SVC_MODE
1104 msr cpsr_c, r1
1105
1106 /*
1107 * CPU例外ハンドラの呼出し
1108 */
1109 ldr r2, =exc_table /* CPU例外ハンドラテーブルの読込み */
1110 ldr r3, [r2,r4,lsl #2] /* CPU例外ハンドラの番地 → r3 */
1111 mov r0, r12 /* CPU例外の情
1112報を記憶している領域の */
1113 /* å…
1114ˆé ­ç•ªåœ°ã‚’第1パラメータに渡す */
1115 mov r1, r4 /* CPU例外番号を第2パラメータに渡す */
1116 mov lr, pc /* CPU例外ハンドラの呼出し */
1117 bx r3
1118
1119 /*
1120 * 例外ネストカウントをデクリメントする.
1121 */
1122 ldr r2, =excpt_nest_count
1123 ldr r3, [r2]
1124 subs r3, r3, #1
1125 str r3, [r2]
1126
1127 /*
1128 * タスク用のスタックに戻す.
1129 */
1130 popeq {r1} /* 戻りå…
1131ˆãŒã‚¿ã‚¹ã‚¯ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãªã‚‰ */
1132 moveq sp, r1 /* タスク用のスタックに戻す */
1133 add sp, sp, #8 /* スタック上の情
1134報を捨てる */
1135
1136 /*
1137 * CPU例外処理からのリターン(irq_handler_3と同じ処理内
1138容)
1139 */
1140#if __TARGET_ARCH_ARM < 6
1141 ldmfd sp!, {r0} /* 戻りå…
1142ˆã®cpsrをspsrに設定 */
1143 msr spsr_cxsf, r0
1144 ldmfd sp!, {r0-r4,r12,lr,pc}^ /* コンテキストの復帰 */
1145 /* ^付きなので,spsr → cpsr */
1146#else /* __TARGET_ARCH_ARM < 6 */
1147 ldmfd sp!, {r0-r4,r12,lr}
1148 rfefd sp!
1149#endif /* __TARGET_ARCH_ARM < 6 */
1150
1151/*
1152 * 微少時間待
1153ち
1154 */
1155 ATEXT
1156 AALIGN(2)
1157 AGLOBAL(_sil_dly_nse)
1158ALABEL(_sil_dly_nse)
1159 subs r0, r0, #SIL_DLY_TIM1
1160 bxls lr
1161ALABEL(_sil_dly_nse1)
1162 subs r0, r0, #SIL_DLY_TIM2
1163 bhi _sil_dly_nse1
1164 bx lr
1165
1166/*
1167 * ステータスレジスタの操作関数
1168 *
1169 * Thumbモードではmrs/msr命令が使用できないため,関数として実現して,
1170 * ARMモードに移行して実行する.
1171 */
1172#ifdef __thumb__
1173
1174 ATEXT
1175 AALIGN(2)
1176 AWEAK(current_cpsr)
1177ALABEL(current_cpsr)
1178 mrs r0, cpsr_cxsf
1179 bx lr
1180
1181 AALIGN(2)
1182 AWEAK(set_cpsr)
1183ALABEL(set_cpsr)
1184 msr cpsr_cxsf, r0
1185 bx lr
1186
1187#endif /* __thumb__ */
Note: See TracBrowser for help on using the repository browser.