📄 z8530sio_dy4.c
字号:
pDusart->portB.baudRate = Z8530_DEFAULT_BAUD; pDusart->portB.channel = SCC_CHANNEL_B; pDusart->portB.getTxChar = z8530DummyCallback; pDusart->portB.putRcvChar = z8530DummyCallback; pDusart->portB.mode = 0; /* undefined */ pDusart->portB.options = Z8530_DEFAULT_OPTIONS; /* reset the chip */ z8530InitChannel(&pDusart->portA); z8530InitChannel(&pDusart->portB); intUnlock(oldlevel);#ifndef VME_181 /* Enable FPGA SCC interrupt */ sysOutLong (FPGA_SCC_INT_CNTRL, SCC_INT);#endif }/********************************************************************************* z8530IntWr - handle a transmitter interrupt** This routine handles write interrupts from the SCC.** RETURNS: N/A*/void z8530IntWr ( Z8530_CHAN * pChan ) { char outChar; volatile char * cr = pChan->cr;#ifdef DATA_REG_8530_DIRECT volatile char * dr = pChan->dr;#endif /* DATA_REG_8530_DIRECT */ /* if a char is available, transmit it */ if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) {#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(cr, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_WRITE(cr, outChar);#else REG_8530_WRITE(dr, outChar);#endif /* DATA_REG_8530_DIRECT */ } /* else, reset tx interrupts */ else REG_8530_WRITE(cr, SCC_WR0_RST_TX_INT); /* reset the interrupt */ REG_8530_WRITE(cr, SCC_WR0_RST_HI_IUS); }/******************************************************************************* z8530IntRd - handle a reciever interrupt** This routine handles read interrupts from the SCC.** RETURNS: N/A*/void z8530IntRd ( Z8530_CHAN * pChan ) { volatile char * cr = pChan->cr; volatile char inchar;#ifdef DATA_REG_8530_DIRECT volatile char * dr = pChan->dr;#endif /* DATA_REG_8530_DIRECT */ BOOL rx = FALSE; /* reset the interrupt in the Z8530 */ REG_8530_WRITE(cr, SCC_WR0_RST_HI_IUS); /* * Receiver is FIFO based so there may be more than one char to read. * Loop here until all chars are read. */ do { /* see if character is valid, if not just read and discard it */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR1); /* read register 1 */ REG_8530_READ(cr, &inchar); if ((inchar & (SCC_RR1_CRC_ERR | /* framing error */ SCC_RR1_RX_OV_ERR | /* receive overrun */ SCC_RR1_PAR_ERR)) /* parity error */ == 0) rx = TRUE; else rx = FALSE; /* read the received character */#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(cr, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_READ(cr, &inchar);#else REG_8530_READ(dr, &inchar);#endif /* DATA_REG_8530_DIRECT */ /* do callback if valid char */ if (rx) (*pChan->putRcvChar) (pChan->putRcvArg, inchar); /* See if more chars available */ REG_8530_READ(cr, &inchar); } while (inchar & SCC_RR0_RX_AVAIL); }/************************************************************************ z8530IntEx - handle error interrupts** This routine handles miscellaneous interrupts on the SCC.** RETURNS: N/A*/void z8530IntEx ( Z8530_CHAN * pChan ) { volatile char * cr = pChan->cr; char charStatus; /* if Tx Underrun, reset it */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR0); /* read register 0 */ REG_8530_READ(cr, &charStatus); if (charStatus & SCC_RR0_TX_UND) REG_8530_WRITE(cr, SCC_WR0_RST_TX_UND); REG_8530_WRITE(cr, SCC_WR0_ERR_RST); /* reset errors */ REG_8530_WRITE(cr, SCC_WR0_RST_INT); /* reset ext/status interrupt */ REG_8530_WRITE(cr, SCC_WR0_RST_HI_IUS); /* reset the interrupt */ }/********************************************************************************* z8530Int - handle all interrupts in one vector** On some boards, all SCC interrupts for both ports share a single interrupt* vector. This is the ISR for such boards.* We determine from the parameter which SCC interrupted, then look at* the code to find out which channel and what kind of interrupt.** RETURNS: N/A*/void z8530Int ( Z8530_DUSART * pDusart ) { volatile char * crA; volatile char * crB; Z8530_CHAN * pChanA; Z8530_CHAN * pChanB; char intStatus; char charStatus; char thisCharA; char thisCharB; BOOL rxA = FALSE; BOOL rxB = FALSE;#ifdef DATA_REG_8530_DIRECT volatile char * drA; volatile char * drB;#endif /* DATA_REG_8530_DIRECT */#ifndef VME_181 /* Clear FPGA SCC interrupt */ sysOutLong (FPGA_SCC_INT_STAT, SCC_INT);#endif /* * We need to find out if the SCC interrupted. We need to read * the A channel of the SCC to find out if there are any pending * interrupts. Note that things are set up so that the A * channel is channel 0, even though on the chip it is the one with * the higher address. */ pChanA = &pDusart->portA; /* Load ch A control reg address */ crA = pChanA->cr; /* get pending interrupt flags from Z8530 (found only in ch A) */ REG_8530_WRITE(crA, SCC_WR0_SEL_WR3); /* read reg 3 */ REG_8530_READ(crA, &intStatus); /* If no interrupt pending, interrupt was not from us; return immediately */ if (intStatus == 0) return; /* our interrupt; handle all pending interrupts */ pChanB = &pDusart->portB; /* Load ch B control reg address */ crB = pChanB->cr;#ifdef DATA_REG_8530_DIRECT drA = pChanA->dr; drB = pChanB->dr;#endif /* DATA_REG_8530_DIRECT */ /* * service the interrupt by type with Tx ints being highest priority * and ch A having priority over B. Ignore Special Receive Conditions. */ /* ch A Tx READY */ if ((intStatus & SCC_RR3_A_TX_IP) != 0) { /* Either output the next character, */ if ((*pChanA->getTxChar) (pChanA->getTxArg, &thisCharA) != ERROR) {#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(crA, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_WRITE(crA, thisCharA);#else REG_8530_WRITE(drA, thisCharA);#endif /* DATA_REG_8530_DIRECT */ } /* or reset/stop the tx. */ else REG_8530_WRITE(crA, SCC_WR0_RST_TX_INT); /* update interrupt status */ intStatus &= ~SCC_RR3_A_TX_IP; } /* ch B Tx READY */ if ((intStatus & SCC_RR3_B_TX_IP) != 0) { /* Either output the next character, */ if ((*pChanB->getTxChar) (pChanB->getTxArg, &thisCharB) != ERROR) {#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(crB, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_WRITE(crB, thisCharB);#else REG_8530_WRITE(drB, thisCharB);#endif /* DATA_REG_8530_DIRECT */ } /* or reset/stop the tx. */ else REG_8530_WRITE(crB, SCC_WR0_RST_TX_INT); /* update interrupt status */ intStatus &= ~SCC_RR3_B_TX_IP; } /* ch A Rx CHAR AVAILABLE */ if ((intStatus & SCC_RR3_A_RX_IP) != 0) { /* * Receiver is FIFO based so there may be more than one char to read. * Loop here until all chars are read. */ do { /* see if character is valid, if not just read and discard it */ REG_8530_WRITE(crA, SCC_WR0_SEL_WR1); /* read register 1 */ REG_8530_READ(crA, &charStatus); if ((charStatus & (SCC_RR1_CRC_ERR | /* framing error */ SCC_RR1_RX_OV_ERR | /* receive overrun */ SCC_RR1_PAR_ERR)) /* parity error */ == 0) rxA = TRUE; else { rxA = FALSE; REG_8530_WRITE(crA, SCC_WR0_ERR_RST); /* reset error */ } /* read the received character */#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(crA, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_READ(crA, &thisCharA);#else REG_8530_READ(drA, &thisCharA);#endif /* DATA_REG_8530_DIRECT */ /* do callback if valid char */ if (rxA) (*pChanA->putRcvChar) (pChanA->putRcvArg, thisCharA); /* See if more chars available */ REG_8530_READ(crA, &charStatus); } while (charStatus & SCC_RR0_RX_AVAIL); /* update interrupt status */ intStatus &= ~SCC_RR3_A_RX_IP; } /* ch B Rx CHAR AVAILABLE */ if ((intStatus & SCC_RR3_B_RX_IP) != 0) { /* * Receiver is FIFO based so there may be more than one char to read. * Loop here until all chars are read. */ do { /* see if character is valid, if not just read and discard it */ REG_8530_WRITE(crB, SCC_WR0_SEL_WR1); /* read register 1 */ REG_8530_READ(crB, &charStatus); if ((charStatus & (SCC_RR1_CRC_ERR | /* framing error */ SCC_RR1_RX_OV_ERR | /* receive overrun */ SCC_RR1_PAR_ERR)) /* parity error */ == 0) rxB = TRUE; else { rxB = FALSE; REG_8530_WRITE(crB, SCC_WR0_ERR_RST); /* reset error */ } /* read the received character */#ifndef DATA_REG_8530_DIRECT REG_8530_WRITE(crB, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_READ(crB, &thisCharB);#else REG_8530_READ(drB, &thisCharB);#endif /* DATA_REG_8530_DIRECT */ /* do callback if valid char */ if (rxB) (*pChanB->putRcvChar) (pChanB->putRcvArg, thisCharB); /* See if more chars available */ REG_8530_READ(crB, &charStatus); } while (charStatus & SCC_RR0_RX_AVAIL); /* update interrupt status */ intStatus &= ~SCC_RR3_B_RX_IP; } /* ch A EXTERNAL STATUS CHANGE */ if ((intStatus & SCC_RR3_A_EXT_IP) != 0) { /* if Tx Underrun, reset it */ REG_8530_WRITE(crA, SCC_WR0_SEL_WR0); /* read register 0 */ REG_8530_READ(crA, &charStatus); if (charStatus & SCC_RR0_TX_UND) REG_8530_WRITE(crA, SCC_WR0_RST_TX_UND); /* reset ext/status interrupt */ REG_8530_WRITE(crA, SCC_WR0_RST_INT); } /* ch B EXTERNAL STATUS CHANGE */ if ((intStatus & SCC_RR3_B_EXT_IP) != 0) { /* if Tx Underrun, reset it */ REG_8530_WRITE(crB, SCC_WR0_SEL_WR0); /* read register 0 */ REG_8530_READ(crB, &charStatus); if (charStatus & SCC_RR0_TX_UND) REG_8530_WRITE(crB, SCC_WR0_RST_TX_UND); /* reset ext/status interrupt */ REG_8530_WRITE(crB, SCC_WR0_RST_INT); } /* reset any error condition */ REG_8530_WRITE(crA, SCC_WR0_ERR_RST); /* Reset the interrupt in the Z8530 */ REG_8530_WRITE(crA, SCC_WR0_RST_HI_IUS); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -