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

📄 st16c554.c

📁 嵌入系统POWERPC+LINUX下ST16C554多串口驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * st16c554.c * * TWO ST16C554 driver for AMCC PPC405EP * * Author: Li Zhi You/Zhu jiang <godiscrazy@163.com> * Date  : $Date: 2007/11/27 11:07:04 $ * * $Revision: 1.1V $ *ST16C554APN7.3728mhz扩展芯片:2*ST16C554可为系统增加8个串口,直接与PPC405EP总线连接,8位数据宽度地址空间:占用系统PC3地址从前到后分别对应每个UART0-7个寄存器UART0A:0xf0200020---0xf020027						A2A1A0(ST16C554)		0xf0200020     0 0 0		0xf0200021     0 0 1		0xf0200022     0 1 0		0xf0200023     0 1 1		0xf0200024     1 0 0		0xf0200025     1 0 1		0xf0200026     1 1 0		0xf0200027     1 1 1UART0B:0xf0200028---0xf020002fUART0C:0xf0200030---0xf0200037UART0D:0xf0200038---0xf020003fUART0E:0xf0200040---0xf020047						A2A1A0(ST16C554)		0xf0200040     0 0 0		0xf0200041     0 0 1		0xf0200042     0 1 0		0xf0200043     0 1 1		0xf0200044     1 0 0		0xf0200045     1 0 1		0xf0200046     1 1 0		0xf0200047     1 1 1UART0F:0xf0200048---0xf020004fUART0G:0xf0200050---0xf0200057UART0H:0xf0200058---0xf020005f控制寄存器Line-control register(LCR)0x03FIFO-control register(FCR)0x02Modem-control register(MCR)0x04Divisor-latch LSB(DLL)LCR(bit7=1)0x00Divisor-latch MSB(DLM)LCR(bit7=1)0x01Interrupt enable register(IER)0x01状态寄存器Line-status register(LSR)0x05Modem-status register(MSR)0x06数据寄存器Receiver-buffer register(RBR)0x00Transmitter-holding register(THR)0x00 */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <asm/processor.h>#include <platforms/ibm405ep.h>#include <platforms/ibm405lp.h>#include <linux/devfs_fs_kernel.h>#include <asm/io.h>#define ST0_A_READ	0#define ST0_B_READ	1#define ST0_C_READ	2#define ST0_D_READ	3#define ST1_A_READ	4#define ST1_B_READ	5#define ST1_C_READ	6#define ST1_D_READ	7#define ST0_A_WRITE	8#define ST0_B_WRITE	9#define ST0_C_WRITE	10#define ST0_D_WRITE	11#define ST1_A_WRITE	12#define ST1_B_WRITE	13#define ST1_C_WRITE	14#define ST1_D_WRITE	15#define ST_INIT	32typedef struct tagST_INIT{	int nChn;	int nBaud;	unsigned char byMode;} myST_INIT;myST_INIT st0A_init;myST_INIT st0B_init;myST_INIT st0C_init;myST_INIT st0D_init;myST_INIT st0E_init;myST_INIT st0F_init;myST_INIT st0G_init;myST_INIT st0H_init;#define NONEPARITY	0x00#define ODDPARITY	0x08#define EVENPARITY	0x18#define DATA7BIT	0x80#define BAUDBASE	0x30					/***4800bps->hex***/#define ST_COM_CNT	8#define ST_RECV_LEN	1600#define ST_SEND_LEN	160//以下定义与系统地址相关(与CPLD有关系)/*   68 mode interface          HOW TO Select CHannel       CS    A4     A3      CHANNEL       1      0/1   0/1       None       0       0      0           A       0       0      1           B       0       1      0           C      0       1      1           D          Internal Register is Decoded by A2 A1 A0;    具体定义见程序开头的宏定义            两片ST16C554都接在405EP的PCS3上,    用A6和A5来区分ST16C554   */    /*这里采用D、C、B、A及H、G、F、E的方式编号主要是为了满足板子   上串口定死的从左到右1——8顺序,并没有其它特殊含义*/#define  YC_PHY_BASE_ADRR           0xf0200000      //映射基地址空间#define  UcsAnd                     0xffffff07      // addr(7)='0',addr(6)='0',addr(5)='0',addr(4)='0',addr(3)='0'#define  Ucs_DChannel_Or            0x20            // addr(7)='0',addr(6)='0',addr(5)='1',addr(4)='0',addr(3)='0'#define  Ucs_CChannel_Or            0x28            // addr(7)='0',addr(6)='0',addr(5)='1',addr(4)='0',addr(3)='1'#define  Ucs_BChannel_Or            0x30            // addr(7)='0',addr(6)='0',addr(5)='1',addr(4)='1',addr(3)='0'#define  Ucs_AChannel_Or            0x38            // addr(7)='0',addr(6)='0',addr(5)='1',addr(4)='1',addr(3)='1'#define  Ucs_HChannel_Or            0x40            // addr(7)='0',addr(6)='1',addr(5)='0',addr(4)='0',addr(3)='0'#define  Ucs_GChannel_Or            0x48            // addr(7)='0',addr(6)='1',addr(5)='0',addr(4)='0',addr(3)='1'#define  Ucs_FChannel_Or            0x50            // addr(7)='0',addr(6)='1',addr(5)='0',addr(4)='1',addr(3)='0'#define  Ucs_EChannel_Or            0x58            // addr(7)='0',addr(6)='1',addr(5)='0',addr(4)='1',addr(3)='1'#define  YC_mul232_IRQ0   26  //中断号 IRQ1#define  YC_mul232_IRQ1   30  //中断号 IRQ5#define delay_counter 100000  //用于写函数,写入一个字符寄存器先延时,然后再写下一个字符typedef struct {	int nAddress0;	int nAddress1;	int sInited;	unsigned char *pbyBase0;		//数据寄存器	int RBR;//Receiver-buffer register				0	int THR;//Transmitter-holding register			0		//状态寄存器	int LSR;//Line-status register					5	int MSR;//Modem-status register					6		//控制寄存器	int LCR;//Line-control register					3	int FCR;//FIFO-control register					2	int MCR;//Modem-control register				4	int DLL;//Divisor-latch LSB						0	int DLM;//Divisor-latch MSB						1	int IER;//Interrupt enable register				1		//其它寄存器	int SPR;//Scratchpad register					7	int IIR;//Interrupt identification register		2		//串口数据接收缓冲区	volatile short sRecvHead;	volatile short sRecvTail;	volatile unsigned char abyRecvData[ST_RECV_LEN];		//串口数据发送缓冲区	volatile short sSendHead;	volatile short sSendTail;	volatile unsigned char abySendData[ST_SEND_LEN];	} ST_COM;static ST_COM st0A = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_AChannel_Or), 0};static ST_COM st0B = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_BChannel_Or), 0};static ST_COM st0C = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_CChannel_Or), 0};static ST_COM st0D = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_DChannel_Or), 0};static ST_COM st0E = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_EChannel_Or), 0};static ST_COM st0F = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_FChannel_Or), 0};static ST_COM st0G = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_GChannel_Or), 0};static ST_COM st0H = { ( (YC_PHY_BASE_ADRR& UcsAnd) | Ucs_HChannel_Or), 0};#define DEVICE_NAME	"ST16C554"#define DEVICE_MAJOR 233#define ST0A	0#define ST0B	1#define ST0C	2#define ST0D	3#define ST0E	4#define ST0F	5#define ST0G	6#define ST0H	7static int stMajor = 233;inline int get_ST0A_rxLen(void){	if(st0A.sRecvHead==st0A.sRecvTail){		return 0;	}	else if(st0A.sRecvTail>st0A.sRecvHead){		return (st0A.sRecvTail-st0A.sRecvHead);	}	else{		return ( ST_RECV_LEN-(st0A.sRecvHead-st0A.sRecvTail) );	}}inline int get_ST0B_rxLen(void){	if(st0B.sRecvHead==st0B.sRecvTail){		return 0;	}	else if(st0B.sRecvTail>st0B.sRecvHead){		return (st0B.sRecvTail-st0B.sRecvHead);	}	else{		return ( ST_RECV_LEN-(st0B.sRecvHead-st0B.sRecvTail) );	}}inline int get_ST0C_rxLen(void){	if(st0C.sRecvHead==st0C.sRecvTail){		return 0;	}	else if(st0C.sRecvTail>st0C.sRecvHead){		return (st0C.sRecvTail-st0C.sRecvHead);	}	else{		return ( ST_RECV_LEN-(st0C.sRecvHead-st0C.sRecvTail) );	}}inline int get_ST0D_rxLen(void){	if(st0D.sRecvHead==st0D.sRecvTail){		return 0;	}	else if(st0D.sRecvTail>st0D.sRecvHead){		return (st0D.sRecvTail-st0D.sRecvHead);	}	else{		return ( ST_RECV_LEN-(st0D.sRecvHead-st0D.sRecvTail) );	}}inline int get_ST0E_rxLen(void){	if(st0E.sRecvHead==st0E.sRecvTail){		return 0;	}	else if(st0E.sRecvTail>st0E.sRecvHead){		return (st0E.sRecvTail-st0E.sRecvHead);	}	else{		return ( ST_RECV_LEN-(st0E.sRecvHead-st0E.sRecvTail) );	}}inline int get_ST0F_rxLen(void){	if(st0F.sRecvHead==st0F.sRecvTail){		return 0;	}	else if(st0F.sRecvTail>st0F.sRecvHead){		return (st0F.sRecvTail-st0F.sRecvHead);	}	else{		return ( ST_RECV_LEN-(st0F.sRecvHead-st0F.sRecvTail) );	}}inline int get_ST0G_rxLen(void){	if(st0G.sRecvHead==st0G.sRecvTail){		return 0;	}	else if(st0G.sRecvTail>st0G.sRecvHead){		return (st0G.sRecvTail-st0G.sRecvHead);	}	else{		return ( ST_RECV_LEN-(st0G.sRecvHead-st0G.sRecvTail) );	}}inline int get_ST0H_rxLen(void){	if(st0H.sRecvHead==st0H.sRecvTail){		return 0;	}	else if(st0H.sRecvTail>st0H.sRecvHead){		return (st0H.sRecvTail-st0H.sRecvHead);	}	else{		return ( ST_RECV_LEN-(st0H.sRecvHead-st0H.sRecvTail) );	}}inline int get_ST0A_txLen(void){	if(st0A.sSendHead==st0A.sSendTail){		return 0;	}	else if(st0A.sSendTail>st0A.sSendHead){		return (st0A.sSendTail-st0A.sSendHead);	}	else{		return ( ST_SEND_LEN-(st0A.sSendHead-st0A.sSendTail) );	}}inline int get_ST0B_txLen(void){	if(st0B.sSendHead==st0B.sSendTail){		return 0;	}	else if(st0B.sSendTail>st0B.sSendHead){		return (st0B.sSendTail-st0B.sSendHead);	}	else{		return ( ST_SEND_LEN-(st0B.sSendHead-st0B.sSendTail) );	}}inline int get_ST0C_txLen(void){	if(st0C.sSendHead==st0C.sSendTail){		return 0;	}	else if(st0C.sSendTail>st0C.sSendHead){		return (st0C.sSendTail-st0C.sSendHead);	}	else{		return ( ST_SEND_LEN-(st0C.sSendHead-st0C.sSendTail) );	}}inline int get_ST0D_txLen(void){	if(st0D.sSendHead==st0D.sSendTail){		return 0;	}	else if(st0D.sSendTail>st0D.sSendHead){		return (st0D.sSendTail-st0D.sSendHead);	}	else{		return ( ST_SEND_LEN-(st0D.sSendHead-st0D.sSendTail) );	}}inline int get_ST0E_txLen(void){	if(st0E.sSendHead==st0E.sSendTail){		return 0;	}	else if(st0E.sSendTail>st0E.sSendHead){		return (st0E.sSendTail-st0E.sSendHead);	}	else{		return ( ST_SEND_LEN-(st0E.sSendHead-st0E.sSendTail) );	}}inline int get_ST0F_txLen(void){	if(st0F.sSendHead==st0F.sSendTail){		return 0;	}	else if(st0F.sSendTail>st0F.sSendHead){		return (st0F.sSendTail-st0F.sSendHead);	}	else{		return ( ST_SEND_LEN-(st0F.sSendHead-st0F.sSendTail) );	}}inline int get_ST0G_txLen(void){	if(st0G.sSendHead==st0G.sSendTail){		return 0;	}	else if(st0G.sSendTail>st0G.sSendHead){		return (st0G.sSendTail-st0G.sSendHead);	}	else{		return ( ST_SEND_LEN-(st0G.sSendHead-st0G.sSendTail) );	}}inline int get_ST0H_txLen(void){	if(st0H.sSendHead==st0H.sSendTail){		return 0;	}	else if(st0H.sSendTail>st0H.sSendHead){		return (st0H.sSendTail-st0H.sSendHead);	}	else{		return ( ST_SEND_LEN-(st0H.sSendHead-st0H.sSendTail) );	}}inline char st0aIsEmpty_rx(void){	return (st0A.sRecvHead==st0A.sRecvTail ? 1 : 0);}inline char st0bIsEmpty_rx(void){	return (st0B.sRecvHead==st0B.sRecvTail ? 1 : 0);}inline char st0cIsEmpty_rx(void){	return (st0C.sRecvHead==st0C.sRecvTail ? 1 : 0);}inline char st0dIsEmpty_rx(void){	return (st0D.sRecvHead==st0D.sRecvTail ? 1 : 0);}inline char st0eIsEmpty_rx(void){	return (st0E.sRecvHead==st0E.sRecvTail ? 1 : 0);}inline char st0fIsEmpty_rx(void){	return (st0F.sRecvHead==st0F.sRecvTail ? 1 : 0);}inline char st0gIsEmpty_rx(void){	return (st0G.sRecvHead==st0G.sRecvTail ? 1 : 0);}inline char st0hIsEmpty_rx(void){	return (st0H.sRecvHead==st0H.sRecvTail ? 1 : 0);}inline char st0aIsFull_rx(void){	return (st0A.sRecvHead==(st0A.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0bIsFull_rx(void){	return (st0B.sRecvHead==(st0B.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0cIsFull_rx(void){	return (st0C.sRecvHead==(st0C.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0dIsFull_rx(void){	return (st0D.sRecvHead==(st0D.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0eIsFull_rx(void){	return (st0E.sRecvHead==(st0E.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0fIsFull_rx(void){	return (st0F.sRecvHead==(st0F.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0gIsFull_rx(void){	return (st0G.sRecvHead==(st0G.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0hIsFull_rx(void){	return (st0H.sRecvHead==(st0H.sRecvTail+1)%ST_RECV_LEN ? 1 : 0);}inline char st0aIsEmpty_tx(void){	return (st0A.sSendHead==st0A.sSendTail ? 1 : 0);}inline char st0bIsEmpty_tx(void){	return (st0B.sSendHead==st0B.sSendTail ? 1 : 0);}inline char st0cIsEmpty_tx(void){	return (st0C.sSendHead==st0C.sSendTail ? 1 : 0);}inline char st0dIsEmpty_tx(void){	return (st0D.sSendHead==st0D.sSendTail ? 1 : 0);}inline char st0eIsEmpty_tx(void){	return (st0E.sSendHead==st0E.sSendTail ? 1 : 0);}inline char st0fIsEmpty_tx(void){	return (st0F.sSendHead==st0F.sSendTail ? 1 : 0);}inline char st0gIsEmpty_tx(void){	return (st0G.sSendHead==st0G.sSendTail ? 1 : 0);}inline char st0hIsEmpty_tx(void){	return (st0H.sSendHead==st0H.sSendTail ? 1 : 0);}inline char st0aIsFull_tx(void){	return (st0A.sSendHead==(st0A.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0bIsFull_tx(void){	return (st0B.sSendHead==(st0B.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0cIsFull_tx(void){	return (st0C.sSendHead==(st0C.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0dIsFull_tx(void){	return (st0D.sSendHead==(st0D.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0eIsFull_tx(void){	return (st0E.sSendHead==(st0E.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0fIsFull_tx(void){	return (st0F.sSendHead==(st0F.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0gIsFull_tx(void){	return (st0G.sSendHead==(st0G.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline char st0hIsFull_tx(void){	return (st0H.sSendHead==(st0H.sSendTail+1)%ST_SEND_LEN ? 1 : 0);}inline void pushST0ARX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	st0A.abyRecvData[st0A.sRecvTail] = byRx;	if(!st0aIsFull_rx()){		st0A.sRecvTail++;		st0A.sRecvTail %= ST_RECV_LEN;	}}inline void pushST0BRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	st0B.abyRecvData[st0B.sRecvTail] = byRx;	if(!st0bIsFull_rx()){		st0B.sRecvTail++;		st0B.sRecvTail %= ST_RECV_LEN;	}}inline void pushST0CRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	st0C.abyRecvData[st0C.sRecvTail] = byRx;	if(!st0cIsFull_rx()){		st0C.sRecvTail++;		st0C.sRecvTail %= ST_RECV_LEN;	}}inline void pushST0DRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	st0D.abyRecvData[st0D.sRecvTail] = byRx;	if(!st0dIsFull_rx()){		st0D.sRecvTail++;		st0D.sRecvTail %= ST_RECV_LEN;	}}inline void pushST0ERX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	st0E.abyRecvData[st0E.sRecvTail] = byRx;	if(!st0eIsFull_rx()){		st0E.sRecvTail++;		st0E.sRecvTail %= ST_RECV_LEN;	}}inline void pushST0FRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	st0F.abyRecvData[st0F.sRecvTail] = byRx;	if(!st0fIsFull_rx()){		st0F.sRecvTail++;		st0F.sRecvTail %= ST_RECV_LEN;	}}inline void pushST0GRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	st0G.abyRecvData[st0G.sRecvTail] = byRx;	if(!st0gIsFull_rx()){		st0G.sRecvTail++;		st0G.sRecvTail %= ST_RECV_LEN;	}}inline void pushST0HRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	st0H.abyRecvData[st0H.sRecvTail] = byRx;	if(!st0hIsFull_rx()){		st0H.sRecvTail++;		st0H.sRecvTail %= ST_RECV_LEN;	}}inline unsigned char st0apopRX(void){//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据	unsigned char byRet;	byRet = st0A.abyRecvData[st0A.sRecvHead];	if(!st0aIsEmpty_rx()){		st0A.sRecvHead++;		st0A.sRecvHead %= ST_RECV_LEN;	}	return byRet;}inline unsigned char st0bpopRX(void){//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据	unsigned char byRet;	byRet = st0B.abyRecvData[st0B.sRecvHead];	if(!st0bIsEmpty_rx()){		st0B.sRecvHead++;		st0B.sRecvHead %= ST_RECV_LEN;

⌨️ 快捷键说明

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