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