source: EcnlProtoTool/trunk/asp3_dcre/syssvc/tSerialPortMain.c

Last change on this file 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: 16.1 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
6 * Toyohashi Univ. of Technology, JAPAN
7 * Copyright (C) 2006-2018 by Embedded and Real-Time Systems Laboratory
8 * Graduate School of Information Science, Nagoya Univ., JAPAN
9 *
10 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
11 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
12 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
13 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15 * スコード中に含まれていること.
16 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
18 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
19 * の無保証規定を掲載すること.
20 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
21 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
22 * と.
23 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
24 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
25 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
26 * 報告すること.
27 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
28 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
29 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
30 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
31 * 免責すること.
32 *
33 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
34 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
35 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
36 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
37 * の責任を負わない.
38 *
39 * $Id$
40 */
41
42/*
43 * シリアルインタフェースドライバ
44 */
45
46#include <kernel.h>
47#include "tSerialPortMain_tecsgen.h"
48#include <t_syslog.h>
49
50/*
51 * フロー制御に関連する定数とマクロ
52 */
53#define FC_STOP '\023' /* コントロール-S */
54#define FC_START '\021' /* コントロール-Q */
55
56#define BUFCNT_STOP(bufsz) ((bufsz) * 3 / 4) /* STOPを送る基準文字数 */
57#define BUFCNT_START(bufsz) ((bufsz) / 2) /* STARTを送る基準文字数 */
58
59/*
60 * ポインタのインクリメント
61 */
62#define INC_PTR(ptr, bufsz) do { \
63 if (++(ptr) == (bufsz)) { \
64 (ptr) = 0; \
65 } \
66} while (false)
67
68/*
69 * サービスコール呼出しマクロ
70 *
71 * サービスコール呼出しを含む式expを評価し,返値がエラー(負の値)の場
72 * 合には,ercにercd_expを評価した値を代入し,error_exitにgotoする.
73 */
74#define SVC(exp, ercd_exp) do { \
75 if ((exp) < 0) { \
76 ercd = (ercd_exp); \
77 goto error_exit; \
78 } \
79} while (false)
80
81/*
82 * E_SYSエラーの生成
83 */
84static ER
85gen_ercd_sys(CELLCB *p_cellcb)
86{
87 VAR_errorFlag = true;
88 return(E_SYS);
89}
90
91/*
92 * 待ちに入るサービスコールからのエラーの変換
93 */
94static ER
95gen_ercd_wait(ER rercd, CELLCB *p_cellcb)
96{
97 switch (MERCD(rercd)) {
98 case E_RLWAI:
99 case E_DLT:
100 case E_RASTER:
101 return(rercd);
102 default:
103 VAR_errorFlag = true;
104 return(E_SYS);
105 }
106}
107
108/*
109 * シリアルポートのオープン(受け口関数)
110 */
111ER
112eSerialPort_open(CELLIDX idx)
113{
114 CELLCB *p_cellcb;
115 ER ercd;
116
117 if (sns_dpn()) { /* コンテキストのチェック */
118 return(E_CTX);
119 }
120 if (!VALID_IDX(idx)) {
121 return(E_ID); /* ポート番号のチェック */
122 }
123 p_cellcb = GET_CELLCB(idx);
124
125 SVC(dis_dsp(), gen_ercd_sys(p_cellcb));
126 if (VAR_openFlag) { /* オープン済みかのチェック */
127 ercd = E_OBJ;
128 }
129 else {
130 /*
131 * 変数の初期化
132 */
133 VAR_ioControl = (IOCTL_ECHO | IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
134
135 VAR_receiveReadPointer = 0U;
136 VAR_receiveWritePointer = 0U;
137 VAR_receiveCount = 0U;
138 VAR_receiveFlowControl = '\0';
139 VAR_receiveStopped = false;
140
141 VAR_sendReadPointer = 0U;
142 VAR_sendWritePointer = 0U;
143 VAR_sendCount = 0U;
144 VAR_sendStopped = false;
145
146 /*
147 * これ以降,割込みを禁止する.
148 */
149 if (loc_cpu() < 0) {
150 ercd = E_SYS;
151 goto error_exit_enadsp;
152 }
153
154 /*
155 * ハードウェア依存のオープン処理
156 */
157 cSIOPort_open();
158
159 /*
160 * 受信通知コールバックを許可する.
161 */
162 cSIOPort_enableCBR(SIOReceiveReady);
163 VAR_openFlag = true;
164 VAR_errorFlag = false;
165
166 if (unl_cpu() < 0) {
167 VAR_errorFlag = true;
168 ercd = E_SYS;
169 goto error_exit_enadsp;
170 }
171 ercd = E_OK;
172 }
173
174 error_exit_enadsp:
175 SVC(ena_dsp(), gen_ercd_sys(p_cellcb));
176
177 error_exit:
178 return(ercd);
179}
180
181/*
182 * シリアルポートのクローズ(受け口関数)
183 */
184ER
185eSerialPort_close(CELLIDX idx)
186{
187 CELLCB *p_cellcb;
188 ER ercd;
189 bool_t eflag = false;
190
191 if (sns_dpn()) { /* コンテキストのチェック */
192 return(E_CTX);
193 }
194 if (!VALID_IDX(idx)) {
195 return(E_ID); /* ポート番号のチェック */
196 }
197 p_cellcb = GET_CELLCB(idx);
198
199 SVC(dis_dsp(), gen_ercd_sys(p_cellcb));
200 if (!VAR_openFlag) { /* オープン済みかのチェック */
201 ercd = E_OBJ;
202 }
203 else {
204 /*
205 * ハードウェア依存のクローズ処理
206 */
207 if (loc_cpu() < 0) {
208 eflag = true;
209 }
210 cSIOPort_close();
211 VAR_openFlag = false;
212 if (unl_cpu() < 0) {
213 eflag = true;
214 }
215
216 /*
217 * セマフォの初期化
218 */
219 if (cSendSemaphore_initialize() < 0) {
220 eflag = true;
221 }
222 if (cReceiveSemaphore_initialize() < 0) {
223 eflag = true;
224 }
225
226 /*
227 * エラーコードの設定
228 */
229 if (eflag) {
230 ercd = gen_ercd_sys(p_cellcb);
231 }
232 else {
233 ercd = E_OK;
234 }
235 }
236 SVC(ena_dsp(), gen_ercd_sys(p_cellcb));
237
238 error_exit:
239 return(ercd);
240}
241
242/*
243 * SIOポートへの文字送信
244 *
245 * p_cellcbで指定されるシリアルポートに対応するSIOポートに対して,文
246 * 字cを送信する.文字を送信レジスタにいれた場合にはtrueを返す.そう
247 * でない場合には,送信レジスタが空いたことを通知するコールバック関数
248 * を許可し,falseを返す.この関数は,CPUロック状態で呼び出される.
249 */
250Inline bool_t
251serialPort_sendChar(CELLCB *p_cellcb, char c)
252{
253 if (cSIOPort_putChar(c)) {
254 return(true);
255 }
256 else {
257 cSIOPort_enableCBR(SIOSendReady);
258 return(false);
259 }
260}
261
262/*
263 * シリアルポートへの1文字送信
264 */
265static ER_BOOL
266serialPort_writeChar(CELLCB *p_cellcb, char c)
267{
268 bool_t buffer_full;
269 ER_BOOL ercd;
270 ER 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 ER_BOOL
362serialPort_readChar(CELLCB *p_cellcb, char *p_c)
363{
364 bool_t buffer_empty;
365 ER_BOOL 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, TMO tmout)
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 rercd = cReceiveSemaphore_waitTimeout(tmout);
426 if (rercd == E_TMOUT)
427 return E_TMOUT;
428 if (rercd < 0) {
429 gen_ercd_wait(rercd, p_cellcb);
430 ercd = rercd;
431 goto error_exit;
432 }
433 }
434 SVC(rercd = serialPort_readChar(p_cellcb, &c), rercd);
435 *buffer++ = c;
436 reacnt++;
437 buffer_empty = (bool_t) rercd;
438
439 /*
440 * エコーバック処理.
441 */
442 if ((VAR_ioControl & IOCTL_ECHO) != 0U) {
443 SVC(rercd = cSendSemaphore_wait(),
444 gen_ercd_wait(rercd, p_cellcb));
445 SVC(rercd = serialPort_writeChar(p_cellcb, c), rercd);
446 if (!((bool_t) rercd)) {
447 SVC(cSendSemaphore_signal(), gen_ercd_sys(p_cellcb));
448 }
449 }
450 }
451 if (!buffer_empty) {
452 SVC(cReceiveSemaphore_signal(), gen_ercd_sys(p_cellcb));
453 }
454 ercd = E_OK;
455
456 error_exit:
457 return(reacnt > 0U ? (ER_UINT) reacnt : ercd);
458}
459
460/*
461 * シリアルポートの制御(受け口関数)
462 */
463ER
464eSerialPort_control(CELLIDX idx, uint_t ioctl)
465{
466 CELLCB *p_cellcb;
467
468 if (sns_dpn()) { /* コンテキストのチェック */
469 return(E_CTX);
470 }
471 if (!VALID_IDX(idx)) {
472 return(E_ID); /* ポート番号のチェック */
473 }
474
475 p_cellcb = GET_CELLCB(idx);
476 if (!VAR_openFlag) { /* オープン済みかのチェック */
477 return(E_OBJ);
478 }
479 if (VAR_errorFlag) { /* エラー状態かのチェック */
480 return(E_SYS);
481 }
482
483 VAR_ioControl = ioctl;
484 return(E_OK);
485}
486
487/*
488 * シリアルポート状態の参照(受け口関数)
489 */
490ER
491eSerialPort_refer(CELLIDX idx, T_SERIAL_RPOR* pk_rpor)
492{
493 CELLCB *p_cellcb;
494
495 if (sns_dpn()) { /* コンテキストのチェック */
496 return(E_CTX);
497 }
498 if (!VALID_IDX(idx)) {
499 return(E_ID); /* ポート番号のチェック */
500 }
501
502 p_cellcb = GET_CELLCB(idx);
503 if (!VAR_openFlag) { /* オープン済みかのチェック */
504 return(E_OBJ);
505 }
506 if (VAR_errorFlag) { /* エラー状態かのチェック */
507 return(E_SYS);
508 }
509
510 pk_rpor->reacnt = VAR_receiveCount;
511 pk_rpor->wricnt = VAR_sendCount;
512 return(E_OK);
513}
514
515/*
516 * シリアルポートからの送信可能コールバック(受け口関数)
517 */
518void
519eiSIOCBR_readySend(CELLIDX idx)
520{
521 CELLCB *p_cellcb;
522
523 assert(VALID_IDX(idx));
524 p_cellcb = GET_CELLCB(idx);
525 if (VAR_receiveFlowControl != '\0') {
526 /*
527 * START/STOPを送信する.
528 */
529 (void) cSIOPort_putChar(VAR_receiveFlowControl);
530 VAR_receiveFlowControl = '\0';
531 }
532 else if (!VAR_sendStopped && VAR_sendCount > 0U) {
533 /*
534 * 送信バッファ中から文字を取り出して送信する.
535 */
536 (void) cSIOPort_putChar(VAR_sendBuffer[VAR_sendReadPointer]);
537 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
538 if (VAR_sendCount == ATTR_sendBufferSize) {
539 if (ciSendSemaphore_signal() < 0) {
540 VAR_errorFlag = true;
541 }
542 }
543 VAR_sendCount--;
544 }
545 else {
546 /*
547 * 送信すべき文字がない場合は,送信可能コールバックを禁止する.
548 */
549 cSIOPort_disableCBR(SIOSendReady);
550 }
551}
552
553/*
554 * シリアルポートからの受信通知コールバック(受け口関数)
555 */
556void
557eiSIOCBR_readyReceive(CELLIDX idx)
558{
559 CELLCB *p_cellcb;
560 char c;
561
562 assert(VALID_IDX(idx));
563 p_cellcb = GET_CELLCB(idx);
564 c = (char) cSIOPort_getChar();
565 if ((VAR_ioControl & IOCTL_FCSND) != 0U && c == FC_STOP) {
566 /*
567 * 送信を一時停止する.送信中の文字はそのまま送信する.
568 */
569 VAR_sendStopped = true;
570 }
571 else if (VAR_sendStopped && (c == FC_START
572 || (VAR_ioControl & IOCTL_FCANY) != 0U)) {
573 /*
574 * 送信を再開する.
575 */
576 VAR_sendStopped = false;
577 while (VAR_sendCount > 0U) {
578 c = VAR_sendBuffer[VAR_sendReadPointer];
579 if (serialPort_sendChar(p_cellcb, c)) {
580 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
581 if (VAR_sendCount == ATTR_sendBufferSize) {
582 if (ciSendSemaphore_signal() < 0) {
583 VAR_errorFlag = true;
584 }
585 }
586 VAR_sendCount--;
587 }
588 else {
589 break;
590 }
591 }
592 }
593 else if ((VAR_ioControl & IOCTL_FCSND) != 0U && c == FC_START) {
594 /*
595 * 送信に対してフロー制御している場合,START は捨てる.
596 */
597 }
598 else if (VAR_receiveCount == ATTR_receiveBufferSize) {
599 /*
600 * バッファフルの場合,受信した文字を捨てる.
601 */
602 }
603 else {
604 /*
605 * 受信した文字を受信バッファに入れる.
606 */
607 VAR_receiveBuffer[VAR_receiveWritePointer] = c;
608 INC_PTR(VAR_receiveWritePointer, ATTR_receiveBufferSize);
609 if (VAR_receiveCount == 0U) {
610 if (ciReceiveSemaphore_signal() < 0) {
611 VAR_errorFlag = true;
612 }
613 }
614 VAR_receiveCount++;
615
616 /*
617 * STOPを送信する.
618 */
619 if ((VAR_ioControl & IOCTL_FCRCV) != 0U && !VAR_receiveStopped
620 && VAR_receiveCount >= BUFCNT_STOP(ATTR_receiveBufferSize)) {
621 if (!serialPort_sendChar(p_cellcb, FC_STOP)) {
622 VAR_receiveFlowControl = FC_STOP;
623 }
624 VAR_receiveStopped = true;
625 }
626 }
627}
628
629/*
630 * シリアルインタフェースドライバからの未送信文字の取出し
631 */
632bool_t
633enSerialPortManage_getChar(CELLIDX idx, char *p_c)
634{
635 CELLCB *p_cellcb;
636
637 if (VALID_IDX(idx)) { /* ポート番号のチェック */
638 p_cellcb = GET_CELLCB(idx);
639 if (VAR_openFlag) { /* オープン済みかのチェック */
640 if (VAR_sendCount > 0U) {
641 *p_c = VAR_sendBuffer[VAR_sendReadPointer];
642 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
643 VAR_sendCount--;
644 return(true);
645 }
646 }
647 }
648 return(false);
649}
Note: See TracBrowser for help on using the repository browser.