]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_LPC1768_GCC_Rowley/main.c
7294f97599ec1ee4e69aca28cf94e7a42646786e
[freertos] / Demo / CORTEX_LPC1768_GCC_Rowley / main.c
1 /*\r
2         FreeRTOS.org V5.4.0 - Copyright (C) 2003-2009 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify it\r
7         under the terms of the GNU General Public License (version 2) as published\r
8         by the Free Software Foundation and modified by the FreeRTOS exception.\r
9         **NOTE** The exception to the GPL is included to allow you to distribute a\r
10         combined work that includes FreeRTOS.org without being obliged to provide\r
11         the source code for any proprietary components.  Alternative commercial\r
12         license and support terms are also available upon request.  See the\r
13         licensing section of http://www.FreeRTOS.org for full details.\r
14 \r
15         FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT\r
16         ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
17         FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
18         more details.\r
19 \r
20         You should have received a copy of the GNU General Public License along\r
21         with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59\r
22         Temple Place, Suite 330, Boston, MA  02111-1307  USA.\r
23 \r
24 \r
25         ***************************************************************************\r
26         *                                                                         *\r
27         * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
28         *                                                                         *\r
29         * This is a concise, step by step, 'hands on' guide that describes both   *\r
30         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
31         * explains numerous examples that are written using the FreeRTOS API.     *\r
32         * Full source code for all the examples is provided in an accompanying    *\r
33         * .zip file.                                                              *\r
34         *                                                                         *\r
35         ***************************************************************************\r
36 \r
37         1 tab == 4 spaces!\r
38 \r
39         Please ensure to read the configuration and relevant port sections of the\r
40         online documentation.\r
41 \r
42         http://www.FreeRTOS.org - Documentation, latest information, license and\r
43         contact details.\r
44 \r
45         http://www.SafeRTOS.com - A version that is certified for use in safety\r
46         critical systems.\r
47 \r
48         http://www.OpenRTOS.com - Commercial support, development, porting,\r
49         licensing and training services.\r
50 */\r
51 \r
52 \r
53 /*\r
54  * Creates all the demo application tasks, then starts the scheduler.  The WEB\r
55  * documentation provides more details of the standard demo application tasks\r
56  * (which just exist to test the kernel port and provide an example of how to use\r
57  * each FreeRTOS API function).\r
58  *\r
59  * In addition to the standard demo tasks, the following tasks and tests are\r
60  * defined and/or created within this file:\r
61  *\r
62  * "LCD" task - the LCD task is a 'gatekeeper' task.  It is the only task that\r
63  * is permitted to access the display directly.  Other tasks wishing to write a\r
64  * message to the LCD send the message on a queue to the LCD task instead of\r
65  * accessing the LCD themselves.  The LCD task just blocks on the queue waiting\r
66  * for messages - waking and displaying the messages as they arrive.  The use\r
67  * of a gatekeeper in this manner permits both tasks and interrupts to write to\r
68  * the LCD without worrying about mutual exclusion.  This is demonstrated by the\r
69  * check hook (see below) which sends messages to the display even though it\r
70  * executes from an interrupt context.\r
71  *\r
72  * "Check" hook -  This only executes fully every five seconds from the tick\r
73  * hook.  Its main function is to check that all the standard demo tasks are\r
74  * still operational.  Should any unexpected behaviour be discovered within a\r
75  * demo task then the tick hook will write an error to the LCD (via the LCD task).\r
76  * If all the demo tasks are executing with their expected behaviour then the\r
77  * check hook writes PASS to the LCD (again via the LCD task), as described above.\r
78  * The check hook also toggles LED 4 each time it executes.\r
79  *\r
80  * LED tasks - These just demonstrate how multiple instances of a single task\r
81  * definition can be created.  Each LED task simply toggles an LED.  The task\r
82  * parameter is used to pass the number of the LED to be toggled into the task.\r
83  *\r
84  * "uIP" task -  This is the task that handles the uIP stack.  All TCP/IP\r
85  * processing is performed in this task.\r
86  */\r
87 \r
88 /* Standard includes. */\r
89 #include <stdio.h>\r
90 \r
91 /* Scheduler includes. */\r
92 #include "FreeRTOS.h"\r
93 #include "task.h"\r
94 #include "queue.h"\r
95 #include "semphr.h"\r
96 \r
97 /* Hardware library includes. */\r
98 #include "LPC17xx_defs.h"\r
99 \r
100 /* Demo app includes. */\r
101 #include "BlockQ.h"\r
102 #include "integer.h"\r
103 #include "blocktim.h"\r
104 #include "flash.h"\r
105 #include "partest.h"\r
106 #include "semtest.h"\r
107 #include "PollQ.h"\r
108 #include "GenQTest.h"\r
109 #include "QPeek.h"\r
110 #include "recmutex.h"\r
111 \r
112 \r
113 #if 0\r
114 \r
115 \r
116 \r
117 \r
118 \r
119 /*-----------------------------------------------------------*/\r
120 \r
121 /* The number of LED tasks that will be created. */\r
122 #define mainNUM_LED_TASKS                                       ( 6 )\r
123 \r
124 /* The time between cycles of the 'check' functionality (defined within the\r
125 tick hook. */\r
126 #define mainCHECK_DELAY                                         ( ( portTickType ) 5000 / portTICK_RATE_MS )\r
127 \r
128 /* Task priorities. */\r
129 #define mainQUEUE_POLL_PRIORITY                         ( tskIDLE_PRIORITY + 2 )\r
130 #define mainSEM_TEST_PRIORITY                           ( tskIDLE_PRIORITY + 1 )\r
131 #define mainBLOCK_Q_PRIORITY                            ( tskIDLE_PRIORITY + 2 )\r
132 #define mainUIP_TASK_PRIORITY                           ( tskIDLE_PRIORITY + 3 )\r
133 #define mainLCD_TASK_PRIORITY                           ( tskIDLE_PRIORITY + 2 )\r
134 #define mainINTEGER_TASK_PRIORITY           ( tskIDLE_PRIORITY )\r
135 #define mainGEN_QUEUE_TASK_PRIORITY                     ( tskIDLE_PRIORITY )\r
136 #define mainFLASH_TASK_PRIORITY                         ( tskIDLE_PRIORITY + 2 )\r
137 \r
138 /* The WEB server has a larger stack as it utilises stack hungry string\r
139 handling library calls. */\r
140 #define mainBASIC_WEB_STACK_SIZE            ( configMINIMAL_STACK_SIZE * 4 )\r
141 \r
142 /* The length of the queue used to send messages to the LCD task. */\r
143 #define mainQUEUE_SIZE                                          ( 3 )\r
144 \r
145 /* The task that is toggled by the check task. */\r
146 #define mainCHECK_TASK_LED                                      ( 4 )\r
147 /*-----------------------------------------------------------*/\r
148 \r
149 /*\r
150  * Configure the hardware for the demo.\r
151  */\r
152 static void prvSetupHardware( void );\r
153 \r
154 /*\r
155  * Very simple task that toggles an LED.\r
156  */\r
157 static void vLEDTask( void *pvParameters );\r
158 \r
159 /*\r
160  * The task that handles the uIP stack.  All TCP/IP processing is performed in\r
161  * this task.\r
162  */\r
163 extern void vuIP_Task( void *pvParameters );\r
164 \r
165 /*\r
166  * The LCD gatekeeper task as described in the comments at the top of this file.\r
167  * */\r
168 static void vLCDTask( void *pvParameters );\r
169 \r
170 /*-----------------------------------------------------------*/\r
171 \r
172 /* The queue used to send messages to the LCD task. */\r
173 xQueueHandle xLCDQueue;\r
174 \r
175 /*-----------------------------------------------------------*/\r
176 \r
177 int main( void )\r
178 {\r
179 long l;\r
180 \r
181         /* Configure the hardware for use by this demo. */\r
182         prvSetupHardware();\r
183 \r
184         /* Start the standard demo tasks.  These are just here to exercise the\r
185         kernel port and provide examples of how the FreeRTOS API can be used. */\r
186         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
187     vCreateBlockTimeTasks();\r
188     vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
189     vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
190     vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );\r
191     vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
192     vStartQueuePeekTasks();\r
193     vStartRecursiveMutexTasks();\r
194         vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );\r
195 \r
196         /* Create the uIP task.  The WEB server runs in this task. */\r
197     xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainUIP_TASK_PRIORITY, NULL );\r
198 \r
199         /* Create the queue used by the LCD task.  Messages for display on the LCD\r
200         are received via this queue. */\r
201         xLCDQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( xLCDMessage ) );\r
202 \r
203         /* Start the LCD gatekeeper task - as described in the comments at the top\r
204         of this file. */\r
205         xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE * 2, NULL, mainLCD_TASK_PRIORITY, NULL );\r
206 \r
207     /* Start the scheduler. */\r
208         vTaskStartScheduler();\r
209 \r
210     /* Will only get here if there was insufficient memory to create the idle\r
211     task.  The idle task is created within vTaskStartScheduler(). */\r
212         for( ;; );\r
213 }\r
214 /*-----------------------------------------------------------*/\r
215 \r
216 void vLCDTask( void *pvParameters )\r
217 {\r
218 xLCDMessage xMessage;\r
219 unsigned long ulRow = 0;\r
220 char cIPAddr[ 17 ]; /* To fit max IP address length of xxx.xxx.xxx.xxx\0 */\r
221 \r
222         ( void ) pvParameters;\r
223 \r
224         /* The LCD gatekeeper task as described in the comments at the top of this\r
225         file. */\r
226 \r
227         /* Initialise the LCD and display a startup message that includes the\r
228         configured IP address. */\r
229     sprintf( cIPAddr, "%d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
230 \r
231         for( ;; )\r
232         {\r
233                 /* Wait for a message to arrive to be displayed. */\r
234                 while( xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY ) != pdPASS );\r
235 \r
236         }\r
237 }\r
238 /*-----------------------------------------------------------*/\r
239 \r
240 void vApplicationTickHook( void )\r
241 {\r
242 static xLCDMessage xMessage = { "PASS" };\r
243 static unsigned portLONG ulTicksSinceLastDisplay = 0;\r
244 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
245 \r
246         /* Called from every tick interrupt as described in the comments at the top\r
247         of this file.\r
248 \r
249         Have enough ticks passed to make it     time to perform our health status\r
250         check again? */\r
251         ulTicksSinceLastDisplay++;\r
252         if( ulTicksSinceLastDisplay >= mainCHECK_DELAY )\r
253         {\r
254                 /* Reset the counter so these checks run again in mainCHECK_DELAY\r
255                 ticks time. */\r
256                 ulTicksSinceLastDisplay = 0;\r
257 \r
258                 /* Has an error been found in any task? */\r
259                 if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
260                 {\r
261                         xMessage.pcMessage = "ERROR: GEN Q";\r
262                 }\r
263                 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
264                 {\r
265                         xMessage.pcMessage = "ERROR: PEEK Q";\r
266                 }\r
267                 else if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
268                 {\r
269                         xMessage.pcMessage = "ERROR: BLOCK Q";\r
270                 }\r
271                 else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
272                 {\r
273                         xMessage.pcMessage = "ERROR: BLOCK TIME";\r
274                 }\r
275             else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
276             {\r
277                 xMessage.pcMessage = "ERROR: SEMAPHR";\r
278             }\r
279             else if( xArePollingQueuesStillRunning() != pdTRUE )\r
280             {\r
281                 xMessage.pcMessage = "ERROR: POLL Q";\r
282             }\r
283             else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
284             {\r
285                 xMessage.pcMessage = "ERROR: INT MATH";\r
286             }\r
287             else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
288             {\r
289                 xMessage.pcMessage = "ERROR: REC MUTEX";\r
290             }\r
291 \r
292                 /* Send the message to the OLED gatekeeper for display.  The\r
293                 xHigherPriorityTaskWoken parameter is not actually used here\r
294                 as this function is running in the tick interrupt anyway - but\r
295                 it must still be supplied. */\r
296                 xHigherPriorityTaskWoken = pdFALSE;\r
297                 xQueueSendFromISR( xLCDQueue, &xMessage, &xHigherPriorityTaskWoken );\r
298 \r
299                 /* Also toggle and LED.  This can be done from here because in this port\r
300                 the LED toggling functions don't use critical sections. */\r
301         vParTestToggleLED( mainCHECK_TASK_LED );\r
302         }\r
303 }\r
304 /*-----------------------------------------------------------*/\r
305 \r
306 void prvSetupHardware( void )\r
307 {\r
308         /* Disable peripherals power. */\r
309         PCONP = 0;\r
310 \r
311         /* Enable GPIO power. */\r
312         PCONP = PCONP_PCGPIO;\r
313 \r
314         /* Disable TPIU. */\r
315         PINSEL10 = 0;\r
316 \r
317         /* Disconnect the main PLL. */\r
318         PLL0CON &= ~PLLCON_PLLC;\r
319         PLL0FEED = PLLFEED_FEED1;\r
320         PLL0FEED = PLLFEED_FEED2;\r
321         while ((PLL0STAT & PLLSTAT_PLLC) != 0);\r
322 \r
323         /* Turn off the main PLL. */\r
324         PLL0CON &= ~PLLCON_PLLE;\r
325         PLL0FEED = PLLFEED_FEED1;\r
326         PLL0FEED = PLLFEED_FEED2;\r
327         while ((PLL0STAT & PLLSTAT_PLLE) != 0);\r
328 \r
329         /* No CPU clock divider. */\r
330         CCLKCFG = 0;\r
331 \r
332         /* OSCEN. */\r
333         SCS = 0x20;\r
334         while ((SCS & 0x40) == 0);\r
335 \r
336         /* Use main oscillator. */\r
337         CLKSRCSEL = 1;\r
338         PLL0CFG = (PLLCFG_MUL16 | PLLCFG_DIV1);\r
339 \r
340         PLL0FEED = PLLFEED_FEED1;\r
341         PLL0FEED = PLLFEED_FEED2;\r
342 \r
343         /*  Activate the PLL by turning it on then feeding the correct\r
344         sequence of bytes. */\r
345         PLL0CON  = PLLCON_PLLE;\r
346         PLL0FEED = PLLFEED_FEED1;\r
347         PLL0FEED = PLLFEED_FEED2;\r
348 \r
349         /* 6x CPU clock divider (64 MHz) */\r
350         CCLKCFG = 5;\r
351 \r
352         /*  Wait for the PLL to lock. */\r
353         while ((PLL0STAT & PLLSTAT_PLOCK) == 0);\r
354 \r
355         /*  Connect the PLL. */\r
356         PLL0CON  = PLLCON_PLLC | PLLCON_PLLE;\r
357         PLL0FEED = PLLFEED_FEED1;\r
358         PLL0FEED = PLLFEED_FEED2;\r
359 \r
360         /*  Setup the peripheral bus to be the same as the PLL output (64 MHz). */\r
361         PCLKSEL0 = 0x05555555;\r
362 \r
363         /* Configure the LEDs. */\r
364         vParTestInitialise();\r
365 }\r
366 /*-----------------------------------------------------------*/\r
367 \r
368 void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )\r
369 {\r
370         /* This function will get called if a task overflows its stack. */\r
371 \r
372         ( void ) pxTask;\r
373         ( void ) pcTaskName;\r
374 \r
375         for( ;; );\r
376 }\r
377 /*-----------------------------------------------------------*/\r
378 \r
379 void vConfigureTimerForRunTimeStats( void )\r
380 {\r
381 const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;\r
382 \r
383         /* This function configures a timer that is used as the time base when\r
384         collecting run time statistical information - basically the percentage\r
385         of CPU time that each task is utilising.  It is called automatically when\r
386         the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set\r
387         to 1. */\r
388 \r
389         /* Power up and feed the timer. */\r
390         PCONP |= 0x02UL;\r
391         PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2);\r
392 \r
393         /* Reset Timer 0 */\r
394         T0TCR = TCR_COUNT_RESET;\r
395 \r
396         /* Just count up. */\r
397         T0CTCR = CTCR_CTM_TIMER;\r
398 \r
399         /* Prescale to a frequency that is good enough to get a decent resolution,\r
400         but not too fast so as to overflow all the time. */\r
401         T0PR =  ( configCPU_CLOCK_HZ / 10000UL ) - 1UL;\r
402 \r
403         /* Start the counter. */\r
404         T0TCR = TCR_COUNT_ENABLE;\r
405 }\r
406 /*-----------------------------------------------------------*/\r
407 \r
408 #else\r
409 \r
410 \r
411 \r
412 \r
413 \r
414 /*----------------------------------------------------------------------*/\r
415 /* FAT file system sample project for FatFs R0.06  (C)ChaN, 2008        */\r
416 /*----------------------------------------------------------------------*/\r
417 \r
418 \r
419 #include <string.h>\r
420 #include "LPC17xx.h"\r
421 #include "integer.h"\r
422 //#include "interrupt.h"\r
423 #include "comm.h"\r
424 #include "monitor.h"\r
425 #include "rtc.h"\r
426 #include "diskio.h"\r
427 #include "ff.h"\r
428 \r
429 #include "ctl_api.h"\r
430 \r
431 #include "usbhost_lpc1768.h"\r
432 \r
433 DWORD acc_size;                         /* Work register for fs command */\r
434 WORD acc_files, acc_dirs;\r
435 FILINFO finfo;\r
436 \r
437 char linebuf[120];                      /* Console input buffer */\r
438 \r
439 FATFS fatfs[_DRIVES];           /* File system object for each logical drive */\r
440 FIL file1, file2;                       /* File objects */\r
441 DIR dir;                                        /* Directory object */\r
442 BYTE Buff[16384] __attribute__ ((aligned (4))) ;                /* Working buffer */\r
443 \r
444 volatile UINT Timer;            /* Performance timer (1kHz increment) */\r
445 \r
446 \r
447 \r
448 /*---------------------------------------------------------*/\r
449 /* 1000Hz timer interrupt generated by TIMER0              */\r
450 /*---------------------------------------------------------*/\r
451 \r
452 void Isr_TIMER0 (void)\r
453 {\r
454         T0IR = 1;                       /* Clear irq flag */\r
455 \r
456         Timer++;\r
457    MMC_TimerProc();\r
458 }\r
459 \r
460 \r
461 \r
462 /*---------------------------------------------------------*/\r
463 /* User Provided Timer Function for FatFs module           */\r
464 /*---------------------------------------------------------*/\r
465 /* This is a real time clock service to be called from     */\r
466 /* FatFs module. Any valid time must be returned even if   */\r
467 /* the system does not support a real time clock.          */\r
468 /* This is not required in read-only configuration.        */\r
469 \r
470 \r
471 DWORD get_fattime ()\r
472 {\r
473         RTC rtc;\r
474 \r
475         rtc_gettime(&rtc);\r
476 \r
477         return          ((DWORD)(rtc.year) << 25)\r
478                         | ((DWORD)rtc.month << 21)\r
479                         | ((DWORD)rtc.mday << 16)\r
480                         | ((DWORD)rtc.hour << 11)\r
481                         | ((DWORD)rtc.min << 5)\r
482                         | ((DWORD)rtc.sec >> 1);\r
483 }\r
484 \r
485 \r
486 /*--------------------------------------------------------------------------*/\r
487 /* Monitor                                                                  */\r
488 /*--------------------------------------------------------------------------*/\r
489 \r
490 static\r
491 FRESULT scan_files (char* path)\r
492 {\r
493         DIR dirs;\r
494         FRESULT res;\r
495         BYTE i;\r
496 \r
497 \r
498         if ((res = f_opendir(&dirs, path)) == FR_OK) {\r
499                 i = strlen(path);\r
500                 while (((res = f_readdir(&dirs, &finfo)) == FR_OK) && finfo.fname[0]) {\r
501                         if (finfo.fattrib & AM_DIR) {\r
502                                 acc_dirs++;\r
503                                 *(path+i) = '/'; strcpy(path+i+1, &finfo.fname[0]);\r
504                                 res = scan_files(path);\r
505                                 *(path+i) = '\0';\r
506                                 if (res != FR_OK) break;\r
507                         } else {\r
508                                 acc_files++;\r
509                                 acc_size += finfo.fsize;\r
510                         }\r
511                 }\r
512         }\r
513 \r
514         return res;\r
515 }\r
516 \r
517 \r
518 \r
519 static\r
520 void put_rc (FRESULT rc)\r
521 {\r
522         const char *p;\r
523         static const char str[] =\r
524                 "OK\0" "NOT_READY\0" "NO_FILE\0" "FR_NO_PATH\0" "INVALID_NAME\0" "INVALID_DRIVE\0"\r
525                 "DENIED\0" "EXIST\0" "RW_ERROR\0" "WRITE_PROTECTED\0" "NOT_ENABLED\0"\r
526                 "NO_FILESYSTEM\0" "INVALID_OBJECT\0" "MKFS_ABORTED\0";\r
527         FRESULT i;\r
528 \r
529         for (p = str, i = 0; i != rc && *p; i++) {\r
530                 while(*p++);\r
531         }\r
532         xprintf("rc=%u FR_%s\n", (UINT)rc, p);\r
533 }\r
534 \r
535 \r
536 \r
537 static\r
538 void IoInit (void)\r
539 {\r
540 #define PLL_N           1UL\r
541 #define PLL_M           12UL\r
542 #define CCLK_DIV        4   // 288MHz / 4 = 72MHz\r
543 #define USBCLK_DIV      6   // 288MHz / 6 = 48MHz\r
544 \r
545 //_RB_  if ( PLLSTAT & (1 << 25) ) {\r
546 //_RB_          PLLCON = 1;                             /* Disconnect PLL output if PLL is in use */\r
547 //_RB_          PLLFEED = 0xAA; PLLFEED = 0x55;\r
548 //_RB_  }\r
549 //_RB_  PLLCON = 0;                             /* Disable PLL */\r
550 //_RB_  PLLFEED = 0xAA; PLLFEED = 0x55;\r
551         CLKSRCSEL = 0;                  /* Select IRC (4MHz) as the PLL clock source */\r
552 \r
553    SCS |= 0x20;                 /* Enable main OSC */\r
554    while( !(SCS & 0x40) );      /* Wait until main OSC is usable */\r
555    CLKSRCSEL = 0x1;             /* select main OSC, 12MHz, as the PLL clock source */\r
556 \r
557 //_RB_  PLLCFG = ((PLL_N - 1) << 16) | (PLL_M - 1);     /* Re-configure PLL */\r
558 //_RB_  PLLFEED = 0xAA; PLLFEED = 0x55;\r
559 //_RB_  PLLCON = 1;                             /* Enable PLL */\r
560 //_RB_  PLLFEED = 0xAA; PLLFEED = 0x55;\r
561 \r
562 //_RB_  while ((PLLSTAT & (1 << 26)) == 0);     /* Wait for PLL locked */\r
563 \r
564         CCLKCFG = CCLK_DIV-1;   /* Select CCLK frequency (divide ratio of hclk) */\r
565    USBCLKCFG = USBCLK_DIV-1;            /* usbclk = 288 MHz/6 = 48 MHz */\r
566 //_RB_   PLLCON = 3;                            /* Connect PLL output to the sysclk */\r
567 //_RB_  PLLFEED = 0xAA; PLLFEED = 0x55;\r
568 \r
569 //_RB_  MAMCR = 0;                              /* Configure MAM for 72MHz operation */\r
570 //_RB_  MAMTIM = 3;\r
571 //_RB_  MAMCR = 2;\r
572 \r
573         PCLKSEL0 = 0x00000000;  /* Initialize peripheral clock to default */\r
574         PCLKSEL1 = 0x00000000;\r
575 \r
576 //      ClearVector();                  /* Initialie VIC */\r
577 \r
578         SCS |= 1;                               /* Enable FIO0 and FIO1 */\r
579 \r
580    FIO1DIR = (1<<26);                      /* Disable Piezo */\r
581         FIO2CLR = (1<<26);\r
582 \r
583         FIO2DIR = (1<<30);                      /* Heartbeat LED output */\r
584         FIO2CLR = (1<<30);\r
585 \r
586         /* Initialize Timer0 as 1kHz interval timer */\r
587 //      RegisterVector(TIMER0_INT, Isr_TIMER0, PRI_LOWEST, CLASS_IRQ);\r
588 //_RB_   ctl_set_isr(TIMER0_INT, PRI_LOWEST, CTL_ISR_TRIGGER_FIXED, Isr_TIMER0, 0);\r
589 //_RB_   ctl_unmask_isr(TIMER0_INT);\r
590 \r
591    T0CTCR = 0;\r
592         T0MR0 = 18000 - 1;              /* 18M / 1k = 18000 */\r
593         T0MCR = 0x3;                    /* Clear TC and Interrupt on MR0 match */\r
594         T0TCR = 1;\r
595 \r
596         uart0_init();                   /* Initialize UART0 */\r
597 \r
598 //      IrqEnable();                    /* Enable Irq */\r
599    ctl_global_interrupts_enable();\r
600 }\r
601 \r
602 \r
603 \r
604 int main (void)\r
605 {\r
606         char *ptr, *ptr2;\r
607         long p1, p2, p3;\r
608         BYTE res, b1;\r
609         WORD w1;\r
610         UINT s1, s2, cnt, blen = sizeof(Buff);\r
611         DWORD ofs = 0, sect = 0;\r
612         FATFS *fs;                              /* Pointer to file system object */\r
613         RTC rtc;\r
614 \r
615    BYTE ActiveDisk = 0;\r
616 \r
617    USB_INT32S  rc;\r
618 \r
619         IoInit();\r
620    Host_Init();\r
621 \r
622         xputs("\nFatFs module test monitor for LPC2468\n");\r
623    xputc('>');\r
624    ptr = linebuf;\r
625 \r
626         for (;;) {\r
627       if (ConnectedDeviceState == DEVICE_CONNECTED) {\r
628          ConnectedDeviceState = DEVICE_CLEAR;\r
629          xprintf("USB Mass Storage device detected\n");\r
630          rc = Host_EnumDev();       // Enumerate the device connected\r
631 \r
632          if (rc == OK) {\r
633             xprintf("USB device enumerated\n");\r
634          }\r
635          xputc('>');\r
636       }\r
637       else if (ConnectedDeviceState == DEVICE_DISCONNECTED) {\r
638          ConnectedDeviceState = DEVICE_CLEAR;\r
639          Host_Init();         // FreeDevice();\r
640          xprintf("Device Disconnected\n");\r
641          xputc('>');\r
642       }\r
643 \r
644                 if (get_line(ptr, sizeof(linebuf)) == '\r') {\r
645          switch (*ptr++) {\r
646 \r
647          case 'm' :\r
648             switch (*ptr++) {\r
649             case 'd' :  /* md <address> [<count>] - Dump memory */\r
650                if (!xatoi(&ptr, &p1)) break;\r
651                if (!xatoi(&ptr, &p2)) p2 = 128;\r
652                for (ptr=(char*)p1; p2 >= 16; ptr += 16, p2 -= 16) {\r
653                   put_dump((BYTE*)ptr, (UINT)ptr, 16);\r
654                }\r
655                if (p2) put_dump((BYTE*)ptr, (UINT)ptr, p2);\r
656                break;\r
657             }\r
658             break;\r
659 \r
660          case 'd' :\r
661             switch (*ptr++) {\r
662             case 'a' :  /* da [#] - select active disk */\r
663                if (xatoi(&ptr, &p1)) {\r
664                   ActiveDisk = (BYTE)p1;\r
665                }\r
666                ActiveDisk = VerifyActiveDisk(ActiveDisk);\r
667                break;\r
668 \r
669             case 'd' :  /* dd [<lba>] - Dump secrtor */\r
670                if (!xatoi(&ptr, &p2)) p2 = sect;\r
671                res = disk_read(ActiveDisk, Buff, p2, 1);\r
672 //               res = disk_read(ActiveDisk, gUsbXferBuffer, p2, 1);\r
673                if (res) { xprintf("rc=%d\n", (WORD)res); break; }\r
674                sect = p2 + 1;\r
675                xprintf("Sector:%lu\n", p2);\r
676                for (ptr=(char*)Buff, ofs = 0; ofs < 0x200; ptr+=16, ofs+=16) {\r
677 //               for (ptr=(char*)gUsbXferBuffer, ofs = 0; ofs < 0x200; ptr+=16, ofs+=16) {\r
678                   put_dump((BYTE*)ptr, ofs, 16);\r
679                }\r
680                break;\r
681 \r
682             case 'i' :  /* di - Initialize disk */\r
683                xprintf("rc=%d\n", (WORD)disk_initialize(ActiveDisk));\r
684                break;\r
685 \r
686             case 's' :  /* ds <phy_drv#> - Show disk status */\r
687 //              if (!xatoi(&ptr, &p1)) break;\r
688                if (disk_ioctl(ActiveDisk, GET_SECTOR_COUNT, &p2) == RES_OK)\r
689                   { xprintf("Drive size: %lu sectors\n", p2); }\r
690                if (disk_ioctl(ActiveDisk, GET_SECTOR_SIZE, &w1) == RES_OK)\r
691                   { xprintf("Sector size: %u\n", w1); }\r
692                if (disk_ioctl(ActiveDisk, GET_BLOCK_SIZE, &p2) == RES_OK)\r
693                   { xprintf("Erase block size: %lu sectors\n", p2); }\r
694                if (disk_ioctl(ActiveDisk, MMC_GET_TYPE, &b1) == RES_OK)\r
695                   { xprintf("MMC/SDC type: %u\n", b1); }\r
696                if (disk_ioctl(ActiveDisk, MMC_GET_CSD, Buff) == RES_OK)\r
697                   { xputs("CSD:\n"); put_dump(Buff, 0, 16); }\r
698                if (disk_ioctl(ActiveDisk, MMC_GET_CID, Buff) == RES_OK)\r
699                   { xputs("CID:\n"); put_dump(Buff, 0, 16); }\r
700                if (disk_ioctl(ActiveDisk, MMC_GET_OCR, Buff) == RES_OK)\r
701                   { xputs("OCR:\n"); put_dump(Buff, 0, 4); }\r
702                if (disk_ioctl(ActiveDisk, MMC_GET_SDSTAT, Buff) == RES_OK) {\r
703                   xputs("SD Status:\n");\r
704                   for (s1 = 0; s1 < 64; s1 += 16) put_dump(Buff+s1, s1, 16);\r
705                }\r
706                break;\r
707             }\r
708             break;\r
709 \r
710          case 'b' :\r
711             switch (*ptr++) {\r
712             case 'd' :  /* bd <addr> - Dump R/W buffer */\r
713                if (!xatoi(&ptr, &p1)) break;\r
714                for (ptr=(char*)&Buff[p1], ofs = p1, cnt = 32; cnt; cnt--, ptr+=16, ofs+=16) {\r
715                   put_dump((BYTE*)ptr, ofs, 16);\r
716                }\r
717                break;\r
718 \r
719             case 'e' :  /* be <addr> [<data>] ... - Edit R/W buffer */\r
720                if (!xatoi(&ptr, &p1)) break;\r
721                if (xatoi(&ptr, &p2)) {\r
722                   do {\r
723                      Buff[p1++] = (BYTE)p2;\r
724                   } while (xatoi(&ptr, &p2));\r
725                   break;\r
726                }\r
727                for (;;) {\r
728                   xprintf("%04X %02X-", (WORD)(p1), (WORD)Buff[p1]);\r
729                   get_line(linebuf, sizeof(linebuf));\r
730                   ptr = linebuf;\r
731                   if (*ptr == '.') break;\r
732                   if (*ptr < ' ') { p1++; continue; }\r
733                   if (xatoi(&ptr, &p2))\r
734                      Buff[p1++] = (BYTE)p2;\r
735                   else\r
736                      xputs("???\n");\r
737                }\r
738                break;\r
739 \r
740             case 'r' :  /* br <lba> [<num>] - Read disk into R/W buffer */\r
741                if (!xatoi(&ptr, &p2)) break;\r
742                if (!xatoi(&ptr, &p3)) p3 = 1;\r
743                xprintf("rc=%u\n", (WORD)disk_read(ActiveDisk, Buff, p2, p3));\r
744                break;\r
745 \r
746             case 'w' :  /* bw <lba> [<num>] - Write R/W buffer into disk */\r
747                if (!xatoi(&ptr, &p2)) break;\r
748                if (!xatoi(&ptr, &p3)) p3 = 1;\r
749                xprintf("rc=%u\n", (WORD)disk_write(ActiveDisk, Buff, p2, p3));\r
750                break;\r
751 \r
752             case 'f' :  /* bf <val> - Fill working buffer */\r
753                if (!xatoi(&ptr, &p1)) break;\r
754                memset(Buff, (BYTE)p1, sizeof(Buff));\r
755                break;\r
756             }\r
757             break;\r
758 \r
759          case 'f' :\r
760             switch (*ptr++) {\r
761 \r
762             case 'i' :  /* fi <log drv#> - Initialize logical drive */\r
763                if (!xatoi(&ptr, &p1)) break;\r
764                put_rc(f_mount((BYTE)p1, &fatfs[p1]));\r
765 //               put_rc(f_mount(ActiveDisk, &fatfs[ActiveDisk]));\r
766                break;\r
767 \r
768             case 's' :  /* fs [<path>] - Show logical drive status */\r
769                res = f_getfree(ptr, (DWORD*)&p2, &fs);\r
770                if (res) { put_rc(res); break; }\r
771                xprintf("FAT type = %u\nBytes/Cluster = %lu\nNumber of FATs = %u\n"\r
772                   "Root DIR entries = %u\nSectors/FAT = %lu\nNumber of clusters = %lu\n"\r
773                   "FAT start (lba) = %lu\nDIR start (lba,cluster) = %lu\nData start (lba) = %lu\n\n",\r
774                                                 (WORD)fs->fs_type, (DWORD)fs->csize * 512, (WORD)fs->n_fats,\r
775                                                 fs->n_rootdir, fs->sects_fat, (DWORD)fs->max_clust - 2,\r
776                                                 fs->fatbase, fs->dirbase, fs->database\r
777                );\r
778                acc_size = acc_files = acc_dirs = 0;\r
779                res = scan_files(ptr);\r
780                if (res) { put_rc(res); break; }\r
781                xprintf("%u files, %lu bytes.\n%u folders.\n"\r
782                                                 "%lu KB total disk space.\n%lu KB available.\n",\r
783                                                 acc_files, acc_size, acc_dirs,\r
784                                                 (fs->max_clust - 2) * (fs->csize / 2), p2 * (fs->csize / 2)\r
785                );\r
786                break;\r
787 \r
788             case 'l' :  /* fl [<path>] - Directory listing */\r
789                res = f_opendir(&dir, ptr);\r
790                if (res) { put_rc(res); break; }\r
791                p1 = s1 = s2 = 0;\r
792                for(;;) {\r
793                   res = f_readdir(&dir, &finfo);\r
794                   if ((res != FR_OK) || !finfo.fname[0]) break;\r
795                   if (finfo.fattrib & AM_DIR) {\r
796                      s2++;\r
797                   } else {\r
798                      s1++; p1 += finfo.fsize;\r
799                   }\r
800                   xprintf("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu  %s\n",\r
801                                                         (finfo.fattrib & AM_DIR) ? 'D' : '-',\r
802                                                         (finfo.fattrib & AM_RDO) ? 'R' : '-',\r
803                                                         (finfo.fattrib & AM_HID) ? 'H' : '-',\r
804                                                         (finfo.fattrib & AM_SYS) ? 'S' : '-',\r
805                                                         (finfo.fattrib & AM_ARC) ? 'A' : '-',\r
806                      (finfo.fdate >> 9) + 1980, (finfo.fdate >> 5) & 15, finfo.fdate & 31,\r
807                                                         (finfo.ftime >> 11), (finfo.ftime >> 5) & 63,\r
808                                                         finfo.fsize, &(finfo.fname[0]));\r
809                }\r
810                xprintf("%4u File(s),%10lu bytes total\n%4u Dir(s)", s1, p1, s2);\r
811                if (f_getfree(ptr, (DWORD*)&p1, &fs) == FR_OK)\r
812                   xprintf(", %10lu bytes free\n", p1 * fs->csize * 512);\r
813                break;\r
814 \r
815             case 'o' :  /* fo <mode> <file> - Open a file */\r
816                if (!xatoi(&ptr, &p1)) break;\r
817                put_rc(f_open(&file1, ptr, (BYTE)p1));\r
818                break;\r
819 \r
820             case 'c' :  /* fc - Close a file */\r
821                put_rc(f_close(&file1));\r
822                break;\r
823 \r
824             case 'e' :  /* fe - Seek file pointer */\r
825                if (!xatoi(&ptr, &p1)) break;\r
826                res = f_lseek(&file1, p1);\r
827                put_rc(res);\r
828                if (res == FR_OK)\r
829                   xprintf("fptr=%lu(0x%lX)\n", file1.fptr, file1.fptr);\r
830                break;\r
831 \r
832             case 'd' :  /* fd <len> - read and dump file from current fp */\r
833                if (!xatoi(&ptr, &p1)) break;\r
834                ofs = file1.fptr;\r
835                while (p1) {\r
836                   if ((UINT)p1 >= 16) { cnt = 16; p1 -= 16; }\r
837                   else                          { cnt = p1; p1 = 0; }\r
838                   res = f_read(&file1, Buff, cnt, &cnt);\r
839                   if (res != FR_OK) { put_rc(res); break; }\r
840                   if (!cnt) break;\r
841                   put_dump(Buff, ofs, cnt);\r
842                   ofs += 16;\r
843                }\r
844                break;\r
845 \r
846             case 'r' :  /* fr <len> - read file */\r
847                if (!xatoi(&ptr, &p1)) break;\r
848                p2 = 0;\r
849                Timer = 0;\r
850                while (p1) {\r
851                   if ((UINT)p1 >= blen) {\r
852                      cnt = blen; p1 -= blen;\r
853                   } else {\r
854                      cnt = p1; p1 = 0;\r
855                   }\r
856                   res = f_read(&file1, Buff, cnt, &s2);\r
857                   if (res != FR_OK) { put_rc(res); break; }\r
858                   p2 += s2;\r
859                   if (cnt != s2) break;\r
860                }\r
861                xprintf("%lu bytes read with %lu kB/sec.\n", p2, p2 / Timer);\r
862                break;\r
863 \r
864             case 'w' :  /* fw <len> <val> - write file */\r
865                if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break;\r
866                memset(Buff, (BYTE)p2, blen);\r
867                p2 = 0;\r
868                Timer = 0;\r
869                while (p1) {\r
870                   if ((UINT)p1 >= blen) {\r
871                      cnt = blen; p1 -= blen;\r
872                   } else {\r
873                      cnt = p1; p1 = 0;\r
874                   }\r
875                   res = f_write(&file1, Buff, cnt, &s2);\r
876                   if (res != FR_OK) { put_rc(res); break; }\r
877                   p2 += s2;\r
878                   if (cnt != s2) break;\r
879                }\r
880                xprintf("%lu bytes written with %lu kB/sec.\n", p2, p2 / Timer);\r
881                break;\r
882 \r
883             case 'n' :  /* fn <old_name> <new_name> - Change file/dir name */\r
884                while (*ptr == ' ') ptr++;\r
885                ptr2 = strchr(ptr, ' ');\r
886                if (!ptr2) break;\r
887                *ptr2++ = 0;\r
888                while (*ptr2 == ' ') ptr2++;\r
889                put_rc(f_rename(ptr, ptr2));\r
890                break;\r
891 \r
892             case 'u' :  /* fu <name> - Unlink a file or dir */\r
893                put_rc(f_unlink(ptr));\r
894                break;\r
895 \r
896             case 'v' :  /* fv - Truncate file */\r
897                put_rc(f_truncate(&file1));\r
898                break;\r
899 \r
900             case 'k' :  /* fk <name> - Create a directory */\r
901                put_rc(f_mkdir(ptr));\r
902                break;\r
903 \r
904             case 'a' :  /* fa <atrr> <mask> <name> - Change file/dir attribute */\r
905                if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break;\r
906                put_rc(f_chmod(ptr, p1, p2));\r
907                break;\r
908 \r
909             case 't' :  /* ft <year> <month> <day> <hour> <min> <sec> <name> - Change timestamp */\r
910                if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break;\r
911                finfo.fdate = ((p1 - 1980) << 9) | ((p2 & 15) << 5) | (p3 & 31);\r
912                if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break;\r
913                finfo.ftime = ((p1 & 31) << 11) | ((p1 & 63) << 5) | ((p1 >> 1) & 31);\r
914                put_rc(f_utime(ptr, &finfo));\r
915                break;\r
916 \r
917             case 'x' : /* fx <src_name> <dst_name> - Copy file */\r
918                while (*ptr == ' ') ptr++;\r
919                ptr2 = strchr(ptr, ' ');\r
920                if (!ptr2) break;\r
921                *ptr2++ = 0;\r
922                while (*ptr2 == ' ') ptr2++;\r
923                xprintf("Opening \"%s\"", ptr);\r
924                res = f_open(&file1, ptr, FA_OPEN_EXISTING | FA_READ);\r
925                xputc('\n');\r
926                if (res) {\r
927                   put_rc(res);\r
928                   break;\r
929                }\r
930                xprintf("Creating \"%s\"", ptr2);\r
931                res = f_open(&file2, ptr2, FA_CREATE_ALWAYS | FA_WRITE);\r
932                xputc('\n');\r
933                if (res) {\r
934                   put_rc(res);\r
935                   f_close(&file1);\r
936                   break;\r
937                }\r
938                xprintf("Copying file...");\r
939                Timer = 0;\r
940                p1 = 0;\r
941                for (;;) {\r
942                   res = f_read(&file1, Buff, blen, &s1);\r
943                   if (res || s1 == 0) break;   /* error or eof */\r
944                   res = f_write(&file2, Buff, s1, &s2);\r
945                   p1 += s2;\r
946                   if (res || s2 < s1) break;   /* error or disk full */\r
947                }\r
948                xprintf("%lu bytes copied with %lu kB/sec.\n", p1, p1 / Timer);\r
949                f_close(&file1);\r
950                f_close(&file2);\r
951                break;\r
952 #if _USE_MKFS\r
953             case 'm' :  /* fm <partition rule> <cluster size> - Create file system */\r
954                if (!xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break;\r
955                xprintf("The drive %u will be formatted. Are you sure? (Y/n)=", ActiveDisk);\r
956                get_line(ptr, sizeof(linebuf));\r
957                if (*ptr == 'Y')\r
958                   put_rc(f_mkfs(ActiveDisk, (BYTE)p2, (WORD)p3));\r
959                break;\r
960 #endif\r
961             case 'z' :  /* fz [<rw size>] - Change R/W length for fr/fw/fx command */\r
962                if (xatoi(&ptr, &p1) && p1 >= 1 && p1 <= sizeof(Buff))\r
963                   blen = p1;\r
964                xprintf("blen=%u\n", blen);\r
965                break;\r
966             }\r
967             break;\r
968 \r
969          case 't' :     /* t [<year> <mon> <mday> <hour> <min> <sec>] */\r
970             if (xatoi(&ptr, &p1)) {\r
971                rtc.year = (WORD)p1;\r
972                xatoi(&ptr, &p1); rtc.month = (BYTE)p1;\r
973                xatoi(&ptr, &p1); rtc.mday = (BYTE)p1;\r
974                xatoi(&ptr, &p1); rtc.hour = (BYTE)p1;\r
975                xatoi(&ptr, &p1); rtc.min = (BYTE)p1;\r
976                if (!xatoi(&ptr, &p1)) break;\r
977                rtc.sec = (BYTE)p1;\r
978                rtc_settime(&rtc);\r
979             }\r
980             rtc_gettime(&rtc);\r
981             xprintf("%u/%u/%u %02u:%02u:%02u\n", rtc.year, rtc.month, rtc.mday, rtc.hour, rtc.min, rtc.sec);\r
982             break;\r
983 \r
984          case 'u' : /* usb test commands */\r
985             switch (*ptr++) {\r
986 \r
987             case 's' :  /* print bulk size */\r
988             xprintf("MS Bulk size %lu\n", MS_BlkSize);\r
989             break;\r
990             }\r
991          break;\r
992          }\r
993          xputc('>');\r
994          ptr = linebuf;\r
995       }\r
996    }\r
997 }\r
998 \r
999 void vApplicationTickHook( void )\r
1000 {\r
1001 }\r
1002 /*-----------------------------------------------------------*/\r
1003 \r
1004 \r
1005 void vConfigureTimerForRunTimeStats( void )\r
1006 {\r
1007 }\r
1008 \r
1009 void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )\r
1010 {\r
1011 }\r
1012 xQueueHandle xLCDQueue;\r
1013 #endif\r