2 FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 This file is part of the FreeRTOS distribution.
\r
9 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
10 the terms of the GNU General Public License (version 2) as published by the
\r
11 Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
\r
13 ***************************************************************************
\r
14 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
15 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
16 >>! obliged to provide the source code for proprietary components !<<
\r
17 >>! outside of the FreeRTOS kernel. !<<
\r
18 ***************************************************************************
\r
20 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
22 FOR A PARTICULAR PURPOSE. Full license text is available on the following
\r
23 link: http://www.freertos.org/a00114.html
\r
25 ***************************************************************************
\r
27 * FreeRTOS provides completely free yet professionally developed, *
\r
28 * robust, strictly quality controlled, supported, and cross *
\r
29 * platform software that is more than just the market leader, it *
\r
30 * is the industry's de facto standard. *
\r
32 * Help yourself get started quickly while simultaneously helping *
\r
33 * to support the FreeRTOS project by purchasing a FreeRTOS *
\r
34 * tutorial book, reference manual, or both: *
\r
35 * http://www.FreeRTOS.org/Documentation *
\r
37 ***************************************************************************
\r
39 http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
\r
40 the FAQ page "My application does not run, what could be wrong?". Have you
\r
41 defined configASSERT()?
\r
43 http://www.FreeRTOS.org/support - In return for receiving this top quality
\r
44 embedded software for free we request you assist our global community by
\r
45 participating in the support forum.
\r
47 http://www.FreeRTOS.org/training - Investing in training allows your team to
\r
48 be as productive as possible as early as possible. Now you can receive
\r
49 FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
\r
50 Ltd, and the world's leading authority on the world's leading RTOS.
\r
52 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
53 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
54 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
56 http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
\r
57 Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
\r
59 http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
\r
60 Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
61 licenses offer ticketed support, indemnification and commercial middleware.
\r
63 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
64 engineered and independently SIL3 certified version for use in safety and
\r
65 mission critical applications that require provable dependability.
\r
70 /* Standard includes. */
\r
73 /* Scheduler includes. */
\r
74 #include "FreeRTOS.h"
\r
77 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
\r
78 /* Check the configuration. */
\r
79 #if( configMAX_PRIORITIES > 32 )
\r
80 #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
82 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
84 #if( configISR_STACK_SIZE < ( configMINIMAL_STACK_SIZE * 2 ) )
\r
85 #warning configISR_STACK_SIZE is probably too small!
\r
86 #endif /* ( configISR_STACK_SIZE < configMINIMAL_STACK_SIZE * 2 ) */
\r
88 #if( ( configMAX_API_CALL_INTERRUPT_PRIORITY > portMAX_PRIORITY ) || ( configMAX_API_CALL_INTERRUPT_PRIORITY < 2 ) )
\r
89 #error configMAX_API_CALL_INTERRUPT_PRIORITY must be between 2 and 15
\r
92 /* A critical section is exited when the critical section nesting count reaches
\r
94 #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
\r
96 /* Tasks are not created with a floating point context, but can be given a
\r
97 floating point context after they have been created. A variable is stored as
\r
98 part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
\r
99 does not have an FPU context, or any other value if the task does have an FPU
\r
101 #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
\r
103 /* Only the IF bit is set so tasks start with interrupts enabled. */
\r
104 #define portINITIAL_EFLAGS ( 0x200UL )
\r
106 /* Error interrupts are at the highest priority vectors. */
\r
107 #define portAPIC_LVT_ERROR_VECTOR ( 0xfe )
\r
108 #define portAPIC_SPURIOUS_INT_VECTOR ( 0xff )
\r
111 #define portEFLAGS_IF ( 0x200UL )
\r
113 /* FPU context size if FSAVE is used. */
\r
114 #define portFPU_CONTEXT_SIZE_BYTES 108
\r
116 /* The expected size of each entry in the IDT. Used to check structure packing
\r
117 is set correctly. */
\r
118 #define portEXPECTED_IDT_ENTRY_SIZE 8
\r
120 /* Default flags setting for entries in the IDT. */
\r
121 #define portIDT_FLAGS ( 0x8E )
\r
123 /* This is the lowest possible ISR vector available to application code. */
\r
124 #define portAPIC_MIN_ALLOWABLE_VECTOR ( 0x20 )
\r
126 /* If configASSERT() is defined then the system stack is filled with this value
\r
127 to allow for a crude stack overflow check. */
\r
128 #define portSTACK_WORD ( 0xecececec )
\r
129 /*-----------------------------------------------------------*/
\r
132 * Starts the first task executing.
\r
134 extern void vPortStartFirstTask( void );
\r
137 * Used to catch tasks that attempt to return from their implementing function.
\r
139 static void prvTaskExitError( void );
\r
142 * Complete one descriptor in the IDT.
\r
144 static void prvSetInterruptGate( uint8_t ucNumber, ISR_Handler_t pxHandlerFunction, uint8_t ucFlags );
\r
147 * The default handler installed in each IDT position.
\r
149 extern void vPortCentralInterruptWrapper( void );
\r
152 * Handler for portYIELD().
\r
154 extern void vPortYieldCall( void );
\r
157 * Configure the APIC to generate the RTOS tick.
\r
159 static void prvSetupTimerInterrupt( void );
\r
162 * Tick interrupt handler.
\r
164 extern void vPortTimerHandler( void );
\r
167 * Check an interrupt vector is not too high, too low, in use by FreeRTOS, or
\r
168 * already in use by the application.
\r
170 static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber );
\r
172 /*-----------------------------------------------------------*/
\r
174 /* A variable is used to keep track of the critical section nesting. This
\r
175 variable must be initialised to a non zero value to ensure interrupts don't
\r
176 inadvertently become unmasked before the scheduler starts. It is set to zero
\r
177 before the first task starts executing. */
\r
178 volatile uint32_t ulCriticalNesting = 9999UL;
\r
180 /* A structure used to map the various fields of an IDT entry into separate
\r
181 structure members. */
\r
184 uint16_t usISRLow; /* Low 16 bits of handler address. */
\r
185 uint16_t usSegmentSelector; /* Flat model means this is not changed. */
\r
186 uint8_t ucZero; /* Must be set to zero. */
\r
187 uint8_t ucFlags; /* Flags for this entry. */
\r
188 uint16_t usISRHigh; /* High 16 bits of handler address. */
\r
189 } __attribute__( ( packed ) );
\r
190 typedef struct IDTEntry IDTEntry_t;
\r
193 /* Use to pass the location of the IDT to the CPU. */
\r
196 uint16_t usTableLimit;
\r
197 uint32_t ulTableBase; /* The address of the first entry in xInterruptDescriptorTable. */
\r
198 } __attribute__( ( __packed__ ) );
\r
199 typedef struct IDTPointer IDTPointer_t;
\r
201 /* The IDT itself. */
\r
202 static __attribute__ ( ( aligned( 32 ) ) ) IDTEntry_t xInterruptDescriptorTable[ portNUM_VECTORS ];
\r
204 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
206 /* A table in which application defined interrupt handlers are stored. These
\r
207 are called by the central interrupt handler if a common interrupt entry
\r
209 static ISR_Handler_t xInterruptHandlerTable[ portNUM_VECTORS ] = { NULL };
\r
211 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
213 #if ( configSUPPORT_FPU == 1 )
\r
215 /* Saved as part of the task context. If pucPortTaskFPUContextBuffer is NULL
\r
216 then the task does not have an FPU context. If pucPortTaskFPUContextBuffer is
\r
217 not NULL then it points to a buffer into which the FPU context can be saved. */
\r
218 uint8_t *pucPortTaskFPUContextBuffer __attribute__((used)) = pdFALSE;
\r
220 #endif /* configSUPPORT_FPU */
\r
222 /* The stack used by interrupt handlers. */
\r
223 static uint32_t ulSystemStack[ configISR_STACK_SIZE ] __attribute__((used)) = { 0 };
\r
225 /* Don't use the very top of the system stack so the return address
\r
226 appears as 0 if the debugger tries to unwind the stack. */
\r
227 volatile uint32_t ulTopOfSystemStack __attribute__((used)) = ( uint32_t ) &( ulSystemStack[ configISR_STACK_SIZE - 5 ] );
\r
229 /* If a yield is requested from an interrupt or from a critical section then
\r
230 the yield is not performed immediately, and ulPortYieldPending is set to pdTRUE
\r
231 instead to indicate the yield should be performed at the end of the interrupt
\r
232 when the critical section is exited. */
\r
233 volatile uint32_t ulPortYieldPending __attribute__((used)) = pdFALSE;
\r
235 /* Counts the interrupt nesting depth. Used to know when to switch to the
\r
236 interrupt/system stack and when to save/restore a complete context. */
\r
237 volatile uint32_t ulInterruptNesting __attribute__((used)) = 0;
\r
239 /*-----------------------------------------------------------*/
\r
242 * See header file for description.
\r
244 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
\r
246 uint32_t ulCodeSegment;
\r
248 /* Setup the initial stack as expected by the portFREERTOS_INTERRUPT_EXIT macro. */
\r
250 *pxTopOfStack = 0x00;
\r
252 *pxTopOfStack = 0x00;
\r
255 /* Parameters first. */
\r
256 *pxTopOfStack = ( StackType_t ) pvParameters;
\r
259 /* There is nothing to return to so assert if attempting to use the return
\r
261 *pxTopOfStack = ( StackType_t ) prvTaskExitError;
\r
264 /* iret used to start the task pops up to here. */
\r
265 *pxTopOfStack = portINITIAL_EFLAGS;
\r
269 __asm volatile( "movl %%cs, %0" : "=r" ( ulCodeSegment ) );
\r
270 *pxTopOfStack = ulCodeSegment;
\r
273 /* First instruction in the task. */
\r
274 *pxTopOfStack = ( StackType_t ) pxCode;
\r
277 /* General purpose registers as expected by a POPA instruction. */
\r
278 *pxTopOfStack = 0xEA;
\r
281 *pxTopOfStack = 0xEC;
\r
284 *pxTopOfStack = 0xED1; /* EDX */
\r
287 *pxTopOfStack = 0xEB1; /* EBX */
\r
290 /* Hole for ESP. */
\r
293 *pxTopOfStack = 0x00; /* EBP */
\r
296 *pxTopOfStack = 0xE5; /* ESI */
\r
299 *pxTopOfStack = 0xeeeeeeee; /* EDI */
\r
301 #if ( configSUPPORT_FPU == 1 )
\r
305 /* Buffer for FPU context, which is initialised to NULL as tasks are not
\r
306 created with an FPU context. */
\r
307 *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
\r
309 #endif /* configSUPPORT_FPU */
\r
311 return pxTopOfStack;
\r
313 /*-----------------------------------------------------------*/
\r
315 static void prvSetInterruptGate( uint8_t ucNumber, ISR_Handler_t pxHandlerFunction, uint8_t ucFlags )
\r
317 uint16_t usCodeSegment;
\r
318 uint32_t ulBase = ( uint32_t ) pxHandlerFunction;
\r
320 xInterruptDescriptorTable[ ucNumber ].usISRLow = ( uint16_t ) ( ulBase & USHRT_MAX );
\r
321 xInterruptDescriptorTable[ ucNumber ].usISRHigh = ( uint16_t ) ( ( ulBase >> 16UL ) & USHRT_MAX );
\r
323 /* When the flat model is used the CS will never change. */
\r
324 __asm volatile( "mov %%cs, %0" : "=r" ( usCodeSegment ) );
\r
325 xInterruptDescriptorTable[ ucNumber ].usSegmentSelector = usCodeSegment;
\r
326 xInterruptDescriptorTable[ ucNumber ].ucZero = 0;
\r
327 xInterruptDescriptorTable[ ucNumber ].ucFlags = ucFlags;
\r
329 /*-----------------------------------------------------------*/
\r
331 void vPortSetupIDT( void )
\r
336 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
338 for( ulNum = 0; ulNum < portNUM_VECTORS; ulNum++ )
\r
340 /* If a handler has not already been installed on this vector. */
\r
341 if( ( xInterruptDescriptorTable[ ulNum ].usISRLow == 0x00 ) && ( xInterruptDescriptorTable[ ulNum ].usISRHigh == 0x00 ) )
\r
343 prvSetInterruptGate( ( uint8_t ) ulNum, vPortCentralInterruptWrapper, portIDT_FLAGS );
\r
347 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
349 /* Set IDT address. */
\r
350 xIDT.ulTableBase = ( uint32_t ) xInterruptDescriptorTable;
\r
351 xIDT.usTableLimit = sizeof( xInterruptDescriptorTable ) - 1;
\r
353 /* Set IDT in CPU. */
\r
354 __asm volatile( "lidt %0" :: "m" (xIDT) );
\r
356 /*-----------------------------------------------------------*/
\r
358 static void prvTaskExitError( void )
\r
360 /* A function that implements a task must not exit or attempt to return to
\r
361 its caller as there is nothing to return to. If a task wants to exit it
\r
362 should instead call vTaskDelete( NULL ).
\r
364 Artificially force an assert() to be triggered if configASSERT() is
\r
365 defined, then stop here so application writers can catch the error. */
\r
366 configASSERT( ulCriticalNesting == ~0UL );
\r
367 portDISABLE_INTERRUPTS();
\r
370 /*-----------------------------------------------------------*/
\r
372 static void prvSetupTimerInterrupt( void )
\r
374 extern void vPortAPICErrorHandlerWrapper( void );
\r
375 extern void vPortAPICSpuriousHandler( void );
\r
377 /* Initialise LAPIC to a well known state. */
\r
378 portAPIC_LDR = 0xFFFFFFFF;
\r
379 portAPIC_LDR = ( ( portAPIC_LDR & 0x00FFFFFF ) | 0x00000001 );
\r
380 portAPIC_LVT_TIMER = portAPIC_DISABLE;
\r
381 portAPIC_LVT_PERF = portAPIC_NMI;
\r
382 portAPIC_LVT_LINT0 = portAPIC_DISABLE;
\r
383 portAPIC_LVT_LINT1 = portAPIC_DISABLE;
\r
384 portAPIC_TASK_PRIORITY = 0;
\r
386 /* Install APIC timer ISR vector. */
\r
387 prvSetInterruptGate( ( uint8_t ) portAPIC_TIMER_INT_VECTOR, vPortTimerHandler, portIDT_FLAGS );
\r
389 /* Install API error handler. */
\r
390 prvSetInterruptGate( ( uint8_t ) portAPIC_LVT_ERROR_VECTOR, vPortAPICErrorHandlerWrapper, portIDT_FLAGS );
\r
392 /* Install Yield handler. */
\r
393 prvSetInterruptGate( ( uint8_t ) portAPIC_YIELD_INT_VECTOR, vPortYieldCall, portIDT_FLAGS );
\r
395 /* Install spurious interrupt vector. */
\r
396 prvSetInterruptGate( ( uint8_t ) portAPIC_SPURIOUS_INT_VECTOR, vPortAPICSpuriousHandler, portIDT_FLAGS );
\r
398 /* Enable the APIC, mapping the spurious interrupt at the same time. */
\r
399 portAPIC_SPURIOUS_INT = portAPIC_SPURIOUS_INT_VECTOR | portAPIC_ENABLE_BIT;
\r
401 /* Set timer error vector. */
\r
402 portAPIC_LVT_ERROR = portAPIC_LVT_ERROR_VECTOR;
\r
404 /* Set the interrupt frequency. */
\r
405 portAPIC_TMRDIV = portAPIC_DIV_16;
\r
406 portAPIC_TIMER_INITIAL_COUNT = ( ( configCPU_CLOCK_HZ >> 4UL ) / configTICK_RATE_HZ ) - 1UL;
\r
408 /*-----------------------------------------------------------*/
\r
410 BaseType_t xPortStartScheduler( void )
\r
414 /* Some versions of GCC require the -mno-ms-bitfields command line option
\r
415 for packing to work. */
\r
416 configASSERT( sizeof( struct IDTEntry ) == portEXPECTED_IDT_ENTRY_SIZE );
\r
418 /* Fill part of the system stack with a known value to help detect stack
\r
419 overflow. A few zeros are left so GDB doesn't get confused unwinding
\r
421 for( xWord = 0; xWord < configISR_STACK_SIZE - 20; xWord++ )
\r
423 ulSystemStack[ xWord ] = portSTACK_WORD;
\r
426 /* Initialise Interrupt Descriptor Table (IDT). */
\r
429 /* Initialise LAPIC and install system handlers. */
\r
430 prvSetupTimerInterrupt();
\r
432 /* Make sure the stack used by interrupts is aligned. */
\r
433 ulTopOfSystemStack &= ~portBYTE_ALIGNMENT_MASK;
\r
435 ulCriticalNesting = 0;
\r
437 /* Enable LAPIC Counter.*/
\r
438 portAPIC_LVT_TIMER = portAPIC_TIMER_PERIODIC | portAPIC_TIMER_INT_VECTOR;
\r
440 /* Sometimes needed. */
\r
441 portAPIC_TMRDIV = portAPIC_DIV_16;
\r
443 /* Should not return from the following function as the scheduler will then
\r
444 be executing the tasks. */
\r
445 vPortStartFirstTask();
\r
449 /*-----------------------------------------------------------*/
\r
451 void vPortEndScheduler( void )
\r
453 /* Not implemented in ports where there is nothing to return to.
\r
454 Artificially force an assert. */
\r
455 configASSERT( ulCriticalNesting == 1000UL );
\r
457 /*-----------------------------------------------------------*/
\r
459 void vPortEnterCritical( void )
\r
461 if( ulCriticalNesting == 0 )
\r
463 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
465 __asm volatile( "cli" );
\r
469 portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
\r
470 configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
\r
475 /* Now interrupts are disabled ulCriticalNesting can be accessed
\r
476 directly. Increment ulCriticalNesting to keep a count of how many times
\r
477 portENTER_CRITICAL() has been called. */
\r
478 ulCriticalNesting++;
\r
480 /*-----------------------------------------------------------*/
\r
482 void vPortExitCritical( void )
\r
484 if( ulCriticalNesting > portNO_CRITICAL_NESTING )
\r
486 /* Decrement the nesting count as the critical section is being
\r
488 ulCriticalNesting--;
\r
490 /* If the nesting level has reached zero then all interrupt
\r
491 priorities must be re-enabled. */
\r
492 if( ulCriticalNesting == portNO_CRITICAL_NESTING )
\r
494 /* Critical nesting has reached zero so all interrupt priorities
\r
495 should be unmasked. */
\r
496 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
498 __asm volatile( "sti" );
\r
502 portAPIC_TASK_PRIORITY = 0;
\r
504 /* If a yield was pended from within the critical section then
\r
505 perform the yield now. */
\r
506 if( ulPortYieldPending != pdFALSE )
\r
508 ulPortYieldPending = pdFALSE;
\r
509 __asm volatile( portYIELD_INTERRUPT );
\r
516 /*-----------------------------------------------------------*/
\r
518 uint32_t ulPortSetInterruptMask( void )
\r
520 volatile uint32_t ulOriginalMask;
\r
522 /* Set mask to max syscall priority. */
\r
523 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
525 /* Return whether interrupts were already enabled or not. Pop adjusts
\r
526 the stack first. */
\r
527 __asm volatile( "pushf \t\n"
\r
530 : "=rm" (ulOriginalMask) :: "memory" );
\r
532 ulOriginalMask &= portEFLAGS_IF;
\r
536 /* Return original mask. */
\r
537 ulOriginalMask = portAPIC_TASK_PRIORITY;
\r
538 portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
\r
539 configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
\r
543 return ulOriginalMask;
\r
545 /*-----------------------------------------------------------*/
\r
547 void vPortClearInterruptMask( uint32_t ulNewMaskValue )
\r
549 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
551 if( ulNewMaskValue != pdFALSE )
\r
553 __asm volatile( "sti" );
\r
558 portAPIC_TASK_PRIORITY = ulNewMaskValue;
\r
559 configASSERT( portAPIC_TASK_PRIORITY == ulNewMaskValue );
\r
563 /*-----------------------------------------------------------*/
\r
565 #if ( configSUPPORT_FPU == 1 )
\r
567 void vPortTaskUsesFPU( void )
\r
569 /* A task is registering the fact that it needs an FPU context. Allocate a
\r
570 buffer into which the context can be saved. */
\r
571 pucPortTaskFPUContextBuffer = ( uint8_t * ) pvPortMalloc( portFPU_CONTEXT_SIZE_BYTES );
\r
572 configASSERT( pucPortTaskFPUContextBuffer );
\r
574 /* Initialise the floating point registers. */
\r
575 __asm volatile( "fninit" );
\r
578 #endif /* configSUPPORT_FPU */
\r
579 /*-----------------------------------------------------------*/
\r
581 void vPortAPICErrorHandler( void )
\r
583 /* Variable to hold the APIC error status for viewing in the debugger. */
\r
584 volatile uint32_t ulErrorStatus = 0;
\r
586 portAPIC_ERROR_STATUS = 0;
\r
587 ulErrorStatus = portAPIC_ERROR_STATUS;
\r
588 ( void ) ulErrorStatus;
\r
590 /* Force an assert. */
\r
591 configASSERT( ulCriticalNesting == ~0UL );
\r
593 /*-----------------------------------------------------------*/
\r
595 #if( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
597 void vPortCentralInterruptHandler( uint32_t ulVector )
\r
599 if( ulVector < portNUM_VECTORS )
\r
601 if( xInterruptHandlerTable[ ulVector ] != NULL )
\r
603 ( xInterruptHandlerTable[ ulVector ] )();
\r
607 /* Check for a system stack overflow. */
\r
608 configASSERT( ulSystemStack[ 10 ] == portSTACK_WORD );
\r
609 configASSERT( ulSystemStack[ 12 ] == portSTACK_WORD );
\r
610 configASSERT( ulSystemStack[ 14 ] == portSTACK_WORD );
\r
613 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
614 /*-----------------------------------------------------------*/
\r
616 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
618 BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber )
\r
620 BaseType_t xReturn;
\r
622 xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
\r
624 if( xReturn != pdFAIL )
\r
626 /* Save the handler passed in by the application in the vector number
\r
627 passed in. The addresses are then called from the central interrupt
\r
629 xInterruptHandlerTable[ ulVectorNumber ] = pxHandler;
\r
635 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
636 /*-----------------------------------------------------------*/
\r
638 BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber )
\r
640 BaseType_t xReturn;
\r
642 xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
\r
644 if( xReturn != pdFAIL )
\r
646 taskENTER_CRITICAL();
\r
648 /* Update the IDT to include the application defined handler. */
\r
649 prvSetInterruptGate( ( uint8_t ) ulVectorNumber, ( ISR_Handler_t ) pxHandler, portIDT_FLAGS );
\r
651 taskEXIT_CRITICAL();
\r
656 /*-----------------------------------------------------------*/
\r
658 static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber )
\r
660 BaseType_t xReturn;
\r
662 /* Check validity of vector number. */
\r
663 if( ulVectorNumber >= portNUM_VECTORS )
\r
668 else if( ulVectorNumber < portAPIC_MIN_ALLOWABLE_VECTOR )
\r
673 else if( ulVectorNumber == portAPIC_TIMER_INT_VECTOR )
\r
675 /* In use by FreeRTOS. */
\r
678 else if( ulVectorNumber == portAPIC_YIELD_INT_VECTOR )
\r
680 /* In use by FreeRTOS. */
\r
683 else if( ulVectorNumber == portAPIC_LVT_ERROR_VECTOR )
\r
685 /* In use by FreeRTOS. */
\r
688 else if( ulVectorNumber == portAPIC_SPURIOUS_INT_VECTOR )
\r
690 /* In use by FreeRTOS. */
\r
693 else if( xInterruptHandlerTable[ ulVectorNumber ] != NULL )
\r
695 /* Already in use by the application. */
\r
705 /*-----------------------------------------------------------*/
\r
707 void vGenerateYieldInterrupt( void )
\r
709 __asm volatile( portYIELD_INTERRUPT );
\r