📄 serial_task.c
字号:
/*
* Copyright 2001, Metro Link, Inc.
* All Rights Reserved
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Metro Link, Inc. and may
* contain proprietary, confidential and trade secret information of
* Metro Link, Inc. and/or its partners.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Metro Link, Inc.
*
*/
/*
* File : serial_task.c
*
* Description : Contains implementation of serial interrupt thread function.
*
* Copyright 2003, ZiLOG Inc.
* All Rights Reserved
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of ZiLOG Inc., and might
* contain proprietary, confidential and trade secret information of
* ZiLOG, our partners and parties from which this code has been licensed.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of ZiLOG Inc.
*/
#ifdef _IAR_CODE
#ifdef _EZ80F91
#include <ioez80f91.h>
#endif
#ifdef _EZ80F92
#include <ioez80f92.h>
#endif
#ifdef _EZ80F93
#include <ioez80f92.h>
#endif
#ifdef _EZ80L92
#include <ioez80l92.h>
#endif
#ifdef _EZ80190
#include <ioez80190.h>
#endif
#endif
#include <stdio.h>
#include "serial.h"
#include "_ez80.h"
#include "ZTypes.h"
#include "ZSysgen.h"
#include "ZDevice.h"
#include "ZThread.h"
#include "ZSemaphore.h"
#include "ZInterrupt.h"
//#define SERIAL_DEBUG
UINT16 spill_count = 0;
UINT16 uart_rdr_no_rd =0 ;
RZK_THREADPARAMS_t ThdParams ;
RZK_THREADPARAMS_t *pThdParams = &ThdParams ;
void Uart_IntTask( UART_DVIOBLK * pDevBlk );
extern RZK_SEMAPHOREHANDLE_t hsem;
extern UINT8 eZ80ProductRevision;
void
Uart_IntTask
(
UART_DVIOBLK * pDevBlk
)
{
UINT8 uart_base = pDevBlk->UARTbase;
volatile UINT8 ier;
volatile UINT8 lsr;
volatile UINT8 msr;
UINT8 ch;
UINT8 * pRxBuf = pDevBlk->pRxBuf;
UINT8 * pBuf = pDevBlk->pWriteBuf;
UINT16 BufLen = pDevBlk->RxBufSize;
UINT8 * pPastBuf = pBuf + BufLen;
UINT16 Avail;
// RZK_SEMAPHOREHANDLE_t Sem = pDevBlk->RxSem; // Commented during IAR Porting
RZK_THREADHANDLE_t pTask;
UINT8 CritFlag;
UINT16 BytesRead;
UINT8 do_cts_check = pDevBlk->serparam->settings & SERSET_RTSCTS;
UINT8 do_dcd_check = !(pDevBlk->serparam->settings & SERSET_IGNHUP);
UINT8 TxFlowOn = RZK_TRUE;
UINTRMASK IntMask ;
UINT8 tempFCTL = 0;
IntMask = RZKDisableInterrupts() ;
lsr = UART_LSR(pDevBlk->UARTbase);
msr = UART_MSR(pDevBlk->UARTbase);
ier = UART_IIR(pDevBlk->UARTbase);
/* new silicon modifications @Modified by Venkat */
tempFCTL = (FCTL_TRIG_8 | FCTL_FIFOEN);
#ifdef _EZ80F91
if (eZ80ProductRevision >= 2)
{
tempFCTL |= (FCTL_CLRTXF | FCTL_CLRRXF);
}
#endif
UART_FCTL(uart_base) = tempFCTL; /* modified by Venkat CR#7743 */
// UART_FCTL(0xD0) = tempFCTL;
while( 1 )
{
ier = UART_SPR( uart_base ) | UART_IER( uart_base );
RZKEnableInterrupts(IntMask) ;
lsr = UART_LSR( uart_base );
msr = UART_MSR( uart_base );
if( lsr& LSR_OE)
{
#ifdef SERIAL_DEBUG
printf( "Serial Overrun \n" );
#endif
}
if( ier & (IIR_RDR<<4) )
{
if( !(lsr&LSR_DR) )
{
/*
* In odd situations the Uart will trigger an Rx interrupt,
* but the LSR indicates that no data is available...
*
* The problem seems most likely to occur in cases where
* the UART interrupts were disabled while the remote was
* sending data.
*
* This situation will immediately clear itself once the
* remote sends some data. However, we can't be sure
* this will ever happen. Therefore to clear this condition,
* we momentarily put the Uart in loopback mode and transmit
* a single character.
*/
UART_MCTL(uart_base) |= MCTL_LOOP;
UART_THR(uart_base) = 'Z';
lsr=UART_LSR(uart_base);
while( !(lsr&LSR_DR) )
{
/*
* MCB CR# 2168
* Wait until data reaches the RBR before emptying FIFO
*/
lsr=UART_LSR(uart_base);
}
while(lsr&LSR_DR)
{
// Toss everything we read - should just be 1 byte.
lsr = UART_RBR(uart_base);
lsr = UART_LSR(uart_base);
}
UART_MCTL( uart_base ) &= ~MCTL_LOOP;
uart_rdr_no_rd++;
}
}
ier &= 0x1F;
if( lsr & LSR_DR )
{
BytesRead = 0;
IntMask = RZKDisableInterrupts() ;
Avail = pDevBlk->RxAvail;
RZKEnableInterrupts(IntMask) ;
while( lsr & LSR_DR )
{
ch=UART_RBR(uart_base);
if( (lsr & (LSR_BI | LSR_FE | LSR_PE | LSR_OE | LSR_DR)) == LSR_DR )
{
if( (Avail+BytesRead) < BufLen )
{
*pBuf++ = ch;
if( pBuf == pPastBuf )
{
pBuf = pRxBuf;
}
BytesRead++;
}
else
{
spill_count++;
#ifdef SERIAL_DEBUG
printf( "Spill count %x\n", spill_count );
#endif
}
}
lsr=UART_LSR(uart_base);
}
CritFlag= RZKDisablePreemption();
pDevBlk->RxAvail += BytesRead;
Avail = pDevBlk->RxAvail;
/*
* If the Rx buffer is close to filling, flow off
*/
if( do_cts_check )
{
if( Avail >= FLOW_OFF_LEVEL )
{
UART_MCTL(uart_base) &= ~MCTL_RTS;
}
}
pTask = pDevBlk->pRxTask;
if( pTask && BytesRead )
{
pDevBlk->pRxTask = NULL;
{
RZKGetThreadParameters( pTask, pThdParams );
if((ThdParams.uState & THREAD_INFINITESUSPEND) == THREAD_INFINITESUSPEND )
{
RZKResumeThread(pTask) ;
}
}
}
RZKRestorePreemption(CritFlag);
}
if( (lsr & LSR_THRE) && (ier & IER_TIE) )
{
ier &= ~IER_TIE;
if( TxFlowOn == RZK_TRUE )
{
CritFlag= RZKDisablePreemption();
pDevBlk->TxCount = UART_FIFODEPTH;
pTask = pDevBlk->pTxTask;
if( pTask )
{
pDevBlk->pTxTask = NULL;
{
RZKGetThreadParameters( pTask, pThdParams );
if((ThdParams.uState & THREAD_INFINITESUSPEND) == THREAD_INFINITESUSPEND )
RZKResumeThread(pTask) ;
}
}
RZKRestorePreemption(CritFlag);
}
}
if( (msr&MSR_DDCD) && !(msr&MSR_DCD) && (do_dcd_check) )
{
ier = 0;
#ifdef SERIAL_DEBUG
printf( "DCD Dropped\n" );
#endif
pDevBlk->pDev->fnClose(pDevBlk->pDev);
}
if( do_cts_check )
{
if( msr&MSR_DCTS )
{
if( msr&MSR_CTS )
{
TxFlowOn = RZK_TRUE;
ier |= IER_TIE;
}
else
{
TxFlowOn = RZK_FALSE;
}
}
}
IntMask = RZKDisableInterrupts() ;
/*
* Re-enable HW interrupts
*/
UART_IER(uart_base) |= ier|0x09 ;// VG 19 Sept 2005 workaround
// UART_IER(uart_base) |= ier;
RZKSuspendInterruptThread();
// RZKReleaseSemaphore(hsem);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -