├── .gitignore ├── FreeRTOS.h ├── FreeRTOSConfig.h ├── FreeRTOSConfig_328p.h ├── Jamfile ├── Jamrules ├── StackMacros.h ├── croutine.h ├── examples ├── Jamfile ├── blinky │ ├── Jamfile │ └── blinky.ino ├── buttonled │ ├── Jamfile │ └── buttonled.ino ├── manybuttons │ ├── Jamfile │ └── manybuttons.ino ├── pingpair │ ├── Jamfile │ ├── app_tasks.cpp │ ├── globals.h │ ├── pingpair.ino │ ├── printf.h │ ├── radio.cpp │ └── setup.cpp └── twotasks │ ├── Jamfile │ └── twotasks.ino ├── heap_1.c ├── list.c ├── list.h ├── mpu_wrappers.h ├── port.c ├── portable.h ├── portmacro.h ├── projdefs.h ├── queue.c ├── queue.h ├── semphr.h ├── task.h ├── tasks.c ├── timers.c └── timers.h /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | version.h 3 | 16000000/ 4 | out/ 5 | -------------------------------------------------------------------------------- /FreeRTOS.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | #ifndef INC_FREERTOS_H 55 | #define INC_FREERTOS_H 56 | 57 | 58 | /* 59 | * Include the generic headers required for the FreeRTOS port being used. 60 | */ 61 | #include 62 | 63 | /* Basic FreeRTOS definitions. */ 64 | #include "projdefs.h" 65 | 66 | /* Application specific configuration options. */ 67 | #include 68 | 69 | /* Definitions specific to the port being used. */ 70 | #include "portable.h" 71 | 72 | 73 | /* Defines the prototype to which the application task hook function must 74 | conform. */ 75 | typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); 76 | 77 | 78 | 79 | 80 | 81 | /* 82 | * Check all the required application specific macros have been defined. 83 | * These macros are application specific and (as downloaded) are defined 84 | * within FreeRTOSConfig.h. 85 | */ 86 | 87 | #ifndef configUSE_PREEMPTION 88 | #error Missing definition: configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 89 | #endif 90 | 91 | #ifndef configUSE_IDLE_HOOK 92 | #error Missing definition: configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 93 | #endif 94 | 95 | #ifndef configUSE_TICK_HOOK 96 | #error Missing definition: configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 97 | #endif 98 | 99 | #ifndef configUSE_CO_ROUTINES 100 | #error Missing definition: configUSE_CO_ROUTINES should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 101 | #endif 102 | 103 | #ifndef INCLUDE_vTaskPrioritySet 104 | #error Missing definition: INCLUDE_vTaskPrioritySet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 105 | #endif 106 | 107 | #ifndef INCLUDE_uxTaskPriorityGet 108 | #error Missing definition: INCLUDE_uxTaskPriorityGet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 109 | #endif 110 | 111 | #ifndef INCLUDE_vTaskDelete 112 | #error Missing definition: INCLUDE_vTaskDelete should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 113 | #endif 114 | 115 | #ifndef INCLUDE_vTaskSuspend 116 | #error Missing definition: INCLUDE_vTaskSuspend should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 117 | #endif 118 | 119 | #ifndef INCLUDE_vTaskDelayUntil 120 | #error Missing definition: INCLUDE_vTaskDelayUntil should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 121 | #endif 122 | 123 | #ifndef INCLUDE_vTaskDelay 124 | #error Missing definition: INCLUDE_vTaskDelay should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 125 | #endif 126 | 127 | #ifndef configUSE_16_BIT_TICKS 128 | #error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. 129 | #endif 130 | 131 | #ifndef INCLUDE_xTaskGetIdleTaskHandle 132 | #define INCLUDE_xTaskGetIdleTaskHandle 0 133 | #endif 134 | 135 | #ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle 136 | #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 137 | #endif 138 | 139 | #ifndef INCLUDE_pcTaskGetTaskName 140 | #define INCLUDE_pcTaskGetTaskName 0 141 | #endif 142 | 143 | #ifndef configUSE_APPLICATION_TASK_TAG 144 | #define configUSE_APPLICATION_TASK_TAG 0 145 | #endif 146 | 147 | #ifndef INCLUDE_uxTaskGetStackHighWaterMark 148 | #define INCLUDE_uxTaskGetStackHighWaterMark 0 149 | #endif 150 | 151 | #ifndef configUSE_RECURSIVE_MUTEXES 152 | #define configUSE_RECURSIVE_MUTEXES 0 153 | #endif 154 | 155 | #ifndef configUSE_MUTEXES 156 | #define configUSE_MUTEXES 0 157 | #endif 158 | 159 | #ifndef configUSE_TIMERS 160 | #define configUSE_TIMERS 0 161 | #endif 162 | 163 | #ifndef configUSE_COUNTING_SEMAPHORES 164 | #define configUSE_COUNTING_SEMAPHORES 0 165 | #endif 166 | 167 | #ifndef configUSE_ALTERNATIVE_API 168 | #define configUSE_ALTERNATIVE_API 0 169 | #endif 170 | 171 | #ifndef portCRITICAL_NESTING_IN_TCB 172 | #define portCRITICAL_NESTING_IN_TCB 0 173 | #endif 174 | 175 | #ifndef configMAX_TASK_NAME_LEN 176 | #define configMAX_TASK_NAME_LEN 16 177 | #endif 178 | 179 | #ifndef configIDLE_SHOULD_YIELD 180 | #define configIDLE_SHOULD_YIELD 1 181 | #endif 182 | 183 | #if configMAX_TASK_NAME_LEN < 1 184 | #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h 185 | #endif 186 | 187 | #ifndef INCLUDE_xTaskResumeFromISR 188 | #define INCLUDE_xTaskResumeFromISR 1 189 | #endif 190 | 191 | #ifndef configASSERT 192 | #define configASSERT( x ) 193 | #endif 194 | 195 | #ifndef portALIGNMENT_ASSERT_pxCurrentTCB 196 | #define portALIGNMENT_ASSERT_pxCurrentTCB configASSERT 197 | #endif 198 | 199 | /* The timers module relies on xTaskGetSchedulerState(). */ 200 | #if configUSE_TIMERS == 1 201 | 202 | #ifndef configTIMER_TASK_PRIORITY 203 | #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. 204 | #endif /* configTIMER_TASK_PRIORITY */ 205 | 206 | #ifndef configTIMER_QUEUE_LENGTH 207 | #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. 208 | #endif /* configTIMER_QUEUE_LENGTH */ 209 | 210 | #ifndef configTIMER_TASK_STACK_DEPTH 211 | #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. 212 | #endif /* configTIMER_TASK_STACK_DEPTH */ 213 | 214 | #endif /* configUSE_TIMERS */ 215 | 216 | #ifndef INCLUDE_xTaskGetSchedulerState 217 | #define INCLUDE_xTaskGetSchedulerState 0 218 | #endif 219 | 220 | #ifndef INCLUDE_xTaskGetCurrentTaskHandle 221 | #define INCLUDE_xTaskGetCurrentTaskHandle 0 222 | #endif 223 | 224 | 225 | #ifndef portSET_INTERRUPT_MASK_FROM_ISR 226 | #define portSET_INTERRUPT_MASK_FROM_ISR() 0 227 | #endif 228 | 229 | #ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR 230 | #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue 231 | #endif 232 | 233 | #ifndef portCLEAN_UP_TCB 234 | #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB 235 | #endif 236 | 237 | #ifndef configQUEUE_REGISTRY_SIZE 238 | #define configQUEUE_REGISTRY_SIZE 0U 239 | #endif 240 | 241 | #if ( configQUEUE_REGISTRY_SIZE < 1 ) 242 | #define vQueueAddToRegistry( xQueue, pcName ) 243 | #define vQueueUnregisterQueue( xQueue ) 244 | #endif 245 | 246 | #ifndef portPOINTER_SIZE_TYPE 247 | #define portPOINTER_SIZE_TYPE uint16_t 248 | #endif 249 | 250 | /* Remove any unused trace macros. */ 251 | #ifndef traceSTART 252 | /* Used to perform any necessary initialisation - for example, open a file 253 | into which trace is to be written. */ 254 | #define traceSTART() 255 | #endif 256 | 257 | #ifndef traceEND 258 | /* Use to close a trace, for example close a file into which trace has been 259 | written. */ 260 | #define traceEND() 261 | #endif 262 | 263 | #ifndef traceTASK_SWITCHED_IN 264 | /* Called after a task has been selected to run. pxCurrentTCB holds a pointer 265 | to the task control block of the selected task. */ 266 | #define traceTASK_SWITCHED_IN() 267 | #endif 268 | 269 | #ifndef traceTASK_SWITCHED_OUT 270 | /* Called before a task has been selected to run. pxCurrentTCB holds a pointer 271 | to the task control block of the task being switched out. */ 272 | #define traceTASK_SWITCHED_OUT() 273 | #endif 274 | 275 | #ifndef traceTASK_PRIORITY_INHERIT 276 | /* Called when a task attempts to take a mutex that is already held by a 277 | lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task 278 | that holds the mutex. uxInheritedPriority is the priority the mutex holder 279 | will inherit (the priority of the task that is attempting to obtain the 280 | muted. */ 281 | #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) 282 | #endif 283 | 284 | #ifndef traceTASK_PRIORITY_DISINHERIT 285 | /* Called when a task releases a mutex, the holding of which had resulted in 286 | the task inheriting the priority of a higher priority task. 287 | pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the 288 | mutex. uxOriginalPriority is the task's configured (base) priority. */ 289 | #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) 290 | #endif 291 | 292 | #ifndef traceBLOCKING_ON_QUEUE_RECEIVE 293 | /* Task is about to block because it cannot read from a 294 | queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore 295 | upon which the read was attempted. pxCurrentTCB points to the TCB of the 296 | task that attempted the read. */ 297 | #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) 298 | #endif 299 | 300 | #ifndef traceBLOCKING_ON_QUEUE_SEND 301 | /* Task is about to block because it cannot write to a 302 | queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore 303 | upon which the write was attempted. pxCurrentTCB points to the TCB of the 304 | task that attempted the write. */ 305 | #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) 306 | #endif 307 | 308 | #ifndef configCHECK_FOR_STACK_OVERFLOW 309 | #define configCHECK_FOR_STACK_OVERFLOW 0 310 | #endif 311 | 312 | /* The following event macros are embedded in the kernel API calls. */ 313 | 314 | #ifndef traceQUEUE_CREATE 315 | #define traceQUEUE_CREATE( pxNewQueue ) 316 | #endif 317 | 318 | #ifndef traceQUEUE_CREATE_FAILED 319 | #define traceQUEUE_CREATE_FAILED( ucQueueType ) 320 | #endif 321 | 322 | #ifndef traceCREATE_MUTEX 323 | #define traceCREATE_MUTEX( pxNewQueue ) 324 | #endif 325 | 326 | #ifndef traceCREATE_MUTEX_FAILED 327 | #define traceCREATE_MUTEX_FAILED() 328 | #endif 329 | 330 | #ifndef traceGIVE_MUTEX_RECURSIVE 331 | #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) 332 | #endif 333 | 334 | #ifndef traceGIVE_MUTEX_RECURSIVE_FAILED 335 | #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) 336 | #endif 337 | 338 | #ifndef traceTAKE_MUTEX_RECURSIVE 339 | #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) 340 | #endif 341 | 342 | #ifndef traceTAKE_MUTEX_RECURSIVE_FAILED 343 | #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) 344 | #endif 345 | 346 | #ifndef traceCREATE_COUNTING_SEMAPHORE 347 | #define traceCREATE_COUNTING_SEMAPHORE() 348 | #endif 349 | 350 | #ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED 351 | #define traceCREATE_COUNTING_SEMAPHORE_FAILED() 352 | #endif 353 | 354 | #ifndef traceQUEUE_SEND 355 | #define traceQUEUE_SEND( pxQueue ) 356 | #endif 357 | 358 | #ifndef traceQUEUE_SEND_FAILED 359 | #define traceQUEUE_SEND_FAILED( pxQueue ) 360 | #endif 361 | 362 | #ifndef traceQUEUE_RECEIVE 363 | #define traceQUEUE_RECEIVE( pxQueue ) 364 | #endif 365 | 366 | #ifndef traceQUEUE_PEEK 367 | #define traceQUEUE_PEEK( pxQueue ) 368 | #endif 369 | 370 | #ifndef traceQUEUE_RECEIVE_FAILED 371 | #define traceQUEUE_RECEIVE_FAILED( pxQueue ) 372 | #endif 373 | 374 | #ifndef traceQUEUE_SEND_FROM_ISR 375 | #define traceQUEUE_SEND_FROM_ISR( pxQueue ) 376 | #endif 377 | 378 | #ifndef traceQUEUE_SEND_FROM_ISR_FAILED 379 | #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) 380 | #endif 381 | 382 | #ifndef traceQUEUE_RECEIVE_FROM_ISR 383 | #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) 384 | #endif 385 | 386 | #ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED 387 | #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) 388 | #endif 389 | 390 | #ifndef traceQUEUE_DELETE 391 | #define traceQUEUE_DELETE( pxQueue ) 392 | #endif 393 | 394 | #ifndef traceTASK_CREATE 395 | #define traceTASK_CREATE( pxNewTCB ) 396 | #endif 397 | 398 | #ifndef traceTASK_CREATE_FAILED 399 | #define traceTASK_CREATE_FAILED() 400 | #endif 401 | 402 | #ifndef traceTASK_DELETE 403 | #define traceTASK_DELETE( pxTaskToDelete ) 404 | #endif 405 | 406 | #ifndef traceTASK_DELAY_UNTIL 407 | #define traceTASK_DELAY_UNTIL() 408 | #endif 409 | 410 | #ifndef traceTASK_DELAY 411 | #define traceTASK_DELAY() 412 | #endif 413 | 414 | #ifndef traceTASK_PRIORITY_SET 415 | #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) 416 | #endif 417 | 418 | #ifndef traceTASK_SUSPEND 419 | #define traceTASK_SUSPEND( pxTaskToSuspend ) 420 | #endif 421 | 422 | #ifndef traceTASK_RESUME 423 | #define traceTASK_RESUME( pxTaskToResume ) 424 | #endif 425 | 426 | #ifndef traceTASK_RESUME_FROM_ISR 427 | #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) 428 | #endif 429 | 430 | #ifndef traceTASK_INCREMENT_TICK 431 | #define traceTASK_INCREMENT_TICK( xTickCount ) 432 | #endif 433 | 434 | #ifndef traceTIMER_CREATE 435 | #define traceTIMER_CREATE( pxNewTimer ) 436 | #endif 437 | 438 | #ifndef traceTIMER_CREATE_FAILED 439 | #define traceTIMER_CREATE_FAILED() 440 | #endif 441 | 442 | #ifndef traceTIMER_COMMAND_SEND 443 | #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) 444 | #endif 445 | 446 | #ifndef traceTIMER_EXPIRED 447 | #define traceTIMER_EXPIRED( pxTimer ) 448 | #endif 449 | 450 | #ifndef traceTIMER_COMMAND_RECEIVED 451 | #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) 452 | #endif 453 | 454 | #ifndef configGENERATE_RUN_TIME_STATS 455 | #define configGENERATE_RUN_TIME_STATS 0 456 | #endif 457 | 458 | #if ( configGENERATE_RUN_TIME_STATS == 1 ) 459 | 460 | #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS 461 | #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. 462 | #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ 463 | 464 | #ifndef portGET_RUN_TIME_COUNTER_VALUE 465 | #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE 466 | #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. 467 | #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ 468 | #endif /* portGET_RUN_TIME_COUNTER_VALUE */ 469 | 470 | #endif /* configGENERATE_RUN_TIME_STATS */ 471 | 472 | #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS 473 | #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() 474 | #endif 475 | 476 | #ifndef configUSE_MALLOC_FAILED_HOOK 477 | #define configUSE_MALLOC_FAILED_HOOK 0 478 | #endif 479 | 480 | #ifndef portPRIVILEGE_BIT 481 | #define portPRIVILEGE_BIT ( ( unsigned portBASE_TYPE ) 0x00 ) 482 | #endif 483 | 484 | #ifndef portYIELD_WITHIN_API 485 | #define portYIELD_WITHIN_API portYIELD 486 | #endif 487 | 488 | #ifndef pvPortMallocAligned 489 | #define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) ) 490 | #endif 491 | 492 | #ifndef vPortFreeAligned 493 | #define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree ) 494 | #endif 495 | 496 | #endif /* INC_FREERTOS_H */ 497 | 498 | -------------------------------------------------------------------------------- /FreeRTOSConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | #ifndef FREERTOS_CONFIG_H 55 | #define FREERTOS_CONFIG_H 56 | 57 | #include 58 | 59 | /*----------------------------------------------------------- 60 | * Application specific definitions. 61 | * 62 | * These definitions should be adjusted for your particular hardware and 63 | * application requirements. 64 | * 65 | * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE 66 | * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. 67 | * 68 | * See http://www.freertos.org/a00110.html. 69 | *----------------------------------------------------------*/ 70 | 71 | #define configUSE_PREEMPTION 1 72 | #define configUSE_IDLE_HOOK 0 73 | #define configUSE_TICK_HOOK 0 74 | #define configCPU_CLOCK_HZ ( ( unsigned long ) F_CPU ) 75 | #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) 76 | #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 4 ) 77 | #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 100 ) 78 | #define configTOTAL_HEAP_SIZE ( (size_t ) ( 1500 ) ) 79 | #define configMAX_TASK_NAME_LEN ( 8 ) 80 | #define configUSE_TRACE_FACILITY 0 81 | #define configUSE_16_BIT_TICKS 1 82 | #define configIDLE_SHOULD_YIELD 1 83 | #define configQUEUE_REGISTRY_SIZE 1 84 | #define configUSE_MUTEXES 1 85 | 86 | /* Co-routine definitions. */ 87 | #define configUSE_CO_ROUTINES 0 88 | #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) 89 | 90 | /* Set the following definitions to 1 to include the API function, or zero 91 | to exclude the API function. */ 92 | 93 | #define INCLUDE_vTaskPrioritySet 0 94 | #define INCLUDE_uxTaskPriorityGet 0 95 | #define INCLUDE_vTaskDelete 0 96 | #define INCLUDE_vTaskCleanUpResources 0 97 | #define INCLUDE_vTaskSuspend 0 98 | #define INCLUDE_vTaskDelayUntil 1 99 | #define INCLUDE_vTaskDelay 1 100 | #define INCLUDE_uxTaskGetStackHighWaterMark 1 101 | 102 | #endif /* FREERTOS_CONFIG_H */ 103 | -------------------------------------------------------------------------------- /FreeRTOSConfig_328p.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | #ifndef FREERTOS_CONFIG_H 55 | #define FREERTOS_CONFIG_H 56 | 57 | #include 58 | 59 | /*----------------------------------------------------------- 60 | * Application specific definitions. 61 | * 62 | * These definitions should be adjusted for your particular hardware and 63 | * application requirements. 64 | * 65 | * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE 66 | * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. 67 | * 68 | * See http://www.freertos.org/a00110.html. 69 | *----------------------------------------------------------*/ 70 | 71 | #define configUSE_PREEMPTION 1 72 | #define configUSE_IDLE_HOOK 0 73 | #define configUSE_TICK_HOOK 0 74 | #define configCPU_CLOCK_HZ ( ( unsigned long ) F_CPU ) 75 | #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) 76 | #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 4 ) 77 | #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 100 ) 78 | #define configTOTAL_HEAP_SIZE ( (size_t ) ( 1500 ) ) 79 | #define configMAX_TASK_NAME_LEN ( 8 ) 80 | #define configUSE_TRACE_FACILITY 0 81 | #define configUSE_16_BIT_TICKS 1 82 | #define configIDLE_SHOULD_YIELD 1 83 | #define configQUEUE_REGISTRY_SIZE 1 84 | #define configUSE_MUTEXES 1 85 | 86 | /* Co-routine definitions. */ 87 | #define configUSE_CO_ROUTINES 0 88 | #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) 89 | 90 | /* Set the following definitions to 1 to include the API function, or zero 91 | to exclude the API function. */ 92 | 93 | #define INCLUDE_vTaskPrioritySet 0 94 | #define INCLUDE_uxTaskPriorityGet 0 95 | #define INCLUDE_vTaskDelete 0 96 | #define INCLUDE_vTaskCleanUpResources 0 97 | #define INCLUDE_vTaskSuspend 0 98 | #define INCLUDE_vTaskDelayUntil 1 99 | #define INCLUDE_vTaskDelay 1 100 | #define INCLUDE_uxTaskGetStackHighWaterMark 1 101 | 102 | #endif /* FREERTOS_CONFIG_H */ 103 | -------------------------------------------------------------------------------- /Jamfile: -------------------------------------------------------------------------------- 1 | ORIGINAL_DIR = $(HOME)/Source/Arduino/1284P/FreeRTOS ; 2 | 3 | rule Files 4 | { 5 | for _i in $(>) 6 | { 7 | if ( $(_i:B) != FreeRTOSConfig ) 8 | { 9 | local _o = $(_i:D=$(<)) ; 10 | File $(_o) : $(_i) ; 11 | Depends $(_o) : $(<) ; 12 | Clean clean : $(_o) ; 13 | MkDir $(<) ; 14 | Depends files : $(_o) ; 15 | } 16 | } 17 | } 18 | 19 | Files $(PWD) : [ GLOB $(ORIGINAL_DIR) : *.c ] [ GLOB $(ORIGINAL_DIR)/include : *.h ] ; 20 | 21 | Files $(PWD)/examples/blinky : [ GLOB $(ORIGINAL_DIR)/ex01_blinky : *.cpp *.pde *.ino ] ; 22 | Files $(PWD)/examples/twotasks : [ GLOB $(ORIGINAL_DIR)/ex02_twotasks : *.cpp *.pde *.ino ] ; 23 | Files $(PWD)/examples/buttonled : [ GLOB $(ORIGINAL_DIR)/ex03_buttonled : *.cpp *.pde *.ino ] ; 24 | Files $(PWD)/examples/manybuttons : [ GLOB $(ORIGINAL_DIR)/ex04_manybuttons : *.cpp *.pde *.ino ] ; 25 | Files $(PWD)/examples/pingpair : [ GLOB $(ORIGINAL_DIR)/pingpair_freertos : *.cpp *.pde *.ino *.h ] ; 26 | 27 | SubDir TOP ; 28 | 29 | SubInclude TOP examples ; 30 | -------------------------------------------------------------------------------- /Jamrules: -------------------------------------------------------------------------------- 1 | 2 | # (2) Board Information 3 | 4 | UPLOAD_PROTOCOL ?= arduino ; 5 | UPLOAD_SPEED ?= 115200 ; 6 | MCU ?= atmega328p ; 7 | F_CPU ?= 16000000 ; 8 | CORE ?= arduino ; 9 | VARIANT ?= standard ; 10 | ARDUINO_VERSION ?= 100 ; 11 | 12 | # (3) USB Ports 13 | 14 | PORTS = p4 p6 p9 u0 u1 u2 ; 15 | PORT_p6 = /dev/tty.usbserial-A600eHIs ; 16 | PORT_p4 = /dev/tty.usbserial-A40081RP ; 17 | PORT_p9 = /dev/tty.usbserial-A9007LmI ; 18 | PORT_u0 = /dev/ttyUSB0 ; 19 | PORT_u1 = /dev/ttyUSB1 ; 20 | PORT_u2 = /dev/ttyUSB2 ; 21 | 22 | # (4) Location of AVR tools 23 | # 24 | # This configuration assumes using avr-tools that were obtained separate from the Arduino 25 | # distribution. 26 | 27 | if $(OS) = MACOSX 28 | { 29 | AVR_BIN ?= /usr/local/avrtools/bin ; 30 | AVR_ETC = /usr/local/avrtools/etc ; 31 | AVR_INCLUDE = /usr/local/avrtools/include ; 32 | } 33 | else 34 | { 35 | AVR_BIN ?= /usr/bin ; 36 | AVR_INCLUDE ?= /usr/lib/avr/include ; 37 | AVR_ETC = /etc ; 38 | } 39 | 40 | # (5) Directories where Arduino core and libraries are located 41 | 42 | SKETCH_DIR = $(HOME)/Source/Arduino ; 43 | ARDUINO_DIR ?= /opt/Arduino ; 44 | ARDUINO_CORE ?= $(ARDUINO_DIR)/hardware/arduino/cores/$(CORE) $(ARDUINO_DIR)/hardware/arduino/variants/$(VARIANT) ; 45 | ARDUINO_LIB = $(ARDUINO_DIR)/libraries ; 46 | SKETCH_LIB = $(HOME)/Source/Arduino/libraries ; 47 | MODULE_EXT = *.c *.cpp *.S *.pde *.ino *.test ; 48 | 49 | # 50 | # -------------------------------------------------- 51 | # Below this line usually never needs to be modified 52 | # 53 | 54 | # Tool locations 55 | 56 | CC = $(AVR_BIN)/avr-gcc ; 57 | C++ = $(AVR_BIN)/avr-g++ ; 58 | LINK = $(AVR_BIN)/avr-gcc ; 59 | AR = $(AVR_BIN)/avr-ar rcs ; 60 | RANLIB = ; 61 | OBJCOPY = $(AVR_BIN)/avr-objcopy ; 62 | AVRDUDE ?= $(AVR_BIN)/avrdude ; 63 | 64 | CXXTEST_DIR = $(HOME)/Source/cxxtest ; 65 | CXXTEST_GEN = $(CXXTEST_DIR)/bin/cxxtestgen ; 66 | 67 | # Flags 68 | 69 | DEFINES += F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H $(PINS) ETHERSHIELD ; 70 | OPTIM = -Os ; 71 | CCFLAGS = -Wall -Wextra -Wno-strict-aliasing -save-temps=obj -mmcu=$(MCU) -ffunction-sections -fdata-sections "-include $(PINS).h" ; 72 | C++FLAGS = $(CCFLAGS) -fno-exceptions -fno-strict-aliasing ; 73 | LINKFLAGS = $(OPTIM) -lm -Wl,--gc-sections -mmcu=$(MCU) ; 74 | AVRDUDEFLAGS = -V -F -D -C $(AVR_ETC)/avrdude.conf -p $(MCU) -c $(UPLOAD_PROTOCOL) -b $(UPLOAD_SPEED) ; 75 | 76 | # Search everywhere for headers 77 | 78 | HDRS = $(TOP)/include $(CXXTEST_DIR) $(AVR_INCLUDE) $(ARDUINO_CORE) ; 79 | LOCATE_TARGET = $(TOP)/$(F_CPU) ; 80 | LINKLIBS = $(LOCATE_TARGET)/core.a ; 81 | 82 | # 83 | # Custom rules 84 | # 85 | 86 | rule GitVersion 87 | { 88 | Always $(<) ; 89 | Depends all : $(<) ; 90 | } 91 | 92 | actions GitVersion 93 | { 94 | echo "const char program_version[] = \"\\" > $(<) 95 | git log -1 --pretty=format:%h >> $(<) 96 | echo "\";" >> $(<) 97 | } 98 | 99 | GitVersion version.h ; 100 | 101 | rule Xxd 102 | { 103 | Depends $(<) : $(>) ; 104 | Depends $(<) : $(<:D) ; 105 | MkDir $(<:D) ; 106 | MakeLocate $(<) : $(LOCATE_SOURCE) ; 107 | Clean clean : $(<) ; 108 | } 109 | 110 | actions Xxd 111 | { 112 | xxd -i $(>) | gawk -f xxd.awk > $(<) 113 | } 114 | 115 | rule C++Xxd 116 | { 117 | local _CPP = $(>:B).cpp ; 118 | Xxd $(_CPP) : $(>) ; 119 | C++ $(<) : $(_CPP) ; 120 | } 121 | 122 | rule BinaryObject 123 | { 124 | Depends $(<) : $(>) ; 125 | MakeLocate $(<) : $(LOCATE_TARGET) ; 126 | Clean clean : $(<) ; 127 | } 128 | 129 | actions BinaryObject 130 | { 131 | avr-objcopy --rename-section .data=.progmem.data,contents,alloc,load,readonly,data -I binary -O elf32-avr $(>) $(<) 132 | } 133 | 134 | rule Pde 135 | { 136 | Depends $(<) : $(>) ; 137 | MakeLocate $(<) : $(LOCATE_SOURCE) ; 138 | Clean clean : $(<) ; 139 | } 140 | 141 | if ( $(ARDUINO_VERSION) < 100 ) 142 | { 143 | ARDUINO_H = WProgram.h ; 144 | } 145 | else 146 | { 147 | ARDUINO_H = Arduino.h ; 148 | } 149 | 150 | actions Pde 151 | { 152 | echo "#include <$(ARDUINO_H)>" > $(<) 153 | echo "#line 1 \"$(>)\"" >> $(<) 154 | cat $(>) >> $(<) 155 | } 156 | 157 | rule C++Pde 158 | { 159 | local _CPP = $(>:B).cpp ; 160 | Pde $(_CPP) : $(>) ; 161 | C++ $(<) : $(_CPP) ; 162 | } 163 | 164 | rule TestSuite 165 | { 166 | Depends $(<) : $(>) ; 167 | MakeLocate $(<) : $(LOCATE_SOURCE) ; 168 | Clean clean : $(<) ; 169 | } 170 | 171 | actions TestSuite 172 | { 173 | $(CXXTEST_GEN) --part $(>) > $(<) 174 | } 175 | 176 | rule TestRoot 177 | { 178 | Depends $(<) : $(SEARCH_SOURCE)/main.tpl ; 179 | MakeLocate $(<) : $(LOCATE_SOURCE) ; 180 | } 181 | 182 | actions TestRoot 183 | { 184 | $(CXXTEST_GEN) --root --template main.tpl > $(<) 185 | } 186 | 187 | rule C++TestSuite 188 | { 189 | local _CPP = $(>:B).cpp ; 190 | TestSuite $(_CPP) : $(>) ; 191 | HDRS on $(<) += $(TOP) ; 192 | C++ $(<) : $(_CPP) ; 193 | } 194 | 195 | rule UserObject 196 | { 197 | switch $(>:S) 198 | { 199 | case .ino : C++Pde $(<) : $(>) ; 200 | case .pde : C++Pde $(<) : $(>) ; 201 | case .test : C++TestSuite $(<) : $(>) ; 202 | case .txt : BinaryObject $(<) : $(>) ; 203 | } 204 | } 205 | 206 | rule Objects 207 | { 208 | local _i ; 209 | 210 | for _i in [ FGristFiles $(<) ] 211 | { 212 | local _b = $(_i:B)$(SUFOBJ) ; 213 | local _o = $(_b:G=$(SOURCE_GRIST:E)) ; 214 | Object $(_o) : $(_i) ; 215 | Depends obj : $(_o) ; 216 | } 217 | } 218 | 219 | rule Library 220 | { 221 | LibraryFromObjects $(<) : $(>:B)$(SUFOBJ) ; 222 | MakeLocate $(<) : $(LOCATE_TARGET) ; 223 | Objects $(>) ; 224 | 225 | Depends $(<) : $(<:D) ; 226 | MkDir $(<:D) ; 227 | } 228 | 229 | rule Main 230 | { 231 | MainFromObjects $(<) : $(>:B)$(SUFOBJ) ; 232 | Depends $(<) : $(<:D) ; 233 | MkDir $(<:D) ; 234 | Objects $(>) ; 235 | } 236 | 237 | rule Hex 238 | { 239 | Depends $(<) : $(>) ; 240 | MakeLocate $(<) : $(LOCATE_TARGET) ; 241 | Depends hex : $(<) ; 242 | Clean clean : $(<) ; 243 | } 244 | 245 | actions Hex 246 | { 247 | $(OBJCOPY) -O ihex -R .eeprom $(>) $(<) 248 | } 249 | 250 | rule Upload 251 | { 252 | Depends $(1) : $(2) ; 253 | Depends $(2) : $(3) ; 254 | NotFile $(1) ; 255 | Always $(1) ; 256 | Always $(2) ; 257 | UploadAction $(2) : $(3) ; 258 | } 259 | 260 | actions UploadAction 261 | { 262 | $(AVRDUDE) $(AVRDUDEFLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i 263 | } 264 | 265 | rule Arduino 266 | { 267 | LINKFLAGS on $(<) = $(LINKFLAGS) -Wl,-Map=$(LOCATE_TARGET)/$(<:B).map ; 268 | Main $(<) : $(>) ; 269 | Depends $(<) : core.a ; 270 | Hex $(<:B).hex : $(<) ; 271 | for _p in $(PORTS) 272 | { 273 | Upload $(_p) : $(PORT_$(_p)) : $(<:B).hex ; 274 | } 275 | } 276 | 277 | # 278 | # Targets 279 | # 280 | 281 | # Grab everything from the core directory 282 | Library core : [ GLOB $(ARDUINO_CORE) : $(MODULE_EXT) ] ; 283 | -------------------------------------------------------------------------------- /StackMacros.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | #ifndef STACK_MACROS_H 55 | #define STACK_MACROS_H 56 | 57 | /* 58 | * Call the stack overflow hook function if the stack of the task being swapped 59 | * out is currently overflowed, or looks like it might have overflowed in the 60 | * past. 61 | * 62 | * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check 63 | * the current stack state only - comparing the current top of stack value to 64 | * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 65 | * will also cause the last few stack bytes to be checked to ensure the value 66 | * to which the bytes were set when the task was created have not been 67 | * overwritten. Note this second test does not guarantee that an overflowed 68 | * stack will always be recognised. 69 | */ 70 | 71 | /*-----------------------------------------------------------*/ 72 | 73 | #if( configCHECK_FOR_STACK_OVERFLOW == 0 ) 74 | 75 | /* FreeRTOSConfig.h is not set to check for stack overflows. */ 76 | #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() 77 | #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() 78 | 79 | #endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ 80 | /*-----------------------------------------------------------*/ 81 | 82 | #if( configCHECK_FOR_STACK_OVERFLOW == 1 ) 83 | 84 | /* FreeRTOSConfig.h is only set to use the first method of 85 | overflow checking. */ 86 | #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() 87 | 88 | #endif 89 | /*-----------------------------------------------------------*/ 90 | 91 | #if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) 92 | 93 | /* Only the current stack state is to be checked. */ 94 | #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ 95 | { \ 96 | /* Is the currently saved stack pointer within the stack limit? */ \ 97 | if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ 98 | { \ 99 | vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ 100 | } \ 101 | } 102 | 103 | #endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */ 104 | /*-----------------------------------------------------------*/ 105 | 106 | #if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) 107 | 108 | /* Only the current stack state is to be checked. */ 109 | #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ 110 | { \ 111 | \ 112 | /* Is the currently saved stack pointer within the stack limit? */ \ 113 | if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ 114 | { \ 115 | vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ 116 | } \ 117 | } 118 | 119 | #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ 120 | /*-----------------------------------------------------------*/ 121 | 122 | #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) 123 | 124 | #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ 125 | { \ 126 | static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 127 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 128 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 129 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 130 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ 131 | \ 132 | \ 133 | /* Has the extremity of the task stack ever been written over? */ \ 134 | if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ 135 | { \ 136 | vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ 137 | } \ 138 | } 139 | 140 | #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ 141 | /*-----------------------------------------------------------*/ 142 | 143 | #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) 144 | 145 | #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ 146 | { \ 147 | char *pcEndOfStack = ( char * ) pxCurrentTCB->pxEndOfStack; \ 148 | static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 149 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 150 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 151 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 152 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ 153 | \ 154 | \ 155 | pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ 156 | \ 157 | /* Has the extremity of the task stack ever been written over? */ \ 158 | if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ 159 | { \ 160 | vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ 161 | } \ 162 | } 163 | 164 | #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ 165 | /*-----------------------------------------------------------*/ 166 | 167 | #endif /* STACK_MACROS_H */ 168 | 169 | -------------------------------------------------------------------------------- /croutine.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | #ifndef CO_ROUTINE_H 55 | #define CO_ROUTINE_H 56 | 57 | #ifndef INC_FREERTOS_H 58 | #error "include FreeRTOS.h must appear in source files before include croutine.h" 59 | #endif 60 | 61 | #include "list.h" 62 | 63 | #ifdef __cplusplus 64 | extern "C" { 65 | #endif 66 | 67 | /* Used to hide the implementation of the co-routine control block. The 68 | control block structure however has to be included in the header due to 69 | the macro implementation of the co-routine functionality. */ 70 | typedef void * xCoRoutineHandle; 71 | 72 | /* Defines the prototype to which co-routine functions must conform. */ 73 | typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE ); 74 | 75 | typedef struct corCoRoutineControlBlock 76 | { 77 | crCOROUTINE_CODE pxCoRoutineFunction; 78 | xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ 79 | xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */ 80 | unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ 81 | unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ 82 | unsigned short uxState; /*< Used internally by the co-routine implementation. */ 83 | } corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */ 84 | 85 | /** 86 | * croutine. h 87 | *
 88 |  portBASE_TYPE xCoRoutineCreate(
 89 |                                  crCOROUTINE_CODE pxCoRoutineCode,
 90 |                                  unsigned portBASE_TYPE uxPriority,
 91 |                                  unsigned portBASE_TYPE uxIndex
 92 |                                );
