2 FreeRTOS V9.0.0 - 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 #if( ( configSUPPORT_FPU == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
\r
93 #error configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 to use this port with an FPU
\r
96 /* A critical section is exited when the critical section nesting count reaches
\r
98 #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
\r
100 /* Tasks are not created with a floating point context, but can be given a
\r
101 floating point context after they have been created. A variable is stored as
\r
102 part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
\r
103 does not have an FPU context, or any other value if the task does have an FPU
\r
105 #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
\r
107 /* Only the IF bit is set so tasks start with interrupts enabled. */
\r
108 #define portINITIAL_EFLAGS ( 0x200UL )
\r
110 /* Error interrupts are at the highest priority vectors. */
\r
111 #define portAPIC_LVT_ERROR_VECTOR ( 0xfe )
\r
112 #define portAPIC_SPURIOUS_INT_VECTOR ( 0xff )
\r
115 #define portEFLAGS_IF ( 0x200UL )
\r
117 /* FPU context size if FSAVE is used. */
\r
118 #define portFPU_CONTEXT_SIZE_BYTES 108
\r
120 /* The expected size of each entry in the IDT. Used to check structure packing
\r
121 is set correctly. */
\r
122 #define portEXPECTED_IDT_ENTRY_SIZE 8
\r
124 /* Default flags setting for entries in the IDT. */
\r
125 #define portIDT_FLAGS ( 0x8E )
\r
127 /* This is the lowest possible ISR vector available to application code. */
\r
128 #define portAPIC_MIN_ALLOWABLE_VECTOR ( 0x20 )
\r
130 /* If configASSERT() is defined then the system stack is filled with this value
\r
131 to allow for a crude stack overflow check. */
\r
132 #define portSTACK_WORD ( 0xecececec )
\r
133 /*-----------------------------------------------------------*/
\r
136 * Starts the first task executing.
\r
138 extern void vPortStartFirstTask( void );
\r
141 * Used to catch tasks that attempt to return from their implementing function.
\r
143 static void prvTaskExitError( void );
\r
146 * Complete one descriptor in the IDT.
\r
148 static void prvSetInterruptGate( uint8_t ucNumber, ISR_Handler_t pxHandlerFunction, uint8_t ucFlags );
\r
151 * The default handler installed in each IDT position.
\r
153 extern void vPortCentralInterruptWrapper( void );
\r
156 * Handler for portYIELD().
\r
158 extern void vPortYieldCall( void );
\r
161 * Configure the APIC to generate the RTOS tick.
\r
163 static void prvSetupTimerInterrupt( void );
\r
166 * Tick interrupt handler.
\r
168 extern void vPortTimerHandler( void );
\r
171 * Check an interrupt vector is not too high, too low, in use by FreeRTOS, or
\r
172 * already in use by the application.
\r
174 static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber );
\r
176 /*-----------------------------------------------------------*/
\r
178 /* A variable is used to keep track of the critical section nesting. This
\r
179 variable must be initialised to a non zero value to ensure interrupts don't
\r
180 inadvertently become unmasked before the scheduler starts. It is set to zero
\r
181 before the first task starts executing. */
\r
182 volatile uint32_t ulCriticalNesting = 9999UL;
\r
184 /* A structure used to map the various fields of an IDT entry into separate
\r
185 structure members. */
\r
188 uint16_t usISRLow; /* Low 16 bits of handler address. */
\r
189 uint16_t usSegmentSelector; /* Flat model means this is not changed. */
\r
190 uint8_t ucZero; /* Must be set to zero. */
\r
191 uint8_t ucFlags; /* Flags for this entry. */
\r
192 uint16_t usISRHigh; /* High 16 bits of handler address. */
\r
193 } __attribute__( ( packed ) );
\r
194 typedef struct IDTEntry IDTEntry_t;
\r
197 /* Use to pass the location of the IDT to the CPU. */
\r
200 uint16_t usTableLimit;
\r
201 uint32_t ulTableBase; /* The address of the first entry in xInterruptDescriptorTable. */
\r
202 } __attribute__( ( __packed__ ) );
\r
203 typedef struct IDTPointer IDTPointer_t;
\r
205 /* The IDT itself. */
\r
206 static __attribute__ ( ( aligned( 32 ) ) ) IDTEntry_t xInterruptDescriptorTable[ portNUM_VECTORS ];
\r
208 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
210 /* A table in which application defined interrupt handlers are stored. These
\r
211 are called by the central interrupt handler if a common interrupt entry
\r
213 static ISR_Handler_t xInterruptHandlerTable[ portNUM_VECTORS ] = { NULL };
\r
215 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
217 #if ( configSUPPORT_FPU == 1 )
\r
219 /* Saved as part of the task context. If pucPortTaskFPUContextBuffer is NULL
\r
220 then the task does not have an FPU context. If pucPortTaskFPUContextBuffer is
\r
221 not NULL then it points to a buffer into which the FPU context can be saved. */
\r
222 uint8_t *pucPortTaskFPUContextBuffer __attribute__((used)) = pdFALSE;
\r
224 #endif /* configSUPPORT_FPU */
\r
226 /* The stack used by interrupt handlers. */
\r
227 static uint32_t ulSystemStack[ configISR_STACK_SIZE ] __attribute__((used)) = { 0 };
\r
229 /* Don't use the very top of the system stack so the return address
\r
230 appears as 0 if the debugger tries to unwind the stack. */
\r
231 volatile uint32_t ulTopOfSystemStack __attribute__((used)) = ( uint32_t ) &( ulSystemStack[ configISR_STACK_SIZE - 5 ] );
\r
233 /* If a yield is requested from an interrupt or from a critical section then
\r
234 the yield is not performed immediately, and ulPortYieldPending is set to pdTRUE
\r
235 instead to indicate the yield should be performed at the end of the interrupt
\r
236 when the critical section is exited. */
\r
237 volatile uint32_t ulPortYieldPending __attribute__((used)) = pdFALSE;
\r
239 /* Counts the interrupt nesting depth. Used to know when to switch to the
\r
240 interrupt/system stack and when to save/restore a complete context. */
\r
241 volatile uint32_t ulInterruptNesting __attribute__((used)) = 0;
\r
243 /*-----------------------------------------------------------*/
\r
246 * See header file for description.
\r
248 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
\r
250 uint32_t ulCodeSegment;
\r
252 /* Setup the initial stack as expected by the portFREERTOS_INTERRUPT_EXIT macro. */
\r
254 *pxTopOfStack = 0x00;
\r
256 *pxTopOfStack = 0x00;
\r
259 /* Parameters first. */
\r
260 *pxTopOfStack = ( StackType_t ) pvParameters;
\r
263 /* There is nothing to return to so assert if attempting to use the return
\r
265 *pxTopOfStack = ( StackType_t ) prvTaskExitError;
\r
268 /* iret used to start the task pops up to here. */
\r
269 *pxTopOfStack = portINITIAL_EFLAGS;
\r
273 __asm volatile( "movl %%cs, %0" : "=r" ( ulCodeSegment ) );
\r
274 *pxTopOfStack = ulCodeSegment;
\r
277 /* First instruction in the task. */
\r
278 *pxTopOfStack = ( StackType_t ) pxCode;
\r
281 /* General purpose registers as expected by a POPA instruction. */
\r
282 *pxTopOfStack = 0xEA;
\r
285 *pxTopOfStack = 0xEC;
\r
288 *pxTopOfStack = 0xED1; /* EDX */
\r
291 *pxTopOfStack = 0xEB1; /* EBX */
\r
294 /* Hole for ESP. */
\r
297 *pxTopOfStack = 0x00; /* EBP */
\r
300 *pxTopOfStack = 0xE5; /* ESI */
\r
303 *pxTopOfStack = 0xeeeeeeee; /* EDI */
\r
305 #if ( configSUPPORT_FPU == 1 )
\r
309 /* Buffer for FPU context, which is initialised to NULL as tasks are not
\r
310 created with an FPU context. */
\r
311 *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
\r
313 #endif /* configSUPPORT_FPU */
\r
315 return pxTopOfStack;
\r
317 /*-----------------------------------------------------------*/
\r
319 static void prvSetInterruptGate( uint8_t ucNumber, ISR_Handler_t pxHandlerFunction, uint8_t ucFlags )
\r
321 uint16_t usCodeSegment;
\r
322 uint32_t ulBase = ( uint32_t ) pxHandlerFunction;
\r
324 xInterruptDescriptorTable[ ucNumber ].usISRLow = ( uint16_t ) ( ulBase & USHRT_MAX );
\r
325 xInterruptDescriptorTable[ ucNumber ].usISRHigh = ( uint16_t ) ( ( ulBase >> 16UL ) & USHRT_MAX );
\r
327 /* When the flat model is used the CS will never change. */
\r
328 __asm volatile( "mov %%cs, %0" : "=r" ( usCodeSegment ) );
\r
329 xInterruptDescriptorTable[ ucNumber ].usSegmentSelector = usCodeSegment;
\r
330 xInterruptDescriptorTable[ ucNumber ].ucZero = 0;
\r
331 xInterruptDescriptorTable[ ucNumber ].ucFlags = ucFlags;
\r
333 /*-----------------------------------------------------------*/
\r
335 void vPortSetupIDT( void )
\r
340 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
342 for( ulNum = 0; ulNum < portNUM_VECTORS; ulNum++ )
\r
344 /* If a handler has not already been installed on this vector. */
\r
345 if( ( xInterruptDescriptorTable[ ulNum ].usISRLow == 0x00 ) && ( xInterruptDescriptorTable[ ulNum ].usISRHigh == 0x00 ) )
\r
347 prvSetInterruptGate( ( uint8_t ) ulNum, vPortCentralInterruptWrapper, portIDT_FLAGS );
\r
351 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
353 /* Set IDT address. */
\r
354 xIDT.ulTableBase = ( uint32_t ) xInterruptDescriptorTable;
\r
355 xIDT.usTableLimit = sizeof( xInterruptDescriptorTable ) - 1;
\r
357 /* Set IDT in CPU. */
\r
358 __asm volatile( "lidt %0" :: "m" (xIDT) );
\r
360 /*-----------------------------------------------------------*/
\r
362 static void prvTaskExitError( void )
\r
364 /* A function that implements a task must not exit or attempt to return to
\r
365 its caller as there is nothing to return to. If a task wants to exit it
\r
366 should instead call vTaskDelete( NULL ).
\r
368 Artificially force an assert() to be triggered if configASSERT() is
\r
369 defined, then stop here so application writers can catch the error. */
\r
370 configASSERT( ulCriticalNesting == ~0UL );
\r
371 portDISABLE_INTERRUPTS();
\r
374 /*-----------------------------------------------------------*/
\r
376 static void prvSetupTimerInterrupt( void )
\r
378 extern void vPortAPICErrorHandlerWrapper( void );
\r
379 extern void vPortAPICSpuriousHandler( void );
\r
381 /* Initialise LAPIC to a well known state. */
\r
382 portAPIC_LDR = 0xFFFFFFFF;
\r
383 portAPIC_LDR = ( ( portAPIC_LDR & 0x00FFFFFF ) | 0x00000001 );
\r
384 portAPIC_LVT_TIMER = portAPIC_DISABLE;
\r
385 portAPIC_LVT_PERF = portAPIC_NMI;
\r
386 portAPIC_LVT_LINT0 = portAPIC_DISABLE;
\r
387 portAPIC_LVT_LINT1 = portAPIC_DISABLE;
\r
388 portAPIC_TASK_PRIORITY = 0;
\r
390 /* Install APIC timer ISR vector. */
\r
391 prvSetInterruptGate( ( uint8_t ) portAPIC_TIMER_INT_VECTOR, vPortTimerHandler, portIDT_FLAGS );
\r
393 /* Install API error handler. */
\r
394 prvSetInterruptGate( ( uint8_t ) portAPIC_LVT_ERROR_VECTOR, vPortAPICErrorHandlerWrapper, portIDT_FLAGS );
\r
396 /* Install Yield handler. */
\r
397 prvSetInterruptGate( ( uint8_t ) portAPIC_YIELD_INT_VECTOR, vPortYieldCall, portIDT_FLAGS );
\r
399 /* Install spurious interrupt vector. */
\r
400 prvSetInterruptGate( ( uint8_t ) portAPIC_SPURIOUS_INT_VECTOR, vPortAPICSpuriousHandler, portIDT_FLAGS );
\r
402 /* Enable the APIC, mapping the spurious interrupt at the same time. */
\r
403 portAPIC_SPURIOUS_INT = portAPIC_SPURIOUS_INT_VECTOR | portAPIC_ENABLE_BIT;
\r
405 /* Set timer error vector. */
\r
406 portAPIC_LVT_ERROR = portAPIC_LVT_ERROR_VECTOR;
\r
408 /* Set the interrupt frequency. */
\r
409 portAPIC_TMRDIV = portAPIC_DIV_16;
\r
410 portAPIC_TIMER_INITIAL_COUNT = ( ( configCPU_CLOCK_HZ >> 4UL ) / configTICK_RATE_HZ ) - 1UL;
\r
412 /*-----------------------------------------------------------*/
\r
414 BaseType_t xPortStartScheduler( void )
\r
418 /* Some versions of GCC require the -mno-ms-bitfields command line option
\r
419 for packing to work. */
\r
420 configASSERT( sizeof( struct IDTEntry ) == portEXPECTED_IDT_ENTRY_SIZE );
\r
422 /* Fill part of the system stack with a known value to help detect stack
\r
423 overflow. A few zeros are left so GDB doesn't get confused unwinding
\r
425 for( xWord = 0; xWord < configISR_STACK_SIZE - 20; xWord++ )
\r
427 ulSystemStack[ xWord ] = portSTACK_WORD;
\r
430 /* Initialise Interrupt Descriptor Table (IDT). */
\r
433 /* Initialise LAPIC and install system handlers. */
\r
434 prvSetupTimerInterrupt();
\r
436 /* Make sure the stack used by interrupts is aligned. */
\r
437 ulTopOfSystemStack &= ~portBYTE_ALIGNMENT_MASK;
\r
439 ulCriticalNesting = 0;
\r
441 /* Enable LAPIC Counter.*/
\r
442 portAPIC_LVT_TIMER = portAPIC_TIMER_PERIODIC | portAPIC_TIMER_INT_VECTOR;
\r
444 /* Sometimes needed. */
\r
445 portAPIC_TMRDIV = portAPIC_DIV_16;
\r
447 /* Should not return from the following function as the scheduler will then
\r
448 be executing the tasks. */
\r
449 vPortStartFirstTask();
\r
453 /*-----------------------------------------------------------*/
\r
455 void vPortEndScheduler( void )
\r
457 /* Not implemented in ports where there is nothing to return to.
\r
458 Artificially force an assert. */
\r
459 configASSERT( ulCriticalNesting == 1000UL );
\r
461 /*-----------------------------------------------------------*/
\r
463 void vPortEnterCritical( void )
\r
465 if( ulCriticalNesting == 0 )
\r
467 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
469 __asm volatile( "cli" );
\r
473 portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
\r
474 configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
\r
479 /* Now interrupts are disabled ulCriticalNesting can be accessed
\r
480 directly. Increment ulCriticalNesting to keep a count of how many times
\r
481 portENTER_CRITICAL() has been called. */
\r
482 ulCriticalNesting++;
\r
484 /*-----------------------------------------------------------*/
\r
486 void vPortExitCritical( void )
\r
488 if( ulCriticalNesting > portNO_CRITICAL_NESTING )
\r
490 /* Decrement the nesting count as the critical section is being
\r
492 ulCriticalNesting--;
\r
494 /* If the nesting level has reached zero then all interrupt
\r
495 priorities must be re-enabled. */
\r
496 if( ulCriticalNesting == portNO_CRITICAL_NESTING )
\r
498 /* Critical nesting has reached zero so all interrupt priorities
\r
499 should be unmasked. */
\r
500 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
502 __asm volatile( "sti" );
\r
506 portAPIC_TASK_PRIORITY = 0;
\r
510 /* If a yield was pended from within the critical section then
\r
511 perform the yield now. */
\r
512 if( ulPortYieldPending != pdFALSE )
\r
514 ulPortYieldPending = pdFALSE;
\r
515 __asm volatile( portYIELD_INTERRUPT );
\r
520 /*-----------------------------------------------------------*/
\r
522 uint32_t ulPortSetInterruptMask( void )
\r
524 volatile uint32_t ulOriginalMask;
\r
526 /* Set mask to max syscall priority. */
\r
527 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
529 /* Return whether interrupts were already enabled or not. Pop adjusts
\r
530 the stack first. */
\r
531 __asm volatile( "pushf \t\n"
\r
534 : "=rm" (ulOriginalMask) :: "memory" );
\r
536 ulOriginalMask &= portEFLAGS_IF;
\r
540 /* Return original mask. */
\r
541 ulOriginalMask = portAPIC_TASK_PRIORITY;
\r
542 portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
\r
543 configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
\r
547 return ulOriginalMask;
\r
549 /*-----------------------------------------------------------*/
\r
551 void vPortClearInterruptMask( uint32_t ulNewMaskValue )
\r
553 #if( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
\r
555 if( ulNewMaskValue != pdFALSE )
\r
557 __asm volatile( "sti" );
\r
562 portAPIC_TASK_PRIORITY = ulNewMaskValue;
\r
563 configASSERT( portAPIC_TASK_PRIORITY == ulNewMaskValue );
\r
567 /*-----------------------------------------------------------*/
\r
569 #if ( configSUPPORT_FPU == 1 )
\r
571 void vPortTaskUsesFPU( void )
\r
573 /* A task is registering the fact that it needs an FPU context. Allocate a
\r
574 buffer into which the context can be saved. */
\r
575 pucPortTaskFPUContextBuffer = ( uint8_t * ) pvPortMalloc( portFPU_CONTEXT_SIZE_BYTES );
\r
576 configASSERT( pucPortTaskFPUContextBuffer );
\r
578 /* Initialise the floating point registers. */
\r
579 __asm volatile( "fninit" );
\r
582 #endif /* configSUPPORT_FPU */
\r
583 /*-----------------------------------------------------------*/
\r
585 void vPortAPICErrorHandler( void )
\r
587 /* Variable to hold the APIC error status for viewing in the debugger. */
\r
588 volatile uint32_t ulErrorStatus = 0;
\r
590 portAPIC_ERROR_STATUS = 0;
\r
591 ulErrorStatus = portAPIC_ERROR_STATUS;
\r
592 ( void ) ulErrorStatus;
\r
594 /* Force an assert. */
\r
595 configASSERT( ulCriticalNesting == ~0UL );
\r
597 /*-----------------------------------------------------------*/
\r
599 #if( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
601 void vPortCentralInterruptHandler( uint32_t ulVector )
\r
603 if( ulVector < portNUM_VECTORS )
\r
605 if( xInterruptHandlerTable[ ulVector ] != NULL )
\r
607 ( xInterruptHandlerTable[ ulVector ] )();
\r
611 /* Check for a system stack overflow. */
\r
612 configASSERT( ulSystemStack[ 10 ] == portSTACK_WORD );
\r
613 configASSERT( ulSystemStack[ 12 ] == portSTACK_WORD );
\r
614 configASSERT( ulSystemStack[ 14 ] == portSTACK_WORD );
\r
617 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
618 /*-----------------------------------------------------------*/
\r
620 #if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
\r
622 BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber )
\r
624 BaseType_t xReturn;
\r
626 xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
\r
628 if( xReturn != pdFAIL )
\r
630 /* Save the handler passed in by the application in the vector number
\r
631 passed in. The addresses are then called from the central interrupt
\r
633 xInterruptHandlerTable[ ulVectorNumber ] = pxHandler;
\r
639 #endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
\r
640 /*-----------------------------------------------------------*/
\r
642 BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber )
\r
644 BaseType_t xReturn;
\r
646 xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
\r
648 if( xReturn != pdFAIL )
\r
650 taskENTER_CRITICAL();
\r
652 /* Update the IDT to include the application defined handler. */
\r
653 prvSetInterruptGate( ( uint8_t ) ulVectorNumber, ( ISR_Handler_t ) pxHandler, portIDT_FLAGS );
\r
655 taskEXIT_CRITICAL();
\r
660 /*-----------------------------------------------------------*/
\r
662 static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber )
\r
664 BaseType_t xReturn;
\r
666 /* Check validity of vector number. */
\r
667 if( ulVectorNumber >= portNUM_VECTORS )
\r
672 else if( ulVectorNumber < portAPIC_MIN_ALLOWABLE_VECTOR )
\r
677 else if( ulVectorNumber == portAPIC_TIMER_INT_VECTOR )
\r
679 /* In use by FreeRTOS. */
\r
682 else if( ulVectorNumber == portAPIC_YIELD_INT_VECTOR )
\r
684 /* In use by FreeRTOS. */
\r
687 else if( ulVectorNumber == portAPIC_LVT_ERROR_VECTOR )
\r
689 /* In use by FreeRTOS. */
\r
692 else if( ulVectorNumber == portAPIC_SPURIOUS_INT_VECTOR )
\r
694 /* In use by FreeRTOS. */
\r
697 else if( xInterruptHandlerTable[ ulVectorNumber ] != NULL )
\r
699 /* Already in use by the application. */
\r
709 /*-----------------------------------------------------------*/
\r
711 void vGenerateYieldInterrupt( void )
\r
713 __asm volatile( portYIELD_INTERRUPT );
\r