2 * FreeRTOS Kernel V10.0.0
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software. If you wish to use our Amazon
\r
14 * FreeRTOS name, please do so in a fair use way that does not cause confusion.
\r
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
18 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
19 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * http://www.FreeRTOS.org
\r
24 * http://aws.amazon.com/freertos
\r
26 * 1 tab == 4 spaces!
\r
29 /* Standard includes. */
\r
32 /* Scheduler includes. */
\r
33 #include "FreeRTOS.h"
\r
36 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
\r
37 /* Check the configuration. */
\r
38 #if( configMAX_PRIORITIES > 32 )
\r
39 #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
\r
41 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
43 #if( configISR_STACK_SIZE < ( configMINIMAL_STACK_SIZE * 2 ) )
\r
44 #warning configISR_STACK_SIZE is probably too small!
\r
45 #endif /* ( configISR_STACK_SIZE < configMINIMAL_STACK_SIZE * 2 ) */
\r
47 #if( ( configMAX_API_CALL_INTERRUPT_PRIORITY > portMAX_PRIORITY ) || ( configMAX_API_CALL_INTERRUPT_PRIORITY < 2 ) )
\r
48 #error configMAX_API_CALL_INTERRUPT_PRIORITY must be between 2 and 15
\r
51 #if( ( configSUPPORT_FPU == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
\r
52 #error configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 to use this port with an FPU
\r
55 /* A critical section is exited when the critical section nesting count reaches
\r
57 #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
\r
59 /* Tasks are not created with a floating point context, but can be given a
\r
60 floating point context after they have been created. A variable is stored as
\r
61 part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
\r
62 does not have an FPU context, or any other value if the task does have an FPU
\r
64 #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
\r
66 /* Only the IF bit is set so tasks start with interrupts enabled. */
\r
67 #define portINITIAL_EFLAGS ( 0x200UL )
\r
69 /* Error interrupts are at the highest priority vectors. */
\r
70 #define portAPIC_LVT_ERROR_VECTOR ( 0xfe )
\r
71 #define portAPIC_SPURIOUS_INT_VECTOR ( 0xff )
\r
74 #define portEFLAGS_IF ( 0x200UL )
\r
76 /* FPU context size if FSAVE is used. */
\r
77 #define portFPU_CONTEXT_SIZE_BYTES 108
\r
79 /* The expected size of each entry in the IDT. Used to check structure packing
\r
80 is set correctly. */
\r
81 #define portEXPECTED_IDT_ENTRY_SIZE 8
\r
83 /* Default flags setting for entries in the IDT. */
\r
84 #define portIDT_FLAGS ( 0x8E )
\r
86 /* This is the lowest possible ISR vector available to application code. */
\r
87 #define portAPIC_MIN_ALLOWABLE_VECTOR ( 0x20 )
\r
89 /* If configASSERT() is defined then the system stack is filled with this value
\r
90 to allow for a crude stack overflow check. */
\r
91 #define portSTACK_WORD ( 0xecececec )
\r
92 /*-----------------------------------------------------------*/
\r
95 * Starts the first task executing.
\r
97 extern void vPortStartFirstTask( void );
\r
100 * Used to catch tasks that attempt to return from their implementing function.
\r
102 static void prvTaskExitError( void );
\r
105 * Complete one descriptor in the IDT.
\r
107 static void prvSetInterruptGate( uint8_t ucNumber, ISR_Handler_t pxHandlerFunction, uint8_t ucFlags );
\r
110 * The default handler installed in each IDT position.
\r
112 extern void vPortCentralInterruptWrapper( void );
\r
115 * Handler for portYIELD().
\r
117 extern void vPortYieldCall( void );
\r
120 * Configure the APIC to generate the RTOS tick.
\r
122 static void prvSetupTimerInterrupt( void );
\r
125 * Tick interrupt handler.
\r
127 extern void vPortTimerHandler( void );
\r
130 * Check an interrupt vector is not too high, too low, in use by FreeRTOS, or
\r
131 * already in use by the application.
\r
133 static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber );
\r
135 /*-----------------------------------------------------------*/
\r
137 /* A variable is used to keep track of the critical section nesting. This
\r
138 variable must be initialised to a non zero value to ensure interrupts don't
\r
139 inadvertently become unmasked before the scheduler starts. It is set to zero
\r
140 before the first task starts executing. */
\r
141 volatile uint32_t ulCriticalNesting = 9999UL;
\r
143 /* A structure used to map the various fields of an IDT entry into separate
\r
144 structure members. */
\r
147 uint16_t usISRLow; /* Low 16 bits of handler address. */
\r
148 uint16_t usSegmentSelector; /* Flat model means this is not changed. */
\r
149 uint8_t ucZero; /* Must be set to zero. */
\r
150 uint8_t ucFlags; /* Flags for this entry. */
\r
151 uint16_t usISRHigh; /* High 16 bits of handler address. */
\r
152 } __attribute__( ( packed ) );
\r
153 typedef struct IDTEntry IDTEntry_t;
\r
156 /* Use to pass the location of the IDT to the CPU. */
\r
159 uint16_t usTableLimit;
\r
160 uint32_t ulTableBase; /* The address of the first entry in xInterruptDescriptorTable. */
\r
161 } __attribute__( ( __packed__ ) );
\r
162 typedef struct IDTPointer IDTPointer_t;
\r
164 /* The IDT itself. */
\r
165 static __attribute__ ( ( aligned( 32 ) ) ) IDTEntry_t xInterruptDescriptorTable[ portNUM_VECTORS ];
\r
167 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
169 /* A table in which application defined interrupt handlers are stored. These
\r
170 are called by the central interrupt handler if a common interrupt entry
\r
172 static ISR_Handler_t xInterruptHandlerTable[ portNUM_VECTORS ] = { NULL };
\r
174 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
176 #if ( configSUPPORT_FPU == 1 )
\r
178 /* Saved as part of the task context. If pucPortTaskFPUContextBuffer is NULL
\r
179 then the task does not have an FPU context. If pucPortTaskFPUContextBuffer is
\r
180 not NULL then it points to a buffer into which the FPU context can be saved. */
\r
181 uint8_t *pucPortTaskFPUContextBuffer __attribute__((used)) = pdFALSE;
\r
183 #endif /* configSUPPORT_FPU */
\r
185 /* The stack used by interrupt handlers. */
\r
186 static uint32_t ulSystemStack[ configISR_STACK_SIZE ] __attribute__((used)) = { 0 };
\r
188 /* Don't use the very top of the system stack so the return address
\r
189 appears as 0 if the debugger tries to unwind the stack. */
\r
190 volatile uint32_t ulTopOfSystemStack __attribute__((used)) = ( uint32_t ) &( ulSystemStack[ configISR_STACK_SIZE - 5 ] );
\r
192 /* If a yield is requested from an interrupt or from a critical section then
\r
193 the yield is not performed immediately, and ulPortYieldPending is set to pdTRUE
\r
194 instead to indicate the yield should be performed at the end of the interrupt
\r
195 when the critical section is exited. */
\r
196 volatile uint32_t ulPortYieldPending __attribute__((used)) = pdFALSE;
\r
198 /* Counts the interrupt nesting depth. Used to know when to switch to the
\r
199 interrupt/system stack and when to save/restore a complete context. */
\r
200 volatile uint32_t ulInterruptNesting __attribute__((used)) = 0;
\r
202 /*-----------------------------------------------------------*/
\r
205 * See header file for description.
\r
207 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
\r
209 uint32_t ulCodeSegment;
\r
211 /* Setup the initial stack as expected by the portFREERTOS_INTERRUPT_EXIT macro. */
\r
213 *pxTopOfStack = 0x00;
\r
215 *pxTopOfStack = 0x00;
\r
218 /* Parameters first. */
\r
219 *pxTopOfStack = ( StackType_t ) pvParameters;
\r
222 /* There is nothing to return to so assert if attempting to use the return
\r
224 *pxTopOfStack = ( StackType_t ) prvTaskExitError;
\r
227 /* iret used to start the task pops up to here. */
\r
228 *pxTopOfStack = portINITIAL_EFLAGS;
\r
232 __asm volatile( "movl %%cs, %0" : "=r" ( ulCodeSegment ) );
\r
233 *pxTopOfStack = ulCodeSegment;
\r
236 /* First instruction in the task. */
\r
237 *pxTopOfStack = ( StackType_t ) pxCode;
\r
240 /* General purpose registers as expected by a POPA instruction. */
\r
241 *pxTopOfStack = 0xEA;
\r
244 *pxTopOfStack = 0xEC;
\r
247 *pxTopOfStack = 0xED1; /* EDX */
\r
250 *pxTopOfStack = 0xEB1; /* EBX */
\r
253 /* Hole for ESP. */
\r
256 *pxTopOfStack = 0x00; /* EBP */
\r
259 *pxTopOfStack = 0xE5; /* ESI */
\r
262 *pxTopOfStack = 0xeeeeeeee; /* EDI */
\r
264 #if ( configSUPPORT_FPU == 1 )
\r
268 /* Buffer for FPU context, which is initialised to NULL as tasks are not
\r
269 created with an FPU context. */
\r
270 *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
\r
272 #endif /* configSUPPORT_FPU */
\r
274 return pxTopOfStack;
\r
276 /*-----------------------------------------------------------*/
\r
278 static void prvSetInterruptGate( uint8_t ucNumber, ISR_Handler_t pxHandlerFunction, uint8_t ucFlags )
\r
280 uint16_t usCodeSegment;
\r
281 uint32_t ulBase = ( uint32_t ) pxHandlerFunction;
\r
283 xInterruptDescriptorTable[ ucNumber ].usISRLow = ( uint16_t ) ( ulBase & USHRT_MAX );
\r
284 xInterruptDescriptorTable[ ucNumber ].usISRHigh = ( uint16_t ) ( ( ulBase >> 16UL ) & USHRT_MAX );
\r
286 /* When the flat model is used the CS will never change. */
\r
287 __asm volatile( "mov %%cs, %0" : "=r" ( usCodeSegment ) );
\r
288 xInterruptDescriptorTable[ ucNumber ].usSegmentSelector = usCodeSegment;
\r
289 xInterruptDescriptorTable[ ucNumber ].ucZero = 0;
\r
290 xInterruptDescriptorTable[ ucNumber ].ucFlags = ucFlags;
\r
292 /*-----------------------------------------------------------*/
\r
294 void vPortSetupIDT( void )
\r
299 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
301 for( ulNum = 0; ulNum < portNUM_VECTORS; ulNum++ )
\r
303 /* If a handler has not already been installed on this vector. */
\r
304 if( ( xInterruptDescriptorTable[ ulNum ].usISRLow == 0x00 ) && ( xInterruptDescriptorTable[ ulNum ].usISRHigh == 0x00 ) )
\r
306 prvSetInterruptGate( ( uint8_t ) ulNum, vPortCentralInterruptWrapper, portIDT_FLAGS );
\r
310 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
312 /* Set IDT address. */
\r
313 xIDT.ulTableBase = ( uint32_t ) xInterruptDescriptorTable;
\r
314 xIDT.usTableLimit = sizeof( xInterruptDescriptorTable ) - 1;
\r
316 /* Set IDT in CPU. */
\r
317 __asm volatile( "lidt %0" :: "m" (xIDT) );
\r
319 /*-----------------------------------------------------------*/
\r
321 static void prvTaskExitError( void )
\r
323 /* A function that implements a task must not exit or attempt to return to
\r
324 its caller as there is nothing to return to. If a task wants to exit it
\r
325 should instead call vTaskDelete( NULL ).
\r
327 Artificially force an assert() to be triggered if configASSERT() is
\r
328 defined, then stop here so application writers can catch the error. */
\r
329 configASSERT( ulCriticalNesting == ~0UL );
\r
330 portDISABLE_INTERRUPTS();
\r
333 /*-----------------------------------------------------------*/
\r
335 static void prvSetupTimerInterrupt( void )
\r
337 extern void vPortAPICErrorHandlerWrapper( void );
\r
338 extern void vPortAPICSpuriousHandler( void );
\r
340 /* Initialise LAPIC to a well known state. */
\r
341 portAPIC_LDR = 0xFFFFFFFF;
\r
342 portAPIC_LDR = ( ( portAPIC_LDR & 0x00FFFFFF ) | 0x00000001 );
\r
343 portAPIC_LVT_TIMER = portAPIC_DISABLE;
\r
344 portAPIC_LVT_PERF = portAPIC_NMI;
\r
345 portAPIC_LVT_LINT0 = portAPIC_DISABLE;
\r
346 portAPIC_LVT_LINT1 = portAPIC_DISABLE;
\r
347 portAPIC_TASK_PRIORITY = 0;
\r
349 /* Install APIC timer ISR vector. */
\r
350 prvSetInterruptGate( ( uint8_t ) portAPIC_TIMER_INT_VECTOR, vPortTimerHandler, portIDT_FLAGS );
\r
352 /* Install API error handler. */
\r
353 prvSetInterruptGate( ( uint8_t ) portAPIC_LVT_ERROR_VECTOR, vPortAPICErrorHandlerWrapper, portIDT_FLAGS );
\r
355 /* Install Yield handler. */
\r
356 prvSetInterruptGate( ( uint8_t ) portAPIC_YIELD_INT_VECTOR, vPortYieldCall, portIDT_FLAGS );
\r
358 /* Install spurious interrupt vector. */
\r
359 prvSetInterruptGate( ( uint8_t ) portAPIC_SPURIOUS_INT_VECTOR, vPortAPICSpuriousHandler, portIDT_FLAGS );
\r
361 /* Enable the APIC, mapping the spurious interrupt at the same time. */
\r
362 portAPIC_SPURIOUS_INT = portAPIC_SPURIOUS_INT_VECTOR | portAPIC_ENABLE_BIT;
\r
364 /* Set timer error vector. */
\r
365 portAPIC_LVT_ERROR = portAPIC_LVT_ERROR_VECTOR;
\r
367 /* Set the interrupt frequency. */
\r
368 portAPIC_TMRDIV = portAPIC_DIV_16;
\r
369 portAPIC_TIMER_INITIAL_COUNT = ( ( configCPU_CLOCK_HZ >> 4UL ) / configTICK_RATE_HZ ) - 1UL;
\r
371 /*-----------------------------------------------------------*/
\r
373 BaseType_t xPortStartScheduler( void )
\r
377 /* Some versions of GCC require the -mno-ms-bitfields command line option
\r
378 for packing to work. */
\r
379 configASSERT( sizeof( struct IDTEntry ) == portEXPECTED_IDT_ENTRY_SIZE );
\r
381 /* Fill part of the system stack with a known value to help detect stack
\r
382 overflow. A few zeros are left so GDB doesn't get confused unwinding
\r
384 for( xWord = 0; xWord < configISR_STACK_SIZE - 20; xWord++ )
\r
386 ulSystemStack[ xWord ] = portSTACK_WORD;
\r
389 /* Initialise Interrupt Descriptor Table (IDT). */
\r
392 /* Initialise LAPIC and install system handlers. */
\r
393 prvSetupTimerInterrupt();
\r
395 /* Make sure the stack used by interrupts is aligned. */
\r
396 ulTopOfSystemStack &= ~portBYTE_ALIGNMENT_MASK;
\r
398 ulCriticalNesting = 0;
\r
400 /* Enable LAPIC Counter.*/
\r
401 portAPIC_LVT_TIMER = portAPIC_TIMER_PERIODIC | portAPIC_TIMER_INT_VECTOR;
\r
403 /* Sometimes needed. */
\r
404 portAPIC_TMRDIV = portAPIC_DIV_16;
\r
406 /* Should not return from the following function as the scheduler will then
\r
407 be executing the tasks. */
\r
408 vPortStartFirstTask();
\r
412 /*-----------------------------------------------------------*/
\r
414 void vPortEndScheduler( void )
\r
416 /* Not implemented in ports where there is nothing to return to.
\r
417 Artificially force an assert. */
\r
418 configASSERT( ulCriticalNesting == 1000UL );
\r
420 /*-----------------------------------------------------------*/
\r
422 void vPortEnterCritical( void )
\r
424 if( ulCriticalNesting == 0 )
\r
426 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
428 __asm volatile( "cli" );
\r
432 portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
\r
433 configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
\r
438 /* Now interrupts are disabled ulCriticalNesting can be accessed
\r
439 directly. Increment ulCriticalNesting to keep a count of how many times
\r
440 portENTER_CRITICAL() has been called. */
\r
441 ulCriticalNesting++;
\r
443 /*-----------------------------------------------------------*/
\r
445 void vPortExitCritical( void )
\r
447 if( ulCriticalNesting > portNO_CRITICAL_NESTING )
\r
449 /* Decrement the nesting count as the critical section is being
\r
451 ulCriticalNesting--;
\r
453 /* If the nesting level has reached zero then all interrupt
\r
454 priorities must be re-enabled. */
\r
455 if( ulCriticalNesting == portNO_CRITICAL_NESTING )
\r
457 /* Critical nesting has reached zero so all interrupt priorities
\r
458 should be unmasked. */
\r
459 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
461 __asm volatile( "sti" );
\r
465 portAPIC_TASK_PRIORITY = 0;
\r
469 /* If a yield was pended from within the critical section then
\r
470 perform the yield now. */
\r
471 if( ulPortYieldPending != pdFALSE )
\r
473 ulPortYieldPending = pdFALSE;
\r
474 __asm volatile( portYIELD_INTERRUPT );
\r
479 /*-----------------------------------------------------------*/
\r
481 uint32_t ulPortSetInterruptMask( void )
\r
483 volatile uint32_t ulOriginalMask;
\r
485 /* Set mask to max syscall priority. */
\r
486 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
488 /* Return whether interrupts were already enabled or not. Pop adjusts
\r
489 the stack first. */
\r
490 __asm volatile( "pushf \t\n"
\r
493 : "=rm" (ulOriginalMask) :: "memory" );
\r
495 ulOriginalMask &= portEFLAGS_IF;
\r
499 /* Return original mask. */
\r
500 ulOriginalMask = portAPIC_TASK_PRIORITY;
\r
501 portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
\r
502 configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
\r
506 return ulOriginalMask;
\r
508 /*-----------------------------------------------------------*/
\r
510 void vPortClearInterruptMask( uint32_t ulNewMaskValue )
\r
512 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
514 if( ulNewMaskValue != pdFALSE )
\r
516 __asm volatile( "sti" );
\r
521 portAPIC_TASK_PRIORITY = ulNewMaskValue;
\r
522 configASSERT( portAPIC_TASK_PRIORITY == ulNewMaskValue );
\r
526 /*-----------------------------------------------------------*/
\r
528 #if ( configSUPPORT_FPU == 1 )
\r
530 void vPortTaskUsesFPU( void )
\r
532 /* A task is registering the fact that it needs an FPU context. Allocate a
\r
533 buffer into which the context can be saved. */
\r
534 pucPortTaskFPUContextBuffer = ( uint8_t * ) pvPortMalloc( portFPU_CONTEXT_SIZE_BYTES );
\r
535 configASSERT( pucPortTaskFPUContextBuffer );
\r
537 /* Initialise the floating point registers. */
\r
538 __asm volatile( "fninit" );
\r
541 #endif /* configSUPPORT_FPU */
\r
542 /*-----------------------------------------------------------*/
\r
544 void vPortAPICErrorHandler( void )
\r
546 /* Variable to hold the APIC error status for viewing in the debugger. */
\r
547 volatile uint32_t ulErrorStatus = 0;
\r
549 portAPIC_ERROR_STATUS = 0;
\r
550 ulErrorStatus = portAPIC_ERROR_STATUS;
\r
551 ( void ) ulErrorStatus;
\r
553 /* Force an assert. */
\r
554 configASSERT( ulCriticalNesting == ~0UL );
\r
556 /*-----------------------------------------------------------*/
\r
558 #if( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
560 void vPortCentralInterruptHandler( uint32_t ulVector )
\r
562 if( ulVector < portNUM_VECTORS )
\r
564 if( xInterruptHandlerTable[ ulVector ] != NULL )
\r
566 ( xInterruptHandlerTable[ ulVector ] )();
\r
570 /* Check for a system stack overflow. */
\r
571 configASSERT( ulSystemStack[ 10 ] == portSTACK_WORD );
\r
572 configASSERT( ulSystemStack[ 12 ] == portSTACK_WORD );
\r
573 configASSERT( ulSystemStack[ 14 ] == portSTACK_WORD );
\r
576 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
577 /*-----------------------------------------------------------*/
\r
579 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
581 BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber )
\r
583 BaseType_t xReturn;
\r
585 xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
\r
587 if( xReturn != pdFAIL )
\r
589 /* Save the handler passed in by the application in the vector number
\r
590 passed in. The addresses are then called from the central interrupt
\r
592 xInterruptHandlerTable[ ulVectorNumber ] = pxHandler;
\r
598 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
599 /*-----------------------------------------------------------*/
\r
601 BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber )
\r
603 BaseType_t xReturn;
\r
605 xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
\r
607 if( xReturn != pdFAIL )
\r
609 taskENTER_CRITICAL();
\r
611 /* Update the IDT to include the application defined handler. */
\r
612 prvSetInterruptGate( ( uint8_t ) ulVectorNumber, ( ISR_Handler_t ) pxHandler, portIDT_FLAGS );
\r
614 taskEXIT_CRITICAL();
\r
619 /*-----------------------------------------------------------*/
\r
621 static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber )
\r
623 BaseType_t xReturn;
\r
625 /* Check validity of vector number. */
\r
626 if( ulVectorNumber >= portNUM_VECTORS )
\r
631 else if( ulVectorNumber < portAPIC_MIN_ALLOWABLE_VECTOR )
\r
636 else if( ulVectorNumber == portAPIC_TIMER_INT_VECTOR )
\r
638 /* In use by FreeRTOS. */
\r
641 else if( ulVectorNumber == portAPIC_YIELD_INT_VECTOR )
\r
643 /* In use by FreeRTOS. */
\r
646 else if( ulVectorNumber == portAPIC_LVT_ERROR_VECTOR )
\r
648 /* In use by FreeRTOS. */
\r
651 else if( ulVectorNumber == portAPIC_SPURIOUS_INT_VECTOR )
\r
653 /* In use by FreeRTOS. */
\r
656 else if( xInterruptHandlerTable[ ulVectorNumber ] != NULL )
\r
658 /* Already in use by the application. */
\r
668 /*-----------------------------------------------------------*/
\r
670 void vGenerateYieldInterrupt( void )
\r
672 __asm volatile( portYIELD_INTERRUPT );
\r