📄 s3c2410_can.cpp
字号:
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_MERRF\r\n")));
interrupts = INTR_MERRF; // Error status
bit_cmd(CANINTE, INTR_MERRF, 0x00);//Disable MERRF interrupter
}
else if(IntPndVal & INTR_ERRIF)
{
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_ERRIF\r\n")));
interrupts = INTR_ERRIF; //
bit_cmd(CANINTE, INTR_ERRIF, 0x00);//Disable ERRIF interrupter
}
}
else if(inter == 0x04)
{
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_WAKIF\r\n")));
interrupts = INTR_WAKIF; //
bit_cmd(CANINTE, INTR_WAKIF, 0x00);//Disable WAKIF interrupter
}
else if((inter == 0x06) && pSpiHead->fSW_EnTxINT )
{
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_TX0IF\r\n")));
interrupts = INTR_TX0IF;
bit_cmd(CANINTE, INTR_TX0IF, 0x00);//Disable TX0IF interrupter
}
else if((inter == 0x08) && pSpiHead->fSW_EnTxINT )
{
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_TX1IF\r\n")));
interrupts = INTR_TX1IF;
bit_cmd(CANINTE, INTR_TX1IF, 0x00);//Disable TX1IF interrupter
}
else if((inter == 0x0a) && pSpiHead->fSW_EnTxINT )
{
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_TX2IF\r\n")));
interrupts = INTR_TX2IF;
bit_cmd(CANINTE, INTR_TX2IF, 0x00);//Disable TX2IF interrupter
}
else if(inter == 0x0c)
{
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_RX0IF\r\n")));
interrupts = INTR_RX0IF; // Received valid data.
bit_cmd(CANINTE, INTR_RX0IF, 0x00);//Disable RX0IF interrupter
}
else if(inter == 0x0e)
{
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_RX1IF\r\n")));
interrupts = INTR_RX1IF; // Received valid data.
bit_cmd(CANINTE, INTR_RX1IF, 0x00);//Disable RX1IF interrupter
}
else
{
// RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_NONE\r\n")));
interrupts = INTR_NONE; // No interrupts pending, vector is useless
}
}
else
{
// RETAILMSG (DEBUGMODE, (TEXT("INTR_NONE\r\n")));
interrupts = INTR_NONE; // No interrupts pending, vector is useless
}
return(interrupts);
}
//
VOID EflgEventHandler(PHW_INDEP_INFO pSpiHead)
{
ERRIF_TYPE it = ERRIF_NONE;
// RETAILMSG(1, (TEXT("EflgEventHandler, pHead 0x%X\r\n"), pSpiHead));
DEBUGMSG (ZONE_THREAD,
(TEXT("+EflgEventHandler, pHead 0x%X\r\n"), pSpiHead));
try
{
r_cmd(EFLG, (U8*)&it, 1);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// RETAILMSG(DEBUGMODE, (TEXT("ACCESS VIOLATION ERROR \r\n")));
it = ERRIF_NONE;
}
// RETAILMSG(1, (TEXT("EflgEventHandler, interrupts 0x%X\r\n"), it));
DEBUGMSG (ZONE_THREAD,
(TEXT("EflgEventHandler, interrupts 0x%X\r\n"), it));
//接受缓冲器0溢出
if(it & ERRIF_RX0OVR)
{
// RETAILMSG(1, (TEXT("RX0OVR Event\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("RX0OVR Event\r\n")));
bit_cmd(CANINTF, RX0IF, 0x00);
bit_cmd(EFLG, RX0OVR, 0x00);
}
//接受缓冲器1溢出
if(it & ERRIF_RX1OVR)
{
// RETAILMSG(1, (TEXT("RX1OVR Event\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("RX1OVR Event\r\n")));
bit_cmd(CANINTF, RX1IF, 0x00);
bit_cmd(EFLG, RX1OVR, 0x00);
}
//TEC>=96 or REC>=96
if(it & ERRIF_EWARN)
{
// RETAILMSG(1, (TEXT("EWARN Event\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("EWARN Event\r\n")));
}
//TEC>=96
if(it & ERRIF_TXWAR)
{
// RETAILMSG(1, (TEXT("TXWAR Event\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("TXWAR Event\r\n")));
w_cmd0(TEC, 0x00);
}
//REC>=96
if(it & ERRIF_RXWAR)
{
// RETAILMSG(1, (TEXT("RXWAR Event\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("RXWAR Event\r\n")));
w_cmd0(REC, 0x00);
}
//TEC>=128
if(it & ERRIF_TXEP)
{
// RETAILMSG(1, (TEXT("RX0OVR Event\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("RX0OVR Event\r\n")));
w_cmd0(TEC, 0x00);
}
//REC>=128
if(it & ERRIF_RXEP)
{
// RETAILMSG(1, (TEXT("RXEP Event\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("RXEP Event\r\n")));
w_cmd0(REC, 0x00);
}
//TEC>=255
if(it & ERRIF_TXB0)
{
// RETAILMSG(1, (TEXT("TXB0 Event\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("TXB0 Event\r\n")));
w_cmd0(TEC, 0x00);
}
return;
}
//
VOID SpiEventHandler(PHW_INDEP_INFO pSpiHead)
{
INTERRUPT_TYPE it = INTR_NONE;
BOOL RxDataAvail = FALSE;
// RETAILMSG(1, (TEXT("+SpiEventHandler, pHead 0x%X\r\n"), pSpiHead));
DEBUGMSG (ZONE_THREAD,
(TEXT("+SpiEventHandler, pHead 0x%X\r\n"), pSpiHead));
if ( pSpiHead->KillRxThread || !pSpiHead->hSpiEvent )
{
// RETAILMSG(1, (TEXT("Exitting thread\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("Exitting thread\r\n")));
SetEvent(pSpiHead->hKillDispatchThread);
ExitThread(0);
}
// NOTE - This one is a little tricky. If the only owner is a monitoring task
// then I don't have an owner for read/write, yet I might be in this routine
// due to a change in line status. Lets just do the best we can and increment
// the count for the access owner if available.
if ( pSpiHead->pAccessOwner )
COM_INC_USAGE_CNT(pSpiHead->pAccessOwner);
while ( 1 )
{
if( !(it = GetInterruptType(pSpiHead)) )
{
// RETAILMSG(1, (TEXT("SpiEventHandler, No Interrupt.\r\n")));
DEBUGMSG (ZONE_THREAD, (TEXT("SpiEventHandler, No Interrupt.\r\n")));
w_cmd0(CANINTF, 0x00); //清中断标志
w_cmd0(CANINTE, 0xff); //中断使能
ClearINTPnd(pSpiHead->bEINT);
EnINT(pSpiHead->bEINT);
break;
}
// RETAILMSG(1, (TEXT("SpiEventHandler, Interrupts 0x%X\r\n"), it));
DEBUGMSG (ZONE_THREAD, (TEXT("SpiEventHandler, Interrupts 0x%X\r\n"), it));
if ( it & INTR_RX0IF )
{
// RETAILMSG(1, (TEXT("RX0IF Event\r\n")));
DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("RX0IF Event\r\n")));
DoRxData(pSpiHead, &RxDataAvail, 0);
// bit_cmd(CANINTF, INTR_RX0IF, 0x00);
}
else if ( it & INTR_RX1IF )
{
// RETAILMSG(1, (TEXT("RX1IF Event\r\n")));
DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("RX1IF Event\r\n")));
DoRxData(pSpiHead, &RxDataAvail, 1);
// bit_cmd(CANINTF, INTR_RX1IF, 0x00);
}
else if ( it & INTR_TX0IF )
{
// RETAILMSG(1, (TEXT("TX0IF Event\r\n")));
DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("TX0IF Event\r\n")));
DoTxData(pSpiHead);
//Clearing TX0IF interrupter
bit_cmd(CANINTF, INTR_TX0IF, 0x00);
}
else if ( it & INTR_TX1IF )
{
// RETAILMSG(1, (TEXT("TX1IF Event\r\n")));
DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("TX1IF Event\r\n")));
DoTxData(pSpiHead);
//Clearing ERRIF interrupter
bit_cmd(CANINTF, INTR_TX1IF, 0x00);
}
else if ( it & INTR_TX2IF )
{
// RETAILMSG(1, (TEXT("TX2IF Event\r\n")));
DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("TX2IF Event\r\n")));
DoTxData(pSpiHead);
//Clearing ERRIF interrupter
bit_cmd(CANINTF, INTR_TX2IF, 0x00);
}
//错误中断
else if ( it & INTR_ERRIF )
{
EflgEventHandler(pSpiHead);
//Clearing ERRIF interrupter
bit_cmd(CANINTF, INTR_ERRIF, 0x00);
//Enable ERRIF interrupter
bit_cmd(CANINTE, INTR_ERRIF, INTR_ERRIF);
}
//总线活动唤醒中断,从休眠模式中跳出
else if ( it & INTR_WAKIF )
{
//do something here
//......
//Clearing WAKIF interrupter
bit_cmd(CANINTF, INTR_WAKIF, 0x00);
//Enable WAKIF interrupter
bit_cmd(CANINTE, INTR_WAKIF, INTR_WAKIF);
}
//报文错误中断,
//1.用于在只听模式下波特率的确定
//2.总线上没有其他报文活动
else if ( it & INTR_MERRF )
{
//do something here
//......
//Clearing MERRF interrupter
bit_cmd(CANINTF, INTR_MERRF, 0x00);
//Enable MERRF interrupter
bit_cmd(CANINTE, INTR_MERRF, INTR_MERRF);
Sleep(1000);
}
}
ClearINTPnd(pSpiHead->bEINT);
EnINT(pSpiHead->bEINT);
// We kept this till the end to optimize the above loop
if ( RxDataAvail )
{
// Signal SPI_Read that bytes are available.
SetEvent(pSpiHead->hReadEvent);
EvaluateEventFlag(pSpiHead, EV_RXCHAR);
}
// RETAILMSG(1, (TEXT("-SpiEventHandler, Fifo(R=%d,W=%d,L=%d)\r\n"),
// RxRead(pSpiHead), RxWrite(pSpiHead), RxLength(pSpiHead)));
DEBUGMSG (ZONE_THREAD ,
(TEXT("-SpiEventHandler, Fifo(R=%d,W=%d,L=%d)\r\n"),
RxRead(pSpiHead), RxWrite(pSpiHead),
RxLength(pSpiHead)));
if ( pSpiHead->pAccessOwner )
COM_DEC_USAGE_CNT(pSpiHead->pAccessOwner);
return;
}
/*
@doc INTERNAL
@func ULONG | SpiDispatchThread | Main spi event dispatch thread code.
* This is the reading and dispatching thread. It gets the
* event associated with the logical interrupt dwIntID and calls
* hardware specific routines to determine whether it's a receive event
* or a transmit event. If it's a transmit event, it calls the HW tx handler.
* If it's a receive event, it calls for the number of characters and calls
* atomic GetByte() to extract characters and put them into the drivers
* buffer represented by pSpiHead->pTargetBuffer, managing waiting
* for events and checking to see if those signals correspond to reading.
* It relies on NK masking the interrupts while it does it's thing, calling
* InterruptDone() to unmask them for each of the above cases.
*
* Not exported to users.
*
@rdesc This thread technically returns a status, but in practice, doesn't return
* while the device is open.
*/
static DWORD WINAPI
SpiDispatchThread(
PVOID pContext /* @parm [IN] Pointer to main data structure. */
)
{
PHW_INDEP_INFO pSpiHead = (PHW_INDEP_INFO)pContext;
ULONG WaitReturn;
// RETAILMSG(1, (TEXT("Entered SpiDispatchThread %X\r\n"), pSpiHead));
DEBUGMSG (ZONE_THREAD, (TEXT("Entered SpiDispatchThread %X\r\n"), pSpiHead));
// It is possible for a PDD to use this routine in its private thread, so
// don't just assume that the MDD synchronization mechanism is in place.
DEBUGMSG(ZONE_INIT, (TEXT("Spinning in dispatch thread %X\n\r"), pSpiHead));
while ( !pSpiHead->pDispatchThread )
{
Sleep(20);
}
/* Wait for the event that any spi port action creates.
*/
while ( !pSpiHead->KillRxThread )
{
DEBUGMSG (ZONE_THREAD, (TEXT("Event %X, %d\r\n"),
pSpiHead->hSpiEvent,
pSpiHead->dwIntID ));
WaitReturn = WaitForSingleObject(pSpiHead->hSpiEvent, INFINITE);
SpiEventHandler(pSpiHead);
InterruptDone(pSpiHead->dwIntID);
}
DEBUGMSG (ZONE_THREAD, (TEXT("SpiDispatchThread %x exiting\r\n"), pSpiHead));
return(0);
}
// ****************************************************************
//
// @doc INTERNAL
// @func BOOL | StartDispatchThread | Start thread if requested by PDD.
//
// @parm ULONG | pspiHead
//
// @rdesc TRUE if success, FALSE if failed.
//
BOOL
StartDispatchThread(
PHW_INDEP_INFO pSpiHead
)
{
// Initialize the interrupt to be associated with the hSpiEvent
// event. GetByte waits on this event and acts as a second
// level decoder determining the type of spi event. If this return
// fails, then another process has registered for the interrupt, so
// fail the init and set the hSpiEvent to NULL.
// RETAILMSG(1, (TEXT("Initializing interrupt 0x%X, 0x%X\n\r"),
// pSpiHead->dwIntID, pSpiHead->hSpiEvent));
DEBUGMSG(ZONE_INIT,
(TEXT("Initializing interrupt 0x%X, 0x%X\n\r"),
pSpiHead->dwIntID, pSpiHead->hSpiEvent));
if ( !InterruptInitialize(pSpiHead->dwIntID, pSpiHead->hSpiEvent, NULL, 0) )
{
DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("Error initializing interrupt\n\r")));
return(FALSE);
}
InterruptDone(pSpiHead->dwIntID);
// Set up the dispatch thread and it's kill flag. Note that the thread
// fills in its own handle in pspiHead.
pSpiHead->KillRxThread = 0;
pSpiHead->pDispatchThread = NULL;
DEBUGMSG(ZONE_INIT, (TEXT("Spinning thread%X\n\r"), pSpiHead));
pSpiHead->pDispatchThread = CreateThread(NULL,0, SpiDispatchThread, pSpiHead, 0,NULL);
if ( pSpiHead->pDispatchThread == NULL )
{
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("Error creating dispatch thread (%d)\n\r"),
GetLastError()));
return(FALSE);
}
// RETAILMSG(1, (TEXT("Created receive thread %X\r\n"), pSpiHead->pDispatchThread));
DEBUGMSG (ZONE_INIT, (TEXT("Created receive thread %X\r\n"),
pSpiHead->pDispatchThread));
return(TRUE);
}
// ****************************************************************
//
// @doc INTERNAL
// @func BOOL | StartDispatchThread | Stop thread, disable interrupt.
//
// @parm ULONG | pspiHead
//
// @rdesc TRUE if success, FALSE if failed.
//
BOOL
StopDispatchThread(
PHW_INDEP_INFO pSpiHead
)
{
HANDLE pThisThread = GetCurrentThread();
ULONG priority256;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -