📄 mupdd.c
字号:
// Parameters:
// None
//
// Returns:
// None
//
//------------------------------------------------------------------------------
void MUGPI0IntrThread(void)
{
MU_FUNCTION_ENTRY();
MUGPI0ISRLoop(INFINITE);
MU_FUNCTION_ENTRY();
return;
}
//------------------------------------------------------------------------------
//
// Function: MUReadISRLoop
//
// This function is the interrupt handler that services
// RX (receive) interrupts to the MCU side of the MU.
// It waits for the MU RX interrupt event, and then reads the
// receive registers.
//
// Parameters:
// timeout
// [in] Timeout value while waiting for MU RX interrupt.
//
// Returns:
// None
//
//------------------------------------------------------------------------------
static void MUReadISRLoop(UINT32 timeout)
{
MUShortMessage_c readMessage;
DWORD msr;
UINT8 i;
MU_FUNCTION_ENTRY();
// loop here
while(TRUE)
{
DEBUGMSG (ZONE_INFO, (TEXT("%s: In the read loop\r\n"), __WFUNCTION__));
if (WaitForSingleObject(g_hMURXIntrEvent, timeout) == WAIT_OBJECT_0)
{
// We have received a read interrupt.
// Check status registers to determine how
// many bytes to read.
DEBUGMSG (ZONE_INFO, (TEXT("%s: Interrupt received\r\n"), __WFUNCTION__));
// We check status registers starting at receive
// register 3, counting down. The highest receive
// register that has been signalled indicates the
// number of 32-bit words that are being read from
// the DSP. Reading from the receive register MRRX
// clears the status bit MRFX.
msr = INREG32(&g_pMU->MSR);
if (msr & MUStatusRegField_MRF3)
{
SetEvent(g_hMUReceive3FullEvent);
readMessage.iLength = 4;
readMessage.dwChunk[3] = INREG32(&g_pMU->MRR3);
readMessage.dwChunk[2] = INREG32(&g_pMU->MRR2);
readMessage.dwChunk[1] = INREG32(&g_pMU->MRR1);
readMessage.dwChunk[0] = INREG32(&g_pMU->MRR0);
}
else if (msr & MUStatusRegField_MRF2)
{
SetEvent(g_hMUReceive2FullEvent);
readMessage.iLength = 3;
readMessage.dwChunk[2] = INREG32(&g_pMU->MRR2);
readMessage.dwChunk[1] = INREG32(&g_pMU->MRR1);
readMessage.dwChunk[0] = INREG32(&g_pMU->MRR0);
}
else if (msr & MUStatusRegField_MRF1)
{
SetEvent(g_hMUReceive1FullEvent);
readMessage.iLength = 2;
readMessage.dwChunk[1] = INREG32(&g_pMU->MRR1);
readMessage.dwChunk[0] = INREG32(&g_pMU->MRR0);
}
else if (msr & MUStatusRegField_MRF0)
{
SetEvent(g_hMUReceive0FullEvent);
readMessage.iLength = 1;
readMessage.dwChunk[0] = INREG32(&g_pMU->MRR0);
}
else
{
DEBUGMSG (ZONE_INFO,
(TEXT("%s: Error: Received RX Interrupt, but no receive status bits set.\r\n"), __WFUNCTION__));
}
for (i = 0; i < readMessage.iLength; i++)
{
DEBUGMSG(ZONE_INFO, (TEXT("%s: Read DWORD #%x to DSP: %x\r\n"),
__WFUNCTION__, i, readMessage.dwChunk[i]));
}
// Waiting on a write-enabled handle to a queue.
// This will block if the receive queue is full.
// Block if receive queue is full until the
// application reads from it. During this time, additional
// transmits from the DSP will be put on hold.
WaitForSingleObject(g_hWriteReceiveQueue, INFINITE);
// Now add newly read message to read message queue.
// This will be processed when MUReadFromDSP is called.
if (!WriteMsgQueue(g_hWriteReceiveQueue, &readMessage, sizeof(MUShortMessage_c),
MU_WRITE_TIMEOUT, 0))
{
DEBUGMSG (ZONE_INFO,
(TEXT("%s: Error: Write to receive queue failed! Error message 0x%x\r\n"), __WFUNCTION__, GetLastError()));
}
}
else
{
// Timeout as requested
DEBUGMSG (ZONE_INFO, (TEXT("%s: Time out\r\n"), __WFUNCTION__));
}
// Kernel call to unmask the interrupt so that it can be signalled again.
InterruptDone(g_MURXIntr);
}
MU_FUNCTION_ENTRY();
return;
}
//------------------------------------------------------------------------------
//
// Function: MUWriteISRLoop
//
// This function is the interrupt handler that services
// TX (transmit) interrupts to the MCU side of the MU.
// It writes data to the DSP whenever there is data ready to be
// written and the DSP side receive registers are empty.
//
// Parameters:
// timeout
// [in] Timeout value while waiting for MU RX interrupt.
//
// Returns:
// None
//
//------------------------------------------------------------------------------
static void MUWriteISRLoop(UINT32 timeout)
{
UINT8 i;
MUShortMessage_c writeMessage;
DWORD bytesRead, flags, msr;
BOOL interruptOff; // used to determine if we should return interrupt value
// to off state after waiting for transmit empty
MU_FUNCTION_ENTRY();
// loop here
while(TRUE)
{
DEBUGMSG (ZONE_INFO,
(TEXT("%s: In the write loop, waiting on write message queue\r\n"), __WFUNCTION__));
if (WaitForSingleObject(g_hReadTransmitQueue, timeout) == WAIT_OBJECT_0)
{
// We have data ready to be written to DSP
DEBUGMSG (ZONE_INFO,
(TEXT("%s: Message ready to write in transmit queue.\r\n"), __WFUNCTION__));
// First, check that Transmit registers are empty
// from previous write operations.
if ((INREG32(&g_pMU->MSR) & 0xF00000) != 0xF00000)
{
DEBUGMSG (ZONE_ERROR, (TEXT("%s: Error: MU Transmit registers not empty.\r\n"), __WFUNCTION__));
}
// Read data from queue
if (!ReadMsgQueue(g_hReadTransmitQueue, &writeMessage, sizeof(MUShortMessage_c),
&bytesRead, 10, &flags))
{
DEBUGMSG(ZONE_ERROR, (TEXT("%s: Could not read from write queue!\r\n"),
__WFUNCTION__));
continue;
}
for (i = 0; i < writeMessage.iLength; i++)
{
DEBUGMSG(ZONE_INFO, (TEXT("%s: Writing DWORD #%x to DSP: %x\r\n"),
__WFUNCTION__, i, writeMessage.dwChunk[i]));
}
// Now write data to transmit register
switch (writeMessage.iLength)
{
case 1:
OUTREG32(&g_pMU->MTR0, writeMessage.dwChunk[0]);
if (EXTREG32BF(&g_pMU->MCR, MU_MCR_MTIE0) != 0)
{
// The required transmit empty interrupt is already on.
interruptOff = FALSE;
}
else
{
// The required transmit empty interrupt is off.
// Turn it on and set boolean so that we turn
// it off once we have completed the write.
interruptOff = TRUE;
INSREG32BF(&g_pMU->MCR, MU_MCR_MTIE0, MU_MCR_MTIE0_ENABLE);
}
break;
case 2:
OUTREG32(&g_pMU->MTR0, writeMessage.dwChunk[0]);
OUTREG32(&g_pMU->MTR1, writeMessage.dwChunk[1]);
if (EXTREG32BF(&g_pMU->MCR, MU_MCR_MTIE1) != 0)
{
// The required transmit empty interrupt is already on.
interruptOff = FALSE;
}
else
{
// The required transmit empty interrupt is off.
// Turn it on and set boolean so that we turn
// it off once we have completed the write.
interruptOff = TRUE;
INSREG32BF(&g_pMU->MCR, MU_MCR_MTIE1, MU_MCR_MTIE1_ENABLE);
}
break;
case 3:
OUTREG32(&g_pMU->MTR0, writeMessage.dwChunk[0]);
OUTREG32(&g_pMU->MTR1, writeMessage.dwChunk[1]);
OUTREG32(&g_pMU->MTR2, writeMessage.dwChunk[2]);
if (EXTREG32BF(&g_pMU->MCR, MU_MCR_MTIE2) != 0)
{
// The required transmit empty interrupt is already on.
interruptOff = FALSE;
}
else
{
// The required transmit empty interrupt is off.
// Turn it on and set boolean so that we turn
// it off once we have completed the write.
interruptOff = TRUE;
INSREG32BF(&g_pMU->MCR, MU_MCR_MTIE2, MU_MCR_MTIE2_ENABLE);
}
break;
case 4:
OUTREG32(&g_pMU->MTR0, writeMessage.dwChunk[0]);
OUTREG32(&g_pMU->MTR1, writeMessage.dwChunk[1]);
OUTREG32(&g_pMU->MTR2, writeMessage.dwChunk[2]);
OUTREG32(&g_pMU->MTR3, writeMessage.dwChunk[3]);
if (EXTREG32BF(&g_pMU->MCR, MU_MCR_MTIE3) != 0)
{
// The required transmit empty interrupt is already on.
interruptOff = FALSE;
}
else
{
// The required transmit empty interrupt is off.
// Turn it on and set boolean so that we turn
// it off once we have completed the write.
interruptOff = TRUE;
INSREG32BF(&g_pMU->MCR, MU_MCR_MTIE3, MU_MCR_MTIE3_ENABLE);
}
break;
default:
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Invalid write message length: %d. Discarding message.\r\n"),
__WFUNCTION__, writeMessage.iLength));
continue;
}
// Reset transmit empty event so that we do not get a stale event
// signaled.
ResetEvent(g_hMUTXIntrEvent);
// Kernel call to unmask the interrupt so that it can be signaled again.
// This prevents any stale interrupts from inappropriately
// causing the thread to continue.
InterruptDone(g_MUTXIntr);
// Now wait for transmit empty interrupt (i.e., wait for
// transmitted data to be read) before completing write
// sequence and moving on to next message.
if (WaitForSingleObject(g_hMUTXIntrEvent, timeout) != WAIT_OBJECT_0)
{
// Timeout as requested
DEBUGMSG (ZONE_INFO, (TEXT("%s: Time out\r\n"), __WFUNCTION__));
}
// We have data ready to be written to DSP
DEBUGMSG (ZONE_INFO,
(TEXT("%s: Message ready to write in transmit queue.\r\n"), __WFUNCTION__));
// Turn off transmit empty interrupt since it was not on before.
if (interruptOff)
{
switch (writeMessage.iLength)
{
case 1:
INSREG32BF(&g_pMU->MCR, MU_MCR_MTIE0, MU_MCR_MTIE0_ENABLE);
break;
case 2:
INSREG32BF(&g_pMU->MCR, MU_MCR_MTIE1, MU_MCR_MTIE1_ENABLE);
break;
case 3:
INSREG32BF(&g_pMU->MCR, MU_MCR_MTIE2, MU_MCR_MTIE2_ENABLE);
break;
case 4:
INSREG32BF(&g_pMU->MCR, MU_MCR_MTIE3, MU_MCR_MTIE3_ENABLE);
break;
}
}
// Set event for transmit empty interrupts.
msr = INREG32(&g_pMU->MSR);
if (msr & MUCtrlRegField_MTIE3)
{
SetEvent(g_hMUTransmit3EmptyEvent);
}
if (msr & MUCtrlRegField_MTIE2)
{
SetEvent(g_hMUTransmit2EmptyEvent);
}
if (msr & MUCtrlRegField_MTIE1)
{
SetEvent(g_hMUTransmit1EmptyEvent);
}
if (msr & MUCtrlRegField_MTIE0)
{
SetEvent(g_hMUTransmit0EmptyEvent);
}
}
}
MU_FUNCTION_ENTRY();
return;
}
//------------------------------------------------------------------------------
//
// Function: MUGPI3ISRLoop
//
// This function is the interrupt handler that services
// General Purpose Interrupt 3, signaling an event and
// setting an event associated with the interrupt.
//
// Parameters:
// timeout
// [in] Timeout value while waiting for MU GPI3 interrupt.
//
// Returns:
// None
//
//------------------------------------------------------------------------------
static void MUGPI3ISRLoop(UINT32 timeout)
{
MU_FUNCTION_ENTRY();
// loop here
while(TRUE)
{
DEBUGMSG (ZONE_INFO,
(TEXT("%s: In the loop, waiting on GPI3\r\n"), __WFUNCTION__));
if (WaitForSingleObject(g_hMUGPI3IntrEvent, timeout) != WAIT_OBJECT_0)
{
// Timeout as requested
DEBUGMSG (ZONE_INFO, (TEXT("%s: Time out\r\n"), __WFUNCTION__));
continue;
}
SetEvent(g_hMUGPI3Event);
// Lock access to MU while we reset status bit for GPI3
EnterCriticalSection(&g_csMULock);
INSREG32BF(&g_pMU->MSR, MU_MSR_MGIP3, 1); // Write 1 to clear
LeaveCriticalSection(&g_csMULock);
InterruptDone(g_MUGPI3Intr);
}
}
//------------------------------------------------------------------------------
//
// Function: MUGPI2ISRLoop
//
// This function is the interrupt handler that services
// General Purpose Interrupt 2, signaling an event and
// setting an event associated with the interrupt.
//
// Parameters:
// timeout
// [in] Timeout value while waiting for MU GPI2 interrupt.
//
// Returns:
// None
//
//------------------------------------------------------------------------------
static void MUGPI2ISRLoop(UINT32 timeout)
{
MU_FUNCTION_ENTRY();
// loop here
while(TRUE)
{
DEBUGMSG (ZONE_INFO,
(TEXT("%s: In the loop, waiting on GPI2\r\n"), __WFUNCTION__));
if (WaitForSingleObject(g_hMUGPI2IntrEvent, timeout) !=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -