source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/syssvc/tSerialPortMain.c@ 337

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

ASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.0 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) 2006-2015 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.h>
48#include "tSerialPortMain_tecsgen.h"
49#include <t_syslog.h>
50
51/*
52 * フロー制御に関連する定数とマクロ
53 */
54#define FC_STOP '\023' /* コントロール-S */
55#define FC_START '\021' /* コントロール-Q */
56
57#define BUFCNT_STOP(bufsz) ((bufsz) * 3 / 4) /* STOPを送る基準文字数 */
58#define BUFCNT_START(bufsz) ((bufsz) / 2) /* STARTを送る基準文字数 */
59
60/*
61 * ポインタのインクリメント
62 */
63#define INC_PTR(ptr, bufsz) do { \
64 if (++(ptr) == (bufsz)) { \
65 (ptr) = 0; \
66 } \
67} while (false)
68
69/*
70 * サービスコール呼出しマクロ
71 *
72 * サービスコール呼出しを含む式expを評価し,返値がエラー(負の値)の場
73 * 合には,ercにercd_expを評価した値を代入し,error_exitにgotoする.
74 */
75#define SVC(exp, ercd_exp) do { \
76 if ((exp) < 0) { \
77 ercd = (ercd_exp); \
78 goto error_exit; \
79 } \
80} while (false)
81
82/*
83 * E_SYSエラーの生成
84 */
85static ER
86gen_ercd_sys(CELLCB *p_cellcb)
87{
88 VAR_errorFlag = true;
89 return(E_SYS);
90}
91
92/*
93 * 待ちに入るサービスコールからのエラーの変換
94 */
95static ER
96gen_ercd_wait(ER rercd, CELLCB *p_cellcb)
97{
98 switch (MERCD(rercd)) {
99 case E_RLWAI:
100 case E_DLT:
101 case E_RASTER:
102 return(rercd);
103 default:
104 VAR_errorFlag = true;
105 return(E_SYS);
106 }
107}
108
109/*
110 * シリアルポートのオープン(受け口関数)
111 */
112ER
113eSerialPort_open(CELLIDX idx)
114{
115 CELLCB *p_cellcb;
116 ER ercd;
117
118 if (sns_dpn()) { /* コンテキストのチェック */
119 return(E_CTX);
120 }
121 if (!VALID_IDX(idx)) {
122 return(E_ID); /* ポート番号のチェック */
123 }
124 p_cellcb = GET_CELLCB(idx);
125
126 SVC(dis_dsp(), gen_ercd_sys(p_cellcb));
127 if (VAR_openFlag) { /* オープン済みかのチェック */
128 ercd = E_OBJ;
129 }
130 else {
131 /*
132 * 変数の初期化
133 */
134 VAR_ioControl = (IOCTL_ECHO | IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
135
136 VAR_receiveReadPointer = 0U;
137 VAR_receiveWritePointer = 0U;
138 VAR_receiveCount = 0U;
139 VAR_receiveFlowControl = '\0';
140 VAR_receiveStopped = false;
141
142 VAR_sendReadPointer = 0U;
143 VAR_sendWritePointer = 0U;
144 VAR_sendCount = 0U;
145 VAR_sendStopped = false;
146
147 /*
148 * これ以降,割込みを禁止する.
149 */
150 if (loc_cpu() < 0) {
151 ercd = E_SYS;
152 goto error_exit_enadsp;
153 }
154
155 /*
156 * ハードウェア依存のオープン処理
157 */
158 cSIOPort_open();
159
160 /*
161 * 受信通知コールバックを許可する.
162 */
163 cSIOPort_enableCBR(SIOReceiveReady);
164 VAR_openFlag = true;
165 VAR_errorFlag = false;
166
167 if (unl_cpu() < 0) {
168 VAR_errorFlag = true;
169 ercd = E_SYS;
170 goto error_exit_enadsp;
171 }
172 ercd = E_OK;
173 }
174
175 error_exit_enadsp:
176 SVC(ena_dsp(), gen_ercd_sys(p_cellcb));
177
178 error_exit:
179 return(ercd);
180}
181
182/*
183 * シリアルポートのクローズ(受け口関数)
184 */
185ER
186eSerialPort_close(CELLIDX idx)
187{
188 CELLCB *p_cellcb;
189 ER ercd;
190 bool_t eflag = false;
191
192 if (sns_dpn()) { /* コンテキストのチェック */
193 return(E_CTX);
194 }
195 if (!VALID_IDX(idx)) {
196 return(E_ID); /* ポート番号のチェック */
197 }
198 p_cellcb = GET_CELLCB(idx);
199
200 SVC(dis_dsp(), gen_ercd_sys(p_cellcb));
201 if (!VAR_openFlag) { /* オープン済みかのチェック */
202 ercd = E_OBJ;
203 }
204 else {
205 /*
206 * ハードウェア依存のクローズ処理
207 */
208 if (loc_cpu() < 0) {
209 eflag = true;
210 }
211 cSIOPort_close();
212 VAR_openFlag = false;
213 if (unl_cpu() < 0) {
214 eflag = true;
215 }
216
217 /*
218 * セマフォの初期化
219 */
220 if (cSendSemaphore_initialize() < 0) {
221 eflag = true;
222 }
223 if (cReceiveSemaphore_initialize() < 0) {
224 eflag = true;
225 }
226
227 /*
228 * エラーコードの設定
229 */
230 if (eflag) {
231 ercd = gen_ercd_sys(p_cellcb);
232 }
233 else {
234 ercd = E_OK;
235 }
236 }
237 SVC(ena_dsp(), gen_ercd_sys(p_cellcb));
238
239 error_exit:
240 return(ercd);
241}
242
243/*
244 * シリアルポートへの文字送信
245 *
246 * p_cellcbで指定されるSIOポートに対して,文字cを送信する.文字を送信
247 * レジスタにいれた場合にはtrueを返す.そうでない場合には,送信レジス
248 * タが空いたことを通知するコールバック関数を許可し,falseを返す.この
249 * 関数は,CPUロック状態で呼び出される.
250 */
251Inline bool_t
252serialPort_sendChar(CELLCB *p_cellcb, char c)
253{
254 if (cSIOPort_putChar(c)) {
255 return(true);
256 }
257 else {
258 cSIOPort_enableCBR(SIOSendReady);
259 return(false);
260 }
261}
262
263/*
264 * シリアルポートへの1文字送信
265 */
266static ER_BOOL
267serialPort_writeChar(CELLCB *p_cellcb, char c)
268{
269 bool_t buffer_full;
270 ER ercd, rercd;
271
272 /*
273 * LFの前にCRを送信する.
274 */
275 if (c == '\n' && (VAR_ioControl & IOCTL_CRLF) != 0U) {
276 /*
277 * 以下のコードは再帰呼出しになっているが,引数cが'\n'の場合に
278 * 引数cを'\r'として呼び出すことから,この再帰呼出しは2回目の
279 * 呼び出しで必ず止まる.
280 */
281 SVC(rercd = serialPort_writeChar(p_cellcb, '\r'), rercd);
282 if ((bool_t) rercd) {
283 SVC(rercd = cSendSemaphore_wait(),
284 gen_ercd_wait(rercd, p_cellcb));
285 }
286 }
287
288 SVC(loc_cpu(), gen_ercd_sys(p_cellcb));
289 if (VAR_sendCount == 0U && !VAR_sendStopped
290 && serialPort_sendChar(p_cellcb, c)) {
291 /*
292 * SIOの送信レジスタに文字を入れることに成功した場合.
293 */
294 buffer_full = false;
295 }
296 else {
297 /*
298 * 送信バッファに文字を入れる.
299 */
300 VAR_sendBuffer[VAR_sendWritePointer] = c;
301 INC_PTR(VAR_sendWritePointer, ATTR_sendBufferSize);
302 VAR_sendCount++;
303 buffer_full = (VAR_sendCount == ATTR_sendBufferSize);
304 }
305
306 SVC(unl_cpu(), gen_ercd_sys(p_cellcb));
307 ercd = (ER_BOOL) buffer_full;
308
309 error_exit:
310 return(ercd);
311}
312
313/*
314 * シリアルポートへの文字列送信(受け口関数)
315 */
316ER_UINT
317eSerialPort_write(CELLIDX idx, const char *buffer, uint_t length)
318{
319 CELLCB *p_cellcb;
320 bool_t buffer_full;
321 uint_t wricnt = 0U;
322 ER ercd, rercd;
323
324 if (sns_dpn()) { /* コンテキストのチェック */
325 return(E_CTX);
326 }
327 if (!VALID_IDX(idx)) { /* ポート番号のチェック */
328 return(E_ID);
329 }
330
331 p_cellcb = GET_CELLCB(idx);
332 if (!VAR_openFlag) { /* オープン済みかのチェック */
333 return(E_OBJ);
334 }
335 if (VAR_errorFlag) { /* エラー状態かのチェック */
336 return(E_SYS);
337 }
338
339 buffer_full = true; /* ループの1回めはwai_semする */
340 while (wricnt < length) {
341 if (buffer_full) {
342 SVC(rercd = cSendSemaphore_wait(),
343 gen_ercd_wait(rercd, p_cellcb));
344 }
345 SVC(rercd = serialPort_writeChar(p_cellcb, *buffer++), rercd);
346 wricnt++;
347 buffer_full = (bool_t) rercd;
348 }
349 if (!buffer_full) {
350 SVC(cSendSemaphore_signal(), gen_ercd_sys(p_cellcb));
351 }
352 ercd = E_OK;
353
354 error_exit:
355 return(wricnt > 0U ? (ER_UINT) wricnt : ercd);
356}
357
358/*
359 * シリアルポートからの1文字受信
360 */
361static bool_t
362serialPort_readChar(CELLCB *p_cellcb, char *p_c)
363{
364 bool_t buffer_empty;
365 ER ercd;
366
367 SVC(loc_cpu(), gen_ercd_sys(p_cellcb));
368
369 /*
370 * 受信バッファから文字を取り出す.
371 */
372 *p_c = VAR_receiveBuffer[VAR_receiveReadPointer];
373 INC_PTR(VAR_receiveReadPointer, ATTR_receiveBufferSize);
374 VAR_receiveCount--;
375 buffer_empty = (VAR_receiveCount == 0U);
376
377 /*
378 * STARTを送信する.
379 */
380 if (VAR_receiveStopped && VAR_receiveCount
381 <= BUFCNT_START(ATTR_receiveBufferSize)) {
382 if (!serialPort_sendChar(p_cellcb, FC_START)) {
383 VAR_receiveFlowControl = FC_START;
384 }
385 VAR_receiveStopped = false;
386 }
387
388 SVC(unl_cpu(), gen_ercd_sys(p_cellcb));
389 ercd = (ER_BOOL) buffer_empty;
390
391 error_exit:
392 return(ercd);
393}
394
395/*
396 * シリアルポートからの文字列受信(受け口関数)
397 */
398ER_UINT
399eSerialPort_read(CELLIDX idx, char *buffer, uint_t length)
400{
401 CELLCB *p_cellcb;
402 bool_t buffer_empty;
403 uint_t reacnt = 0U;
404 char c = '\0'; /* コンパイラの警告を抑止するために初期化する */
405 ER ercd, rercd;
406
407 if (sns_dpn()) { /* コンテキストのチェック */
408 return(E_CTX);
409 }
410 if (!VALID_IDX(idx)) { /* ポート番号のチェック */
411 return(E_ID);
412 }
413
414 p_cellcb = GET_CELLCB(idx);
415 if (!VAR_openFlag) { /* オープン済みかのチェック */
416 return(E_OBJ);
417 }
418 if (VAR_errorFlag) { /* エラー状態かのチェック */
419 return(E_SYS);
420 }
421
422 buffer_empty = true; /* ループの1回めはwai_semする */
423 while (reacnt < length) {
424 if (buffer_empty) {
425 SVC(rercd = cReceiveSemaphore_wait(),
426 gen_ercd_wait(rercd, p_cellcb));
427 }
428 SVC(rercd = serialPort_readChar(p_cellcb, &c), rercd);
429 *buffer++ = c;
430 reacnt++;
431 buffer_empty = (bool_t) rercd;
432
433 /*
434 * エコーバック処理.
435 */
436 if ((VAR_ioControl & IOCTL_ECHO) != 0U) {
437 SVC(rercd = cSendSemaphore_wait(),
438 gen_ercd_wait(rercd, p_cellcb));
439 SVC(rercd = serialPort_writeChar(p_cellcb, c), rercd);
440 if (!((bool_t) rercd)) {
441 SVC(cSendSemaphore_signal(), gen_ercd_sys(p_cellcb));
442 }
443 }
444 }
445 if (!buffer_empty) {
446 SVC(cReceiveSemaphore_signal(), gen_ercd_sys(p_cellcb));
447 }
448 ercd = E_OK;
449
450 error_exit:
451 return(reacnt > 0U ? (ER_UINT) reacnt : ercd);
452}
453
454/*
455 * シリアルポートの制御(受け口関数)
456 */
457ER
458eSerialPort_control(CELLIDX idx, uint_t ioctl)
459{
460 CELLCB *p_cellcb;
461
462 if (sns_dpn()) { /* コンテキストのチェック */
463 return(E_CTX);
464 }
465 if (!VALID_IDX(idx)) {
466 return(E_ID); /* ポート番号のチェック */
467 }
468
469 p_cellcb = GET_CELLCB(idx);
470 if (!VAR_openFlag) { /* オープン済みかのチェック */
471 return(E_OBJ);
472 }
473 if (VAR_errorFlag) { /* エラー状態かのチェック */
474 return(E_SYS);
475 }
476
477 VAR_ioControl = ioctl;
478 return(E_OK);
479}
480
481/*
482 * シリアルポート状態の参照(受け口関数)
483 */
484ER
485eSerialPort_refer(CELLIDX idx, T_SERIAL_RPOR* pk_rpor)
486{
487 CELLCB *p_cellcb;
488
489 if (sns_dpn()) { /* コンテキストのチェック */
490 return(E_CTX);
491 }
492 if (!VALID_IDX(idx)) {
493 return(E_ID); /* ポート番号のチェック */
494 }
495
496 p_cellcb = GET_CELLCB(idx);
497 if (!VAR_openFlag) { /* オープン済みかのチェック */
498 return(E_OBJ);
499 }
500 if (VAR_errorFlag) { /* エラー状態かのチェック */
501 return(E_SYS);
502 }
503
504 pk_rpor->reacnt = VAR_receiveCount;
505 pk_rpor->wricnt = VAR_sendCount;
506 return(E_OK);
507}
508
509/*
510 * シリアルポートからの送信可能コールバック(受け口関数)
511 */
512void
513eiSIOCBR_readySend(CELLIDX idx)
514{
515 CELLCB *p_cellcb;
516
517 assert(VALID_IDX(idx));
518 p_cellcb = GET_CELLCB(idx);
519 if (VAR_receiveFlowControl != '\0') {
520 /*
521 * START/STOP を送信する.
522 */
523 (void) cSIOPort_putChar(VAR_receiveFlowControl);
524 VAR_receiveFlowControl = '\0';
525 }
526 else if (!VAR_sendStopped && VAR_sendCount > 0U) {
527 /*
528 * 送信バッファ中から文字を取り出して送信する.
529 */
530 (void) cSIOPort_putChar(VAR_sendBuffer[VAR_sendReadPointer]);
531 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
532 if (VAR_sendCount == ATTR_sendBufferSize) {
533 if (ciSendSemaphore_signal() < 0) {
534 VAR_errorFlag = true;
535 }
536 }
537 VAR_sendCount--;
538 }
539 else {
540 /*
541 * 送信すべき文字がない場合は,送信可能コールバックを禁止する.
542 */
543 cSIOPort_disableCBR(SIOSendReady);
544 }
545}
546
547/*
548 * シリアルポートからの受信通知コールバック(受け口関数)
549 */
550void
551eiSIOCBR_readyReceive(CELLIDX idx)
552{
553 CELLCB *p_cellcb;
554 char c;
555
556 assert(VALID_IDX(idx));
557 p_cellcb = GET_CELLCB(idx);
558 c = (char) cSIOPort_getChar();
559 if ((VAR_ioControl & IOCTL_FCSND) != 0U && c == FC_STOP) {
560 /*
561 * 送信を一時停止する.送信中の文字はそのまま送信する.
562 */
563 VAR_sendStopped = true;
564 }
565 else if (VAR_sendStopped && (c == FC_START
566 || (VAR_ioControl & IOCTL_FCANY) != 0U)) {
567 /*
568 * 送信を再開する.
569 */
570 VAR_sendStopped = false;
571 if (VAR_sendCount > 0U) {
572 c = VAR_sendBuffer[VAR_sendReadPointer];
573 if (serialPort_sendChar(p_cellcb, c)) {
574 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
575 if (VAR_sendCount == ATTR_sendBufferSize) {
576 if (ciSendSemaphore_signal() < 0) {
577 VAR_errorFlag = true;
578 }
579 }
580 VAR_sendCount--;
581 }
582 }
583 }
584 else if ((VAR_ioControl & IOCTL_FCSND) != 0U && c == FC_START) {
585 /*
586 * 送信に対してフロー制御している場合,START は捨てる.
587 */
588 }
589 else if (VAR_receiveCount == ATTR_receiveBufferSize) {
590 /*
591 * バッファフルの場合,受信した文字を捨てる.
592 */
593 }
594 else {
595 /*
596 * 受信した文字を受信バッファに入れる.
597 */
598 VAR_receiveBuffer[VAR_receiveWritePointer] = c;
599 INC_PTR(VAR_receiveWritePointer, ATTR_receiveBufferSize);
600 if (VAR_receiveCount == 0U) {
601 if (ciReceiveSemaphore_signal() < 0) {
602 VAR_errorFlag = true;
603 }
604 }
605 VAR_receiveCount++;
606
607 /*
608 * STOPを送信する.
609 */
610 if ((VAR_ioControl & IOCTL_FCRCV) != 0U && !VAR_receiveStopped
611 && VAR_receiveCount >= BUFCNT_STOP(ATTR_receiveBufferSize)) {
612 if (!serialPort_sendChar(p_cellcb, FC_STOP)) {
613 VAR_receiveFlowControl = FC_STOP;
614 }
615 VAR_receiveStopped = true;
616 }
617 }
618}
619
620/*
621 * シリアルインタフェースドライバからの未送信文字の取出し
622 */
623bool_t
624enSerialPortManage_getChar(CELLIDX idx, char *p_c)
625{
626 CELLCB *p_cellcb;
627
628 if (VALID_IDX(idx)) { /* ポート番号のチェック */
629 p_cellcb = GET_CELLCB(idx);
630 if (VAR_openFlag) { /* オープン済みかのチェック */
631 if (VAR_sendCount > 0U) {
632 *p_c = VAR_sendBuffer[VAR_sendReadPointer];
633 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
634 VAR_sendCount--;
635 return(true);
636 }
637 }
638 }
639 return(false);
640}
Note: See TracBrowser for help on using the repository browser.