FreeRTOS Real Time Operating System, Modified from Kenji Arai's initial port. See freertos.org for full documentation.
Fork of FreeRTOS_on_mbed_v1 by
port.c
00001 /* 00002 FreeRTOS V6.0.3 - Copyright (C) 2010 Real Time Engineers Ltd. 00003 00004 *************************************************************************** 00005 * * 00006 * If you are: * 00007 * * 00008 * + New to FreeRTOS, * 00009 * + Wanting to learn FreeRTOS or multitasking in general quickly * 00010 * + Looking for basic training, * 00011 * + Wanting to improve your FreeRTOS skills and productivity * 00012 * * 00013 * then take a look at the FreeRTOS eBook * 00014 * * 00015 * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * 00016 * http://www.FreeRTOS.org/Documentation * 00017 * * 00018 * A pdf reference manual is also available. Both are usually delivered * 00019 * to your inbox within 20 minutes to two hours when purchased between 8am * 00020 * and 8pm GMT (although please allow up to 24 hours in case of * 00021 * exceptional circumstances). Thank you for your support! * 00022 * * 00023 *************************************************************************** 00024 00025 This file is part of the FreeRTOS distribution. 00026 00027 FreeRTOS is free software; you can redistribute it and/or modify it under 00028 the terms of the GNU General Public License (version 2) as published by the 00029 Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 00030 ***NOTE*** The exception to the GPL is included to allow you to distribute 00031 a combined work that includes FreeRTOS without being obliged to provide the 00032 source code for proprietary components outside of the FreeRTOS kernel. 00033 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT 00034 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00035 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00036 more details. You should have received a copy of the GNU General Public 00037 License and the FreeRTOS license exception along with FreeRTOS; if not it 00038 can be viewed here: http://www.freertos.org/a00114.html and also obtained 00039 by writing to Richard Barry, contact details for whom are available on the 00040 FreeRTOS WEB site. 00041 00042 1 tab == 4 spaces! 00043 00044 http://www.FreeRTOS.org - Documentation, latest information, license and 00045 contact details. 00046 00047 http://www.SafeRTOS.com - A version that is certified for use in safety 00048 critical systems. 00049 00050 http://www.OpenRTOS.com - Commercial support, development, porting, 00051 licensing and training services. 00052 */ 00053 00054 /*----------------------------------------------------------- 00055 * Implementation of functions defined in portable.h for the ARM CM3 port. 00056 *----------------------------------------------------------*/ 00057 00058 // Modified by Kenji Arai / JH1PJL, October 30th,2010 00059 // Some functions go to port_asm.c 00060 00061 /* Scheduler includes. */ 00062 #include "FreeRTOS.h" 00063 #include "task.h" 00064 00065 /* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is 00066 defined. The value should also ensure backward compatibility. 00067 FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ 00068 #ifndef configKERNEL_INTERRUPT_PRIORITY 00069 #define configKERNEL_INTERRUPT_PRIORITY 255 00070 #endif 00071 00072 /* Constants required to manipulate the NVIC. */ 00073 #define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) 00074 #define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) 00075 #define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) 00076 #define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) 00077 #define portNVIC_SYSTICK_CLK 0x00000004 00078 #define portNVIC_SYSTICK_INT 0x00000002 00079 #define portNVIC_SYSTICK_ENABLE 0x00000001 00080 #define portNVIC_PENDSVSET 0x10000000 00081 #define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) 00082 #define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) 00083 00084 /* Constants required to set up the initial stack. */ 00085 #define portINITIAL_XPSR ( 0x01000000 ) 00086 00087 /* The priority used by the kernel is assigned to a variable to make access 00088 from inline assembler easier. */ 00089 //const unsigned long ulKernelPriority = configKERNEL_INTERRUPT_PRIORITY; 00090 00091 /* Each task maintains its own interrupt status in the critical nesting 00092 variable. */ 00093 #if 0 00094 static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; 00095 #else 00096 unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; 00097 #endif 00098 /* 00099 * Setup the timer to generate the tick interrupts. 00100 */ 00101 static void prvSetupTimerInterrupt( void ); 00102 00103 /* 00104 * Exception handlers. 00105 */ 00106 #if 0 00107 void xPortPendSVHandler( void ) __attribute__ (( naked )); 00108 #else 00109 extern void xPortPendSVHandler( void ); 00110 #endif 00111 void xPortSysTickHandler( void ); 00112 #if 0 00113 void vPortSVCHandler( void ) __attribute__ (( naked )); 00114 #else 00115 extern void vPortSVCHandler( void ); 00116 #endif 00117 00118 /* 00119 * Start first task is a separate function so it can be tested in isolation. 00120 */ 00121 #ifdef __cplusplus 00122 extern "C" { 00123 #endif 00124 #if 0 00125 void vPortStartFirstTask( void ) __attribute__ (( naked )); 00126 #else 00127 extern void vPortStartFirstTask( void ); 00128 #endif 00129 #ifdef __cplusplus 00130 } 00131 #endif 00132 /*-----------------------------------------------------------*/ 00133 00134 /* 00135 * See header file for description. 00136 */ 00137 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) 00138 { 00139 /* Simulate the stack frame as it would be created by a context switch 00140 interrupt. */ 00141 pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ 00142 *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ 00143 pxTopOfStack--; 00144 *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ 00145 pxTopOfStack--; 00146 *pxTopOfStack = 0; /* LR */ 00147 pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ 00148 *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ 00149 pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ 00150 00151 return pxTopOfStack; 00152 } 00153 /*-----------------------------------------------------------*/ 00154 00155 #if 0 00156 void vPortSVCHandler( void ) 00157 { 00158 __asm volatile ( 00159 " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ 00160 " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ 00161 " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ 00162 " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ 00163 " msr psp, r0 \n" /* Restore the task stack pointer. */ 00164 " mov r0, #0 \n" 00165 " msr basepri, r0 \n" 00166 " orr r14, #0xd \n" 00167 " bx r14 \n" 00168 " \n" 00169 " .align 2 \n" 00170 "pxCurrentTCBConst2: .word pxCurrentTCB \n" 00171 ); 00172 } 00173 /*-----------------------------------------------------------*/ 00174 #endif 00175 00176 #if 0 00177 void vPortStartFirstTask( void ) 00178 { 00179 __asm volatile( 00180 " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ 00181 " ldr r0, [r0] \n" 00182 " ldr r0, [r0] \n" 00183 " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ 00184 " svc 0 \n" /* System call to start first task. */ 00185 ); 00186 } 00187 /*-----------------------------------------------------------*/ 00188 #endif 00189 00190 /* 00191 * See header file for description. 00192 */ 00193 portBASE_TYPE xPortStartScheduler( void ) 00194 { 00195 /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ 00196 *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; 00197 *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; 00198 00199 /* Start the timer that generates the tick ISR. Interrupts are disabled 00200 here already. */ 00201 prvSetupTimerInterrupt(); 00202 00203 /* Initialise the critical nesting count ready for the first task. */ 00204 uxCriticalNesting = 0; 00205 00206 /* Start the first task. */ 00207 vPortStartFirstTask(); 00208 00209 /* Should not get here! */ 00210 return 0; 00211 } 00212 /*-----------------------------------------------------------*/ 00213 00214 void vPortEndScheduler( void ) 00215 { 00216 /* It is unlikely that the CM3 port will require this function as there 00217 is nothing to return to. */ 00218 } 00219 /*-----------------------------------------------------------*/ 00220 00221 void vPortYieldFromISR( void ) 00222 { 00223 /* Set a PendSV to request a context switch. */ 00224 *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; 00225 } 00226 /*-----------------------------------------------------------*/ 00227 00228 #if 0 00229 void vPortEnterCritical( void ) 00230 { 00231 portDISABLE_INTERRUPTS(); 00232 uxCriticalNesting++; 00233 } 00234 /*-----------------------------------------------------------*/ 00235 00236 void vPortExitCritical( void ) 00237 { 00238 uxCriticalNesting--; 00239 if( uxCriticalNesting == 0 ) 00240 { 00241 portENABLE_INTERRUPTS(); 00242 } 00243 } 00244 /*-----------------------------------------------------------*/ 00245 00246 00247 void xPortPendSVHandler( void ) 00248 { 00249 /* This is a naked function. */ 00250 00251 __asm volatile 00252 ( 00253 " mrs r0, psp \n" 00254 " \n" 00255 " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ 00256 " ldr r2, [r3] \n" 00257 " \n" 00258 " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ 00259 " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ 00260 " \n" 00261 " stmdb sp!, {r3, r14} \n" 00262 " mov r0, %0 \n" 00263 " msr basepri, r0 \n" 00264 " bl vTaskSwitchContext \n" 00265 " mov r0, #0 \n" 00266 " msr basepri, r0 \n" 00267 " ldmia sp!, {r3, r14} \n" 00268 " \n" /* Restore the context, including the critical nesting count. */ 00269 " ldr r1, [r3] \n" 00270 " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ 00271 " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ 00272 " msr psp, r0 \n" 00273 " bx r14 \n" 00274 " \n" 00275 " .align 2 \n" 00276 "pxCurrentTCBConst: .word pxCurrentTCB \n" 00277 ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) 00278 ); 00279 } 00280 /*-----------------------------------------------------------*/ 00281 00282 void xPortSysTickHandler( void ) 00283 { 00284 unsigned long ulDummy; 00285 00286 /* If using preemption, also force a context switch. */ 00287 #if configUSE_PREEMPTION == 1 00288 *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; 00289 #endif 00290 00291 // Modified by Kenji Arai / JH1PJL, October 30th,2010 00292 ulDummy = 0; 00293 portSET_INTERRUPT_MASK_FROM_ISR(); 00294 { 00295 vTaskIncrementTick(); 00296 } 00297 portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); 00298 } 00299 /*-----------------------------------------------------------*/ 00300 #endif 00301 00302 /* 00303 * Setup the systick timer to generate the tick interrupts at the required 00304 * frequency. 00305 */ 00306 void prvSetupTimerInterrupt( void ) 00307 { 00308 /* Configure SysTick to interrupt at the requested rate. */ 00309 *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 00310 *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; 00311 } 00312 /*-----------------------------------------------------------*/ 00313
Generated on Fri Jul 15 2022 10:21:25 by
1.7.2
