www.freertos.org

Dependents:   mbed_freeRTOS_send

Fork of FreeRTOS by Rohit Grover

Committer:
ser1516
Date:
Wed May 18 21:25:21 2016 +0000
Revision:
1:6db425da9b9e
Parent:
0:8e57f3e9cc89
queue implementada com accelarometro e pot a enviar para o can -  ainda nao testado

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 0:8e57f3e9cc89 1 /*
rgrover1 0:8e57f3e9cc89 2 FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
rgrover1 0:8e57f3e9cc89 3 All rights reserved
rgrover1 0:8e57f3e9cc89 4
rgrover1 0:8e57f3e9cc89 5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
rgrover1 0:8e57f3e9cc89 6
rgrover1 0:8e57f3e9cc89 7 ***************************************************************************
rgrover1 0:8e57f3e9cc89 8 * *
rgrover1 0:8e57f3e9cc89 9 * FreeRTOS provides completely free yet professionally developed, *
rgrover1 0:8e57f3e9cc89 10 * robust, strictly quality controlled, supported, and cross *
rgrover1 0:8e57f3e9cc89 11 * platform software that has become a de facto standard. *
rgrover1 0:8e57f3e9cc89 12 * *
rgrover1 0:8e57f3e9cc89 13 * Help yourself get started quickly and support the FreeRTOS *
rgrover1 0:8e57f3e9cc89 14 * project by purchasing a FreeRTOS tutorial book, reference *
rgrover1 0:8e57f3e9cc89 15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
rgrover1 0:8e57f3e9cc89 16 * *
rgrover1 0:8e57f3e9cc89 17 * Thank you! *
rgrover1 0:8e57f3e9cc89 18 * *
rgrover1 0:8e57f3e9cc89 19 ***************************************************************************
rgrover1 0:8e57f3e9cc89 20
rgrover1 0:8e57f3e9cc89 21 This file is part of the FreeRTOS distribution.
rgrover1 0:8e57f3e9cc89 22
rgrover1 0:8e57f3e9cc89 23 FreeRTOS is free software; you can redistribute it and/or modify it under
rgrover1 0:8e57f3e9cc89 24 the terms of the GNU General Public License (version 2) as published by the
rgrover1 0:8e57f3e9cc89 25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
rgrover1 0:8e57f3e9cc89 26
rgrover1 0:8e57f3e9cc89 27 >>! NOTE: The modification to the GPL is included to allow you to distribute
rgrover1 0:8e57f3e9cc89 28 >>! a combined work that includes FreeRTOS without being obliged to provide
rgrover1 0:8e57f3e9cc89 29 >>! the source code for proprietary components outside of the FreeRTOS
rgrover1 0:8e57f3e9cc89 30 >>! kernel.
rgrover1 0:8e57f3e9cc89 31
rgrover1 0:8e57f3e9cc89 32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
rgrover1 0:8e57f3e9cc89 33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
rgrover1 0:8e57f3e9cc89 34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
rgrover1 0:8e57f3e9cc89 35 link: http://www.freertos.org/a00114.html
rgrover1 0:8e57f3e9cc89 36
rgrover1 0:8e57f3e9cc89 37 1 tab == 4 spaces!
rgrover1 0:8e57f3e9cc89 38
rgrover1 0:8e57f3e9cc89 39 ***************************************************************************
rgrover1 0:8e57f3e9cc89 40 * *
rgrover1 0:8e57f3e9cc89 41 * Having a problem? Start by reading the FAQ "My application does *
rgrover1 0:8e57f3e9cc89 42 * not run, what could be wrong?" *
rgrover1 0:8e57f3e9cc89 43 * *
rgrover1 0:8e57f3e9cc89 44 * http://www.FreeRTOS.org/FAQHelp.html *
rgrover1 0:8e57f3e9cc89 45 * *
rgrover1 0:8e57f3e9cc89 46 ***************************************************************************
rgrover1 0:8e57f3e9cc89 47
rgrover1 0:8e57f3e9cc89 48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
rgrover1 0:8e57f3e9cc89 49 license and Real Time Engineers Ltd. contact details.
rgrover1 0:8e57f3e9cc89 50
rgrover1 0:8e57f3e9cc89 51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
rgrover1 0:8e57f3e9cc89 52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
rgrover1 0:8e57f3e9cc89 53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
rgrover1 0:8e57f3e9cc89 54
rgrover1 0:8e57f3e9cc89 55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
rgrover1 0:8e57f3e9cc89 56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
rgrover1 0:8e57f3e9cc89 57 licenses offer ticketed support, indemnification and middleware.
rgrover1 0:8e57f3e9cc89 58
rgrover1 0:8e57f3e9cc89 59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
rgrover1 0:8e57f3e9cc89 60 engineered and independently SIL3 certified version for use in safety and
rgrover1 0:8e57f3e9cc89 61 mission critical applications that require provable dependability.
rgrover1 0:8e57f3e9cc89 62
rgrover1 0:8e57f3e9cc89 63 1 tab == 4 spaces!
rgrover1 0:8e57f3e9cc89 64 */
rgrover1 0:8e57f3e9cc89 65
rgrover1 0:8e57f3e9cc89 66 /*-----------------------------------------------------------
rgrover1 0:8e57f3e9cc89 67 * Implementation of functions defined in portable.h for the ARM CM3 port.
rgrover1 0:8e57f3e9cc89 68 *----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 69
rgrover1 0:8e57f3e9cc89 70 /* Scheduler includes. */
rgrover1 0:8e57f3e9cc89 71 #include "FreeRTOS.h"
rgrover1 0:8e57f3e9cc89 72 #include "task.h"
rgrover1 0:8e57f3e9cc89 73
rgrover1 0:8e57f3e9cc89 74 #ifndef configKERNEL_INTERRUPT_PRIORITY
rgrover1 0:8e57f3e9cc89 75 #define configKERNEL_INTERRUPT_PRIORITY 255
rgrover1 0:8e57f3e9cc89 76 #endif
rgrover1 0:8e57f3e9cc89 77
rgrover1 0:8e57f3e9cc89 78 #if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
rgrover1 0:8e57f3e9cc89 79 #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
rgrover1 0:8e57f3e9cc89 80 #endif
rgrover1 0:8e57f3e9cc89 81
rgrover1 0:8e57f3e9cc89 82 #ifndef configSYSTICK_CLOCK_HZ
rgrover1 0:8e57f3e9cc89 83 #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
rgrover1 0:8e57f3e9cc89 84 #endif
rgrover1 0:8e57f3e9cc89 85
rgrover1 0:8e57f3e9cc89 86 /* The __weak attribute does not work as you might expect with the Keil tools
rgrover1 0:8e57f3e9cc89 87 so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if
rgrover1 0:8e57f3e9cc89 88 the application writer wants to provide their own implementation of
rgrover1 0:8e57f3e9cc89 89 vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION
rgrover1 0:8e57f3e9cc89 90 is defined. */
rgrover1 0:8e57f3e9cc89 91 #ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
rgrover1 0:8e57f3e9cc89 92 #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
rgrover1 0:8e57f3e9cc89 93 #endif
rgrover1 0:8e57f3e9cc89 94
rgrover1 0:8e57f3e9cc89 95 /* Constants required to manipulate the core. Registers first... */
rgrover1 0:8e57f3e9cc89 96 #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
rgrover1 0:8e57f3e9cc89 97 #define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
rgrover1 0:8e57f3e9cc89 98 #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
rgrover1 0:8e57f3e9cc89 99 #define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
rgrover1 0:8e57f3e9cc89 100 /* ...then bits in the registers. */
rgrover1 0:8e57f3e9cc89 101 #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
rgrover1 0:8e57f3e9cc89 102 #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
rgrover1 0:8e57f3e9cc89 103 #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
rgrover1 0:8e57f3e9cc89 104 #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
rgrover1 0:8e57f3e9cc89 105 #define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
rgrover1 0:8e57f3e9cc89 106 #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
rgrover1 0:8e57f3e9cc89 107
rgrover1 0:8e57f3e9cc89 108 #define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
rgrover1 0:8e57f3e9cc89 109 #define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
rgrover1 0:8e57f3e9cc89 110
rgrover1 0:8e57f3e9cc89 111 /* Constants required to check the validity of an interrupt priority. */
rgrover1 0:8e57f3e9cc89 112 #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
rgrover1 0:8e57f3e9cc89 113 #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
rgrover1 0:8e57f3e9cc89 114 #define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
rgrover1 0:8e57f3e9cc89 115 #define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff )
rgrover1 0:8e57f3e9cc89 116 #define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 )
rgrover1 0:8e57f3e9cc89 117 #define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 )
rgrover1 0:8e57f3e9cc89 118 #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
rgrover1 0:8e57f3e9cc89 119 #define portPRIGROUP_SHIFT ( 8UL )
rgrover1 0:8e57f3e9cc89 120
rgrover1 0:8e57f3e9cc89 121 /* Constants required to set up the initial stack. */
rgrover1 0:8e57f3e9cc89 122 #define portINITIAL_XPSR ( 0x01000000 )
rgrover1 0:8e57f3e9cc89 123
rgrover1 0:8e57f3e9cc89 124 /* Constants used with memory barrier intrinsics. */
rgrover1 0:8e57f3e9cc89 125 #define portSY_FULL_READ_WRITE ( 15 )
rgrover1 0:8e57f3e9cc89 126
rgrover1 0:8e57f3e9cc89 127 /* The systick is a 24-bit counter. */
rgrover1 0:8e57f3e9cc89 128 #define portMAX_24_BIT_NUMBER ( 0xffffffUL )
rgrover1 0:8e57f3e9cc89 129
rgrover1 0:8e57f3e9cc89 130 /* A fiddle factor to estimate the number of SysTick counts that would have
rgrover1 0:8e57f3e9cc89 131 occurred while the SysTick counter is stopped during tickless idle
rgrover1 0:8e57f3e9cc89 132 calculations. */
rgrover1 0:8e57f3e9cc89 133 #define portMISSED_COUNTS_FACTOR ( 45UL )
rgrover1 0:8e57f3e9cc89 134
rgrover1 0:8e57f3e9cc89 135 /* Each task maintains its own interrupt status in the critical nesting
rgrover1 0:8e57f3e9cc89 136 variable. */
rgrover1 0:8e57f3e9cc89 137 static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
rgrover1 0:8e57f3e9cc89 138
rgrover1 0:8e57f3e9cc89 139 /*
rgrover1 0:8e57f3e9cc89 140 * Setup the timer to generate the tick interrupts. The implementation in this
rgrover1 0:8e57f3e9cc89 141 * file is weak to allow application writers to change the timer used to
rgrover1 0:8e57f3e9cc89 142 * generate the tick interrupt.
rgrover1 0:8e57f3e9cc89 143 */
rgrover1 0:8e57f3e9cc89 144 void vPortSetupTimerInterrupt( void );
rgrover1 0:8e57f3e9cc89 145
rgrover1 0:8e57f3e9cc89 146 /*
rgrover1 0:8e57f3e9cc89 147 * Exception handlers.
rgrover1 0:8e57f3e9cc89 148 */
rgrover1 0:8e57f3e9cc89 149 void xPortPendSVHandler( void );
rgrover1 0:8e57f3e9cc89 150 void xPortSysTickHandler( void );
rgrover1 0:8e57f3e9cc89 151 void vPortSVCHandler( void );
rgrover1 0:8e57f3e9cc89 152
rgrover1 0:8e57f3e9cc89 153 /*
rgrover1 0:8e57f3e9cc89 154 * Start first task is a separate function so it can be tested in isolation.
rgrover1 0:8e57f3e9cc89 155 */
rgrover1 0:8e57f3e9cc89 156 static void prvStartFirstTask( void );
rgrover1 0:8e57f3e9cc89 157
rgrover1 0:8e57f3e9cc89 158 /*
rgrover1 0:8e57f3e9cc89 159 * Used to catch tasks that attempt to return from their implementing function.
rgrover1 0:8e57f3e9cc89 160 */
rgrover1 0:8e57f3e9cc89 161 static void prvTaskExitError( void );
rgrover1 0:8e57f3e9cc89 162
rgrover1 0:8e57f3e9cc89 163 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 164
rgrover1 0:8e57f3e9cc89 165 /*
rgrover1 0:8e57f3e9cc89 166 * The number of SysTick increments that make up one tick period.
rgrover1 0:8e57f3e9cc89 167 */
rgrover1 0:8e57f3e9cc89 168 #if configUSE_TICKLESS_IDLE == 1
rgrover1 0:8e57f3e9cc89 169 static unsigned long ulTimerCountsForOneTick = 0;
rgrover1 0:8e57f3e9cc89 170 #endif /* configUSE_TICKLESS_IDLE */
rgrover1 0:8e57f3e9cc89 171
rgrover1 0:8e57f3e9cc89 172 /*
rgrover1 0:8e57f3e9cc89 173 * The maximum number of tick periods that can be suppressed is limited by the
rgrover1 0:8e57f3e9cc89 174 * 24 bit resolution of the SysTick timer.
rgrover1 0:8e57f3e9cc89 175 */
rgrover1 0:8e57f3e9cc89 176 #if configUSE_TICKLESS_IDLE == 1
rgrover1 0:8e57f3e9cc89 177 static unsigned long xMaximumPossibleSuppressedTicks = 0;
rgrover1 0:8e57f3e9cc89 178 #endif /* configUSE_TICKLESS_IDLE */
rgrover1 0:8e57f3e9cc89 179
rgrover1 0:8e57f3e9cc89 180 /*
rgrover1 0:8e57f3e9cc89 181 * Compensate for the CPU cycles that pass while the SysTick is stopped (low
rgrover1 0:8e57f3e9cc89 182 * power functionality only.
rgrover1 0:8e57f3e9cc89 183 */
rgrover1 0:8e57f3e9cc89 184 #if configUSE_TICKLESS_IDLE == 1
rgrover1 0:8e57f3e9cc89 185 static unsigned long ulStoppedTimerCompensation = 0;
rgrover1 0:8e57f3e9cc89 186 #endif /* configUSE_TICKLESS_IDLE */
rgrover1 0:8e57f3e9cc89 187
rgrover1 0:8e57f3e9cc89 188 /*
rgrover1 0:8e57f3e9cc89 189 * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
rgrover1 0:8e57f3e9cc89 190 * FreeRTOS API functions are not called from interrupts that have been assigned
rgrover1 0:8e57f3e9cc89 191 * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
rgrover1 0:8e57f3e9cc89 192 */
rgrover1 0:8e57f3e9cc89 193 #if ( configASSERT_DEFINED == 1 )
rgrover1 0:8e57f3e9cc89 194 static unsigned char ucMaxSysCallPriority = 0;
rgrover1 0:8e57f3e9cc89 195 static unsigned long ulMaxPRIGROUPValue = 0;
rgrover1 0:8e57f3e9cc89 196 static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16;
rgrover1 0:8e57f3e9cc89 197 #endif /* configASSERT_DEFINED */
rgrover1 0:8e57f3e9cc89 198
rgrover1 0:8e57f3e9cc89 199 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 200
rgrover1 0:8e57f3e9cc89 201 /*
rgrover1 0:8e57f3e9cc89 202 * See header file for description.
rgrover1 0:8e57f3e9cc89 203 */
rgrover1 0:8e57f3e9cc89 204 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
rgrover1 0:8e57f3e9cc89 205 {
rgrover1 0:8e57f3e9cc89 206 /* Simulate the stack frame as it would be created by a context switch
rgrover1 0:8e57f3e9cc89 207 interrupt. */
rgrover1 0:8e57f3e9cc89 208 pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
rgrover1 0:8e57f3e9cc89 209 *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
rgrover1 0:8e57f3e9cc89 210 pxTopOfStack--;
rgrover1 0:8e57f3e9cc89 211 *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
rgrover1 0:8e57f3e9cc89 212 pxTopOfStack--;
rgrover1 0:8e57f3e9cc89 213 *pxTopOfStack = ( portSTACK_TYPE ) prvTaskExitError; /* LR */
rgrover1 0:8e57f3e9cc89 214
rgrover1 0:8e57f3e9cc89 215 pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
rgrover1 0:8e57f3e9cc89 216 *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
rgrover1 0:8e57f3e9cc89 217 pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
rgrover1 0:8e57f3e9cc89 218
rgrover1 0:8e57f3e9cc89 219 return pxTopOfStack;
rgrover1 0:8e57f3e9cc89 220 }
rgrover1 0:8e57f3e9cc89 221 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 222
rgrover1 0:8e57f3e9cc89 223 static void prvTaskExitError( void )
rgrover1 0:8e57f3e9cc89 224 {
rgrover1 0:8e57f3e9cc89 225 /* A function that implements a task must not exit or attempt to return to
rgrover1 0:8e57f3e9cc89 226 its caller as there is nothing to return to. If a task wants to exit it
rgrover1 0:8e57f3e9cc89 227 should instead call vTaskDelete( NULL ).
rgrover1 0:8e57f3e9cc89 228
rgrover1 0:8e57f3e9cc89 229 Artificially force an assert() to be triggered if configASSERT() is
rgrover1 0:8e57f3e9cc89 230 defined, then stop here so application writers can catch the error. */
rgrover1 0:8e57f3e9cc89 231 configASSERT( uxCriticalNesting == ~0UL );
rgrover1 0:8e57f3e9cc89 232 portDISABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 233 for( ;; );
rgrover1 0:8e57f3e9cc89 234 }
rgrover1 0:8e57f3e9cc89 235 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 236
rgrover1 0:8e57f3e9cc89 237 __asm void vPortSVCHandler( void )
rgrover1 0:8e57f3e9cc89 238 {
rgrover1 0:8e57f3e9cc89 239 PRESERVE8
rgrover1 0:8e57f3e9cc89 240
rgrover1 0:8e57f3e9cc89 241 ldr r3, =pxCurrentTCB /* Restore the context. */
rgrover1 0:8e57f3e9cc89 242 ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
rgrover1 0:8e57f3e9cc89 243 ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
rgrover1 0:8e57f3e9cc89 244 ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
rgrover1 0:8e57f3e9cc89 245 msr psp, r0 /* Restore the task stack pointer. */
rgrover1 0:8e57f3e9cc89 246 mov r0, #0
rgrover1 0:8e57f3e9cc89 247 msr basepri, r0
rgrover1 0:8e57f3e9cc89 248 orr r14, #0xd
rgrover1 0:8e57f3e9cc89 249 bx r14
rgrover1 0:8e57f3e9cc89 250 }
rgrover1 0:8e57f3e9cc89 251 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 252
rgrover1 0:8e57f3e9cc89 253 __asm void prvStartFirstTask( void )
rgrover1 0:8e57f3e9cc89 254 {
rgrover1 0:8e57f3e9cc89 255 PRESERVE8
rgrover1 0:8e57f3e9cc89 256
rgrover1 0:8e57f3e9cc89 257 /* Use the NVIC offset register to locate the stack. */
rgrover1 0:8e57f3e9cc89 258 ldr r0, =0xE000ED08
rgrover1 0:8e57f3e9cc89 259 ldr r0, [r0]
rgrover1 0:8e57f3e9cc89 260 ldr r0, [r0]
rgrover1 0:8e57f3e9cc89 261 /* Set the msp back to the start of the stack. */
rgrover1 0:8e57f3e9cc89 262 msr msp, r0
rgrover1 0:8e57f3e9cc89 263 /* Globally enable interrupts. */
rgrover1 0:8e57f3e9cc89 264 cpsie i
rgrover1 0:8e57f3e9cc89 265 /* Call SVC to start the first task. */
rgrover1 0:8e57f3e9cc89 266 svc 0
rgrover1 0:8e57f3e9cc89 267 nop
rgrover1 0:8e57f3e9cc89 268 }
rgrover1 0:8e57f3e9cc89 269 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 270
rgrover1 0:8e57f3e9cc89 271 /*
rgrover1 0:8e57f3e9cc89 272 * See header file for description.
rgrover1 0:8e57f3e9cc89 273 */
rgrover1 0:8e57f3e9cc89 274 portBASE_TYPE xPortStartScheduler( void )
rgrover1 0:8e57f3e9cc89 275 {
rgrover1 0:8e57f3e9cc89 276 #if( configASSERT_DEFINED == 1 )
rgrover1 0:8e57f3e9cc89 277 {
rgrover1 0:8e57f3e9cc89 278 volatile unsigned long ulOriginalPriority;
rgrover1 0:8e57f3e9cc89 279 volatile char * const pcFirstUserPriorityRegister = ( char * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
rgrover1 0:8e57f3e9cc89 280 volatile unsigned char ucMaxPriorityValue;
rgrover1 0:8e57f3e9cc89 281
rgrover1 0:8e57f3e9cc89 282 /* Determine the maximum priority from which ISR safe FreeRTOS API
rgrover1 0:8e57f3e9cc89 283 functions can be called. ISR safe functions are those that end in
rgrover1 0:8e57f3e9cc89 284 "FromISR". FreeRTOS maintains separate thread and ISR API functions to
rgrover1 0:8e57f3e9cc89 285 ensure interrupt entry is as fast and simple as possible.
rgrover1 0:8e57f3e9cc89 286
rgrover1 0:8e57f3e9cc89 287 Save the interrupt priority value that is about to be clobbered. */
rgrover1 0:8e57f3e9cc89 288 ulOriginalPriority = *pcFirstUserPriorityRegister;
rgrover1 0:8e57f3e9cc89 289
rgrover1 0:8e57f3e9cc89 290 /* Determine the number of priority bits available. First write to all
rgrover1 0:8e57f3e9cc89 291 possible bits. */
rgrover1 0:8e57f3e9cc89 292 *pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
rgrover1 0:8e57f3e9cc89 293
rgrover1 0:8e57f3e9cc89 294 /* Read the value back to see how many bits stuck. */
rgrover1 0:8e57f3e9cc89 295 ucMaxPriorityValue = *pcFirstUserPriorityRegister;
rgrover1 0:8e57f3e9cc89 296
rgrover1 0:8e57f3e9cc89 297 /* Use the same mask on the maximum system call priority. */
rgrover1 0:8e57f3e9cc89 298 ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
rgrover1 0:8e57f3e9cc89 299
rgrover1 0:8e57f3e9cc89 300 /* Calculate the maximum acceptable priority group value for the number
rgrover1 0:8e57f3e9cc89 301 of bits read back. */
rgrover1 0:8e57f3e9cc89 302 ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
rgrover1 0:8e57f3e9cc89 303 while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
rgrover1 0:8e57f3e9cc89 304 {
rgrover1 0:8e57f3e9cc89 305 ulMaxPRIGROUPValue--;
rgrover1 0:8e57f3e9cc89 306 ucMaxPriorityValue <<= ( unsigned char ) 0x01;
rgrover1 0:8e57f3e9cc89 307 }
rgrover1 0:8e57f3e9cc89 308
rgrover1 0:8e57f3e9cc89 309 /* Shift the priority group value back to its position within the AIRCR
rgrover1 0:8e57f3e9cc89 310 register. */
rgrover1 0:8e57f3e9cc89 311 ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
rgrover1 0:8e57f3e9cc89 312 ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
rgrover1 0:8e57f3e9cc89 313
rgrover1 0:8e57f3e9cc89 314 /* Restore the clobbered interrupt priority register to its original
rgrover1 0:8e57f3e9cc89 315 value. */
rgrover1 0:8e57f3e9cc89 316 *pcFirstUserPriorityRegister = ulOriginalPriority;
rgrover1 0:8e57f3e9cc89 317 }
rgrover1 0:8e57f3e9cc89 318 #endif /* conifgASSERT_DEFINED */
rgrover1 0:8e57f3e9cc89 319
rgrover1 0:8e57f3e9cc89 320 /* Make PendSV and SysTick the lowest priority interrupts. */
rgrover1 0:8e57f3e9cc89 321 portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
rgrover1 0:8e57f3e9cc89 322 portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
rgrover1 0:8e57f3e9cc89 323
rgrover1 0:8e57f3e9cc89 324 /* Start the timer that generates the tick ISR. Interrupts are disabled
rgrover1 0:8e57f3e9cc89 325 here already. */
rgrover1 0:8e57f3e9cc89 326 vPortSetupTimerInterrupt();
rgrover1 0:8e57f3e9cc89 327
rgrover1 0:8e57f3e9cc89 328 /* Initialise the critical nesting count ready for the first task. */
rgrover1 0:8e57f3e9cc89 329 uxCriticalNesting = 0;
rgrover1 0:8e57f3e9cc89 330
rgrover1 0:8e57f3e9cc89 331 /* Start the first task. */
rgrover1 0:8e57f3e9cc89 332 prvStartFirstTask();
rgrover1 0:8e57f3e9cc89 333
rgrover1 0:8e57f3e9cc89 334 /* Should not get here! */
rgrover1 0:8e57f3e9cc89 335 return 0;
rgrover1 0:8e57f3e9cc89 336 }
rgrover1 0:8e57f3e9cc89 337 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 338
rgrover1 0:8e57f3e9cc89 339 void vPortEndScheduler( void )
rgrover1 0:8e57f3e9cc89 340 {
rgrover1 0:8e57f3e9cc89 341 /* It is unlikely that the CM3 port will require this function as there
rgrover1 0:8e57f3e9cc89 342 is nothing to return to. */
rgrover1 0:8e57f3e9cc89 343 }
rgrover1 0:8e57f3e9cc89 344 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 345
rgrover1 0:8e57f3e9cc89 346 void vPortYield( void )
rgrover1 0:8e57f3e9cc89 347 {
rgrover1 0:8e57f3e9cc89 348 /* Set a PendSV to request a context switch. */
rgrover1 0:8e57f3e9cc89 349 portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
rgrover1 0:8e57f3e9cc89 350
rgrover1 0:8e57f3e9cc89 351 /* Barriers are normally not required but do ensure the code is completely
rgrover1 0:8e57f3e9cc89 352 within the specified behaviour for the architecture. */
rgrover1 0:8e57f3e9cc89 353 __dsb( portSY_FULL_READ_WRITE );
rgrover1 0:8e57f3e9cc89 354 __isb( portSY_FULL_READ_WRITE );
rgrover1 0:8e57f3e9cc89 355 }
rgrover1 0:8e57f3e9cc89 356 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 357
rgrover1 0:8e57f3e9cc89 358 void vPortEnterCritical( void )
rgrover1 0:8e57f3e9cc89 359 {
rgrover1 0:8e57f3e9cc89 360 portDISABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 361 uxCriticalNesting++;
rgrover1 0:8e57f3e9cc89 362 __dsb( portSY_FULL_READ_WRITE );
rgrover1 0:8e57f3e9cc89 363 __isb( portSY_FULL_READ_WRITE );
rgrover1 0:8e57f3e9cc89 364 }
rgrover1 0:8e57f3e9cc89 365 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 366
rgrover1 0:8e57f3e9cc89 367 void vPortExitCritical( void )
rgrover1 0:8e57f3e9cc89 368 {
rgrover1 0:8e57f3e9cc89 369 uxCriticalNesting--;
rgrover1 0:8e57f3e9cc89 370 if( uxCriticalNesting == 0 )
rgrover1 0:8e57f3e9cc89 371 {
rgrover1 0:8e57f3e9cc89 372 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 373 }
rgrover1 0:8e57f3e9cc89 374 }
rgrover1 0:8e57f3e9cc89 375 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 376
rgrover1 0:8e57f3e9cc89 377 __asm void xPortPendSVHandler( void )
rgrover1 0:8e57f3e9cc89 378 {
rgrover1 0:8e57f3e9cc89 379 extern uxCriticalNesting;
rgrover1 0:8e57f3e9cc89 380 extern pxCurrentTCB;
rgrover1 0:8e57f3e9cc89 381 extern vTaskSwitchContext;
rgrover1 0:8e57f3e9cc89 382
rgrover1 0:8e57f3e9cc89 383 PRESERVE8
rgrover1 0:8e57f3e9cc89 384
rgrover1 0:8e57f3e9cc89 385 mrs r0, psp
rgrover1 0:8e57f3e9cc89 386
rgrover1 0:8e57f3e9cc89 387 ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
rgrover1 0:8e57f3e9cc89 388 ldr r2, [r3]
rgrover1 0:8e57f3e9cc89 389
rgrover1 0:8e57f3e9cc89 390 stmdb r0!, {r4-r11} /* Save the remaining registers. */
rgrover1 0:8e57f3e9cc89 391 str r0, [r2] /* Save the new top of stack into the first member of the TCB. */
rgrover1 0:8e57f3e9cc89 392
rgrover1 0:8e57f3e9cc89 393 stmdb sp!, {r3, r14}
rgrover1 0:8e57f3e9cc89 394 mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
rgrover1 0:8e57f3e9cc89 395 msr basepri, r0
rgrover1 0:8e57f3e9cc89 396 bl vTaskSwitchContext
rgrover1 0:8e57f3e9cc89 397 mov r0, #0
rgrover1 0:8e57f3e9cc89 398 msr basepri, r0
rgrover1 0:8e57f3e9cc89 399 ldmia sp!, {r3, r14}
rgrover1 0:8e57f3e9cc89 400
rgrover1 0:8e57f3e9cc89 401 ldr r1, [r3]
rgrover1 0:8e57f3e9cc89 402 ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
rgrover1 0:8e57f3e9cc89 403 ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */
rgrover1 0:8e57f3e9cc89 404 msr psp, r0
rgrover1 0:8e57f3e9cc89 405 bx r14
rgrover1 0:8e57f3e9cc89 406 nop
rgrover1 0:8e57f3e9cc89 407 }
rgrover1 0:8e57f3e9cc89 408 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 409
rgrover1 0:8e57f3e9cc89 410 void xPortSysTickHandler( void )
rgrover1 0:8e57f3e9cc89 411 {
rgrover1 0:8e57f3e9cc89 412 /* The SysTick runs at the lowest interrupt priority, so when this interrupt
rgrover1 0:8e57f3e9cc89 413 executes all interrupts must be unmasked. There is therefore no need to
rgrover1 0:8e57f3e9cc89 414 save and then restore the interrupt mask value as its value is already
rgrover1 0:8e57f3e9cc89 415 known. */
rgrover1 0:8e57f3e9cc89 416 ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
rgrover1 0:8e57f3e9cc89 417 {
rgrover1 0:8e57f3e9cc89 418 /* Increment the RTOS tick. */
rgrover1 0:8e57f3e9cc89 419 if( xTaskIncrementTick() != pdFALSE )
rgrover1 0:8e57f3e9cc89 420 {
rgrover1 0:8e57f3e9cc89 421 /* A context switch is required. Context switching is performed in
rgrover1 0:8e57f3e9cc89 422 the PendSV interrupt. Pend the PendSV interrupt. */
rgrover1 0:8e57f3e9cc89 423 portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
rgrover1 0:8e57f3e9cc89 424 }
rgrover1 0:8e57f3e9cc89 425 }
rgrover1 0:8e57f3e9cc89 426 portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
rgrover1 0:8e57f3e9cc89 427 }
rgrover1 0:8e57f3e9cc89 428 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 429
rgrover1 0:8e57f3e9cc89 430 #if configUSE_TICKLESS_IDLE == 1
rgrover1 0:8e57f3e9cc89 431
rgrover1 0:8e57f3e9cc89 432 __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
rgrover1 0:8e57f3e9cc89 433 {
rgrover1 0:8e57f3e9cc89 434 unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
rgrover1 0:8e57f3e9cc89 435 portTickType xModifiableIdleTime;
rgrover1 0:8e57f3e9cc89 436
rgrover1 0:8e57f3e9cc89 437 /* Make sure the SysTick reload value does not overflow the counter. */
rgrover1 0:8e57f3e9cc89 438 if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
rgrover1 0:8e57f3e9cc89 439 {
rgrover1 0:8e57f3e9cc89 440 xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
rgrover1 0:8e57f3e9cc89 441 }
rgrover1 0:8e57f3e9cc89 442
rgrover1 0:8e57f3e9cc89 443 /* Stop the SysTick momentarily. The time the SysTick is stopped for
rgrover1 0:8e57f3e9cc89 444 is accounted for as best it can be, but using the tickless mode will
rgrover1 0:8e57f3e9cc89 445 inevitably result in some tiny drift of the time maintained by the
rgrover1 0:8e57f3e9cc89 446 kernel with respect to calendar time. */
rgrover1 0:8e57f3e9cc89 447 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
rgrover1 0:8e57f3e9cc89 448
rgrover1 0:8e57f3e9cc89 449 /* Calculate the reload value required to wait xExpectedIdleTime
rgrover1 0:8e57f3e9cc89 450 tick periods. -1 is used because this code will execute part way
rgrover1 0:8e57f3e9cc89 451 through one of the tick periods. */
rgrover1 0:8e57f3e9cc89 452 ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
rgrover1 0:8e57f3e9cc89 453 if( ulReloadValue > ulStoppedTimerCompensation )
rgrover1 0:8e57f3e9cc89 454 {
rgrover1 0:8e57f3e9cc89 455 ulReloadValue -= ulStoppedTimerCompensation;
rgrover1 0:8e57f3e9cc89 456 }
rgrover1 0:8e57f3e9cc89 457
rgrover1 0:8e57f3e9cc89 458 /* Enter a critical section but don't use the taskENTER_CRITICAL()
rgrover1 0:8e57f3e9cc89 459 method as that will mask interrupts that should exit sleep mode. */
rgrover1 0:8e57f3e9cc89 460 __disable_irq();
rgrover1 0:8e57f3e9cc89 461
rgrover1 0:8e57f3e9cc89 462 /* If a context switch is pending or a task is waiting for the scheduler
rgrover1 0:8e57f3e9cc89 463 to be unsuspended then abandon the low power entry. */
rgrover1 0:8e57f3e9cc89 464 if( eTaskConfirmSleepModeStatus() == eAbortSleep )
rgrover1 0:8e57f3e9cc89 465 {
rgrover1 0:8e57f3e9cc89 466 /* Restart from whatever is left in the count register to complete
rgrover1 0:8e57f3e9cc89 467 this tick period. */
rgrover1 0:8e57f3e9cc89 468 portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
rgrover1 0:8e57f3e9cc89 469
rgrover1 0:8e57f3e9cc89 470 /* Restart SysTick. */
rgrover1 0:8e57f3e9cc89 471 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
rgrover1 0:8e57f3e9cc89 472
rgrover1 0:8e57f3e9cc89 473 /* Reset the reload register to the value required for normal tick
rgrover1 0:8e57f3e9cc89 474 periods. */
rgrover1 0:8e57f3e9cc89 475 portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
rgrover1 0:8e57f3e9cc89 476
rgrover1 0:8e57f3e9cc89 477 /* Re-enable interrupts - see comments above __disable_irq() call
rgrover1 0:8e57f3e9cc89 478 above. */
rgrover1 0:8e57f3e9cc89 479 __enable_irq();
rgrover1 0:8e57f3e9cc89 480 }
rgrover1 0:8e57f3e9cc89 481 else
rgrover1 0:8e57f3e9cc89 482 {
rgrover1 0:8e57f3e9cc89 483 /* Set the new reload value. */
rgrover1 0:8e57f3e9cc89 484 portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
rgrover1 0:8e57f3e9cc89 485
rgrover1 0:8e57f3e9cc89 486 /* Clear the SysTick count flag and set the count value back to
rgrover1 0:8e57f3e9cc89 487 zero. */
rgrover1 0:8e57f3e9cc89 488 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
rgrover1 0:8e57f3e9cc89 489
rgrover1 0:8e57f3e9cc89 490 /* Restart SysTick. */
rgrover1 0:8e57f3e9cc89 491 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
rgrover1 0:8e57f3e9cc89 492
rgrover1 0:8e57f3e9cc89 493 /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
rgrover1 0:8e57f3e9cc89 494 set its parameter to 0 to indicate that its implementation contains
rgrover1 0:8e57f3e9cc89 495 its own wait for interrupt or wait for event instruction, and so wfi
rgrover1 0:8e57f3e9cc89 496 should not be executed again. However, the original expected idle
rgrover1 0:8e57f3e9cc89 497 time variable must remain unmodified, so a copy is taken. */
rgrover1 0:8e57f3e9cc89 498 xModifiableIdleTime = xExpectedIdleTime;
rgrover1 0:8e57f3e9cc89 499 configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
rgrover1 0:8e57f3e9cc89 500 if( xModifiableIdleTime > 0 )
rgrover1 0:8e57f3e9cc89 501 {
rgrover1 0:8e57f3e9cc89 502 __dsb( portSY_FULL_READ_WRITE );
rgrover1 0:8e57f3e9cc89 503 __wfi();
rgrover1 0:8e57f3e9cc89 504 __isb( portSY_FULL_READ_WRITE );
rgrover1 0:8e57f3e9cc89 505 }
rgrover1 0:8e57f3e9cc89 506 configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
rgrover1 0:8e57f3e9cc89 507
rgrover1 0:8e57f3e9cc89 508 /* Stop SysTick. Again, the time the SysTick is stopped for is
rgrover1 0:8e57f3e9cc89 509 accounted for as best it can be, but using the tickless mode will
rgrover1 0:8e57f3e9cc89 510 inevitably result in some tiny drift of the time maintained by the
rgrover1 0:8e57f3e9cc89 511 kernel with respect to calendar time. */
rgrover1 0:8e57f3e9cc89 512 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
rgrover1 0:8e57f3e9cc89 513
rgrover1 0:8e57f3e9cc89 514 /* Re-enable interrupts - see comments above __disable_irq() call
rgrover1 0:8e57f3e9cc89 515 above. */
rgrover1 0:8e57f3e9cc89 516 __enable_irq();
rgrover1 0:8e57f3e9cc89 517
rgrover1 0:8e57f3e9cc89 518 if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
rgrover1 0:8e57f3e9cc89 519 {
rgrover1 0:8e57f3e9cc89 520 unsigned long ulCalculatedLoadValue;
rgrover1 0:8e57f3e9cc89 521
rgrover1 0:8e57f3e9cc89 522 /* The tick interrupt has already executed, and the SysTick
rgrover1 0:8e57f3e9cc89 523 count reloaded with ulReloadValue. Reset the
rgrover1 0:8e57f3e9cc89 524 portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
rgrover1 0:8e57f3e9cc89 525 period. */
rgrover1 0:8e57f3e9cc89 526 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
rgrover1 0:8e57f3e9cc89 527
rgrover1 0:8e57f3e9cc89 528 /* Don't allow a tiny value, or values that have somehow
rgrover1 0:8e57f3e9cc89 529 underflowed because the post sleep hook did something
rgrover1 0:8e57f3e9cc89 530 that took too long. */
rgrover1 0:8e57f3e9cc89 531 if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
rgrover1 0:8e57f3e9cc89 532 {
rgrover1 0:8e57f3e9cc89 533 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
rgrover1 0:8e57f3e9cc89 534 }
rgrover1 0:8e57f3e9cc89 535
rgrover1 0:8e57f3e9cc89 536 portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
rgrover1 0:8e57f3e9cc89 537
rgrover1 0:8e57f3e9cc89 538 /* The tick interrupt handler will already have pended the tick
rgrover1 0:8e57f3e9cc89 539 processing in the kernel. As the pending tick will be
rgrover1 0:8e57f3e9cc89 540 processed as soon as this function exits, the tick value
rgrover1 0:8e57f3e9cc89 541 maintained by the tick is stepped forward by one less than the
rgrover1 0:8e57f3e9cc89 542 time spent waiting. */
rgrover1 0:8e57f3e9cc89 543 ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
rgrover1 0:8e57f3e9cc89 544 }
rgrover1 0:8e57f3e9cc89 545 else
rgrover1 0:8e57f3e9cc89 546 {
rgrover1 0:8e57f3e9cc89 547 /* Something other than the tick interrupt ended the sleep.
rgrover1 0:8e57f3e9cc89 548 Work out how long the sleep lasted rounded to complete tick
rgrover1 0:8e57f3e9cc89 549 periods (not the ulReload value which accounted for part
rgrover1 0:8e57f3e9cc89 550 ticks). */
rgrover1 0:8e57f3e9cc89 551 ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
rgrover1 0:8e57f3e9cc89 552
rgrover1 0:8e57f3e9cc89 553 /* How many complete tick periods passed while the processor
rgrover1 0:8e57f3e9cc89 554 was waiting? */
rgrover1 0:8e57f3e9cc89 555 ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
rgrover1 0:8e57f3e9cc89 556
rgrover1 0:8e57f3e9cc89 557 /* The reload value is set to whatever fraction of a single tick
rgrover1 0:8e57f3e9cc89 558 period remains. */
rgrover1 0:8e57f3e9cc89 559 portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
rgrover1 0:8e57f3e9cc89 560 }
rgrover1 0:8e57f3e9cc89 561
rgrover1 0:8e57f3e9cc89 562 /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
rgrover1 0:8e57f3e9cc89 563 again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
rgrover1 0:8e57f3e9cc89 564 value. The critical section is used to ensure the tick interrupt
rgrover1 0:8e57f3e9cc89 565 can only execute once in the case that the reload register is near
rgrover1 0:8e57f3e9cc89 566 zero. */
rgrover1 0:8e57f3e9cc89 567 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
rgrover1 0:8e57f3e9cc89 568 portENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 569 {
rgrover1 0:8e57f3e9cc89 570 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
rgrover1 0:8e57f3e9cc89 571 vTaskStepTick( ulCompleteTickPeriods );
rgrover1 0:8e57f3e9cc89 572 portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
rgrover1 0:8e57f3e9cc89 573 }
rgrover1 0:8e57f3e9cc89 574 portEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 575 }
rgrover1 0:8e57f3e9cc89 576 }
rgrover1 0:8e57f3e9cc89 577
rgrover1 0:8e57f3e9cc89 578 #endif /* #if configUSE_TICKLESS_IDLE */
rgrover1 0:8e57f3e9cc89 579
rgrover1 0:8e57f3e9cc89 580 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 581
rgrover1 0:8e57f3e9cc89 582 /*
rgrover1 0:8e57f3e9cc89 583 * Setup the SysTick timer to generate the tick interrupts at the required
rgrover1 0:8e57f3e9cc89 584 * frequency.
rgrover1 0:8e57f3e9cc89 585 */
rgrover1 0:8e57f3e9cc89 586 #if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0
rgrover1 0:8e57f3e9cc89 587
rgrover1 0:8e57f3e9cc89 588 void vPortSetupTimerInterrupt( void )
rgrover1 0:8e57f3e9cc89 589 {
rgrover1 0:8e57f3e9cc89 590 /* Calculate the constants required to configure the tick interrupt. */
rgrover1 0:8e57f3e9cc89 591 #if configUSE_TICKLESS_IDLE == 1
rgrover1 0:8e57f3e9cc89 592 {
rgrover1 0:8e57f3e9cc89 593 ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
rgrover1 0:8e57f3e9cc89 594 xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
rgrover1 0:8e57f3e9cc89 595 ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
rgrover1 0:8e57f3e9cc89 596 }
rgrover1 0:8e57f3e9cc89 597 #endif /* configUSE_TICKLESS_IDLE */
rgrover1 0:8e57f3e9cc89 598
rgrover1 0:8e57f3e9cc89 599 /* Configure SysTick to interrupt at the requested rate. */
rgrover1 0:8e57f3e9cc89 600 portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;;
rgrover1 0:8e57f3e9cc89 601 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
rgrover1 0:8e57f3e9cc89 602 }
rgrover1 0:8e57f3e9cc89 603
rgrover1 0:8e57f3e9cc89 604 #endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
rgrover1 0:8e57f3e9cc89 605 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 606
rgrover1 0:8e57f3e9cc89 607 __asm unsigned long ulPortSetInterruptMask( void )
rgrover1 0:8e57f3e9cc89 608 {
rgrover1 0:8e57f3e9cc89 609 PRESERVE8
rgrover1 0:8e57f3e9cc89 610
rgrover1 0:8e57f3e9cc89 611 mrs r0, basepri
rgrover1 0:8e57f3e9cc89 612 mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
rgrover1 0:8e57f3e9cc89 613 msr basepri, r1
rgrover1 0:8e57f3e9cc89 614 bx r14
rgrover1 0:8e57f3e9cc89 615 }
rgrover1 0:8e57f3e9cc89 616 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 617
rgrover1 0:8e57f3e9cc89 618 __asm void vPortClearInterruptMask( unsigned long ulNewMask )
rgrover1 0:8e57f3e9cc89 619 {
rgrover1 0:8e57f3e9cc89 620 PRESERVE8
rgrover1 0:8e57f3e9cc89 621
rgrover1 0:8e57f3e9cc89 622 msr basepri, r0
rgrover1 0:8e57f3e9cc89 623 bx r14
rgrover1 0:8e57f3e9cc89 624 }
rgrover1 0:8e57f3e9cc89 625 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 626
rgrover1 0:8e57f3e9cc89 627 __asm unsigned long vPortGetIPSR( void )
rgrover1 0:8e57f3e9cc89 628 {
rgrover1 0:8e57f3e9cc89 629 PRESERVE8
rgrover1 0:8e57f3e9cc89 630
rgrover1 0:8e57f3e9cc89 631 mrs r0, ipsr
rgrover1 0:8e57f3e9cc89 632 bx r14
rgrover1 0:8e57f3e9cc89 633 }
rgrover1 0:8e57f3e9cc89 634 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 635
rgrover1 0:8e57f3e9cc89 636 #if( configASSERT_DEFINED == 1 )
rgrover1 0:8e57f3e9cc89 637
rgrover1 0:8e57f3e9cc89 638 void vPortValidateInterruptPriority( void )
rgrover1 0:8e57f3e9cc89 639 {
rgrover1 0:8e57f3e9cc89 640 unsigned long ulCurrentInterrupt;
rgrover1 0:8e57f3e9cc89 641 unsigned char ucCurrentPriority;
rgrover1 0:8e57f3e9cc89 642
rgrover1 0:8e57f3e9cc89 643 /* Obtain the number of the currently executing interrupt. */
rgrover1 0:8e57f3e9cc89 644 ulCurrentInterrupt = vPortGetIPSR();
rgrover1 0:8e57f3e9cc89 645
rgrover1 0:8e57f3e9cc89 646 /* Is the interrupt number a user defined interrupt? */
rgrover1 0:8e57f3e9cc89 647 if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
rgrover1 0:8e57f3e9cc89 648 {
rgrover1 0:8e57f3e9cc89 649 /* Look up the interrupt's priority. */
rgrover1 0:8e57f3e9cc89 650 ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
rgrover1 0:8e57f3e9cc89 651
rgrover1 0:8e57f3e9cc89 652 /* The following assertion will fail if a service routine (ISR) for
rgrover1 0:8e57f3e9cc89 653 an interrupt that has been assigned a priority above
rgrover1 0:8e57f3e9cc89 654 configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
rgrover1 0:8e57f3e9cc89 655 function. ISR safe FreeRTOS API functions must *only* be called
rgrover1 0:8e57f3e9cc89 656 from interrupts that have been assigned a priority at or below
rgrover1 0:8e57f3e9cc89 657 configMAX_SYSCALL_INTERRUPT_PRIORITY.
rgrover1 0:8e57f3e9cc89 658
rgrover1 0:8e57f3e9cc89 659 Numerically low interrupt priority numbers represent logically high
rgrover1 0:8e57f3e9cc89 660 interrupt priorities, therefore the priority of the interrupt must
rgrover1 0:8e57f3e9cc89 661 be set to a value equal to or numerically *higher* than
rgrover1 0:8e57f3e9cc89 662 configMAX_SYSCALL_INTERRUPT_PRIORITY.
rgrover1 0:8e57f3e9cc89 663
rgrover1 0:8e57f3e9cc89 664 Interrupts that use the FreeRTOS API must not be left at their
rgrover1 0:8e57f3e9cc89 665 default priority of zero as that is the highest possible priority,
rgrover1 0:8e57f3e9cc89 666 which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
rgrover1 0:8e57f3e9cc89 667 and therefore also guaranteed to be invalid.
rgrover1 0:8e57f3e9cc89 668
rgrover1 0:8e57f3e9cc89 669 FreeRTOS maintains separate thread and ISR API functions to ensure
rgrover1 0:8e57f3e9cc89 670 interrupt entry is as fast and simple as possible.
rgrover1 0:8e57f3e9cc89 671
rgrover1 0:8e57f3e9cc89 672 The following links provide detailed information:
rgrover1 0:8e57f3e9cc89 673 http://www.freertos.org/RTOS-Cortex-M3-M4.html
rgrover1 0:8e57f3e9cc89 674 http://www.freertos.org/FAQHelp.html */
rgrover1 0:8e57f3e9cc89 675 configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
rgrover1 0:8e57f3e9cc89 676 }
rgrover1 0:8e57f3e9cc89 677
rgrover1 0:8e57f3e9cc89 678 /* Priority grouping: The interrupt controller (NVIC) allows the bits
rgrover1 0:8e57f3e9cc89 679 that define each interrupt's priority to be split between bits that
rgrover1 0:8e57f3e9cc89 680 define the interrupt's pre-emption priority bits and bits that define
rgrover1 0:8e57f3e9cc89 681 the interrupt's sub-priority. For simplicity all bits must be defined
rgrover1 0:8e57f3e9cc89 682 to be pre-emption priority bits. The following assertion will fail if
rgrover1 0:8e57f3e9cc89 683 this is not the case (if some bits represent a sub-priority).
rgrover1 0:8e57f3e9cc89 684
rgrover1 0:8e57f3e9cc89 685 If the application only uses CMSIS libraries for interrupt
rgrover1 0:8e57f3e9cc89 686 configuration then the correct setting can be achieved on all Cortex-M
rgrover1 0:8e57f3e9cc89 687 devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
rgrover1 0:8e57f3e9cc89 688 scheduler. Note however that some vendor specific peripheral libraries
rgrover1 0:8e57f3e9cc89 689 assume a non-zero priority group setting, in which cases using a value
rgrover1 0:8e57f3e9cc89 690 of zero will result in unpredicable behaviour. */
rgrover1 0:8e57f3e9cc89 691 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
rgrover1 0:8e57f3e9cc89 692 }
rgrover1 0:8e57f3e9cc89 693
rgrover1 0:8e57f3e9cc89 694 #endif /* configASSERT_DEFINED */
rgrover1 0:8e57f3e9cc89 695
rgrover1 0:8e57f3e9cc89 696