📄 s3c2410_can.cpp
字号:
v_pINTregs = (volatile INTreg *)SER_RegAlloc((PVOID)INT_BASE, sizeof(INTreg));
if (v_pINTregs == NULL)
{
ERRORMSG(1,(TEXT("For INTregs: VirtualAlloc failed!\r\n")));
break;
}
v_pPWMregs = (volatile PWMreg *)SER_RegAlloc((PVOID)PWM_BASE, sizeof(PWMreg));
if (v_pPWMregs == NULL)
{
ERRORMSG(1,(TEXT("For PWMregs: VirtualAlloc failed!\r\n")));
break;
}
r = TRUE;
} while (0);
if (!r)
{
SER_VirtualFree();
// RETAILMSG(DEBUGMODE,(TEXT("::: SPI_VirtualAlloc() - Fail\r\n")));
}
else
{
// RETAILMSG(DEBUGMODE,(TEXT("::: SPI_VirtualAlloc() - Success\r\n")));
}
return r;
}
PRIVATE void
SER_VirtualFree(VOID)
{
// RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualFree()\r\n")));
if (v_pIOPregs)
{
VirtualFree((PVOID)v_pIOPregs, 0, MEM_RELEASE);
v_pIOPregs = NULL;
}
if (v_pSPI0regs)
{
VirtualFree((PVOID)v_pSPI0regs, 0, MEM_RELEASE);
v_pSPI0regs = NULL;
}
if (v_pINTregs)
{
VirtualFree((PVOID)v_pINTregs, 0, MEM_RELEASE);
v_pINTregs = NULL;
}
if (v_pPWMregs)
{
VirtualFree((PVOID)v_pPWMregs, 0, MEM_RELEASE);
v_pPWMregs = NULL;
}
}
//
// @doc OEM
// @func ULONG | HWTxIntrHandler | This routine is called
// whenever INTR_TX is returned by GetInterruptType
//
// @rdesc None
//
VOID
HWTxIntrHandler(
PVOID pHead, // Hardware Head
PUCHAR pTxBuffer, // @parm Pointer to receive buffer
ULONG *pBufflen // @parm In = max bytes to transmit, out = bytes transmitted
)
{
PHW_INDEP_INFO pSpiHead = (PHW_INDEP_INFO)pHead;
ULONG NumberOfBytes = *pBufflen;
// RETAILMSG(DEBUGMODE, (TEXT("HWTxIntrHandler \r\n")));
// We may be done sending. If so, just disable the TX interrupts and return.
if( ! *pBufflen )
{
//Disable ERRIF interrupter
// bit_cmd(CANINTE, INTR_TX0IF, 0x00);
bit_cmd(CANINTE, 0x1c, 0x00);
pSpiHead->fSW_EnTxINT = FALSE;
return;
}
*pBufflen = 0; //In case we don't send anything below.
// OK, now lets actually transmit some data.
EnterCriticalSection(&(pSpiHead->TransmitCritSec));
EnterCriticalSection(&(pSpiHead->RegCritSec));
try {
*pBufflen = CAN_Send(pTxBuffer, NumberOfBytes);
// Enable xmit intr. We need to do this no matter what,
// since it relies on one final interrupt before
// returning to the application.
//Enable TX0IF/TX1IF/TX2IF interrupter
// bit_cmd(CANINTE, INTR_TX0IF, INTR_TX0IF);
bit_cmd(CANINTE, 0x1c, INTR_TX0IF|INTR_TX1IF|INTR_TX2IF);
pSpiHead->fSW_EnTxINT = TRUE;
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// Hmm, not sure what would cause this. Lets just
// go away until we get another TX interrupt.
}
LeaveCriticalSection(&(pSpiHead->RegCritSec));
LeaveCriticalSection(&(pSpiHead->TransmitCritSec));
return;
}
// @doc OEM
// @func ULONG | HWRxIntrHandler | This routine gets several characters from the hardware
// receive buffer and puts them in a buffer provided via the second argument.
// It returns the number of bytes lost to overrun.
//
// @rdesc The return value indicates the number of overruns detected.
// The actual number of dropped characters may be higher.
//
ULONG
HWRxIntrHandler(
PVOID pHead, // @parm Pointer to hardware head
PUCHAR pRxBuffer, // @parm Pointer to receive buffer
ULONG *pBufflen, // @parm In = max bytes to read, out = bytes read
U8 index
)
{
PHW_INDEP_INFO pSpiHead = (PHW_INDEP_INFO)pHead;
ULONG RetVal=0, iCount=0;
ULONG TargetRoom = *pBufflen;
BOOL fRXFlag = FALSE;
UCHAR cEvtChar, cRXChar;
ULONG RxDataReady;
*pBufflen = 0;
cEvtChar = 0x0d;//EVENT_CHAR
// RETAILMSG(DEBUGMODE, (TEXT("HWRxIntrHandler \r\n")));
try
{
U8 length = 0;
U8 dat0[20] = {0};
U8 selrx[2] = {RX0IF, RX1IF};
U8 selreg[2] = {RXB0SIDH, RXB1SIDH};
CAN_State(&cRXChar);
if(cRXChar & selrx[index])
RxDataReady = 1;
else
RxDataReady = 0;
while ( TargetRoom && RxDataReady )
{
// Read the byte
r_cmd(selreg[index], dat0, 13);
length = (dat0[4] & 0x0f) ;
// RETAILMSG(DEBUGMODE, (TEXT("RxIntr : cRXChar = 0x%x \r\n"), cRXChar));
// Finally, we can get byte, update status and save.
if (!pSpiHead->RxDiscard )
{
for(iCount=0; iCount<length; iCount++)
{
*pRxBuffer++ = dat0[5+iCount];
// Do character replacement if parity error detected.
// See if we need to generate an EV_RXFLAG for the received char.
if(dat0[5+iCount] == cEvtChar)//0x0d
{
// RETAILMSG(1, (TEXT("RxIntr : EV_RXFLAG 0x%x\r\n"), cRXChar));
fRXFlag = TRUE;
}
}
(*pBufflen) += length;
}
else
{
// RETAILMSG (1, (TEXT("RXIntr : Dropping byte because now Txing\r\n")));
}
TargetRoom -= length;
RxDataReady = 0;
}
//Clear interrupt pending bit
bit_cmd(CANINTF, selrx[index], 0x00);
bit_cmd(CANINTE, selrx[index], selrx[index]);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// just exit
}
// if we saw one (or more) EVT chars, then generate an event
if ( fRXFlag )
{
EvaluateEventFlag( pSpiHead, EV_RXFLAG );
}
if ( pSpiHead->DroppedBytes )
{
// RETAILMSG (DEBUGMODE, (TEXT("Rx drop %d.\r\n"), pSpiHead->DroppedBytes));
}
RetVal = pSpiHead->DroppedBytes;
pSpiHead->DroppedBytes = 0;
return(RetVal);
}
/*
@doc INTERNAL
@func VOID | DoRxData | Reces next available chunk of RX data.
*
*/
VOID
DoRxData(PHW_INDEP_INFO pSpiHead, BOOL *RxDataAvail, U8 index)
{
ULONG CharIndex = 0;
ULONG RoomLeft = 0;
ULONG TotalLeft = 0;
// It's read data event. Ack the receive,
// unmask the interrupt, get the current data pointer
// and see if data is available.
// RETAILMSG(1, (TEXT("Rx Event\r\n")));
DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("Rx Event\r\n")));
if ( RxRead(pSpiHead) == 0 )
{
// have to leave one byte free.
RoomLeft = RxLength(pSpiHead) - RxWrite(pSpiHead) - 1;
}
else
{
RoomLeft = RxLength(pSpiHead) - RxWrite(pSpiHead);
}
if ( RxRead(pSpiHead) > RxWrite(pSpiHead) )
{
RoomLeft = RxRead(pSpiHead) - RxWrite(pSpiHead) - 1;
}
if ( RoomLeft )
{
pSpiHead->DroppedBytes += HWRxIntrHandler(pSpiHead,
RxBuffWrite(pSpiHead),
&RoomLeft, index);
}
else
{
BYTE TempBuf[16];
RoomLeft = 16;
HWRxIntrHandler(pSpiHead, TempBuf, &RoomLeft, index);
pSpiHead->DroppedBytes += RoomLeft;
// RETAILMSG(1, (TEXT("Tossed %d bytes\r\n"), RoomLeft));
DEBUGMSG (ZONE_WARN|ZONE_READ, (TEXT("Tossed %d bytes\r\n"), RoomLeft));
RoomLeft = 0;
}
// RETAILMSG(1, (TEXT("After HWGetBytes, Fifo(R=%d,W=%d,BA=%d,L=%d) ByteRead=%d\r\n"),
// RxRead(pSpiHead), RxWrite(pSpiHead),
// RxBytesAvail(pSpiHead), RxLength(pSpiHead), RoomLeft));
DEBUGMSG (ZONE_READ,
(TEXT("After HWGetBytes, Fifo(R=%d,W=%d,BA=%d,L=%d) ByteRead=%d\r\n"),
RxRead(pSpiHead), RxWrite(pSpiHead),
RxBytesAvail(pSpiHead), RxLength(pSpiHead), RoomLeft));
pSpiHead->RxBytes += RoomLeft;
RxWrite(pSpiHead) += RoomLeft;
RxWrite(pSpiHead) %= RxLength(pSpiHead);
if ( RoomLeft )
{
*RxDataAvail = TRUE;
}
}
/*
@doc INTERNAL
@func VOID | DoTxData | Sends next available chunk of TX data.
*
*/
VOID
DoTxData(PHW_INDEP_INFO pSpiHead)
{
ULONG Len;
// RETAILMSG(1, (TEXT("DoPutBytes wait for CritSec %x.\r\n"), &(pSpiHead->TxBufferInfo.CS)));
DEBUGMSG (ZONE_WRITE, (TEXT("DoPutBytes wait for CritSec %x.\r\n"),
&(pSpiHead->TxBufferInfo.CS)));
TxEnterCS(pSpiHead);
DEBUGMSG (ZONE_WRITE, (TEXT("DoPutBytes got CritSec %x.\r\n"),
&(pSpiHead->TxBufferInfo.CS)));
// If device was closed from under us, stop transmitting
if ( !pSpiHead->OpenCnt )
{
// RETAILMSG(1, (TEXT("Device closed! Quit transmission!\r\n")));
DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("Device closed! Quit transmission!\r\n")));
DEBUGMSG (ZONE_WRITE,
(TEXT("SpiEventHandler: %d sent up-to-now.\n\r"),
pSpiHead->TxBytesSent));
pSpiHead->TxBufferInfo.Permissions = 0;
pSpiHead->TxBufferInfo.TxCharBuffer = NULL;
pSpiHead->TxBufferInfo.Length = 0;
TxRead(pSpiHead) = 0;
}
//call the hw TX routine to actually transmit some data.
if ( pSpiHead->TxBufferInfo.TxCharBuffer && TxBytesAvail(pSpiHead) )
{
DWORD oldPerm = SetProcPermissions(pSpiHead->TxBufferInfo.Permissions);
// RETAILMSG(1, (TEXT("TxRead = %d, TxLength = %d, TxBytesAvail = %d.\r\n"),
// TxRead(pSpiHead), TxLength(pSpiHead), TxBytesAvail(pSpiHead)));
DEBUGMSG (ZONE_WRITE,
(TEXT("TxRead = %d, TxLength = %d, TxBytesAvail = %d.\r\n"),
TxRead(pSpiHead), TxLength(pSpiHead),
TxBytesAvail(pSpiHead)));
Len = TxBytesAvail(pSpiHead);
// RETAILMSG(1, (TEXT("About to copy %d bytes\r\n"), Len));
DEBUGMSG (ZONE_WRITE, (TEXT("About to copy %d bytes\r\n"), Len));
//
HWTxIntrHandler(pSpiHead, TxBuffRead(pSpiHead), &Len);
// RETAILMSG(1, (TEXT("%d bytes actually copied.\r\n"), Len));
DEBUGMSG (ZONE_WRITE, (TEXT("%d bytes actually copied.\r\n"), Len));
// Update Fifo info
pSpiHead->TxBytes += Len;
pSpiHead->TxBytesSent += Len;
TxRead(pSpiHead) += Len;
// Even if everything was Tx'ed, don't signal TX complete until
// we get transmit interrupt indicating that the data has
// actually been sent. Since few/no UARTS have a way to tell
// how much data remains, we don't bother trying to adjust the
// return length to account for partially completed hardware buffer TX
SetProcPermissions(oldPerm);
}
else
{
// Even if there is nothing left to send, we need to call
// the interrupt handler so that it can clear the
// transmit interrupt
Len = 0;
HWTxIntrHandler(pSpiHead, NULL, &Len);
// RETAILMSG(1, (TEXT("Transmission complete, %d bytes sent\r\n"), Len));
DEBUGMSG (ZONE_WRITE, (TEXT("Transmission complete, %d bytes sent\r\n"), Len));
pSpiHead->TxBufferInfo.Permissions = 0;
pSpiHead->TxBufferInfo.TxCharBuffer = NULL;
pSpiHead->TxBufferInfo.Length = 0;
TxRead(pSpiHead) = 0;
SetEvent(pSpiHead->hTransmitEvent);
}
TxLeaveCS(pSpiHead);
// RETAILMSG(1, (TEXT("DoPutBytes released CritSec: %x.\r\n"), &(pSpiHead->TxBufferInfo.CS)));
DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
(TEXT("DoPutBytes released CritSec: %x.\r\n"),
&(pSpiHead->TxBufferInfo.CS)));
}
//
// @doc OEM
// @func ULONG | GetInterruptType | This function is called
// by the MDD whenever an interrupt occurs. The return code
// is then checked by the MDD to determine which of the four
// interrupt handling routines are to be called.
//
// @rdesc This routine returns a bitmask indicating which interrupts
// are currently pending.
//
INTERRUPT_TYPE
GetInterruptType(
PVOID pHead // Pointer to hardware head
)
{
PHW_INDEP_INFO pSpiHead = (PHW_INDEP_INFO)pHead;
INTERRUPT_TYPE interrupts;
ULONG IntPndVal = 0;
U8 inter=0;
try
{
// r_cmd(CANINTF, (U8*)&IntPndVal, 1);
r_cmd(CANSTAT, &inter, 1);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// RETAILMSG(DEBUGMODE, (TEXT("ACCESS VIOLATION ERROR \r\n")));
IntPndVal = INTR_NONE;
}
if ( inter )
{
if(inter == 0x02)
{
r_cmd(CANINTF, (U8*)&IntPndVal, 1);
if(IntPndVal & INTR_MERRF )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -