1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - library - dsp
3 File: dsp_if.c
4
5 Copyright 2007-2009 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2009-06-04#$
14 $Rev: 10698 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17 #include <twl.h>
18 #include <twl/dsp.h>
19
20 #include <dsp_coff.h>
21 #include "dsp_process.h"
22
23 /*---------------------------------------------------------------------------*
24 Constant Definitions
25 *---------------------------------------------------------------------------*/
26
27 #define reg_CFG_DSP_RST *(vu8*)REG_RST_ADDR
28
29 #define REG_DSP_PCFG_RRIE_MASK (REG_DSP_PCFG_PRIE0_MASK | REG_DSP_PCFG_PRIE1_MASK | REG_DSP_PCFG_PRIE2_MASK)
30 #define REG_DSP_PCFG_RRIE_SHIFT REG_DSP_PCFG_PRIE0_SHIFT
31 #define REG_DSP_PSTS_RCOMIM_SHIFT REG_DSP_PSTS_RCOMIM0_SHIFT
32 #define REG_DSP_PSTS_RRI_SHIFT REG_DSP_PSTS_RRI0_SHIFT
33
34
35 #define DSP_DPRINTF(...) ((void) 0)
36 //#define DSP_DPRINTF OS_TPrintf
37
38 /*---------------------------------------------------------------------------*
39 Type Definitions
40 *---------------------------------------------------------------------------*/
41 typedef struct DSPData
42 {
43 u16 send;
44 u16 reserve1;
45 u16 recv;
46 u16 reserve2;
47 }
48 DSPData;
49
50
51 /*---------------------------------------------------------------------------*
52 Static Variable Definitions
53 *---------------------------------------------------------------------------*/
54 static volatile DSPData *const dspData = (DSPData*)REG_COM0_ADDR;
55
56 /*---------------------------------------------------------------------------*
57 Internal Function Definitions
58 *---------------------------------------------------------------------------*/
59
60 /*---------------------------------------------------------------------------*
61 Name: DSP_PowerOn
62
63 Description: Turns on the DSP and configures it to be in the reset state.
64 You must call DSP_ResetOff() to start the DSP.
65
66 Arguments: None.
67
68 Returns: None.
69 *---------------------------------------------------------------------------*/
DSP_PowerOnCore(void)70 void DSP_PowerOnCore(void) // DSP_Init
71 {
72 SCFG_ResetDSP(); // Confirms reset of DSP block
73 SCFG_SupplyClockToDSP(TRUE); // Power on for DSP block
74 OS_SpinWaitSysCycles(2); // Wait 8 cycles @ 134 MHz
75 SCFG_ReleaseResetDSP(); // Release reset of DSP block
76 DSP_ResetOnCore(); // Set reset of DSP core
77 }
78
79 /*---------------------------------------------------------------------------*
80 Name: DSP_PowerOff
81
82 Description: Turns off the DSP.
83
84 Arguments: None.
85
86 Returns: None.
87 *---------------------------------------------------------------------------*/
DSP_PowerOffCore(void)88 void DSP_PowerOffCore(void) // DSP_End
89 {
90 SCFG_ResetDSP(); // Sets reset of DSP block
91 SCFG_SupplyClockToDSP(FALSE); // Power off for DSP block
92 }
93
94 /*---------------------------------------------------------------------------*
95 Name: DSP_ResetOn
96
97 Description: Resets the DSP.
98
99 Arguments: None.
100
101 Returns: None.
102 *---------------------------------------------------------------------------*/
DSP_ResetOnCore(void)103 void DSP_ResetOnCore(void)
104 {
105 if ((reg_DSP_PCFG & REG_DSP_PCFG_DSPR_MASK) == 0)
106 {
107 reg_DSP_PCFG |= REG_DSP_PCFG_DSPR_MASK;
108 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
109 {
110 }
111 }
112 }
113
114 /*---------------------------------------------------------------------------*
115 Name: DSP_ResetOff
116
117 Description: Starts the DSP from the reset state.
118
119 Arguments: None.
120
121 Returns: None.
122 *---------------------------------------------------------------------------*/
DSP_ResetOffCore(void)123 void DSP_ResetOffCore(void)
124 {
125 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
126 {
127 }
128 DSP_ResetInterfaceCore(); // Initialize DSP-A9IF
129 reg_DSP_PCFG &= ~REG_DSP_PCFG_DSPR_MASK;
130 }
131
132 /*---------------------------------------------------------------------------*
133 Name: DSP_ResetOffEx
134
135 Description: Starts the DSP from the reset state.
136
137 Arguments: bitmap: Bitmap of the reply registers and semaphores that allow interrupts from the DSP to the ARM9.
138
139 Returns: None.
140 *---------------------------------------------------------------------------*/
DSP_ResetOffExCore(u16 bitmap)141 void DSP_ResetOffExCore(u16 bitmap)
142 {
143 SDK_ASSERT(bitmap >= 0 && bitmap <= 7);
144
145 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
146 {
147 }
148 DSP_ResetInterfaceCore(); // Initialize DSP-A9IF
149 reg_DSP_PCFG |= (bitmap) << REG_DSP_PCFG_RRIE_SHIFT;
150 reg_DSP_PCFG &= ~REG_DSP_PCFG_DSPR_MASK;
151 }
152
153 /*---------------------------------------------------------------------------*
154 Name: DSP_ResetInterface
155
156 Description: Initializes the registers.
157 You must call this function when the DSP is reset.
158
159 Arguments: None.
160
161 Returns: None.
162 *---------------------------------------------------------------------------*/
DSP_ResetInterfaceCore(void)163 void DSP_ResetInterfaceCore(void)
164 {
165 if (reg_DSP_PCFG & REG_DSP_PCFG_DSPR_MASK)
166 {
167 u16 dummy;
168 reg_DSP_PCFG &= ~REG_DSP_PCFG_RRIE_MASK;
169 reg_DSP_PSEM = 0;
170 reg_DSP_PCLEAR = 0xFFFF;
171 dummy = dspData[0].recv;
172 dummy = dspData[1].recv;
173 dummy = dspData[2].recv;
174 }
175 }
176
177 /*---------------------------------------------------------------------------*
178 Name: DSP_EnableRecvDataInterrupt
179
180 Description: Enables interrupts for the specified reply register.
181
182 Arguments: dataNo: Reply register number (0-2)
183
184 Returns: None.
185 *---------------------------------------------------------------------------*/
DSP_EnableRecvDataInterruptCore(u32 dataNo)186 void DSP_EnableRecvDataInterruptCore(u32 dataNo)
187 {
188 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
189 reg_DSP_PCFG |= (1 << dataNo) << REG_DSP_PCFG_RRIE_SHIFT;
190 }
191
192 /*---------------------------------------------------------------------------*
193 Name: DSP_DisableRecvDataInterrupt
194
195 Description: Disables interrupts for the specified reply register.
196
197 Arguments: dataNo: Reply register number (0-2)
198
199 Returns: None.
200 *---------------------------------------------------------------------------*/
DSP_DisableRecvDataInterruptCore(u32 dataNo)201 void DSP_DisableRecvDataInterruptCore(u32 dataNo)
202 {
203 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
204 reg_DSP_PCFG &= ~((1 << dataNo) << REG_DSP_PCFG_RRIE_SHIFT);
205 }
206
207 /*---------------------------------------------------------------------------*
208 Name: DSP_SendDataIsEmpty
209
210 Description: Checks whether the DSP has received data for the specified command register.
211
212 Arguments: dataNo: Command register number (0-2)
213
214 Returns: TRUE if the DSP has already received data.
215 *---------------------------------------------------------------------------*/
DSP_SendDataIsEmptyCore(u32 dataNo)216 BOOL DSP_SendDataIsEmptyCore(u32 dataNo)
217 {
218 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
219 return (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RCOMIM_SHIFT)) ? FALSE : TRUE;
220 }
221
222 /*---------------------------------------------------------------------------*
223 Name: DSP_RecvDataIsReady
224
225 Description: Checks whether data was sent from the DSP to the specified reply register.
226
227 Arguments: dataNo: Reply register number (0-2)
228
229 Returns: TRUE if the DSP has sent data.
230 *---------------------------------------------------------------------------*/
DSP_RecvDataIsReadyCore(u32 dataNo)231 BOOL DSP_RecvDataIsReadyCore(u32 dataNo)
232 {
233 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
234 return (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RRI_SHIFT)) ? TRUE : FALSE;
235 }
236
237 /*---------------------------------------------------------------------------*
238 Name: DSP_SendData
239
240 Description: Sends data to the DSP.
241
242 Arguments: dataNo: Command register number (0-2)
243 data: The data to send
244
245 Returns: None.
246 *---------------------------------------------------------------------------*/
DSP_SendDataCore(u32 dataNo,u16 data)247 void DSP_SendDataCore(u32 dataNo, u16 data)
248 {
249 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
250 while (DSP_SendDataIsEmptyCore(dataNo) == FALSE)
251 {
252 }
253 dspData[dataNo].send = data;
254 }
255
256 /*---------------------------------------------------------------------------*
257 Name: DSP_RecvData
258
259 Description: Receives data from the DSP.
260
261 Arguments: dataNo: Reply register number (0-2)
262
263 Returns: The received data.
264 *---------------------------------------------------------------------------*/
DSP_RecvDataCore(u32 dataNo)265 u16 DSP_RecvDataCore(u32 dataNo)
266 {
267 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
268 while (DSP_RecvDataIsReadyCore(dataNo) == FALSE)
269 {
270 }
271 return dspData[dataNo].recv;
272 }
273
274 /*---------------------------------------------------------------------------*
275 Name: DSP_EnableFifoInterrupt
276
277 Description: Enables FIFO interrupts.
278
279 Arguments: type: The cause of the FIFO interrupt
280
281 Returns: None.
282 *---------------------------------------------------------------------------*/
DSP_EnableFifoInterruptCore(DSPFifoIntr type)283 void DSP_EnableFifoInterruptCore(DSPFifoIntr type)
284 {
285 reg_DSP_PCFG |= type;
286 }
287
288 /*---------------------------------------------------------------------------*
289 Name: DSP_DisableFifoInterrupt
290
291 Description: Disables FIFO interrupts.
292
293 Arguments: type: The cause of the FIFO interrupt
294
295 Returns: None.
296 *---------------------------------------------------------------------------*/
DSP_DisableFifoInterruptCore(DSPFifoIntr type)297 void DSP_DisableFifoInterruptCore(DSPFifoIntr type)
298 {
299 reg_DSP_PCFG &= ~type;
300 }
301
302 /*---------------------------------------------------------------------------*
303 Name: DSP_SendFifoEx
304
305 Description: Writes data in the DSP's memory space.
306
307 Arguments: memsel: Memory space in which to write data
308 dest: Address to write to (half-word).
309 If the most-significant 16 bits are set, values must be set in the DMA register in advance.
310
311 src: Data to write
312 size: Length of the data to write (half-word)
313 flags: You can select a write mode other than DSP_FIFO_FLAG_RECV_UNIT_* from DSPFifoFlag
314
315
316 Returns: None.
317 *---------------------------------------------------------------------------*/
DSP_SendFifoExCore(DSPFifoMemSel memsel,u16 dest,const u16 * src,int size,u16 flags)318 void DSP_SendFifoExCore(DSPFifoMemSel memsel, u16 dest, const u16 *src, int size, u16 flags)
319 {
320 OSIntrMode bak = OS_DisableInterrupts();
321 u16 incmode = (u16)((flags & DSP_FIFO_FLAG_DEST_FIX) ? 0 : REG_DSP_PCFG_AIM_MASK);
322
323 reg_DSP_PADR = dest;
324 reg_DSP_PCFG = (u16)((reg_DSP_PCFG & ~(REG_DSP_PCFG_MEMSEL_MASK|REG_DSP_PCFG_AIM_MASK))
325 | memsel | incmode);
326
327 if (flags & DSP_FIFO_FLAG_SRC_FIX)
328 {
329 while (size-- > 0)
330 {
331 while (reg_DSP_PSTS & REG_DSP_PSTS_WFFI_MASK)
332 {
333 }
334 reg_DSP_PDATA = *src;
335 }
336 }
337 else
338 {
339 while (size-- > 0)
340 {
341 while (reg_DSP_PSTS & REG_DSP_PSTS_WFFI_MASK)
342 {
343 }
344 reg_DSP_PDATA = *src++;
345 }
346 }
347 (void)OS_RestoreInterrupts(bak);
348 }
349
350 /*---------------------------------------------------------------------------*
351 Name: DSP_RecvFifoEx
352
353 Description: Reads data from the DSP's memory space.
354
355 Arguments: memsel: Memory space to read data from (other than program memory)
356 dest: Address at which to receive data
357 src: Address from which the data was received (half-word)
358 If the most-significant 16 bits are set, values must be set in the DMA register in advance.
359
360 size: Data size to read (half-word)
361 flags: You can select the read mode from DSPFifoFlag
362
363 Returns: None.
364 *---------------------------------------------------------------------------*/
DSP_RecvFifoExCore(DSPFifoMemSel memsel,u16 * dest,u16 src,int size,u16 flags)365 void DSP_RecvFifoExCore(DSPFifoMemSel memsel, u16* dest, u16 src, int size, u16 flags)
366 {
367 OSIntrMode bak = OS_DisableInterrupts();
368 DSPFifoRecvLength len;
369 u16 incmode = (u16)((flags & DSP_FIFO_FLAG_SRC_FIX) ? 0 : REG_DSP_PCFG_AIM_MASK);
370
371 SDK_ASSERT(memsel != DSP_FIFO_MEMSEL_PROGRAM);
372
373 switch (flags & DSP_FIFO_FLAG_RECV_MASK)
374 {
375 case DSP_FIFO_FLAG_RECV_UNIT_2B:
376 len = DSP_FIFO_RECV_2B;
377 size = 1;
378 break;
379 case DSP_FIFO_FLAG_RECV_UNIT_16B:
380 len = DSP_FIFO_RECV_16B;
381 size = 8;
382 break;
383 case DSP_FIFO_FLAG_RECV_UNIT_32B:
384 len = DSP_FIFO_RECV_32B;
385 size = 16;
386 break;
387 default:
388 len = DSP_FIFO_RECV_CONTINUOUS;
389 break;
390 }
391
392 reg_DSP_PADR = src;
393 reg_DSP_PCFG = (u16)((reg_DSP_PCFG & ~(REG_DSP_PCFG_MEMSEL_MASK|REG_DSP_PCFG_DRS_MASK|REG_DSP_PCFG_AIM_MASK))
394 | memsel | len | incmode | REG_DSP_PCFG_RS_MASK);
395
396 if (flags & DSP_FIFO_FLAG_DEST_FIX)
397 {
398 while (size-- > 0)
399 {
400 while ((reg_DSP_PSTS & REG_DSP_PSTS_RFNEI_MASK) == 0)
401 {
402 }
403 *dest = reg_DSP_PDATA;
404 }
405 }
406 else
407 {
408 while (size-- > 0)
409 {
410 while ((reg_DSP_PSTS & REG_DSP_PSTS_RFNEI_MASK) == 0)
411 {
412 }
413 *dest++ = reg_DSP_PDATA;
414 }
415 }
416 reg_DSP_PCFG &= ~REG_DSP_PCFG_RS_MASK;
417 (void)OS_RestoreInterrupts(bak);
418 }
419
420 /*---------------------------------------------------------------------------*
421 Name: DSP_SetCommandReg
422
423 Description: Writes a value to a command register.
424
425 Arguments: regNo: Command register number (0-2)
426 data: Data
427
428 Returns: None.
429 *---------------------------------------------------------------------------*/
DSP_SetCommandRegCore(u32 regNo,u16 data)430 void DSP_SetCommandRegCore(u32 regNo, u16 data)
431 {
432 SDK_ASSERT(regNo >= 0 && regNo <= 2);
433 dspData[regNo].send = data;
434 }
435
436 /*---------------------------------------------------------------------------*
437 Name: DSP_GetReplyReg
438
439 Description: Reads a value from a reply register.
440
441 Arguments: regNo: Reply register number (0-2)
442
443 Returns: The data read.
444 *---------------------------------------------------------------------------*/
DSP_GetReplyRegCore(u32 regNo)445 u16 DSP_GetReplyRegCore(u32 regNo)
446 {
447 SDK_ASSERT(regNo >= 0 && regNo <= 2);
448 return dspData[regNo].recv;
449 }
450
451 /*---------------------------------------------------------------------------*
452 Name: DSP_SetSemaphore
453
454 Description: Writes a value to the semaphore register for sending notifications from an ARM processor to the DSP.
455
456 Arguments: mask: Value to set
457
458 Returns: None.
459 *---------------------------------------------------------------------------*/
DSP_SetSemaphoreCore(u16 mask)460 void DSP_SetSemaphoreCore(u16 mask)
461 {
462 reg_DSP_PSEM = mask;
463 }
464
465 /*---------------------------------------------------------------------------*
466 Name: DSP_GetSemaphore
467
468 Description: Reads the value of the semaphore register for sending notifications from the DSP to an ARM processor.
469
470 Arguments: None.
471
472 Returns: The value written to the semaphore by the DSP.
473 *---------------------------------------------------------------------------*/
DSP_GetSemaphoreCore(void)474 u16 DSP_GetSemaphoreCore(void)
475 {
476 return reg_DSP_SEM;
477 }
478
479 /*---------------------------------------------------------------------------*
480 Name: DSP_ClearSemaphore
481
482 Description: Clears the value of the semaphore register for sending notifications from the DSP to an ARM processor.
483
484 Arguments: mask: The bits to clear.
485
486 Returns: None.
487 *---------------------------------------------------------------------------*/
DSP_ClearSemaphoreCore(u16 mask)488 void DSP_ClearSemaphoreCore(u16 mask)
489 {
490 reg_DSP_PCLEAR = mask;
491 }
492
493 /*---------------------------------------------------------------------------*
494 Name: DSP_MaskSemaphore
495
496 Description: Sets bits that correspond to interrupts to disable in the semaphore register for sending notifications from the DSP to an ARM processor.
497
498 Arguments: mask: Bits corresponding to interrupts to disable.
499
500 Returns: None.
501 *---------------------------------------------------------------------------*/
DSP_MaskSemaphoreCore(u16 mask)502 void DSP_MaskSemaphoreCore(u16 mask)
503 {
504 reg_DSP_PMASK = mask;
505 }
506
507 /*---------------------------------------------------------------------------*
508 Name: DSP_CheckSemaphoreRequest
509
510 Description: Checks whether there is an interrupt request from the semaphore register.
511
512 Arguments: None.
513
514 Returns: TRUE if there is a request.
515 *---------------------------------------------------------------------------*/
DSP_CheckSemaphoreRequestCore(void)516 BOOL DSP_CheckSemaphoreRequestCore(void)
517 {
518 return (reg_DSP_PSTS & REG_DSP_PSTS_PSEMI_MASK) >> REG_DSP_PSTS_PSEMI_SHIFT;
519 }
520
521
522 #if defined(DSP_SUPPORT_OBSOLETE_LOADER)
523 /*---------------------------------------------------------------------------*
524 * The following shows candidate interfaces for termination because they are considered not to be currently in use
525 *---------------------------------------------------------------------------*/
526
527 /*---------------------------------------------------------------------------*
528 * Below is the old interface using a straight-mapping method
529 *---------------------------------------------------------------------------*/
530
531 /*---------------------------------------------------------------------------*
532 Name: DSPi_MapProcessSlotAsStraight
533
534 Description: Initializes the slot map so the segment number and the WRAM slot number match.
535 (This method is used only with the initial load function that does not have Ex applied.)
536
537 Arguments: context: DSPProcessContext structure
538 slotB: WRAM-B allowed for use for code memory
539 slotC: WRAM-C allowed for use for data memory
540
541 Returns: None.
542 *---------------------------------------------------------------------------*/
DSPi_MapProcessSlotAsStraight(DSPProcessContext * context,int slotB,int slotC)543 static BOOL DSPi_MapProcessSlotAsStraight(DSPProcessContext *context, int slotB, int slotC)
544 {
545 int segment;
546 for (segment = 0; segment < MI_WRAM_B_MAX_NUM; ++segment)
547 {
548 if (context->segmentCode & (1 << segment) != 0)
549 {
550 int slot = segment;
551 if ((slotB & (1 << slot)) == 0)
552 {
553 return FALSE;
554 }
555 context->slotOfSegmentCode[segment] = slot;
556 }
557 }
558 for (segment = 0; segment < MI_WRAM_C_MAX_NUM; ++segment)
559 {
560 if (context->segmentData & (1 << segment) != 0)
561 {
562 int slot = segment;
563 if ((slotC & (1 << slot)) == 0)
564 {
565 return FALSE;
566 }
567 context->slotOfSegmentData[segment] = slot;
568 }
569 }
570 return TRUE;
571 }
572
573 /*---------------------------------------------------------------------------*
574 Name: DSP_LoadFileAuto
575
576 Description: Loads a COFF format DSP program and assigns the necessary WRAM to DSP.
577
578 Arguments: image: COFF file
579
580 Returns: TRUE on success.
581 *---------------------------------------------------------------------------*/
DSP_LoadFileAutoCore(const void * image)582 BOOL DSP_LoadFileAutoCore(const void *image)
583 {
584 // Temporarily convert to a memory file
585 FSFile memfile[1];
586 if(DSPi_CreateMemoryFile(memfile, image))
587 {
588 DSPProcessContext context[1];
589 DSP_InitProcessContext(context, NULL);
590 return DSP_StartupProcess(context, memfile, 0xFF, 0xFF, DSPi_MapProcessSlotAsStraight);
591 }
592 return FALSE;
593 }
594
595
596 #endif
597
598 /*---------------------------------------------------------------------------*
599 End of file
600 *---------------------------------------------------------------------------*/
601