source: EcnlProtoTool/trunk/asp3_dcre/kernel/cyclic.c@ 429

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

ASP3, TINET, mbed を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 10.6 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-2018 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 "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_ACRE_CYC_ENTER
63#define LOG_ACRE_CYC_ENTER(pk_ccyc)
64#endif /* LOG_ACRE_CYC_ENTER */
65
66#ifndef LOG_ACRE_CYC_LEAVE
67#define LOG_ACRE_CYC_LEAVE(ercd)
68#endif /* LOG_ACRE_CYC_LEAVE */
69
70#ifndef LOG_DEL_CYC_ENTER
71#define LOG_DEL_CYC_ENTER(cycid)
72#endif /* LOG_DEL_CYC_ENTER */
73
74#ifndef LOG_DEL_CYC_LEAVE
75#define LOG_DEL_CYC_LEAVE(ercd)
76#endif /* LOG_DEL_CYC_LEAVE */
77
78#ifndef LOG_STA_CYC_ENTER
79#define LOG_STA_CYC_ENTER(cycid)
80#endif /* LOG_STA_CYC_ENTER */
81
82#ifndef LOG_STA_CYC_LEAVE
83#define LOG_STA_CYC_LEAVE(ercd)
84#endif /* LOG_STA_CYC_LEAVE */
85
86#ifndef LOG_STP_CYC_ENTER
87#define LOG_STP_CYC_ENTER(cycid)
88#endif /* LOG_STP_CYC_ENTER */
89
90#ifndef LOG_STP_CYC_LEAVE
91#define LOG_STP_CYC_LEAVE(ercd)
92#endif /* LOG_STP_CYC_LEAVE */
93
94#ifndef LOG_REF_CYC_ENTER
95#define LOG_REF_CYC_ENTER(cycid, pk_rcyc)
96#endif /* LOG_REF_CYC_ENTER */
97
98#ifndef LOG_REF_CYC_LEAVE
99#define LOG_REF_CYC_LEAVE(ercd, pk_rcyc)
100#endif /* LOG_REF_CYC_LEAVE */
101
102/*
103 * 周期通知の数
104 */
105#define tnum_cyc ((uint_t)(tmax_cycid - TMIN_CYCID + 1))
106#define tnum_scyc ((uint_t)(tmax_scycid - TMIN_CYCID + 1))
107
108/*
109 * 周期通知IDから周期通知管理ブロックを取り出すためのマクロ
110 */
111#define INDEX_CYC(cycid) ((uint_t)((cycid) - TMIN_CYCID))
112#define get_cyccb(cycid) (&(cyccb_table[INDEX_CYC(cycid)]))
113
114#ifdef TOPPERS_cycini
115
116/*
117 * 使用していない周期通知管理ブロックのリスト
118 *
119 * 周期通知管理ブロックの先頭にはキューにつなぐための領域がないため,
120 * タイムイベントブロック(tmevtb)の領域を用いる.
121 */
122QUEUE free_cyccb;
123
124/*
125 * 周期通知機能の初期化
126 */
127void
128initialize_cyclic(void)
129{
130 uint_t i, j;
131 CYCCB *p_cyccb;
132 CYCINIB *p_cycinib;
133
134 for (i = 0; i < tnum_scyc; i++) {
135 p_cyccb = &(cyccb_table[i]);
136 p_cyccb->p_cycinib = &(cycinib_table[i]);
137 p_cyccb->tmevtb.callback = (CBACK) call_cyclic;
138 p_cyccb->tmevtb.arg = (void *) p_cyccb;
139 if ((p_cyccb->p_cycinib->cycatr & TA_STA) != 0U) {
140 /*
141 * 初回の起動のためのタイムイベントを登録する[ASPD1035]
142 * [ASPD1062].
143 */
144 p_cyccb->cycsta = true;
145 p_cyccb->tmevtb.evttim = (EVTTIM)(p_cyccb->p_cycinib->cycphs);
146 tmevtb_register(&(p_cyccb->tmevtb));
147 }
148 else {
149 p_cyccb->cycsta = false;
150 }
151 }
152 queue_initialize(&free_cyccb);
153 for (j = 0; i < tnum_cyc; i++, j++) {
154 p_cyccb = &(cyccb_table[i]);
155 p_cycinib = &(acycinib_table[j]);
156 p_cycinib->cycatr = TA_NOEXS;
157 p_cyccb->p_cycinib = ((const CYCINIB *) p_cycinib);
158 p_cyccb->tmevtb.callback = (CBACK) call_cyclic;
159 p_cyccb->tmevtb.arg = (void *) p_cyccb;
160 queue_insert_prev(&free_cyccb, ((QUEUE *) &(p_cyccb->tmevtb)));
161 }
162}
163
164#endif /* TOPPERS_cycini */
165
166/*
167 * 周期通知の生成
168 */
169#ifdef TOPPERS_acre_cyc
170
171ER_UINT
172acre_cyc(const T_CCYC *pk_ccyc)
173{
174 CYCCB *p_cyccb;
175 CYCINIB *p_cycinib;
176 ATR cycatr;
177 RELTIM cyctim, cycphs;
178 T_NFYINFO *p_nfyinfo;
179 ER ercd;
180
181 LOG_ACRE_CYC_ENTER(pk_ccyc);
182 CHECK_TSKCTX_UNL();
183
184 cycatr = pk_ccyc->cycatr;
185 cyctim = pk_ccyc->cyctim;
186 cycphs = pk_ccyc->cycphs;
187
188 CHECK_VALIDATR(cycatr, TA_STA);
189 ercd = check_nfyinfo(&(pk_ccyc->nfyinfo));
190 if (ercd != E_OK) {
191 goto error_exit;
192 }
193 CHECK_PAR(0 < cyctim && cyctim <= TMAX_RELTIM);
194 CHECK_PAR(0 <= cycphs && cycphs <= TMAX_RELTIM);
195
196 lock_cpu();
197 if (tnum_cyc == 0 || queue_empty(&free_cyccb)) {
198 ercd = E_NOID;
199 }
200 else {
201 p_cyccb = ((CYCCB *)(((char *) queue_delete_next(&free_cyccb))
202 - offsetof(CYCCB, tmevtb)));
203 p_cycinib = (CYCINIB *)(p_cyccb->p_cycinib);
204 p_cycinib->cycatr = cycatr;
205 if (pk_ccyc->nfyinfo.nfymode == TNFY_HANDLER) {
206 p_cycinib->exinf = pk_ccyc->nfyinfo.nfy.handler.exinf;
207 p_cycinib->nfyhdr = (NFYHDR)(pk_ccyc->nfyinfo.nfy.handler.tmehdr);
208 }
209 else {
210 p_nfyinfo = &acyc_nfyinfo_table[p_cycinib - acycinib_table];
211 *p_nfyinfo = pk_ccyc->nfyinfo;
212 p_cycinib->exinf = (intptr_t) p_nfyinfo;
213 p_cycinib->nfyhdr = notify_handler;
214 }
215 p_cycinib->cyctim = cyctim;
216 p_cycinib->cycphs = cycphs;
217
218 if ((p_cyccb->p_cycinib->cycatr & TA_STA) != 0U) {
219 p_cyccb->cycsta = true;
220 tmevtb_enqueue_reltim(&(p_cyccb->tmevtb),
221 p_cyccb->p_cycinib->cycphs);
222 }
223 else {
224 p_cyccb->cycsta = false;
225 }
226 ercd = CYCID(p_cyccb);
227 }
228 unlock_cpu();
229
230 error_exit:
231 LOG_ACRE_CYC_LEAVE(ercd);
232 return(ercd);
233}
234
235#endif /* TOPPERS_acre_cyc */
236
237/*
238 * 周期通知の削除
239 */
240#ifdef TOPPERS_del_cyc
241
242ER
243del_cyc(ID cycid)
244{
245 CYCCB *p_cyccb;
246 CYCINIB *p_cycinib;
247 ER ercd;
248
249 LOG_DEL_CYC_ENTER(cycid);
250 CHECK_TSKCTX_UNL();
251 CHECK_ID(VALID_CYCID(cycid));
252 p_cyccb = get_cyccb(cycid);
253
254 lock_cpu();
255 if (p_cyccb->p_cycinib->cycatr == TA_NOEXS) {
256 ercd = E_NOEXS;
257 }
258 else if (cycid <= tmax_scycid) {
259 ercd = E_OBJ;
260 }
261 else {
262 if (p_cyccb->cycsta) {
263 p_cyccb->cycsta = false;
264 tmevtb_dequeue(&(p_cyccb->tmevtb));
265 }
266
267 p_cycinib = (CYCINIB *)(p_cyccb->p_cycinib);
268 p_cycinib->cycatr = TA_NOEXS;
269 queue_insert_prev(&free_cyccb, ((QUEUE *) &(p_cyccb->tmevtb)));
270 ercd = E_OK;
271 }
272 unlock_cpu();
273
274 error_exit:
275 LOG_DEL_CYC_LEAVE(ercd);
276 return(ercd);
277}
278
279#endif /* TOPPERS_del_cyc */
280
281/*
282 * 周期通知の動作開始
283 */
284#ifdef TOPPERS_sta_cyc
285
286ER
287sta_cyc(ID cycid)
288{
289 CYCCB *p_cyccb;
290 ER ercd;
291
292 LOG_STA_CYC_ENTER(cycid);
293 CHECK_TSKCTX_UNL();
294 CHECK_ID(VALID_CYCID(cycid));
295 p_cyccb = get_cyccb(cycid);
296
297 lock_cpu();
298 if (p_cyccb->p_cycinib->cycatr == TA_NOEXS) {
299 ercd = E_NOEXS;
300 }
301 else {
302 if (p_cyccb->cycsta) {
303 tmevtb_dequeue(&(p_cyccb->tmevtb));
304 }
305 else {
306 p_cyccb->cycsta = true;
307 }
308 /*
309 * 初回の起動のためのタイムイベントを登録する[ASPD1036].
310 */
311 tmevtb_enqueue_reltim(&(p_cyccb->tmevtb), p_cyccb->p_cycinib->cycphs);
312 ercd = E_OK;
313 }
314 unlock_cpu();
315
316 error_exit:
317 LOG_STA_CYC_LEAVE(ercd);
318 return(ercd);
319}
320
321#endif /* TOPPERS_sta_cyc */
322
323/*
324 * 周期通知の動作停止
325 */
326#ifdef TOPPERS_stp_cyc
327
328ER
329stp_cyc(ID cycid)
330{
331 CYCCB *p_cyccb;
332 ER ercd;
333
334 LOG_STP_CYC_ENTER(cycid);
335 CHECK_TSKCTX_UNL();
336 CHECK_ID(VALID_CYCID(cycid));
337 p_cyccb = get_cyccb(cycid);
338
339 lock_cpu();
340 if (p_cyccb->p_cycinib->cycatr == TA_NOEXS) {
341 ercd = E_NOEXS;
342 }
343 else {
344 if (p_cyccb->cycsta) {
345 p_cyccb->cycsta = false;
346 tmevtb_dequeue(&(p_cyccb->tmevtb));
347 }
348 ercd = E_OK;
349 }
350 unlock_cpu();
351
352 error_exit:
353 LOG_STP_CYC_LEAVE(ercd);
354 return(ercd);
355}
356
357#endif /* TOPPERS_stp_cyc */
358
359/*
360 * 周期通知の状態参照
361 */
362#ifdef TOPPERS_ref_cyc
363
364ER
365ref_cyc(ID cycid, T_RCYC *pk_rcyc)
366{
367 CYCCB *p_cyccb;
368 ER ercd;
369
370 LOG_REF_CYC_ENTER(cycid, pk_rcyc);
371 CHECK_TSKCTX_UNL();
372 CHECK_ID(VALID_CYCID(cycid));
373 p_cyccb = get_cyccb(cycid);
374
375 lock_cpu();
376 if (p_cyccb->p_cycinib->cycatr == TA_NOEXS) {
377 ercd = E_NOEXS;
378 }
379 else {
380 if (p_cyccb->cycsta) {
381 pk_rcyc->cycstat = TCYC_STA;
382 pk_rcyc->lefttim = tmevt_lefttim(&(p_cyccb->tmevtb));
383 }
384 else {
385 pk_rcyc->cycstat = TCYC_STP;
386 }
387 ercd = E_OK;
388 }
389 unlock_cpu();
390
391 error_exit:
392 LOG_REF_CYC_LEAVE(ercd, pk_rcyc);
393 return(ercd);
394}
395
396#endif /* TOPPERS_ref_cyc */
397
398/*
399 * 周期通知起動ルーチン
400 */
401#ifdef TOPPERS_cyccal
402
403void
404call_cyclic(CYCCB *p_cyccb)
405{
406 /*
407 * 次回の起動のためのタイムイベントを登録する[ASPD1037].
408 */
409 p_cyccb->tmevtb.evttim += p_cyccb->p_cycinib->cyctim; /*[ASPD1038]*/
410 tmevtb_register(&(p_cyccb->tmevtb));
411
412 /*
413 * 通知ハンドラを,CPUロック解除状態で呼び出す.
414 *
415 * 周期通知の生成/削除はタスクからしか行えないため,周期通知初期
416 * 化ブロックをCPUロック解除状態で参照しても問題ない.
417 */
418 unlock_cpu();
419
420 LOG_CYC_ENTER(p_cyccb);
421 (*(p_cyccb->p_cycinib->nfyhdr))(p_cyccb->p_cycinib->exinf);
422 LOG_CYC_LEAVE(p_cyccb);
423
424 if (!sense_lock()) {
425 lock_cpu();
426 }
427}
428
429#endif /* TOPPERS_cyccal */
Note: See TracBrowser for help on using the repository browser.