X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=FreeRTOS%2FSource%2Fportable%2FGCC%2FARM_CA9%2Fport.c;h=16998062e5d1acaec346bd9d5f8645b8ad44ecbb;hb=b473fddd0a6a35390132c46400b32af8c7ef36e9;hp=c52b0bb66af6993f455980102568c16950ac8a40;hpb=1b49edf45586f529a2ac6bc3cf5b455009f2a89c;p=freertos diff --git a/FreeRTOS/Source/portable/GCC/ARM_CA9/port.c b/FreeRTOS/Source/portable/GCC/ARM_CA9/port.c index c52b0bb66..16998062e 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CA9/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CA9/port.c @@ -1,5 +1,5 @@ /* - FreeRTOS V8.0.0:rc1 - Copyright (C) 2014 Real Time Engineers Ltd. + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -24,10 +24,10 @@ the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - >>! NOTE: The modification to the GPL is included to allow you to distribute - >>! a combined work that includes FreeRTOS without being obliged to provide - >>! the source code for proprietary components outside of the FreeRTOS - >>! kernel. + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS @@ -110,6 +110,8 @@ #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #endif +/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in +portmacro.h. */ #ifndef configCLEAR_TICK_INTERRUPT #define configCLEAR_TICK_INTERRUPT() #endif @@ -120,7 +122,7 @@ this value. */ /* In all GICs 255 can be written to the priority mask register to unmask all (but the lowest) interrupt priority. */ -#define portUNMASK_VALUE ( 0xFF ) +#define portUNMASK_VALUE ( 0xFFUL ) /* Tasks are not created with a floating point context, but can be given a floating point context after they have been created. A variable is stored as @@ -165,8 +167,8 @@ the CPU itself before modifying certain hardware registers. */ { \ portCPU_IRQ_DISABLE(); \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ - __asm( "DSB \n" \ - "ISB \n" ); \ + __asm volatile ( "DSB \n" \ + "ISB \n" ); \ portCPU_IRQ_ENABLE(); \ } @@ -174,6 +176,15 @@ the CPU itself before modifying certain hardware registers. */ #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portBIT_0_SET ( ( uint8_t ) 0x01 ) +/* Let the user override the pre-loading of the initial LR with the address of +prvTaskExitError() in case is messes up unwinding of the stack in the +debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + /*-----------------------------------------------------------*/ /* @@ -182,6 +193,11 @@ the CPU itself before modifying certain hardware registers. */ */ extern void vPortRestoreTaskContext( void ); +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + /*-----------------------------------------------------------*/ /* A variable is used to keep track of the critical section nesting. This @@ -241,7 +257,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px pxTopOfStack--; /* Next all the registers other than the stack pointer. */ - *pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */ + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */ pxTopOfStack--; *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ pxTopOfStack--; @@ -284,6 +300,20 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px } /*-----------------------------------------------------------*/ +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( ulPortInterruptNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + BaseType_t xPortStartScheduler( void ) { uint32_t ulAPSR; @@ -354,7 +384,10 @@ uint32_t ulAPSR; /* Will only get here if xTaskStartScheduler() was called with the CPU in a non-privileged mode or the binary point register was not set to its lowest - possible value. */ + possible value. prvTaskExitError() is referenced to prevent a compiler + warning about it being defined but not referenced in the case that the user + defines their own exit address. */ + ( void ) prvTaskExitError; return 0; } /*-----------------------------------------------------------*/ @@ -376,6 +409,16 @@ void vPortEnterCritical( void ) directly. Increment ulCriticalNesting to keep a count of how many times portENTER_CRITICAL() has been called. */ ulCriticalNesting++; + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( ulCriticalNesting == 1 ) + { + configASSERT( ulPortInterruptNesting == 0 ); + } } /*-----------------------------------------------------------*/ @@ -407,9 +450,9 @@ void FreeRTOS_Tick_Handler( void ) necessary to turn off interrupts in the CPU itself while the ICCPMR is being updated. */ portCPU_IRQ_DISABLE(); - portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); - __asm( "dsb \n" - "isb \n" ); + portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); + __asm volatile ( "dsb \n" + "isb \n" ); portCPU_IRQ_ENABLE(); /* Increment the RTOS tick. */ @@ -433,7 +476,7 @@ uint32_t ulInitialFPSCR = 0; ulPortTaskHasFPUContext = pdTRUE; /* Initialise the floating point status register. */ - __asm( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) ); + __asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) ); } /*-----------------------------------------------------------*/ @@ -453,7 +496,7 @@ uint32_t ulReturn; /* Interrupt in the CPU must be turned off while the ICCPMR is being updated. */ portCPU_IRQ_DISABLE(); - if( portICCPMR_PRIORITY_MASK_REGISTER == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) + if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) { /* Interrupts were already masked. */ ulReturn = pdTRUE; @@ -461,9 +504,9 @@ uint32_t ulReturn; else { ulReturn = pdFALSE; - portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); - __asm( "dsb \n" - "isb \n" ); + portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); + __asm volatile ( "dsb \n" + "isb \n" ); } portCPU_IRQ_ENABLE(); @@ -488,12 +531,8 @@ uint32_t ulReturn; configMAX_SYSCALL_INTERRUPT_PRIORITY. FreeRTOS maintains separate thread and ISR API functions to ensure - interrupt entry is as fast and simple as possible. - - The following links provide detailed information: - http://www.freertos.org/RTOS-Cortex-M3-M4.html - http://www.freertos.org/FAQHelp.html */ - configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); + interrupt entry is as fast and simple as possible. */ + configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); /* Priority grouping: The interrupt controller (GIC) allows the bits that define each interrupt's priority to be split between bits that