📄 ddk_sdma.c
字号:
//
//-----------------------------------------------------------------------------
BOOL SdmaDealloc(void)
{
// Unmap host shared region
if (g_pHostSharedUA)
{
MmUnmapIoSpace(g_pHostSharedUA, BSPSdmaGetSharedSize());
g_pHostSharedUA = NULL;
g_pHostSharedPA = NULL;
}
// Unmap peripheral registers
if (g_pSDMA)
{
MmUnmapIoSpace(g_pSDMA, sizeof(CSP_SDMA_REGS));
g_pSDMA = NULL;
}
if (g_hSdmaMutex)
{
CloseHandle(g_hSdmaMutex);
g_hSdmaMutex = NULL;
}
if (g_hAcrMutex)
{
CloseHandle(g_hAcrMutex);
g_hAcrMutex = NULL;
}
return TRUE;
}
//-----------------------------------------------------------------------------
//
// Function: SdmaWritePM
//
// This function uses the channel 0 boot code to write code to the
// SDMA's internal memory. This function can be used to load SDMA scripts
// from the host memory into the SDMA's RAM.
//
// Parameters:
// srcAddrPA
// [in] - Physical source address for data to be written into SDMA.
//
// dstAddrPM
// [in] - Physical destination address within SDMA program memory
// into which the data will be written.
//
// count
// [in] - Number of data bytes to be written into the SDAM.
//
// Returns:
// Returns TRUE.
//
//-----------------------------------------------------------------------------
static BOOL SdmaWritePM(UINT32 srcAddrPA, UINT32 dstAddrPM, UINT16 count)
{
BOOL rc = FALSE;
// Request lock
SdmaLockCtrlChan();
// Configure chan 0 buffer descriptor
g_pHostSharedUA->chan0BufDesc.mode =
CSP_BITFVAL(SDMA_MODE_COMMAND, SDMA_CMD_C0_SET_PM) |
CSP_BITFVAL(SDMA_MODE_EXT, SDMA_MODE_EXT_USED) |
CSP_BITFVAL(SDMA_MODE_ERROR, SDMA_MODE_ERROR_NOTFOUND) |
CSP_BITFVAL(SDMA_MODE_INTR, SDMA_MODE_INTR_NOSEND) |
CSP_BITFVAL(SDMA_MODE_CONT, SDMA_MODE_CONT_END) |
CSP_BITFVAL(SDMA_MODE_WRAP, SDMA_MODE_WRAP_WRAP2FIRST) |
CSP_BITFVAL(SDMA_MODE_DONE, SDMA_MODE_DONE_NOTREADY) |
CSP_BITFVAL(SDMA_MODE_COUNT, count / 2);
g_pHostSharedUA->chan0BufDesc.srcAddrPA = srcAddrPA;
g_pHostSharedUA->chan0BufDesc.destAddrPA = dstAddrPM;
// Start the channel 0 script
if (!DDKSdmaStartChan(0))
{
ERRORMSG(1, (_T("Chan 0 cannot be started!\r\n")));
goto cleanUp;
}
// Wait for script to complete
while (SdmaGetChanStatus(0))
{
// Give up the CPU
Sleep(0);
}
// Make sure chan 0 buffer descriptor was processed
if (CSP_BITFEXT(g_pHostSharedUA->chan0BufDesc.mode, SDMA_MODE_DONE)
== SDMA_MODE_DONE_NOTREADY)
{
ERRORMSG(1, (_T("Chan 0 buffer descriptor not processed!\r\n")));
goto cleanUp;
}
// Make sure chan 0 buffer descriptor did not incur error
if (CSP_BITFEXT(g_pHostSharedUA->chan0BufDesc.mode, SDMA_MODE_ERROR)
== SDMA_MODE_ERROR_FOUND)
{
ERRORMSG(1, (_T("Chan 0 buffer descriptor incurred error!\r\n")));
goto cleanUp;
}
rc = TRUE;
cleanUp:
SdmaUnlockCtrlChan();
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: SdmaWriteChanContext
//
// This function uses the channel 0 boot code to load a channel context into
// the SDMA's internal memory reserved for the context page area.
//
// Parameters:
// chan
// [in] - Virtual channel whose context will be loaded.
//
// srcAddrPA
// [in] - Physical source address for context to be written into SDMA.
//
// Returns:
// Returns TRUE.
//
//-----------------------------------------------------------------------------
static BOOL SdmaWriteChanContext(UINT8 chan, UINT32 srcAddrPA)
{
BOOL rc = FALSE;
// Configure chan 0 buffer descriptor
g_pHostSharedUA->chan0BufDesc.mode =
CSP_BITFVAL(SDMA_MODE_COMMAND, CMD_SETCTX(chan)) |
CSP_BITFVAL(SDMA_MODE_EXT, SDMA_MODE_EXT_UNUSED) |
CSP_BITFVAL(SDMA_MODE_ERROR, SDMA_MODE_ERROR_NOTFOUND) |
CSP_BITFVAL(SDMA_MODE_INTR, SDMA_MODE_INTR_NOSEND) |
CSP_BITFVAL(SDMA_MODE_CONT, SDMA_MODE_CONT_END) |
CSP_BITFVAL(SDMA_MODE_WRAP, SDMA_MODE_WRAP_WRAP2FIRST) |
CSP_BITFVAL(SDMA_MODE_DONE, SDMA_MODE_DONE_NOTREADY) |
CSP_BITFVAL(SDMA_MODE_COUNT, sizeof(SDMA_CHANNEL_CONTEXT) / 4);
g_pHostSharedUA->chan0BufDesc.srcAddrPA = srcAddrPA;
// Start the channel 0 script
if (!DDKSdmaStartChan(0))
{
ERRORMSG(1, (_T("Chan 0 cannot be started!\r\n")));
goto cleanUp;
}
// Wait for script to complete
while (SdmaGetChanStatus(0))
{
// Give up the CPU
Sleep(0);
}
// Make sure chan 0 buffer descriptor was processed
if (CSP_BITFEXT(g_pHostSharedUA->chan0BufDesc.mode, SDMA_MODE_DONE)
== SDMA_MODE_DONE_NOTREADY)
{
ERRORMSG(1, (_T("Chan 0 buffer descriptor not processed!\r\n")));
goto cleanUp;
}
// Make sure chan 0 buffer descriptor did not incur error
if (CSP_BITFEXT(g_pHostSharedUA->chan0BufDesc.mode, SDMA_MODE_ERROR)
== SDMA_MODE_ERROR_FOUND)
{
ERRORMSG(1, (_T("Chan 0 buffer descriptor incurred error!\r\n")));
goto cleanUp;
}
rc = TRUE;
cleanUp:
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: SdmaSetChanOverride
//
// This function configures the override bits for a specified channel.
//
// Parameters:
// chan
// [in] - Channel for which override bits will be set.
//
// bHostOvr
// [in] - Specifies if the HO (Host Override) bit is set.
//
// bEventOvr
// [in] - Specifies if the EO (Event Override) bit is set.
//
// bDspOvr
// [in] - Specifies if the DO (DSP Override) bit is set.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
static void SdmaSetChanOverride(UINT8 chan, BOOL bHostOvr,
BOOL bEventOvr, BOOL bDspOvr)
{
UINT32 oldOvr, newOvr;
// Use interlocked function to update override registers
do
{
oldOvr = INREG32(&g_pSDMA->HOSTOVR);
newOvr = (oldOvr & (~CHAN_MASK(chan))) | (bHostOvr << chan);
} while (InterlockedTestExchange(&g_pSDMA->HOSTOVR,
oldOvr, newOvr) != oldOvr);
do
{
oldOvr = INREG32(&g_pSDMA->EVTOVR);
newOvr = (oldOvr & (~CHAN_MASK(chan))) | (bEventOvr << chan);
} while (InterlockedTestExchange(&g_pSDMA->EVTOVR,
oldOvr, newOvr) != oldOvr);
do
{
oldOvr = INREG32(&g_pSDMA->DSPOVR);
newOvr = (oldOvr & (~CHAN_MASK(chan))) | (bDspOvr << chan);
} while (InterlockedTestExchange(&g_pSDMA->DSPOVR,
oldOvr, newOvr) != oldOvr);
}
//-----------------------------------------------------------------------------
//
// Function: SdmaSetChanPriority
//
// This function configures the priority for a specified channel.
//
// Parameters:
// chan
// [in] - Channel for which the priority will be set.
//
// priority
// [in] - Priority assigned to the channel. Possible priority
// values are 0-7 with 7 being the highest possible priority.
// A channel assigned priority 0 will be prevented from running.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
static void SdmaSetChanPriority(UINT8 chan, UINT8 priority)
{
OUTREG32(&g_pSDMA->CHNPRI[chan], priority);
}
//-----------------------------------------------------------------------------
//
// Function: SdmaGetChanStatus
//
// This function reads the status the specified channel.
//
// Parameters:
// chan
// [in] - Virtual channel to for which status will be read.
//
// Returns:
// Returns TRUE if the specified channel is enabled (HE bit set),
// else returns FALSE (HE bit clear).
//
//-----------------------------------------------------------------------------
static BOOL SdmaGetChanStatus(UINT8 chan)
{
return (INREG32(&g_pSDMA->STOP_STAT) & CHAN_MASK(chan)) ? TRUE : FALSE;
}
//-----------------------------------------------------------------------------
//
// Function: SdmaFindUnusedChan
//
// This function searches the SDMA channel control blocks to find a virtual
// channel that is currently not in use and is available for a handling
// a peripheral-to-memory, memory-to-peripheral, or memory-to-memory
// trasfer.
//
// Parameters:
// priority
// [in] - Priority that will be assigned to unused channel to
// claim it as used.
//
// Returns:
// Returns virtual channel ID if an available virtual channel is found,
// otherwise returns 0.
//
//-----------------------------------------------------------------------------
static UINT8 SdmaFindUnusedChan(UINT8 priority)
{
UINT8 chan;
// Walk the CCB to find available virtual channel (channel 0 is reserved)
for (chan = 1; chan < SDMA_NUM_CHANNELS; chan++)
{
// Check channel status for availability
if (INREG32(&g_pSDMA->CHNPRI[chan]) == SDMA_CHNPRI_CHNPRI_DISABLE)
{
// Use interlocked call to safely update CHNPRI register which
// is a shared resource
if (InterlockedTestExchange(&g_pSDMA->CHNPRI[chan],
SDMA_CHNPRI_CHNPRI_DISABLE, priority)
== SDMA_CHNPRI_CHNPRI_DISABLE)
{
break;
}
}
}
if (chan >= SDMA_NUM_CHANNELS)
{
ERRORMSG(1, (_T("No unused channel found!\r\n")));
chan = 0;
}
return chan;
}
//-----------------------------------------------------------------------------
//
// Function: SdmaLockCtrlChan
//
// This function locks the SDMA control channel (channel 0) to provide
// safe access to the control channel shared resources.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
static void SdmaLockCtrlChan(void)
{
WaitForSingleObject(g_hSdmaMutex, INFINITE);
OUTREG32(&g_pSDMA->CHNPRI[0], SDMA_CHNPRI_CHNPRI_HIGHEST);
}
//-----------------------------------------------------------------------------
//
// Function: SdmaUnlockCtrlChan
//
// This function unlocks the SDMA control channel (channel 0).
//
// Parameters:
// None.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
static void SdmaUnlockCtrlChan(void)
{
OUTREG32(&g_pSDMA->CHNPRI[0], SDMA_CHNPRI_CHNPRI_DISABLE);
ReleaseMutex(g_hSdmaMutex);
}
//-----------------------------------------------------------------------------
//
// Function: SdmaValidChan
//
// This function determines if a channel is valid and configured properly
// for allocation and configuration of buffer descriptors.
//
// Parameters:
// chan
// [in] - Virtual channel to for which status will be read.
//
// Returns:
// Returns TRUE if the specified channel is valid, otherwise
// returns FALSE.
//
//-----------------------------------------------------------------------------
static BOOL SdmaValidChan(UINT8 chan)
{
BOOL rc = FALSE;
// Validate channel parameter
if (chan <= 0 || chan >= SDMA_NUM_CHANNELS)
{
ERRORMSG(1, (_T("Invalid channel!\r\n")));
goto cleanUp;
}
// Check if channel has been previously opened
if (INREG32(&g_pSDMA->CHNPRI[chan]) == SDMA_CHNPRI_CHNPRI_DISABLE)
{
ERRORMSG(1, (_T("Channel not opened!\r\n")));
goto cleanUp;
}
rc = TRUE;
cleanUp:
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -