📄 serial.c
字号:
/* * Roadrunner/pk * Copyright (C) 1989-2001 Cornfed Systems, Inc. * * The Roadrunner/pk operating system is free software; you can * redistribute and/or modify it under the terms of the GNU General * Public License, version 2, as published by the Free Software * Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * More information about the Roadrunner/pk operating system of * which this file is a part is available on the World-Wide Web * at: http://www.cornfed.com. * *//* * This driver is based on the Linux serial driver: * * linux/drivers/char/serial.c * * Copyright (C) 1991, 1992 Linus Torvalds * (and a host of others, including Theodore Ts'o) * * Port of the serial driver to the Roadrunner/pk operating system. * -- Joel Vallier <joel.vallier@wanadoo.fr>, May 2000 */ #include <errno.h> #include <m68328.h>#include <dev/serial.h>#include <sys/intr.h>#include <event.h>#include <stdlib.h>#include <sys/mem.h>#include <sys/config.h>#include <string.h>#include <sys/ioctl.h>#include <stdio.h>#define MASTER_CLOCK CLOCK_16_58MHZ#define RXQ_LENGTH PAGE_SIZEstatic int s0_initialized = 0;typedef struct { unsigned char id; volatile unsigned short *UART_CTL; volatile unsigned short *BAUD_CTL; volatile unsigned short *MISC_REG; volatile unsigned short *RX; volatile unsigned short *TX; volatile unsigned char *TX_REG; volatile unsigned char *TX_DATA; int intr; /* Interrupt number */ int eoi; /* End-of-interrupt mask */ int event; /* Asynchronous event number */ char *name; /* UART name */ int dfl_xmit_fifo_size; /* fifo size */ int flags; /* flag */ int speed; /* Baud rate */ int databits; /* Number of data bits */ int parity; /* Parity type */ int stopbits; /* Number of stop bits */ char *q; /* Receive queue */ int h, t; /* Receive queue head and tail */ char last; /* Last character received */ } m68328_port;m68328_port port0 = { 0, (unsigned short *)M328_USTCNT, (unsigned short *)M328_UBAUD, (unsigned short *)M328_UARTMISC, (unsigned short *)M328_UARTRX, (unsigned short *)M328_UARTTX, (unsigned char *)M328_UARTTX, (unsigned char *)(M328_UARTTX + 1), INTR_UTXD0, /* Interrupt number */ 0, /* End-of-interrupt mask */ EVENT_UTXD0, /* Asynchronous event number */ "MC68EZ328_S0", /* UART name */ 8, /* fifo size */ 0, /* flag */ 115200, /* Baud rate */ 8, /* Number of data bits */ 0, /* Parity type */ 1, /* Number of stop bits */ NULL, /* Receive queue */ 0, /* Receive queue head */ 0, /* Receive queue tail */ 0, /* Last character received */ };m68328_port *s0 = &port0;/* Enable bits in the UART Control Register */#define UART_ENABLE 0x1 << 15#define RX_ENABLE 0x1 << 14#define TX_ENABLE 0x1 << 13#define PARITY_ENABLE 0x1 << 11#define ODD_PARITY 0x1 << 10#define STOP_BITS 0x1 << 9#define EIGHT_BIT_TRX 0x1 << 8#define TX_AVAIL_EN 0x1 << 0/* Define masks to disable certain bits in UART Control Register */#define TX_DISABLE 0xDFFF#define RX_DISABLE 0xBFFF/* Enumerate supported clock speeds */#define CLOCK_16_58MHZ 1#define CLOCK_32_16MHZ 2/* Here are just some different values to configure the baudrate */#if MASTER_CLOCK == CLOCK_16_58MHZ #define B230400 0x001c #define B115200 0x0038 #define B57600 0x0138 #define B38400 0x0026 #define B19200 0x0126 #define B9600 0x0226 #define B4800 0x0326 #define B2400 0x0426 #define B1200 0x0526 #define B600 0x0626 #define B300 0x0726#elif MASTER_CLOCK == CLOCK_32_16MHZ #define B230400 0x0038 #define B115200 0x0138 #define B57600 0x0238 #define B38400 0x0126 #define B19200 0x0226 #define B9600 0x0326 #define B4800 0x0426 #define B2400 0x0526 #define B1200 0x0626 #define B600 0x0726 #define B300 0x070B#else #error "MASTER_CLOCK is not defined correctly"#endif/* local data */static unsigned char PESEL ;//: M328_PESEL;static unsigned char PEPUEN ;//: M328_PEPUEN;static unsigned char PGSEL ;//: M328_PGSEL;static unsigned char PGPUEN ;//: M328_PGPUEN;static unsigned char PJSEL ;//: M328_PJSEL;static unsigned char PJPUEN ;//: M328_PJPUEN;static unsigned short PLL_CTL ;//: M328_PLLCR;static voids0_isr(void *params){ u_char ch; unsigned short receive_reg; disable; /* XXX Only handling the receive chars interrupt for now */ do { receive_reg = *(s0->RX); /* Word-read the receiver regs */ if (receive_reg & 0x2000) { /* a character is already in the FIFO */ if (receive_reg & 0x0F00) { /* a data read error occured, we don't differentiate */ break; } else { /* the data */ ch = (char)receive_reg; /* Place character in receive queue */ if (((s0->t + 1) % RXQ_LENGTH) != s0->h) { s0->q[s0->t] = ch; s0->t = (s0->t + 1) % RXQ_LENGTH; #if _DEBUG_ECHO s0_put(ch); #endif } } } } while (1); enable;}ints0_init(){ /* Allocate and initialize receive queue */ //2002年10月09日修改 //s0->q = (char *) kmalloc(RXQ_LENGTH); s0->q = (char *) malloc(RXQ_LENGTH); bzero(s0->q, RXQ_LENGTH); PESEL &= 0x0F; /* configure the E port */ PEPUEN |= 0x10; /* receive pull-up must be enabled */ //SCM: PLL config should be part of board initialization, not here //PLL_CTL = 0x2400; /* configure the PLL control */ *(s0->UART_CTL) = 0x0000; /* disable UART for re-configuration */ *(s0->MISC_REG) = 0x0000; /* Set the MISC register to defaults */ *(s0->BAUD_CTL) = B115200; /* Set the baudrate */ *(s0->TX_REG) = 0x08; /* Set TX register to ignore CTS */ /* set UART control to enabled (Tx and Rx), 1 stop bits, 8 data bits, no parity */ *(s0->UART_CTL) = UART_ENABLE | RX_ENABLE | TX_ENABLE | STOP_BITS | EIGHT_BIT_TRX; isr_inst(s0->intr, s0_isr, s0); intr_unmask(s0->intr); return 0;}ints0_shut(){ return ENOSYS;}ints0_ioctl(int cmd, void *args){ if (cmd == GET_BUFFER_SIZE) { if (args == NULL) return EINVAL; *((u_long *) args) = 1; return 0; } return ENOTTY;}ints0_get(int *c){ int len; char * addr; addr = (char *)0x00710000; //kprintf("%x %2x\n",addr); len = 0; do { u_char ch; unsigned short receive_reg; receive_reg = *(s0->RX); /* Word-read the receiver regs */ if (receive_reg & 0x2000) { /* a character is already in the FIFO */ if (receive_reg & 0x0F00) { /* a data read error occured, we don't differentiate */ continue; } else { /* the data */ ch = (char)receive_reg; *addr = ch; *addr++; //len ++; //if(len == 0x100) // { // len = 0; //kprintf("%x %2x\n",addr,ch); s0_put(ch); // } //if(addr == (char *)0x00716000)kprintf("copy end!"); } } } while (1); disable; while (s0->h == s0->t) { enable; event_wait(s0->event); disable; } *c = s0->q[s0->h]; s0->h = (s0->h + 1) % RXQ_LENGTH; if (*c == '\r') *c = '\n'; enable; return 0;}ints0_put(int c){ disable; while (1) { if (*(s0->TX_REG) & 0x20) { /* The FIFO has a slot available*/ *(s0->TX_DATA) = (unsigned char) c; break; } } if (c == '\r') { while (1) { if (*(s0->TX_REG) & 0x20) { /* The FIFO has a slot available*/ *(s0->TX_DATA) = (unsigned char) '\n'; break; } } } if (c == '\n' && s0->last != '\r') { while (1) { if (*(s0->TX_REG) & 0x20) { /* The FIFO has a slot available*/ *(s0->TX_DATA) = (unsigned char) '\r'; break; } } } s0->last = c; enable; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -