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

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • 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.1 KB
RevLine 
[388]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 388 2019-05-22 11:25:18Z 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, TMO tmout)
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 rercd = cReceiveSemaphore_waitTimeout(tmout);
450 if (rercd == E_TMOUT)
451 return E_TMOUT;
452 if (rercd < 0) {
453 gen_ercd_wait(rercd, p_cellcb);
454 ercd = rercd;
455 goto error_exit;
456 }
457 }
458 SVC(rercd = serialPort_readChar(p_cellcb, &c), rercd);
459 *buffer++ = c;
460 reacnt++;
461 buffer_empty = (bool_t) rercd;
462
463 /*
464 * エコーバック処理.
465 */
466 if ((VAR_ioControl & IOCTL_ECHO) != 0U) {
467 SVC(rercd = cSendSemaphore_wait(),
468 gen_ercd_wait(rercd, p_cellcb));
469 SVC(rercd = serialPort_writeChar(p_cellcb, c), rercd);
470 if (!((bool_t) rercd)) {
471 SVC(cSendSemaphore_signal(), gen_ercd_sys(p_cellcb));
472 }
473 }
474 }
475 if (!buffer_empty) {
476 SVC(cReceiveSemaphore_signal(), gen_ercd_sys(p_cellcb));
477 }
478 ercd = E_OK;
479
480 error_exit:
481 return(reacnt > 0U ? (ER_UINT) reacnt : ercd);
482}
483
484/*
485 * シリアルポートの制御(受け口関数)
486 */
487ER
488eSerialPort_control(CELLIDX idx, uint_t ioctl)
489{
490 CELLCB *p_cellcb;
491
492 if (sns_dpn()) { /* コンテキストのチェック */
493 return(E_CTX);
494 }
495 if (!VALID_IDX(idx)) {
496 return(E_ID); /* ポート番号のチェック */
497 }
498
499 p_cellcb = GET_CELLCB(idx);
500 if (!VAR_openFlag) { /* オープン済みかのチェック */
501 return(E_OBJ);
502 }
503 if (VAR_errorFlag) { /* エラー状æ…
504‹ã‹ã®ãƒã‚§ãƒƒã‚¯ */
505 return(E_SYS);
506 }
507
508 VAR_ioControl = ioctl;
509 return(E_OK);
510}
511
512/*
513 * シリアルポート状æ…
514‹ã®å‚ç…
515§ï¼ˆå—け口関数)
516 */
517ER
518eSerialPort_refer(CELLIDX idx, T_SERIAL_RPOR* pk_rpor)
519{
520 CELLCB *p_cellcb;
521
522 if (sns_dpn()) { /* コンテキストのチェック */
523 return(E_CTX);
524 }
525 if (!VALID_IDX(idx)) {
526 return(E_ID); /* ポート番号のチェック */
527 }
528
529 p_cellcb = GET_CELLCB(idx);
530 if (!VAR_openFlag) { /* オープン済みかのチェック */
531 return(E_OBJ);
532 }
533 if (VAR_errorFlag) { /* エラー状æ…
534‹ã‹ã®ãƒã‚§ãƒƒã‚¯ */
535 return(E_SYS);
536 }
537
538 pk_rpor->reacnt = VAR_receiveCount;
539 pk_rpor->wricnt = VAR_sendCount;
540 return(E_OK);
541}
542
543/*
544 * シリアルポートからの送信可能コールバック(受け口関数)
545 */
546void
547eiSIOCBR_readySend(CELLIDX idx)
548{
549 CELLCB *p_cellcb;
550
551 assert(VALID_IDX(idx));
552 p_cellcb = GET_CELLCB(idx);
553 if (VAR_receiveFlowControl != '\0') {
554 /*
555 * START/STOP を送信する.
556 */
557 (void) cSIOPort_putChar(VAR_receiveFlowControl);
558 VAR_receiveFlowControl = '\0';
559 }
560 else if (!VAR_sendStopped && VAR_sendCount > 0U) {
561 /*
562 * 送信バッファ中から文字を取り出して送信する.
563 */
564 (void) cSIOPort_putChar(VAR_sendBuffer[VAR_sendReadPointer]);
565 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
566 if (VAR_sendCount == ATTR_sendBufferSize) {
567 if (ciSendSemaphore_signal() < 0) {
568 VAR_errorFlag = true;
569 }
570 }
571 VAR_sendCount--;
572 }
573 else {
574 /*
575 * 送信すべき文字がない場合は,送信可能コールバックを禁止する.
576 */
577 cSIOPort_disableCBR(SIOSendReady);
578 }
579}
580
581/*
582 * シリアルポートからの受信通知コールバック(受け口関数)
583 */
584void
585eiSIOCBR_readyReceive(CELLIDX idx)
586{
587 CELLCB *p_cellcb;
588 char c;
589
590 assert(VALID_IDX(idx));
591 p_cellcb = GET_CELLCB(idx);
592 c = (char) cSIOPort_getChar();
593 if ((VAR_ioControl & IOCTL_FCSND) != 0U && c == FC_STOP) {
594 /*
595 * 送信を一時停止する.送信中の文字はそのまま送信する.
596 */
597 VAR_sendStopped = true;
598 }
599 else if (VAR_sendStopped && (c == FC_START
600 || (VAR_ioControl & IOCTL_FCANY) != 0U)) {
601 /*
602 * 送信を再開する.
603 */
604 VAR_sendStopped = false;
605 if (VAR_sendCount > 0U) {
606 c = VAR_sendBuffer[VAR_sendReadPointer];
607 if (serialPort_sendChar(p_cellcb, c)) {
608 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
609 if (VAR_sendCount == ATTR_sendBufferSize) {
610 if (ciSendSemaphore_signal() < 0) {
611 VAR_errorFlag = true;
612 }
613 }
614 VAR_sendCount--;
615 }
616 }
617 }
618 else if ((VAR_ioControl & IOCTL_FCSND) != 0U && c == FC_START) {
619 /*
620 * 送信に対してフロー制御している場合,START は捨てる.
621 */
622 }
623 else if (VAR_receiveCount == ATTR_receiveBufferSize) {
624 /*
625 * バッファフルの場合,受信した文字を捨てる.
626 */
627 }
628 else {
629 /*
630 * 受信した文字を受信バッファにå…
631¥ã‚Œã‚‹ï¼Ž
632 */
633 VAR_receiveBuffer[VAR_receiveWritePointer] = c;
634 INC_PTR(VAR_receiveWritePointer, ATTR_receiveBufferSize);
635 if (VAR_receiveCount == 0U) {
636 if (ciReceiveSemaphore_signal() < 0) {
637 VAR_errorFlag = true;
638 }
639 }
640 VAR_receiveCount++;
641
642 /*
643 * STOPを送信する.
644 */
645 if ((VAR_ioControl & IOCTL_FCRCV) != 0U && !VAR_receiveStopped
646 && VAR_receiveCount >= BUFCNT_STOP(ATTR_receiveBufferSize)) {
647 if (!serialPort_sendChar(p_cellcb, FC_STOP)) {
648 VAR_receiveFlowControl = FC_STOP;
649 }
650 VAR_receiveStopped = true;
651 }
652 }
653}
654
655/*
656 * シリアルインタフェースドライバからの未送信文字の取出し
657 */
658bool_t
659enSerialPortManage_getChar(CELLIDX idx, char *p_c)
660{
661 CELLCB *p_cellcb;
662
663 if (VALID_IDX(idx)) { /* ポート番号のチェック */
664 p_cellcb = GET_CELLCB(idx);
665 if (VAR_openFlag) { /* オープン済みかのチェック */
666 if (VAR_sendCount > 0U) {
667 *p_c = VAR_sendBuffer[VAR_sendReadPointer];
668 INC_PTR(VAR_sendReadPointer, ATTR_sendBufferSize);
669 VAR_sendCount--;
670 return(true);
671 }
672 }
673 }
674 return(false);
675}
Note: See TracBrowser for help on using the repository browser.