source: rtos_arduino/trunk/asp_1.9.2/arch/arm_m_gcc/common/core_support.S@ 136

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

ライブラリとOS及びベーシックなサンプルの追加.

File size: 33.2 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) 2008-2015 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
8 *
9 * 上記著作権者
10は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
11 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
12 * 変・再é…
13å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
14 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16 * スコード中に含まれていること.
17 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18 * 用できる形で再é…
19å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
20å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
21 * 者
22マニュアルなど)に,上記の著作権表示,この利用条件および下記
23 * の無保証規定を掲載すること.
24 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
25 * 用できない形で再é…
26å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
27 * と.
28 * (a) 再é…
29å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
30マニュアルなど)に,上記の著
31 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
32 * (b) 再é…
33å¸ƒã®å½¢æ…
34‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
35 * 報告すること.
36 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
37 * 害からも,上記著作権者
38およびTOPPERSプロジェクトをå…
39è²¬ã™ã‚‹ã“と.
40 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
41 * 由に基づく請求からも,上記著作権者
42およびTOPPERSプロジェクトを
43 * å…
44è²¬ã™ã‚‹ã“と.
45 *
46 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
47お
48 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
49 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
50 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
51 * の責任を負わない.
52 *
53 * @(#) $Id: core_support.S 2704 2015-11-21 15:50:12Z ertl-honda $
54 */
55
56/*
57 * プロセッサ依存モジュール アセンブリ言語部(ARM-M用)
58 */
59
60#define TOPPERS_MACRO_ONLY
61#define UINT_C(val) (val) /* uint_t型の定数を作るマクロ */
62#define ULONG_C(val) (val) /* ulong_t型の定数を作るマクロ */
63#define CAST(type, val) (val) /* 型キャストを行うマクロ */
64
65#include "kernel_impl.h"
66#include "arm_m.h"
67#include "offset.h"
68#include "target_asm.inc"
69
70/*
71 * タスクディスパッチャ
72 */
73 ATEXT
74 ABALIGN(4)
75 ATHUMB(dispatch)
76 AGLOBAL(dispatch)
77ALABEL(dispatch)
78 /*
79 *
80 * このルーチンは,タスクコンテキスト・CPUロック状æ…
81‹ãƒ»ãƒ‡ã‚£ãƒ‘ッチ許可状æ…
82‹
83 * ・(モデル上の)割込み優å…
84ˆåº¦ãƒžã‚¹ã‚¯å…
85¨é–‹çŠ¶æ…
86‹ã§å‘¼ã³å‡ºã•ã‚Œã‚‹ï¼Ž
87 */
88 stmfd sp!,{r4-r11,lr} /* レジスタの保存 */
89#ifdef TOPPERS_FPU_CONTEXT
90 /*
91 * ディスパッチå…
92ƒã®ã‚¿ã‚¹ã‚¯FPUを使用した場合はFPUレジスタを保存
93 */
94 mrs r0, control /* CONTROL.FPCA == 0(FPU未使用)ならばスキップ */
95 tst r0, #CONTROL_FPCA
96 beq dispatch_1
97 vpush {s16-s31} /* FPUレジスタの保存 */
98ALABEL(dispatch_1)
99 push {r0} /* 復帰時の判定用にCONTROLを保存 */
100#endif /* TOPPERS_FPU_CONTEXT */
101 ldr r0, =p_runtsk /* p_runtskを読み込む */
102 ldr r1, [r0]
103 str sp, [r1,#TCB_sp] /* タスクスタックを保存 */
104 ldr lr, =dispatch_r /* 実行再開番地を保存 */
105 str lr, [r1,#TCB_pc]
106 b dispatcher
107
108 ATHUMB(dispatch_r)
109 AGLOBAL(dispatch_r)
110ALABEL(dispatch_r)
111#ifdef TOPPERS_FPU_CONTEXT
112 /*
113 * ディスパッチå…
114ˆã®ã‚¿ã‚¹ã‚¯ã§FPUを使用していた場合はFPUレジスタを復帰
115 * スタックに保存したCONTROL.FPCAをチェック
116 */
117 pop {r3}
118 tst r3, #CONTROL_FPCA /* CONTROL.FPCA == 0(FPU未使用)ならばスキップ */
119 beq dispatch_r_0
120 vpop {s16-s31} /* FPUレジスタの復帰 */
121ALABEL(dispatch_r_0)
122#endif /* TOPPERS_FPU_CONTEXT */
123 ldmfd sp!,{r4 - r11,lr} /* レジスタの復帰 */
124 /*
125 * タスク例外処理ルーチンの起動
126 * dispatcherから呼び出されるため,TCBのアドレスはr1にå…
127¥ã£ã¦ã„ã‚‹
128 */
129 ldrb r0,[r1,#TCB_enatex]
130 tst r0,#TCB_enatex_mask
131 beq dispatch_r_1 /* enatex が false ならリターン */
132 ldr r0,[r1,#TCB_texptn] /* texptn が 0 ならリターン */
133 tst r0,r0
134 beq dispatch_r_1
135 ldr r1, =ipmflg /* ipmflgが false ならリターン */
136 ldr r0, [r1]
137 tst r0,r0
138 beq dispatch_r_1
139 ldr r0, =call_texrtn /* タスク例外ルーチンの呼び出し */
140 bx r0
141ALABEL(dispatch_r_1) /* タスクへのcall_textnから戻る */
142 bx lr
143
144/*
145 * CPU例外エントリ
146 *
147 * 割込みエントリと処理の内
148容は同等だが,ログの種類が異なるため,
149 * 分けている.
150 */
151 ABALIGN(4)
152 ATEXT
153 ATHUMB(core_exc_entry)
154 AGLOBAL(core_exc_entry)
155ALABEL(core_exc_entry)
156 /*
157 * 例外/割込みが発生すると,発生時にアクティブなスタックにスクラ
158 * ッチレジスタ等が保存される.
159 * この内
160容に加えて,CPU例外ハンドラへの情
161報として,basepri の値と,
162 * EXC_RETURNの情
163報を加えて保存する.basepriの値は,CPU例外からの
164 * リターン時に割込み優å…
165ˆåº¦ãƒžã‚¹ã‚¯ã®å€¤ã‚’å…
166ƒã«æˆ»ã™ãŸã‚ã«ã‚‚用いられる.
167 *
168 * -----------
169 * | basepri |
170 * -----------
171 * | EXC_RETURN|
172 * -----------
173 * | R0 |
174 * -----------
175 * | R1 |
176 * -----------
177 * | R2 |
178 * -----------
179 * | R3 |
180 * -----------
181 * | R12 |
182 * -----------
183 * | LR |
184 * -----------
185 * | PC |
186 * -----------
187 * | xPSR |
188 * -----------
189 *
190 */
191
192 /*
193 * カーネル管理外の例外かチェック
194 * カーネル内
195のクリティカルセクションの実行中,å…
196¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
197‹ï¼Œ
198 * CPUロック状æ…
199‹ï¼Œã‚«ãƒ¼ãƒãƒ«ç®¡ç†å¤–の割込みハンドラ実行中のいずれかで
200 * 発生したCPU例外を,カーネル管理外のCPU例外と呼ぶ
201 * å…
202¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
203‹ã¯FAULTMASKが'1'の場合
204 * CPUロック状æ…
205‹ã¯basepriがIIPM_LOCKかで判断する.
206 */
207 mrs r2, FAULTMASK /* å…
208¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
209‹ãªã‚‰ã‚«ãƒ¼ãƒãƒ«ç®¡ç†å¤–例外処理へ */
210 cbnz r2, core_nonkernel_exc_entry
211
212 mrs r0, basepri /* baepriの値を取得 */
213 cmp r0, #IIPM_LOCK /* CPUロック状æ…
214‹ãªã‚‰ã‚«ãƒ¼ãƒãƒ«ç®¡ç†å¤–例外処理へ */
215 beq core_nonkernel_exc_entry
216
217 /*
218 * スタックを変更する必
219要があるかチェック
220 * EXC_RETURN(割込み時にLRに設定される値)をチェックして,例外発生時に
221 * アクティブなスタックを特定することで多重割込みか判定する.
222 */
223 tst lr, #EXC_RETURN_PSP /* 割込みå…
224ƒãŒMSPなら多重割込み */
225 beq core_exc_entry_1 /* 多重割込みならcore_exc_entry_1へ */
226 mrs r3, psp /* 一段目の割込みの場合はPSP上に */
227 stmfd r3!, {r0, lr} /* 割込み発生時の割込み優å…
228ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にPSP上に積む */
229 msr psp, r3
230 push {r0,lr} /* 割込み発生時の割込み優å…
231ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にMSP上に積む */
232 mov r0, r3 /* CPU例外ハンドラへの引数となる */
233 b core_exc_entry_2
234ALABEL(core_exc_entry_1) /* 多重割込みの場合 */
235 push {r0,lr} /* 割込み発生時の割込み優å…
236ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にPSP上に積む */
237 mov r0, sp /* CPU例外ハンドラへの引数となる */
238
239 /*
240 * å…
241±é€šå‡¦ç†
242 */
243ALABEL(core_exc_entry_2)
244 mrs r3, ipsr /* ハンドラアドレスを取得 */
245 ldr r1, =_kernel_exc_tbl
246 ldr r2, [r1, r3, lsl #2]
247
248#ifdef LOG_EXC_ENTER
249 push {r0,r2,r3}
250 mov r0, r3 /* 例外番号をパラメータに */
251 bl log_exc_enter /* log_exc_enterを呼び出す */
252 pop {r0,r2,r3}
253 push {r3} /* 例外番号をスタックへ */
254#endif /* LOG_EXC_ENTER */
255
256 /*
257 * CPU例外ハンドラの呼び出し
258 */
259 blx r2
260
261#ifdef LOG_EXC_ENTER
262 pop {r0} /* 例外番号を引数に */
263 bl log_exc_leave /* log_exc_leaveを呼び出す */
264#endif /* LOG_EXC_ENTER */
265
266 b ret_exc
267
268/*
269 * カーネル管理外のCPU例外の出å…
270¥å£å‡¦ç†
271 */
272ALABEL(core_nonkernel_exc_entry)
273 tst lr, #EXC_RETURN_PSP /* 割込みå…
274ƒãŒMSPなら多重割込み */
275 beq core_nonkernel_exc_entry_1 /* 多重割込みなら */
276 mrs r3, psp /* 一段目の割込みの場合はPSP上に */
277 stmfd r3!, {r0, lr} /* 割込み発生時の割込み優å…
278ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にPSP上に積む */
279 msr psp, r3
280 push {r0,lr} /* 割込み発生時の割込み優å…
281ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にMSP上に積む */
282 mov r0, r3 /* CPU例外ハンドラへの引数となる */
283 b core_nonkernel_exc_entry_2
284ALABEL(core_nonkernel_exc_entry_1) /* 多重割込みの場合 */
285 push {r0,lr} /* 割込み発生時の割込み優å…
286ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にPSP上に積む */
287 mov r0, sp /* CPU例外ハンドラへの引数となる */
288
289ALABEL(core_nonkernel_exc_entry_2)
290 mrs r3, ipsr /* CPU例外ハンドラのアドレスを取得 */
291 ldr r1, =_kernel_exc_tbl
292 ldr r2, [r1, r3, lsl #2]
293
294 /*
295 * CPU例外ハンドラの呼び出し
296 */
297 blx r2
298
299 /*
300 * 割込みロック状æ…
301‹ã¨ã™ã‚‹ï¼Ž
302 */
303 cpsid f
304
305 /*
306 * 戻りå…
307ˆã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã®åˆ¤å®š
308 *
309 * 割込みハンドラ実行にLRにセットされるEXC_RETURNをチェックして,戻り
310 * å…
311ˆã§MSPが使われていれば,割込みå…
312ˆãŒéžã‚¿ã‚¹ã‚¯ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã¨åˆ¤å®šã™ã‚‹ï¼Ž
313 */
314 pop {r1,r3} /* å…
315ƒã®å‰²è¾¼ã¿å„ªå…
316ˆåº¦ãƒžã‚¹ã‚¯(basepri)をr1へ,EXC_RETURNをr3へ */
317 tst r3, #EXC_RETURN_PSP /* 戻りå…
318ˆãŒPSPなら */
319 bne core_nonkernel_ret_exc_1
320 b core_nonkernel_ret_exc_2 /* の値をMSPから取得 */
321
322ALABEL(core_nonkernel_ret_exc_1)
323 /*
324 * PSP上から,EXC_RETURN(r0)とå…
325ƒã®å‰²è¾¼ã¿å„ªå…
326ˆåº¦ãƒžã‚¹ã‚¯(basepri)分を削除
327 */
328 mrs r2, psp
329 add r2, r2, #(0x04*2)
330 msr psp, r2
331
332ALABEL(core_nonkernel_ret_exc_2)
333 msr basepri, r1 /* 割込み優å…
334ˆåº¦ãƒžã‚¹ã‚¯ã‚’割込み前に状æ…
335‹ã¸ */
336 bx r3 /* リターン */
337
338/*
339 * 割込みエントリ
340 */
341 ATHUMB(core_int_entry)
342 AGLOBAL(core_int_entry)
343ALABEL(core_int_entry)
344 /*
345 * 割込み発生時の割込み優å…
346ˆåº¦ãƒžã‚¹ã‚¯ã‚’スタックに保存するため取得
347 */
348 mrs r0, basepri /* baepriの値を取得 */
349
350 /*
351 * 多重割込みかチェック
352 * EXC_RETURN(割込み時にLRに設定される値)をチェックして,例外発生時に
353 * アクティブなスタックを特定することで多重割込みか判定する.
354 */
355 tst lr, #EXC_RETURN_PSP /* 割込みå…
356ƒãŒMSPなら多重割込み */
357 beq core_int_entry_1 /* 多重割込みならcore_int_entry_1へ */
358 mrs r3, psp /* 一段目の割込みの場合はPSP上に */
359 stmfd r3!, {r0, lr} /* 割込み発生時の割込み優å…
360ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にPSP上に積む */
361 msr psp, r3
362 push {r0,lr} /* 割込み発生時の割込み優å…
363ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にMSP上に積む */
364 mov r0, r3 /* 未定義の割込みが発生した場合の情
365報とする */
366 b core_int_entry_2
367ALABEL(core_int_entry_1) /* 多重割込みの場合 */
368 push {r0,lr} /* 割込み発生時の割込み優å…
369ˆåº¦ãƒžã‚¹ã‚¯(r0),EXC_RETURN(lr)の順にPSP上に積む */
370 mov r0, sp /* 未定義の割込みが発生した場合の情
371報とする */
372
373 /*
374 * å…
375±é€šå‡¦ç†
376 */
377ALABEL(core_int_entry_2)
378 mrs r3, ipsr /* ハンドラアドレスを取得 */
379 ldr r1, =_kernel_exc_tbl
380 ldr r2, [r1, r3, lsl #2]
381
382 /*
383 * basepriの設定
384 * NVIC優å…
385ˆåº¦ãƒžã‚¹ã‚¯ãŒè‡ªå‹•çš„に設定されるため優å…
386ˆåº¦ãƒžã‚¹ã‚¯ã®ç‚¹ã§ã¯å¿…
387要な
388 * いが,x_get_ipm()がbasepriを参ç…
389§ã™ã‚‹ãŸã‚ï¼Œbasepriも更新する.
390 */
391 ldr r1, =_kernel_int_iipm_tbl
392 ldr lr, [r1, r3, lsl #2]
393 msr basepri, lr
394
395#ifdef LOG_INH_ENTER
396 push {r0,r2,r3}
397 mov r0, r3 /* 例外番号をパラメータに */
398 bl log_inh_enter /* log_exc_enterを呼び出す */
399 pop {r0,r2,r3}
400#endif /* LOG_EXC_ENTER */
401
402#ifdef LOG_INH_LEAVE
403 push { r3 } /* 例外番号をスタックへ */
404#endif /* LOG_INT_LEAVE */
405
406 /*
407 * 割込みハンドラの呼び出し
408 */
409 blx r2
410
411#ifdef LOG_INH_LEAVE
412 pop {r0} /* 例外番号を引数に */
413 bl log_exc_leave /* log_exc_leaveを呼び出す */
414#endif /* LOG_INH_LEAVE */
415
416/*
417 * 割込み/例外出口
418 *
419 * ret_exc/ret_intは,CPU例外/割込みハンドラから戻った直後に実行する
420 * ルーチンである.
421 */
422ALABEL(ret_exc)
423ALABEL(ret_int)
424 /*
425 * 割込みロック状æ…
426‹ã¨ã™ã‚‹ï¼Žã“の時点では,CPUロック状æ…
427‹ã«ã¯ãªã‚‰ãªã„
428 * (basepriとlock_flagとsaved_iipmは更新しない).
429 *
430 * 割込みロック状æ…
431‹ã¨ã™ã‚‹ã®ã¯ï¼Œæˆ»ã‚Šå…
432ˆã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã®ãƒã‚§ãƒƒã‚¯ã¨ï¼Œ
433 * 戻りå…
434ˆãŒéžã‚¿ã‚¹ã‚¯ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã§ã‚った場合のリターンをアトミック
435 * に行うためである.bsepriをCPUロックの値にすることでもアトミッ
436 * クなチェックと復帰は可能であるが,割込みからリターンしても,
437 * basepri の設定内
438容はå…
439ƒã«æˆ»ã‚‰ãªã„ため,使用することができない.
440 * 一方,FAULTMASKは,割込みからのリターン処理によって,'0'にクリ
441 * アされる.
442 */
443 cpsid f
444
445 /*
446 * 戻りå…
447ˆã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã®åˆ¤å®š
448 *
449 * 割込みハンドラ実行にLRにセットされるEXC_RETURNをチェックして,戻り
450 * å…
451ˆã§MSPが使われていれば,割込みå…
452ˆãŒéžã‚¿ã‚¹ã‚¯ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã¨åˆ¤å®šã™ã‚‹ï¼Ž
453 */
454 pop {r1,r3} /* å…
455ƒã®å‰²è¾¼ã¿å„ªå…
456ˆåº¦ãƒžã‚¹ã‚¯(basepri)をr1へ,EXC_RETURNをr3へ */
457 tst r3, #EXC_RETURN_PSP /* 戻りå…
458ˆãŒPSPなら ret_int_1 へ */
459 bne ret_int_1
460 b ret_int_2 /* の値をMSPから取得 */
461
462 /*
463 * 一段目の割込みの出口処理
464 */
465ALABEL(ret_int_1)
466 /*
467 * reqflgをチェックする
468 *
469 * カーネル管理内
470の割込みは禁止した状æ…
471‹ã§å®Ÿè¡Œã™ã‚‹å¿…
472要があるため,
473 * FAULTMASKを'1'にした状æ…
474‹ã§å®Ÿè¡Œã™ã‚‹ï¼Ž
475 * reqflgをチェックする前に割込みを禁止するのは,reqflgをチェック
476 * した直後に割込みハンドラが起動され,その中でディスパッチが要求
477 * された場合に,すぐにディスパッチされないという問題が生じるため
478 * である.
479 */
480 ldr r0, =reqflg /* reqflgがfalseならそのまま戻る */
481 ldr r2, [r0]
482 cbnz r2, ret_int_3 /* trueならret_int_3へ */
483
484 /*
485 * PSP上から,EXC_RETURN(r0)とå…
486ƒã®å‰²è¾¼ã¿å„ªå…
487ˆåº¦ãƒžã‚¹ã‚¯(basepri)分を削除
488 */
489 mrs r2, psp
490 add r2, r2, #(0x04*2)
491 msr psp, r2
492
493ALABEL(ret_int_2)
494 /*
495 * ここには割込みロック状æ…
496‹ï¼ˆFAULTMASKがセット)された状æ…
497‹ã§æ¥ã‚‹ï¼Ž
498 * Threadモードからのリターンにより自動的に割込みロック解除状æ…
499‹ã«ãªã‚‹ï¼Ž
500 * 割込み優å…
501ˆåº¦ãƒžã‚¹ã‚¯ã¯å‰²è¾¼ã¿å‰ã«çŠ¶æ…
502‹ã«æˆ»ã™ï¼Ž
503 */
504 msr basepri, r1 /* 割込み優å…
505ˆåº¦ãƒžã‚¹ã‚¯ã‚’割込み前の状æ…
506‹ã¸ */
507 bx r3 /* リターン */
508
509ALABEL(ret_int_3)
510 /*
511 * ここでは,戻りå…
512ˆãŒã‚¿ã‚¹ã‚¯ã§ã‚り,PSP上にスクラッチレジスタと割
513 * 込み優å…
514ˆåº¦ãƒžã‚¹ã‚¯(basepri)が保存された状æ…
515‹ã«ãªã£ã¦ã„る.また,
516 * プロセッサは,Handlerモード・割込みロック状æ…
517‹ã¨ãªã£ã¦ã„る.
518 * また,r0には,reqflgのアドレス,r3には割込み受付時のlrの値が保
519 * 持されている.
520 */
521 /*
522 * タスク例外ハンドラやディスパッチをする際にThreadモードへ遷移する
523 * ダミーのスタックフレームを作成して,bx命令でHandlerモードからリ
524 * ターンする.また,遅
525延ディスパッチする場合も,再び割り込んだタス
526 * クに戻る際には,svc命令で,svc_handlerを呼び出す.
527 * スタックフレームは,Configureation and Control Register(CCR)の
528 * STKALIGNが'1'の場合は,8byte境界にアラインされる.
529 * 参考 : DDI0403B_arm_architecture_v7m_reference_manual(P.220)
530 * そのため,この時点のスタックは割込みや例外発生時に作成された
531 * スタックフレームから,8byte境界のサイズにしておくと,svc_handler
532 * 等でスタックフレームのアライメントの有無の確認を省略できる.
533 * ただし,システム起動後は,動的にCCRのSTKALIGNの設定を変更するのは
534 * 禁止とする.
535 * この時点は標準のスタックフレームは,割込み・例外発生時と同等であ
536 * るため,タスクスタック(PSP)は8byte境界になっている.
537 */
538 mov r1, #0 /* reqflgをfalseに */
539 str r1, [r0]
540
541 /*
542 * CPUロック状æ…
543‹ã«ç§»è¡Œã™ã‚‹ï¼Ž
544 *
545 * カーネルの管理内
546の割込みを禁止するようにbasepriを設定し,
547 * lock_flag と saved_iipm を更新する.saved_iipmは,戻りå…
548ˆã®å‰²è¾¼ã¿
549 * 優å…
550ˆåº¦ãƒžã‚¹ã‚¯ï¼ˆã®å†…
551部表現)に設定する.
552 * この時点でCPUロック状æ…
553‹ã¨ã™ã‚‹ã®ã¯ï¼Œdispatcherへ分岐する時と,
554 * call_texrtnを呼び出す時に,CPUロック状æ…
555‹ã«ãªã£ã¦ã„ã‚‹å¿…
556要がある
557 * ためである.
558 * なお,この処理の後,Threadモードへの移行処理を行なうため,割込み
559 * ロック状æ…
560‹(FAULTMASKを"1")は保持する.
561 */
562 ldr r1, =IIPM_LOCK /* CPUロック状æ…
563‹ */
564 msr basepri, r1
565 mov r1, #0x01 /* lock_flag を trueに */
566 ldr r0, =lock_flag
567 str r1, [r0]
568
569 /*
570 * 割込み優å…
571ˆåº¦ãƒžã‚¹ã‚¯ã‚’,å…
572¨è§£é™¤çŠ¶æ…
573‹ï¼ˆTIPM_ENAALL)に設定する
574 * すでにCPUロック状æ…
575‹ãªã®ã§ï¼Œsaved_iipmをIIPM_ENAALLとする.
576 */
577 ldr r1, =IIPM_ENAALL
578 ldr r0, =saved_iipm
579 str r1, [r0]
580
581 /*
582 * Threadモードへ移行する.
583 *
584 * dispatcherやcall_texrnを呼び出す場合は,Threadモードである必
585
586 * 要があるため,PSPスタック上にダミーの例外フレームを置いて,
587 * 擬似的に割込みハンドラからリターンする.
588 * リターンと同時にFAULTMASKが自動的にクリアされ,カーネル管理外の
589 * 割込みが許可される.
590 */
591 ldr r0, =ret_int_4 /* PC */
592 ldr r1, =EPSR_T /* xPSR(Tビットが'1'である必
593要がある) */
594 mrs r2, psp
595 stmfd r2!, {r0-r1} /* ダミーフレームをスタック上に積む */
596 subs r2, #(EXC_FRAME_SIZE - (4*2)) /* r0-r3,r12,lrの内
597容は設定する必
598要がない */
599 msr psp,r2
600 /* Basicフレーム,THREADモード,PSPのための EXC_RETURN */
601 mov r0, #(EXC_RETURN_TREAD_PSP|EXC_RETURN_OTHER|EXC_RETURN_FP_NONUSED)
602 bx r0 /* Threadモードへ移行 */
603
604ALABEL(ret_int_4)
605 /*
606 * 上記の処理により,Threadモードで実行される.
607 * dspflgがfalseである場合と,p_runtskとp_schedtskが同じ場合には,
608 * ディスパッチを行わない.このチェックが必
609要なのは,タスク例外処
610 * 理ルーチンの呼出しが必
611要な場合に,ディスパッチが必
612要なくても,
613 * reqflgをtrueにするためである.
614 */
615 ldr r0, =p_runtsk /* ディスパッチを行わない場合でも,r1にp_runtsk の値(TCB) */
616 ldr r1, [r0] /* がå…
617¥ã£ã¦ã„ã‚‹å¿…
618要があるので,å…
619ˆã«èª­ã¿è¾¼ã‚€ */
620 ldr r0, =dspflg
621 ldr r2, [r0]
622 cbz r2, ret_int_r_1 /* dspflgがfalseならret_int_r_1へ */
623 ldr r0, =p_schedtsk
624 ldr r2, [r0]
625 cmp r1, r2 /* p_runtskとp_schedtskが同じなら */
626 beq ret_int_r_1 /* ret_int_r_1へ */
627#ifdef TOPPERS_FPU_CONTEXT
628 ldr r3, [sp,4] /* ディスパッチå…
629ƒã®EXC_RETURNを取得 */
630 /*
631 * ディスパッチå…
632ƒã®ã‚¿ã‚¹ã‚¯FPUを使用した場合はFPUレジスタを保存
633 */
634 tst r3, #EXC_RETURN_FP
635 bne ret_int_5 /* EXC_RETURN[4] == 1(FPU未使用)ならばスキップ */
636 vpush {s16-s31} /* FPUレジスタの保存 */
637ALABEL(ret_int_5)
638 push {r3} /* 戻りå…
639ˆã®EXC_RETURNを保存 */
640#endif /* TOPPERS_FPU_CONTEXT */
641 stmfd sp!, {r4-r11} /* 残りのレジスタを保存 */
642 str sp, [r1,#TCB_sp] /* タスクスタックを保存 */
643 ldr lr, =ret_int_r /* 実行再開番地を保存 */
644 str lr, [r1,#TCB_pc]
645 b dispatcher /* ディスパッチャへ */
646
647/*
648 * 割込みによりプリエンプトされたタスクへのリターン処理
649 *
650 * Threadモードで,ディスパッチャや割込みの出口処理から呼び出される.
651 * 割込みによりプリエンプトされたタスクへリターンするには,いったん
652 * Handlerモードに移行し,PCに0xfffffffdを代å…
653¥ã—てリターンする必
654要
655 * がある.そのため,SVCにより,SVCハンドラを呼び出し,Handlerモー
656 * ドへ移行する.
657 */
658 ATHUMB(ret_int_r)
659 AGLOBAL(ret_int_r)
660ALABEL(ret_int_r)
661 pop {r4-r11} /* レジスタの復帰 */
662#ifdef TOPPERS_FPU_CONTEXT
663 pop {r3} /* 戻りå…
664ˆã®EXC_RETURNを取得 */
665 /*
666 * ディスパッチå…
667ƒã®ã‚¿ã‚¹ã‚¯FPUを使用した場合はFPUレジスタを復帰
668 */
669 tst r3, #EXC_RETURN_FP
670 bne ret_int_r_1 /* EXC_RETURN[4] == 1(FPU未使用)ならばスキップ */
671 vpop {s16-s31} /* FPUレジスタの復帰 */
672#endif /* TOPPERS_FPU_CONTEXT */
673ALABEL(ret_int_r_1)
674 /*
675 * enatexがtrueで,texptnが0でなければ,タスク例外処理ルーチンを
676 * 呼び出す.
677 * dispatcherから呼び出されるため,TCBのアドレスはr1にå…
678¥ã£ã¦ã„ã‚‹
679 */
680 ldrb r0, [r1,#TCB_enatex]
681 tst r0, #TCB_enatex_mask
682 beq ret_int_r_2 /* enatex が false なら ret_int_r_2へ */
683 ldr r0, [r1,#TCB_texptn] /* texptn が 0 ならリターン */
684 cbz r0, ret_int_r_2
685 ldr r1, =ipmflg /* ipmflgが false ならリターン */
686 ldr r0, [r1]
687 cbz r0, ret_int_r_2
688#ifdef TOPPERS_FPU_LAZYSTACKING
689 /*
690 * Lazy Stacking かつ 割込みの出口処理からの分岐で来た場合は
691 * ここでFPU命令を実行して例外フレームにFPUのコンテキストを書き戻す必
692要がある
693 * 他の状況では必
694要ないが,判断が困難なため一律実行する.
695 */
696 vmov r3, s15
697#endif /* TOPPERS_FPU_LAZYSTACKING */
698 bl call_texrtn /* タスク例外ルーチンの呼び出し */
699ALABEL(ret_int_r_2)
700#ifdef TOPPERS_FPU_CONTEXT
701 /*
702 * SVCの実行でFPUコンテキストをスタックに積まないように
703 * CONTROL.FPCAをクリア
704 */
705 mrs r3, control
706 bic r3, r3, #CONTROL_FPCA
707 msr control, r3
708#endif /* TOPPERS_FPU_CONTEXT */
709 svc 0 /* SVCの呼び出し */
710
711/*
712 * SVCハンドラ
713 */
714 ATHUMB(svc_handler)
715 AGLOBAL(svc_handler)
716ALABEL(svc_handler)
717 /*
718 * 割込み処理からのリターンにより,CPUロック解除状æ…
719‹ã«ç§»è¡Œã™ã‚‹ã‚ˆ
720 * う準備する.
721 */
722 cpsid f /* 割込みロック状æ…
723‹ã¸ */
724 mrs r0, psp
725 adds r0, #EXC_FRAME_SIZE /* スタックを捨てる */
726 ldmfd r0!,{r1,lr} /* EXC_RETURNは,FPU使用時・未使用時で異なるためスタックから取得 */
727 msr psp, r0
728 mov r0, #0
729 ldr r1, =lock_flag /* CPUロック解除状æ…
730‹ã¸ */
731 str r0, [r1]
732 ldr r1, =IIPM_ENAALL /* 割込み優å…
733ˆåº¦ãƒžã‚¹ã‚¯ã‚’å…
734¨è§£é™¤çŠ¶æ…
735‹ã«è¨­å®š */
736 msr basepri, r1
737 bx lr /* リターン */
738
739/*
740 * ディスパッチャの動作開始
741 */
742 ATHUMB(start_dispatch)
743 AGLOBAL(start_dispatch)
744ALABEL(start_dispatch)
745 /*
746 * このルーチンは,カーネル起動時に,すべての割込みを禁止した状æ…
747‹
748 * (割込みロック状æ…
749‹ã¨åŒç­‰ï¼‰ã§å‘¼ã³å‡ºã•ã‚Œã‚‹ï¼Žã¾ãŸï¼Œå‰²è¾¼ã¿ãƒ¢ãƒ¼ãƒ‰ï¼ˆéž
750 * タスクコンテキストと同等)で呼び出されることを想定している.
751 *
752 * core_initializeで,lock_flagをtrueに,saved_iipmをIIPM_ENAALLに
753 * 初期化しているため,カーネル管理外の割込みを許可することで,
754 * CPUロック状æ…
755‹ãƒ»ï¼ˆãƒ¢ãƒ‡ãƒ«ä¸Šã®ï¼‰å‰²è¾¼ã¿å„ªå…
756ˆåº¦ãƒžã‚¹ã‚¯å…
757¨è§£é™¤çŠ¶æ…
758‹ã«ãªã‚‹ï¼Ž
759 * また,task_initializeでdisdspをfalseに初期化しているため,ディ
760 * スパッチ許可状æ…
761‹ã«ãªã£ã¦ã„る.
762 */
763 ldr r0,=istkpt /* MSPを初期化 */
764 ldr r1,[r0] /* start_dispatch呼び出し時に呼び出し用に */
765 msr msp, r1 /* 使用しているため初期化する */
766 ldr r1, =IIPM_LOCK /* カーネル管理内
767の割込みを禁止 */
768 msr basepri, r1
769 cpsie f /* カーネル管理外の割込みを許可 */
770 mov r0, #CONTROL_PSP /* PSPを有効に */
771 msr control, r0
772 isb /* control の操作後に必
773要 */
774
775/*
776 * 現在のコンテキストを捨ててディスパッチ
777 */
778 ATHUMB(exit_and_dispatch)
779 AGLOBAL(exit_and_dispatch)
780ALABEL(exit_and_dispatch)
781 /* ディスパッチャ本体(dispatcher)へ */
782
783/*
784 * ディスパッチャ本体
785 */
786ALABEL(dispatcher)
787 /*
788 * このルーチンは,タスクコンテキスト・CPUロック状æ…
789‹ãƒ»ãƒ‡ã‚£ã‚¹ãƒ‘ッチ
790 * 許可状æ…
791‹ãƒ»ï¼ˆãƒ¢ãƒ‡ãƒ«ä¸Šã®ï¼‰å‰²è¾¼ã¿å„ªå…
792ˆåº¦ãƒžã‚¹ã‚¯å…
793¨è§£é™¤çŠ¶æ…
794‹ã§å‘¼ã³å‡ºã•
795 * れる.
796 *
797 * すなわち,Threadモード・lock_flagがtrue・disdspがfalse・dspflg
798 * がtrue・saved_iipmがIIPM_ENAALLとなっている.実行再開番地へもこ
799 * の状æ…
800‹ã®ã¾ã¾åˆ†å²ã™ã‚‹ï¼Ž
801 */
802#ifdef TOPPERS_FPU_CONTEXT
803 mrs r3, control /* ディスパッチャ実行時はFPCAを一律クリアする */
804 bic r3, r3, #CONTROL_FPCA
805 msr control, r3
806#endif /* TOPPERS_FPU_CONTEXT */
807#ifdef LOG_DSP_ENTER
808 ldr r1, =p_runtsk /* p_runtskをパラメータに */
809 ldr r0, [r1]
810 bl log_dsp_enter
811#endif /* LOG_DSP_ENTER */
812ALABEL(dispatcher_0)
813 ldr r0, =p_schedtsk /* p_schedtskをp_runtskに */
814 ldr r1, [r0]
815 ldr r2, =p_runtsk
816 str r1, [r2]
817 cbz r1, dispatcher_1 /* p_runtskがNULLならdispatcher_1へ */
818 ldr sp, [r1,#TCB_sp] /* タスクスタックを復帰 */
819#ifdef LOG_DSP_LEAVE
820 mov r0, r1 /* p_runtskをパラメータに */
821 mov r4, r1 /* r1はスクラッチレジスタなので保存 */
822 bl log_dsp_leave
823 mov r1, r4
824#endif /* LOG_DSP_LEAVE */
825 ldr pc, [r1,#TCB_pc] /* 実行再開番地を復帰 */
826ALABEL(dispatcher_1)
827 /*
828 * CPUロック状æ…
829‹ã®è§£é™¤ã¨ï¼Œéžã‚¿ã‚¹ã‚¯ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆå®Ÿè¡ŒçŠ¶æ…
830‹ã¸ã®
831 * 準備をする
832 */
833 mov r0, #CONTROL_MSP /* MSPを有効に */
834 msr control, r0
835 isb /* control の操作後に必
836要 */
837 mov r4, #0 /* r4 <- '0' */
838 ldr r5, =IIPM_LOCK /* r5 <- 割込みロック状æ…
839‹ã®å‰²è¾¼ã¿å„ªå…
840ˆåº¦ãƒžã‚¹ã‚¯ã®å€¤ */
841 ldr r6, =reqflg /* r6 <- reqflg */
842 ldr r7, =lock_flag /* r7 <- lock_flg */
843 str r4, [r7] /* CPUロック解除状æ…
844‹ã¸ */
845ALABEL(dispatcher_2)
846 /*
847 * 割込みを許可し,非タスクコンテキスト実行状æ…
848‹ã¨ã—割込みを待
849つ.
850 *
851 * ここで非タスクコンテキスト実行状æ…
852‹ã«åˆ‡ã‚Šæ›ãˆã‚‹ã®ã¯ï¼Œã“こで発生
853 * する割込み処理にどのスタックを使うかという問題の解決と,割込み
854 * ハンドラ内
855でのタスクディスパッチの防止という2つの意味がある.
856 *
857 * プロセッサを割込み待
858ちに移行させる処理と,割込み許可とは,不可
859 * 分に行なう必
860要がある.
861 * これを不可分に行なわない場合,割込みを許可した直後に割込
862 * みがå…
863¥ã‚Šï¼Œãã®ä¸­ã§ã‚¿ã‚¹ã‚¯ãŒå®Ÿè¡Œå¯èƒ½çŠ¶æ…
864‹ã«ãªã‚‹ã¨ï¼Œå®Ÿè¡Œã™ã¹ãã‚¿ã‚¹
865 * クがあるにもかかわらずプロセッサが割込み待
866ちになってしまう.
867 * ARM-Mでは,PRIMASKをセットした状æ…
868‹ã§WFIを呼び出すことで実現できる.
869 * この状æ…
870‹ã§å‰²è¾¼ã¿ãŒå…
871¥ã‚‹ã¨ï¼Œå‰²è¾¼ã¿ã¯å®Ÿè¡Œã•ã‚Œãšï¼ŒWFIからリターンす
872 * ることになるので,一旦割込みを許可して割込みハンドラを実行する.
873 *
874 * 割込み待
875ちの間は,p_runtskをNULL(=0)に設定しなければならな
876 * い.このように設定しないと,割込みハンドラからiget_tidを呼び出
877 * した際の動作が仕様に合致しなくなる.
878 *
879 * ターゲットによっては,省電力モード等に移行するため,標準の方法と
880 * 異なる手順が必
881要な場合がある.
882 * そのようなターゲットでは,ターゲット依存において,TOPPERS_CUSTOM_IDLE
883 * を定義し,アセンブラマクロとして,toppers_asm_custom_idle を用意
884 * すればよい.
885 *
886 * なお,toppers_asm_custom_idle の記述にあたっては,次のレジスタは
887 * toppers_asm_custom_idleの前後で使用するため,
888 * toppers_asm_custom_idle 内
889で使用する場合は,前後で保存復帰すること.
890 * これらのレジスタは Calee saved レジスタであるため,
891 * toppers_asm_custom_idle として関数呼び出しをした場合は,呼び出した
892 * 関数で自動的に保存復帰されるため,アセンブラレベルでの保存復帰は必
893
894 * 要ない.
895 *
896 * レジスタ : 内
897容
898 * r4 : '0'
899 * r5 : 'IIPM_LOCK'
900 * r6 : reqflgのアドレス
901 * r7 : lock_flgのアドレス
902 * sp : 非タスクコンテキスト用のスタックのå…
903ˆé ­ã‚¢ãƒ‰ãƒ¬ã‚¹(msp)
904 */
905#ifdef TOPPERS_CUSTOM_IDLE
906 toppers_asm_custom_idle
907#else
908 cpsid i /* PRIMASK をセット */
909 msr basepri, r4 /* å…
910¨å‰²è¾¼ã¿è¨±å¯ */
911 wfi
912 cpsie i /* PRIMASK をクリア(割込みを受け付ける) */
913 msr basepri, r5 /* CPUロック状æ…
914‹ã¸ */
915#endif /* TOPPERS_CUSTOM_IDLE */
916
917 ldr r0, [r6] /* reqflgがfalseならdispatcher_2へ */
918 cmp r0, #0
919 beq dispatcher_2
920 str r4, [r6] /* reqflgをfalseに */
921
922 /*
923 * CPUロック状æ…
924‹ã«æˆ»ã™ï¼Žå‰²è¾¼ã¿å¾…
925ちの間に実行した割込みハンドラによ
926 * り,saved_iipmが書き換えられる可能性があるため,å…
927ƒã®å€¤ã«æˆ»ã™å¿…
928
929 * 要がある.dispatcherが実行される時は,saved_iipmがIIPM_ENAALL
930 * となっているため,ここではsaved_iipmをIIPM_ENAALL(=0)に戻せ
931 * ばよい.
932 */
933 mov r0, #CONTROL_PSP /* PSPを有効に */
934 msr control, r0
935 isb /* control の操作後に必
936要 */
937 mov r2, #1 /* lock_flagをtrueへ */
938 str r2, [r7]
939 ldr r0, =saved_iipm /* saved_iipm を0に */
940 str r4, [r0]
941 b dispatcher_0
942
943
944/*
945 * カーネルの終了処理の呼出し
946 *
947 * スタックを非タスクコンテキスト用に切り替え.
948 *
949 */
950 ATHUMB(call_exit_kernel)
951 AGLOBAL(call_exit_kernel)
952ALABEL(call_exit_kernel)
953 mov r0, #CONTROL_MSP
954 msr control, r0 /* MSPを有効に */
955 isb /* control の操作後に必
956要 */
957 ldr r0, =exit_kernel /* カーネルの終了処理を呼ぶ */
958 bx r0
959
960
961/*
962 * タスク起動処理
963 *
964 * dispatcherから呼び出されるため,TCBのアドレスはr1にå…
965¥ã£ã¦ã„ã‚‹
966 *
967 */
968 ATHUMB(start_r)
969 AGLOBAL(start_r)
970ALABEL(start_r)
971 mov r0, #0
972 ldr r4, =lock_flag /* CPUロック解除状æ…
973‹ã¸ */
974 str r0, [r4]
975 msr basepri, r0 /* 割込み許可 */
976 ldr lr, =ext_tsk /* 戻り番地設定 */
977 ldr r2, [r1, #TCB_p_tinib] /* p_runtsk->p_tinibをr2に */
978 ldr r0, [r2, #TINIB_exinf] /* exinfを引数レジスタr0に */
979 ldr r1, [r2, #TINIB_task] /* タスク起動番地にジャンプ */
980 bx r1
981
982/*
983 * 微少時間待
984ち
985 */
986 ABALIGN(4)
987 ATEXT
988 ATHUMB(sil_dly_nse)
989 AGLOBAL(sil_dly_nse)
990ALABEL(sil_dly_nse)
991 subs r0, r0, #SIL_DLY_TIM1
992 cmp r0, #0
993 bgt sil_dly_nse1
994 bx lr
995ALABEL(sil_dly_nse1)
996 subs r0, r0, #SIL_DLY_TIM2
997 cmp r0, #0
998 bgt sil_dly_nse1
999 bx lr
Note: See TracBrowser for help on using the repository browser.