📄 serial.c
字号:
/* * TOPPERS/JSP Kernel * Toyohashi Open Platform for Embedded Real-Time Systems/ * Just Standard Profile Kernel * * Copyright (C) 2000,2001 by Embedded and Real-Time Systems Laboratory * Toyohashi Univ. of Technology, JAPAN * * 惧淡螟侯涪荚は·Free Software Foundation によって给山されている * GNU General Public License の Version 2 に淡揭されている掘凤か·笆 * 布の(1)×(4)の掘凤を塔たす眷圭に嘎り·塑ソフトウェア∈塑ソフトウェ * アを猖恃したものを崔むˉ笆布票じ∷を蝗脱ˇ剩澜ˇ猖恃ˇ浩芹邵∈笆布· * 网脱と钙ぶ∷することを痰浸で钓满するˉ * (1) 塑ソフトウェアをソ〖スコ〖ドの妨で网脱する眷圭には·惧淡の螟侯 * 涪山绩·この网脱掘凤および布淡の痰瘦沮惮年が·そのままの妨でソ〖 * スコ〖ド面に崔まれていることˉ * (2) 塑ソフトウェアを浩网脱材墙なバイナリコ〖ド∈リロケ〖タブルオブ * ジェクトファイルやライブラリなど∷の妨で网脱する眷圭には·网脱 * に燃うドキュメント∈网脱荚マニュアルなど∷に·惧淡の螟侯涪山绩· * この网脱掘凤および布淡の痰瘦沮惮年を非很することˉ * (3) 塑ソフトウェアを浩网脱稍材墙なバイナリコ〖ドの妨または怠达に寥 * み哈んだ妨で网脱する眷圭には·肌のいずれかの掘凤を塔たすことˉ * (a) 网脱に燃うドキュメント∈网脱荚マニュアルなど∷に·惧淡の螟侯 * 涪山绩·この网脱掘凤および布淡の痰瘦沮惮年を非很することˉ * (b) 网脱の妨轮を·侍に年める数恕によって·惧淡螟侯涪荚に鼠桂する * ことˉ * (4) 塑ソフトウェアの网脱により木儡弄または粗儡弄に栏じるいかなる禄 * 巢からも·惧淡螟侯涪荚を倘勒することˉ * * 塑ソフトウェアは·痰瘦沮で捏丁されているものであるˉ惧淡螟侯涪荚は· * 塑ソフトウェアに簇して·その努脱材墙拉も崔めて·いかなる瘦沮も乖わ * ないˉまた·塑ソフトウェアの网脱により木儡弄または粗儡弄に栏じたい * かなる禄巢に簇しても·その勒扦を砷わないˉ * * @(#) $Id: serial.c,v 1.8 2002/04/08 05:30:13 hiro Exp $ *//* * シリアルインタフェ〖スドライバ */#include <jsp_services.h>#include "kernel_id.h"/* * シリアルインタフェ〖スドライバの弹瓢 */static BOOL in_inirtn = FALSE; /* 介袋步ル〖チン悸乖面を绩す */voidserial_initialize(VP_INT portid){ in_inirtn = TRUE; syscall(serial_open((ID) portid)); in_inirtn = FALSE; syslog_1(LOG_NOTICE, "Serial driver service starts on port %d.", portid);}/* * シリアルポ〖ト瓷妄ブロックの年盗 */#define SERIAL_BUFSZ 256 /* シリアルインタフェ〖ス脱バッファのサイズ */#define inc(x) (((x)+1 < SERIAL_BUFSZ) ? (x)+1 : 0)#define INC(x) ((x) = inc(x))typedef struct serial_port_control_block { BOOL init_flag; /* 介袋步貉か々 */ HWPORT hwport; /* ハ〖ドウェア巴赂攫鼠 */ ID in_semid; /* 减慨バッファ瓷妄脱セマフォの ID */ ID out_semid; /* 流慨バッファ瓷妄脱セマフォの ID */ int in_read_ptr; /* 减慨バッファ粕み叫しポインタ */ int in_write_ptr; /* 减慨バッファ今き哈みポインタ */ int out_read_ptr; /* 流慨バッファ粕み叫しポインタ */ int out_write_ptr; /* 流慨バッファ今き哈みポインタ */ UINT ioctl; /* ioctl による肋年柒推 */ BOOL send_enabled; /* 流慨をイネ〖ブルしてあるか々 */ BOOL ixon_stopped; /* STOP を减け艰った觉轮か々 */ BOOL ixoff_stopped; /* 陵缄に STOP を流った觉轮か々 */ char ixoff_send; /* 陵缄に START/STOP を流るか々 */ char in_buffer[SERIAL_BUFSZ]; /* 减慨バッファエリア */ char out_buffer[SERIAL_BUFSZ]; /* 减慨バッファエリア */} SPCB;#define IN_BUFFER_EMPTY(spcb) \ ((spcb)->in_read_ptr == (spcb)->in_write_ptr)#define IN_BUFFER_FULL(spcb) \ ((spcb)->in_read_ptr == inc((spcb)->in_write_ptr))#define OUT_BUFFER_FULL(spcb) \ ((spcb)->out_read_ptr == inc((spcb)->out_write_ptr))/* * モジュ〖ル柒で蝗う簇眶 */static BOOL serial_getc(SPCB *spcb, char *c);static BOOL serial_putc(SPCB *spcb, char c);/* * シリアルポ〖ト瓷妄ブロックの年盗と介袋步 */static SPCB spcb_table[NUM_PORT] = { { 0, HWPORT1, SEM_SERIAL1_IN, SEM_SERIAL1_OUT },#if NUM_PORT > 1 { 0, HWPORT2, SEM_SERIAL2_IN, SEM_SERIAL2_OUT },#endif};#define get_spcb(portid) (&(spcb_table[(portid)-1]))#define get_spcb_def(portid) get_spcb((portid) ? (portid) : CONSOLE_PORTID)/* * ポ〖トのオ〖プン * * 剩眶のタスクが票箕に钙ぶ觉斗には滦炳していないˉ */ERserial_open(ID portid){ SPCB *spcb; ER ercd; if (!(1 <= portid && portid <= NUM_PORT)) { return(E_ID); } spcb = get_spcb(portid); if (spcb->init_flag) { /* 介袋步貉かのチェック */ return(E_OK); } /* * 恃眶の介袋步 */ spcb->in_read_ptr = spcb->in_write_ptr = 0; spcb->out_read_ptr = spcb->out_write_ptr = 0; spcb->ioctl = (IOCTL_ECHO | IOCTL_CRLF | IOCTL_CANONICAL | IOCTL_IXON | IOCTL_IXOFF); spcb->send_enabled = FALSE; spcb->ixon_stopped = spcb->ixoff_stopped = FALSE; spcb->ixoff_send = 0; /* * ハ〖ドウェア巴赂の介袋步 */ if (!in_inirtn) { syscall(loc_cpu()); } if (hw_port_initialize(&(spcb->hwport))) { ercd = E_SYS; } else { spcb->init_flag = TRUE; ercd = E_OK; } if (!in_inirtn) { syscall(unl_cpu()); } return(ercd);}/* * ポ〖トのクロ〖ズ * * flush が TRUE の眷圭は·シリアルポ〖トへの流慨バッファが鄂になるま * で略つˉ * 剩眶のタスクが票箕に钙ぶ觉斗には滦炳していないˉ */#define MAX_FLUSH_LOOP 1000000ERserial_close(ID portid, BOOL flush){ SPCB *spcb; int i; if (!(1 <= portid && portid <= NUM_PORT)) { return(E_ID); /* ポ〖ト戎规のチェック */ } spcb = get_spcb(portid); if (!(spcb->init_flag)) { /* 介袋步貉かのチェック */ return(E_OBJ); } /* * バッファのフラッシュ借妄 */ if (flush) { for (i = 0; i < MAX_FLUSH_LOOP; i++) { if (spcb->out_write_ptr == spcb->out_read_ptr) { break; } } } /* * ハ〖ドウェア巴赂のシャットダウン借妄 */ syscall(loc_cpu()); hw_port_terminate(&(spcb->hwport)); syscall(unl_cpu()); spcb->init_flag = FALSE; return(E_OK);}/* * フロ〖コントロ〖ル簇犯の年盗 */#define STOP '\023' /* コントロ〖ル-S */#define START '\021' /* コントロ〖ル-Q */#define IXOFF_STOP 64 /* STOPを流る荒りバッファエリア */#define IXOFF_START 128 /* STARTを流る荒りバッファエリア */#define in_buf_area(spcb) \ ((spcb->in_read_ptr >= spcb->in_write_ptr) ? \ (spcb->in_read_ptr - spcb->in_write_ptr) : \ (spcb->in_read_ptr + SERIAL_BUFSZ - spcb->in_write_ptr))/* * ユ〖ティリティル〖チン */Inline BOOLenable_send(SPCB *spcb, char c){ if (!(spcb->send_enabled)) { hw_port_sendstart(&(spcb->hwport)); spcb->send_enabled = TRUE; if (hw_port_putready(&(spcb->hwport))) { hw_port_putchar(&(spcb->hwport), c); return(TRUE); } } return(FALSE);}/* * シリアルポ〖トからの减慨 */static BOOLserial_getc(SPCB *spcb, char *c){ BOOL buffer_empty; syscall(loc_cpu()); *c = spcb->in_buffer[spcb->in_read_ptr]; INC(spcb->in_read_ptr); if (*c == '\r' && (spcb->ioctl & IOCTL_RAW) == 0) { *c = '\n'; } if (spcb->ixoff_stopped && (in_buf_area(spcb) > IXOFF_START)) { if (!enable_send(spcb, START)) { spcb->ixoff_send = START; } spcb->ixoff_stopped = FALSE; } buffer_empty = IN_BUFFER_EMPTY(spcb); syscall(unl_cpu()); return(buffer_empty);}ER_UINTserial_read(ID portid, char *buf, UINT len){ SPCB *spcb; BOOL buffer_empty; char c; unsigned int i; if (sns_dpn()) { /* コンテキストのチェック */ return(E_CTX); } if (!(0 <= portid && portid <= NUM_PORT)) { return(E_ID); /* ポ〖ト戎规のチェック */ } spcb = get_spcb_def(portid); if (!(spcb->init_flag)) { /* 介袋步貉かのチェック */ return(E_OBJ); } if (len == 0) { return(len); } syscall(wai_sem(spcb->in_semid)); buffer_empty = FALSE; for (i = 0; i < len; i++) { buffer_empty = serial_getc(spcb, &c); if ((spcb->ioctl & IOCTL_ECHO) != 0) { syscall(wai_sem(spcb->out_semid)); if (!serial_putc(spcb, c)) { syscall(sig_sem(spcb->out_semid)); } } *buf++ = c; if ((spcb->ioctl & IOCTL_RAW) != 0 || ((spcb->ioctl & IOCTL_CANONICAL) != 0 && c == '\n')) { len = i + 1; break; } if (buffer_empty && i < len - 1) { syscall(wai_sem(spcb->in_semid)); } } if (!buffer_empty) { syscall(sig_sem(spcb->in_semid)); } return(len);}/* * シリアルポ〖トへの流慨 */static BOOLserial_putc(SPCB *spcb, char c){ BOOL buffer_full; if (c == '\n' && (spcb->ioctl & IOCTL_CRLF) != 0) { if (serial_putc(spcb, '\r')) { syscall(wai_sem(spcb->out_semid)); } } syscall(loc_cpu()); if (!(spcb->ixon_stopped) && enable_send(spcb, c)) { buffer_full = FALSE; } else { spcb->out_buffer[spcb->out_write_ptr] = c; INC(spcb->out_write_ptr); buffer_full = OUT_BUFFER_FULL(spcb); } syscall(unl_cpu()); return(buffer_full);}ER_UINTserial_write(ID portid, char *buf, UINT len){ SPCB *spcb; BOOL buffer_full; unsigned int i; if (sns_dpn()) { /* コンテキストのチェック */ return(E_CTX); } if (!(0 <= portid && portid <= NUM_PORT)) { return(E_ID); /* ポ〖ト戎规のチェック */ } spcb = get_spcb_def(portid); if (!(spcb->init_flag)) { /* 介袋步貉かのチェック */ return(E_OBJ); } syscall(wai_sem(spcb->out_semid)); buffer_full = FALSE; for (i = 0; i < len; i++) { buffer_full = serial_putc(spcb, *buf++); if (buffer_full && i < len - 1) { syscall(wai_sem(spcb->out_semid)); } } if (!buffer_full) { syscall(sig_sem(spcb->out_semid)); } return(len);}/* * シリアルポ〖トの扩告 */ERserial_ioctl(ID portid, UINT ioctl){ SPCB *spcb; if (sns_ctx()) { /* コンテキストのチェック */ return(E_CTX); } if (!(0 <= portid && portid <= NUM_PORT)) { return(E_ID); /* ポ〖ト戎规のチェック */ } spcb = get_spcb_def(portid); if (!(spcb->init_flag)) { /* 介袋步貉かのチェック */ return(E_OBJ); } spcb->ioctl = ioctl; return(E_OK);}/* * シリアルポ〖ト充哈みサ〖ビスル〖チン */voidserial_handler_in(ID portid){ SPCB *spcb; char c; spcb = get_spcb(portid); if (hw_port_getready(&(spcb->hwport))) { c = hw_port_getchar(&(spcb->hwport)); if ((spcb->ioctl & IOCTL_IXON) != 0 && c == STOP) { spcb->ixon_stopped = TRUE; } else if (((spcb->ioctl & IOCTL_IXON) != 0 || spcb->ixon_stopped) && (c == START || (spcb->ioctl & IOCTL_IXANY) != 0)) { spcb->ixon_stopped = FALSE; if (!(spcb->send_enabled)) { hw_port_sendstart(&(spcb->hwport)); spcb->send_enabled = TRUE; } } else if (IN_BUFFER_FULL(spcb)) { /* バッファフルの眷圭·减慨した矢机を嘉てるˉ*/ } else { spcb->in_buffer[spcb->in_write_ptr] = c; if (spcb->in_read_ptr == spcb->in_write_ptr) { syscall(isig_sem(spcb->in_semid)); } INC(spcb->in_write_ptr); if ((spcb->ioctl & IOCTL_IXOFF) != 0 && !(spcb->ixoff_stopped) && (in_buf_area(spcb) < IXOFF_STOP)) { if (!enable_send(spcb, STOP)) { spcb->ixoff_send = STOP; } spcb->ixoff_stopped = TRUE; } } }}voidserial_handler_out(ID portid){ SPCB *spcb; spcb = get_spcb(portid); if (hw_port_putready(&(spcb->hwport))) { if (!spcb->send_enabled) { hw_port_sendstop(&(spcb->hwport)); } else if (spcb->ixoff_send) { hw_port_putchar(&(spcb->hwport), spcb->ixoff_send); spcb->ixoff_send = 0; } else if (spcb->ixon_stopped || spcb->out_read_ptr == spcb->out_write_ptr) { /* 流慨匿贿 */ hw_port_sendstop(&(spcb->hwport)); spcb->send_enabled = FALSE; } else { hw_port_putchar(&(spcb->hwport), spcb->out_buffer[spcb->out_read_ptr]); if (OUT_BUFFER_FULL(spcb)) { syscall(isig_sem(spcb->out_semid)); } INC(spcb->out_read_ptr); } }}/* * 充哈みハンドラ */#ifdef SEPARATE_SIO_INTvoidserial_in_handler(void){ hw_serial_handler_in();}voidserial_out_handler(void){ hw_serial_handler_out();}#else /* SEPARATE_SIO_INT */voidserial_handler(void){ hw_serial_handler();}#endif /* SEPARATE_SIO_INT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -