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

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

mruby版ECNLプロトタイピング・ツールを追加

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