source: azure_iot_hub/trunk/asp3_dcre/syssvc/tSerialPortMain.c@ 389

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

ビルドが通るよう更新

  • 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/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, 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 if (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 }
589 }
590 else if ((VAR_ioControl & IOCTL_FCSND) != 0U && c == FC_START) {
591 /*
592 * 送信に対してフロー制御している場合,START は捨てる.
593 */
594 }
595 else if (VAR_receiveCount == ATTR_receiveBufferSize) {
596 /*
597 * バッファフルの場合,受信した文字を捨てる.
598 */
599 }
600 else {
601 /*
602 * 受信した文字を受信バッファに入れる.
603 */
604 VAR_receiveBuffer[VAR_receiveWritePointer] = c;
605 INC_PTR(VAR_receiveWritePointer, ATTR_receiveBufferSize);
606 if (VAR_receiveCount == 0U) {
607 if (ciReceiveSemaphore_signal() < 0) {
608 VAR_errorFlag = true;
609 }
610 }
611 VAR_receiveCount++;
612
613 /*
614 * STOPを送信する.
615 */
616 if ((VAR_ioControl & IOCTL_FCRCV) != 0U && !VAR_receiveStopped
617 && VAR_receiveCount >= BUFCNT_STOP(ATTR_receiveBufferSize)) {
618 if (!serialPort_sendChar(p_cellcb, FC_STOP)) {
619 VAR_receiveFlowControl = FC_STOP;
620 }
621 VAR_receiveStopped = true;
622 }
623 }
624}
625
626/*
627 * シリアルインタフェースドライバからの未送信文字の取出し
628 */
629bool_t
630enSerialPortManage_getChar(CELLIDX idx, char *p_c)
631{
632 CELLCB *p_cellcb;
633
634 if (VALID_IDX(idx)) { /* ポート番号のチェック */
635 p_cellcb = GET_CELLCB(idx);
636 if (VAR_openFlag) { /* オープン済みかのチェック */
637 if (VAR_sendCount > 0U) {
638 *p_c = VAR_sendBuffer[VAR_sendReadPointer];
639 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
640 VAR_sendCount--;
641 return(true);
642 }
643 }
644 }
645 return(false);
646}
Note: See TracBrowser for help on using the repository browser.