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