2 * FreeRTOS Kernel V10.1.0
\r
3 * Copyright (C) 2018 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.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
28 /* Standard includes. */
\r
31 /* Scheduler includes. */
\r
32 #include "FreeRTOS.h"
\r
35 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
\r
36 /* Check the configuration. */
\r
37 #if( configMAX_PRIORITIES > 32 )
\r
38 #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
40 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
42 #if( configISR_STACK_SIZE < ( configMINIMAL_STACK_SIZE * 2 ) )
\r
43 #warning configISR_STACK_SIZE is probably too small!
\r
44 #endif /* ( configISR_STACK_SIZE < configMINIMAL_STACK_SIZE * 2 ) */
\r
46 #if( ( configMAX_API_CALL_INTERRUPT_PRIORITY > portMAX_PRIORITY ) || ( configMAX_API_CALL_INTERRUPT_PRIORITY < 2 ) )
\r
47 #error configMAX_API_CALL_INTERRUPT_PRIORITY must be between 2 and 15
\r
50 #if( ( configSUPPORT_FPU == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
\r
51 #error configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 to use this port with an FPU
\r
54 /* A critical section is exited when the critical section nesting count reaches
\r
56 #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
\r
58 /* Tasks are not created with a floating point context, but can be given a
\r
59 floating point context after they have been created. A variable is stored as
\r
60 part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
\r
61 does not have an FPU context, or any other value if the task does have an FPU
\r
63 #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
\r
65 /* Only the IF bit is set so tasks start with interrupts enabled. */
\r
66 #define portINITIAL_EFLAGS ( 0x200UL )
\r
68 /* Error interrupts are at the highest priority vectors. */
\r
69 #define portAPIC_LVT_ERROR_VECTOR ( 0xfe )
\r
70 #define portAPIC_SPURIOUS_INT_VECTOR ( 0xff )
\r
73 #define portEFLAGS_IF ( 0x200UL )
\r
75 /* FPU context size if FSAVE is used. */
\r
76 #define portFPU_CONTEXT_SIZE_BYTES 108
\r
78 /* The expected size of each entry in the IDT. Used to check structure packing
\r
79 is set correctly. */
\r
80 #define portEXPECTED_IDT_ENTRY_SIZE 8
\r
82 /* Default flags setting for entries in the IDT. */
\r
83 #define portIDT_FLAGS ( 0x8E )
\r
85 /* This is the lowest possible ISR vector available to application code. */
\r
86 #define portAPIC_MIN_ALLOWABLE_VECTOR ( 0x20 )
\r
88 /* If configASSERT() is defined then the system stack is filled with this value
\r
89 to allow for a crude stack overflow check. */
\r
90 #define portSTACK_WORD ( 0xecececec )
\r
91 /*-----------------------------------------------------------*/
\r
94 * Starts the first task executing.
\r
96 extern void vPortStartFirstTask( void );
\r
99 * Used to catch tasks that attempt to return from their implementing function.
\r
101 static void prvTaskExitError( void );
\r
104 * Complete one descriptor in the IDT.
\r
106 static void prvSetInterruptGate( uint8_t ucNumber, ISR_Handler_t pxHandlerFunction, uint8_t ucFlags );
\r
109 * The default handler installed in each IDT position.
\r
111 extern void vPortCentralInterruptWrapper( void );
\r
114 * Handler for portYIELD().
\r
116 extern void vPortYieldCall( void );
\r
119 * Configure the APIC to generate the RTOS tick.
\r
121 static void prvSetupTimerInterrupt( void );
\r
124 * Tick interrupt handler.
\r
126 extern void vPortTimerHandler( void );
\r
129 * Check an interrupt vector is not too high, too low, in use by FreeRTOS, or
\r
130 * already in use by the application.
\r
132 static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber );
\r
134 /*-----------------------------------------------------------*/
\r
136 /* A variable is used to keep track of the critical section nesting. This
\r
137 variable must be initialised to a non zero value to ensure interrupts don't
\r
138 inadvertently become unmasked before the scheduler starts. It is set to zero
\r
139 before the first task starts executing. */
\r
140 volatile uint32_t ulCriticalNesting = 9999UL;
\r
142 /* A structure used to map the various fields of an IDT entry into separate
\r
143 structure members. */
\r
146 uint16_t usISRLow; /* Low 16 bits of handler address. */
\r
147 uint16_t usSegmentSelector; /* Flat model means this is not changed. */
\r
148 uint8_t ucZero; /* Must be set to zero. */
\r
149 uint8_t ucFlags; /* Flags for this entry. */
\r
150 uint16_t usISRHigh; /* High 16 bits of handler address. */
\r
151 } __attribute__( ( packed ) );
\r
152 typedef struct IDTEntry IDTEntry_t;
\r
155 /* Use to pass the location of the IDT to the CPU. */
\r
158 uint16_t usTableLimit;
\r
159 uint32_t ulTableBase; /* The address of the first entry in xInterruptDescriptorTable. */
\r
160 } __attribute__( ( __packed__ ) );
\r
161 typedef struct IDTPointer IDTPointer_t;
\r
163 /* The IDT itself. */
\r
164 static __attribute__ ( ( aligned( 32 ) ) ) IDTEntry_t xInterruptDescriptorTable[ portNUM_VECTORS ];
\r
166 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
168 /* A table in which application defined interrupt handlers are stored. These
\r
169 are called by the central interrupt handler if a common interrupt entry
\r
171 static ISR_Handler_t xInterruptHandlerTable[ portNUM_VECTORS ] = { NULL };
\r
173 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
175 #if ( configSUPPORT_FPU == 1 )
\r
177 /* Saved as part of the task context. If pucPortTaskFPUContextBuffer is NULL
\r
178 then the task does not have an FPU context. If pucPortTaskFPUContextBuffer is
\r
179 not NULL then it points to a buffer into which the FPU context can be saved. */
\r
180 uint8_t *pucPortTaskFPUContextBuffer __attribute__((used)) = pdFALSE;
\r
182 #endif /* configSUPPORT_FPU */
\r
184 /* The stack used by interrupt handlers. */
\r
185 static uint32_t ulSystemStack[ configISR_STACK_SIZE ] __attribute__((used)) = { 0 };
\r
187 /* Don't use the very top of the system stack so the return address
\r
188 appears as 0 if the debugger tries to unwind the stack. */
\r
189 volatile uint32_t ulTopOfSystemStack __attribute__((used)) = ( uint32_t ) &( ulSystemStack[ configISR_STACK_SIZE - 5 ] );
\r
191 /* If a yield is requested from an interrupt or from a critical section then
\r
192 the yield is not performed immediately, and ulPortYieldPending is set to pdTRUE
\r
193 instead to indicate the yield should be performed at the end of the interrupt
\r
194 when the critical section is exited. */
\r
195 volatile uint32_t ulPortYieldPending __attribute__((used)) = pdFALSE;
\r
197 /* Counts the interrupt nesting depth. Used to know when to switch to the
\r
198 interrupt/system stack and when to save/restore a complete context. */
\r
199 volatile uint32_t ulInterruptNesting __attribute__((used)) = 0;
\r
201 /*-----------------------------------------------------------*/
\r
204 * See header file for description.
\r
206 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
\r
208 uint32_t ulCodeSegment;
\r
210 /* Setup the initial stack as expected by the portFREERTOS_INTERRUPT_EXIT macro. */
\r
212 *pxTopOfStack = 0x00;
\r
214 *pxTopOfStack = 0x00;
\r
217 /* Parameters first. */
\r
218 *pxTopOfStack = ( StackType_t ) pvParameters;
\r
221 /* There is nothing to return to so assert if attempting to use the return
\r
223 *pxTopOfStack = ( StackType_t ) prvTaskExitError;
\r
226 /* iret used to start the task pops up to here. */
\r
227 *pxTopOfStack = portINITIAL_EFLAGS;
\r
231 __asm volatile( "movl %%cs, %0" : "=r" ( ulCodeSegment ) );
\r
232 *pxTopOfStack = ulCodeSegment;
\r
235 /* First instruction in the task. */
\r
236 *pxTopOfStack = ( StackType_t ) pxCode;
\r
239 /* General purpose registers as expected by a POPA instruction. */
\r
240 *pxTopOfStack = 0xEA;
\r
243 *pxTopOfStack = 0xEC;
\r
246 *pxTopOfStack = 0xED1; /* EDX */
\r
249 *pxTopOfStack = 0xEB1; /* EBX */
\r
252 /* Hole for ESP. */
\r
255 *pxTopOfStack = 0x00; /* EBP */
\r
258 *pxTopOfStack = 0xE5; /* ESI */
\r
261 *pxTopOfStack = 0xeeeeeeee; /* EDI */
\r
263 #if ( configSUPPORT_FPU == 1 )
\r
267 /* Buffer for FPU context, which is initialised to NULL as tasks are not
\r
268 created with an FPU context. */
\r
269 *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
\r
271 #endif /* configSUPPORT_FPU */
\r
273 return pxTopOfStack;
\r
275 /*-----------------------------------------------------------*/
\r
277 static void prvSetInterruptGate( uint8_t ucNumber, ISR_Handler_t pxHandlerFunction, uint8_t ucFlags )
\r
279 uint16_t usCodeSegment;
\r
280 uint32_t ulBase = ( uint32_t ) pxHandlerFunction;
\r
282 xInterruptDescriptorTable[ ucNumber ].usISRLow = ( uint16_t ) ( ulBase & USHRT_MAX );
\r
283 xInterruptDescriptorTable[ ucNumber ].usISRHigh = ( uint16_t ) ( ( ulBase >> 16UL ) & USHRT_MAX );
\r
285 /* When the flat model is used the CS will never change. */
\r
286 __asm volatile( "mov %%cs, %0" : "=r" ( usCodeSegment ) );
\r
287 xInterruptDescriptorTable[ ucNumber ].usSegmentSelector = usCodeSegment;
\r
288 xInterruptDescriptorTable[ ucNumber ].ucZero = 0;
\r
289 xInterruptDescriptorTable[ ucNumber ].ucFlags = ucFlags;
\r
291 /*-----------------------------------------------------------*/
\r
293 void vPortSetupIDT( void )
\r
298 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
300 for( ulNum = 0; ulNum < portNUM_VECTORS; ulNum++ )
\r
302 /* If a handler has not already been installed on this vector. */
\r
303 if( ( xInterruptDescriptorTable[ ulNum ].usISRLow == 0x00 ) && ( xInterruptDescriptorTable[ ulNum ].usISRHigh == 0x00 ) )
\r
305 prvSetInterruptGate( ( uint8_t ) ulNum, vPortCentralInterruptWrapper, portIDT_FLAGS );
\r
309 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
311 /* Set IDT address. */
\r
312 xIDT.ulTableBase = ( uint32_t ) xInterruptDescriptorTable;
\r
313 xIDT.usTableLimit = sizeof( xInterruptDescriptorTable ) - 1;
\r
315 /* Set IDT in CPU. */
\r
316 __asm volatile( "lidt %0" :: "m" (xIDT) );
\r
318 /*-----------------------------------------------------------*/
\r
320 static void prvTaskExitError( void )
\r
322 /* A function that implements a task must not exit or attempt to return to
\r
323 its caller as there is nothing to return to. If a task wants to exit it
\r
324 should instead call vTaskDelete( NULL ).
\r
326 Artificially force an assert() to be triggered if configASSERT() is
\r
327 defined, then stop here so application writers can catch the error. */
\r
328 configASSERT( ulCriticalNesting == ~0UL );
\r
329 portDISABLE_INTERRUPTS();
\r
332 /*-----------------------------------------------------------*/
\r
334 static void prvSetupTimerInterrupt( void )
\r
336 extern void vPortAPICErrorHandlerWrapper( void );
\r
337 extern void vPortAPICSpuriousHandler( void );
\r
339 /* Initialise LAPIC to a well known state. */
\r
340 portAPIC_LDR = 0xFFFFFFFF;
\r
341 portAPIC_LDR = ( ( portAPIC_LDR & 0x00FFFFFF ) | 0x00000001 );
\r
342 portAPIC_LVT_TIMER = portAPIC_DISABLE;
\r
343 portAPIC_LVT_PERF = portAPIC_NMI;
\r
344 portAPIC_LVT_LINT0 = portAPIC_DISABLE;
\r
345 portAPIC_LVT_LINT1 = portAPIC_DISABLE;
\r
346 portAPIC_TASK_PRIORITY = 0;
\r
348 /* Install APIC timer ISR vector. */
\r
349 prvSetInterruptGate( ( uint8_t ) portAPIC_TIMER_INT_VECTOR, vPortTimerHandler, portIDT_FLAGS );
\r
351 /* Install API error handler. */
\r
352 prvSetInterruptGate( ( uint8_t ) portAPIC_LVT_ERROR_VECTOR, vPortAPICErrorHandlerWrapper, portIDT_FLAGS );
\r
354 /* Install Yield handler. */
\r
355 prvSetInterruptGate( ( uint8_t ) portAPIC_YIELD_INT_VECTOR, vPortYieldCall, portIDT_FLAGS );
\r
357 /* Install spurious interrupt vector. */
\r
358 prvSetInterruptGate( ( uint8_t ) portAPIC_SPURIOUS_INT_VECTOR, vPortAPICSpuriousHandler, portIDT_FLAGS );
\r
360 /* Enable the APIC, mapping the spurious interrupt at the same time. */
\r
361 portAPIC_SPURIOUS_INT = portAPIC_SPURIOUS_INT_VECTOR | portAPIC_ENABLE_BIT;
\r
363 /* Set timer error vector. */
\r
364 portAPIC_LVT_ERROR = portAPIC_LVT_ERROR_VECTOR;
\r
366 /* Set the interrupt frequency. */
\r
367 portAPIC_TMRDIV = portAPIC_DIV_16;
\r
368 portAPIC_TIMER_INITIAL_COUNT = ( ( configCPU_CLOCK_HZ >> 4UL ) / configTICK_RATE_HZ ) - 1UL;
\r
370 /*-----------------------------------------------------------*/
\r
372 BaseType_t xPortStartScheduler( void )
\r
376 /* Some versions of GCC require the -mno-ms-bitfields command line option
\r
377 for packing to work. */
\r
378 configASSERT( sizeof( struct IDTEntry ) == portEXPECTED_IDT_ENTRY_SIZE );
\r
380 /* Fill part of the system stack with a known value to help detect stack
\r
381 overflow. A few zeros are left so GDB doesn't get confused unwinding
\r
383 for( xWord = 0; xWord < configISR_STACK_SIZE - 20; xWord++ )
\r
385 ulSystemStack[ xWord ] = portSTACK_WORD;
\r
388 /* Initialise Interrupt Descriptor Table (IDT). */
\r
391 /* Initialise LAPIC and install system handlers. */
\r
392 prvSetupTimerInterrupt();
\r
394 /* Make sure the stack used by interrupts is aligned. */
\r
395 ulTopOfSystemStack &= ~portBYTE_ALIGNMENT_MASK;
\r
397 ulCriticalNesting = 0;
\r
399 /* Enable LAPIC Counter.*/
\r
400 portAPIC_LVT_TIMER = portAPIC_TIMER_PERIODIC | portAPIC_TIMER_INT_VECTOR;
\r
402 /* Sometimes needed. */
\r
403 portAPIC_TMRDIV = portAPIC_DIV_16;
\r
405 /* Should not return from the following function as the scheduler will then
\r
406 be executing the tasks. */
\r
407 vPortStartFirstTask();
\r
411 /*-----------------------------------------------------------*/
\r
413 void vPortEndScheduler( void )
\r
415 /* Not implemented in ports where there is nothing to return to.
\r
416 Artificially force an assert. */
\r
417 configASSERT( ulCriticalNesting == 1000UL );
\r
419 /*-----------------------------------------------------------*/
\r
421 void vPortEnterCritical( void )
\r
423 if( ulCriticalNesting == 0 )
\r
425 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
427 __asm volatile( "cli" );
\r
431 portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
\r
432 configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
\r
437 /* Now interrupts are disabled ulCriticalNesting can be accessed
\r
438 directly. Increment ulCriticalNesting to keep a count of how many times
\r
439 portENTER_CRITICAL() has been called. */
\r
440 ulCriticalNesting++;
\r
442 /*-----------------------------------------------------------*/
\r
444 void vPortExitCritical( void )
\r
446 if( ulCriticalNesting > portNO_CRITICAL_NESTING )
\r
448 /* Decrement the nesting count as the critical section is being
\r
450 ulCriticalNesting--;
\r
452 /* If the nesting level has reached zero then all interrupt
\r
453 priorities must be re-enabled. */
\r
454 if( ulCriticalNesting == portNO_CRITICAL_NESTING )
\r
456 /* Critical nesting has reached zero so all interrupt priorities
\r
457 should be unmasked. */
\r
458 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
460 __asm volatile( "sti" );
\r
464 portAPIC_TASK_PRIORITY = 0;
\r
468 /* If a yield was pended from within the critical section then
\r
469 perform the yield now. */
\r
470 if( ulPortYieldPending != pdFALSE )
\r
472 ulPortYieldPending = pdFALSE;
\r
473 __asm volatile( portYIELD_INTERRUPT );
\r
478 /*-----------------------------------------------------------*/
\r
480 uint32_t ulPortSetInterruptMask( void )
\r
482 volatile uint32_t ulOriginalMask;
\r
484 /* Set mask to max syscall priority. */
\r
485 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
487 /* Return whether interrupts were already enabled or not. Pop adjusts
\r
488 the stack first. */
\r
489 __asm volatile( "pushf \t\n"
\r
492 : "=rm" (ulOriginalMask) :: "memory" );
\r
494 ulOriginalMask &= portEFLAGS_IF;
\r
498 /* Return original mask. */
\r
499 ulOriginalMask = portAPIC_TASK_PRIORITY;
\r
500 portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
\r
501 configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
\r
505 return ulOriginalMask;
\r
507 /*-----------------------------------------------------------*/
\r
509 void vPortClearInterruptMask( uint32_t ulNewMaskValue )
\r
511 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
513 if( ulNewMaskValue != pdFALSE )
\r
515 __asm volatile( "sti" );
\r
520 portAPIC_TASK_PRIORITY = ulNewMaskValue;
\r
521 configASSERT( portAPIC_TASK_PRIORITY == ulNewMaskValue );
\r
525 /*-----------------------------------------------------------*/
\r
527 #if ( configSUPPORT_FPU == 1 )
\r
529 void vPortTaskUsesFPU( void )
\r
531 /* A task is registering the fact that it needs an FPU context. Allocate a
\r
532 buffer into which the context can be saved. */
\r
533 pucPortTaskFPUContextBuffer = ( uint8_t * ) pvPortMalloc( portFPU_CONTEXT_SIZE_BYTES );
\r
534 configASSERT( pucPortTaskFPUContextBuffer );
\r
536 /* Initialise the floating point registers. */
\r
537 __asm volatile( "fninit" );
\r
540 #endif /* configSUPPORT_FPU */
\r
541 /*-----------------------------------------------------------*/
\r
543 void vPortAPICErrorHandler( void )
\r
545 /* Variable to hold the APIC error status for viewing in the debugger. */
\r
546 volatile uint32_t ulErrorStatus = 0;
\r
548 portAPIC_ERROR_STATUS = 0;
\r
549 ulErrorStatus = portAPIC_ERROR_STATUS;
\r
550 ( void ) ulErrorStatus;
\r
552 /* Force an assert. */
\r
553 configASSERT( ulCriticalNesting == ~0UL );
\r
555 /*-----------------------------------------------------------*/
\r
557 #if( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
559 void vPortCentralInterruptHandler( uint32_t ulVector )
\r
561 if( ulVector < portNUM_VECTORS )
\r
563 if( xInterruptHandlerTable[ ulVector ] != NULL )
\r
565 ( xInterruptHandlerTable[ ulVector ] )();
\r
569 /* Check for a system stack overflow. */
\r
570 configASSERT( ulSystemStack[ 10 ] == portSTACK_WORD );
\r
571 configASSERT( ulSystemStack[ 12 ] == portSTACK_WORD );
\r
572 configASSERT( ulSystemStack[ 14 ] == portSTACK_WORD );
\r
575 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
576 /*-----------------------------------------------------------*/
\r
578 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
580 BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber )
\r
582 BaseType_t xReturn;
\r
584 xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
\r
586 if( xReturn != pdFAIL )
\r
588 /* Save the handler passed in by the application in the vector number
\r
589 passed in. The addresses are then called from the central interrupt
\r
591 xInterruptHandlerTable[ ulVectorNumber ] = pxHandler;
\r
597 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
598 /*-----------------------------------------------------------*/
\r
600 BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber )
\r
602 BaseType_t xReturn;
\r
604 xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
\r
606 if( xReturn != pdFAIL )
\r
608 taskENTER_CRITICAL();
\r
610 /* Update the IDT to include the application defined handler. */
\r
611 prvSetInterruptGate( ( uint8_t ) ulVectorNumber, ( ISR_Handler_t ) pxHandler, portIDT_FLAGS );
\r
613 taskEXIT_CRITICAL();
\r
618 /*-----------------------------------------------------------*/
\r
620 static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber )
\r
622 BaseType_t xReturn;
\r
624 /* Check validity of vector number. */
\r
625 if( ulVectorNumber >= portNUM_VECTORS )
\r
630 else if( ulVectorNumber < portAPIC_MIN_ALLOWABLE_VECTOR )
\r
635 else if( ulVectorNumber == portAPIC_TIMER_INT_VECTOR )
\r
637 /* In use by FreeRTOS. */
\r
640 else if( ulVectorNumber == portAPIC_YIELD_INT_VECTOR )
\r
642 /* In use by FreeRTOS. */
\r
645 else if( ulVectorNumber == portAPIC_LVT_ERROR_VECTOR )
\r
647 /* In use by FreeRTOS. */
\r
650 else if( ulVectorNumber == portAPIC_SPURIOUS_INT_VECTOR )
\r
652 /* In use by FreeRTOS. */
\r
655 else if( xInterruptHandlerTable[ ulVectorNumber ] != NULL )
\r
657 /* Already in use by the application. */
\r
667 /*-----------------------------------------------------------*/
\r
669 void vGenerateYieldInterrupt( void )
\r
671 __asm volatile( portYIELD_INTERRUPT );
\r