/*\r
- FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd.\r
+ FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.\r
All rights reserved\r
\r
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
\r
FreeRTOS is free software; you can redistribute it and/or modify it under\r
the terms of the GNU General Public License (version 2) as published by the\r
- Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
\r
***************************************************************************\r
>>! NOTE: The modification to the GPL is included to allow you to !<<\r
/* The systick is a 24-bit counter. */\r
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )\r
\r
+/* For strict compliance with the Cortex-M spec the task start address should\r
+have bit-0 clear, as it is loaded into the PC on exit from an ISR. */\r
+#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )\r
+\r
/* A fiddle factor to estimate the number of SysTick counts that would have\r
occurred while the SysTick counter is stopped during tickless idle\r
calculations. */\r
#define portMISSED_COUNTS_FACTOR ( 45UL )\r
\r
/* Let the user override the pre-loading of the initial LR with the address of\r
-prvTaskExitError() in case is messes up unwinding of the stack in the\r
+prvTaskExitError() in case it messes up unwinding of the stack in the\r
debugger. */\r
#ifdef configTASK_RETURN_ADDRESS\r
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS\r
/*\r
* Function to enable the VFP.\r
*/\r
- static void vPortEnableVFP( void ) __attribute__ (( naked ));\r
+static void vPortEnableVFP( void ) __attribute__ (( naked ));\r
\r
/*\r
* Used to catch tasks that attempt to return from their implementing function.\r
\r
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) pxCode; /* PC */\r
+ *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */\r
pxTopOfStack--;\r
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */\r
\r
" msr basepri, r0 \n"\r
" bx r14 \n"\r
" \n"\r
- " .align 2 \n"\r
+ " .align 4 \n"\r
"pxCurrentTCBConst2: .word pxCurrentTCB \n"\r
);\r
}\r
\r
static void prvPortStartFirstTask( void )\r
{\r
+ /* Start the first task. This also clears the bit that indicates the FPU is\r
+ in use in case the FPU was used before the scheduler was started - which\r
+ would otherwise result in the unnecessary leaving of space in the SVC stack\r
+ for lazy saving of FPU registers. */\r
__asm volatile(\r
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */\r
" ldr r0, [r0] \n"\r
" ldr r0, [r0] \n"\r
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */\r
+ " mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */\r
+ " msr control, r0 \n"\r
" cpsie i \n" /* Globally enable interrupts. */\r
" cpsie f \n"\r
" dsb \n"\r
ucMaxPriorityValue <<= ( uint8_t ) 0x01;\r
}\r
\r
+ #ifdef __NVIC_PRIO_BITS\r
+ {\r
+ /* Check the CMSIS configuration that defines the number of\r
+ priority bits matches the number of priority bits actually queried\r
+ from the hardware. */\r
+ configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );\r
+ }\r
+ #endif\r
+\r
+ #ifdef configPRIO_BITS\r
+ {\r
+ /* Check the FreeRTOS configuration that defines the number of\r
+ priority bits matches the number of priority bits actually queried\r
+ from the hardware. */\r
+ configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );\r
+ }\r
+ #endif\r
+\r
/* Shift the priority group value back to its position within the AIRCR\r
register. */\r
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;\r
" vstmdbeq r0!, {s16-s31} \n"\r
" \n"\r
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */\r
- " \n"\r
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */\r
" \n"\r
" stmdb sp!, {r3} \n"\r
" mov r0, %0 \n"\r
" msr basepri, r0 \n"\r
" dsb \n"\r
- " isb \n"\r
+ " isb \n"\r
" bl vTaskSwitchContext \n"\r
" mov r0, #0 \n"\r
" msr basepri, r0 \n"\r
" \n"\r
" bx r14 \n"\r
" \n"\r
- " .align 2 \n"\r
+ " .align 4 \n"\r
"pxCurrentTCBConst: .word pxCurrentTCB \n"\r
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)\r
);\r
executes all interrupts must be unmasked. There is therefore no need to\r
save and then restore the interrupt mask value as its value is already\r
known. */\r
- ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
+ portDISABLE_INTERRUPTS();\r
{\r
/* Increment the RTOS tick. */\r
if( xTaskIncrementTick() != pdFALSE )\r
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
}\r
}\r
- portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
+ portENABLE_INTERRUPTS();\r
}\r
/*-----------------------------------------------------------*/\r
\r
\r
/* Enter a critical section but don't use the taskENTER_CRITICAL()\r
method as that will mask interrupts that should exit sleep mode. */\r
- __asm volatile( "cpsid i" );\r
+ __asm volatile( "cpsid i" ::: "memory" );\r
+ __asm volatile( "dsb" );\r
+ __asm volatile( "isb" );\r
\r
/* If a context switch is pending or a task is waiting for the scheduler\r
to be unsuspended then abandon the low power entry. */\r
\r
/* Re-enable interrupts - see comments above the cpsid instruction()\r
above. */\r
- __asm volatile( "cpsie i" );\r
+ __asm volatile( "cpsie i" ::: "memory" );\r
}\r
else\r
{\r
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );\r
if( xModifiableIdleTime > 0 )\r
{\r
- __asm volatile( "dsb" );\r
+ __asm volatile( "dsb" ::: "memory" );\r
__asm volatile( "wfi" );\r
__asm volatile( "isb" );\r
}\r
\r
/* Re-enable interrupts - see comments above the cpsid instruction()\r
above. */\r
- __asm volatile( "cpsie i" );\r
+ __asm volatile( "cpsie i" ::: "memory" );\r
\r
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )\r
{\r
\r
/* The reload value is set to whatever fraction of a single tick\r
period remains. */\r
- portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;\r
+ portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;\r
}\r
\r
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG\r
}\r
#endif /* configUSE_TICKLESS_IDLE */\r
\r
+ /* Stop and clear the SysTick. */\r
+ portNVIC_SYSTICK_CTRL_REG = 0UL;\r
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+\r
/* Configure SysTick to interrupt at the requested rate. */\r
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );\r
uint8_t ucCurrentPriority;\r
\r
/* Obtain the number of the currently executing interrupt. */\r
- __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );\r
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );\r
\r
/* Is the interrupt number a user defined interrupt? */\r
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )\r