source: EcnlProtoTool/trunk/asp3_dcre/kernel/interrupt.c@ 321

Last change on this file since 321 was 321, checked in by coas-nagasima, 7 years ago

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 11.8 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2005-2016 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 *
11 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
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 * 割込み管理機能
45 */
46
47#include "kernel_impl.h"
48#include "check.h"
49#include "task.h"
50#include "interrupt.h"
51
52/*
53 * トレースログマクロのデフォルト定義
54 */
55#ifndef LOG_ISR_ENTER
56#define LOG_ISR_ENTER(isrid)
57#endif /* LOG_ISR_ENTER */
58
59#ifndef LOG_ISR_LEAVE
60#define LOG_ISR_LEAVE(isrid)
61#endif /* LOG_ISR_LEAVE */
62
63#ifndef LOG_ACRE_ISR_ENTER
64#define LOG_ACRE_ISR_ENTER(pk_cisr)
65#endif /* LOG_ACRE_ISR_ENTER */
66
67#ifndef LOG_ACRE_ISR_LEAVE
68#define LOG_ACRE_ISR_LEAVE(ercd)
69#endif /* LOG_ACRE_ISR_LEAVE */
70
71#ifndef LOG_DEL_ISR_ENTER
72#define LOG_DEL_ISR_ENTER(isrid)
73#endif /* LOG_DEL_ISR_ENTER */
74
75#ifndef LOG_DEL_ISR_LEAVE
76#define LOG_DEL_ISR_LEAVE(ercd)
77#endif /* LOG_DEL_ISR_LEAVE */
78
79#ifndef LOG_DIS_INT_ENTER
80#define LOG_DIS_INT_ENTER(intno)
81#endif /* LOG_DIS_INT_ENTER */
82
83#ifndef LOG_DIS_INT_LEAVE
84#define LOG_DIS_INT_LEAVE(ercd)
85#endif /* LOG_DIS_INT_LEAVE */
86
87#ifndef LOG_ENA_INT_ENTER
88#define LOG_ENA_INT_ENTER(intno)
89#endif /* LOG_ENA_INT_ENTER */
90
91#ifndef LOG_ENA_INT_LEAVE
92#define LOG_ENA_INT_LEAVE(ercd)
93#endif /* LOG_ENA_INT_LEAVE */
94
95#ifndef LOG_CHG_IPM_ENTER
96#define LOG_CHG_IPM_ENTER(intpri)
97#endif /* LOG_CHG_IPM_ENTER */
98
99#ifndef LOG_CHG_IPM_LEAVE
100#define LOG_CHG_IPM_LEAVE(ercd)
101#endif /* LOG_CHG_IPM_LEAVE */
102
103#ifndef LOG_GET_IPM_ENTER
104#define LOG_GET_IPM_ENTER(p_intpri)
105#endif /* LOG_GET_IPM_ENTER */
106
107#ifndef LOG_GET_IPM_LEAVE
108#define LOG_GET_IPM_LEAVE(ercd, p_intpri)
109#endif /* LOG_GET_IPM_LEAVE */
110
111/*
112 * 割込みサービスルーチンの数
113 */
114#define tnum_isr ((uint_t)(tmax_isrid - TMIN_ISRID + 1))
115#define tnum_sisr ((uint_t)(tmax_sisrid - TMIN_ISRID + 1))
116
117/*
118 * 割込みサービスルーチンIDから割込みサービスルーチン管理ブロックを取
119 * り出すためのマクロ
120 */
121#define INDEX_ISR(isrid) ((uint_t)((isrid) - TMIN_ISRID))
122#define get_isrcb(isrid) (&(isrcb_table[INDEX_ISR(isrid)]))
123
124/*
125 * 割込みサービスルーチンキューへの登録
126 */
127Inline void
128enqueue_isr(QUEUE *p_isr_queue, ISRCB *p_isrcb)
129{
130 QUEUE *p_entry;
131 PRI isrpri = p_isrcb->p_isrinib->isrpri;
132
133 for (p_entry = p_isr_queue->p_next; p_entry != p_isr_queue;
134 p_entry = p_entry->p_next) {
135 if (isrpri < ((ISRCB *) p_entry)->p_isrinib->isrpri) {
136 break;
137 }
138 }
139 queue_insert_prev(p_entry, &(p_isrcb->isr_queue));
140}
141
142#ifdef TOPPERS_isrini
143
144/*
145 * 使用していない割込みサービスルーチン管理ブロックのリスト
146 */
147QUEUE free_isrcb;
148
149/*
150 * 割込みサービスルーチン機能の初期化
151 */
152void
153initialize_isr(void)
154{
155 uint_t i, j;
156 ISRCB *p_isrcb;
157 ISRINIB *p_isrinib;
158
159 for (i = 0; i < tnum_isr_queue; i++) {
160 queue_initialize(&(isr_queue_table[i]));
161 }
162 for (i = 0; i < tnum_sisr; i++) {
163 j = INDEX_ISR(isrorder_table[i]);
164 p_isrcb = &(isrcb_table[j]);
165 p_isrcb->p_isrinib = &(isrinib_table[j]);
166 enqueue_isr(p_isrcb->p_isrinib->p_isr_queue, p_isrcb);
167 }
168 queue_initialize(&free_isrcb);
169 for (j = 0; i < tnum_isr; i++, j++) {
170 p_isrcb = &(isrcb_table[i]);
171 p_isrinib = &(aisrinib_table[j]);
172 p_isrinib->isratr = TA_NOEXS;
173 p_isrcb->p_isrinib = ((const ISRINIB *) p_isrinib);
174 queue_insert_prev(&free_isrcb, &(p_isrcb->isr_queue));
175 }
176}
177
178#endif /* TOPPERS_isrini */
179
180/*
181 * 割込みサービスルーチンの呼出し
182 */
183#ifdef TOPPERS_isrcal
184
185void
186call_isr(QUEUE *p_isr_queue)
187{
188 QUEUE *p_queue;
189 ISRCB *p_isrcb;
190
191 for (p_queue = p_isr_queue->p_next; p_queue != p_isr_queue;
192 p_queue = p_queue->p_next) {
193 p_isrcb = (ISRCB *) p_queue;
194 LOG_ISR_ENTER(ISRID(p_isrcb));
195 (*(p_isrcb->p_isrinib->isr))(p_isrcb->p_isrinib->exinf);
196 LOG_ISR_LEAVE(ISRID(p_isrcb));
197
198 if (p_queue->p_next != p_isr_queue) {
199 /* ISRの呼出し前の状態に戻す */
200 if (sense_lock()) {
201 unlock_cpu();
202 }
203 }
204 }
205}
206
207#endif /* TOPPERS_isrcal */
208
209/*
210 * 割込みサービスルーチン呼出しキューの検索
211 */
212Inline QUEUE *
213search_isr_queue(INTNO intno)
214{
215 int_t left, right, i;
216
217 if (tnum_isr_queue == 0) {
218 return(NULL);
219 }
220
221 left = 0;
222 right = tnum_isr_queue - 1;
223 while (left < right) {
224 i = (left + right + 1) / 2;
225 if (intno < isr_queue_list[i].intno) {
226 right = i - 1;
227 }
228 else {
229 left = i;
230 }
231 }
232 if (isr_queue_list[left].intno == intno) {
233 return(isr_queue_list[left].p_isr_queue);
234 }
235 else {
236 return(NULL);
237 }
238}
239
240/*
241 * 割込みサービスルーチンの生成
242 *
243 * pk_cisr->exinfは,エラーチェックをせず,一度しか参照しないため,ロー
244 * カル変数にコピーする必要がない(途中で書き換わっても支障がない).
245 */
246#ifdef TOPPERS_acre_isr
247
248ER_UINT
249acre_isr(const T_CISR *pk_cisr)
250{
251 ISRCB *p_isrcb;
252 ISRINIB *p_isrinib;
253 QUEUE *p_isr_queue;
254 ATR isratr;
255 INTNO intno;
256 ISR isr;
257 PRI isrpri;
258 ER ercd;
259
260 LOG_ACRE_ISR_ENTER(pk_cisr);
261 CHECK_TSKCTX_UNL();
262
263 isratr = pk_cisr->isratr;
264 intno = pk_cisr->intno;
265 isr = pk_cisr->isr;
266 isrpri = pk_cisr->isrpri;
267
268 CHECK_RSATR(isratr, TARGET_ISRATR);
269 CHECK_PAR(VALID_INTNO_CREISR(intno));
270 CHECK_PAR(FUNC_ALIGN(isr));
271 CHECK_PAR(FUNC_NONNULL(isr));
272 CHECK_PAR(VALID_ISRPRI(isrpri));
273
274 p_isr_queue = search_isr_queue(intno);
275 CHECK_OBJ(p_isr_queue != NULL);
276
277 lock_cpu();
278 if (tnum_isr == 0 || queue_empty(&free_isrcb)) {
279 ercd = E_NOID;
280 }
281 else {
282 p_isrcb = ((ISRCB *) queue_delete_next(&free_isrcb));
283 p_isrinib = (ISRINIB *)(p_isrcb->p_isrinib);
284 p_isrinib->isratr = isratr;
285 p_isrinib->exinf = pk_cisr->exinf;
286 p_isrinib->p_isr_queue = p_isr_queue;
287 p_isrinib->isr = isr;
288 p_isrinib->isrpri = isrpri;
289 enqueue_isr(p_isr_queue, p_isrcb);
290 ercd = ISRID(p_isrcb);
291 }
292 unlock_cpu();
293
294 error_exit:
295 LOG_ACRE_ISR_LEAVE(ercd);
296 return(ercd);
297}
298
299#endif /* TOPPERS_acre_isr */
300
301/*
302 * 割込みサービスルーチンの削除
303 */
304#ifdef TOPPERS_del_isr
305
306ER
307del_isr(ID isrid)
308{
309 ISRCB *p_isrcb;
310 ISRINIB *p_isrinib;
311 ER ercd;
312
313 LOG_DEL_ISR_ENTER(isrid);
314 CHECK_TSKCTX_UNL();
315 CHECK_ID(VALID_ISRID(isrid));
316 p_isrcb = get_isrcb(isrid);
317
318 lock_cpu();
319 if (p_isrcb->p_isrinib->isratr == TA_NOEXS) {
320 ercd = E_NOEXS;
321 }
322 else if (isrid <= tmax_sisrid) {
323 ercd = E_OBJ;
324 }
325 else {
326 queue_delete(&(p_isrcb->isr_queue));
327 p_isrinib = (ISRINIB *)(p_isrcb->p_isrinib);
328 p_isrinib->isratr = TA_NOEXS;
329 queue_insert_prev(&free_isrcb, &(p_isrcb->isr_queue));
330 ercd = E_OK;
331 }
332 unlock_cpu();
333
334 error_exit:
335 LOG_DEL_ISR_LEAVE(ercd);
336 return(ercd);
337}
338
339#endif /* TOPPERS_del_isr */
340
341/*
342 * 割込み管理機能の初期化
343 */
344#ifdef TOPPERS_intini
345#ifndef OMIT_INITIALIZE_INTERRUPT
346
347void
348initialize_interrupt(void)
349{
350 uint_t i;
351 const INHINIB *p_inhinib;
352 const INTINIB *p_intinib;
353
354 for (i = 0; i < tnum_def_inhno; i++) {
355 p_inhinib = &(inhinib_table[i]);
356 define_inh(p_inhinib->inhno, p_inhinib->int_entry);
357 }
358 for (i = 0; i < tnum_cfg_intno; i++) {
359 p_intinib = &(intinib_table[i]);
360 config_int(p_intinib->intno, p_intinib->intatr, p_intinib->intpri);
361 }
362}
363
364#endif /* OMIT_INITIALIZE_INTERRUPT */
365#endif /* TOPPERS_intini */
366
367/*
368 * 割込みの禁止[NGKI3555]
369 */
370#ifdef TOPPERS_dis_int
371#ifdef TOPPERS_SUPPORT_DIS_INT /*[NGKI3093]*/
372
373ER
374dis_int(INTNO intno)
375{
376 bool_t locked;
377 ER ercd;
378
379 LOG_DIS_INT_ENTER(intno);
380 CHECK_PAR(VALID_INTNO_DISINT(intno)); /*[NGKI3083][NGKI3087]*/
381
382 locked = sense_lock();
383 if (!locked) {
384 lock_cpu();
385 }
386 if (disable_int(intno)) { /*[NGKI3086]*/
387 ercd = E_OK;
388 }
389 else {
390 ercd = E_OBJ; /*[NGKI3085]*/
391 }
392 if (!locked) {
393 unlock_cpu();
394 }
395
396 error_exit:
397 LOG_DIS_INT_LEAVE(ercd);
398 return(ercd);
399}
400
401#endif /* TOPPERS_SUPPORT_DIS_INT */
402#endif /* TOPPERS_dis_int */
403
404/*
405 * 割込みの許可[NGKI3556]
406 */
407#ifdef TOPPERS_ena_int
408#ifdef TOPPERS_SUPPORT_ENA_INT /*[NGKI3106]*/
409
410ER
411ena_int(INTNO intno)
412{
413 bool_t locked;
414 ER ercd;
415
416 LOG_ENA_INT_ENTER(intno);
417 CHECK_PAR(VALID_INTNO_DISINT(intno)); /*[NGKI3096][NGKI3100]*/
418
419 locked = sense_lock();
420 if (!locked) {
421 lock_cpu();
422 }
423 if (enable_int(intno)) { /*[NGKI3099]*/
424 ercd = E_OK;
425 }
426 else {
427 ercd = E_OBJ; /*[NGKI3098]*/
428 }
429 if (!locked) {
430 unlock_cpu();
431 }
432
433 error_exit:
434 LOG_ENA_INT_LEAVE(ercd);
435 return(ercd);
436}
437
438#endif /* TOPPERS_SUPPORT_ENA_INT */
439#endif /* TOPPERS_ena_int */
440
441/*
442 * 割込み優先度マスクの変更[NGKI3107]
443 */
444#ifdef TOPPERS_chg_ipm
445
446ER
447chg_ipm(PRI intpri)
448{
449 ER ercd;
450
451 LOG_CHG_IPM_ENTER(intpri);
452 CHECK_TSKCTX_UNL(); /*[NGKI3108][NGKI3109]*/
453 CHECK_PAR(VALID_INTPRI_CHGIPM(intpri)); /*[NGKI3113][NGKI3114]*/
454
455 lock_cpu();
456 t_set_ipm(intpri); /*[NGKI3111]*/
457 if (intpri == TIPM_ENAALL && enadsp) {
458 dspflg = true;
459 p_schedtsk = search_schedtsk();
460 if (p_runtsk->raster && p_runtsk->enater) {
461 task_terminate(p_runtsk);
462 exit_and_dispatch();
463 ercd = E_SYS;
464 }
465 else {
466 if (p_runtsk != p_schedtsk) {
467 dispatch();
468 }
469 ercd = E_OK;
470 }
471 }
472 else {
473 dspflg = false;
474 ercd = E_OK;
475 }
476 unlock_cpu();
477
478 error_exit:
479 LOG_CHG_IPM_LEAVE(ercd);
480 return(ercd);
481}
482
483#endif /* TOPPERS_chg_ipm */
484
485/*
486 * 割込み優先度マスクの参照[NGKI3115]
487 */
488#ifdef TOPPERS_get_ipm
489
490ER
491get_ipm(PRI *p_intpri)
492{
493 ER ercd;
494
495 LOG_GET_IPM_ENTER(p_intpri);
496 CHECK_TSKCTX_UNL(); /*[NGKI3116][NGKI3117]*/
497
498 lock_cpu();
499 *p_intpri = t_get_ipm(); /*[NGKI3120]*/
500 ercd = E_OK;
501 unlock_cpu();
502
503 error_exit:
504 LOG_GET_IPM_LEAVE(ercd, p_intpri);
505 return(ercd);
506}
507
508#endif /* TOPPERS_get_ipm */
Note: See TracBrowser for help on using the repository browser.