]> git.sur5r.net Git - freertos/blob - Demo/Cygnal/main.c
Update to V5.0.2
[freertos] / Demo / Cygnal / main.c
1 /*\r
2         FreeRTOS.org V5.0.2 - Copyright (C) 2003-2008 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\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26     ***************************************************************************\r
27     ***************************************************************************\r
28     *                                                                         *\r
29     * SAVE TIME AND MONEY!  We can port FreeRTOS.org to your own hardware,    *\r
30     * and even write all or part of your application on your behalf.          *\r
31     * See http://www.OpenRTOS.com for details of the services we provide to   *\r
32     * expedite your project.                                                  *\r
33     *                                                                         *\r
34     ***************************************************************************\r
35     ***************************************************************************\r
36 \r
37         Please ensure to read the configuration and relevant port sections of the\r
38         online documentation.\r
39 \r
40         http://www.FreeRTOS.org - Documentation, latest information, license and \r
41         contact details.\r
42 \r
43         http://www.SafeRTOS.com - A version that is certified for use in safety \r
44         critical systems.\r
45 \r
46         http://www.OpenRTOS.com - Commercial support, development, porting, \r
47         licensing and training services.\r
48 */\r
49 \r
50 /*\r
51  * Creates the demo application tasks, then starts the scheduler.  The WEB\r
52  * documentation provides more details of the demo application tasks.\r
53  * \r
54  * Main. c also creates four other tasks:\r
55  * \r
56  * 1) vErrorChecks()\r
57  * This only executes every few seconds but has the highest priority so is \r
58  * guaranteed to get processor time.  Its main function is to check that all \r
59  * the standard demo application tasks are still operational and have not\r
60  * experienced any errors.  vErrorChecks() will toggle the on board LED\r
61  * every mainNO_ERROR_FLASH_PERIOD milliseconds if none of the demo application\r
62  * tasks have reported an error.  Should any task report an error at any time\r
63  * the rate at which the on board LED is toggled is increased to \r
64  * mainERROR_FLASH_PERIOD - providing visual feedback that something has gone\r
65  * wrong.\r
66  *\r
67  * 2) vRegisterCheck()\r
68  * This is a very simple task that checks that all the registers are always\r
69  * in their expected state.  The task only makes use of the A register, so\r
70  * all the other registers should always contain their initial values.\r
71  * An incorrect value indicates an error in the context switch mechanism.\r
72  * The task operates at the idle priority so will be preempted regularly.\r
73  * Any error will cause the toggle rate of the on board LED to increase to\r
74  * mainERROR_FLASH_PERIOD milliseconds.\r
75  *\r
76  * 3 and 4) vFLOPCheck1() and vFLOPCheck2()\r
77  * These are very basic versions of the standard FLOP tasks.  They are good\r
78  * at detecting errors in the context switch mechanism, and also check that\r
79  * the floating point libraries are correctly built to be re-enterant.  The\r
80  * stack restrictions of the 8051 prevent the use of the standard FLOP demo\r
81  * tasks.\r
82  */\r
83 \r
84 /* Standard includes. */\r
85 #include <stdlib.h>\r
86 \r
87 /* Scheduler includes. */\r
88 #include "FreeRTOS.h"\r
89 #include "task.h"\r
90 \r
91 /* Demo application includes. */\r
92 #include "partest.h"\r
93 #include "flash.h"\r
94 #include "integer.h"\r
95 #include "PollQ.h"\r
96 #include "comtest2.h"\r
97 #include "semtest.h"\r
98 \r
99 /* Demo task priorities. */\r
100 #define mainLED_TASK_PRIORITY           ( tskIDLE_PRIORITY + 1 )\r
101 #define mainQUEUE_POLL_PRIORITY         ( tskIDLE_PRIORITY + 2 )\r
102 #define mainCOM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 2 )\r
103 #define mainCHECK_TASK_PRIORITY         ( tskIDLE_PRIORITY + 3 )\r
104 #define mainSEM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 2 )\r
105 #define mainINTEGER_PRIORITY            tskIDLE_PRIORITY\r
106 \r
107 /* Constants required to disable the watchdog. */\r
108 #define mainDISABLE_BYTE_1                      ( ( unsigned portCHAR ) 0xde )\r
109 #define mainDISABLE_BYTE_2                      ( ( unsigned portCHAR ) 0xad )\r
110 \r
111 /* Constants to setup and use the on board LED. */\r
112 #define ucLED_BIT                                       ( ( unsigned portCHAR ) 0x40 )\r
113 #define mainPORT_1_BIT_6                        ( ( unsigned portCHAR ) 0x40 )\r
114 #define mainENABLE_CROSS_BAR            ( ( unsigned portCHAR ) 0x40 )\r
115 \r
116 /* Constants to set the clock frequency. */\r
117 #define mainSELECT_INTERNAL_OSC         ( ( unsigned portCHAR ) 0x80 )\r
118 #define mainDIVIDE_CLOCK_BY_1           ( ( unsigned portCHAR ) 0x03 )\r
119 #define mainPLL_USES_INTERNAL_OSC       ( ( unsigned portCHAR ) 0x04 )\r
120 #define mainFLASH_READ_TIMING           ( ( unsigned portCHAR ) 0x30 )\r
121 #define mainPLL_POWER_ON                        ( ( unsigned portCHAR ) 0x01 )\r
122 #define mainPLL_NO_PREDIVIDE            ( ( unsigned portCHAR ) 0x01 )\r
123 #define mainPLL_FILTER                          ( ( unsigned portCHAR ) 0x01 )\r
124 #define mainPLL_MULTIPLICATION          ( ( unsigned portCHAR ) 0x04 )\r
125 #define mainENABLE_PLL                          ( ( unsigned portCHAR ) 0x02 )\r
126 #define mainPLL_LOCKED                          ( ( unsigned portCHAR ) 0x10 )\r
127 #define mainSELECT_PLL_AS_SOURCE        ( ( unsigned portCHAR ) 0x02 )\r
128 \r
129 /* Toggle rate for the on board LED - which is dependent on whether or not\r
130 an error has been detected. */\r
131 #define mainNO_ERROR_FLASH_PERIOD       ( ( portTickType ) 5000 )\r
132 #define mainERROR_FLASH_PERIOD          ( ( portTickType ) 250 )\r
133 \r
134 /* Baud rate used by the serial port tasks. */\r
135 #define mainCOM_TEST_BAUD_RATE          ( ( unsigned portLONG ) 115200 )\r
136 \r
137 /* Pass an invalid LED number to the COM test task as we don't want it to flash\r
138 an LED.  There are only 8 LEDs (excluding the on board LED) wired in and these\r
139 are all used by the flash tasks. */\r
140 #define mainCOM_TEST_LED                        ( 200 )\r
141 \r
142 /* We want the Cygnal to act as much as possible as a standard 8052. */\r
143 #define mainAUTO_SFR_OFF                        ( ( unsigned portCHAR ) 0 )\r
144 \r
145 /* Constants required to setup the IO pins for serial comms. */\r
146 #define mainENABLE_COMS                         ( ( unsigned portCHAR ) 0x04 )\r
147 #define mainCOMS_LINES_TO_PUSH_PULL ( ( unsigned portCHAR ) 0x03 )\r
148 \r
149 /* Pointer passed as a parameter to vRegisterCheck() just so it has some know\r
150 values to check for in the DPH, DPL and B registers. */\r
151 #define mainDUMMY_POINTER               ( ( xdata void * ) 0xabcd )\r
152 \r
153 /* Macro that lets vErrorChecks() know that one of the tasks defined in\r
154 main. c has detected an error.  A critical region is used around xLatchError\r
155 as it is accessed from vErrorChecks(), which has a higher priority. */ \r
156 #define mainLATCH_ERROR()                       \\r
157 {                                                                       \\r
158         portENTER_CRITICAL();                   \\r
159                 xLatchedError = pdTRUE;         \\r
160         portEXIT_CRITICAL();                    \\r
161 }\r
162 \r
163 /*\r
164  * Setup the Cygnal microcontroller for its fastest operation. \r
165  */\r
166 static void prvSetupSystemClock( void );\r
167 \r
168 /*\r
169  * Setup the peripherals, including the on board LED. \r
170  */\r
171 static void prvSetupHardware( void );\r
172 \r
173 /*\r
174  * Toggle the state of the on board LED. \r
175  */\r
176 static void prvToggleOnBoardLED( void );\r
177 \r
178 /*\r
179  * See comments at the top of the file for details. \r
180  */\r
181 static void vErrorChecks( void *pvParameters );\r
182 \r
183 /*\r
184  * See comments at the top of the file for details. \r
185  */\r
186 static void vRegisterCheck( void *pvParameters );\r
187 \r
188 /*\r
189  * See comments at the top of the file for details. \r
190  */\r
191 static void vFLOPCheck1( void *pvParameters );\r
192 \r
193 /*\r
194  * See comments at the top of the file for details. \r
195  */\r
196 static void vFLOPCheck2( void *pvParameters );\r
197 \r
198 /* File scope variable used to communicate the occurrence of an error between\r
199 tasks. */\r
200 static portBASE_TYPE xLatchedError = pdFALSE;\r
201 \r
202 /*-----------------------------------------------------------*/\r
203 \r
204 /*\r
205  * Starts all the other tasks, then starts the scheduler. \r
206  */\r
207 void main( void )\r
208 {\r
209         /* Initialise the hardware including the system clock and on board\r
210         LED. */\r
211         prvSetupHardware();\r
212 \r
213         /* Initialise the port that controls the external LED's utilized by the\r
214         flash tasks. */\r
215         vParTestInitialise();\r
216 \r
217         /* Start the used standard demo tasks. */\r
218         vStartLEDFlashTasks( mainLED_TASK_PRIORITY );\r
219         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
220         vStartIntegerMathTasks( mainINTEGER_PRIORITY );\r
221         vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );\r
222         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
223 \r
224         /* Start the tasks defined in this file.  The first three never block so\r
225         must not be used with the co-operative scheduler. */\r
226         #if configUSE_PREEMPTION == 1\r
227         {\r
228                 xTaskCreate( vRegisterCheck, "RegChck", configMINIMAL_STACK_SIZE, mainDUMMY_POINTER, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );\r
229                 xTaskCreate( vFLOPCheck1, "FLOP", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );\r
230                 xTaskCreate( vFLOPCheck2, "FLOP", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );\r
231         }\r
232         #endif \r
233 \r
234         xTaskCreate( vErrorChecks, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, ( xTaskHandle * ) NULL );\r
235 \r
236         /* Finally kick off the scheduler.  This function should never return. */\r
237         vTaskStartScheduler();\r
238 \r
239         /* Should never reach here as the tasks will now be executing under control\r
240         of the scheduler. */\r
241 }\r
242 /*-----------------------------------------------------------*/\r
243 \r
244 /*\r
245  * Setup the hardware prior to using the scheduler.  Most of the Cygnal\r
246  * specific initialisation is performed here leaving standard 8052 setup\r
247  * only in the driver code.\r
248  */\r
249 static void prvSetupHardware( void )\r
250 {\r
251 unsigned portCHAR ucOriginalSFRPage;\r
252 \r
253         /* Remember the SFR page before it is changed so it can get set back\r
254         before the function exits. */\r
255         ucOriginalSFRPage = SFRPAGE;\r
256 \r
257         /* Setup the SFR page to access the config SFR's. */\r
258         SFRPAGE = CONFIG_PAGE;\r
259 \r
260         /* Don't allow the microcontroller to automatically switch SFR page, as the\r
261         SFR page is not stored as part of the task context. */\r
262         SFRPGCN = mainAUTO_SFR_OFF;\r
263 \r
264         /* Disable the watchdog. */\r
265         WDTCN = mainDISABLE_BYTE_1;\r
266         WDTCN = mainDISABLE_BYTE_2;\r
267 \r
268         /* Set the on board LED to push pull. */\r
269         P1MDOUT |= mainPORT_1_BIT_6;\r
270 \r
271         /* Setup the cross bar to enable serial comms here as it is not part of the \r
272         standard 8051 setup and therefore is not in the driver code. */\r
273         XBR0 |= mainENABLE_COMS;\r
274         P0MDOUT |= mainCOMS_LINES_TO_PUSH_PULL;\r
275 \r
276         /* Enable the cross bar so our hardware setup takes effect. */\r
277         XBR2 = mainENABLE_CROSS_BAR;\r
278 \r
279         /* Setup a fast system clock. */\r
280         prvSetupSystemClock();\r
281 \r
282         /* Return the SFR page. */\r
283         SFRPAGE = ucOriginalSFRPage;\r
284 }\r
285 /*-----------------------------------------------------------*/\r
286 \r
287 static void prvSetupSystemClock( void )\r
288 {\r
289 volatile unsigned portSHORT usWait;\r
290 const unsigned portSHORT usWaitTime = ( unsigned portSHORT ) 0x2ff;\r
291 unsigned portCHAR ucOriginalSFRPage;\r
292 \r
293         /* Remember the SFR page so we can set it back at the end. */\r
294         ucOriginalSFRPage = SFRPAGE;\r
295         SFRPAGE = CONFIG_PAGE;\r
296 \r
297         /* Use the internal oscillator set to its fasted frequency. */\r
298         OSCICN = mainSELECT_INTERNAL_OSC | mainDIVIDE_CLOCK_BY_1;\r
299 \r
300         /* Ensure the clock is stable. */\r
301         for( usWait = 0; usWait < usWaitTime; usWait++ );\r
302 \r
303         /* Setup the clock source for the PLL. */\r
304         PLL0CN &= ~mainPLL_USES_INTERNAL_OSC;\r
305 \r
306         /* Change the read timing for the flash ready for the fast clock. */\r
307         SFRPAGE = LEGACY_PAGE;\r
308         FLSCL |= mainFLASH_READ_TIMING;\r
309 \r
310         /* Turn on the PLL power. */\r
311         SFRPAGE = CONFIG_PAGE;\r
312         PLL0CN |= mainPLL_POWER_ON;\r
313 \r
314         /* Don't predivide the clock. */\r
315         PLL0DIV = mainPLL_NO_PREDIVIDE;\r
316 \r
317         /* Set filter for fastest clock. */\r
318         PLL0FLT = mainPLL_FILTER;\r
319         PLL0MUL = mainPLL_MULTIPLICATION;\r
320 \r
321         /* Ensure the clock is stable. */\r
322         for( usWait = 0; usWait < usWaitTime; usWait++ );\r
323 \r
324         /* Enable the PLL and wait for it to lock. */\r
325         PLL0CN |= mainENABLE_PLL;\r
326         for( usWait = 0; usWait < usWaitTime; usWait++ )\r
327         {\r
328                 if( PLL0CN & mainPLL_LOCKED )\r
329                 {\r
330                         break;\r
331                 }\r
332         }\r
333 \r
334         /* Select the PLL as the clock source. */\r
335         CLKSEL |= mainSELECT_PLL_AS_SOURCE;\r
336 \r
337         /* Return the SFR back to its original value. */\r
338         SFRPAGE = ucOriginalSFRPage;\r
339 }\r
340 /*-----------------------------------------------------------*/\r
341 \r
342 static void prvToggleOnBoardLED( void )\r
343 {\r
344         /* If the on board LED is on, turn it off and visa versa. */\r
345         if( P1 & ucLED_BIT )\r
346         {\r
347                 P1 &= ~ucLED_BIT;\r
348         }\r
349         else\r
350         {\r
351                 P1 |= ucLED_BIT;\r
352         }\r
353 }\r
354 /*-----------------------------------------------------------*/\r
355 \r
356 /*\r
357  * See the documentation at the top of this file. \r
358  */\r
359 static void vErrorChecks( void *pvParameters )\r
360 {\r
361 portBASE_TYPE xErrorHasOccurred = pdFALSE;\r
362         \r
363         /* Just to prevent compiler warnings. */\r
364         ( void ) pvParameters;\r
365         \r
366         /* Cycle for ever, delaying then checking all the other tasks are still\r
367         operating without error.   The delay period depends on whether an error\r
368         has ever been detected. */\r
369         for( ;; )\r
370         {\r
371                 if( xLatchedError == pdFALSE )\r
372                 {               \r
373                         /* No errors have been detected so delay for a longer period.  The\r
374                         on board LED will get toggled every mainNO_ERROR_FLASH_PERIOD ms. */\r
375                         vTaskDelay( mainNO_ERROR_FLASH_PERIOD );\r
376                 }\r
377                 else\r
378                 {\r
379                         /* We have at some time recognised an error in one of the demo\r
380                         application tasks, delay for a shorter period.  The on board LED\r
381                         will get toggled every mainERROR_FLASH_PERIOD ms. */\r
382                         vTaskDelay( mainERROR_FLASH_PERIOD );\r
383                 }\r
384 \r
385                 \r
386                 \r
387                 /* Check the demo application tasks for errors. */\r
388 \r
389                 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
390                 {\r
391                         xErrorHasOccurred = pdTRUE;\r
392                 }\r
393 \r
394                 if( xArePollingQueuesStillRunning() != pdTRUE )\r
395                 {\r
396                         xErrorHasOccurred = pdTRUE;\r
397                 }\r
398 \r
399                 if( xAreComTestTasksStillRunning() != pdTRUE )\r
400                 {\r
401                         xErrorHasOccurred = pdTRUE;\r
402                 }\r
403 \r
404                 if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
405                 {\r
406                         xErrorHasOccurred = pdTRUE;\r
407                 }\r
408 \r
409                 /* If an error has occurred, latch it to cause the LED flash rate to \r
410                 increase. */\r
411                 if( xErrorHasOccurred == pdTRUE )\r
412                 {\r
413                         xLatchedError = pdTRUE;\r
414                 }\r
415 \r
416                 /* Toggle the LED to indicate the completion of a check cycle.  The\r
417                 frequency of check cycles is dependent on whether or not we have \r
418                 latched an error. */\r
419                 prvToggleOnBoardLED();\r
420         }\r
421 }\r
422 /*-----------------------------------------------------------*/\r
423 \r
424 /*\r
425  * See the documentation at the top of this file.  Also see the standard FLOP\r
426  * demo task documentation for the rationale of these tasks.\r
427  */\r
428 static void vFLOPCheck1( void *pvParameters )\r
429 {\r
430 volatile portFLOAT fVal1, fVal2, fResult;\r
431 \r
432         ( void ) pvParameters;\r
433 \r
434         for( ;; )\r
435         {\r
436                 fVal1 = ( portFLOAT ) -1234.5678;\r
437                 fVal2 = ( portFLOAT ) 2345.6789;\r
438 \r
439                 fResult = fVal1 + fVal2;\r
440                 if( ( fResult > ( portFLOAT )  1111.15 ) || ( fResult < ( portFLOAT ) 1111.05 ) )\r
441                 {\r
442                         mainLATCH_ERROR();\r
443                 }\r
444 \r
445                 fResult = fVal1 / fVal2;\r
446                 if( ( fResult > ( portFLOAT ) -0.51 ) || ( fResult < ( portFLOAT ) -0.53 ) )\r
447                 {\r
448                         mainLATCH_ERROR();\r
449                 }\r
450         }\r
451 }\r
452 /*-----------------------------------------------------------*/\r
453 \r
454 /*\r
455  * See the documentation at the top of this file.\r
456  */\r
457 static void vFLOPCheck2( void *pvParameters )\r
458 {\r
459 volatile portFLOAT fVal1, fVal2, fResult;\r
460 \r
461         ( void ) pvParameters;\r
462 \r
463         for( ;; )\r
464         {\r
465                 fVal1 = ( portFLOAT ) -12340.5678;\r
466                 fVal2 = ( portFLOAT ) 23450.6789;\r
467 \r
468                 fResult = fVal1 + fVal2;\r
469                 if( ( fResult > ( portFLOAT ) 11110.15 ) || ( fResult < ( portFLOAT ) 11110.05 ) )\r
470                 {\r
471                         mainLATCH_ERROR();\r
472                 }\r
473 \r
474                 fResult = fVal1 / -fVal2;\r
475                 if( ( fResult > ( portFLOAT ) 0.53 ) || ( fResult < ( portFLOAT ) 0.51 ) )\r
476                 {\r
477                         mainLATCH_ERROR();\r
478                 }\r
479         }\r
480 }\r
481 /*-----------------------------------------------------------*/\r
482 \r
483 /*\r
484  * See the documentation at the top of this file. \r
485  */\r
486 static void vRegisterCheck( void *pvParameters )\r
487 {\r
488         ( void ) pvParameters;\r
489 \r
490         for( ;; )\r
491         {\r
492                 if( SP != configSTACK_START )\r
493                 {\r
494                         mainLATCH_ERROR();\r
495                 }\r
496 \r
497                 _asm\r
498                         MOV ACC, ar0\r
499                 _endasm;\r
500 \r
501                 if( ACC != 0 )\r
502                 {\r
503                         mainLATCH_ERROR();\r
504                 }\r
505 \r
506                 _asm\r
507                         MOV ACC, ar1\r
508                 _endasm;\r
509 \r
510                 if( ACC != 1 )\r
511                 {\r
512                         mainLATCH_ERROR();\r
513                 }\r
514                 _asm\r
515                         MOV ACC, ar2\r
516                 _endasm;\r
517 \r
518                 if( ACC != 2 )\r
519                 {\r
520                         mainLATCH_ERROR();\r
521                 }\r
522                 _asm\r
523                         MOV ACC, ar3\r
524                 _endasm;\r
525 \r
526                 if( ACC != 3 )\r
527                 {\r
528                         mainLATCH_ERROR();\r
529                 }\r
530                 _asm\r
531                         MOV ACC, ar4\r
532                 _endasm;\r
533 \r
534                 if( ACC != 4 )\r
535                 {\r
536                         mainLATCH_ERROR();\r
537                 }\r
538                 _asm\r
539                         MOV ACC, ar5\r
540                 _endasm;\r
541 \r
542                 if( ACC != 5 )\r
543                 {\r
544                         mainLATCH_ERROR();\r
545                 }\r
546                 _asm\r
547                         MOV ACC, ar6\r
548                 _endasm;\r
549 \r
550                 if( ACC != 6 )\r
551                 {\r
552                         mainLATCH_ERROR();\r
553                 }\r
554                 _asm\r
555                         MOV ACC, ar7\r
556                 _endasm;\r
557 \r
558                 if( ACC != 7 )\r
559                 {\r
560                         mainLATCH_ERROR();\r
561                 }\r
562 \r
563                 if( DPL != 0xcd )\r
564                 {\r
565                         mainLATCH_ERROR();\r
566                 }\r
567 \r
568                 if( DPH != 0xab )\r
569                 {\r
570                         mainLATCH_ERROR();\r
571                 }\r
572 \r
573                 if( B != 0x01 )\r
574                 {\r
575                         mainLATCH_ERROR();\r
576                 }                       \r
577         }\r
578 }\r
579 \r
580 \r