93 | * 94 | * Create a new co-routine and add it to the list of co-routines that are 95 | * ready to run. 96 | * 97 | * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine 98 | * functions require special syntax - see the co-routine section of the WEB 99 | * documentation for more information. 100 | * 101 | * @param uxPriority The priority with respect to other co-routines at which 102 | * the co-routine will run. 103 | * 104 | * @param uxIndex Used to distinguish between different co-routines that 105 | * execute the same function. See the example below and the co-routine section 106 | * of the WEB documentation for further information. 107 | * 108 | * @return pdPASS if the co-routine was successfully created and added to a ready 109 | * list, otherwise an error code defined with ProjDefs.h. 110 | * 111 | * Example usage: 112 |
113 |  // Co-routine to be created.
114 |  void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
115 |  {
116 |  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
117 |  // This may not be necessary for const variables.
118 |  static const char cLedToFlash[ 2 ] = { 5, 6 };
119 |  static const portTickType uxFlashRates[ 2 ] = { 200, 400 };
120 | 
121 |      // Must start every co-routine with a call to crSTART();
122 |      crSTART( xHandle );
123 | 
124 |      for( ;; )
125 |      {
126 |          // This co-routine just delays for a fixed period, then toggles
127 |          // an LED.  Two co-routines are created using this function, so
128 |          // the uxIndex parameter is used to tell the co-routine which
129 |          // LED to flash and how long to delay.  This assumes xQueue has
130 |          // already been created.
131 |          vParTestToggleLED( cLedToFlash[ uxIndex ] );
132 |          crDELAY( xHandle, uxFlashRates[ uxIndex ] );
133 |      }
134 | 
135 |      // Must end every co-routine with a call to crEND();
136 |      crEND();
137 |  }
138 | 
139 |  // Function that creates two co-routines.
140 |  void vOtherFunction( void )
141 |  {
142 |  unsigned char ucParameterToPass;
143 |  xTaskHandle xHandle;
144 | 		
145 |      // Create two co-routines at priority 0.  The first is given index 0
146 |      // so (from the code above) toggles LED 5 every 200 ticks.  The second
147 |      // is given index 1 so toggles LED 6 every 400 ticks.
148 |      for( uxIndex = 0; uxIndex < 2; uxIndex++ )
149 |      {
150 |          xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
151 |      }
152 |  }
153 |    
154 | * \defgroup xCoRoutineCreate xCoRoutineCreate 155 | * \ingroup Tasks 156 | */ 157 | signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ); 158 | 159 | 160 | /** 161 | * croutine. h 162 | *
163 |  void vCoRoutineSchedule( void );
164 | * 165 | * Run a co-routine. 166 | * 167 | * vCoRoutineSchedule() executes the highest priority co-routine that is able 168 | * to run. The co-routine will execute until it either blocks, yields or is 169 | * preempted by a task. Co-routines execute cooperatively so one 170 | * co-routine cannot be preempted by another, but can be preempted by a task. 171 | * 172 | * If an application comprises of both tasks and co-routines then 173 | * vCoRoutineSchedule should be called from the idle task (in an idle task 174 | * hook). 175 | * 176 | * Example usage: 177 |
178 |  // This idle task hook will schedule a co-routine each time it is called.
179 |  // The rest of the idle task will execute between co-routine calls.
180 |  void vApplicationIdleHook( void )
181 |  {
182 | 	vCoRoutineSchedule();
183 |  }
184 | 
185 |  // Alternatively, if you do not require any other part of the idle task to
186 |  // execute, the idle task hook can call vCoRoutineScheduler() within an
187 |  // infinite loop.
188 |  void vApplicationIdleHook( void )
189 |  {
190 |     for( ;; )
191 |     {
192 |         vCoRoutineSchedule();
193 |     }
194 |  }
195 |  
196 | * \defgroup vCoRoutineSchedule vCoRoutineSchedule 197 | * \ingroup Tasks 198 | */ 199 | void vCoRoutineSchedule( void ); 200 | 201 | /** 202 | * croutine. h 203 | *
204 |  crSTART( xCoRoutineHandle xHandle );
205 | * 206 | * This macro MUST always be called at the start of a co-routine function. 207 | * 208 | * Example usage: 209 |
210 |  // Co-routine to be created.
211 |  void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
212 |  {
213 |  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
214 |  static long ulAVariable;
215 | 
216 |      // Must start every co-routine with a call to crSTART();
217 |      crSTART( xHandle );
218 | 
219 |      for( ;; )
220 |      {
221 |           // Co-routine functionality goes here.
222 |      }
223 | 
224 |      // Must end every co-routine with a call to crEND();
225 |      crEND();
226 |  }
227 | * \defgroup crSTART crSTART 228 | * \ingroup Tasks 229 | */ 230 | #define crSTART( pxCRCB ) switch( ( ( corCRCB * )( pxCRCB ) )->uxState ) { case 0: 231 | 232 | /** 233 | * croutine. h 234 | *
235 |  crEND();
236 | * 237 | * This macro MUST always be called at the end of a co-routine function. 238 | * 239 | * Example usage: 240 |
241 |  // Co-routine to be created.
242 |  void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
243 |  {
244 |  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
245 |  static long ulAVariable;
246 | 
247 |      // Must start every co-routine with a call to crSTART();
248 |      crSTART( xHandle );
249 | 
250 |      for( ;; )
251 |      {
252 |           // Co-routine functionality goes here.
253 |      }
254 | 
255 |      // Must end every co-routine with a call to crEND();
256 |      crEND();
257 |  }
258 | * \defgroup crSTART crSTART 259 | * \ingroup Tasks 260 | */ 261 | #define crEND() } 262 | 263 | /* 264 | * These macros are intended for internal use by the co-routine implementation 265 | * only. The macros should not be used directly by application writers. 266 | */ 267 | #define crSET_STATE0( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): 268 | #define crSET_STATE1( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): 269 | 270 | /** 271 | * croutine. h 272 | *
273 |  crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );
274 | * 275 | * Delay a co-routine for a fixed period of time. 276 | * 277 | * crDELAY can only be called from the co-routine function itself - not 278 | * from within a function called by the co-routine function. This is because 279 | * co-routines do not maintain their own stack. 280 | * 281 | * @param xHandle The handle of the co-routine to delay. This is the xHandle 282 | * parameter of the co-routine function. 283 | * 284 | * @param xTickToDelay The number of ticks that the co-routine should delay 285 | * for. The actual amount of time this equates to is defined by 286 | * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS 287 | * can be used to convert ticks to milliseconds. 288 | * 289 | * Example usage: 290 |
291 |  // Co-routine to be created.
292 |  void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
293 |  {
294 |  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
295 |  // This may not be necessary for const variables.
296 |  // We are to delay for 200ms.
297 |  static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
298 | 
299 |      // Must start every co-routine with a call to crSTART();
300 |      crSTART( xHandle );
301 | 
302 |      for( ;; )
303 |      {
304 |         // Delay for 200ms.
305 |         crDELAY( xHandle, xDelayTime );
306 | 
307 |         // Do something here.
308 |      }
309 | 
310 |      // Must end every co-routine with a call to crEND();
311 |      crEND();
312 |  }
313 | * \defgroup crDELAY crDELAY 314 | * \ingroup Tasks 315 | */ 316 | #define crDELAY( xHandle, xTicksToDelay ) \ 317 | if( ( xTicksToDelay ) > 0 ) \ 318 | { \ 319 | vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ 320 | } \ 321 | crSET_STATE0( ( xHandle ) ); 322 | 323 | /** 324 | *
325 |  crQUEUE_SEND(
326 |                   xCoRoutineHandle xHandle,
327 |                   xQueueHandle pxQueue,
328 |                   void *pvItemToQueue,
329 |                   portTickType xTicksToWait,
330 |                   portBASE_TYPE *pxResult
331 |              )
332 | * 333 | * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine 334 | * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. 335 | * 336 | * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas 337 | * xQueueSend() and xQueueReceive() can only be used from tasks. 338 | * 339 | * crQUEUE_SEND can only be called from the co-routine function itself - not 340 | * from within a function called by the co-routine function. This is because 341 | * co-routines do not maintain their own stack. 342 | * 343 | * See the co-routine section of the WEB documentation for information on 344 | * passing data between tasks and co-routines and between ISR's and 345 | * co-routines. 346 | * 347 | * @param xHandle The handle of the calling co-routine. This is the xHandle 348 | * parameter of the co-routine function. 349 | * 350 | * @param pxQueue The handle of the queue on which the data will be posted. 351 | * The handle is obtained as the return value when the queue is created using 352 | * the xQueueCreate() API function. 353 | * 354 | * @param pvItemToQueue A pointer to the data being posted onto the queue. 355 | * The number of bytes of each queued item is specified when the queue is 356 | * created. This number of bytes is copied from pvItemToQueue into the queue 357 | * itself. 358 | * 359 | * @param xTickToDelay The number of ticks that the co-routine should block 360 | * to wait for space to become available on the queue, should space not be 361 | * available immediately. The actual amount of time this equates to is defined 362 | * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant 363 | * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example 364 | * below). 365 | * 366 | * @param pxResult The variable pointed to by pxResult will be set to pdPASS if 367 | * data was successfully posted onto the queue, otherwise it will be set to an 368 | * error defined within ProjDefs.h. 369 | * 370 | * Example usage: 371 |
372 |  // Co-routine function that blocks for a fixed period then posts a number onto
373 |  // a queue.
374 |  static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
375 |  {
376 |  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
377 |  static portBASE_TYPE xNumberToPost = 0;
378 |  static portBASE_TYPE xResult;
379 | 
380 |     // Co-routines must begin with a call to crSTART().
381 |     crSTART( xHandle );
382 | 
383 |     for( ;; )
384 |     {
385 |         // This assumes the queue has already been created.
386 |         crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
387 | 
388 |         if( xResult != pdPASS )
389 |         {
390 |             // The message was not posted!
391 |         }
392 | 
393 |         // Increment the number to be posted onto the queue.
394 |         xNumberToPost++;
395 | 
396 |         // Delay for 100 ticks.
397 |         crDELAY( xHandle, 100 );
398 |     }
399 | 
400 |     // Co-routines must end with a call to crEND().
401 |     crEND();
402 |  }
403 | * \defgroup crQUEUE_SEND crQUEUE_SEND 404 | * \ingroup Tasks 405 | */ 406 | #define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ 407 | { \ 408 | *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ 409 | if( *( pxResult ) == errQUEUE_BLOCKED ) \ 410 | { \ 411 | crSET_STATE0( ( xHandle ) ); \ 412 | *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ 413 | } \ 414 | if( *pxResult == errQUEUE_YIELD ) \ 415 | { \ 416 | crSET_STATE1( ( xHandle ) ); \ 417 | *pxResult = pdPASS; \ 418 | } \ 419 | } 420 | 421 | /** 422 | * croutine. h 423 | *
424 |   crQUEUE_RECEIVE(
425 |                      xCoRoutineHandle xHandle,
426 |                      xQueueHandle pxQueue,
427 |                      void *pvBuffer,
428 |                      portTickType xTicksToWait,
429 |                      portBASE_TYPE *pxResult
430 |                  )
431 | * 432 | * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine 433 | * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. 434 | * 435 | * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas 436 | * xQueueSend() and xQueueReceive() can only be used from tasks. 437 | * 438 | * crQUEUE_RECEIVE can only be called from the co-routine function itself - not 439 | * from within a function called by the co-routine function. This is because 440 | * co-routines do not maintain their own stack. 441 | * 442 | * See the co-routine section of the WEB documentation for information on 443 | * passing data between tasks and co-routines and between ISR's and 444 | * co-routines. 445 | * 446 | * @param xHandle The handle of the calling co-routine. This is the xHandle 447 | * parameter of the co-routine function. 448 | * 449 | * @param pxQueue The handle of the queue from which the data will be received. 450 | * The handle is obtained as the return value when the queue is created using 451 | * the xQueueCreate() API function. 452 | * 453 | * @param pvBuffer The buffer into which the received item is to be copied. 454 | * The number of bytes of each queued item is specified when the queue is 455 | * created. This number of bytes is copied into pvBuffer. 456 | * 457 | * @param xTickToDelay The number of ticks that the co-routine should block 458 | * to wait for data to become available from the queue, should data not be 459 | * available immediately. The actual amount of time this equates to is defined 460 | * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant 461 | * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the 462 | * crQUEUE_SEND example). 463 | * 464 | * @param pxResult The variable pointed to by pxResult will be set to pdPASS if 465 | * data was successfully retrieved from the queue, otherwise it will be set to 466 | * an error code as defined within ProjDefs.h. 467 | * 468 | * Example usage: 469 |
470 |  // A co-routine receives the number of an LED to flash from a queue.  It
471 |  // blocks on the queue until the number is received.
472 |  static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
473 |  {
474 |  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
475 |  static portBASE_TYPE xResult;
476 |  static unsigned portBASE_TYPE uxLEDToFlash;
477 | 
478 |     // All co-routines must start with a call to crSTART().
479 |     crSTART( xHandle );
480 | 
481 |     for( ;; )
482 |     {
483 |         // Wait for data to become available on the queue.
484 |         crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
485 | 
486 |         if( xResult == pdPASS )
487 |         {
488 |             // We received the LED to flash - flash it!
489 |             vParTestToggleLED( uxLEDToFlash );
490 |         }
491 |     }
492 | 
493 |     crEND();
494 |  }
495 | * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE 496 | * \ingroup Tasks 497 | */ 498 | #define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ 499 | { \ 500 | *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ 501 | if( *( pxResult ) == errQUEUE_BLOCKED ) \ 502 | { \ 503 | crSET_STATE0( ( xHandle ) ); \ 504 | *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ 505 | } \ 506 | if( *( pxResult ) == errQUEUE_YIELD ) \ 507 | { \ 508 | crSET_STATE1( ( xHandle ) ); \ 509 | *( pxResult ) = pdPASS; \ 510 | } \ 511 | } 512 | 513 | /** 514 | * croutine. h 515 | *
516 |   crQUEUE_SEND_FROM_ISR(
517 |                             xQueueHandle pxQueue,
518 |                             void *pvItemToQueue,
519 |                             portBASE_TYPE xCoRoutinePreviouslyWoken
520 |                        )
521 | * 522 | * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the 523 | * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() 524 | * functions used by tasks. 525 | * 526 | * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to 527 | * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and 528 | * xQueueReceiveFromISR() can only be used to pass data between a task and and 529 | * ISR. 530 | * 531 | * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue 532 | * that is being used from within a co-routine. 533 | * 534 | * See the co-routine section of the WEB documentation for information on 535 | * passing data between tasks and co-routines and between ISR's and 536 | * co-routines. 537 | * 538 | * @param xQueue The handle to the queue on which the item is to be posted. 539 | * 540 | * @param pvItemToQueue A pointer to the item that is to be placed on the 541 | * queue. The size of the items the queue will hold was defined when the 542 | * queue was created, so this many bytes will be copied from pvItemToQueue 543 | * into the queue storage area. 544 | * 545 | * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto 546 | * the same queue multiple times from a single interrupt. The first call 547 | * should always pass in pdFALSE. Subsequent calls should pass in 548 | * the value returned from the previous call. 549 | * 550 | * @return pdTRUE if a co-routine was woken by posting onto the queue. This is 551 | * used by the ISR to determine if a context switch may be required following 552 | * the ISR. 553 | * 554 | * Example usage: 555 |
556 |  // A co-routine that blocks on a queue waiting for characters to be received.
557 |  static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
558 |  {
559 |  char cRxedChar;
560 |  portBASE_TYPE xResult;
561 | 
562 |      // All co-routines must start with a call to crSTART().
563 |      crSTART( xHandle );
564 | 
565 |      for( ;; )
566 |      {
567 |          // Wait for data to become available on the queue.  This assumes the
568 |          // queue xCommsRxQueue has already been created!
569 |          crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
570 | 
571 |          // Was a character received?
572 |          if( xResult == pdPASS )
573 |          {
574 |              // Process the character here.
575 |          }
576 |      }
577 | 
578 |      // All co-routines must end with a call to crEND().
579 |      crEND();
580 |  }
581 | 
582 |  // An ISR that uses a queue to send characters received on a serial port to
583 |  // a co-routine.
584 |  void vUART_ISR( void )
585 |  {
586 |  char cRxedChar;
587 |  portBASE_TYPE xCRWokenByPost = pdFALSE;
588 | 
589 |      // We loop around reading characters until there are none left in the UART.
590 |      while( UART_RX_REG_NOT_EMPTY() )
591 |      {
592 |          // Obtain the character from the UART.
593 |          cRxedChar = UART_RX_REG;
594 | 
595 |          // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
596 |          // the first time around the loop.  If the post causes a co-routine
597 |          // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
598 |          // In this manner we can ensure that if more than one co-routine is
599 |          // blocked on the queue only one is woken by this ISR no matter how
600 |          // many characters are posted to the queue.
601 |          xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
602 |      }
603 |  }
604 | * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR 605 | * \ingroup Tasks 606 | */ 607 | #define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) 608 | 609 | 610 | /** 611 | * croutine. h 612 | *
613 |   crQUEUE_SEND_FROM_ISR(
614 |                             xQueueHandle pxQueue,
615 |                             void *pvBuffer,
616 |                             portBASE_TYPE * pxCoRoutineWoken
617 |                        )
618 | * 619 | * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the 620 | * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() 621 | * functions used by tasks. 622 | * 623 | * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to 624 | * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and 625 | * xQueueReceiveFromISR() can only be used to pass data between a task and and 626 | * ISR. 627 | * 628 | * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data 629 | * from a queue that is being used from within a co-routine (a co-routine 630 | * posted to the queue). 631 | * 632 | * See the co-routine section of the WEB documentation for information on 633 | * passing data between tasks and co-routines and between ISR's and 634 | * co-routines. 635 | * 636 | * @param xQueue The handle to the queue on which the item is to be posted. 637 | * 638 | * @param pvBuffer A pointer to a buffer into which the received item will be 639 | * placed. The size of the items the queue will hold was defined when the 640 | * queue was created, so this many bytes will be copied from the queue into 641 | * pvBuffer. 642 | * 643 | * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become 644 | * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a 645 | * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise 646 | * *pxCoRoutineWoken will remain unchanged. 647 | * 648 | * @return pdTRUE an item was successfully received from the queue, otherwise 649 | * pdFALSE. 650 | * 651 | * Example usage: 652 |
653 |  // A co-routine that posts a character to a queue then blocks for a fixed
654 |  // period.  The character is incremented each time.
655 |  static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
656 |  {
657 |  // cChar holds its value while this co-routine is blocked and must therefore
658 |  // be declared static.
659 |  static char cCharToTx = 'a';
660 |  portBASE_TYPE xResult;
661 | 
662 |      // All co-routines must start with a call to crSTART().
663 |      crSTART( xHandle );
664 | 
665 |      for( ;; )
666 |      {
667 |          // Send the next character to the queue.
668 |          crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
669 | 
670 |          if( xResult == pdPASS )
671 |          {
672 |              // The character was successfully posted to the queue.
673 |          }
674 | 		 else
675 | 		 {
676 | 			// Could not post the character to the queue.
677 | 		 }
678 | 
679 |          // Enable the UART Tx interrupt to cause an interrupt in this
680 | 		 // hypothetical UART.  The interrupt will obtain the character
681 | 		 // from the queue and send it.
682 | 		 ENABLE_RX_INTERRUPT();
683 | 
684 | 		 // Increment to the next character then block for a fixed period.
685 | 		 // cCharToTx will maintain its value across the delay as it is
686 | 		 // declared static.
687 | 		 cCharToTx++;
688 | 		 if( cCharToTx > 'x' )
689 | 		 {
690 | 			cCharToTx = 'a';
691 | 		 }
692 | 		 crDELAY( 100 );
693 |      }
694 | 
695 |      // All co-routines must end with a call to crEND().
696 |      crEND();
697 |  }
698 | 
699 |  // An ISR that uses a queue to receive characters to send on a UART.
700 |  void vUART_ISR( void )
701 |  {
702 |  char cCharToTx;
703 |  portBASE_TYPE xCRWokenByPost = pdFALSE;
704 | 
705 |      while( UART_TX_REG_EMPTY() )
706 |      {
707 |          // Are there any characters in the queue waiting to be sent?
708 | 		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
709 | 		 // is woken by the post - ensuring that only a single co-routine is
710 | 		 // woken no matter how many times we go around this loop.
711 |          if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
712 | 		 {
713 | 			 SEND_CHARACTER( cCharToTx );
714 | 		 }
715 |      }
716 |  }
717 | * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR 718 | * \ingroup Tasks 719 | */ 720 | #define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) 721 | 722 | /* 723 | * This function is intended for internal use by the co-routine macros only. 724 | * The macro nature of the co-routine implementation requires that the 725 | * prototype appears here. The function should not be used by application 726 | * writers. 727 | * 728 | * Removes the current co-routine from its ready list and places it in the 729 | * appropriate delayed list. 730 | */ 731 | void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ); 732 | 733 | /* 734 | * This function is intended for internal use by the queue implementation only. 735 | * The function should not be used by application writers. 736 | * 737 | * Removes the highest priority co-routine from the event list and places it in 738 | * the pending ready list. 739 | */ 740 | signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ); 741 | 742 | #ifdef __cplusplus 743 | } 744 | #endif 745 | 746 | #endif /* CO_ROUTINE_H */ 747 | -------------------------------------------------------------------------------- /examples/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir TOP examples ; 2 | 3 | SubInclude TOP examples blinky ; 4 | SubInclude TOP examples buttonled ; 5 | SubInclude TOP examples manybuttons ; 6 | #SubInclude TOP examples pingpair ; 7 | SubInclude TOP examples twotasks ; 8 | -------------------------------------------------------------------------------- /examples/blinky/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir TOP examples blinky ; 2 | 3 | # Set up output directories 4 | LOCATE_TARGET = $(SEARCH_SOURCE)/out/$(F_CPU) ; 5 | LOCATE_SOURCE = $(LOCATE_TARGET) ; 6 | 7 | # Pull in local libraries 8 | SKETCH_LIBS = MemoryFree ; 9 | HDRS += $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) ; 10 | 11 | # FreeRTOS library 12 | HDRS += $(TOP) ; 13 | Library $(LOCATE_TARGET)/freertos : [ GLOB $(TOP) : $(MODULE_EXT) ] ; 14 | 15 | # Main output executable 16 | Arduino $(SEARCH_SOURCE:B).elf : [ GLOB $(SEARCH_SOURCE) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) : $(MODULE_EXT) ] ; 17 | LinkLibraries $(SEARCH_SOURCE:B).elf : $(LOCATE_TARGET)/freertos : $(TOP)/$(F_CPU)/freertos ; 18 | -------------------------------------------------------------------------------- /examples/blinky/blinky.ino: -------------------------------------------------------------------------------- 1 | #include "FreeRTOS.h" 2 | #include "task.h" 3 | #include "Arduino.h" 4 | #include "MemoryFree.h" 5 | 6 | static void vBlinkTask( void *pvParameters ); 7 | 8 | #ifndef PINS_DEFINED 9 | const int led_red = 13; 10 | #endif 11 | 12 | /*--------------------------------------------------------------------------*/ 13 | 14 | void setup( void ) 15 | { 16 | Serial.begin(57600); 17 | Serial.println(__FILE__); 18 | 19 | /* Create the tasks defined within this file. */ 20 | xTaskCreate( vBlinkTask, ( signed portCHAR * ) "vBlinkTask", 50, NULL, 21 | tskIDLE_PRIORITY+1, NULL ); 22 | 23 | Serial.print("FREE="); 24 | Serial.println(freeMemory()); 25 | 26 | vTaskStartScheduler(); 27 | } 28 | 29 | void loop( void ) 30 | { 31 | } 32 | 33 | /*--------------------------------------------------------------------------*/ 34 | 35 | static void vBlinkTask( void * ) 36 | { 37 | pinMode(led_red,OUTPUT); 38 | for( ;; ) 39 | { 40 | digitalWrite(led_red,digitalRead(led_red)^1); 41 | vTaskDelay( 250 ); 42 | } 43 | } 44 | 45 | // vim:cin:ai:et:sts=4 sw=4 46 | -------------------------------------------------------------------------------- /examples/buttonled/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir TOP examples blinky ; 2 | 3 | # Set up output directories 4 | LOCATE_TARGET = $(SEARCH_SOURCE)/out/$(F_CPU) ; 5 | LOCATE_SOURCE = $(LOCATE_TARGET) ; 6 | 7 | # Pull in local libraries 8 | SKETCH_LIBS = MemoryFree ; 9 | HDRS += $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) ; 10 | 11 | # FreeRTOS library 12 | HDRS += $(TOP) ; 13 | Library $(LOCATE_TARGET)/freertos : [ GLOB $(TOP) : $(MODULE_EXT) ] ; 14 | 15 | # Main output executable 16 | Arduino $(SEARCH_SOURCE:B).elf : [ GLOB $(SEARCH_SOURCE) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) : $(MODULE_EXT) ] ; 17 | LinkLibraries $(SEARCH_SOURCE:B).elf : $(LOCATE_TARGET)/freertos : $(TOP)/$(F_CPU)/freertos ; 18 | -------------------------------------------------------------------------------- /examples/buttonled/buttonled.ino: -------------------------------------------------------------------------------- 1 | #include "FreeRTOS.h" 2 | #include "task.h" 3 | #include "queue.h" 4 | #include "Arduino.h" 5 | #include "MemoryFree.h" 6 | 7 | static void vLedTask( void *pvParameters ); 8 | static void vButtonTask( void *pvParameters ); 9 | static xQueueHandle xButtonQueue; 10 | 11 | #ifndef PINS_DEFINED 12 | const int led_red = 13; 13 | const int button_a = 2; 14 | #endif 15 | 16 | /*--------------------------------------------------------------------------*/ 17 | 18 | void setup( void ) 19 | { 20 | Serial.begin(57600); 21 | Serial.println(__FILE__); 22 | 23 | /* Create the tasks defined within this file. */ 24 | xTaskCreate( vLedTask, ( signed portCHAR * ) "vBlinkTask", 100, NULL, 25 | tskIDLE_PRIORITY+1, NULL ); 26 | xTaskCreate( vButtonTask, ( signed portCHAR * ) "vButtonTask", 100, NULL, 27 | tskIDLE_PRIORITY, NULL ); 28 | 29 | /* Create the Queue for communication between the tasks */ 30 | xButtonQueue = xQueueCreate( 5, sizeof(uint8_t) ); 31 | 32 | Serial.print("FREE="); 33 | Serial.println(freeMemory()); 34 | 35 | vTaskStartScheduler(); 36 | } 37 | 38 | void loop( void ) 39 | { 40 | } 41 | 42 | /*--------------------------------------------------------------------------*/ 43 | 44 | static void vLedTask( void * ) 45 | { 46 | pinMode(led_red,OUTPUT); 47 | digitalWrite(led_red,OUTPUT); 48 | uint8_t state; 49 | 50 | for( ;; ) 51 | { 52 | /* Wait until an element is received from the queue */ 53 | if (xQueueReceive(xButtonQueue, &state, portMAX_DELAY)) 54 | { 55 | // On button UP, toggle the LED 56 | if ( state == HIGH ) 57 | digitalWrite(led_red,digitalRead(led_red)^1); 58 | } 59 | } 60 | } 61 | 62 | /*--------------------------------------------------------------------------*/ 63 | 64 | static void vButtonTask( void * ) 65 | { 66 | pinMode(button_a,INPUT); 67 | digitalWrite(button_a,HIGH); 68 | uint8_t newstate, state = HIGH; 69 | 70 | for( ;; ) 71 | { 72 | if ( digitalRead(button_a) != state ) 73 | { 74 | // debounce and read again 75 | vTaskDelay( 20 ); 76 | 77 | newstate = digitalRead(button_a); 78 | if ( newstate != state ) 79 | { 80 | state = newstate; 81 | xQueueSendToBack(xButtonQueue, &newstate, 0); 82 | } 83 | } 84 | // read again soon 85 | vTaskDelay( 20 ); 86 | } 87 | } 88 | 89 | // vim:cin:ai:et:sts=4 sw=4 90 | -------------------------------------------------------------------------------- /examples/manybuttons/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir TOP examples manybuttons ; 2 | 3 | # Set up output directories 4 | LOCATE_TARGET = $(SEARCH_SOURCE)/out/$(F_CPU) ; 5 | LOCATE_SOURCE = $(LOCATE_TARGET) ; 6 | 7 | # Pull in local libraries 8 | SKETCH_LIBS = MemoryFree ; 9 | HDRS += $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) ; 10 | 11 | # FreeRTOS library 12 | HDRS += $(TOP) ; 13 | Library $(LOCATE_TARGET)/freertos : [ GLOB $(TOP) : $(MODULE_EXT) ] ; 14 | 15 | # Main output executable 16 | Arduino $(SEARCH_SOURCE:B).elf : [ GLOB $(SEARCH_SOURCE) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) : $(MODULE_EXT) ] ; 17 | LinkLibraries $(SEARCH_SOURCE:B).elf : $(LOCATE_TARGET)/freertos : $(TOP)/$(F_CPU)/freertos ; 18 | -------------------------------------------------------------------------------- /examples/manybuttons/manybuttons.ino: -------------------------------------------------------------------------------- 1 | #include "FreeRTOS.h" 2 | #include "task.h" 3 | #include "queue.h" 4 | #include "Arduino.h" 5 | #include "MemoryFree.h" 6 | 7 | static void vButtonTask( void *pvParameters ); 8 | static void vPrintTask( void *pvParameters ); 9 | static xQueueHandle xButtonQueue; 10 | 11 | #ifndef PINS_DEFINED 12 | const int button_a = 2; 13 | const int button_b = 3; 14 | const int button_c = 4; 15 | #endif 16 | 17 | struct button_status 18 | { 19 | uint8_t pin; 20 | uint8_t state; 21 | }; 22 | 23 | uint8_t button_pins[] = { button_a, button_b, button_c }; 24 | 25 | /*--------------------------------------------------------------------------*/ 26 | 27 | void setup( void ) 28 | { 29 | Serial.begin(57600); 30 | Serial.println(__FILE__); 31 | 32 | /* Create the tasks defined within this file. */ 33 | xTaskCreate( vPrintTask, ( signed portCHAR * ) "vPrintTask", 120, NULL, 34 | tskIDLE_PRIORITY, NULL ); 35 | 36 | // One task for each button 37 | int i = sizeof(button_pins); 38 | while ( i-- ) 39 | { 40 | xTaskCreate( vButtonTask, ( signed portCHAR * ) "vButtonTask", 70, button_pins + i, 41 | tskIDLE_PRIORITY, NULL ); 42 | } 43 | 44 | /* Create the Queue for communication between the tasks */ 45 | xButtonQueue = xQueueCreate( sizeof(button_pins), sizeof(button_status) ); 46 | 47 | Serial.print("FREE="); 48 | Serial.println(freeMemory()); 49 | 50 | vTaskStartScheduler(); 51 | } 52 | 53 | void loop( void ) 54 | { 55 | } 56 | 57 | /*--------------------------------------------------------------------------*/ 58 | 59 | static void vButtonTask( void * pv ) 60 | { 61 | uint8_t* buttonPin = reinterpret_cast(pv); 62 | 63 | button_status qstatus; 64 | qstatus.pin = *buttonPin; 65 | qstatus.state = HIGH; 66 | 67 | pinMode(*buttonPin,INPUT); 68 | digitalWrite(*buttonPin,HIGH); 69 | 70 | for( ;; ) 71 | { 72 | if ( digitalRead(*buttonPin) != qstatus.state ) 73 | { 74 | // debounce and read again 75 | vTaskDelay( 20 ); 76 | 77 | uint8_t newstate = digitalRead(*buttonPin); 78 | if ( newstate != qstatus.state ) 79 | { 80 | qstatus.state = newstate; 81 | 82 | xQueueSendToBack(xButtonQueue, &qstatus, 0); 83 | } 84 | } 85 | // read again soon 86 | vTaskDelay( 20 ); 87 | } 88 | } 89 | 90 | /*--------------------------------------------------------------------------*/ 91 | 92 | static void vPrintTask( void * ) 93 | { 94 | button_status qstatus; 95 | 96 | for( ;; ) 97 | { 98 | /* Wait until an element is received from the queue */ 99 | if (xQueueReceive(xButtonQueue, &qstatus, portMAX_DELAY)) 100 | { 101 | //Serial.print(uxTaskGetStackHighWaterMark(NULL)); 102 | Serial.print(" Button "); 103 | Serial.print(qstatus.pin); 104 | Serial.print(" is "); 105 | Serial.println(qstatus.state?"HIGH":"LOW"); 106 | } 107 | } 108 | } 109 | 110 | // vim:cin:ai:et:sts=4 sw=4 111 | -------------------------------------------------------------------------------- /examples/pingpair/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir TOP examples pingpair ; 2 | 3 | # Set up output directories 4 | LOCATE_TARGET = $(SEARCH_SOURCE)/out/$(F_CPU) ; 5 | LOCATE_SOURCE = $(LOCATE_TARGET) ; 6 | 7 | # Pull in local libraries 8 | SKETCH_LIBS = MemoryFree RF24 ; 9 | ARDUINO_LIBS = SPI ; 10 | HDRS += $(ARDUINO_DIR)/libraries/$(ARDUINO_LIBS) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) ; 11 | Library $(LOCATE_TARGET)/libs : [ GLOB $(ARDUINO_DIR)/libraries/$(ARDUINO_LIBS) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) : $(MODULE_EXT) ] ; 12 | 13 | # FreeRTOS library 14 | HDRS += $(TOP) ; 15 | Library $(LOCATE_TARGET)/freertos : [ GLOB $(TOP) : $(MODULE_EXT) ] ; 16 | 17 | # Main output executable 18 | Arduino $(SEARCH_SOURCE:B).elf : [ GLOB $(SEARCH_SOURCE) : $(MODULE_EXT) ] ; 19 | LinkLibraries $(SEARCH_SOURCE:B).elf : $(LOCATE_TARGET)/freertos libs ; 20 | -------------------------------------------------------------------------------- /examples/pingpair/app_tasks.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file app_tasks.cpp 3 | * 4 | * All application logic is contain within these tasks 5 | */ 6 | 7 | /* System includes */ 8 | #include 9 | 10 | /* Application includes */ 11 | #include "globals.h" 12 | 13 | static uint32_t message_count = 0; 14 | 15 | // Note that this module is the only one which should be accessing the console 16 | // ergo the only using this mutex. 17 | xSemaphoreHandle xConsoleMutex; 18 | 19 | /****************************************************************************/ 20 | 21 | /** 22 | * The input task 23 | * It monitors the serial input and modifies the behaviour of the program 24 | * based on user input. 25 | * \param pvParameter NULL is passed as parameter. 26 | */ 27 | void vInputTask(void*) 28 | { 29 | portTickType xLastWakeTime = xTaskGetTickCount(); 30 | const portTickType tickPeriod = 20; 31 | 32 | /* Infinite loop */ 33 | while (1) 34 | { 35 | if (SerialUSB.available()) 36 | { 37 | char c = toupper(SerialUSB.read()); 38 | if ( c == 'S' && role == role_receiver ) 39 | { 40 | xSemaphoreTake(xConsoleMutex, portMAX_DELAY); 41 | printf_P(PSTR("*** CHANGING TO SENDER ROLE -- PRESS 'R' TO SWITCH BACK\r\n")); 42 | xSemaphoreGive(xConsoleMutex); 43 | 44 | // Become the primary transmitter (ping out) 45 | radio_set_role(role_sender); 46 | } 47 | else if ( c == 'R' && role == role_sender ) 48 | { 49 | xSemaphoreTake(xConsoleMutex, portMAX_DELAY); 50 | printf_P(PSTR("*** CHANGING TO RECEIVE ROLE -- PRESS 'S' TO SWITCH BACK\r\n")); 51 | xSemaphoreGive(xConsoleMutex); 52 | 53 | // Become the primary receiver (pong back) 54 | radio_set_role(role_receiver); 55 | } 56 | else 57 | { 58 | printf_P(PSTR("Unknown: %c\r\n"),c); 59 | } 60 | } 61 | vTaskDelayUntil(&xLastWakeTime, tickPeriod); 62 | } 63 | } 64 | 65 | /****************************************************************************/ 66 | 67 | /** 68 | * The Status task 69 | * It simply monitors the status queue and notifies the user 70 | * \param pvParameter NULL is passed as parameter. 71 | */ 72 | void vStatusTask(void*) 73 | { 74 | status_e status; 75 | 76 | /* Infinite loop */ 77 | while (1) 78 | { 79 | /* Wait until an element is received from the queue */ 80 | if (xQueueReceive(xStatusQueue, &status, portMAX_DELAY)) 81 | { 82 | xSemaphoreTake(xConsoleMutex, portMAX_DELAY); 83 | printf_P(PSTR("Status: %S\r\n"),pgm_read_word(&status_str[status])); 84 | xSemaphoreGive(xConsoleMutex); 85 | } 86 | } 87 | } 88 | 89 | /****************************************************************************/ 90 | 91 | /** 92 | * The Sender task 93 | * It sends a ping out repeatedly 94 | * then waits for a given delay and start over again. 95 | * \param pvParameter NULL is passed as parameter. 96 | */ 97 | void vSenderTask(void*) 98 | { 99 | portTickType xLastWakeTime = xTaskGetTickCount(); 100 | 101 | // How often to wait between sends. 102 | const portTickType sendPeriod = 2000; 103 | 104 | /* Infinite task loop */ 105 | while (1) 106 | { 107 | if ( role == role_sender ) 108 | { 109 | digitalWrite(status_pending,HIGH); 110 | digitalWrite(status_ok,LOW); 111 | digitalWrite(status_fail,LOW); 112 | 113 | // Take the time, and send it. 114 | payload_t payload('T',xLastWakeTime); 115 | 116 | xSemaphoreTake(xConsoleMutex, portMAX_DELAY); 117 | printf_P(PSTR("Now sending %u\r\n"),payload.value); 118 | xSemaphoreGive(xConsoleMutex); 119 | 120 | xSemaphoreTake(xRadioMutex, portMAX_DELAY); 121 | radio.stopListening(); 122 | radio.startWrite( &payload, sizeof(payload) ); 123 | xSemaphoreGive(xRadioMutex); 124 | } 125 | 126 | /* Block the task for the defined time */ 127 | vTaskDelayUntil(&xLastWakeTime, 128 | sendPeriod - (xLastWakeTime % sendPeriod) ); 129 | } 130 | } 131 | 132 | /****************************************************************************/ 133 | 134 | /** 135 | * The Receiver task function. 136 | * It waits until a ping message has been put in the queue, by the radio 137 | * softirq, and prints it out to the serial usb, and adds an ack payload 138 | * for hte next time around. 139 | * \param pvParameter NULL is passed as parameter. 140 | */ 141 | void vReceiverTask(void*) 142 | { 143 | payload_t payload; 144 | 145 | /* Infinite loop */ 146 | while (1) 147 | { 148 | /* Wait until an element is received from the queue */ 149 | if (xQueueReceive(xPayloadQueue, &payload, portMAX_DELAY)) 150 | { 151 | xSemaphoreTake(xConsoleMutex, portMAX_DELAY); 152 | printf_P(PSTR("Got payload type=%02x value=%u\r\n"),payload.type,payload.value); 153 | xSemaphoreGive(xConsoleMutex); 154 | 155 | if ( payload.type == 'T' ) 156 | { 157 | // Add an ack packet for the next time around. This is a simple 158 | // packet counter 159 | payload_t ack('A',++message_count); 160 | 161 | xSemaphoreTake(xRadioMutex, portMAX_DELAY); 162 | radio.writeAckPayload( 1, &ack, sizeof(ack) ); 163 | xSemaphoreGive(xRadioMutex); 164 | 165 | xSemaphoreTake(xConsoleMutex, portMAX_DELAY); 166 | printf_P(PSTR("Sent ack value=%u\r\n"),ack.value); 167 | xSemaphoreGive(xConsoleMutex); 168 | } 169 | } 170 | } 171 | } 172 | 173 | // vim:cin:ai:et:sts=4 sw=4 174 | -------------------------------------------------------------------------------- /examples/pingpair/globals.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file globals.h 3 | * 4 | * Single global header file that all modules of the application need. 5 | */ 6 | 7 | #ifndef __GLOBALS_H__ 8 | #define __GLOBALS_H__ 9 | 10 | #ifdef MAPLE_IDE 11 | 12 | /* Framework includes */ 13 | #include 14 | 15 | /* Library includes. */ 16 | #include "MapleFreeRTOS.h" 17 | 18 | #define SERIAL_BAUD(x) 19 | 20 | #endif // MAPLE_IDE 21 | 22 | #ifdef ARDUINO 23 | 24 | #include 25 | #include 26 | #include "FreeRTOS.h" 27 | #include "semphr.h" 28 | #include "task.h" 29 | 30 | #define BOARD_LED_PIN LED 31 | #define BOARD_BUTTON_PIN 2 32 | #define SerialUSB Serial 33 | #define SERIAL_BAUD(x) (x) 34 | 35 | #endif // ARDUINO 36 | 37 | #include "RF24.h" 38 | 39 | // The various roles supported by this sketch 40 | typedef enum { role_sender = 1, role_receiver } role_e; 41 | 42 | // The role of the current running sketch 43 | extern role_e role; 44 | 45 | enum status_e { status_none = 0, status_txok, status_txfail, status_invalid }; 46 | 47 | extern const char* const status_str[]; 48 | 49 | /* Function Prototypes */ 50 | extern void vSenderTask(void* pvParameters); 51 | extern void vReceiverTask(void* pvParameters); 52 | extern void vStatusTask(void* pvParameters); 53 | extern void vInputTask(void* pvParameters); 54 | extern void vRadioSoftIrqTask(void* pvParameters); 55 | extern void setup_radio(void); 56 | extern void radio_set_role(role_e); 57 | 58 | /* Global Variables */ 59 | extern xSemaphoreHandle xRadioIrqSemaphore; 60 | extern xSemaphoreHandle xRadioMutex; 61 | extern xSemaphoreHandle xConsoleMutex; 62 | extern xQueueHandle xPayloadQueue; 63 | extern xQueueHandle xStatusQueue; 64 | 65 | extern RF24 radio; 66 | 67 | // Status LEDs 68 | 69 | #ifndef PINS_DEFINED 70 | const int led_red = 7; 71 | const int led_yellow = 6; 72 | const int led_green = 5; 73 | #endif 74 | 75 | #ifndef LED 76 | #define LED led_red 77 | #endif 78 | 79 | const int status_pending = led_yellow; 80 | const int status_ok = led_green; 81 | const int status_fail = led_red; 82 | 83 | // 84 | // Payload 85 | // 86 | 87 | struct payload_t 88 | { 89 | char type; 90 | uint32_t value; 91 | 92 | payload_t(void): type(0), value(0) {} 93 | payload_t( char _type, uint32_t _value ): type(_type), value(_value) {} 94 | } __attribute__ ((packed)); 95 | 96 | #endif // __GLOBALS_H__ 97 | 98 | // vim:cin:ai:et:sts=4 sw=4 99 | -------------------------------------------------------------------------------- /examples/pingpair/pingpair.ino: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * 3 | * RF24 Pingpair using FreeRTOS 4 | * 5 | * See .cpp files for the code (INO file is just here to appease the IDE). 6 | * 7 | * This requires the RF24 library, of course. 8 | * http://maniacbug.github.com/RF24 9 | * 10 | * This is designed to work with a node running pingpair_irq. They use the 11 | * same radio setup. Pingpair_irq sends by default, and this receives by 12 | * default. 13 | */ 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef MAPLE_IDE 20 | #include "MapleFreeRTOS.h" 21 | #endif 22 | 23 | // vim:cin:ai:sts=4 sw=4 ft=cpp 24 | -------------------------------------------------------------------------------- /examples/pingpair/printf.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 J. Coliz 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | /** 10 | * @file printf.h 11 | * 12 | * Setup necessary to direct stdout to the Arduino Serial library, which 13 | * enables 'printf' 14 | */ 15 | 16 | #ifndef __PRINTF_H__ 17 | #define __PRINTF_H__ 18 | 19 | #ifdef ARDUINO 20 | 21 | int serial_putc( char c, FILE * ) 22 | { 23 | Serial.write( c ); 24 | 25 | return c; 26 | } 27 | 28 | void printf_begin(void) 29 | { 30 | fdevopen( &serial_putc, 0 ); 31 | } 32 | 33 | #else 34 | #error This example is only for use on Arduino. 35 | #endif // ARDUINO 36 | 37 | #endif // __PRINTF_H__ 38 | -------------------------------------------------------------------------------- /examples/pingpair/radio.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file radio.cpp 3 | * 4 | * All major interaction with the radio is here 5 | */ 6 | 7 | /* Library includes */ 8 | #include "RF24.h" 9 | 10 | /* Application includes */ 11 | #include "globals.h" 12 | 13 | /* Forward delcarations */ 14 | static void rf_irq_handler(void); 15 | 16 | /* RTOS objects */ 17 | xSemaphoreHandle xRadioIrqSemaphore; 18 | xSemaphoreHandle xRadioMutex; 19 | xQueueHandle xPayloadQueue; 20 | xQueueHandle xStatusQueue; 21 | 22 | /* Hardware Setup */ 23 | 24 | #ifdef __AVR_ATmega328P__ 25 | // Kind of a hack to experiment with this sketch on 328 26 | const int rf_ce_pin = 8; 27 | const int rf_csn_pin = 9; 28 | const int rf_irq_pin = 0; 29 | #endif 30 | 31 | #ifdef __AVR_ATmega1284P__ 32 | const int rf_ce_pin = rf_ce; //7; 33 | const int rf_csn_pin = rf_csn; //6; 34 | const int rf_irq_pin = rf_irq; //12; 35 | #endif 36 | 37 | // 38 | // Hardware configuration 39 | // 40 | 41 | // Set up nRF24L01 radio on SPI bus 42 | 43 | RF24 radio(rf_ce_pin,rf_csn_pin); 44 | 45 | #ifdef MAPLE_IDE 46 | HardwareSPI SPI(2); 47 | #endif 48 | 49 | // 50 | // Role management 51 | // 52 | // Set up role. This sketch uses the same software for all the nodes in this 53 | // system. Doing so greatly simplifies testing. 54 | // 55 | 56 | // The debug-friendly names of those roles 57 | const char role_friendly_name_0[] PROGMEM = "invalid"; 58 | const char role_friendly_name_1[] PROGMEM = "Sender"; 59 | const char role_friendly_name_2[] PROGMEM = "Receiver"; 60 | const char* const role_friendly_name[] PROGMEM = { 61 | role_friendly_name_0, 62 | role_friendly_name_1, 63 | role_friendly_name_2, 64 | }; 65 | 66 | // The role of the current running sketch 67 | role_e role = role_receiver; 68 | 69 | // 70 | // Status messages 71 | // 72 | 73 | const char status_str_0[] PROGMEM = "None"; 74 | const char status_str_1[] PROGMEM = "Send OK"; 75 | const char status_str_2[] PROGMEM = "Send Failed"; 76 | const char status_str_3[] PROGMEM = "*** INVALID ***"; 77 | const char* const status_str[] PROGMEM = { 78 | status_str_0, 79 | status_str_1, 80 | status_str_2, 81 | status_str_3, 82 | }; 83 | 84 | // 85 | // Topology 86 | // 87 | 88 | // Single radio pipe address for the 2 nodes to communicate. 89 | const uint64_t pipe = 0xE8E8F0F0E1LL; 90 | 91 | /****************************************************************************/ 92 | 93 | void setup_radio(void) 94 | { 95 | // 96 | // Setup and configure rf radio 97 | // 98 | 99 | radio.begin(); 100 | 101 | // We will be using the Ack Payload feature, so please enable it 102 | radio.enableAckPayload(); 103 | 104 | // 105 | // Open pipes to other nodes for communication 106 | // 107 | 108 | // This simple sketch opens a single pipe for these two nodes to 109 | // communicate back and forth. One listens on it, the other talks to it. 110 | 111 | if ( role == role_sender ) 112 | { 113 | radio.openWritingPipe(pipe); 114 | radio.openReadingPipe(1,0); 115 | } 116 | else 117 | { 118 | radio.openWritingPipe(0); 119 | radio.openReadingPipe(1,pipe); 120 | } 121 | 122 | // 123 | // Start listening 124 | // 125 | 126 | if ( role == role_sender ) 127 | radio.startListening(); 128 | 129 | // 130 | // Dump the configuration of the rf unit for debugging 131 | // 132 | 133 | radio.printDetails(); 134 | 135 | // 136 | // Attach interrupt handler to interrupt #0 (using pin 2) 137 | // on BOTH the sender and receiver 138 | // 139 | 140 | /* Get called when the button is pressed */ 141 | attachInterrupt(rf_irq_pin,rf_irq_handler,FALLING); 142 | 143 | // 144 | // Give information about the role 145 | // 146 | 147 | printf_P(PSTR("ROLE: %S\r\n"),pgm_read_word(&role_friendly_name[role])); 148 | printf_P(PSTR("*** PRESS 'S' to begin sending to the other node")); 149 | 150 | pinMode(led_yellow,OUTPUT); 151 | digitalWrite(led_yellow,HIGH); 152 | } 153 | /****************************************************************************/ 154 | 155 | void radio_set_role(role_e newrole) 156 | { 157 | if ( newrole == role_sender ) 158 | { 159 | xSemaphoreTake(xRadioMutex, portMAX_DELAY); 160 | role = role_sender; 161 | radio.openWritingPipe(pipe); 162 | radio.openReadingPipe(1,0); 163 | radio.stopListening(); 164 | xSemaphoreGive(xRadioMutex); 165 | } 166 | else if ( newrole == role_receiver ) 167 | { 168 | // Become the primary receiver (pong back) 169 | xSemaphoreTake(xRadioMutex, portMAX_DELAY); 170 | role = role_receiver; 171 | radio.openWritingPipe(0); 172 | radio.openReadingPipe(1,pipe); 173 | radio.startListening(); 174 | xSemaphoreGive(xRadioMutex); 175 | } 176 | } 177 | 178 | /****************************************************************************/ 179 | 180 | /** 181 | * The Radio Soft IRQ task 182 | * It waits the semaphore is given, then takes it and services the radio 183 | * 184 | * Ideally, the only thing this softirq interacts with is the radio 185 | * and the queues. 186 | * 187 | * \param pvParameters NULL is passed, unused here. 188 | */ 189 | void vRadioSoftIrqTask(void*) 190 | { 191 | /* Infinite loop */ 192 | while(1) 193 | { 194 | /* Block until the semaphore is given */ 195 | xSemaphoreTake(xRadioIrqSemaphore, portMAX_DELAY); 196 | 197 | /* Get the radio access semaphore for the whole time */ 198 | xSemaphoreTake(xRadioMutex, portMAX_DELAY); 199 | 200 | digitalWrite(status_pending,LOW); 201 | 202 | // What happened? 203 | bool tx,fail,rx; 204 | radio.whatHappened(tx,fail,rx); 205 | 206 | // Have we successfully transmitted? 207 | if ( tx ) 208 | { 209 | status_e status = status_txok; 210 | xQueueSendToBack(xStatusQueue, &status, 0); 211 | } 212 | 213 | // Have we failed to transmit? 214 | if ( fail ) 215 | { 216 | digitalWrite(status_fail,HIGH); 217 | status_e status = status_txfail; 218 | xQueueSendToBack(xStatusQueue, &status, 0); 219 | } 220 | 221 | // Transmitter can power down for now, because 222 | // the transmission is done. 223 | if ( ( tx || fail ) && ( role == role_sender ) ) 224 | radio.powerDown(); 225 | 226 | // Did we receive a message? 227 | if ( rx ) 228 | { 229 | digitalWrite(status_ok,HIGH); 230 | 231 | // Get this payload and queue it 232 | payload_t payload; 233 | radio.read( &payload, sizeof(payload) ); 234 | xQueueSendToBack(xPayloadQueue, &payload, 0); 235 | #if 0 236 | SerialUSB.print("[RAW] ** "); 237 | SerialUSB.print(sizeof(payload_t)); 238 | SerialUSB.print(" "); 239 | uint8_t* raw = reinterpret_cast(&payload); 240 | int i = 0; 241 | while ( i < sizeof(payload) ) 242 | { 243 | SerialUSB.print(raw[i],DEC); 244 | SerialUSB.print(" "); 245 | ++i; 246 | } 247 | SerialUSB.println(" **"); 248 | #endif 249 | } 250 | 251 | // Done with the radio now. 252 | xSemaphoreGive(xRadioMutex); 253 | 254 | // Print the stack hi water mark 255 | xSemaphoreTake(xConsoleMutex, portMAX_DELAY); 256 | printf_P(PSTR("Stack min: %u\r\n"),uxTaskGetStackHighWaterMark(NULL)); 257 | xSemaphoreGive(xConsoleMutex); 258 | 259 | } 260 | } 261 | 262 | /****************************************************************************/ 263 | 264 | /** 265 | * The irq callback function called when the radio hw irq is raised. 266 | * It gives the semaphore. 267 | */ 268 | static void rf_irq_handler(void) 269 | { 270 | digitalWrite(led_yellow,LOW); 271 | static signed portBASE_TYPE xHigherPriorityTaskWoken; 272 | /* Give the semaphore */ 273 | xSemaphoreGiveFromISR(xRadioIrqSemaphore, &xHigherPriorityTaskWoken); 274 | } 275 | 276 | /****************************************************************************/ 277 | 278 | // vim:cin:ai:et:sts=4 sw=4 279 | -------------------------------------------------------------------------------- /examples/pingpair/setup.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file setup.cpp 3 | * 4 | * Instantiate and set up all objects, run main loop 5 | */ 6 | 7 | /* System includes */ 8 | 9 | /* LIbrary includes */ 10 | #include "MemoryFree.h" 11 | 12 | /* Application includes */ 13 | #include "globals.h" 14 | 15 | #include "printf.h" 16 | 17 | /****************************************************************************/ 18 | 19 | /** 20 | * Setup 21 | * 22 | * Creates all the objects needed by the application and launches the 23 | * task loop. 24 | */ 25 | void setup( void ) 26 | { 27 | // Set up the LED to steady on 28 | pinMode(BOARD_LED_PIN, OUTPUT); 29 | digitalWrite(BOARD_LED_PIN, HIGH); 30 | 31 | // Setup the button as input 32 | pinMode(BOARD_BUTTON_PIN, INPUT); 33 | digitalWrite(BOARD_BUTTON_PIN, HIGH); 34 | 35 | // Wait until the user is watching 36 | SerialUSB.begin(SERIAL_BAUD(57600)); 37 | printf_begin(); 38 | printf_P(PSTR("FREE=%u\r\n"),freeMemory()); 39 | printf_P(PSTR("Press any key to continue\r\n")); 40 | while ( ! SerialUSB.available() ) 41 | { 42 | } 43 | SerialUSB.read(); 44 | printf_P(PSTR("Starting ~/Source/Arduino/1284P/FreeRTOS/pingpair_freertos...\r\n")); 45 | 46 | pinMode(status_pending,OUTPUT); 47 | pinMode(status_ok,OUTPUT); 48 | pinMode(status_fail,OUTPUT); 49 | 50 | // setup the radio 51 | setup_radio(); 52 | 53 | /* Create the Semaphore for synchronization between hw & softirq */ 54 | vSemaphoreCreateBinary( xRadioIrqSemaphore); 55 | 56 | /* Create the Mutex for accessing the radio */ 57 | xRadioMutex = xSemaphoreCreateMutex(); 58 | 59 | /* Create the Mutex for accessing the console */ 60 | xConsoleMutex = xSemaphoreCreateMutex(); 61 | 62 | /* Create the Payload Queue which carries messages received from the radio */ 63 | xPayloadQueue = xQueueCreate( 5, sizeof(payload_t) ); 64 | 65 | /* Create the Status Queue which carries status received from the radio */ 66 | xStatusQueue = xQueueCreate( 5, sizeof(status_e) ); 67 | 68 | /* Add the tasks to the scheduler */ 69 | xTaskCreate(vRadioSoftIrqTask, (const signed char*)PSTR("RA"), 70 | configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3, NULL ); 71 | xTaskCreate(vReceiverTask, (const signed char*)PSTR("RC"), 72 | configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL ); 73 | xTaskCreate(vSenderTask, (const signed char*)PSTR("SE"), 74 | configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL ); 75 | xTaskCreate(vStatusTask, (const signed char*)PSTR("ST"), 76 | configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL ); 77 | xTaskCreate(vInputTask, (const signed char*)PSTR("IN"), 78 | configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL ); 79 | 80 | /* Start the scheduler. */ 81 | vTaskStartScheduler(); 82 | } 83 | 84 | #ifdef ARDUINO 85 | extern "C" void _write(int,char* str,size_t len) 86 | { 87 | while(len--) 88 | Serial.print(*str++); 89 | } 90 | void loop(void) 91 | { 92 | } 93 | #endif 94 | 95 | 96 | // vim:cin:ai:et:sts=4 sw=4 97 | -------------------------------------------------------------------------------- /examples/twotasks/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir TOP examples twotasks ; 2 | 3 | # Set up output directories 4 | LOCATE_TARGET = $(SEARCH_SOURCE)/out/$(F_CPU) ; 5 | LOCATE_SOURCE = $(LOCATE_TARGET) ; 6 | 7 | # Pull in local libraries 8 | SKETCH_LIBS = MemoryFree ; 9 | HDRS += $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) ; 10 | 11 | # FreeRTOS library 12 | HDRS += $(TOP) ; 13 | Library $(LOCATE_TARGET)/freertos : [ GLOB $(TOP) : $(MODULE_EXT) ] ; 14 | 15 | # Main output executable 16 | Arduino $(SEARCH_SOURCE:B).elf : [ GLOB $(SEARCH_SOURCE) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) : $(MODULE_EXT) ] ; 17 | LinkLibraries $(SEARCH_SOURCE:B).elf : $(LOCATE_TARGET)/freertos : $(TOP)/$(F_CPU)/freertos ; 18 | -------------------------------------------------------------------------------- /examples/twotasks/twotasks.ino: -------------------------------------------------------------------------------- 1 | #include "FreeRTOS.h" 2 | #include "task.h" 3 | #include "Arduino.h" 4 | #include "MemoryFree.h" 5 | 6 | static void vBlinkTask( void *pvParameters ); 7 | static void vPrintTask( void *pvParameters ); 8 | 9 | #ifndef PINS_DEFINED 10 | const int led_red = 13; 11 | #endif 12 | 13 | /*--------------------------------------------------------------------------*/ 14 | 15 | void setup( void ) 16 | { 17 | Serial.begin(57600); 18 | Serial.println(__FILE__); 19 | 20 | /* Create the tasks defined within this file. */ 21 | xTaskCreate( vBlinkTask, ( signed portCHAR * ) "vBlinkTask", 50, NULL, 22 | tskIDLE_PRIORITY+1, NULL ); 23 | xTaskCreate( vPrintTask, ( signed portCHAR * ) "vPrintTask", 120, NULL, 24 | tskIDLE_PRIORITY+2, NULL ); 25 | 26 | Serial.print("FREE="); 27 | Serial.println(freeMemory()); 28 | 29 | vTaskStartScheduler(); 30 | } 31 | 32 | void loop( void ) 33 | { 34 | } 35 | 36 | /*--------------------------------------------------------------------------*/ 37 | 38 | static void vBlinkTask( void * ) 39 | { 40 | pinMode(led_red,OUTPUT); 41 | for( ;; ) 42 | { 43 | digitalWrite(led_red,digitalRead(led_red)^1); 44 | vTaskDelay( 250 ); 45 | } 46 | } 47 | 48 | /*--------------------------------------------------------------------------*/ 49 | 50 | static void vPrintTask( void * ) 51 | { 52 | portTickType xLastWakeTime = xTaskGetTickCount(); 53 | 54 | for( ;; ) 55 | { 56 | Serial.println(xTaskGetTickCount()); 57 | vTaskDelayUntil(&xLastWakeTime,1000); 58 | } 59 | } 60 | 61 | // vim:cin:ai:et:sts=4 sw=4 62 | -------------------------------------------------------------------------------- /heap_1.c: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | 55 | /* 56 | * The simplest possible implementation of pvPortMalloc(). Note that this 57 | * implementation does NOT allow allocated memory to be freed again. 58 | * 59 | * See heap_2.c and heap_3.c for alternative implementations, and the memory 60 | * management pages of http://www.FreeRTOS.org for more information. 61 | */ 62 | #include 63 | 64 | /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining 65 | all the API functions to use the MPU wrappers. That should only be done when 66 | task.h is included from an application file. */ 67 | #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE 68 | 69 | #include "FreeRTOS.h" 70 | #include "task.h" 71 | 72 | #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE 73 | 74 | /* Allocate the memory for the heap. The struct is used to force byte 75 | alignment without using any non-portable code. */ 76 | static union xRTOS_HEAP 77 | { 78 | #if portBYTE_ALIGNMENT == 8 79 | volatile portDOUBLE dDummy; 80 | #else 81 | volatile unsigned long ulDummy; 82 | #endif 83 | unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; 84 | } xHeap; 85 | 86 | static size_t xNextFreeByte = ( size_t ) 0; 87 | /*-----------------------------------------------------------*/ 88 | 89 | void *pvPortMalloc( size_t xWantedSize ) 90 | { 91 | void *pvReturn = NULL; 92 | 93 | /* Ensure that blocks are always aligned to the required number of bytes. */ 94 | #if portBYTE_ALIGNMENT != 1 95 | if( xWantedSize & portBYTE_ALIGNMENT_MASK ) 96 | { 97 | /* Byte alignment required. */ 98 | xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); 99 | } 100 | #endif 101 | 102 | vTaskSuspendAll(); 103 | { 104 | /* Check there is enough room left for the allocation. */ 105 | if( ( ( xNextFreeByte + xWantedSize ) < configTOTAL_HEAP_SIZE ) && 106 | ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */ 107 | { 108 | /* Return the next free byte then increment the index past this 109 | block. */ 110 | pvReturn = &( xHeap.ucHeap[ xNextFreeByte ] ); 111 | xNextFreeByte += xWantedSize; 112 | } 113 | } 114 | xTaskResumeAll(); 115 | 116 | #if( configUSE_MALLOC_FAILED_HOOK == 1 ) 117 | { 118 | if( pvReturn == NULL ) 119 | { 120 | extern void vApplicationMallocFailedHook( void ); 121 | vApplicationMallocFailedHook(); 122 | } 123 | } 124 | #endif 125 | 126 | return pvReturn; 127 | } 128 | /*-----------------------------------------------------------*/ 129 | 130 | void vPortFree( void *pv ) 131 | { 132 | /* Memory cannot be freed using this scheme. See heap_2.c and heap_3.c 133 | for alternative implementations, and the memory management pages of 134 | http://www.FreeRTOS.org for more information. */ 135 | ( void ) pv; 136 | } 137 | /*-----------------------------------------------------------*/ 138 | 139 | void vPortInitialiseBlocks( void ) 140 | { 141 | /* Only required when static memory is not cleared. */ 142 | xNextFreeByte = ( size_t ) 0; 143 | } 144 | /*-----------------------------------------------------------*/ 145 | 146 | size_t xPortGetFreeHeapSize( void ) 147 | { 148 | return ( configTOTAL_HEAP_SIZE - xNextFreeByte ); 149 | } 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /list.c: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | 55 | #include 56 | #include "FreeRTOS.h" 57 | #include "list.h" 58 | 59 | /*----------------------------------------------------------- 60 | * PUBLIC LIST API documented in list.h 61 | *----------------------------------------------------------*/ 62 | 63 | void vListInitialise( xList *pxList ) 64 | { 65 | /* The list structure contains a list item which is used to mark the 66 | end of the list. To initialise the list the list end is inserted 67 | as the only list entry. */ 68 | pxList->pxIndex = ( xListItem * ) &( pxList->xListEnd ); 69 | 70 | /* The list end value is the highest possible value in the list to 71 | ensure it remains at the end of the list. */ 72 | pxList->xListEnd.xItemValue = portMAX_DELAY; 73 | 74 | /* The list end next and previous pointers point to itself so we know 75 | when the list is empty. */ 76 | pxList->xListEnd.pxNext = ( xListItem * ) &( pxList->xListEnd ); 77 | pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd ); 78 | 79 | pxList->uxNumberOfItems = ( unsigned portBASE_TYPE ) 0U; 80 | } 81 | /*-----------------------------------------------------------*/ 82 | 83 | void vListInitialiseItem( xListItem *pxItem ) 84 | { 85 | /* Make sure the list item is not recorded as being on a list. */ 86 | pxItem->pvContainer = NULL; 87 | } 88 | /*-----------------------------------------------------------*/ 89 | 90 | void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ) 91 | { 92 | volatile xListItem * pxIndex; 93 | 94 | /* Insert a new list item into pxList, but rather than sort the list, 95 | makes the new list item the last item to be removed by a call to 96 | pvListGetOwnerOfNextEntry. This means it has to be the item pointed to by 97 | the pxIndex member. */ 98 | pxIndex = pxList->pxIndex; 99 | 100 | pxNewListItem->pxNext = pxIndex->pxNext; 101 | pxNewListItem->pxPrevious = pxList->pxIndex; 102 | pxIndex->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; 103 | pxIndex->pxNext = ( volatile xListItem * ) pxNewListItem; 104 | pxList->pxIndex = ( volatile xListItem * ) pxNewListItem; 105 | 106 | /* Remember which list the item is in. */ 107 | pxNewListItem->pvContainer = ( void * ) pxList; 108 | 109 | ( pxList->uxNumberOfItems )++; 110 | } 111 | /*-----------------------------------------------------------*/ 112 | 113 | void vListInsert( xList *pxList, xListItem *pxNewListItem ) 114 | { 115 | volatile xListItem *pxIterator; 116 | portTickType xValueOfInsertion; 117 | 118 | /* Insert the new list item into the list, sorted in ulListItem order. */ 119 | xValueOfInsertion = pxNewListItem->xItemValue; 120 | 121 | /* If the list already contains a list item with the same item value then 122 | the new list item should be placed after it. This ensures that TCB's which 123 | are stored in ready lists (all of which have the same ulListItem value) 124 | get an equal share of the CPU. However, if the xItemValue is the same as 125 | the back marker the iteration loop below will not end. This means we need 126 | to guard against this by checking the value first and modifying the 127 | algorithm slightly if necessary. */ 128 | if( xValueOfInsertion == portMAX_DELAY ) 129 | { 130 | pxIterator = pxList->xListEnd.pxPrevious; 131 | } 132 | else 133 | { 134 | /* *** NOTE *********************************************************** 135 | If you find your application is crashing here then likely causes are: 136 | 1) Stack overflow - 137 | see http://www.freertos.org/Stacks-and-stack-overflow-checking.html 138 | 2) Incorrect interrupt priority assignment, especially on Cortex-M3 139 | parts where numerically high priority values denote low actual 140 | interrupt priories, which can seem counter intuitive. See 141 | configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html 142 | 3) Calling an API function from within a critical section or when 143 | the scheduler is suspended. 144 | 4) Using a queue or semaphore before it has been initialised or 145 | before the scheduler has been started (are interrupts firing 146 | before vTaskStartScheduler() has been called?). 147 | See http://www.freertos.org/FAQHelp.html for more tips. 148 | **********************************************************************/ 149 | 150 | for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) 151 | { 152 | /* There is nothing to do here, we are just iterating to the 153 | wanted insertion position. */ 154 | } 155 | } 156 | 157 | pxNewListItem->pxNext = pxIterator->pxNext; 158 | pxNewListItem->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; 159 | pxNewListItem->pxPrevious = pxIterator; 160 | pxIterator->pxNext = ( volatile xListItem * ) pxNewListItem; 161 | 162 | /* Remember which list the item is in. This allows fast removal of the 163 | item later. */ 164 | pxNewListItem->pvContainer = ( void * ) pxList; 165 | 166 | ( pxList->uxNumberOfItems )++; 167 | } 168 | /*-----------------------------------------------------------*/ 169 | 170 | void vListRemove( xListItem *pxItemToRemove ) 171 | { 172 | xList * pxList; 173 | 174 | pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; 175 | pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; 176 | 177 | /* The list item knows which list it is in. Obtain the list from the list 178 | item. */ 179 | pxList = ( xList * ) pxItemToRemove->pvContainer; 180 | 181 | /* Make sure the index is left pointing to a valid item. */ 182 | if( pxList->pxIndex == pxItemToRemove ) 183 | { 184 | pxList->pxIndex = pxItemToRemove->pxPrevious; 185 | } 186 | 187 | pxItemToRemove->pvContainer = NULL; 188 | ( pxList->uxNumberOfItems )--; 189 | } 190 | /*-----------------------------------------------------------*/ 191 | 192 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | /* 55 | * This is the list implementation used by the scheduler. While it is tailored 56 | * heavily for the schedulers needs, it is also available for use by 57 | * application code. 58 | * 59 | * xLists can only store pointers to xListItems. Each xListItem contains a 60 | * numeric value (xItemValue). Most of the time the lists are sorted in 61 | * descending item value order. 62 | * 63 | * Lists are created already containing one list item. The value of this 64 | * item is the maximum possible that can be stored, it is therefore always at 65 | * the end of the list and acts as a marker. The list member pxHead always 66 | * points to this marker - even though it is at the tail of the list. This 67 | * is because the tail contains a wrap back pointer to the true head of 68 | * the list. 69 | * 70 | * In addition to it's value, each list item contains a pointer to the next 71 | * item in the list (pxNext), a pointer to the list it is in (pxContainer) 72 | * and a pointer to back to the object that contains it. These later two 73 | * pointers are included for efficiency of list manipulation. There is 74 | * effectively a two way link between the object containing the list item and 75 | * the list item itself. 76 | * 77 | * 78 | * \page ListIntroduction List Implementation 79 | * \ingroup FreeRTOSIntro 80 | */ 81 | 82 | 83 | #ifndef LIST_H 84 | #define LIST_H 85 | 86 | #ifdef __cplusplus 87 | extern "C" { 88 | #endif 89 | /* 90 | * Definition of the only type of object that a list can contain. 91 | */ 92 | struct xLIST_ITEM 93 | { 94 | portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ 95 | volatile struct xLIST_ITEM * pxNext; /*< Pointer to the next xListItem in the list. */ 96 | volatile struct xLIST_ITEM * pxPrevious;/*< Pointer to the previous xListItem in the list. */ 97 | void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ 98 | void * pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ 99 | }; 100 | typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */ 101 | 102 | struct xMINI_LIST_ITEM 103 | { 104 | portTickType xItemValue; 105 | volatile struct xLIST_ITEM *pxNext; 106 | volatile struct xLIST_ITEM *pxPrevious; 107 | }; 108 | typedef struct xMINI_LIST_ITEM xMiniListItem; 109 | 110 | /* 111 | * Definition of the type of queue used by the scheduler. 112 | */ 113 | typedef struct xLIST 114 | { 115 | volatile unsigned portBASE_TYPE uxNumberOfItems; 116 | volatile xListItem * pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */ 117 | volatile xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ 118 | } xList; 119 | 120 | /* 121 | * Access macro to set the owner of a list item. The owner of a list item 122 | * is the object (usually a TCB) that contains the list item. 123 | * 124 | * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER 125 | * \ingroup LinkedList 126 | */ 127 | #define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) 128 | 129 | /* 130 | * Access macro to set the value of the list item. In most cases the value is 131 | * used to sort the list in descending order. 132 | * 133 | * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE 134 | * \ingroup LinkedList 135 | */ 136 | #define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( pxListItem )->xItemValue = ( xValue ) 137 | 138 | /* 139 | * Access macro the retrieve the value of the list item. The value can 140 | * represent anything - for example a the priority of a task, or the time at 141 | * which a task should be unblocked. 142 | * 143 | * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE 144 | * \ingroup LinkedList 145 | */ 146 | #define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) 147 | 148 | /* 149 | * Access macro the retrieve the value of the list item at the head of a given 150 | * list. 151 | * 152 | * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE 153 | * \ingroup LinkedList 154 | */ 155 | #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->xItemValue ) 156 | 157 | /* 158 | * Access macro to determine if a list contains any items. The macro will 159 | * only have the value true if the list is empty. 160 | * 161 | * \page listLIST_IS_EMPTY listLIST_IS_EMPTY 162 | * \ingroup LinkedList 163 | */ 164 | #define listLIST_IS_EMPTY( pxList ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 ) 165 | 166 | /* 167 | * Access macro to return the number of items in the list. 168 | */ 169 | #define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) 170 | 171 | /* 172 | * Access function to obtain the owner of the next entry in a list. 173 | * 174 | * The list member pxIndex is used to walk through a list. Calling 175 | * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list 176 | * and returns that entries pxOwner parameter. Using multiple calls to this 177 | * function it is therefore possible to move through every item contained in 178 | * a list. 179 | * 180 | * The pxOwner parameter of a list item is a pointer to the object that owns 181 | * the list item. In the scheduler this is normally a task control block. 182 | * The pxOwner parameter effectively creates a two way link between the list 183 | * item and its owner. 184 | * 185 | * @param pxList The list from which the next item owner is to be returned. 186 | * 187 | * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY 188 | * \ingroup LinkedList 189 | */ 190 | #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ 191 | { \ 192 | xList * const pxConstList = ( pxList ); \ 193 | /* Increment the index to the next item and return the item, ensuring */ \ 194 | /* we don't return the marker used at the end of the list. */ \ 195 | ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ 196 | if( ( pxConstList )->pxIndex == ( xListItem * ) &( ( pxConstList )->xListEnd ) ) \ 197 | { \ 198 | ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ 199 | } \ 200 | ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ 201 | } 202 | 203 | 204 | /* 205 | * Access function to obtain the owner of the first entry in a list. Lists 206 | * are normally sorted in ascending item value order. 207 | * 208 | * This function returns the pxOwner member of the first item in the list. 209 | * The pxOwner parameter of a list item is a pointer to the object that owns 210 | * the list item. In the scheduler this is normally a task control block. 211 | * The pxOwner parameter effectively creates a two way link between the list 212 | * item and its owner. 213 | * 214 | * @param pxList The list from which the owner of the head item is to be 215 | * returned. 216 | * 217 | * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY 218 | * \ingroup LinkedList 219 | */ 220 | #define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) 221 | 222 | /* 223 | * Check to see if a list item is within a list. The list item maintains a 224 | * "container" pointer that points to the list it is in. All this macro does 225 | * is check to see if the container and the list match. 226 | * 227 | * @param pxList The list we want to know if the list item is within. 228 | * @param pxListItem The list item we want to know if is in the list. 229 | * @return pdTRUE is the list item is in the list, otherwise pdFALSE. 230 | * pointer against 231 | */ 232 | #define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) 233 | 234 | /* 235 | * Must be called before a list is used! This initialises all the members 236 | * of the list structure and inserts the xListEnd item into the list as a 237 | * marker to the back of the list. 238 | * 239 | * @param pxList Pointer to the list being initialised. 240 | * 241 | * \page vListInitialise vListInitialise 242 | * \ingroup LinkedList 243 | */ 244 | void vListInitialise( xList *pxList ); 245 | 246 | /* 247 | * Must be called before a list item is used. This sets the list container to 248 | * null so the item does not think that it is already contained in a list. 249 | * 250 | * @param pxItem Pointer to the list item being initialised. 251 | * 252 | * \page vListInitialiseItem vListInitialiseItem 253 | * \ingroup LinkedList 254 | */ 255 | void vListInitialiseItem( xListItem *pxItem ); 256 | 257 | /* 258 | * Insert a list item into a list. The item will be inserted into the list in 259 | * a position determined by its item value (descending item value order). 260 | * 261 | * @param pxList The list into which the item is to be inserted. 262 | * 263 | * @param pxNewListItem The item to that is to be placed in the list. 264 | * 265 | * \page vListInsert vListInsert 266 | * \ingroup LinkedList 267 | */ 268 | void vListInsert( xList *pxList, xListItem *pxNewListItem ); 269 | 270 | /* 271 | * Insert a list item into a list. The item will be inserted in a position 272 | * such that it will be the last item within the list returned by multiple 273 | * calls to listGET_OWNER_OF_NEXT_ENTRY. 274 | * 275 | * The list member pvIndex is used to walk through a list. Calling 276 | * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list. 277 | * Placing an item in a list using vListInsertEnd effectively places the item 278 | * in the list position pointed to by pvIndex. This means that every other 279 | * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before 280 | * the pvIndex parameter again points to the item being inserted. 281 | * 282 | * @param pxList The list into which the item is to be inserted. 283 | * 284 | * @param pxNewListItem The list item to be inserted into the list. 285 | * 286 | * \page vListInsertEnd vListInsertEnd 287 | * \ingroup LinkedList 288 | */ 289 | void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ); 290 | 291 | /* 292 | * Remove an item from a list. The list item has a pointer to the list that 293 | * it is in, so only the list item need be passed into the function. 294 | * 295 | * @param vListRemove The item to be removed. The item will remove itself from 296 | * the list pointed to by it's pxContainer parameter. 297 | * 298 | * \page vListRemove vListRemove 299 | * \ingroup LinkedList 300 | */ 301 | void vListRemove( xListItem *pxItemToRemove ); 302 | 303 | #ifdef __cplusplus 304 | } 305 | #endif 306 | 307 | #endif 308 | 309 | -------------------------------------------------------------------------------- /mpu_wrappers.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | #ifndef MPU_WRAPPERS_H 55 | #define MPU_WRAPPERS_H 56 | 57 | /* This file redefines API functions to be called through a wrapper macro, but 58 | only for ports that are using the MPU. */ 59 | #ifdef portUSING_MPU_WRAPPERS 60 | 61 | /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is 62 | included from queue.c or task.c to prevent it from having an effect within 63 | those files. */ 64 | #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE 65 | 66 | #define xTaskGenericCreate MPU_xTaskGenericCreate 67 | #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions 68 | #define vTaskDelete MPU_vTaskDelete 69 | #define vTaskDelayUntil MPU_vTaskDelayUntil 70 | #define vTaskDelay MPU_vTaskDelay 71 | #define uxTaskPriorityGet MPU_uxTaskPriorityGet 72 | #define vTaskPrioritySet MPU_vTaskPrioritySet 73 | #define vTaskSuspend MPU_vTaskSuspend 74 | #define xTaskIsTaskSuspended MPU_xTaskIsTaskSuspended 75 | #define vTaskResume MPU_vTaskResume 76 | #define vTaskSuspendAll MPU_vTaskSuspendAll 77 | #define xTaskResumeAll MPU_xTaskResumeAll 78 | #define xTaskGetTickCount MPU_xTaskGetTickCount 79 | #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks 80 | #define vTaskList MPU_vTaskList 81 | #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats 82 | #define vTaskStartTrace MPU_vTaskStartTrace 83 | #define ulTaskEndTrace MPU_ulTaskEndTrace 84 | #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag 85 | #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag 86 | #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook 87 | #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark 88 | #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle 89 | #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState 90 | 91 | #define xQueueCreate MPU_xQueueCreate 92 | #define xQueueCreateMutex MPU_xQueueCreateMutex 93 | #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive 94 | #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive 95 | #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore 96 | #define xQueueGenericSend MPU_xQueueGenericSend 97 | #define xQueueAltGenericSend MPU_xQueueAltGenericSend 98 | #define xQueueAltGenericReceive MPU_xQueueAltGenericReceive 99 | #define xQueueGenericReceive MPU_xQueueGenericReceive 100 | #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting 101 | #define vQueueDelete MPU_vQueueDelete 102 | 103 | #define pvPortMalloc MPU_pvPortMalloc 104 | #define vPortFree MPU_vPortFree 105 | #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize 106 | #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks 107 | 108 | #if configQUEUE_REGISTRY_SIZE > 0 109 | #define vQueueAddToRegistry MPU_vQueueAddToRegistry 110 | #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue 111 | #endif 112 | 113 | /* Remove the privileged function macro. */ 114 | #define PRIVILEGED_FUNCTION 115 | 116 | #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ 117 | 118 | /* Ensure API functions go in the privileged execution section. */ 119 | #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) 120 | #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) 121 | //#define PRIVILEGED_DATA 122 | 123 | #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ 124 | 125 | #else /* portUSING_MPU_WRAPPERS */ 126 | 127 | #define PRIVILEGED_FUNCTION 128 | #define PRIVILEGED_DATA 129 | #define portUSING_MPU_WRAPPERS 0 130 | 131 | #endif /* portUSING_MPU_WRAPPERS */ 132 | 133 | 134 | #endif /* MPU_WRAPPERS_H */ 135 | 136 | -------------------------------------------------------------------------------- /port.c: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | /* 55 | 56 | Changes from V2.6.0 57 | 58 | + AVR port - Replaced the inb() and outb() functions with direct memory 59 | access. This allows the port to be built with the 20050414 build of 60 | WinAVR. 61 | */ 62 | 63 | #include 64 | #include 65 | 66 | #include "FreeRTOS.h" 67 | #include "task.h" 68 | 69 | /*----------------------------------------------------------- 70 | * Implementation of functions defined in portable.h for the AVR port. 71 | *----------------------------------------------------------*/ 72 | 73 | /* Start tasks with interrupts enables. */ 74 | #define portFLAGS_INT_ENABLED ( ( portSTACK_TYPE ) 0x80 ) 75 | 76 | /* Hardware constants for timer 1. */ 77 | #define portCLEAR_COUNTER_ON_MATCH ( ( unsigned char ) (1<>= 8; 237 | *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff ); 238 | pxTopOfStack--; 239 | 240 | /* Next simulate the stack as if after a call to portSAVE_CONTEXT(). 241 | portSAVE_CONTEXT places the flags on the stack immediately after r0 242 | to ensure the interrupts get disabled as soon as possible, and so ensuring 243 | the stack use is minimal should a context switch interrupt occur. */ 244 | *pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* R0 */ 245 | pxTopOfStack--; 246 | *pxTopOfStack = portFLAGS_INT_ENABLED; 247 | pxTopOfStack--; 248 | 249 | 250 | /* Now the remaining registers. The compiler expects R1 to be 0. */ 251 | *pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* R1 */ 252 | pxTopOfStack--; 253 | *pxTopOfStack = ( portSTACK_TYPE ) 0x02; /* R2 */ 254 | pxTopOfStack--; 255 | *pxTopOfStack = ( portSTACK_TYPE ) 0x03; /* R3 */ 256 | pxTopOfStack--; 257 | *pxTopOfStack = ( portSTACK_TYPE ) 0x04; /* R4 */ 258 | pxTopOfStack--; 259 | *pxTopOfStack = ( portSTACK_TYPE ) 0x05; /* R5 */ 260 | pxTopOfStack--; 261 | *pxTopOfStack = ( portSTACK_TYPE ) 0x06; /* R6 */ 262 | pxTopOfStack--; 263 | *pxTopOfStack = ( portSTACK_TYPE ) 0x07; /* R7 */ 264 | pxTopOfStack--; 265 | *pxTopOfStack = ( portSTACK_TYPE ) 0x08; /* R8 */ 266 | pxTopOfStack--; 267 | *pxTopOfStack = ( portSTACK_TYPE ) 0x09; /* R9 */ 268 | pxTopOfStack--; 269 | *pxTopOfStack = ( portSTACK_TYPE ) 0x10; /* R10 */ 270 | pxTopOfStack--; 271 | *pxTopOfStack = ( portSTACK_TYPE ) 0x11; /* R11 */ 272 | pxTopOfStack--; 273 | *pxTopOfStack = ( portSTACK_TYPE ) 0x12; /* R12 */ 274 | pxTopOfStack--; 275 | *pxTopOfStack = ( portSTACK_TYPE ) 0x13; /* R13 */ 276 | pxTopOfStack--; 277 | *pxTopOfStack = ( portSTACK_TYPE ) 0x14; /* R14 */ 278 | pxTopOfStack--; 279 | *pxTopOfStack = ( portSTACK_TYPE ) 0x15; /* R15 */ 280 | pxTopOfStack--; 281 | *pxTopOfStack = ( portSTACK_TYPE ) 0x16; /* R16 */ 282 | pxTopOfStack--; 283 | *pxTopOfStack = ( portSTACK_TYPE ) 0x17; /* R17 */ 284 | pxTopOfStack--; 285 | *pxTopOfStack = ( portSTACK_TYPE ) 0x18; /* R18 */ 286 | pxTopOfStack--; 287 | *pxTopOfStack = ( portSTACK_TYPE ) 0x19; /* R19 */ 288 | pxTopOfStack--; 289 | *pxTopOfStack = ( portSTACK_TYPE ) 0x20; /* R20 */ 290 | pxTopOfStack--; 291 | *pxTopOfStack = ( portSTACK_TYPE ) 0x21; /* R21 */ 292 | pxTopOfStack--; 293 | *pxTopOfStack = ( portSTACK_TYPE ) 0x22; /* R22 */ 294 | pxTopOfStack--; 295 | *pxTopOfStack = ( portSTACK_TYPE ) 0x23; /* R23 */ 296 | pxTopOfStack--; 297 | 298 | /* Place the parameter on the stack in the expected location. */ 299 | usAddress = ( unsigned short ) pvParameters; 300 | *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff ); 301 | pxTopOfStack--; 302 | 303 | usAddress >>= 8; 304 | *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff ); 305 | pxTopOfStack--; 306 | 307 | *pxTopOfStack = ( portSTACK_TYPE ) 0x26; /* R26 X */ 308 | pxTopOfStack--; 309 | *pxTopOfStack = ( portSTACK_TYPE ) 0x27; /* R27 */ 310 | pxTopOfStack--; 311 | *pxTopOfStack = ( portSTACK_TYPE ) 0x28; /* R28 Y */ 312 | pxTopOfStack--; 313 | *pxTopOfStack = ( portSTACK_TYPE ) 0x29; /* R29 */ 314 | pxTopOfStack--; 315 | *pxTopOfStack = ( portSTACK_TYPE ) 0x30; /* R30 Z */ 316 | pxTopOfStack--; 317 | *pxTopOfStack = ( portSTACK_TYPE ) 0x031; /* R31 */ 318 | pxTopOfStack--; 319 | 320 | /*lint +e950 +e611 +e923 */ 321 | 322 | return pxTopOfStack; 323 | } 324 | /*-----------------------------------------------------------*/ 325 | 326 | portBASE_TYPE xPortStartScheduler( void ) 327 | { 328 | /* Setup the hardware to generate the tick. */ 329 | prvSetupTimerInterrupt(); 330 | 331 | /* Restore the context of the first task that is going to run. */ 332 | portRESTORE_CONTEXT(); 333 | 334 | /* Simulate a function call end as generated by the compiler. We will now 335 | jump to the start of the task the context of which we have just restored. */ 336 | asm volatile ( "ret" ); 337 | 338 | /* Should not get here. */ 339 | return pdTRUE; 340 | } 341 | /*-----------------------------------------------------------*/ 342 | 343 | void vPortEndScheduler( void ) 344 | { 345 | /* It is unlikely that the AVR port will get stopped. If required simply 346 | disable the tick interrupt here. */ 347 | } 348 | /*-----------------------------------------------------------*/ 349 | 350 | /* 351 | * Manual context switch. The first thing we do is save the registers so we 352 | * can use a naked attribute. 353 | */ 354 | void vPortYield( void ) __attribute__ ( ( naked ) ); 355 | void vPortYield( void ) 356 | { 357 | portSAVE_CONTEXT(); 358 | vTaskSwitchContext(); 359 | portRESTORE_CONTEXT(); 360 | 361 | asm volatile ( "ret" ); 362 | } 363 | /*-----------------------------------------------------------*/ 364 | 365 | /* 366 | * Context switch function used by the tick. This must be identical to 367 | * vPortYield() from the call to vTaskSwitchContext() onwards. The only 368 | * difference from vPortYield() is the tick count is incremented as the 369 | * call comes from the tick ISR. 370 | */ 371 | void vPortYieldFromTick( void ) __attribute__ ( ( naked ) ); 372 | void vPortYieldFromTick( void ) 373 | { 374 | portSAVE_CONTEXT(); 375 | vTaskIncrementTick(); 376 | vTaskSwitchContext(); 377 | portRESTORE_CONTEXT(); 378 | 379 | asm volatile ( "ret" ); 380 | } 381 | /*-----------------------------------------------------------*/ 382 | 383 | /* 384 | * Setup timer 1 compare match A to generate a tick interrupt. 385 | */ 386 | static void prvSetupTimerInterrupt( void ) 387 | { 388 | unsigned long ulCompareMatch; 389 | unsigned char ucHighByte, ucLowByte; 390 | 391 | /* Using 16bit timer 1 to generate the tick. Correct fuses must be 392 | selected for the configCPU_CLOCK_HZ clock. */ 393 | 394 | ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; 395 | 396 | /* We only have 16 bits so have to scale to get our required tick rate. */ 397 | ulCompareMatch /= portCLOCK_PRESCALER; 398 | 399 | /* Adjust for correct value. */ 400 | ulCompareMatch -= ( unsigned long ) 1; 401 | 402 | /* Setup compare match value for compare match A. Interrupts are disabled 403 | before this is called so we need not worry here. */ 404 | ucLowByte = ( unsigned char ) ( ulCompareMatch & ( unsigned long ) 0xff ); 405 | ulCompareMatch >>= 8; 406 | ucHighByte = ( unsigned char ) ( ulCompareMatch & ( unsigned long ) 0xff ); 407 | OCR1AH = ucHighByte; 408 | OCR1AL = ucLowByte; 409 | 410 | /* Setup clock source and compare match behaviour. */ 411 | ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64; 412 | TCCR1B = ucLowByte; 413 | 414 | /* Enable the interrupt - this is okay as interrupt are currently globally 415 | disabled. */ 416 | ucLowByte = TIMSK1; 417 | ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE; 418 | TIMSK1 = ucLowByte; 419 | } 420 | /*-----------------------------------------------------------*/ 421 | 422 | #if configUSE_PREEMPTION == 1 423 | 424 | /* 425 | * Tick ISR for preemptive scheduler. We can use a naked attribute as 426 | * the context is saved at the start of vPortYieldFromTick(). The tick 427 | * count is incremented after the context is saved. 428 | */ 429 | void TIMER1_COMPA_vect( void ) __attribute__ ( ( signal, naked ) ); 430 | void TIMER1_COMPA_vect( void ) 431 | { 432 | vPortYieldFromTick(); 433 | asm volatile ( "reti" ); 434 | } 435 | #else 436 | 437 | /* 438 | * Tick ISR for the cooperative scheduler. All this does is increment the 439 | * tick count. We don't need to switch context, this can only be done by 440 | * manual calls to taskYIELD(); 441 | */ 442 | void TIMER1_COMPA_vect( void ) __attribute__ ( ( signal ) ); 443 | void TIMER1_COMPA_vect( void ) 444 | { 445 | vTaskIncrementTick(); 446 | } 447 | #endif 448 | 449 | 450 | 451 | -------------------------------------------------------------------------------- /portable.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | /*----------------------------------------------------------- 55 | * Portable layer API. Each function must be defined for each port. 56 | *----------------------------------------------------------*/ 57 | 58 | #ifndef PORTABLE_H 59 | #define PORTABLE_H 60 | 61 | /* Include the macro file relevant to the port being used. */ 62 | 63 | #ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT 64 | #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" 65 | typedef void ( __interrupt __far *pxISR )(); 66 | #endif 67 | 68 | #ifdef OPEN_WATCOM_FLASH_LITE_186_PORT 69 | #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" 70 | typedef void ( __interrupt __far *pxISR )(); 71 | #endif 72 | 73 | #ifdef GCC_MEGA_AVR 74 | #include "../portable/GCC/ATMega323/portmacro.h" 75 | #endif 76 | 77 | #ifdef IAR_MEGA_AVR 78 | #include "../portable/IAR/ATMega323/portmacro.h" 79 | #endif 80 | 81 | #ifdef MPLAB_PIC24_PORT 82 | #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" 83 | #endif 84 | 85 | #ifdef MPLAB_DSPIC_PORT 86 | #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" 87 | #endif 88 | 89 | #ifdef MPLAB_PIC18F_PORT 90 | #include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h" 91 | #endif 92 | 93 | #ifdef MPLAB_PIC32MX_PORT 94 | #include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h" 95 | #endif 96 | 97 | #ifdef _FEDPICC 98 | #include "libFreeRTOS/Include/portmacro.h" 99 | #endif 100 | 101 | #ifdef SDCC_CYGNAL 102 | #include "../../Source/portable/SDCC/Cygnal/portmacro.h" 103 | #endif 104 | 105 | #ifdef GCC_ARM7 106 | #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" 107 | #endif 108 | 109 | #ifdef GCC_ARM7_ECLIPSE 110 | #include "portmacro.h" 111 | #endif 112 | 113 | #ifdef ROWLEY_LPC23xx 114 | #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" 115 | #endif 116 | 117 | #ifdef IAR_MSP430 118 | #include "..\..\Source\portable\IAR\MSP430\portmacro.h" 119 | #endif 120 | 121 | #ifdef GCC_MSP430 122 | #include "../../Source/portable/GCC/MSP430F449/portmacro.h" 123 | #endif 124 | 125 | #ifdef ROWLEY_MSP430 126 | #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" 127 | #endif 128 | 129 | #ifdef ARM7_LPC21xx_KEIL_RVDS 130 | #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" 131 | #endif 132 | 133 | #ifdef SAM7_GCC 134 | #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" 135 | #endif 136 | 137 | #ifdef SAM7_IAR 138 | #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" 139 | #endif 140 | 141 | #ifdef SAM9XE_IAR 142 | #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" 143 | #endif 144 | 145 | #ifdef LPC2000_IAR 146 | #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" 147 | #endif 148 | 149 | #ifdef STR71X_IAR 150 | #include "..\..\Source\portable\IAR\STR71x\portmacro.h" 151 | #endif 152 | 153 | #ifdef STR75X_IAR 154 | #include "..\..\Source\portable\IAR\STR75x\portmacro.h" 155 | #endif 156 | 157 | #ifdef STR75X_GCC 158 | #include "..\..\Source\portable\GCC\STR75x\portmacro.h" 159 | #endif 160 | 161 | #ifdef STR91X_IAR 162 | #include "..\..\Source\portable\IAR\STR91x\portmacro.h" 163 | #endif 164 | 165 | #ifdef GCC_H8S 166 | #include "../../Source/portable/GCC/H8S2329/portmacro.h" 167 | #endif 168 | 169 | #ifdef GCC_AT91FR40008 170 | #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" 171 | #endif 172 | 173 | #ifdef RVDS_ARMCM3_LM3S102 174 | #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" 175 | #endif 176 | 177 | #ifdef GCC_ARMCM3_LM3S102 178 | #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" 179 | #endif 180 | 181 | #ifdef GCC_ARMCM3 182 | #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" 183 | #endif 184 | 185 | #ifdef IAR_ARM_CM3 186 | #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" 187 | #endif 188 | 189 | #ifdef IAR_ARMCM3_LM 190 | #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" 191 | #endif 192 | 193 | #ifdef HCS12_CODE_WARRIOR 194 | #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" 195 | #endif 196 | 197 | #ifdef MICROBLAZE_GCC 198 | #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" 199 | #endif 200 | 201 | #ifdef TERN_EE 202 | #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" 203 | #endif 204 | 205 | #ifdef GCC_HCS12 206 | #include "../../Source/portable/GCC/HCS12/portmacro.h" 207 | #endif 208 | 209 | #ifdef GCC_MCF5235 210 | #include "../../Source/portable/GCC/MCF5235/portmacro.h" 211 | #endif 212 | 213 | #ifdef COLDFIRE_V2_GCC 214 | #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" 215 | #endif 216 | 217 | #ifdef COLDFIRE_V2_CODEWARRIOR 218 | #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" 219 | #endif 220 | 221 | #ifdef GCC_PPC405 222 | #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" 223 | #endif 224 | 225 | #ifdef GCC_PPC440 226 | #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" 227 | #endif 228 | 229 | #ifdef _16FX_SOFTUNE 230 | #include "..\..\Source\portable\Softune\MB96340\portmacro.h" 231 | #endif 232 | 233 | #ifdef BCC_INDUSTRIAL_PC_PORT 234 | /* A short file name has to be used in place of the normal 235 | FreeRTOSConfig.h when using the Borland compiler. */ 236 | #include "frconfig.h" 237 | #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" 238 | typedef void ( __interrupt __far *pxISR )(); 239 | #endif 240 | 241 | #ifdef BCC_FLASH_LITE_186_PORT 242 | /* A short file name has to be used in place of the normal 243 | FreeRTOSConfig.h when using the Borland compiler. */ 244 | #include "frconfig.h" 245 | #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" 246 | typedef void ( __interrupt __far *pxISR )(); 247 | #endif 248 | 249 | #ifdef __GNUC__ 250 | #ifdef __AVR32_AVR32A__ 251 | #include "portmacro.h" 252 | #endif 253 | #endif 254 | 255 | #ifdef __ICCAVR32__ 256 | #ifdef __CORE__ 257 | #if __CORE__ == __AVR32A__ 258 | #include "portmacro.h" 259 | #endif 260 | #endif 261 | #endif 262 | 263 | #ifdef __91467D 264 | #include "portmacro.h" 265 | #endif 266 | 267 | #ifdef __96340 268 | #include "portmacro.h" 269 | #endif 270 | 271 | 272 | #ifdef __IAR_V850ES_Fx3__ 273 | #include "../../Source/portable/IAR/V850ES/portmacro.h" 274 | #endif 275 | 276 | #ifdef __IAR_V850ES_Jx3__ 277 | #include "../../Source/portable/IAR/V850ES/portmacro.h" 278 | #endif 279 | 280 | #ifdef __IAR_V850ES_Jx3_L__ 281 | #include "../../Source/portable/IAR/V850ES/portmacro.h" 282 | #endif 283 | 284 | #ifdef __IAR_V850ES_Jx2__ 285 | #include "../../Source/portable/IAR/V850ES/portmacro.h" 286 | #endif 287 | 288 | #ifdef __IAR_V850ES_Hx2__ 289 | #include "../../Source/portable/IAR/V850ES/portmacro.h" 290 | #endif 291 | 292 | #ifdef __IAR_78K0R_Kx3__ 293 | #include "../../Source/portable/IAR/78K0R/portmacro.h" 294 | #endif 295 | 296 | #ifdef __IAR_78K0R_Kx3L__ 297 | #include "../../Source/portable/IAR/78K0R/portmacro.h" 298 | #endif 299 | 300 | /* Catch all to ensure portmacro.h is included in the build. Newer demos 301 | have the path as part of the project options, rather than as relative from 302 | the project location. If portENTER_CRITICAL() has not been defined then 303 | portmacro.h has not yet been included - as every portmacro.h provides a 304 | portENTER_CRITICAL() definition. Check the demo application for your demo 305 | to find the path to the correct portmacro.h file. */ 306 | #ifndef portENTER_CRITICAL 307 | #include "portmacro.h" 308 | #endif 309 | 310 | #if portBYTE_ALIGNMENT == 8 311 | #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) 312 | #endif 313 | 314 | #if portBYTE_ALIGNMENT == 4 315 | #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) 316 | #endif 317 | 318 | #if portBYTE_ALIGNMENT == 2 319 | #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) 320 | #endif 321 | 322 | #if portBYTE_ALIGNMENT == 1 323 | #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) 324 | #endif 325 | 326 | #ifndef portBYTE_ALIGNMENT_MASK 327 | #error "Invalid portBYTE_ALIGNMENT definition" 328 | #endif 329 | 330 | #ifndef portNUM_CONFIGURABLE_REGIONS 331 | #define portNUM_CONFIGURABLE_REGIONS 1 332 | #endif 333 | 334 | #ifdef __cplusplus 335 | extern "C" { 336 | #endif 337 | 338 | #include "mpu_wrappers.h" 339 | 340 | /* 341 | * Setup the stack of a new task so it is ready to be placed under the 342 | * scheduler control. The registers have to be placed on the stack in 343 | * the order that the port expects to find them. 344 | * 345 | */ 346 | #if( portUSING_MPU_WRAPPERS == 1 ) 347 | portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters, portBASE_TYPE xRunPrivileged ) PRIVILEGED_FUNCTION; 348 | #else 349 | portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ); 350 | #endif 351 | 352 | /* 353 | * Map to the memory management routines required for the port. 354 | */ 355 | void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; 356 | void vPortFree( void *pv ) PRIVILEGED_FUNCTION; 357 | void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; 358 | size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; 359 | 360 | /* 361 | * Setup the hardware ready for the scheduler to take control. This generally 362 | * sets up a tick interrupt and sets timers for the correct tick frequency. 363 | */ 364 | portBASE_TYPE xPortStartScheduler( void ) PRIVILEGED_FUNCTION; 365 | 366 | /* 367 | * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so 368 | * the hardware is left in its original condition after the scheduler stops 369 | * executing. 370 | */ 371 | void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; 372 | 373 | /* 374 | * The structures and methods of manipulating the MPU are contained within the 375 | * port layer. 376 | * 377 | * Fills the xMPUSettings structure with the memory region information 378 | * contained in xRegions. 379 | */ 380 | #if( portUSING_MPU_WRAPPERS == 1 ) 381 | struct xMEMORY_REGION; 382 | void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, portSTACK_TYPE *pxBottomOfStack, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; 383 | #endif 384 | 385 | #ifdef __cplusplus 386 | } 387 | #endif 388 | 389 | #endif /* PORTABLE_H */ 390 | 391 | -------------------------------------------------------------------------------- /portmacro.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | /* 55 | Changes from V1.2.3 56 | 57 | + portCPU_CLOSK_HZ definition changed to 8MHz base 10, previously it 58 | base 16. 59 | */ 60 | 61 | #ifndef PORTMACRO_H 62 | #define PORTMACRO_H 63 | 64 | #ifdef __cplusplus 65 | extern "C" { 66 | #endif 67 | 68 | /*----------------------------------------------------------- 69 | * Port specific definitions. 70 | * 71 | * The settings in this file configure FreeRTOS correctly for the 72 | * given hardware and compiler. 73 | * 74 | * These settings should not be altered. 75 | *----------------------------------------------------------- 76 | */ 77 | 78 | /* Type definitions. */ 79 | #define portCHAR char 80 | #define portFLOAT float 81 | #define portDOUBLE double 82 | #define portLONG long 83 | #define portSHORT int 84 | #define portSTACK_TYPE unsigned portCHAR 85 | #define portBASE_TYPE char 86 | 87 | #if( configUSE_16_BIT_TICKS == 1 ) 88 | typedef unsigned portSHORT portTickType; 89 | #define portMAX_DELAY ( portTickType ) 0xffff 90 | #else 91 | typedef unsigned portLONG portTickType; 92 | #define portMAX_DELAY ( portTickType ) 0xffffffff 93 | #endif 94 | /*-----------------------------------------------------------*/ 95 | 96 | /* Critical section management. */ 97 | #define portENTER_CRITICAL() asm volatile ( "in __tmp_reg__, __SREG__" :: ); \ 98 | asm volatile ( "cli" :: ); \ 99 | asm volatile ( "push __tmp_reg__" :: ) 100 | 101 | #define portEXIT_CRITICAL() asm volatile ( "pop __tmp_reg__" :: ); \ 102 | asm volatile ( "out __SREG__, __tmp_reg__" :: ) 103 | 104 | #define portDISABLE_INTERRUPTS() asm volatile ( "cli" :: ); 105 | #define portENABLE_INTERRUPTS() asm volatile ( "sei" :: ); 106 | /*-----------------------------------------------------------*/ 107 | 108 | /* Architecture specifics. */ 109 | #define portSTACK_GROWTH ( -1 ) 110 | #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) 111 | #define portBYTE_ALIGNMENT 1 112 | #define portNOP() asm volatile ( "nop" ); 113 | /*-----------------------------------------------------------*/ 114 | 115 | /* Kernel utilities. */ 116 | extern void vPortYield( void ) __attribute__ ( ( naked ) ); 117 | #define portYIELD() vPortYield() 118 | /*-----------------------------------------------------------*/ 119 | 120 | /* Task function macros as described on the FreeRTOS.org WEB site. */ 121 | #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) 122 | #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | 128 | #endif /* PORTMACRO_H */ 129 | 130 | -------------------------------------------------------------------------------- /projdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | #ifndef PROJDEFS_H 55 | #define PROJDEFS_H 56 | 57 | /* Defines the prototype to which task functions must conform. */ 58 | typedef void (*pdTASK_CODE)( void * ); 59 | 60 | #define pdTRUE ( 1 ) 61 | #define pdFALSE ( 0 ) 62 | 63 | #define pdPASS ( 1 ) 64 | #define pdFAIL ( 0 ) 65 | #define errQUEUE_EMPTY ( 0 ) 66 | #define errQUEUE_FULL ( 0 ) 67 | 68 | /* Error definitions. */ 69 | #define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) 70 | #define errNO_TASK_TO_RUN ( -2 ) 71 | #define errQUEUE_BLOCKED ( -4 ) 72 | #define errQUEUE_YIELD ( -5 ) 73 | 74 | #endif /* PROJDEFS_H */ 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /timers.c: -------------------------------------------------------------------------------- 1 | /* 2 | FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. 3 | 4 | 5 | *************************************************************************** 6 | * * 7 | * FreeRTOS tutorial books are available in pdf and paperback. * 8 | * Complete, revised, and edited pdf reference manuals are also * 9 | * available. * 10 | * * 11 | * Purchasing FreeRTOS documentation will not only help you, by * 12 | * ensuring you get running as quickly as possible and with an * 13 | * in-depth knowledge of how to use FreeRTOS, it will also help * 14 | * the FreeRTOS project to continue with its mission of providing * 15 | * professional grade, cross platform, de facto standard solutions * 16 | * for microcontrollers - completely free of charge! * 17 | * * 18 | * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * 19 | * * 20 | * Thank you for using FreeRTOS, and thank you for your support! * 21 | * * 22 | *************************************************************************** 23 | 24 | 25 | This file is part of the FreeRTOS distribution. 26 | 27 | FreeRTOS is free software; you can redistribute it and/or modify it under 28 | the terms of the GNU General Public License (version 2) as published by the 29 | Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 30 | >>>NOTE<<< The modification to the GPL is included to allow you to 31 | distribute a combined work that includes FreeRTOS without being obliged to 32 | provide the source code for proprietary components outside of the FreeRTOS 33 | kernel. FreeRTOS is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 35 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 36 | more details. You should have received a copy of the GNU General Public 37 | License and the FreeRTOS license exception along with FreeRTOS; if not it 38 | can be viewed here: http://www.freertos.org/a00114.html and also obtained 39 | by writing to Richard Barry, contact details for whom are available on the 40 | FreeRTOS WEB site. 41 | 42 | 1 tab == 4 spaces! 43 | 44 | http://www.FreeRTOS.org - Documentation, latest information, license and 45 | contact details. 46 | 47 | http://www.SafeRTOS.com - A version that is certified for use in safety 48 | critical systems. 49 | 50 | http://www.OpenRTOS.com - Commercial support, development, porting, 51 | licensing and training services. 52 | */ 53 | 54 | /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining 55 | all the API functions to use the MPU wrappers. That should only be done when 56 | task.h is included from an application file. */ 57 | #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE 58 | 59 | #include "FreeRTOS.h" 60 | #include "task.h" 61 | #include "queue.h" 62 | #include "timers.h" 63 | 64 | #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE 65 | 66 | /* This entire source file will be skipped if the application is not configured 67 | to include software timer functionality. This #if is closed at the very bottom 68 | of this file. If you want to include software timer functionality then ensure 69 | configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ 70 | #if ( configUSE_TIMERS == 1 ) 71 | 72 | /* Misc definitions. */ 73 | #define tmrNO_DELAY ( portTickType ) 0U 74 | 75 | /* The definition of the timers themselves. */ 76 | typedef struct tmrTimerControl 77 | { 78 | const signed char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ 79 | xListItem xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ 80 | portTickType xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ 81 | unsigned portBASE_TYPE uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one shot timer. */ 82 | void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ 83 | tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */ 84 | } xTIMER; 85 | 86 | /* The definition of messages that can be sent and received on the timer 87 | queue. */ 88 | typedef struct tmrTimerQueueMessage 89 | { 90 | portBASE_TYPE xMessageID; /*<< The command being sent to the timer service task. */ 91 | portTickType xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ 92 | xTIMER * pxTimer; /*<< The timer to which the command will be applied. */ 93 | } xTIMER_MESSAGE; 94 | 95 | 96 | /* The list in which active timers are stored. Timers are referenced in expire 97 | time order, with the nearest expiry time at the front of the list. Only the 98 | timer service task is allowed to access xActiveTimerList. */ 99 | PRIVILEGED_DATA static xList xActiveTimerList1; 100 | PRIVILEGED_DATA static xList xActiveTimerList2; 101 | PRIVILEGED_DATA static xList *pxCurrentTimerList; 102 | PRIVILEGED_DATA static xList *pxOverflowTimerList; 103 | 104 | /* A queue that is used to send commands to the timer service task. */ 105 | PRIVILEGED_DATA static xQueueHandle xTimerQueue = NULL; 106 | 107 | #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) 108 | 109 | PRIVILEGED_DATA static xTaskHandle xTimerTaskHandle = NULL; 110 | 111 | #endif 112 | 113 | /*-----------------------------------------------------------*/ 114 | 115 | /* 116 | * Initialise the infrastructure used by the timer service task if it has not 117 | * been initialised already. 118 | */ 119 | static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; 120 | 121 | /* 122 | * The timer service task (daemon). Timer functionality is controlled by this 123 | * task. Other tasks communicate with the timer service task using the 124 | * xTimerQueue queue. 125 | */ 126 | static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; 127 | 128 | /* 129 | * Called by the timer service task to interpret and process a command it 130 | * received on the timer queue. 131 | */ 132 | static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; 133 | 134 | /* 135 | * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, 136 | * depending on if the expire time causes a timer counter overflow. 137 | */ 138 | static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) PRIVILEGED_FUNCTION; 139 | 140 | /* 141 | * An active timer has reached its expire time. Reload the timer if it is an 142 | * auto reload timer, then call its callback. 143 | */ 144 | static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) PRIVILEGED_FUNCTION; 145 | 146 | /* 147 | * The tick count has overflowed. Switch the timer lists after ensuring the 148 | * current timer list does not still reference some timers. 149 | */ 150 | static void prvSwitchTimerLists( portTickType xLastTime ) PRIVILEGED_FUNCTION; 151 | 152 | /* 153 | * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE 154 | * if a tick count overflow occurred since prvSampleTimeNow() was last called. 155 | */ 156 | static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; 157 | 158 | /* 159 | * If the timer list contains any active timers then return the expire time of 160 | * the timer that will expire first and set *pxListWasEmpty to false. If the 161 | * timer list does not contain any timers then return 0 and set *pxListWasEmpty 162 | * to pdTRUE. 163 | */ 164 | static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) PRIVILEGED_FUNCTION; 165 | 166 | /* 167 | * If a timer has expired, process it. Otherwise, block the timer service task 168 | * until either a timer does expire or a command is received. 169 | */ 170 | static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) PRIVILEGED_FUNCTION; 171 | 172 | /*-----------------------------------------------------------*/ 173 | 174 | portBASE_TYPE xTimerCreateTimerTask( void ) 175 | { 176 | portBASE_TYPE xReturn = pdFAIL; 177 | 178 | /* This function is called when the scheduler is started if 179 | configUSE_TIMERS is set to 1. Check that the infrastructure used by the 180 | timer service task has been created/initialised. If timers have already 181 | been created then the initialisation will already have been performed. */ 182 | prvCheckForValidListAndQueue(); 183 | 184 | if( xTimerQueue != NULL ) 185 | { 186 | #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) 187 | { 188 | /* Create the timer task, storing its handle in xTimerTaskHandle so 189 | it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */ 190 | xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY, &xTimerTaskHandle ); 191 | } 192 | #else 193 | { 194 | /* Create the timer task without storing its handle. */ 195 | xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY, NULL); 196 | } 197 | #endif 198 | } 199 | 200 | configASSERT( xReturn ); 201 | return xReturn; 202 | } 203 | /*-----------------------------------------------------------*/ 204 | 205 | xTimerHandle xTimerCreate( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) 206 | { 207 | xTIMER *pxNewTimer; 208 | 209 | /* Allocate the timer structure. */ 210 | if( xTimerPeriodInTicks == ( portTickType ) 0U ) 211 | { 212 | pxNewTimer = NULL; 213 | configASSERT( ( xTimerPeriodInTicks > 0 ) ); 214 | } 215 | else 216 | { 217 | pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) ); 218 | if( pxNewTimer != NULL ) 219 | { 220 | /* Ensure the infrastructure used by the timer service task has been 221 | created/initialised. */ 222 | prvCheckForValidListAndQueue(); 223 | 224 | /* Initialise the timer structure members using the function parameters. */ 225 | pxNewTimer->pcTimerName = pcTimerName; 226 | pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; 227 | pxNewTimer->uxAutoReload = uxAutoReload; 228 | pxNewTimer->pvTimerID = pvTimerID; 229 | pxNewTimer->pxCallbackFunction = pxCallbackFunction; 230 | vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); 231 | 232 | traceTIMER_CREATE( pxNewTimer ); 233 | } 234 | else 235 | { 236 | traceTIMER_CREATE_FAILED(); 237 | } 238 | } 239 | 240 | return ( xTimerHandle ) pxNewTimer; 241 | } 242 | /*-----------------------------------------------------------*/ 243 | 244 | portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) 245 | { 246 | portBASE_TYPE xReturn = pdFAIL; 247 | xTIMER_MESSAGE xMessage; 248 | 249 | /* Send a message to the timer service task to perform a particular action 250 | on a particular timer definition. */ 251 | if( xTimerQueue != NULL ) 252 | { 253 | /* Send a command to the timer service task to start the xTimer timer. */ 254 | xMessage.xMessageID = xCommandID; 255 | xMessage.xMessageValue = xOptionalValue; 256 | xMessage.pxTimer = ( xTIMER * ) xTimer; 257 | 258 | if( pxHigherPriorityTaskWoken == NULL ) 259 | { 260 | if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) 261 | { 262 | xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xBlockTime ); 263 | } 264 | else 265 | { 266 | xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); 267 | } 268 | } 269 | else 270 | { 271 | xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); 272 | } 273 | 274 | traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); 275 | } 276 | 277 | return xReturn; 278 | } 279 | /*-----------------------------------------------------------*/ 280 | 281 | #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) 282 | 283 | xTaskHandle xTimerGetTimerDaemonTaskHandle( void ) 284 | { 285 | /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been 286 | started, then xTimerTaskHandle will be NULL. */ 287 | configASSERT( ( xTimerTaskHandle != NULL ) ); 288 | return xTimerTaskHandle; 289 | } 290 | 291 | #endif 292 | /*-----------------------------------------------------------*/ 293 | 294 | static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) 295 | { 296 | xTIMER *pxTimer; 297 | portBASE_TYPE xResult; 298 | 299 | /* Remove the timer from the list of active timers. A check has already 300 | been performed to ensure the list is not empty. */ 301 | pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); 302 | vListRemove( &( pxTimer->xTimerListItem ) ); 303 | traceTIMER_EXPIRED( pxTimer ); 304 | 305 | /* If the timer is an auto reload timer then calculate the next 306 | expiry time and re-insert the timer in the list of active timers. */ 307 | if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) 308 | { 309 | /* This is the only time a timer is inserted into a list using 310 | a time relative to anything other than the current time. It 311 | will therefore be inserted into the correct list relative to 312 | the time this task thinks it is now, even if a command to 313 | switch lists due to a tick count overflow is already waiting in 314 | the timer queue. */ 315 | if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) 316 | { 317 | /* The timer expired before it was added to the active timer 318 | list. Reload it now. */ 319 | xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); 320 | configASSERT( xResult ); 321 | ( void ) xResult; 322 | } 323 | } 324 | 325 | /* Call the timer callback. */ 326 | pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); 327 | } 328 | /*-----------------------------------------------------------*/ 329 | 330 | static void prvTimerTask( void *pvParameters ) 331 | { 332 | portTickType xNextExpireTime; 333 | portBASE_TYPE xListWasEmpty; 334 | 335 | /* Just to avoid compiler warnings. */ 336 | ( void ) pvParameters; 337 | 338 | for( ;; ) 339 | { 340 | /* Query the timers list to see if it contains any timers, and if so, 341 | obtain the time at which the next timer will expire. */ 342 | xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); 343 | 344 | /* If a timer has expired, process it. Otherwise, block this task 345 | until either a timer does expire, or a command is received. */ 346 | prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); 347 | 348 | /* Empty the command queue. */ 349 | prvProcessReceivedCommands(); 350 | } 351 | } 352 | /*-----------------------------------------------------------*/ 353 | 354 | static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) 355 | { 356 | portTickType xTimeNow; 357 | portBASE_TYPE xTimerListsWereSwitched; 358 | 359 | vTaskSuspendAll(); 360 | { 361 | /* Obtain the time now to make an assessment as to whether the timer 362 | has expired or not. If obtaining the time causes the lists to switch 363 | then don't process this timer as any timers that remained in the list 364 | when the lists were switched will have been processed within the 365 | prvSampelTimeNow() function. */ 366 | xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); 367 | if( xTimerListsWereSwitched == pdFALSE ) 368 | { 369 | /* The tick count has not overflowed, has the timer expired? */ 370 | if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) 371 | { 372 | xTaskResumeAll(); 373 | prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); 374 | } 375 | else 376 | { 377 | /* The tick count has not overflowed, and the next expire 378 | time has not been reached yet. This task should therefore 379 | block to wait for the next expire time or a command to be 380 | received - whichever comes first. The following line cannot 381 | be reached unless xNextExpireTime > xTimeNow, except in the 382 | case when the current timer list is empty. */ 383 | vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) ); 384 | 385 | if( xTaskResumeAll() == pdFALSE ) 386 | { 387 | /* Yield to wait for either a command to arrive, or the block time 388 | to expire. If a command arrived between the critical section being 389 | exited and this yield then the yield will not cause the task 390 | to block. */ 391 | portYIELD_WITHIN_API(); 392 | } 393 | } 394 | } 395 | else 396 | { 397 | xTaskResumeAll(); 398 | } 399 | } 400 | } 401 | /*-----------------------------------------------------------*/ 402 | 403 | static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) 404 | { 405 | portTickType xNextExpireTime; 406 | 407 | /* Timers are listed in expiry time order, with the head of the list 408 | referencing the task that will expire first. Obtain the time at which 409 | the timer with the nearest expiry time will expire. If there are no 410 | active timers then just set the next expire time to 0. That will cause 411 | this task to unblock when the tick count overflows, at which point the 412 | timer lists will be switched and the next expiry time can be 413 | re-assessed. */ 414 | *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); 415 | if( *pxListWasEmpty == pdFALSE ) 416 | { 417 | xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); 418 | } 419 | else 420 | { 421 | /* Ensure the task unblocks when the tick count rolls over. */ 422 | xNextExpireTime = ( portTickType ) 0U; 423 | } 424 | 425 | return xNextExpireTime; 426 | } 427 | /*-----------------------------------------------------------*/ 428 | 429 | static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) 430 | { 431 | portTickType xTimeNow; 432 | static portTickType xLastTime = ( portTickType ) 0U; 433 | 434 | xTimeNow = xTaskGetTickCount(); 435 | 436 | if( xTimeNow < xLastTime ) 437 | { 438 | prvSwitchTimerLists( xLastTime ); 439 | *pxTimerListsWereSwitched = pdTRUE; 440 | } 441 | else 442 | { 443 | *pxTimerListsWereSwitched = pdFALSE; 444 | } 445 | 446 | xLastTime = xTimeNow; 447 | 448 | return xTimeNow; 449 | } 450 | /*-----------------------------------------------------------*/ 451 | 452 | static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) 453 | { 454 | portBASE_TYPE xProcessTimerNow = pdFALSE; 455 | 456 | listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); 457 | listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); 458 | 459 | if( xNextExpiryTime <= xTimeNow ) 460 | { 461 | /* Has the expiry time elapsed between the command to start/reset a 462 | timer was issued, and the time the command was processed? */ 463 | if( ( ( portTickType ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) 464 | { 465 | /* The time between a command being issued and the command being 466 | processed actually exceeds the timers period. */ 467 | xProcessTimerNow = pdTRUE; 468 | } 469 | else 470 | { 471 | vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); 472 | } 473 | } 474 | else 475 | { 476 | if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) 477 | { 478 | /* If, since the command was issued, the tick count has overflowed 479 | but the expiry time has not, then the timer must have already passed 480 | its expiry time and should be processed immediately. */ 481 | xProcessTimerNow = pdTRUE; 482 | } 483 | else 484 | { 485 | vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); 486 | } 487 | } 488 | 489 | return xProcessTimerNow; 490 | } 491 | /*-----------------------------------------------------------*/ 492 | 493 | static void prvProcessReceivedCommands( void ) 494 | { 495 | xTIMER_MESSAGE xMessage; 496 | xTIMER *pxTimer; 497 | portBASE_TYPE xTimerListsWereSwitched, xResult; 498 | portTickType xTimeNow; 499 | 500 | /* In this case the xTimerListsWereSwitched parameter is not used, but it 501 | must be present in the function call. */ 502 | xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); 503 | 504 | while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) 505 | { 506 | pxTimer = xMessage.pxTimer; 507 | 508 | /* Is the timer already in a list of active timers? When the command 509 | is trmCOMMAND_PROCESS_TIMER_OVERFLOW, the timer will be NULL as the 510 | command is to the task rather than to an individual timer. */ 511 | if( pxTimer != NULL ) 512 | { 513 | if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) 514 | { 515 | /* The timer is in a list, remove it. */ 516 | vListRemove( &( pxTimer->xTimerListItem ) ); 517 | } 518 | } 519 | 520 | traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.xMessageValue ); 521 | 522 | switch( xMessage.xMessageID ) 523 | { 524 | case tmrCOMMAND_START : 525 | /* Start or restart a timer. */ 526 | if( prvInsertTimerInActiveList( pxTimer, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.xMessageValue ) == pdTRUE ) 527 | { 528 | /* The timer expired before it was added to the active timer 529 | list. Process it now. */ 530 | pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); 531 | 532 | if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) 533 | { 534 | xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); 535 | configASSERT( xResult ); 536 | ( void ) xResult; 537 | } 538 | } 539 | break; 540 | 541 | case tmrCOMMAND_STOP : 542 | /* The timer has already been removed from the active list. 543 | There is nothing to do here. */ 544 | break; 545 | 546 | case tmrCOMMAND_CHANGE_PERIOD : 547 | pxTimer->xTimerPeriodInTicks = xMessage.xMessageValue; 548 | configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); 549 | prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); 550 | break; 551 | 552 | case tmrCOMMAND_DELETE : 553 | /* The timer has already been removed from the active list, 554 | just free up the memory. */ 555 | vPortFree( pxTimer ); 556 | break; 557 | 558 | default : 559 | /* Don't expect to get here. */ 560 | break; 561 | } 562 | } 563 | } 564 | /*-----------------------------------------------------------*/ 565 | 566 | static void prvSwitchTimerLists( portTickType xLastTime ) 567 | { 568 | portTickType xNextExpireTime, xReloadTime; 569 | xList *pxTemp; 570 | xTIMER *pxTimer; 571 | portBASE_TYPE xResult; 572 | 573 | /* Remove compiler warnings if configASSERT() is not defined. */ 574 | ( void ) xLastTime; 575 | 576 | /* The tick count has overflowed. The timer lists must be switched. 577 | If there are any timers still referenced from the current timer list 578 | then they must have expired and should be processed before the lists 579 | are switched. */ 580 | while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) 581 | { 582 | xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); 583 | 584 | /* Remove the timer from the list. */ 585 | pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); 586 | vListRemove( &( pxTimer->xTimerListItem ) ); 587 | 588 | /* Execute its callback, then send a command to restart the timer if 589 | it is an auto-reload timer. It cannot be restarted here as the lists 590 | have not yet been switched. */ 591 | pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); 592 | 593 | if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) 594 | { 595 | /* Calculate the reload value, and if the reload value results in 596 | the timer going into the same timer list then it has already expired 597 | and the timer should be re-inserted into the current list so it is 598 | processed again within this loop. Otherwise a command should be sent 599 | to restart the timer to ensure it is only inserted into a list after 600 | the lists have been swapped. */ 601 | xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); 602 | if( xReloadTime > xNextExpireTime ) 603 | { 604 | listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); 605 | listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); 606 | vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); 607 | } 608 | else 609 | { 610 | xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); 611 | configASSERT( xResult ); 612 | ( void ) xResult; 613 | } 614 | } 615 | } 616 | 617 | pxTemp = pxCurrentTimerList; 618 | pxCurrentTimerList = pxOverflowTimerList; 619 | pxOverflowTimerList = pxTemp; 620 | } 621 | /*-----------------------------------------------------------*/ 622 | 623 | static void prvCheckForValidListAndQueue( void ) 624 | { 625 | /* Check that the list from which active timers are referenced, and the 626 | queue used to communicate with the timer service, have been 627 | initialised. */ 628 | taskENTER_CRITICAL(); 629 | { 630 | if( xTimerQueue == NULL ) 631 | { 632 | vListInitialise( &xActiveTimerList1 ); 633 | vListInitialise( &xActiveTimerList2 ); 634 | pxCurrentTimerList = &xActiveTimerList1; 635 | pxOverflowTimerList = &xActiveTimerList2; 636 | xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xTIMER_MESSAGE ) ); 637 | } 638 | } 639 | taskEXIT_CRITICAL(); 640 | } 641 | /*-----------------------------------------------------------*/ 642 | 643 | portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) 644 | { 645 | portBASE_TYPE xTimerIsInActiveList; 646 | xTIMER *pxTimer = ( xTIMER * ) xTimer; 647 | 648 | /* Is the timer in the list of active timers? */ 649 | taskENTER_CRITICAL(); 650 | { 651 | /* Checking to see if it is in the NULL list in effect checks to see if 652 | it is referenced from either the current or the overflow timer lists in 653 | one go, but the logic has to be reversed, hence the '!'. */ 654 | xTimerIsInActiveList = !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); 655 | } 656 | taskEXIT_CRITICAL(); 657 | 658 | return xTimerIsInActiveList; 659 | } 660 | /*-----------------------------------------------------------*/ 661 | 662 | void *pvTimerGetTimerID( xTimerHandle xTimer ) 663 | { 664 | xTIMER *pxTimer = ( xTIMER * ) xTimer; 665 | 666 | return pxTimer->pvTimerID; 667 | } 668 | /*-----------------------------------------------------------*/ 669 | 670 | /* This entire source file will be skipped if the application is not configured 671 | to include software timer functionality. If you want to include software timer 672 | functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ 673 | #endif /* configUSE_TIMERS == 1 */ 674 | --------------------------------------------------------------------------------