source: asp3_wo_tecs/trunk/arch/arm_gcc/doc/arm_design.txt@ 306

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

3.1.0を反映

File size: 41.3 KB
Line 
1
2 TOPPERS/ASP3カーネル
3 ARMコア依存部 設計メモ
4
5 対応バージョン: Release 3.1.0
6 最終更新: 2016年5月14日
7
8----------------------------------------------------------------------
9 TOPPERS/ASP Kernel
10 Toyohashi Open Platform for Embedded Real-Time Systems/
11 Advanced Standard Profile Kernel
12
13 Copyright (C) 2014-2016 by Embedded and Real-Time Systems Laboratory
14 Graduate School of Information Science, Nagoya Univ., JAPAN
15
16 上記著作権者
17は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
18 ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
19 変・再é…
20å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
21 (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
22 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
23 スコード中に含まれていること.
24 (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
25 用できる形で再é…
26å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
27å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
28 者
29マニュアルなど)に,上記の著作権表示,この利用条件および下記
30 の無保証規定を掲載すること.
31 (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
32 用できない形で再é…
33å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
34 と.
35 (a) 再é…
36å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
37マニュアルなど)に,上記の著
38 作権表示,この利用条件および下記の無保証規定を掲載すること.
39 (b) 再é…
40å¸ƒã®å½¢æ…
41‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
42 報告すること.
43 (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
44 害からも,上記著作権者
45およびTOPPERSプロジェクトをå…
46è²¬ã™ã‚‹ã“と.
47 また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
48 由に基づく請求からも,上記著作権者
49およびTOPPERSプロジェクトを
50 å…
51è²¬ã™ã‚‹ã“と.
52
53 本ソフトウェアは,無保証で提供されているものである.上記著作権者
54お
55 よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
56 に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
57 アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
58 の責任を負わない.
59
60 $Id: arm_design.txt 751 2016-05-14 15:03:06Z ertl-hiro $
61----------------------------------------------------------------------
62
63○目次
64
65・略号
66・参考文献
67・ARMコア依存部の位置づけ
68 - Thumb命令の扱い
69・システム状æ…
70‹ã®ç®¡ç†
71 - プロセッサモード
72 - カーネル管理外の割込み
73 - å…
74¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
75‹ã®ç®¡ç†
76 - コンテキストの管理
77 - CPUロック状æ…
78‹ã®ç®¡ç†
79 - 割込み優å…
80ˆåº¦ãƒžã‚¹ã‚¯ã®ç®¡ç†
81 - 割込み要求禁止フラグの管理
82 - 割込みに関するその他の操作
83 - CPSR(Program Status Register)の設定値
84・例外(割込みハンドラおよびCPU例外ハンドラ)の出å…
85¥å£
86 - ARMv6より前のプロセッサの場合
87 - ARMv6以降のプロセッサの場合
88・割込みハンドラの出å…
89¥å£å‡¦ç†
90・CPU例外ハンドラの出å…
91¥å£å‡¦ç†
92 - スタックポインタが不正の場合の対策
93
94○略号
95
96CPSR Current Program Status Register
97FIQ Fast Interrupt Request
98GIC Generic Interrupt Controller
99IRQ Interrupt Request
100
101○参考文献
102
103[1] TOPPERSプロジェクト 設計メモ「ARMのアーキテクチャに関するメモ」.
104
105○ARMコア依存部の位置づけ
106
107ARMコア依存部は,カーネルのターゲット依存部の中で,ARMv4,ARMv5,ARMv6,
108ARMv7-A,ARMv7-Rに準拠したプロセッサコアを持つターゲットシステム(チッ
109プ)にå…
110±é€šã«ä½¿ç”¨ã§ãã‚‹éƒ¨åˆ†ã§ã‚る.ただし,これに該当するすべてのARMコア
111に対応できているわけではない.新しいチップにポーティングする際には,コ
112ア依存部に何らかの修正が必
113要になることも多いと思われる.
114
115ARMコアのプロセッサコア略称を"arm"とする.GNU開発環境向けのARMコア依存
116部を置くディレクトリはarch/arm_gcc/commonとなる.
117
118ARMの場合,割込みコントローラはコアの外にあることから,割込みコントロー
119ラに依存する部分はARMコア依存部に含めないことを原則とするが,多くのチッ
120プに採用されている割込みコントローラであるGIC(ARM Generic Interrupt
121Controller)に依存する部分(GIC依存部)は,ARMコア依存部のディレクトリ
122に置いている.GIC依存部の設計については,「GIC依存部 設計メモ」を参ç…
123§ã™
124ること.
125
126なお,ARMコア依存部は,ARMアーキテクチャのバージョン番号(4〜7のいずれ
127か)が,__TARGET_ARCH_ARMにマクロ定義されているものとして記述してある.
128
129●Thumbモードの扱い
130
131アプリケーションプログラムとカーネルのC言語で記述された部分は,Thumbモー
132ド向けにコンパイルしても動作するようにする.それに対して,カーネルのア
133センブリ言語記述の部分は,ARM命令で記述し,Thumbモードで実行することは
134考えない.
135
136○システム状æ…
137‹ã®ç®¡ç†
138
139●プロセッサモード
140
141ASP3カーネルのARMコア依存部では,アプリケーションプログラムとカーネルの
142大部分を,スーパバイザモードで実行する.例外のå…
143¥å£ã§ãã‚Œãžã‚Œã®ãƒ—ロセッ
144サモードに切り換わるが,å…
145¥å£å‡¦ç†ã®ä¸­ã§ã‚¹ãƒ¼ãƒ‘バイザモードに戻すため,あ
146くまでカーネルの内
147部で一時的に他のモードを使うに過ぎない.
148
149割込み処理の実行にIRQモードを使わないのは,次の理由である.IRQモードで
150実行中に割込みが発生すると,lrレジスタに戻り番地が格納される.そのため,
151割込み処理をIRQモードを実行すると,多重割込みによりlrレジスタの内
152容が失
153われるため,多重割込みを許可することができない.
154
155アプリケーションプログラムとカーネルの大部分の実行にシステムモードを使
156わない理由は,以下の通りである.
157
158(1) ARMv5以前のプロセッサでは,例外からの復帰を,
159
160 ldmfd sp!, {<復帰すべきレジスタのリスト>, pc}^
161
162の命令で行う.この命令は,例外モードでのみ使用することができ,システム
163モードでは使用できない(システムモードにはSPSRがないため,CPSRを復帰で
164きない).そのため,割込みハンドラやCPU例外ハンドラをシステムモードで実
165行すると,例外からのリターン時に,余計なプロセッサモード切換えとそれに
166伴うスタック操作が必
167要になり,効率が悪い.
168
169ARMv6以降のプロセッサでは,例外からの復帰のためにrfe命令を持っているが,
170rfe命令にはシステムモードでは使用できないという制約がないために,このこ
171とは当てはまらない.
172
173(2) 保護機能対応カーネルにおいては,例外のå…
174¥å£ã§ï¼Œãƒ¦ãƒ¼ã‚¶ã‚¹ã‚¿ãƒƒã‚¯ã‹ã‚‰ã‚·
175ステムスタックに切り換える処理が必
176要であるが,アプリケーションプログラ
177ムの非特権モードで実行すべき部分をユーザモードで,アプリケーションプロ
178グラムの特権モードで実行すべき部分とカーネルの大部分をスーパバイザモー
179ドを実行すれば,スタックの切換えがハードウェアで行われ,効率的である.
180
181逆に,アプリケーションプログラムとカーネルの大部分をシステムモードで実
182行するメリットとして,以下を挙げることができる.
183
184・スーパバイザモードで実行中にsvc命令を発行すると,lrレジスタに戻り番地
185 が格納される.lrが壊れる想定でsvc命令を呼び出せばよいが,プログラムに
186 パッチを当てる目的でsvc命令を使う場合など,lrを保存/復帰する余地がな
187 い場合には,スーパバイザモードで実行しているとうまく実装
188できない.
189
190保護機能対応でないASP3カーネルで,ARMv6以降のプロセッサを使用する場合に
191は,アプリケーションプログラムとカーネルの大部分をシステムモードで実行
192するように修正するのは容易である.å…
193·ä½“的には,core_support.Sとstart.S内
194
195の約20箇所程度のCPSR_SVC_MODEを,CPSR_SYS_MODEに書き換えればよい.
196
197●カーネル管理外の割込み
198
199ARMコア依存部の標準では,IRQをカーネル管理の割込み,FIQをカーネル管理外
200の割込みと扱う.このようにするのが,最もシンプルで性能が良いためである.
201
202ただし,SafeGのセキュアモードでASP3カーネルを動作させる場合には,FIQを
203カーネル管理の割込みとして扱い,カーネル管理外の割込みはサポートしない.
204IRQは,ノンセキュアモードで動作するOSが使用する.この設定にする場合には,
205TOPPERS_SAFEG_SECUREをマクロ定義する.
206
207●å…
208¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
209‹ã®ç®¡ç†
210
211å…
212¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
213‹ã§ã¯ï¼ŒFIQ・IRQともマスクする.å…
214·å¤–的には,CPSR中のFビッ
215ト(FIQ禁止)とIビット(IRQ禁止)をセットする.
216
217●コンテキストの管理
218
219実行中のコンテキストをプロセッサモードで判断することができないため,例
220外(割込みハンドラおよびCPU例外ハンドラ)のネスト段数を変数(これを,例
221外ネストカウントと呼ぶ)で管理し,例外ネストカウントが0の時にタスクコン
222テキスト,0より大きい場合に非タスクコンテキストであると判断する.
223
224●CPUロック状æ…
225‹ã®ç®¡ç†
226
227CPUロック状æ…
228‹ã§ã¯ï¼ŒIRQをマスクする.å…
229·å¤–的には,CPSR中のIビット(IRQ禁
230止)をセットする.å…
231¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
232‹ã¨CPUロック状æ…
233‹ã‚’区別できる必
234要はな
235いことから,CPSR中のIビットが立っていれば,CPUロック状æ…
236‹ã§ã‚ると判断す
237る.
238
239TOPPERS_SAFEG_SECUREがマクロ定義されている場合には,CPUロック状æ…
240‹ã§ã¯ï¼Œ
241FIQをマスクする.IRQは常にマスクするため,FIQ・IRQともマスクすることに
242なる.CPSR中のFビットが立っていれば,CPUロック状æ…
243‹ã§ã‚ると判断する.
244
245●割込み優å…
246ˆåº¦ãƒžã‚¹ã‚¯ã®ç®¡ç†
247
248割込み優å…
249ˆåº¦ãƒžã‚¹ã‚¯ã®ç®¡ç†ã¯ï¼Œå‰²è¾¼ã¿ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ã«ã‚ˆã£ã¦è¡Œã†ï¼Žãã®ãŸã‚ï¼Œ
250ARM依存部には含めない.
251
252GICの場合には,GICC_PMR(Interrupt Priority Mask Register)により,割込
253み優å…
254ˆåº¦ãƒžã‚¹ã‚¯ã‚’管理する.
255
256●割込み要求禁止フラグの管理
257
258割込み要求禁止フラグの管理は,割込みコントローラによって行う.そのため,
259ARM依存部には含めない.
260
261GICの場合には,GICD_ISENABLEn(Interrupt Set-Enable Registers)と
262GICD_ICENABLERn(Interrupt Clear-Enable Registers)によって,セット/ク
263リアする.
264
265●割込みに関するその他の操作
266
267割込みに関するその他の操作は,割込みコントローラによって実現する.その
268ため,ARM依存部には含めない.
269
270GICの場合には,割込み要求のクリアとプローブは,GICD_ICPENDRn(Interrupt
271Clear-Pending Registers)とGICD_ISPENDRn(Interrupt Set-Pending
272Registers)によって実現する.
273
274●CPSR(Program Status Register)の設定値
275
276CPUロック・å…
277¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯è§£é™¤çŠ¶æ…
278‹ï¼ŒCPUロック状æ…
279‹ï¼Œå…
280¨å‰²è¾¼ãƒ­ãƒƒã‚¯çŠ¶æ…
281‹ã¨ã™
282るCPSRの設定値を,以下のように定義しておく.
283
284#define CPSR_UNLOCK UINT_C(0x00)
285#define CPSR_CPULOCK CPSR_IRQ_BIT
286#define CPSR_INTLOCK CPSR_FIQ_IRQ_BIT
287
288TOPPERS_SAFEG_SECUREがマクロ定義されている場合には,以下のように定義す
289る.
290
291#define CPSR_UNLOCK CPSR_IRQ_BIT
292#define CPSR_CPULOCK CPSR_FIQ_IRQ_BIT
293#define CPSR_INTLOCK CPSR_FIQ_IRQ_BIT
294
295ここで,CPSR_IRQ_BITとCPSR_FIQ_BITは,それぞれIRQとFIQをマスクする場合
296のCPSRの値,CPSR_FIQ_IRQ_BITは,FIQ・IRQともマスクする場合のCPSRの値で
297あり,以下のように定義しておく.
298
299#define CPSR_IRQ_BIT UINT_C(0x80)
300#define CPSR_FIQ_BIT UINT_C(0x40)
301#define CPSR_FIQ_IRQ_BIT (CPSR_FIQ_BIT|CPSR_IRQ_BIT)
302
303○例外(割込みハンドラおよびCPU例外ハンドラ)の出å…
304¥å£
305
306SRS命令とRFE命令を持つARMv6以降と,それより前のプロセッサでは,例外の出
307å…
308¥å£ï¼ˆå‰²è¾¼ã¿ãƒãƒ³ãƒ‰ãƒ©ãŠã‚ˆã³CPU例外ハンドラの出å…
309¥å£å‡¦ç†ã®æœ€åˆã¨æœ€å¾Œã®éƒ¨åˆ†ï¼‰
310の最適なコードが異なる.
311
312●ARMv6より前のプロセッサの場合
313
314アーキテクチャの想定では,例外からの復帰を,
315
316 ldmfd sp!, {<復帰すべきレジスタのリスト>, pc}^
317
318の命令で行う.この時点で,戻り番地がスタックの最後(最も大きい番地)に
319保存されており,戻りå…
320ˆã®CPSRがこのモードのSPSRに置かれていることが必
321要
322である.
323
324例外の出å…
325¥å£å‡¦ç†ã§ï¼Œã™ã¹ã¦ã®ã‚¹ã‚¯ãƒ©ãƒƒãƒãƒ¬ã‚¸ã‚¹ã‚¿ã‚’保存/復帰することにす
326ると,上の命令の<復帰すべきレジスタのリスト>には,すべてのスクラッチレ
327ジスタのリストを記述する.また,例外からのリターンでモードが変わらない
328(どちらもスーパバイザモードである)ため,復帰するレジスタに,lrも加え
329ておくことが必
330要である.
331
332å…
333·ä½“的には,例外の出口は,次のようなコードとなる.
334
335----------------------------------------
336 /*
337 * この時点ではスーパバイザモードになっている.
338 */
339 ldmfd sp!, {r0} /* 戻りå…
340ˆã®cpsrをspsrに復帰 */
341 msr spsr_cxsf, r0
342 ldmfd sp!, {r0-r5,r12,lr,pc}^ /* 例外処理からの復帰 */
343----------------------------------------
344
345ここで,スクラッチレジスタに加えてr4とr5も復帰しているのは,例外の出å…
346¥
347口処理でスクラッチレジスタ以外に使えるレジスタとして,r4とr5を確保する
348ためである(実際には,r4だけが使えれば十分であるが,スタックポインタを
3498バイト境界にアラインするためにr5も保存/復帰している).
350
351この出口を実行する時点で,スタックは次のようになっている必
352要がある(レ
353ジスタはいずれもCPU例外発生時の値を示す.例えば,CPSRはCPU例外発生時の
354CPSRを示す).
355
356 +----------------+ <- sp
357 | cpsr |
358 +----------------+ <- sp+0x04
359 | r0 |
360 +----------------+ <- sp+0x08
361 | r1 |
362 +----------------+ <- sp+0x0c
363 | r2 |
364 +----------------+ <- sp+0x10
365 | r3 |
366 +----------------+ <- sp+0x14
367 | r4 |
368 +----------------+ <- sp+0x18
369 | r5 |
370 +----------------+ <- sp+0x1c
371 | r12 |
372 +----------------+ <- sp+0x20
373 | lr |
374 +----------------+ <- sp+0x24
375 | 戻り番地 |
376 +----------------+ <- sp+0x28
377
378これに対応する例外のå…
379¥å£ã¯ï¼Œæ¬¡ã®ã‚³ãƒ¼ãƒ‰ã¨ãªã‚‹ï¼ˆIRQの場合).
380
381----------------------------------------
382 /*
383 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
384 */
385 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_IRQ_BIT)
386 stmfd sp!, {r0-r5,r12,lr,pc} /* pcはスペース確保のため */ (*1)
387
388 /*
389 * IRQモードに戻して,戻り番地とspsr(戻りå…
390ˆã®cpsr)を取得する.
391 */
392 msr cpsr_c, #(CPSR_IRQ_MODE AOR CPSR_IRQ_BIT)
393 sub r2, lr, #4
394 mrs r1, spsr
395
396 /*
397 * スーパバイザモードに切り換え,戻り番地とspsrを保存する.
398 */
399 msr cpsr_c, #(CPSR_SVC_MODE AOR CPSR_IRQ_BIT)
400 str r2, [sp,#0x20] /* 戻り番地をスタックに保存 */ (*2)
401 push {r1} /* spsrをスタックに保存 */
402----------------------------------------
403
404(*1)でpcを保存するのは,戻り番地を保存すべきスペースを確保するためであ
405り,その時点で保存するpcの値は使わない.(*2)で,確保したスペースに戻り
406番地を格納する.格納å…
407ˆã‚’[sp,#0x20]とするのは,この時点ではspは上の図の
408(sp+0x04)を指しており,戻り番地は(sp+0x24)に格納したいためである.
409
410例外を受け付けるとIビットをセットするため,例外のå…
411¥å£ãŒå®Ÿè¡Œã•ã‚Œã‚‹æ™‚点で,
412CPSRのIビットはセットされている.IRQの場合,IRQが受け付けられたというこ
413とは,受付前の時点ではIビットはクリアされていたはずであるため,Fビット
414はクリアされている(Iビットがセットされており,Fビットがクリアされてい
415る状況は作らないため).よって,上記のコードで,IビットとFビットは変化
416しない.
417
418IRQ以外の例外(CPU例外ハンドラ)の出å…
419¥å£ã«ãŠã„ては,上記のコードに対し
420て,次の修正を加える.
421
422・Iビットだけではなく,Fビットもセットする.å…
423·ä½“的には,3箇所にある
424 CPSR_IRQ_BITを,CPSR_FIQ_IRQ_BITに置き換える.
425
426・戻り番地を取得する時に,lrから4を減算しない(実際に戻るべき番地になっ
427 ているとは限らない).
428
429・戻り番地とspsrを取得する時に,IRQモードではなく,そのCPU例外で遷移す
430 るモードに戻す(スーパバイザコールの場合は,戻す必
431要がない).
432
433IビットだけでなくFビットもセットするのは,(1) FIQを受け付けるとFビット
434もセットされる,(2) その他の例外はFビットがセットされている状æ…
435‹ã§ã‚‚受け
436付けられる,の2つの理由からである.ただし,Fビットがクリアされている時
437に発生した(FIQ以外の)例外では,この処理によりFビットがセットされるこ
438とになり,カーネル管理外の割込みがマスクされる期間が長くなるが,CPU例外
439ハンドラを呼び出すまでの短時間なので,許容することにする.
440
4413つめの処理(スーパバイザモードに切り換えと,戻り番地とspsrの保存)は,
442(IRQ以外の)すべての例外でå…
443±é€šã§ã‚るため,exc_handler_1のå…
444ˆé ­ã§å®Ÿæ–½ã™
445ることもできるが,ARMv6以降のプロセッサの場合とのå…
446±é€šåŒ–のために,例外毎
447に個別に実施する.
448
449●ARMv6以降のプロセッサの場合
450
451例外からの復帰にrfe命令を用いると,例外の出口は,次のようなコードとなる.
452
453----------------------------------------
454 ldmfd sp!, {r0-r5,r12,lr}
455 rfefd sp!
456----------------------------------------
457
458ここで,スクラッチレジスタに加えてr4とr5も復帰しているのは,例外の出å…
459¥
460口処理でスクラッチレジスタ以外に使えるレジスタとして,r4とr5を確保する
461ためである(実際には,r4だけが使えれば十分であるが,スタックポインタを
4628バイト境界にアラインするためにr5も保存/復帰している).
463
464この出口を実行する時点で,スタックは次のようになっている必
465要がある(レ
466ジスタはいずれもCPU例外発生時の値を示す.例えば,CPSRはCPU例外発生時の
467CPSRを示す).
468
469 +----------------+ <- sp
470 | r0 |
471 +----------------+ <- sp+0x04
472 | r1 |
473 +----------------+ <- sp+0x08
474 | r2 |
475 +----------------+ <- sp+0x0c
476 | r3 |
477 +----------------+ <- sp+0x10
478 | r4 |
479 +----------------+ <- sp+0x14
480 | r5 |
481 +----------------+ <- sp+0x18
482 | r12 |
483 +----------------+ <- sp+0x1c
484 | lr |
485 +----------------+ <- sp+0x20
486 | 戻り番地 |
487 +----------------+ <- sp+0x24
488 | cpsr |
489 +----------------+ <- sp+0x28
490
491これに対応する例外のå…
492¥å£ã¯ï¼Œæ¬¡ã®ã‚ˆã†ãªã‚³ãƒ¼ãƒ‰ã¨ãªã‚‹ï¼ˆIRQの場合).
493
494----------------------------------------
495 /*
496 * 戻りå…
497ˆï¼ˆlr)とspsr(cpsr_svc)をスーパバイザモードのスタックに
498 * 保存する.
499 */
500 sub lr, lr, #4 /* 戻り番地の算出 */
501 srsfd #CPSR_SVC_MODE!
502
503 /*
504 * スーパバイザモードに切り換え,スクラッチレジスタを保存する.
505 */
506 cps #CPSR_SVC_MODE
507 stmfd sp!, {r0-r5,r12,lr}
508----------------------------------------
509
510IRQ以外の例外(CPU例外ハンドラ)の出å…
511¥å£ã«ãŠã„ては,上記のコードに対し
512て,次の修正を加える.
513
514・戻り番地の算出のためにlrから4を減算しない(実際に戻るべき番地になって
515 いるとは限らない).
516
517後半の処理(スーパバイザモードへの切換えとスクラッチレジスタの保存)は
518å…
519±é€šã ãŒï¼Œã“の直後でCPU例外ハンドラ番号を格納するためにr4を使うため,
520exc_handler_1の方へ移動できない.
521
522○割込みハンドラの出å…
523¥å£å‡¦ç†
524
525ASP3カーネル ポーティングガイドに従って,割込みハンドラの出å…
526¥å£å‡¦ç†ã®å®Ÿ
527装
528方法を検討していく.
529
530----------------------------------------
531void
532<割込みの出å…
533¥å£å‡¦ç†>(void)
534{
535 少なくともカーネル管理の割込みを禁止した状æ…
536‹ã«ã™ã‚‹ … (*d)
537 スクラッチレジスタをスタックに保存する
538----------------------------------------
539
540ARMコアは,例外を受け付けると,CPSR中のIビットをセットして割込みを禁止
541するため,(*d)の処理は必
542要ない.スクラッチレジスタの保存は,例外のå…
543¥å£
544で実装
545済みである.
546
547----------------------------------------
548 if (割込みがタスクコンテキストで発生) {
549----------------------------------------
550
551まず,例外ネストカウントをインクリメントする.インクリメント後の値が1で
552ない場合には,非タスクコンテキストでの割込み発生であるため,この後の{}
553内
554の処理をスキップする(irq_handler_1に分岐).
555
556----------------------------------------
557#ifdef TOPPERS_SUPPORT_OVRHDR
558 ovrtimer_stop(); /* オーバランタイマの停止 */
559#endif /* TOPPERS_SUPPORT_OVRHDR */
560 スタックを非タスクコンテキスト用のスタックに切り換え,
561 非タスクコンテキストに切り換える
562 }
563----------------------------------------
564
565スタックを非タスクコンテキスト用のスタックに切り換え,切り換え前のスタッ
566クポインタを切り換え後のスタック上に保存する.これらの処理の後に,
567irq_handler_1ラベルを置く.
568
569----------------------------------------
570 割込み優å…
571ˆåº¦ãƒžã‚¹ã‚¯ã‚’,受け付けた割込みの割込み優å…
572ˆåº¦ã«è¨­å®šã™ã‚‹
573
574 CPUロック解除状æ…
575‹ã«ã™ã‚‹ï¼ˆå—け付けた割込みよりも優å…
576ˆåº¦ã®é«˜ã„割込みを
577 受け付けるようにする)
578
579 割込みハンドラのå…
580¥å£ã§å¿…
581要なIRCの操作を行う(割込み要求ラインがエッ
582 ジトリガである場合のトリガされた割込み要求のクリアなど)
583----------------------------------------
584
585割込み優å…
586ˆåº¦ãƒžã‚¹ã‚¯ã®ç®¡ç†ã¯ï¼Œãƒãƒƒãƒ—依存の割込みコントローラによって行う
587必
588要があるため,上記の処理の順序を一部変更し,上記の処理の中で「CPUロッ
589ク解除状æ…
590‹ã«ã™ã‚‹ã€ä»¥å¤–の処理は,チップ依存部のirc_begin_intで行うことと
591する.すなわち,irc_begin_intは,割込み優å…
592ˆåº¦ãƒžã‚¹ã‚¯ã‚’受け付けた割込み要
593求の割込み優å…
594ˆåº¦ã«è¨­å®šã—,割込みハンドラのå…
595¥å£ã§å¿…
596要なIRCの操作を行う.
597またirc_begin_intは,割込み番号(0から始まる番号で,割込みハンドラ番号
598と一致させる)を返すようにする.スプリアス割込みの場合には,
599irc_begin_intは割込み番号の最大値より大きい値を返すものとし,その場合に
600は,割込みハンドラの呼出し処理をスキップする(irq_handler_2に分岐).
601
602その後,irc_begin_intで行わなかった「CPUロック解除状æ…
603‹ã«ã™ã‚‹ã€å‡¦ç†ã‚’è¡Œ
604う.å…
605·ä½“的には,CPSR中のFビットとIビット(ただし,TOPPERS_SAFEG_SECURE
606の場合は,Fビットのみ)をクリアして,割込みを許可する.
607
608----------------------------------------
609#ifdef LOG_INH_ENTER
610 log_inh_enter(割込みハンドラ番号);
611#endif /* LOG_INH_ENTER */
612 割込みハンドラを呼び出す
613#ifdef LOG_INH_LEAVE
614 log_inh_leave(割込みハンドラ番号);
615#endif /* LOG_INH_LEAVE */
616----------------------------------------
617
618割込みハンドラテーブル(inh_table)から割込みハンドラの番地を取り出して
619呼び出す.
620
621----------------------------------------
622 割込みハンドラの出口で必
623要なIRCの操作を行う(IRCに対する割込み処理
624 の終了通知など)
625
626 少なくともカーネル管理の割込みを禁止した状æ…
627‹ã«ã™ã‚‹
628
629 割込み優å…
630ˆåº¦ãƒžã‚¹ã‚¯ã‚’,割込みを受け付ける前の値に戻す … (*e)
631----------------------------------------
632
633割込みハンドラの呼出し前の処理の順序を一部変更したのに対応して,まず,
634カーネル管理の割込みを禁止する.å…
635·ä½“的には,CPSR中のIビット(ただし,
636TOPPERS_SAFEG_SECUREの場合は,Fビットも)をセットする.この処理の後に,
637irq_handler_2ラベルを置く.
638
639次に,チップ依存部のirc_end_intを呼び出す.irc_end_intでは,割込みハン
640ドラの出口で必
641要なIRCの操作を行い,割込み優å…
642ˆåº¦ãƒžã‚¹ã‚¯ã‚’割込み処理前の状
643æ…
644‹ã«æˆ»ã™ï¼Ž
645
646コア依存部からは,irc_end_intにパラメータを渡さないため,irc_end_intの
647中で必
648要な情
649報(例えば,割込み番号)は,irc_begin_intでスタックのå…
650ˆé ­ã«
651保存しておく必
652要がある.これに用いるために,スタックのå…
653ˆé ­ã«1ワードの空
654き領域を設けている.
655
656irc_end_intで必
657要な情
658報が1ワードで不足する場合には,irc_begin_intでスタッ
659クに積み,irc_end_intでスタックから取り出す.これを可能にするために,
660irc_begin_intが呼び出されたら,irc_end_intも必
661ず呼び出されるようにして
662おく.スプリアス割込みの場合にも,irc_end_intを呼び出すようにしている.
663サブルーチン(irc_begin_int)の中でスタックに積み増すのは,一般には採用
664しないプログラミング技法であるが,irc_begin_intからirc_end_intに渡す情
665
666報は,チップ依存部によって異なること,ARMでは戻り番地をlrに保存するため
667スタックに積み増すのが容易であることから,この方法を採用することにした.
668
669----------------------------------------
670 ret_int:
671 if (割込みがタスクコンテキストで発生) {
672----------------------------------------
673
674まず,例外ネストカウントをデクリメントする.デクリメント後の値が0でない
675場合には,非タスクコンテキストでの割込み発生であるため,{}内
676の処理をス
677キップする(irq_handler_3に分岐).
678
679----------------------------------------
680 スタックをタスク用のスタックに戻し,タスクコンテキストに切り換える
681 … (*f)
682----------------------------------------
683
684タスクコンテキストのスタックポインタは,この時点で,スタックのå…
685ˆé ­ã«ä¿
686存されているため,スタックのå…
687ˆé ­ã‚’取り出して,スタックポインタに設定す
688る.
689
690----------------------------------------
691 if (p_runtsk != p_schedtsk) {
692----------------------------------------
693
694この処理の前に,ret_int_1ラベルを置く.p_runtskとp_schedtskが一致しない
695時は,irq_handler_4へ分岐する.
696
697----------------------------------------
698 CPUロック状æ…
699‹ã«ã™ã‚‹ … (*g)
700 割込み優å…
701ˆåº¦ãƒžã‚¹ã‚¯ã¯ï¼Œå…
702¨è§£é™¤çŠ¶æ…
703‹ï¼ˆTIPM_ENAALL)になって
704 いなければならない … (*h)
705----------------------------------------
706
707(*g)の処理は,irc_end_intを呼び出す前に行ったカーネル管理の割込みを禁止
708する処理で十分であるため,ここでは行わない.(*h)については,
709irc_end_intで割込み優å…
710ˆåº¦ãƒžã‚¹ã‚¯ã‚’割込み処理前の状æ…
711‹ã«æˆ»ã™ã“とで,満たさ
712れているはずである.
713
714----------------------------------------
715 if (p_runtsk != NULL) {
716 スクラッチレジスタを除くすべてのレジスタをスタックに保存する
717 スタックポインタを自タスク(p_runtsk)のTCBに保存する
718 ret_int_rを,実行再開番地として自タスクのTCBに保存する … (*a)
719#ifdef LOG_DSP_ENTER
720 log_dsp_enter(p_runtsk);
721#endif /* LOG_DSP_ENTER */
722 }
723 dispatcherに分岐する
724
725 ret_int_r:
726 スクラッチレジスタを除くすべてのレジスタをスタックから復帰する
727#ifdef TOPPERS_SUPPORT_OVRHDR
728 ovrtimer_start(); /* オーバランタイマの動作開始 */
729#endif /* TOPPERS_SUPPORT_OVRHDR */
730 }
731----------------------------------------
732
733この辺りは素直に実装
734できる.
735
736----------------------------------------
737#ifdef TOPPERS_SUPPORT_OVRHDR
738 else {
739 if (p_runtsk != NULL) {
740 ovrtimer_start(); /* オーバランタイマの動作開始 */
741 }
742 }
743#endif /* TOPPERS_SUPPORT_OVRHDR */
744 }
745----------------------------------------
746
747このelse部は,p_runtskとp_schedtskが一致しており,タスク切換えが必
748要な
749かった場合の処理である.else部の{}の中の処理のå…
750ˆé ­ã«ï¼Œirq_handler_4ラベ
751ルを置く.オーバランハンドラをサポートしない場合は,irq_handler_4のラベ
752ルを,irq_handler_3と同じ場所(後述)に置く.これにより,上の処理をスキッ
753プする.
754
755----------------------------------------
756 スクラッチレジスタをスタックから復帰する
757 割込み処理からのリターン後に,CPUロック解除状æ…
758‹ã«æˆ»ã‚‹ã‚ˆã†ã«æº–備する
759 割込み処理からのリターン
760}
761----------------------------------------
762
763これらの処理の前に,irq_handler_3のラベルを置く.これらの処理は,例外か
764らの出口で行う.
765
766○CPU例外ハンドラの出å…
767¥å£å‡¦ç†
768
769ASP3カーネル ポーティングガイドに従って,CPU例外ハンドラの出å…
770¥å£å‡¦ç†ã®
771実装
772方法を検討していく.
773
774----------------------------------------
775void
776<CPU例外の出å…
777¥å£å‡¦ç†>(void)
778{
779 スクラッチレジスタをスタックに保存する
780----------------------------------------
781
782この処理は,例外のå…
783¥å£ã§å®Ÿè£…
784済みである.
785
786----------------------------------------
787 CPU例外が発生した状況を判断するための追加情
788報をスタックに保存する … (*j)
789 この時点でのスタックポインタ±nを,CPU例外の情
790報を記憶している領域の
791 å…
792ˆé ­ç•ªåœ°ã¨ã™ã‚‹ï¼ˆå¿…
793要なら保存する)
794----------------------------------------
795
796exc_sense_intmaskを実現するために,CPU例外が発生した時点でのコンテキス
797トと割込み優å…
798ˆåº¦ãƒžã‚¹ã‚¯ãŒå¿…
799要となるため,現在の割込み優å…
800ˆåº¦ãƒžã‚¹ã‚¯ï¼ˆCPU例
801外の発生で割込み優å…
802ˆåº¦ãƒžã‚¹ã‚¯ãŒå¤‰ã‚ã‚‹ã“とはないため,これで良い)と例外
803ネストカウントをスタックに保存する.また,CPU例外の情
804報を記憶している領
805域のå…
806ˆé ­ç•ªåœ°ã¨ã—て,この時点でのスタックポインタを,レジスタに保存して
807おく.
808
809----------------------------------------
810 if (カーネル管理外のCPU例外) {
811----------------------------------------
812
813カーネル管理外のCPU例外は,カーネル実行中,å…
814¨å‰²è¾¼ã¿ãƒ­ãƒƒã‚¯çŠ¶æ…
815‹ï¼ŒCPUロッ
816ク状æ…
817‹ï¼Œã‚«ãƒ¼ãƒãƒ«ç®¡ç†å¤–の割込みハンドラ実行中に発生したCPU例外である.
818ARMコアの場合は,戻りå…
819ˆã®CPSRのIビットかFビットのいずれかがセットされて
820いるなら,これに該当する.
821
822そこで,例外フレームから戻りå…
823ˆã®CPSRを取り出し,IビットかFビットのいず
824れかがセットされている場合には,カーネル管理外のCPU例外の出å…
825¥å£å‡¦ç†
826(nk_exc_handler_1)に分岐する.
827
828----------------------------------------
829 if (CPU例外がタスクコンテキストで発生) {
830 スタックを非タスクコンテキスト用のスタックに切り換え,
831 非タスクコンテキストに切り換える … (*k)
832 }
833----------------------------------------
834
835カーネル管理外のCPU例外の出å…
836¥å£å‡¦ç†ï¼ˆnk_exc_handler_1)では,まず,例外
837ネストカウントをインクリメントする.CPU例外発生前がタスクコンテキストな
838ら,非タスクコンテキスト用のスタックに切り換え,切り換え前のスタックポ
839インタを切り換え後のスタック上に保存する.
840
841----------------------------------------
842 システム状æ…
843‹ï¼ˆã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã¯é™¤ãï¼‰ã‚’,CPU例外発生時の状æ…
844‹ã«ã™ã‚‹
845----------------------------------------
846
847システム状æ…
848‹ï¼ˆã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã¯é™¤ãï¼‰ã‚’CPU例外発生時の状æ…
849‹ã«ã™ã‚‹ã«ã¯ï¼Œã‚¹ãƒ¼
850パバイザモードに切り換え,IフラグとFフラグの状æ…
851‹ã‚’CPU例外発生時の状æ…
852‹ã«
853戻す.
854
855----------------------------------------
856 CPU例外ハンドラを,CPU例外の情
857報を記憶している領域のå…
858ˆé ­ç•ªåœ°ã‚’
859 パラメータ(p_excinf)として呼び出す
860----------------------------------------
861
862CPU例外ハンドラテーブル(exc_table)からCPU例外ハンドラの番地を取り出し,
863CPU例外の情
864報を記憶している領域のå…
865ˆé ­ç•ªåœ°ã‚’第1パラメータ,CPU例外ハンド
866ラ番号を第2パラメータとして呼び出す.第2パラメータにCPU例外ハンドラ番号
867を渡すのは,default_exc_handlerで割込みハンドラ番号を表示できるようにす
868るためで,ARMコア依存部の独自拡張である.
869
870----------------------------------------
871 if (CPU例外がタスクコンテキストで発生) {
872 スタックをタスク用のスタックに戻し,
873 タスクコンテキストに切り換える … (*k)
874 }
875 CPU例外処理からのリターン後に,CPU例外発生時のシステム状æ…
876‹ã«
877 戻るように準備する
878 }
879 CPU例外が発生した状況を判断するための追加情
880報をスタック上から捨てる
881 スクラッチレジスタをスタックから復帰する
882 CPU例外処理からのリターン
883}
884----------------------------------------
885
886例外ネストカウントをデクリメントし,0になった場合には,タスク用のスタッ
887クに戻す.その後,CPU例外が発生した状況を判断するための追加情
888報をスタッ
889ク上から捨て,スクラッチレジスタを復帰した後,例外からリターンする.
890
891----------------------------------------
892 else {
893 if (CPU例外がタスクコンテキストで発生) {
894----------------------------------------
895
896カーネル管理のCPU例外の出å…
897¥å£å‡¦ç†ã§ã¯ï¼Œã¾ãšï¼Œä¾‹å¤–ネストカウントをインク
898リメントする.CPU例外発生前が非タスクコンテキストなら,この後の{}内
899の処
900理をスキップする(exc_handler_2に分岐).
901
902----------------------------------------
903 少なくともカーネル管理の割込みを禁止した状æ…
904‹ã«ã™ã‚‹
905----------------------------------------
906
907ARMコアでは,例外の受付によりCPSRのIビットがセットされるため,この処理
908は必
909要ない.
910
911----------------------------------------
912#ifdef TOPPERS_SUPPORT_OVRHDR
913 ovrtimer_stop(); /* オーバランタイマの停止 */
914#endif /* TOPPERS_SUPPORT_OVRHDR */
915 スタックを非タスクコンテキスト用のスタックに切り換え,
916 非タスクコンテキストに切り換える
917 }
918----------------------------------------
919
920スタックを非タスクコンテキスト用のスタックに切り換え,切り換え前のスタッ
921クポインタを切り換え後のスタック上に保存する.これらの処理の後に,
922exc_handler_2ラベルを置く.
923
924----------------------------------------
925 割込み優å…
926ˆåº¦ãƒžã‚¹ã‚¯ã‚’,CPU例外発生時の値に設定する … (*l)
927----------------------------------------
928
929チップ依存部のirc_begin_excを呼び出し,必
930要であれば,割込み優å…
931ˆåº¦ãƒžã‚¹ã‚¯
932をCPU例外発生時の値に設定する.また,irc_end_excで必
933要な情
934報をスタック
935に保存する.
936
937----------------------------------------
938 CPUロック解除状æ…
939‹ã«ã™ã‚‹ï¼ˆCPU例外発生時の割込み優å…
940ˆåº¦ãƒžã‚¹ã‚¯ã‚ˆã‚Šã‚‚
941 優å…
942ˆåº¦ã®é«˜ã„割込みを受け付けるようにする)
943----------------------------------------
944
945割込みを許可して,CPUロック解除状æ…
946‹ã«ã™ã‚‹ï¼Ž
947
948----------------------------------------
949#ifdef LOG_EXC_ENTER
950 log_exc_enter(CPU例外ハンドラ番号);
951#endif /* LOG_EXC_ENTER */
952 CPU例外ハンドラを,CPU例外の情
953報を記憶している領域のå…
954ˆé ­ç•ªåœ°ã‚’
955 パラメータ(p_excinf)として呼び出す
956#ifdef LOG_EXC_LEAVE
957 log_exc_leave(CPU例外ハンドラ番号);
958#endif /* LOG_EXC_LEAVE */
959----------------------------------------
960
961CPU例外ハンドラテーブル(exc_table)からCPU例外ハンドラの番地を取り出し,
962CPU例外の情
963報を記憶している領域のå…
964ˆé ­ç•ªåœ°ã‚’第1パラメータ,CPU例外ハンド
965ラ番号を第2パラメータとして呼び出す.
966
967----------------------------------------
968 少なくともカーネル管理の割込みを禁止した状æ…
969‹ã«ã™ã‚‹ … (*m)
970 割込み優å…
971ˆåº¦ãƒžã‚¹ã‚¯ã‚’,CPU例外発生時の値に設定する … (*n)
972----------------------------------------
973
974カーネル管理の割込みを禁止した後,チップ依存部のirc_end_excを呼び出す.
975
976----------------------------------------
977 if (CPU例外がタスクコンテキストで発生) {
978 スタックをタスク用のスタックに戻し,タスクコンテキストに切り換える
979 … (*g)
980----------------------------------------
981
982例外ネストカウントをデクリメントし,0になった場合には,タスク用のスタッ
983クに戻す.その後,CPU例外が発生した状況を判断するための追加情
984報をスタッ
985ク上から捨てる.例外ネストカウントが0になった場合の処理は,追加情
986報をス
987タック上から捨てること以外は,割込みハンドラの出口処理と同様である.
988
989----------------------------------------
990 if (p_runtsk != p_schedtsk) {
991 CPUロック状æ…
992‹ã«ã™ã‚‹ … (*h)
993 割込み優å…
994ˆåº¦ãƒžã‚¹ã‚¯ã¯ï¼Œå…
995¨è§£é™¤çŠ¶æ…
996‹ï¼ˆTIPM_ENAALL)になって
997 いなければならない … (*i)
998 if (p_runtsk != NULL) {
999 スクラッチレジスタを除くすべてのレジスタをスタックに保存する
1000 スタックポインタを自タスク(p_runtsk)のTCBに保存する
1001 ret_exc_rを,実行再開番地として自タスクのTCBに保存する
1002 … (*a)
1003#ifdef LOG_DSP_ENTER
1004 log_dsp_enter(p_runtsk);
1005#endif /* LOG_DSP_ENTER */
1006 }
1007 dispatcherに分岐する
1008
1009 ret_exc_r:
1010 スクラッチレジスタを除くすべてのレジスタをスタックから復帰する
1011#ifdef TOPPERS_SUPPORT_OVRHDR
1012 ovrtimer_start(); /* オーバランタイマの動作開始 */
1013#endif /* TOPPERS_SUPPORT_OVRHDR */
1014 }
1015#ifdef TOPPERS_SUPPORT_OVRHDR
1016 else {
1017 if (p_runtsk != NULL) {
1018 ovrtimer_start(); /* オーバランタイマの動作開始 */
1019 }
1020 }
1021#endif /* TOPPERS_SUPPORT_OVRHDR */
1022 }
1023 CPU例外処理からのリターン後に,CPUロック解除状æ…
1024‹ã«æˆ»ã‚‹ã‚ˆã†ã«æº–備する
1025 }
1026 CPU例外が発生した状況を判断するための追加情
1027報をスタック上から捨てる
1028 スクラッチレジスタをスタックから復帰する
1029 CPU例外処理からのリターン
1030}
1031----------------------------------------
1032
1033●スタックポインタが不正の場合の対策
1034
1035CPU例外ハンドラを実行する際に経由する部分で,CPU例外が起こる可能性とし
1036て,スタックポインタが不正な番地となった場合が考えられる.スーパバイザ
1037モードのスタックポインタが不正な番地となった状æ…
1038‹ã§ä¾‹å¤–が発生すると,そ
1039のå…
1040¥å£ã§ã‚¹ã‚¯ãƒ©ãƒƒãƒãƒ¬ã‚¸ã‚¹ã‚¿ç­‰ã‚’保存しようとして,再度例外が発生する.こ
1041の状況で,例外発生が無限に繰り返すことを防ぐ対策をとることが望ましい.
1042
1043これを防ぐために,データアボートのå…
1044¥å£ã§ï¼Œãƒ‡ãƒ¼ã‚¿ã‚¢ãƒœãƒ¼ãƒˆã‚’発生された番
1045地を調べ,CPU例外のå…
1046¥å£ã§ã‚った場合には,フェイタルデータアボート処理を
1047行う.
1048
1049フェイタルデータアボート処理では,スーパバイザモードのスタックを,強制
1050的に,非タスクコンテキスト用のスタックの初期値に設定した後,CPU例外の処
1051理を行う.この際,通常のデータアボートと区別できるように,例外ネストカ
1052ウントの最上位ビットを1にする.フェイタルデータアボート処理からはリター
1053ンすることができない.
1054
1055以上
Note: See TracBrowser for help on using the repository browser.