/*---------------------------------------------------------------------------* Project: TwlSDK - library - dsp File: dsp_if.c Copyright 2007-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2008-09-17#$ $Rev: 8556 $ $Author: okubata_ryoma $ *---------------------------------------------------------------------------*/ #include #include #include #include "dsp_process.h" /*---------------------------------------------------------------------------* Constant Definitions *---------------------------------------------------------------------------*/ #define reg_CFG_DSP_RST *(vu8*)REG_RST_ADDR #define REG_DSP_PCFG_RRIE_MASK (REG_DSP_PCFG_PRIE0_MASK | REG_DSP_PCFG_PRIE1_MASK | REG_DSP_PCFG_PRIE2_MASK) #define REG_DSP_PCFG_RRIE_SHIFT REG_DSP_PCFG_PRIE0_SHIFT #define REG_DSP_PSTS_RCOMIM_SHIFT REG_DSP_PSTS_RCOMIM0_SHIFT #define REG_DSP_PSTS_RRI_SHIFT REG_DSP_PSTS_RRI0_SHIFT #define DSP_DPRINTF(...) ((void) 0) //#define DSP_DPRINTF OS_TPrintf /*---------------------------------------------------------------------------* Type Definitions *---------------------------------------------------------------------------*/ typedef struct DSPData { u16 send; u16 reserve1; u16 recv; u16 reserve2; } DSPData; /*---------------------------------------------------------------------------* Static Variable Definitions *---------------------------------------------------------------------------*/ static volatile DSPData *const dspData = (DSPData*)REG_COM0_ADDR; /*---------------------------------------------------------------------------* Internal Function Definitions *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* Name: DSP_PowerOn Description: Power DSP block on but reset yet. You should call DSP_ResetOff() to boot DSP. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void DSP_PowerOnCore(void) // DSP_Init { SCFG_ResetDSP(); // Confirms reset of DSP block SCFG_SupplyClockToDSP(TRUE); // Power on for DSP block OS_SpinWaitSysCycles(2); // wait 8 cycle @ 134MHz SCFG_ReleaseResetDSP(); // Release reset of DSP block DSP_ResetOnCore(); // Set reset of DSP core } /*---------------------------------------------------------------------------* Name: DSP_PowerOff Description: Power DSP block off. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void DSP_PowerOffCore(void) // DSP_End { SCFG_ResetDSP(); // Sets reset of DSP block SCFG_SupplyClockToDSP(FALSE); // Power off for DSP block } /*---------------------------------------------------------------------------* Name: DSP_ResetOn Description: Reset DSP unless Reset state. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void DSP_ResetOnCore(void) { if ((reg_DSP_PCFG & REG_DSP_PCFG_DSPR_MASK) == 0) { reg_DSP_PCFG |= REG_DSP_PCFG_DSPR_MASK; while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK ) { } } } /*---------------------------------------------------------------------------* Name: DSP_ResetOff Description: Boot DSP if in Reset state. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void DSP_ResetOffCore(void) { while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK ) { } DSP_ResetInterfaceCore(); // Initialize DSP-A9IF reg_DSP_PCFG &= ~REG_DSP_PCFG_DSPR_MASK; } /*---------------------------------------------------------------------------* Name: DSP_ResetOffEx Description: Boot DSP if in Reset state. Arguments: bitmap: Enable interrupt for receive data from DSP bitmap Returns: None. *---------------------------------------------------------------------------*/ void DSP_ResetOffExCore(u16 bitmap) { SDK_ASSERT(bitmap >= 0 && bitmap <= 7); while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK ) { } DSP_ResetInterfaceCore(); // Initialize DSP-A9IF reg_DSP_PCFG |= (bitmap) << REG_DSP_PCFG_RRIE_SHIFT; reg_DSP_PCFG &= ~REG_DSP_PCFG_DSPR_MASK; } /*---------------------------------------------------------------------------* Name: DSP_ResetInterface Description: Resets interface registers. It should be called while in reset state. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void DSP_ResetInterfaceCore(void) { if (reg_DSP_PCFG & REG_DSP_PCFG_DSPR_MASK) { u16 dummy; reg_DSP_PCFG &= ~REG_DSP_PCFG_RRIE_MASK; reg_DSP_PSEM = 0; reg_DSP_PCLEAR = 0xFFFF; dummy = dspData[0].recv; dummy = dspData[1].recv; dummy = dspData[2].recv; } } /*---------------------------------------------------------------------------* Name: DSP_EnableRecvDataInterrupt Description: Enables interrupt for receive data from DSP. Arguments: dataNo: Target data register (0-2) Returns: None. *---------------------------------------------------------------------------*/ void DSP_EnableRecvDataInterruptCore(u32 dataNo) { SDK_ASSERT(dataNo >= 0 && dataNo <= 2); reg_DSP_PCFG |= (1 << dataNo) << REG_DSP_PCFG_RRIE_SHIFT; } /*---------------------------------------------------------------------------* Name: DSP_DisableRecvDataInterrupt Description: Disables interrupt for receive data from DSP. Arguments: dataNo: Target data register (0-2) Returns: None. *---------------------------------------------------------------------------*/ void DSP_DisableRecvDataInterruptCore(u32 dataNo) { SDK_ASSERT(dataNo >= 0 && dataNo <= 2); reg_DSP_PCFG &= ~((1 << dataNo) << REG_DSP_PCFG_RRIE_SHIFT); } /*---------------------------------------------------------------------------* Name: DSP_SendDataIsEmpty Description: Whether DSP has received sending data. Arguments: dataNo: Target data register (0-2) Returns: None. *---------------------------------------------------------------------------*/ BOOL DSP_SendDataIsEmptyCore(u32 dataNo) { SDK_ASSERT(dataNo >= 0 && dataNo <= 2); return (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RCOMIM_SHIFT)) ? FALSE : TRUE; } /*---------------------------------------------------------------------------* Name: DSP_RecvDataIsReady Description: Whether there is sent data from DSP. Arguments: dataNo: Target data register (0-2) Returns: None. *---------------------------------------------------------------------------*/ BOOL DSP_RecvDataIsReadyCore(u32 dataNo) { SDK_ASSERT(dataNo >= 0 && dataNo <= 2); return (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RRI_SHIFT)) ? TRUE : FALSE; } /*---------------------------------------------------------------------------* Name: DSP_SendData Description: Sends data to DSP. Arguments: dataNo: Target data register (0-2) data: Data to send Returns: None. *---------------------------------------------------------------------------*/ void DSP_SendDataCore(u32 dataNo, u16 data) { SDK_ASSERT(dataNo >= 0 && dataNo <= 2); while (DSP_SendDataIsEmptyCore(dataNo) == FALSE) { } dspData[dataNo].send = data; } /*---------------------------------------------------------------------------* Name: DSP_RecvData Description: Receives data from DSP. Arguments: dataNo: Target data register (0-2) Returns: receiving data *---------------------------------------------------------------------------*/ u16 DSP_RecvDataCore(u32 dataNo) { SDK_ASSERT(dataNo >= 0 && dataNo <= 2); while (DSP_RecvDataIsReadyCore(dataNo) == FALSE) { } return dspData[dataNo].recv; } /*---------------------------------------------------------------------------* Name: DSP_EnableFifoInterrupt Description: Enables interrupt for FIFO. Arguments: type: One of DSPFifoIntr Returns: None. *---------------------------------------------------------------------------*/ void DSP_EnableFifoInterruptCore(DSPFifoIntr type) { reg_DSP_PCFG |= type; } /*---------------------------------------------------------------------------* Name: DSP_DisableFifoInterrupt Description: Disables interrupt for FIFO. Arguments: type: One of DSPFifoIntr Returns: None. *---------------------------------------------------------------------------*/ void DSP_DisableFifoInterruptCore(DSPFifoIntr type) { reg_DSP_PCFG &= ~type; } /*---------------------------------------------------------------------------* Name: DSP_SendFifoEx Description: Writes data into DSP memory space. Arguments: memsel: One of DSPFifoMemSel dest: Destination address (in half words). If you want to set high address, ask DSP to set DMA register. src: Data to send size: Data length to send (in half words) flags: bitOR of DSPFifoFlag to specify special mode Returns: None. *---------------------------------------------------------------------------*/ void DSP_SendFifoExCore(DSPFifoMemSel memsel, u16 dest, const u16 *src, int size, u16 flags) { OSIntrMode bak = OS_DisableInterrupts(); u16 incmode = (u16)((flags & DSP_FIFO_FLAG_DEST_FIX) ? 0 : REG_DSP_PCFG_AIM_MASK); reg_DSP_PADR = dest; reg_DSP_PCFG = (u16)((reg_DSP_PCFG & ~(REG_DSP_PCFG_MEMSEL_MASK|REG_DSP_PCFG_AIM_MASK)) | memsel | incmode); if (flags & DSP_FIFO_FLAG_SRC_FIX) { while (size-- > 0) { while (reg_DSP_PSTS & REG_DSP_PSTS_WFFI_MASK) { } reg_DSP_PDATA = *src; } } else { while (size-- > 0) { while (reg_DSP_PSTS & REG_DSP_PSTS_WFFI_MASK) { } reg_DSP_PDATA = *src++; } } (void)OS_RestoreInterrupts(bak); } /*---------------------------------------------------------------------------* Name: DSP_RecvFifoEx Description: Reads data into DSP memory space. Arguments: memsel: One of DSPFifoMemSel without PROGRAM area dest: Data to receive src: Source address (in half words). if you want to set high address, ask DSP to set DMA register. size: Data length to receive (in half words). Ignore unless continuous mode. flags: bitOR of DSPFifoFlag to specify special mode Returns: None. *---------------------------------------------------------------------------*/ void DSP_RecvFifoExCore(DSPFifoMemSel memsel, u16* dest, u16 src, int size, u16 flags) { OSIntrMode bak = OS_DisableInterrupts(); DSPFifoRecvLength len; u16 incmode = (u16)((flags & DSP_FIFO_FLAG_SRC_FIX) ? 0 : REG_DSP_PCFG_AIM_MASK); SDK_ASSERT(memsel != DSP_FIFO_MEMSEL_PROGRAM); switch (flags & DSP_FIFO_FLAG_RECV_MASK) { case DSP_FIFO_FLAG_RECV_UNIT_2B: len = DSP_FIFO_RECV_2B; size = 1; break; case DSP_FIFO_FLAG_RECV_UNIT_16B: len = DSP_FIFO_RECV_16B; size = 8; break; case DSP_FIFO_FLAG_RECV_UNIT_32B: len = DSP_FIFO_RECV_32B; size = 16; break; default: len = DSP_FIFO_RECV_CONTINUOUS; break; } reg_DSP_PADR = src; reg_DSP_PCFG = (u16)((reg_DSP_PCFG & ~(REG_DSP_PCFG_MEMSEL_MASK|REG_DSP_PCFG_DRS_MASK|REG_DSP_PCFG_AIM_MASK)) | memsel | len | incmode | REG_DSP_PCFG_RS_MASK); if (flags & DSP_FIFO_FLAG_DEST_FIX) { while (size-- > 0) { while ((reg_DSP_PSTS & REG_DSP_PSTS_RFNEI_MASK) == 0) { } *dest = reg_DSP_PDATA; } } else { while (size-- > 0) { while ((reg_DSP_PSTS & REG_DSP_PSTS_RFNEI_MASK) == 0) { } *dest++ = reg_DSP_PDATA; } } reg_DSP_PCFG &= ~REG_DSP_PCFG_RS_MASK; (void)OS_RestoreInterrupts(bak); } /*---------------------------------------------------------------------------* Name: DSP_SetCommandReg Description: Sets command register to signal to DSP. Arguments: data: Data Returns: None. *---------------------------------------------------------------------------*/ void DSP_SetCommandRegCore(u32 regNo, u16 data) { SDK_ASSERT(regNo >= 0 && regNo <= 2); dspData[regNo].send = data; } /*---------------------------------------------------------------------------* Name: DSP_GetReplyReg Description: Gets reply register to be recieved from DSP. Arguments: None. Returns: data. *---------------------------------------------------------------------------*/ u16 DSP_GetReplyRegCore(u32 regNo) { SDK_ASSERT(regNo >= 0 && regNo <= 2); return dspData[regNo].recv; } /*---------------------------------------------------------------------------* Name: DSP_SetSemaphore Description: Sets semaphore to signal to DSP. NOTE: received semaphore is individual register. Arguments: mask: Bit mask to set Returns: None. *---------------------------------------------------------------------------*/ void DSP_SetSemaphoreCore(u16 mask) { reg_DSP_PSEM = mask; } /*---------------------------------------------------------------------------* Name: DSP_GetSemaphore Description: Gets semaphore to be recieved from DSP. NOTE: sending semaphore is individual register. Arguments: None. Returns: Bit mask is set by DSP. *---------------------------------------------------------------------------*/ u16 DSP_GetSemaphoreCore(void) { return reg_DSP_SEM; } /*---------------------------------------------------------------------------* Name: DSP_ClearSemaphore Description: Clears semaphore to be recieved from DSP. Arguments: mask: Bit mask to clear Returns: None. *---------------------------------------------------------------------------*/ void DSP_ClearSemaphoreCore(u16 mask) { reg_DSP_PCLEAR = mask; } /*---------------------------------------------------------------------------* Name: DSP_MaskSemaphore Description: Masks semaphore to interrupt to ARM9. Arguments: mask: Bit mask to disable to interrupt Returns: None. *---------------------------------------------------------------------------*/ void DSP_MaskSemaphoreCore(u16 mask) { reg_DSP_PMASK = mask; } /*---------------------------------------------------------------------------* Name: DSP_CheckSemaphoreRequest Description: Whether there is requested interrupt by semaphore Arguments: None. Returns: TRUE if requested. *---------------------------------------------------------------------------*/ BOOL DSP_CheckSemaphoreRequestCore(void) { return (reg_DSP_PSTS & REG_DSP_PSTS_PSEMI_MASK) >> REG_DSP_PSTS_PSEMI_SHIFT; } #if defined(DSP_SUPPORT_OBSOLETE_LOADER) /*---------------------------------------------------------------------------* * The following shows candidate interfaces for termination because they are considered not to be currently in use *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* * Below is the old interface using a straight-mapping method *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* Name: DSPi_MapProcessSlotAsStraight Description: Initializes the slot map so the segment number and the WRAM slot number match. (This method is used only with the initial load function that does not have Ex applied) Arguments: context: DSPProcessContext structure slotB: WRAM-B allowed for use for code memory slotC: WRAM-C allowed for use for data memory Returns: None. *---------------------------------------------------------------------------*/ static BOOL DSPi_MapProcessSlotAsStraight(DSPProcessContext *context, int slotB, int slotC) { int segment; for (segment = 0; segment < MI_WRAM_B_MAX_NUM; ++segment) { if (context->segmentCode & (1 << segment) != 0) { int slot = segment; if ((slotB & (1 << slot)) == 0) { return FALSE; } context->slotOfSegmentCode[segment] = slot; } } for (segment = 0; segment < MI_WRAM_C_MAX_NUM; ++segment) { if (context->segmentData & (1 << segment) != 0) { int slot = segment; if ((slotC & (1 << slot)) == 0) { return FALSE; } context->slotOfSegmentData[segment] = slot; } } return TRUE; } /*---------------------------------------------------------------------------* Name: DSP_LoadFileAuto Description: Loads a COFF format DSP program and assigns the necessary WRAM to DSP Arguments: image: Coff file Returns: TRUE if success. *---------------------------------------------------------------------------*/ BOOL DSP_LoadFileAutoCore(const void *image) { // Temporarily convert to a memory file FSFile memfile[1]; if(DSPi_CreateMemoryFile(memfile, image)) { DSPProcessContext context[1]; DSP_InitProcessContext(context, NULL); return DSP_StartupProcess(context, memfile, 0xFF, 0xFF, DSPi_MapProcessSlotAsStraight); } return FALSE; } #endif /*---------------------------------------------------------------------------* End of file *---------------------------------------------------------------------------*/