📄 serial.c
字号:
/* * (INCA) ASC UART support */#include <config.h>#ifdef CONFIG_PURPLE#define serial_init asc_serial_init#define serial_putc asc_serial_putc#define serial_puts asc_serial_puts#define serial_getc asc_serial_getc#define serial_tstc asc_serial_tstc#define serial_setbrg asc_serial_setbrg#endif#include <common.h>#include <asm/inca-ip.h>#include "serial.h"#ifdef CONFIG_PURPLE#undef ASC_FIFO_PRESENT#define TOUT_LOOP 100000/* Set base address for second FPI interrupt control register bank */#define SFPI_INTCON_BASEADDR 0xBF0F0000 /* Register offset from base address */#define FBS_ISR 0x00000000 /* Interrupt status register */#define FBS_IMR 0x00000008 /* Interrupt mask register */#define FBS_IDIS 0x00000010 /* Interrupt disable register *//* Interrupt status register bits */#define FBS_ISR_AT 0x00000040 /* ASC transmit interrupt */#define FBS_ISR_AR 0x00000020 /* ASC receive interrupt */#define FBS_ISR_AE 0x00000010 /* ASC error interrupt */#define FBS_ISR_AB 0x00000008 /* ASC transmit buffer interrupt */#define FBS_ISR_AS 0x00000004 /* ASC start of autobaud detection interrupt */#define FBS_ISR_AF 0x00000002 /* ASC end of autobaud detection interrupt */#else#define ASC_FIFO_PRESENT#endif#define SET_BIT(reg, mask) reg |= (mask)#define CLEAR_BIT(reg, mask) reg &= (~mask)#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)#define SET_BITS(reg, mask) SET_BIT(reg, mask)#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}extern uint incaip_get_fpiclk(void);static int serial_setopt (void);/* pointer to ASC register base address */static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;/******************************************************************************** serial_init - initialize a INCAASC channel** This routine initializes the number of data bits, parity* and set the selected baud rate. Interrupts are disabled.* Set the modem control signals if the option is selected.** RETURNS: N/A*/int serial_init (void){#ifdef CONFIG_INCA_IP /* we have to set PMU.EN13 bit to enable an ASC device*/ INCAASC_PMU_ENABLE(13);#endif /* and we have to set CLC register*/ CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS); SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001); /* initialy we are in async mode */ pAsc->asc_con = ASCCON_M_8ASYNC; /* select input port */ pAsc->asc_pisel = (CONSOLE_TTY & 0x1);#ifdef ASC_FIFO_PRESENT /* TXFIFO's filling level */ SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK, ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL); /* enable TXFIFO */ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN); /* RXFIFO's filling level */ SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK, ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL); /* enable RXFIFO */ SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);#endif /* enable error signals */ SET_BIT(pAsc->asc_con, ASCCON_FEN); SET_BIT(pAsc->asc_con, ASCCON_OEN);#ifdef CONFIG_INCA_IP /* acknowledge ASC interrupts */ ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL); /* disable ASC interrupts */ ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);#endif#ifdef ASC_FIFO_PRESENT /* set FIFOs into the transparent mode */ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN); SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);#endif /* set baud rate */ serial_setbrg(); /* set the options */ serial_setopt(); return 0;}void serial_setbrg (void){ ulong uiReloadValue, fdv; ulong f_ASC;#ifdef CONFIG_INCA_IP f_ASC = incaip_get_fpiclk();#else f_ASC = ASC_CLOCK_RATE;#endif#ifndef INCAASC_USE_FDV fdv = 2; uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;#else fdv = INCAASC_FDV_HIGH_BAUDRATE; uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;#endif /* INCAASC_USE_FDV */ if ( (uiReloadValue < 0) || (uiReloadValue > 8191) ) {#ifndef INCAASC_USE_FDV fdv = 3; uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;#else fdv = INCAASC_FDV_LOW_BAUDRATE; uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;#endif /* INCAASC_USE_FDV */ if ( (uiReloadValue < 0) || (uiReloadValue > 8191) ) { return; /* can't impossibly generate that baud rate */ } } /* Disable Baud Rate Generator; BG should only be written when R=0 */ CLEAR_BIT(pAsc->asc_con, ASCCON_R);#ifndef INCAASC_USE_FDV /* * Disable Fractional Divider (FDE) * Divide clock by reload-value + constant (BRS) */ /* FDE = 0 */ CLEAR_BIT(pAsc->asc_con, ASCCON_FDE); if ( fdv == 2 ) CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */ else SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */#else /* INCAASC_USE_FDV */ /* Enable Fractional Divider */ SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */ /* Set fractional divider value */ pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;#endif /* INCAASC_USE_FDV */ /* Set reload value in BG */ pAsc->asc_bg = uiReloadValue; /* Enable Baud Rate Generator */ SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */}/********************************************************************************* serial_setopt - set the serial options** Set the channel operating mode to that specified. Following options* are supported: CREAD, CSIZE, PARENB, and PARODD.** Note, this routine disables the transmitter. The calling routine* may have to re-enable it.** RETURNS:* Returns 0 to indicate success, otherwise -1 is returned*/static int serial_setopt (void){ ulong con; switch ( ASC_OPTIONS & ASCOPT_CSIZE ) { /* 7-bit-data */ case ASCOPT_CS7: con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */ break; /* 8-bit-data */ case ASCOPT_CS8: if ( ASC_OPTIONS & ASCOPT_PARENB ) con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */ else con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */ break; /* * only 7 and 8-bit frames are supported * if we don't use IOCTL extensions */ default: return -1; } if ( ASC_OPTIONS & ASCOPT_STOPB ) SET_BIT(con, ASCCON_STP); /* 2 stop bits */ else CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */ if ( ASC_OPTIONS & ASCOPT_PARENB ) SET_BIT(con, ASCCON_PEN); /* enable parity checking */ else CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */ if ( ASC_OPTIONS & ASCOPT_PARODD ) SET_BIT(con, ASCCON_ODD); /* odd parity */ else CLEAR_BIT(con, ASCCON_ODD); /* even parity */ if ( ASC_OPTIONS & ASCOPT_CREAD ) SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */ pAsc->asc_con |= con; return 0;}void serial_putc (const char c){#ifdef ASC_FIFO_PRESENT uint txFl = 0;#else uint timeout = 0;#endif if (c == '\n') serial_putc ('\r');#ifdef ASC_FIFO_PRESENT /* check do we have a free space in the TX FIFO */ /* get current filling level */ do { txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF; } while ( txFl == INCAASC_TXFIFO_FULL );#else while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) & FBS_ISR_AB)) { if (timeout++ > TOUT_LOOP) { break; } }#endif pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */#ifndef ASC_FIFO_PRESENT *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AB | FBS_ISR_AT;#endif /* check for errors */ if ( pAsc->asc_con & ASCCON_OE ) { SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE); return; }}void serial_puts (const char *s){ while (*s) { serial_putc (*s++); }}int serial_getc (void){ ulong symbol_mask; char c; while (!serial_tstc()); symbol_mask = ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff); c = (char)(pAsc->asc_rbuf & symbol_mask);#ifndef ASC_FIFO_PRESENT *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AR;#endif return c;}int serial_tstc (void){ int res = 1;#ifdef ASC_FIFO_PRESENT if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 ) { res = 0; }#else if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) & FBS_ISR_AR)) { res = 0; }#endif else if ( pAsc->asc_con & ASCCON_FE ) { SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE); res = 0; } else if ( pAsc->asc_con & ASCCON_PE ) { SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE); res = 0; } else if ( pAsc->asc_con & ASCCON_OE ) { SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE); res = 0; } return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -