1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - demos - CTRDG - backup-1
3   File:     main.c
4 
5   Copyright 2008 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:: $
14   $Rev: $
15   $Author: $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nitro.h>
19 
20 /* Routine for screen rendering */
21 #include "draw.h"
22 
23 /* ****************************************************************************/
24 static  async_task_busy = FALSE;       // TRUE when a separate task is running
25 
26 // Insert data here because it is global, and send to command
27 CTRDGTaskInfo CTRDG_TaskData;
28 
29 u32     TaskBusyCallback(CTRDGTaskInfo * p);
30 u32     ReadCallback(CTRDGTaskInfo * p);
31 //---------------------------------------------------------------------------
32 static void InitBackupAccess(void);
33 static void TestBackupAccess(void);
34 static void SelectDevice(void);
35 
36 u16     sec_num = 1;                   // 0�`16
37 u8      dst_buf[4096];
38 
39 // Key information
40 u16     Trg;
41 u16     Cont;
42 u16     keyData;
43 
44 BOOL    sram_flag = FALSE;             // TRUE for SRAM
45 BOOL    flash512k_flag = FALSE;        // TRUE for FLASH512K
46 BOOL    flash1m_flag = FALSE;          // TRUE for FLASH1M
47 BOOL    nocommond_flag = FALSE;        // TRUE if the specified command is not on the device
48 BOOL    async_flag = FALSE;            // TRUE if in asynchronous mode
49 /* Sample demo function  **********************************************************/
TaskBusyCallback(CTRDGTaskInfo * p)50 u32 TaskBusyCallback(CTRDGTaskInfo * p)
51 {
52     async_task_busy = FALSE;
53     if (p->result != 0)
54         OS_TPrintf("error\n");
55     return 1;
56 }
57 
ReadCallback(CTRDGTaskInfo * p)58 u32 ReadCallback(CTRDGTaskInfo * p)
59 {
60     (void)p;
61     async_task_busy = FALSE;
62     OS_TPrintf("Read : sector%d = %s\n", sec_num, dst_buf);
63     ClearFrame(RGB555_BLACK);
64     return 1;
65 }
66 
67 /*---------------------------------------------------------------------------*
68   Name:         VBlankIntr
69 
70   Description:  V-Blank callback.
71 
72   Arguments:    None.
73 
74   Returns:      None.
75  *---------------------------------------------------------------------------*/
VBlankIntr(void)76 static void VBlankIntr(void)
77 {
78     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
79 }
80 
81 /*---------------------------------------------------------------------------*
82   Name:         InitApp
83 
84   Description:  OS and other initializations of basic parts of the application.
85 
86   Arguments:    None.
87 
88   Returns:      None.
89  *---------------------------------------------------------------------------*/
InitApp(void)90 static void InitApp(void)
91 {
92     void   *tmp;
93     OSHeapHandle hh;
94 
95     /* OS initialization */
96     OS_Init();
97     OS_InitThread();
98     OS_InitTick();
99     /* Arena initialization */
100     tmp = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
101     OS_SetArenaLo(OS_ARENA_MAIN, tmp);
102     hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
103     if (hh < 0)
104         OS_Panic("ARM9: Fail to create heap...\n");
105     hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
106     /* Enable interrupts */
107     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
108     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
109     (void)OS_EnableIrq();
110 }
111 
112 /*---------------------------------------------------------------------------*
113   Name:         NitroMain
114 
115   Description:  Main entry point.
116 
117   Arguments:    None.
118 
119   Returns:      None.
120  *---------------------------------------------------------------------------*/
NitroMain(void)121 void NitroMain(void)
122 {
123     /* Sample application initialization */
124     InitApp();
125 
126     InitBackupAccess();
127 
128     OS_TPrintf("start test\n");
129 
130     TestBackupAccess();
131 
132 }
133 
InitBackupAccess(void)134 void InitBackupAccess(void)
135 {
136     CTRDG_Init();
137     CTRDG_Enable(TRUE);
138     InitDraw();
139 
140     /* Device identified and default settings */
141     SelectDevice();
142 }
143 
TestBackupAccess(void)144 void TestBackupAccess(void)
145 {
146     u32     result = TRUE;
147     u32     offset = 0;
148     u8      src_buf[4096];
149     u8      src_buf2[4096];
150     u32     size = 4096;
151     u16     i;
152 
153     MI_CpuClear8(dst_buf, size);
154     MI_CpuClear8(src_buf, size);
155     MI_CpuClear8(src_buf2, size);
156     MI_CpuCopy8("Write Sector", src_buf, 13);
157     MI_CpuCopy8("Write & Verify", src_buf2, 14);
158 
159     if (sram_flag)
160         offset = CTRDG_AGB_SRAM_ADR;
161     ClearFrame(RGB555_BLACK);
162 
163     while (1)
164     {
165         DrawBegin();
166         //---- Read pad data
167         keyData = PAD_Read();
168         keyData = PAD_Read();
169         Trg = (u16)(keyData & (keyData ^ Cont));
170         Cont = keyData;
171 
172         /* String display */
173         DrawText(10, 40, "A : Write");
174         DrawText(10, 50, "B : Erase");
175         DrawText(10, 60, "X : Read");
176         DrawText(10, 70, "Y : Write & Verify");
177         DrawText(10, 80, "UP    : Add SectorNo or offset");
178         DrawText(10, 90, "DOWN  : Sub SectorNo or offset");
179         DrawText(10, 100, "START : change Async/Sync Mode");
180 
181         if (!async_task_busy)
182         {
183             // Write with A
184             if (Trg == PAD_BUTTON_A)
185             {
186                 if (async_flag)
187                 {
188                     async_task_busy = TRUE;
189                     if (!sram_flag)
190                     {
191                         CTRDG_WriteAgbFlashSectorAsync(sec_num, src_buf, TaskBusyCallback);
192                     }
193                     else
194                     {
195                         CTRDG_WriteAgbSramAsync(offset, src_buf, size, TaskBusyCallback);
196                     }
197                 }
198                 else
199                 {
200                     if (!sram_flag)
201                     {
202                         result = CTRDG_WriteAgbFlashSector(sec_num, src_buf);
203                         if (result != 0)
204                             OS_TPrintf("error : Write\n");
205                     }
206                     else
207                     {
208                         CTRDG_WriteAgbSram(offset, src_buf, size);
209                     }
210                 }
211                 OS_TPrintf("Write sector%d\n", sec_num);
212             }
213             // Erase with B
214             else if (Trg == PAD_BUTTON_B)
215             {
216                 if (async_flag)
217                 {
218                     async_task_busy = TRUE;
219                     if (!sram_flag)
220                     {
221                         CTRDG_EraseAgbFlashSectorAsync(sec_num, TaskBusyCallback);
222                     }
223                     else
224                     {
225                         nocommond_flag = TRUE;
226                         ClearFrame(RGB555_BLACK);
227                         async_task_busy = FALSE;
228                     }
229                 }
230                 else
231                 {
232                     if (!sram_flag)
233                     {
234                         result = CTRDG_EraseAgbFlashSector(sec_num);
235                     }
236                     else
237                     {
238                         nocommond_flag = TRUE;
239                         ClearFrame(RGB555_BLACK);
240                         result = 0;
241                     }
242                     if (result != 0)
243                         OS_TPrintf("error : Erase\n");
244                 }
245                 OS_TPrintf("Erase : sector%d\n", sec_num);
246             }
247             // Read with X
248             else if (Trg == PAD_BUTTON_X)
249             {
250                 nocommond_flag = FALSE;
251                 if (async_flag)
252                 {
253                     async_task_busy = TRUE;
254                     if (!sram_flag)
255                     {
256                         CTRDG_ReadAgbFlashAsync(sec_num, offset, dst_buf, size, ReadCallback);
257                     }
258                     else
259                     {
260                         CTRDG_ReadAgbSramAsync(offset, (void *)dst_buf, size, ReadCallback);
261                     }
262                 }
263                 else
264                 {
265                     if (!sram_flag)
266                     {
267                         CTRDG_ReadAgbFlash(sec_num, offset, dst_buf, size);
268                     }
269                     else
270                     {
271                         CTRDG_ReadAgbSram(offset, (void *)dst_buf, size);
272                     }
273                     OS_TPrintf("Read : sector%d = %s\n", sec_num, dst_buf);
274                     ClearFrame(RGB555_BLACK);
275                 }
276             }
277             // WriteAndVerify with Y
278             else if (Trg == PAD_BUTTON_Y)
279             {
280                 if (async_flag)
281                 {
282                     async_task_busy = TRUE;
283                     if (!sram_flag)
284                     {
285                         CTRDG_WriteAndVerifyAgbFlashAsync(sec_num, src_buf2, size,
286                                                           TaskBusyCallback);
287                     }
288                     else
289                     {
290                         CTRDG_WriteAndVerifyAgbSramAsync(offset, src_buf2, size, TaskBusyCallback);
291                     }
292                 }
293                 else
294                 {
295                     if (!sram_flag)
296                     {
297                         result = CTRDG_WriteAndVerifyAgbFlash(sec_num, src_buf2, size);
298                     }
299                     else
300                     {
301                         result = CTRDG_WriteAndVerifyAgbSram(offset, src_buf2, size);
302                     }
303                     if (result != 0)
304                         OS_TPrintf("error : WriteAndVerify\n");
305                 }
306                 OS_TPrintf("Write sector%d\n", sec_num);
307             }
308             // Use the above key to increase the accessed SectorNo and offset
309             else if (Trg == PAD_KEY_UP)
310             {
311                 if (flash512k_flag)
312                 {
313                     if (sec_num < 15)
314                         sec_num++;
315                 }
316                 else if (flash1m_flag)
317                 {
318                     if (sec_num < 31)
319                         sec_num++;
320                 }
321                 else if (sram_flag)
322                 {
323                     if (offset <= 167800832)
324                         offset += 4096;
325                 }
326 
327                 ClearFrame(RGB555_BLACK);
328             }
329             // Use the lower key to decrease the accessed SectorNo and offset
330             else if (Trg == PAD_KEY_DOWN)
331             {
332                 if (flash512k_flag || flash1m_flag)
333                 {
334                     if (sec_num > 0)
335                         sec_num--;
336                 }
337                 else if (sram_flag)
338                 {
339                     if (offset >= 167776256)
340                         offset -= 4096;
341                 }
342                 ClearFrame(RGB555_BLACK);
343             }
344             // Use the right key to increase the accessed Size
345             else if (Cont == PAD_KEY_RIGHT)
346             {
347                 if (size <= 4088)
348                     size += 8;
349                 OS_TPrintf("Access Size = %d\n", size);
350                 ClearFrame(RGB555_BLACK);
351             }
352             // Use the left key to decrease the accessed Size
353             else if (Cont == PAD_KEY_LEFT)
354             {
355                 if (size >= 8)
356                     size -= 8;
357                 OS_TPrintf("Access Size = %d\n", size);
358                 ClearFrame(RGB555_BLACK);
359             }
360             // Use START to switch between asynchronous and synchronous modes
361             else if (Trg == PAD_BUTTON_START)
362             {
363                 async_flag = !async_flag;
364                 ClearFrame(RGB555_BLACK);
365             }
366             // Use SELECT to Verify
367             else if (Trg == PAD_BUTTON_SELECT)
368             {
369                 if (async_flag)
370                 {
371                     async_task_busy = TRUE;
372                     if (!sram_flag)
373                     {
374                         CTRDG_VerifyAgbFlashAsync(sec_num, src_buf2, size, TaskBusyCallback);
375                     }
376                     else
377                     {
378                         offset = CTRDG_AGB_SRAM_ADR;
379                         CTRDG_VerifyAgbSramAsync(offset, src_buf2, size, TaskBusyCallback);
380                     }
381                 }
382                 else
383                 {
384                     if (!sram_flag)
385                     {
386                         result = CTRDG_VerifyAgbFlash(sec_num, src_buf2, size);
387                     }
388                     else
389                     {
390                         offset = CTRDG_AGB_SRAM_ADR;
391                         result = CTRDG_VerifyAgbSram(offset, src_buf2, size);
392                     }
393                     if (result != 0)
394                         OS_TPrintf("error : Verify\n");
395                 }
396                 OS_TPrintf("Verify sector%d\n", sec_num);
397             }
398             // Use L to set the thread priority to 0
399             else if (Trg == PAD_BUTTON_L)
400             {
401                 u32     priority = 0;
402                 CTRDG_SetTaskThreadPriority(priority);
403                 OS_TPrintf("Task Thread Priority = %d\n", priority);
404             }
405         }
406         /* String display */
407         if (flash512k_flag || flash1m_flag)
408         {
409             DrawText(10, 140, "SectorNo    : %d", sec_num);
410         }
411         else if (sram_flag)
412         {
413             DrawText(10, 140, "offset      : %x", offset);
414         }
415         DrawText(10, 150, "Access Size : %d", size);
416         DrawText(10, 130, "result      : ");
417         if (nocommond_flag)
418             DrawText(120, 130, "Erase is nothing");
419         if (!nocommond_flag)
420         {
421             for (i = 0; i < size; i++)
422             {
423                 if (dst_buf[i] != 0xFF)
424                     DrawText(120 + (i * 8), 130, "%c", dst_buf[i]);
425             }
426         }
427         if (async_flag)
428             DrawText(10, 170, "Async Mode");
429         if (!async_flag)
430             DrawText(10, 170, "Sync Mode");
431 
432         DrawEnd();
433         OS_WaitVBlankIntr();
434     }
435 }
436 
437 /*---------------------------------------------------------------------------*
438   Name:         SelectDevice
439 
440   Description:  Device selection screen.
441 
442   Arguments:    None.
443 
444   Returns:      None.
445  *---------------------------------------------------------------------------*/
SelectDevice(void)446 static void SelectDevice(void)
447 {
448     /* *INDENT-OFF* */
449     static const struct
450     {
451         CTRDGBackupType type;
452         const char *comment;
453     }
454     types_table[] =
455     {
456         { CTRDG_BACKUP_TYPE_FLASH_512K,   "FLASH   512 kb"},
457         { CTRDG_BACKUP_TYPE_FLASH_1M,     "FLASH     1 Mb"},
458         { CTRDG_BACKUP_TYPE_SRAM,         "SRAM    256 kb"},
459     };
460     /* *INDENT-ON* */
461     enum
462     { types_table_max = sizeof(types_table) / sizeof(*types_table) };
463 
464     int     cur = 0;
465     BOOL    error = FALSE;
466     BOOL    end = TRUE;
467     int     i;
468 
469     while (end != 0)
470     {
471 
472         keyData = PAD_Read();
473         keyData = PAD_Read();
474         Trg = (u16)(keyData & (keyData ^ Cont));
475         Cont = keyData;
476 
477         DrawBegin();
478         ClearFrame(RGB555_BLACK);
479 
480         /* Move the cursor with the up and down buttons */
481         if (Trg & PAD_KEY_DOWN)
482         {
483             error = FALSE;
484             if (++cur >= types_table_max)
485                 cur -= types_table_max;
486         }
487         if (Trg & PAD_KEY_UP)
488         {
489             error = FALSE;
490             if (--cur < 0)
491                 cur += types_table_max;
492         }
493 
494         /*
495          * Set the currently selected device with the A Button.
496          *
497          * Set this correctly because the library cannot determine whether the specified device has actually been loaded.
498          *
499          */
500         if (Trg & PAD_BUTTON_A)
501         {
502             end = CTRDG_IdentifyAgbBackup(types_table[cur].type);
503             if (end != 0)
504             {
505                 error = TRUE;
506             }
507             else
508             {
509                 if (types_table[cur].type == CTRDG_BACKUP_TYPE_SRAM)
510                     sram_flag = TRUE;
511                 if (types_table[cur].type == CTRDG_BACKUP_TYPE_FLASH_512K)
512                     flash512k_flag = TRUE;
513                 if (types_table[cur].type == CTRDG_BACKUP_TYPE_FLASH_1M)
514                     flash1m_flag = TRUE;
515             }
516         }
517 
518         /* String display */
519         SetTextColor(RGB555_GREEN);
520         DrawText(10, 40, "select device!");
521         for (i = 0; i < types_table_max; ++i)
522         {
523             DrawText(20, 60 + 10 * i, types_table[i].comment);
524         }
525         FillRect(10, 60, 10, i * 10, RGB555_BLACK);
526         DrawText(10, 60 + 10 * cur, ">");
527         if (error)
528         {
529             /* Error display */
530             SetTextColor(RGB555_RED);
531             DrawText(10, 120, "error!");
532         }
533         DrawEnd();
534     }
535 }
536