📄 z85230async.c
字号:
* Setup the FPGA DMA facility */ tmp=sysInByte ((UINT32)FPGA_SCC_INT_CNTRL); switch ( cha ) { case Z85230_CHANNEL_A: /* Enable the FPGA DMA facility for Ch.A */ sysOutByte ((UINT32)FPGA_SCC_INT_CNTRL, (tmp | SCC_RXA_DMA_EN | SCC_RXA_INT_EN | SCC_TXA_DMA_EN )); /* Enable the Disco IDMA facility interrupt */ gtDmaIntEnable(SCC_TXA_DMA_INT); break; case Z85230_CHANNEL_B: /* Enable the FPGA DMA facility for Ch.B */ sysOutByte ((UINT32)FPGA_SCC_INT_CNTRL, (tmp | SCC_RXB_DMA_EN | SCC_RXB_INT_EN | SCC_TXB_DMA_EN)); /* Enable the Disco IDMA facility interrupt */ gtDmaIntEnable(SCC_TXB_DMA_INT); break; default: return ERROR; } sprintf(tname,"tAsync%d",cha); /* create a task name */ taskSpawn(tname,Z85230_RX_PRIO,0,4096, (FUNCPTR)z85230AsyncRxTask, (int)channel, 0, 0, 0, 0, 0, 0, 0, 0, 0); result=z85230DmaStart(SCC_DMA_CHAN_RX, channel->hw.rxfpga, dmaRxBuf[cha], dmaRxBufSize );#endif /* VME_181 */ return result;}/*************************************************************************** * z85230AsyncRxInt - interrupt callback */void z85230AsyncRxInt( struct _Z85230_CHAN * channel, unsigned char intStatus ) { volatile char * cr = channel->hw.cr; volatile unsigned char rr; BOOL rx = TRUE; /* * 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, &rr ); /* by default, received an ok character and we want to deliver it * to the application */ rx = TRUE; /* parity */ if ( rr & SCC_RR1_PAR_ERR ) { channel->readError = Z85230_ERR_PARITY; rx = FALSE; } /* rx fifo overflow */ if ( rr & SCC_RR1_RX_OV_ERR ) { channel->readError = Z85230_ERR_RX_OVERFLOW; rx = FALSE; } /* framing error - not reported */ if ( rr & SCC_RR1_CRC_ERR ) { rx = FALSE; } /* read the received character */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR8 ); /* select data register */ REG_8530_READ( cr, &rr ); /* do callback if valid char */ if ( rx ) { if ( z85230AsyncPutRxChar( channel, rr ) == Z85230_ERR ) { channel->readError = Z85230_ERR_RX_BUF_OVERFLOW; } } /* See if more chars available */ REG_8530_READ( cr, &rr ); } while ( rr & SCC_RR0_RX_AVAIL ); /* wake up blocking reads */ if ( (z85230BufStreamSize( &(channel->rxStreamBuf) ) >= async[ channel->channel ].blockingReadSize) && (async[ channel->channel ].blockingReadSize > 0) ) { async[ channel->channel ].blockingReadSize = 0; semGive( channel->readSem ); } }/*************************************************************************** * z85230AsyncTxInt - interrupt callback */void z85230AsyncTxInt( struct _Z85230_CHAN * channel, unsigned char intStatus ) { char outChar; volatile char * cr = channel->hw.cr; /* if a char is available, transmit it */ if ( z85230AsyncGetTxChar( channel, &outChar ) != ERROR ) { REG_8530_WRITE(cr, SCC_WR0_SEL_WR8); /* select data register */ REG_8530_WRITE(cr, outChar); } else { /* reset tx interrupts */ REG_8530_WRITE(cr, SCC_WR0_RST_TX_INT); /* awaken blocking writes */ if ( async[ channel->channel ].blockingOnWrite ) { async[ channel->channel ].blockingOnWrite = FALSE; semGive( channel->writeSem ); } } }/*************************************************************************** * z85230AsyncExInt - interrupt callback */void z85230AsyncExInt( struct _Z85230_CHAN * channel, unsigned char intStatus ) { /* check tx underrun */ unsigned char rr0; REG_8530_READ( channel->hw.cr, &rr0 ); if ( rr0 & SCC_RR0_TX_UND ) { channel->writeError = Z85230_ERR_TX_UNDERFLOW; } }/*************************************************************************** * z85230AsyncRxDmaInt - interrupt callback * * NOMANUAL */void z85230AsyncRxDmaInt( struct _Z85230_CHAN * channel ) { /* logMsg("\nDiscoDma\n",0,0,0,0,0,0); */#if FALSE /* this part is disabled for purpose */ int size ; STATUS result ; UINT32 bytesRead ; /* update the stream */ bytesRead = z85230DmaBytesTransfered( SCC_DMA_CHAN_RX ) - z85230DmaGetReadValue( &(channel->rxStreamBuf));/* logMsg("End DMA bts read=%d\n",bytesRead,0,0,0,0,0); */ z85230DmaWritePtrUp( &(channel->rxStreamBuf), bytesRead ); size = z85230DmaGetRxStreamSize(&(channel->rxStreamBuf)); if((size<0) || (size>4096)) { size = 4096; channel->rxStreamBuf.write = 0 ; channel->rxStreamBuf.read = 0 ; } result=z85230DmaStart( SCC_DMA_CHAN_RX, channel->hw.rxfpga, z85230DmaGetRxStream(&(channel->rxStreamBuf)), size );#endif }#ifdef VME_181/*************************************************************************** * z85230AsyncFpgaInt - FPGA interrupt callback in DMA mode * * Disable the associated receiving IDMA Channel Enable bit * and read the actual data counter from the FPGA register. * The disable operation will flash all the received data within the internal on-chip * buffer, write it to the SDRAM buffer, update the DMA byte count and the destination * addresse accordingly. * z85230DmaAbort is not called from within due to potential overhead / endless loop risk * * NOMANUAL updated aak */void z85230AsyncFpgaInt( struct _Z85230_CHAN * channel ){ UINT16 frame_size; int cha = channel->channel; gtDmaIntDisable(SCC_DMA_CHAN_RX); sysOutLong( (UINT32)GT64260_DMACC( SCC_DMA_CHAN_RX ), 0x200 ); /* * Get actual Rx byte count */ frame_size = (cha)?sysInWordNoSwap ((UINT32)FPGA_SCC_CHB_CNTR):sysInWordNoSwap ((UINT32)FPGA_SCC_CHA_CNTR); msgQSend(dmaMsgQid[cha], (char*)&frame_size, sizeof(UINT16),NO_WAIT, MSG_PRI_NORMAL); /* logMsg("\nFPGA read=%d\n",actual,0,0,0,0,0); */}/*************************************************************************** * z85230AsyncTxDmaInt - interrupt callback * * NOMANUAL updated aak */void z85230AsyncTxDmaInt( struct _Z85230_CHAN * channel ) { int bytes_written ; bytes_written = z85230DmaBytesTransfered( SCC_DMA_CHAN_TX ); z85230DmaReadPtrUp( &(channel->txStreamBuf), bytes_written); semGive( channel->writeSem ); }#endif /* VME_181 *//*************************************************************************** * z85230AsyncOpen - open channel in Async mode * * RETURNS * Z85230_OK: success * anything else: fail */int z85230AsyncOpen( struct _Z85230_CHAN * channel ) { Z8530_CHAN * hw = &(channel->hw); volatile unsigned char * cr = channel->hw.cr; unsigned char rr; /* allocate buffers */#ifdef VME_181 z85230BufCreateStream( &(channel->txStreamBuf), Z85230ASYNC_DEFAULT_BUFFERSIZE + 1); z85230BufCreateStream( &(channel->rxStreamBuf), Z85230ASYNC_DEFAULT_BUFFERSIZE + 1);#else z85230BufCreateStream( &(channel->txStreamBuf), Z85230ASYNC_DEFAULT_BUFFERSIZE + 1 + (Z85230ASYNC_DEFAULT_BUFFERSIZE/Z85230_MAX_DESC)); z85230BufCreateStream( &(channel->rxStreamBuf), Z85230ASYNC_DEFAULT_BUFFERSIZE + 1 + (Z85230ASYNC_DEFAULT_BUFFERSIZE/Z85230_MAX_DESC));#endif /* reset the chip */ REG_8530_READ( cr, &rr ); /* reset any error or interrupts */ REG_8530_WRITE(cr, SCC_WR0_ERR_RST); REG_8530_WRITE(cr, SCC_WR0_RST_INT); /* clear the option field of the device header */ hw->options = 0 ; /* write reg 9 - master interrupt control and reset */ REG_8530_WRITE(cr, SCC_WR0_SEL_WR9); if ( channel->channel == Z85230_CHANNEL_A ) { REG_8530_WRITE( cr, SCC_WR9_CH_A_RST ); /* reset channel A */ } else { /* channel B */ REG_8530_WRITE( cr, SCC_WR9_CH_B_RST ); /* reset channel B */ } /* Delay for about 1 uSec (typically) before further chip accesses */ Z8530_RESET_DELAY; REG_8530_READ( cr, &rr ); /* write reg 4 - misc parms & modes */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR4 ); REG_8530_WRITE( cr, SCC_WR4_1_STOP | SCC_WR4_16_CLOCK ); /*SRR+1*/ hw->options &= ~STOPB ; /*STOPB(0x20)==1, 2 else 1*/ /* write reg 10 - misc tx/rx control */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR10 ); REG_8530_WRITE( cr, 0 ); /* clear sync, loop, poll */ /* write reg 11 - clock mode */ hw->writeReg11 = SCC_WR11_RX_BR_GEN | SCC_WR11_TX_BR_GEN | SCC_WR11_OUT_BR_GEN; REG_8530_WRITE( cr, SCC_WR0_SEL_WR11 ); REG_8530_WRITE( cr, hw->writeReg11 ); /* write reg 15 - disable external/status interrupts */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR15 ); REG_8530_WRITE( cr, SCC_WR15_TX_UND_IE ); /* write reg 14 - misc control bits */ hw->writeReg14 = SCC_WR14_BR_EN | SCC_WR14_BR_SRC | SCC_WR14_SRC_BR; REG_8530_WRITE( cr, SCC_WR0_SEL_WR14 ); REG_8530_WRITE( cr, hw->writeReg14 ); /* reset external interrupts and errors */ REG_8530_WRITE( cr, SCC_WR0_RST_INT ); REG_8530_WRITE( cr, SCC_WR0_ERR_RST ); /* write reg 3 - receive params */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR3 ); REG_8530_WRITE( cr, SCC_WR3_RX_8_BITS | SCC_WR3_RX_EN ); /* write reg 5 - tx params */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR5 ); REG_8530_WRITE( cr, SCC_WR5_TX_EN | SCC_WR5_DTR ); /* write reg 2 - interrupt vector */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR2 ); REG_8530_WRITE( cr, hw->intVec ); /* write reg 1 - disable interrupts and xfer mode */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); REG_8530_WRITE( cr, 0 ); /* write reg 9 - enable master interrupt control */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR9 ); REG_8530_WRITE( cr, SCC_WR9_MIE | hw->intType ); /* reset Tx CRC generator and any pending ext/status interrupts */ REG_8530_WRITE( cr, SCC_WR0_RST_TX_CRC ); REG_8530_WRITE( cr, SCC_WR0_RST_INT ); REG_8530_WRITE( cr, SCC_WR0_RST_INT ); /* write reg 7` - sdlc options */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR15 ); REG_8530_READ( cr, &rr ); REG_8530_WRITE( cr, SCC_WR0_SEL_WR15 ); REG_8530_WRITE( cr, rr | SCC_WR15_WR7P_EN ); REG_8530_WRITE( cr, SCC_WR0_SEL_WR7 ); REG_8530_WRITE( cr, SCC_WR7P_EXT_READ_ENB /* | SCC_WR7P_TX_FIFO_INT_LVL */ ); /* reset SCC register counter */ REG_8530_WRITE( cr, 0 ); hw->baudRate = z85230HwSetRate( channel, Z85230ASYNC_DEFAULT_BAUDRATE ); /* wait a moment */ taskDelay( 1 ); /* options */ z85230AsyncOptsSet( channel, CREAD | CLOCAL | CS8 ); /* connect */ z85230AsyncConnect( channel ); /* reset tx interrupts */ REG_8530_WRITE(cr, SCC_WR0_RST_TX_INT);#ifdef VME_181 /* default mode is interrupt mode */ z85230AsyncModeSet( channel, Z85230_MODE_INT );#else /* default mode is DMA mode */ z85230AsyncModeSet( channel, Z85230_MODE_DMA );#endif return Z85230_OK; }/*************************************************************************** * z85230AsyncClose - close Async channel * * RETURNS * Z85230_OK: success * anything else: fail */int z85230AsyncClose( struct _Z85230_CHAN * channel ) { volatile unsigned char * cr = channel->hw.cr; int oldLevel; /* release buffers */ z85230BufDeleteStream( &(channel->rxStreamBuf) ); z85230BufDeleteStream( &(channel->txStreamBuf) ); if ( channel->hw.mode == Z85230_MODE_DMA ) z85230AsyncModeReset(channel);/* if( dmaRxBuf[cha] != NULL ) { cacheDmaFree( dmaRxBuf[cha] ); dmaRxBuf[cha] = NULL ; } if(dmaMsgQid[cha] != NULL) { msgQDelete(dmaMsgQid[cha]); dmaMsgQid[cha] = NULL; }*/ oldLevel = intLock(); /* disable interrupts */ REG_8530_WRITE( cr, SCC_WR0_SEL_WR1 ); REG_8530_WRITE( cr, 0 ); intUnlock( oldLevel ); return Z85230_OK; }#ifdef VME_181/*************************************************************************** * z85230AsyncRxTask - moves data from DMA buffer into the driver buffer * * This routine is spawned as a task when DMA mode is selected. * The task dies either when the channel is closed or when INT mode * is selected. * * NOMANUAL */LOCAL void z85230AsyncRxTask( struct _Z85230_CHAN * channel){ int cha = channel->channel; UINT16 bytesRead ; UINT8 rxTaskDone=FALSE;/* static UINT32 rxFragmentCount[Z85230_NUM_CHANNELS] = {0,0} ; *//* * Do loop until the termination signal is received: */do { bytesRead=0; msgQReceive(dmaMsgQid[cha], (char *)&bytesRead, sizeof(UINT16), WAIT_FOREVER); /* no timeout */ /* This part was performed upon MsgQ timeout if (bytesRead) { bytesRead -= rxFragmentCount[cha]; rxFragmentCount[cha] =0; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -