OSDN Git Service

15729517f2a85fafe31620ec3a374542e838bc37
[toppersasp4lpc/asp.git] / asp / kernel / cyclic.c
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-2008 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: cyclic.c 1358 2008-09-21 09:16:57Z ertl-hiro $
41  */
42
43 /*
44  *              周期ハンドラ機能
45  */
46
47 #include "kernel_impl.h"
48 #include "check.h"
49 #include "cyclic.h"
50
51 /*
52  *  トレースログマクロのデフォルト定義
53  */
54 #ifndef LOG_CYC_ENTER
55 #define LOG_CYC_ENTER(p_cyccb)
56 #endif /* LOG_CYC_ENTER */
57
58 #ifndef LOG_CYC_LEAVE
59 #define LOG_CYC_LEAVE(p_cyccb)
60 #endif /* LOG_CYC_LEAVE */
61
62 #ifndef LOG_STA_CYC_ENTER
63 #define LOG_STA_CYC_ENTER(cycid)
64 #endif /* LOG_STA_CYC_ENTER */
65
66 #ifndef LOG_STA_CYC_LEAVE
67 #define LOG_STA_CYC_LEAVE(ercd)
68 #endif /* LOG_STA_CYC_LEAVE */
69
70 #ifndef LOG_STP_CYC_ENTER
71 #define LOG_STP_CYC_ENTER(cycid)
72 #endif /* LOG_STP_CYC_ENTER */
73
74 #ifndef LOG_STP_CYC_LEAVE
75 #define LOG_STP_CYC_LEAVE(ercd)
76 #endif /* LOG_STP_CYC_LEAVE */
77
78 #ifndef LOG_REF_CYC_ENTER
79 #define LOG_REF_CYC_ENTER(cycid, pk_rcyc)
80 #endif /* LOG_REF_CYC_ENTER */
81
82 #ifndef LOG_REF_CYC_LEAVE
83 #define LOG_REF_CYC_LEAVE(ercd, pk_rcyc)
84 #endif /* LOG_REF_CYC_LEAVE */
85
86 /*
87  *  周期ハンドラの数
88  */
89 #define tnum_cyc        ((uint_t)(tmax_cycid - TMIN_CYCID + 1))
90
91 /*
92  *  周期ハンドラIDから周期ハンドラ管理ブロックを取り出すためのマクロ
93  */
94 #define INDEX_CYC(cycid)        ((uint_t)((cycid) - TMIN_CYCID))
95 #define get_cyccb(cycid)        (&(cyccb_table[INDEX_CYC(cycid)]))
96
97 /*
98  *  周期ハンドラ起動のためのタイムイベントブロックの登録
99  */
100 Inline void
101 tmevtb_enqueue_cyc(CYCCB *p_cyccb, EVTTIM evttim)
102 {
103         tmevtb_enqueue_evttim(&(p_cyccb->tmevtb), evttim,
104                                                                 (CBACK) call_cychdr, (void *) p_cyccb);
105         p_cyccb->evttim = evttim;
106 }
107
108 /*
109  *  周期ハンドラ機能の初期化
110  */
111 #ifdef TOPPERS_cycini
112
113 void
114 initialize_cyclic(void)
115 {
116         uint_t  i;
117         CYCCB   *p_cyccb;
118
119         for (p_cyccb = cyccb_table, i = 0; i < tnum_cyc; p_cyccb++, i++) {
120                 p_cyccb->p_cycinib = &(cycinib_table[i]);
121                 if ((p_cyccb->p_cycinib->cycatr & TA_STA) != 0U) {
122                         p_cyccb->cycsta = true;
123                         tmevtb_enqueue_cyc(p_cyccb, (EVTTIM)(p_cyccb->p_cycinib->cycphs));
124                 }
125                 else {
126                         p_cyccb->cycsta = false;
127                 }
128         }
129 }
130
131 #endif /* TOPPERS_cycini */
132
133 /*
134  *  周期ハンドラの動作開始
135  */
136 #ifdef TOPPERS_sta_cyc
137
138 ER
139 sta_cyc(ID cycid)
140 {
141         CYCCB   *p_cyccb;
142         ER              ercd;
143
144         LOG_STA_CYC_ENTER(cycid);
145         CHECK_TSKCTX_UNL();
146         CHECK_CYCID(cycid);
147         p_cyccb = get_cyccb(cycid);
148
149         t_lock_cpu();
150         if (p_cyccb->cycsta) {
151                 tmevtb_dequeue(&(p_cyccb->tmevtb));
152         }
153         else {
154                 p_cyccb->cycsta = true;
155         }
156         tmevtb_enqueue_cyc(p_cyccb, base_time + p_cyccb->p_cycinib->cycphs);
157         ercd = E_OK;
158         t_unlock_cpu();
159
160   error_exit:
161         LOG_STA_CYC_LEAVE(ercd);
162         return(ercd);
163 }
164
165 #endif /* TOPPERS_sta_cyc */
166
167 /*
168  *  周期ハンドラの動作停止
169  */
170 #ifdef TOPPERS_stp_cyc
171
172 ER
173 stp_cyc(ID cycid)
174 {
175         CYCCB   *p_cyccb;
176         ER              ercd;
177
178         LOG_STP_CYC_ENTER(cycid);
179         CHECK_TSKCTX_UNL();
180         CHECK_CYCID(cycid);
181         p_cyccb = get_cyccb(cycid);
182
183         t_lock_cpu();
184         if (p_cyccb->cycsta) {
185                 p_cyccb->cycsta = false;
186                 tmevtb_dequeue(&(p_cyccb->tmevtb));
187         }
188         ercd = E_OK;
189         t_unlock_cpu();
190
191   error_exit:
192         LOG_STP_CYC_LEAVE(ercd);
193         return(ercd);
194 }
195
196 #endif /* TOPPERS_stp_cyc */
197
198 /*
199  *  周期ハンドラの状態参照
200  */
201 #ifdef TOPPERS_ref_cyc
202
203 ER
204 ref_cyc(ID cycid, T_RCYC *pk_rcyc)
205 {
206         CYCCB   *p_cyccb;
207         ER              ercd;
208     
209         LOG_REF_CYC_ENTER(cycid, pk_rcyc);
210         CHECK_TSKCTX_UNL();
211         CHECK_CYCID(cycid);
212         p_cyccb = get_cyccb(cycid);
213
214         t_lock_cpu();
215         if (p_cyccb->cycsta) {
216                 pk_rcyc->cycstat = TCYC_STA;
217                 pk_rcyc->lefttim = tmevt_lefttim(&(p_cyccb->tmevtb));
218         }
219         else {
220                 pk_rcyc->cycstat = TCYC_STP;
221         }
222         ercd = E_OK;
223         t_unlock_cpu();
224
225   error_exit:
226         LOG_REF_CYC_LEAVE(ercd, pk_rcyc);
227         return(ercd);
228 }
229
230 #endif /* TOPPERS_ref_cyc */
231
232 /*
233  *  周期ハンドラ起動ルーチン
234  */
235 #ifdef TOPPERS_cyccal
236
237 void
238 call_cychdr(CYCCB *p_cyccb)
239 {
240         PRI             saved_ipm;
241
242         /*
243          *  次回の起動のためのタイムイベントブロックを登録する.
244          *
245          *  同じタイムティックで周期ハンドラを再度起動すべき場合には,この
246          *  関数からsignal_timeに戻った後に,再度この関数が呼ばれることにな
247          *  る.
248          */
249         tmevtb_enqueue_cyc(p_cyccb, p_cyccb->evttim + p_cyccb->p_cycinib->cyctim);
250
251         /*
252          *  周期ハンドラを,CPUロック解除状態で呼び出す.
253          */
254         saved_ipm = i_get_ipm();
255         i_unlock_cpu();
256
257         LOG_CYC_ENTER(p_cyccb);
258         (*((CYCHDR)(p_cyccb->p_cycinib->cychdr)))(p_cyccb->p_cycinib->exinf);
259         LOG_CYC_LEAVE(p_cyccb);
260
261         if (!i_sense_lock()) {
262                 i_lock_cpu();
263         }
264         i_set_ipm(saved_ipm);
265 }
266
267 #endif /* TOPPERS_cyccal */