source: rtos_arduino/trunk/asp_1.9.2/syssvc/serial.c@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 20.9 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-2013 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: serial.c 2524 2013-09-15 17:40:06Z ertl-hiro $
56 */
57
58/*
59 * シリアルインタフェースドライバ
60 */
61
62#include <kernel.h>
63#include <t_syslog.h>
64#include "target_syssvc.h"
65#include "target_serial.h"
66#include "serial.h"
67#include "kernel_cfg.h"
68
69/*
70 * バッファサイズのデフォルト値とバッファの定義
71 */
72#ifndef SERIAL_RCV_BUFSZ1
73#define SERIAL_RCV_BUFSZ1 256 /* ポート1の受信バッファサイズ */
74#endif /* SERIAL_RCV_BUFSZ1 */
75
76#ifndef SERIAL_SND_BUFSZ1
77#define SERIAL_SND_BUFSZ1 256 /* ポート1の送信バッファサイズ */
78#endif /* SERIAL_SND_BUFSZ1 */
79
80static char rcv_buffer1[SERIAL_RCV_BUFSZ1];
81static char snd_buffer1[SERIAL_SND_BUFSZ1];
82
83#if TNUM_PORT >= 2 /* ポート2に関する定義 */
84
85#ifndef SERIAL_RCV_BUFSZ2
86#define SERIAL_RCV_BUFSZ2 256 /* ポート2の受信バッファサイズ */
87#endif /* SERIAL_RCV_BUFSZ2 */
88
89#ifndef SERIAL_SND_BUFSZ2
90#define SERIAL_SND_BUFSZ2 256 /* ポート2の送信バッファサイズ */
91#endif /* SERIAL_SND_BUFSZ2 */
92
93static char rcv_buffer2[SERIAL_RCV_BUFSZ2];
94static char snd_buffer2[SERIAL_SND_BUFSZ2];
95
96#endif /* TNUM_PORT >= 2 */
97
98#if TNUM_PORT >= 3 /* ポート3に関する定義 */
99
100#ifndef SERIAL_RCV_BUFSZ3
101#define SERIAL_RCV_BUFSZ3 256 /* ポート3の受信バッファサイズ */
102#endif /* SERIAL_RCV_BUFSZ3 */
103
104#ifndef SERIAL_SND_BUFSZ3
105#define SERIAL_SND_BUFSZ3 256 /* ポート3の送信バッファサイズ */
106#endif /* SERIAL_SND_BUFSZ3 */
107
108static char rcv_buffer3[SERIAL_RCV_BUFSZ3];
109static char snd_buffer3[SERIAL_SND_BUFSZ3];
110
111#endif /* TNUM_PORT >= 3 */
112
113#if TNUM_PORT >= 4 /* ポート4に関する定義 */
114
115#ifndef SERIAL_RCV_BUFSZ4
116#define SERIAL_RCV_BUFSZ4 256 /* ポート4の受信バッファサイズ */
117#endif /* SERIAL_RCV_BUFSZ4 */
118
119#ifndef SERIAL_SND_BUFSZ4
120#define SERIAL_SND_BUFSZ4 256 /* ポート4の送信バッファサイズ */
121#endif /* SERIAL_SND_BUFSZ4 */
122
123static char rcv_buffer4[SERIAL_RCV_BUFSZ4];
124static char snd_buffer4[SERIAL_SND_BUFSZ4];
125
126#endif /* TNUM_PORT >= 4 */
127
128#if TNUM_PORT >= 5
129#error Serial interface driver supports up to 4 ports.
130#endif /* TNUM_PORT >= 5 */
131
132/*
133 * フロー制御に関連する定数とマクロ
134 */
135#define FC_STOP '\023' /* コントロール-S */
136#define FC_START '\021' /* コントロール-Q */
137
138#define BUFCNT_STOP(bufsz) ((bufsz) * 3 / 4) /* STOPを送る基準文字数 */
139#define BUFCNT_START(bufsz) ((bufsz) / 2) /* STARTを送る基準文字数 */
140
141/*
142 * シリアルポート初期化ブロック
143 */
144typedef struct serial_port_initialization_block {
145 ID rcv_semid; /* 受信バッファ管理用セマフォのID */
146 ID snd_semid; /* 送信バッファ管理用セマフォのID */
147 uint_t rcv_bufsz; /* 受信バッファサイズ */
148 char *rcv_buffer; /* 受信バッファ */
149 uint_t snd_bufsz; /* 送信バッファサイズ */
150 char *snd_buffer; /* 送信バッファ */
151} SPINIB;
152
153static const SPINIB spinib_table[TNUM_PORT] = {
154 { SERIAL_RCV_SEM1, SERIAL_SND_SEM1,
155 SERIAL_RCV_BUFSZ1, rcv_buffer1,
156 SERIAL_SND_BUFSZ1, snd_buffer1 },
157#if TNUM_PORT >= 2
158 { SERIAL_RCV_SEM2, SERIAL_SND_SEM2,
159 SERIAL_RCV_BUFSZ2, rcv_buffer2,
160 SERIAL_SND_BUFSZ2, snd_buffer2 },
161#endif /* TNUM_PORT >= 2 */
162#if TNUM_PORT >= 3
163 { SERIAL_RCV_SEM3, SERIAL_SND_SEM3,
164 SERIAL_RCV_BUFSZ3, rcv_buffer3,
165 SERIAL_SND_BUFSZ3, snd_buffer3 },
166#endif /* TNUM_PORT >= 3 */
167#if TNUM_PORT >= 4
168 { SERIAL_RCV_SEM4, SERIAL_SND_SEM4,
169 SERIAL_RCV_BUFSZ4, rcv_buffer4,
170 SERIAL_SND_BUFSZ4, snd_buffer4 },
171#endif /* TNUM_PORT >= 4 */
172};
173
174/*
175 * シリアルポート管理ブロック
176 */
177typedef struct serial_port_control_block {
178 const SPINIB *p_spinib; /* シリアルポート初期化ブロック */
179 SIOPCB *p_siopcb; /* シリアルI/Oポート管理ブロック */
180 bool_t openflag; /* オープン済みフラグ */
181 bool_t errorflag; /* エラーフラグ */
182 uint_t ioctl; /* 動作制御の設定値 */
183
184 uint_t rcv_read_ptr; /* 受信バッファ読出しポインタ */
185 uint_t rcv_write_ptr; /* 受信バッファ書込みポインタ */
186 uint_t rcv_count; /* 受信バッファ中の文字数 */
187 char rcv_fc_chr; /* 送るべきSTART/STOP */
188 bool_t rcv_stopped; /* STOPを送った状æ…
189‹ã‹ï¼Ÿ */
190
191 uint_t snd_read_ptr; /* 送信バッファ読出しポインタ */
192 uint_t snd_write_ptr; /* 送信バッファ書込みポインタ */
193 uint_t snd_count; /* 送信バッファ中の文字数 */
194 bool_t snd_stopped; /* STOPを受け取った状æ…
195‹ã‹ï¼Ÿ */
196} SPCB;
197
198static SPCB spcb_table[TNUM_PORT];
199
200/*
201 * シリアルポートIDからシリアルポート管理ブロックを取り出すためのマクロ
202 */
203#define INDEX_PORT(portid) ((uint_t)((portid) - 1))
204#define get_spcb(portid) (&(spcb_table[INDEX_PORT(portid)]))
205
206/*
207 * ポインタのインクリメント
208 */
209#define INC_PTR(ptr, bufsz) do { \
210 if (++(ptr) == (bufsz)) { \
211 (ptr) = 0; \
212 } \
213} while (false)
214
215/*
216 * サービスコール呼出しマクロ
217 *
218 * サービスコール呼出しを含む式expを評価し,返値がエラー(負の値)の場
219 * 合には,ercにercd_expを評価した値を代å…
220¥ã—,error_exitにgotoする.
221 */
222#define SVC(exp, ercd_exp) do { \
223 if ((exp) < 0) { \
224 ercd = (ercd_exp); \
225 goto error_exit; \
226 } \
227} while (false)
228
229/*
230 * E_SYSエラーの生成
231 */
232static ER
233gen_ercd_sys(SPCB *p_spcb)
234{
235 p_spcb->errorflag = true;
236 return(E_SYS);
237}
238
239/*
240 * 待
241ちにå…
242¥ã‚‹ã‚µãƒ¼ãƒ“スコールからのエラーの変換
243 */
244static ER
245gen_ercd_wait(ER rercd, SPCB *p_spcb)
246{
247 switch (MERCD(rercd)) {
248 case E_RLWAI:
249 case E_DLT:
250 return(rercd);
251 default:
252 p_spcb->errorflag = true;
253 return(E_SYS);
254 }
255}
256
257/*
258 * シリアルインタフェースドライバの初期化ルーチン
259 */
260void
261serial_initialize(intptr_t exinf)
262{
263 uint_t i;
264 SPCB *p_spcb;
265
266 for (i = 0; i < TNUM_PORT; i++) {
267 p_spcb = &(spcb_table[i]);
268 p_spcb->p_spinib = &(spinib_table[i]);
269 p_spcb->openflag = false;
270 }
271}
272
273/*
274 * シリアルポートのオープン(サービスコール)
275 */
276ER
277serial_opn_por(ID portid)
278{
279 SPCB *p_spcb;
280 ER ercd;
281
282 if (sns_dpn()) { /* コンテキストのチェック */
283 return(E_CTX);
284 }
285 if (!(1 <= portid && portid <= TNUM_PORT)) {
286 return(E_ID); /* ポート番号のチェック */
287 }
288 p_spcb = get_spcb(portid);
289
290 SVC(dis_dsp(), gen_ercd_sys(p_spcb));
291 if (p_spcb->openflag) { /* オープン済みかのチェック */
292 ercd = E_OBJ;
293 }
294 else {
295 /*
296 * 変数の初期化
297 */
298 p_spcb->ioctl = (IOCTL_ECHO | IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
299
300 p_spcb->rcv_read_ptr = 0U;
301 p_spcb->rcv_write_ptr = 0U;
302 p_spcb->rcv_count = 0U;
303 p_spcb->rcv_fc_chr = '\0';
304 p_spcb->rcv_stopped = false;
305
306 p_spcb->snd_read_ptr = 0U;
307 p_spcb->snd_write_ptr = 0U;
308 p_spcb->snd_count = 0U;
309 p_spcb->snd_stopped = false;
310
311 /*
312 * これ以降,割込みを禁止する.
313 */
314 if (loc_cpu() < 0) {
315 ercd = E_SYS;
316 goto error_exit_enadsp;
317 }
318
319 /*
320 * ハードウェア依存のオープン処理
321 */
322 p_spcb->p_siopcb = sio_opn_por(portid, (intptr_t) p_spcb);
323
324 /*
325 * 受信通知コールバックを許可する.
326 */
327 sio_ena_cbr(p_spcb->p_siopcb, SIO_RDY_RCV);
328 p_spcb->openflag = true;
329 p_spcb->errorflag = false;
330
331 if (unl_cpu() < 0) {
332 p_spcb->errorflag = true;
333 ercd = E_SYS;
334 goto error_exit_enadsp;
335 }
336 ercd = E_OK;
337 }
338
339 error_exit_enadsp:
340 SVC(ena_dsp(), gen_ercd_sys(p_spcb));
341
342 error_exit:
343 return(ercd);
344}
345
346/*
347 * シリアルポートのクローズ(サービスコール)
348 */
349ER
350serial_cls_por(ID portid)
351{
352 SPCB *p_spcb;
353 ER ercd;
354 bool_t eflag = false;
355
356 if (sns_dpn()) { /* コンテキストのチェック */
357 return(E_CTX);
358 }
359 if (!(1 <= portid && portid <= TNUM_PORT)) {
360 return(E_ID); /* ポート番号のチェック */
361 }
362 p_spcb = get_spcb(portid);
363
364 SVC(dis_dsp(), gen_ercd_sys(p_spcb));
365 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
366 ercd = E_OBJ;
367 }
368 else {
369 /*
370 * ハードウェア依存のクローズ処理
371 */
372 if (loc_cpu() < 0) {
373 eflag = true;
374 }
375 sio_cls_por(p_spcb->p_siopcb);
376 p_spcb->openflag = false;
377 if (unl_cpu() < 0) {
378 eflag = true;
379 }
380
381 /*
382 * セマフォの初期化
383 */
384 if (ini_sem(p_spcb->p_spinib->snd_semid) < 0) {
385 eflag = true;
386 }
387 if (ini_sem(p_spcb->p_spinib->rcv_semid) < 0) {
388 eflag = true;
389 }
390
391 /*
392 * エラーコードの設定
393 */
394 if (eflag) {
395 ercd = gen_ercd_sys(p_spcb);
396 }
397 else {
398 ercd = E_OK;
399 }
400 }
401 SVC(ena_dsp(), gen_ercd_sys(p_spcb));
402
403 error_exit:
404 return(ercd);
405}
406
407/*
408 * シリアルポートへの文字送信
409 *
410 * p_spcbで指定されるシリアルI/Oポートに対して,文字cを送信する.文字
411 * を送信レジスタにいれた場合にはtrueを返す.そうでない場合には,送信
412 * レジスタが空いたことを通知するコールバック関数を許可し,falseを返す.
413 * この関数は,CPUロック状æ…
414‹ã§å‘¼ã³å‡ºã•ã‚Œã‚‹ï¼Ž
415 */
416Inline bool_t
417serial_snd_chr(SPCB *p_spcb, char c)
418{
419 if (sio_snd_chr(p_spcb->p_siopcb, c)) {
420 return(true);
421 }
422 else {
423 sio_ena_cbr(p_spcb->p_siopcb, SIO_RDY_SND);
424 return(false);
425 }
426}
427
428/*
429 * シリアルポートへの1文字送信
430 */
431static ER_BOOL
432serial_wri_chr(SPCB *p_spcb, char c)
433{
434 bool_t buffer_full;
435 ER ercd, rercd;
436
437 /*
438 * LFの前にCRを送信する.
439 */
440 if (c == '\n' && (p_spcb->ioctl & IOCTL_CRLF) != 0U) {
441 /*
442 * 以下のコードは再帰呼出しになっているが,引数cが'\n'の場合に
443 * 引数cを'\r'として呼び出すことから,この再帰呼出しは2回目の
444 * 呼び出しで必
445ず止まる.
446 */
447 SVC(rercd = serial_wri_chr(p_spcb, '\r'), rercd);
448 if ((bool_t) rercd) {
449 SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
450 gen_ercd_wait(rercd, p_spcb));
451 }
452 }
453
454 SVC(loc_cpu(), gen_ercd_sys(p_spcb));
455 if (p_spcb->snd_count == 0U && !(p_spcb->snd_stopped)
456 && serial_snd_chr(p_spcb, c)) {
457 /*
458 * シリアルI/Oデバイスの送信レジスタに文字をå…
459¥ã‚Œã‚‹ã“とに成功し
460 * た場合.
461 */
462 buffer_full = false;
463 }
464 else {
465 /*
466 * 送信バッファに文字をå…
467¥ã‚Œã‚‹ï¼Ž
468 */
469 p_spcb->p_spinib->snd_buffer[p_spcb->snd_write_ptr] = c;
470 INC_PTR(p_spcb->snd_write_ptr, p_spcb->p_spinib->snd_bufsz);
471 p_spcb->snd_count++;
472 buffer_full = (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz);
473 }
474
475 SVC(unl_cpu(), gen_ercd_sys(p_spcb));
476 ercd = (ER_BOOL) buffer_full;
477
478 error_exit:
479 return(ercd);
480}
481
482/*
483 * シリアルポートへの文字列送信(サービスコール)
484 */
485ER_UINT
486serial_wri_dat(ID portid, const char *buf, uint_t len)
487{
488 SPCB *p_spcb;
489 bool_t buffer_full;
490 uint_t wricnt = 0U;
491 ER ercd, rercd;
492
493 if (sns_dpn()) { /* コンテキストのチェック */
494 return(E_CTX);
495 }
496 if (!(1 <= portid && portid <= TNUM_PORT)) {
497 return(E_ID); /* ポート番号のチェック */
498 }
499
500 p_spcb = get_spcb(portid);
501 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
502 return(E_OBJ);
503 }
504 if (p_spcb->errorflag) { /* エラー状æ…
505‹ã‹ã®ãƒã‚§ãƒƒã‚¯ */
506 return(E_SYS);
507 }
508
509 buffer_full = true; /* ループの1回めはwai_semする */
510 while (wricnt < len) {
511 if (buffer_full) {
512 SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
513 gen_ercd_wait(rercd, p_spcb));
514 }
515 SVC(rercd = serial_wri_chr(p_spcb, *buf++), rercd);
516 wricnt++;
517 buffer_full = (bool_t) rercd;
518 }
519 if (!buffer_full) {
520 SVC(sig_sem(p_spcb->p_spinib->snd_semid), gen_ercd_sys(p_spcb));
521 }
522 ercd = E_OK;
523
524 error_exit:
525 return(wricnt > 0U ? (ER_UINT) wricnt : ercd);
526}
527
528/*
529 * シリアルポートからの1文字受信
530 */
531static bool_t
532serial_rea_chr(SPCB *p_spcb, char *p_c)
533{
534 bool_t buffer_empty;
535 ER ercd;
536
537 SVC(loc_cpu(), gen_ercd_sys(p_spcb));
538
539 /*
540 * 受信バッファから文字を取り出す.
541 */
542 *p_c = p_spcb->p_spinib->rcv_buffer[p_spcb->rcv_read_ptr];
543 INC_PTR(p_spcb->rcv_read_ptr, p_spcb->p_spinib->rcv_bufsz);
544 p_spcb->rcv_count--;
545 buffer_empty = (p_spcb->rcv_count == 0U);
546
547 /*
548 * STARTを送信する.
549 */
550 if (p_spcb->rcv_stopped && p_spcb->rcv_count
551 <= BUFCNT_START(p_spcb->p_spinib->rcv_bufsz)) {
552 if (!serial_snd_chr(p_spcb, FC_START)) {
553 p_spcb->rcv_fc_chr = FC_START;
554 }
555 p_spcb->rcv_stopped = false;
556 }
557
558 SVC(unl_cpu(), gen_ercd_sys(p_spcb));
559 ercd = (ER_BOOL) buffer_empty;
560
561 error_exit:
562 return(ercd);
563}
564
565/*
566 * シリアルポートからの文字列受信(サービスコール)
567 */
568ER_UINT
569serial_rea_dat(ID portid, char *buf, uint_t len)
570{
571 SPCB *p_spcb;
572 bool_t buffer_empty;
573 uint_t reacnt = 0U;
574 char c = '\0'; /* コンパイラの警告を抑止するために初期化する */
575 ER ercd, rercd;
576
577 if (sns_dpn()) { /* コンテキストのチェック */
578 return(E_CTX);
579 }
580 if (!(1 <= portid && portid <= TNUM_PORT)) {
581 return(E_ID); /* ポート番号のチェック */
582 }
583
584 p_spcb = get_spcb(portid);
585 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
586 return(E_OBJ);
587 }
588 if (p_spcb->errorflag) { /* エラー状æ…
589‹ã‹ã®ãƒã‚§ãƒƒã‚¯ */
590 return(E_SYS);
591 }
592
593 buffer_empty = true; /* ループの1回めはwai_semする */
594 while (reacnt < len) {
595 if (buffer_empty) {
596 SVC(rercd = wai_sem(p_spcb->p_spinib->rcv_semid),
597 gen_ercd_wait(rercd, p_spcb));
598 }
599 SVC(rercd = serial_rea_chr(p_spcb, &c), rercd);
600 *buf++ = c;
601 reacnt++;
602 buffer_empty = (bool_t) rercd;
603
604 /*
605 * エコーバック処理.
606 */
607 if ((p_spcb->ioctl & IOCTL_ECHO) != 0U) {
608 SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
609 gen_ercd_wait(rercd, p_spcb));
610 SVC(rercd = serial_wri_chr(p_spcb, c), rercd);
611 if (!((bool_t) rercd)) {
612 SVC(sig_sem(p_spcb->p_spinib->snd_semid),
613 gen_ercd_sys(p_spcb));
614 }
615 }
616 }
617 if (!buffer_empty) {
618 SVC(sig_sem(p_spcb->p_spinib->rcv_semid), gen_ercd_sys(p_spcb));
619 }
620 ercd = E_OK;
621
622 error_exit:
623 return(reacnt > 0U ? (ER_UINT) reacnt : ercd);
624}
625
626/*
627 * シリアルポートの制御(サービスコール)
628 */
629ER
630serial_ctl_por(ID portid, uint_t ioctl)
631{
632 SPCB *p_spcb;
633
634 if (sns_dpn()) { /* コンテキストのチェック */
635 return(E_CTX);
636 }
637 if (!(1 <= portid && portid <= TNUM_PORT)) {
638 return(E_ID); /* ポート番号のチェック */
639 }
640
641 p_spcb = get_spcb(portid);
642 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
643 return(E_OBJ);
644 }
645 if (p_spcb->errorflag) { /* エラー状æ…
646‹ã‹ã®ãƒã‚§ãƒƒã‚¯ */
647 return(E_SYS);
648 }
649
650 p_spcb->ioctl = ioctl;
651 return(E_OK);
652}
653
654/*
655 * シリアルポート状æ…
656‹ã®å‚ç…
657§ï¼ˆã‚µãƒ¼ãƒ“スコール)
658 */
659ER
660serial_ref_por(ID portid, T_SERIAL_RPOR *pk_rpor)
661{
662 SPCB *p_spcb;
663
664 if (sns_dpn()) { /* コンテキストのチェック */
665 return(E_CTX);
666 }
667 if (!(1 <= portid && portid <= TNUM_PORT)) {
668 return(E_ID); /* ポート番号のチェック */
669 }
670
671 p_spcb = get_spcb(portid);
672 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
673 return(E_OBJ);
674 }
675 if (p_spcb->errorflag) { /* エラー状æ…
676‹ã‹ã®ãƒã‚§ãƒƒã‚¯ */
677 return(E_SYS);
678 }
679
680 pk_rpor->reacnt = p_spcb->rcv_count;
681 pk_rpor->wricnt = p_spcb->snd_count;
682 return(E_OK);
683}
684
685/*
686 * シリアルポートからの送信可能コールバック
687 */
688void
689sio_irdy_snd(intptr_t exinf)
690{
691 SPCB *p_spcb;
692
693 p_spcb = (SPCB *) exinf;
694 if (p_spcb->rcv_fc_chr != '\0') {
695 /*
696 * START/STOP を送信する.
697 */
698 (void) sio_snd_chr(p_spcb->p_siopcb, p_spcb->rcv_fc_chr);
699 p_spcb->rcv_fc_chr = '\0';
700 }
701 else if (!(p_spcb->snd_stopped) && p_spcb->snd_count > 0U) {
702 /*
703 * 送信バッファ中から文字を取り出して送信する.
704 */
705 (void) sio_snd_chr(p_spcb->p_siopcb,
706 p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr]);
707 INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
708 if (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz) {
709 if (isig_sem(p_spcb->p_spinib->snd_semid) < 0) {
710 p_spcb->errorflag = true;
711 }
712 }
713 p_spcb->snd_count--;
714 }
715 else {
716 /*
717 * 送信すべき文字がない場合は,送信可能コールバックを禁止する.
718 */
719 sio_dis_cbr(p_spcb->p_siopcb, SIO_RDY_SND);
720 }
721}
722
723/*
724 * シリアルポートからの受信通知コールバック
725 */
726void
727sio_irdy_rcv(intptr_t exinf)
728{
729 SPCB *p_spcb;
730 char c;
731
732 p_spcb = (SPCB *) exinf;
733 c = (char) sio_rcv_chr(p_spcb->p_siopcb);
734 if ((p_spcb->ioctl & IOCTL_FCSND) != 0U && c == FC_STOP) {
735 /*
736 * 送信を一時停止する.送信中の文字はそのまま送信する.
737 */
738 p_spcb->snd_stopped = true;
739 }
740 else if (p_spcb->snd_stopped && (c == FC_START
741 || (p_spcb->ioctl & IOCTL_FCANY) != 0U)) {
742 /*
743 * 送信を再開する.
744 */
745 p_spcb->snd_stopped = false;
746 if (p_spcb->snd_count > 0U) {
747 c = p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr];
748 if (serial_snd_chr(p_spcb, c)) {
749 INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
750 if (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz) {
751 if (isig_sem(p_spcb->p_spinib->snd_semid) < 0) {
752 p_spcb->errorflag = true;
753 }
754 }
755 p_spcb->snd_count--;
756 }
757 }
758 }
759 else if ((p_spcb->ioctl & IOCTL_FCSND) != 0U && c == FC_START) {
760 /*
761 * 送信に対してフロー制御している場合,START は捨てる.
762 */
763 }
764 else if (p_spcb->rcv_count == p_spcb->p_spinib->rcv_bufsz) {
765 /*
766 * バッファフルの場合,受信した文字を捨てる.
767 */
768 }
769 else {
770 /*
771 * 受信した文字を受信バッファにå…
772¥ã‚Œã‚‹ï¼Ž
773 */
774 p_spcb->p_spinib->rcv_buffer[p_spcb->rcv_write_ptr] = c;
775 INC_PTR(p_spcb->rcv_write_ptr, p_spcb->p_spinib->rcv_bufsz);
776 if (p_spcb->rcv_count == 0U) {
777 if (isig_sem(p_spcb->p_spinib->rcv_semid) < 0) {
778 p_spcb->errorflag = true;
779 }
780 }
781 p_spcb->rcv_count++;
782
783 /*
784 * STOPを送信する.
785 */
786 if ((p_spcb->ioctl & IOCTL_FCRCV) != 0U && !(p_spcb->rcv_stopped)
787 && p_spcb->rcv_count
788 >= BUFCNT_STOP(p_spcb->p_spinib->rcv_bufsz)) {
789 if (!serial_snd_chr(p_spcb, FC_STOP)) {
790 p_spcb->rcv_fc_chr = FC_STOP;
791 }
792 p_spcb->rcv_stopped = true;
793 }
794 }
795}
796
797/*
798 * シリアルインタフェースドライバからの未送信文字の取出し
799 */
800bool_t
801serial_get_chr(ID portid, char *p_c)
802{
803 SPCB *p_spcb;
804
805 if (1 <= portid && portid <= TNUM_PORT) { /* ポート番号のチェック */
806 p_spcb = get_spcb(portid);
807 if (p_spcb->openflag) { /* オープン済みかのチェック */
808 if (p_spcb->snd_count > 0U) {
809 *p_c = p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr];
810 INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
811 p_spcb->snd_count--;
812 return(true);
813 }
814 }
815 }
816 return(false);
817}
Note: See TracBrowser for help on using the repository browser.