⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux_serial.c

📁 嵌入式系统开发 TOPPERS and JSP Kernel Release 1.3 TOPPERS = Toyohashi Open Platform for Embedded Real-Tim
💻 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: linux_serial.c,v 1.6 2002/04/08 05:30:13 hiro Exp $ */#define _LINX_SERIAL_#include <jsp_services.h>#include <signal.h>#include <termios.h>#include <fcntl.h>#include <errno.h>#undef __USE_MISC #include <unistd.h>#include <linux_sigio.h>#include "kernel_id.h"#include "sys_config.h"/* *  シリアルポ〖トの你レベル年盗 */typedef struct hardware_serial_port_descripter {	char   *path;		            /* UNIX 惧でのファイル叹 */	int	   fd;		                /* ファイルディスクリプタ */	struct termios	current_term;	/* 眉琐扩告攫鼠 */	struct termios	saved_term;    } HWPORT;#define NUM_PORT	1#define RAWPORT1	{ 0 }/* *  UNIX レベルのポ〖ト介袋步/シャットダウン借妄 * *  附哼の悸刘では·眉琐を蝗うケ〖スしか雇えていないˉ塑丸は·open し *  たのが眉琐かどうかで借妄を恃えるべきˉ */Inline voidhw_port_initialize(HWPORT *p){	if (p->path) {		p->fd = open(p->path, O_RDWR|O_NDELAY);	}	else {		p->fd = 0;			/* 筛洁掐叫蜗を蝗う */	}	fcntl(p->fd, F_SETOWN, getpid());	fcntl(p->fd, F_SETFL, FASYNC|FNDELAY);            tcgetattr(p->fd, &(p->saved_term));    	p->current_term = p->saved_term;    p->current_term.c_lflag &= ~(ECHO);    p->current_term.c_lflag &= ~(ICANON);    p->current_term.c_cc[VMIN] = 1;    p->current_term.c_cc[VTIME] = 0;        tcsetattr(p->fd, TCSAFLUSH, &(p->current_term));}Inline voidhw_port_terminate(HWPORT *p){    tcsetattr(p->fd, TCSAFLUSH, &(p->saved_term));	fcntl(p->fd, F_SETFL, 0);	if (p->path) {		close(p->fd);	}}/* *  シリアルインタフェ〖スドライバ脱の SIGIO 奶梦イベントブロック */static SIGIOEB	serial_sigioeb;/* *  シリアルポ〖ト瓷妄ブロックの年盗 */typedef struct ioctl_descripter {	int	echo;	int	input;	int	newline;	int	flowc;} IOCTL;#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 void	sigint_handler();static BOOL	serial_getc(SPCB *spcb, char *c);static BOOL	serial_putc(SPCB *spcb, char c);/* *  シリアルポ〖ト瓷妄ブロックの年盗と介袋步 */static SPCB spcb_table[NUM_PORT] = {    {0, RAWPORT1, SEM_SERIAL1_IN, SEM_SERIAL1_OUT }};#define get_spcb(portid)	(&(spcb_table[(portid)-1]))#define get_spcb_def(portid)	get_spcb((portid) ? (portid) : CONSOLE_PORTID)/* *  ポ〖トの介袋步 */intserial_open(ID portid){    SPCB	*spcb;	ER	ercd = E_OK;;	if (!(1 <= portid && portid <= NUM_PORT)) {		return(E_PAR);	}	spcb = get_spcb(portid);	/*	 *  剩眶のタスクが票箕に serial_open を钙ぶ觉斗には滦炳してい	 *  ないˉ	 */	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->ixon_stopped = spcb->ixoff_stopped = FALSE;	spcb->ixoff_send = 0;	/*	 *  ハ〖ドウェア巴赂の介袋步	 */	hw_port_initialize(&(spcb->hwport));        	/* 	 *  プロセスを姜位させるシグナルを梳まえる         *  sigaction()で今き木した数がいいのか?	 */	signal(SIGHUP, sigint_handler);	signal(SIGINT, sigint_handler);	signal(SIGTERM, sigint_handler);            spcb->init_flag = TRUE;	spcb->send_enabled = FALSE;	return(ercd);}/* *  ポ〖トのシャットダウン * *  flush が TRUE の眷圭は·シリアルポ〖トへの流慨バッファが鄂になるま *  で略つˉ */#define	MAX_FLUSH_LOOP	1000000intserial_close(ID portid, int flush){	SPCB	*spcb;	int	i;	if (!(1 <= portid && portid <= NUM_PORT)) {		return(E_PAR);		/* ポ〖ト戎规のチェック */	}	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);}/* *  プロセスを姜位させるシグナルに滦するハンドラ */voidsigint_handler(){	SPCB	*spcb;	int	i;	for (i = 1; i <= NUM_PORT; i++) {		spcb = get_spcb(i);		if (spcb->init_flag) {			hw_port_terminate(&(spcb->hwport));		}	}	exit(0);}/* *  フロ〖コントロ〖ル簇犯の年盗 */#define	STOP	'\023'		/* Control-S */#define	START	'\021'		/* Control-Q */#define	IXOFF_STOP	64	/* buffer area size to send STOP */#define	IXOFF_START	128	/* buffer area size to send START */#define	in_buf_area(p)							\		((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 BOOLread_char(SPCB *spcb, char *c){	int	n;	if ((n = read(spcb->hwport.fd, c, 1)) == 1) {		return(1);	}	assert(n < 0 && errno == EWOULDBLOCK);	return(0);}Inline BOOLwrite_char(SPCB *spcb, char c){	int	n;	if ((n = write(spcb->hwport.fd, &c, 1)) == 1) {		return(1);	}	assert(n < 0 && errno == EWOULDBLOCK);	return(0);}/* *  シリアルポ〖トからの减慨 */static BOOLserial_getc(SPCB *spcb, char *c){	BOOL	buffer_empty;	syscall(loc_cpu());	*c = spcb->in_buffer[spcb->in_read_ptr];        if (inc(spcb->in_write_ptr) == spcb->in_read_ptr) {            /*             *  バッファフル觉轮が豺近されたら、充り哈みが掐ったのと             *  票じ慷る神いをさせる。             */            kill(getpid(), SIGIO);        }        	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 (!write_char(spcb, START)) {			spcb->ixoff_send = START;		}		spcb->ixoff_stopped = FALSE;	}	buffer_empty = IN_BUFFER_EMPTY(spcb);	syscall(unl_cpu());	return(buffer_empty);}intserial_read(int portid, char *buf, unsigned int len){    	SPCB	*spcb;	BOOL	buffer_empty;	char	c;	int	i;	if (sns_dpn()) {		/* コンテキストのチェック */		return(E_CTX);	}	if (!(0 <= portid && portid <= NUM_PORT)) {		return(E_PAR);		/* ポ〖ト戎规のチェック */	}	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) && write_char(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, unsigned int len){	SPCB	*spcb;	BOOL	buffer_full;	int	i;	if (sns_dpn()) {		/* コンテキストのチェック */		return(E_CTX);	}	if (!(0 <= portid && portid <= NUM_PORT)) {		return(E_PAR);		/* ポ〖ト戎规のチェック */	}	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);}/* *  シリアルポ〖トの扩告 */intserial_ioctl(ID portid, UINT ioctl){	SPCB	*spcb;	if (sns_ctx()) {		/* コンテキストのチェック */		return(E_CTX);	}	if (!(0 <= portid && portid <= NUM_PORT)) {		return(E_PAR);		/* ポ〖ト戎规のチェック */	}	spcb = get_spcb_def(portid);	if (!(spcb->init_flag)) {	/* 介袋步貉かのチェック */		return(E_OBJ);	}    spcb->ioctl = ioctl;    return(E_OK);}/* *  シリアルポ〖ト充哈みハンドラ */static BOOLserial_int_handler(ID portid){	SPCB	*spcb;	BOOL	flag;	char	c;	spcb = get_spcb(portid);	flag = 0;	/*	 *  1矢机减慨借妄	 *	 *  まず·バッファフルでない眷圭に·1矢机粕んでみるˉ粕めれば·	 *  それに炳じた借妄を乖うˉ	 */	if (inc(spcb->in_write_ptr) != spcb->in_read_ptr            && read_char(spcb, &c)) {		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;		}		else {			spcb->in_buffer[spcb->in_write_ptr] = c;                        if(spcb->in_read_ptr == spcb->in_write_ptr){                            syscall(sig_sem(spcb->in_semid));                        }                        			INC(spcb->in_write_ptr);                        			if ((spcb->ioctl & IOCTL_IXOFF) != 0 && !(spcb->ixoff_stopped)					&& (in_buf_area(p) < IXOFF_STOP)) {				spcb->ixoff_stopped = TRUE;				spcb->ixoff_send = STOP;			}		}		flag = 1;	}	/*	 *  1矢机流慨借妄	 */	if (spcb->ixoff_send) {		if (write_char(spcb, spcb->ixoff_send)) {			spcb->ixoff_send = 0;			flag = 1;		}	}	else if (!(spcb->ixon_stopped)                      && spcb->out_read_ptr != spcb->out_write_ptr) {		if (write_char(spcb, spcb->out_buffer[spcb->out_read_ptr])) {                    if(OUT_BUFFER_FULL(spcb)){			syscall(isig_sem(spcb->out_semid));                    }                    INC(spcb->out_read_ptr);                                            flag = 1;		}	}	return(flag);}/* *  SIGIO コ〖ルバックル〖チン */static BOOLserial_sigio_callback(VP arg){	BOOL	flag;	do {		syscall(loc_cpu());		flag = serial_int_handler(1);		syscall(unl_cpu());	} while (flag);	return(0);}/* *  シリアルインタフェ〖スドライバの弹瓢 */voidserial_initialize(VP_INT portid){	syscall(serial_open((ID) portid));	serial_sigioeb.callback = serial_sigio_callback;	serial_sigioeb.arg = (VP) 0;	syscall(enqueue_sigioeb_initialize(&serial_sigioeb));	syslog_1(LOG_NOTICE, "Serial driver service starts on port %d.\r",		 portid);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -