Add tickless idle support in Cortex-M ports.

Change CCS R4 directory name.
This commit is contained in:
Richard Barry 2012-10-16 07:55:40 +00:00
parent 6ec4c7cecb
commit e03ab659f3
21 changed files with 2395 additions and 596 deletions

View file

@ -528,5 +528,17 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree ) #define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree )
#endif #endif
#ifndef portSUPPRESS_TICKS_AND_SLEEP
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )
#endif
#ifndef portPRE_SLEEP_PROCESSING
#define portPRE_SLEEP_PROCESSING()
#endif
#ifndef portPOST_SLEEP_PROCESSING
#define portPOST_SLEEP_PROCESSING()
#endif
#endif /* INC_FREERTOS_H */ #endif /* INC_FREERTOS_H */

View file

@ -1320,6 +1320,27 @@ unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask );
*/ */
void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ); void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle );
/*
* Return the amount of time, in ticks, that will pass before the kernel will
* next move a task from the Blocked state to the Running state.
*/
portTickType xTaskGetExpectedIdleTime( void );
/*
* If tickless mode is being used, or a low power mode is implemented, then
* the tick interrupt will not execute during idle periods. When this is the
* case, the tick count value maintained by the scheduler needs to be kept up
* to date with the actual execution time by being skipped forward by the by
* a time equal to the idle period.
*/
void vTaskStepTick( portTickType xTicksToJump );
/*
* Returns the number of tick interrupts that have occurred while the scheduler
* has been suspended. The count pending ticks is reset if xResetOnExit is set
* to pdTRUE.
*/
unsigned portBASE_TYPE uxTaskPendingTicksGet( portBASE_TYPE xResetOnExit );
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -0,0 +1,350 @@
/*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
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. FreeRTOS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong? *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com.
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/*-----------------------------------------------------------*/
/* Count of the critical section nesting depth. */
unsigned portLONG ulCriticalNesting = 9999;
/*-----------------------------------------------------------*/
/* Registers required to configure the RTI. */
#define portRTI_GCTRL_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC00 ) )
#define portRTI_TBCTRL_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC04 ) )
#define portRTI_COMPCTRL_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC0C ) )
#define portRTI_CNT0_FRC0_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC10 ) )
#define portRTI_CNT0_UC0_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC14 ) )
#define portRTI_CNT0_CPUC0_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC18 ) )
#define portRTI_CNT0_COMP0_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC50 ) )
#define portRTI_CNT0_UDCP0_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC54 ) )
#define portRTI_SETINTENA_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC80 ) )
#define portRTI_CLEARINTENA_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC84 ) )
#define portRTI_INTFLAG_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC88 ) )
/* Constants required to set up the initial stack of each task. */
#define portINITIAL_SPSR ( ( portSTACK_TYPE ) 0x1F )
#define portINITIAL_FPSCR ( ( portSTACK_TYPE ) 0x00 )
#define portINSTRUCTION_SIZE ( ( portSTACK_TYPE ) 0x04 )
#define portTHUMB_MODE_BIT ( ( portSTACK_TYPE ) 0x20 )
/* The number of words on the stack frame between the saved Top Of Stack and
R0 (in which the parameters are passed. */
#define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 )
/*-----------------------------------------------------------*/
/* vPortStartFirstSTask() is defined in portASM.asm */
extern void vPortStartFirstTask( void );
/*-----------------------------------------------------------*/
/* Saved as part of the task context. Set to pdFALSE if the task does not
require an FPU context. */
unsigned long ulTaskHasFPUContext = 0;
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{
portSTACK_TYPE *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack;
#if __TI_VFP_SUPPORT__
{
/* Ensure the stack is correctly aligned on exit. */
pxTopOfStack--;
}
#endif
/* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which is the start of the as
the task has not executed yet. The offset is added to make the return
address appear as it would within an IRQ ISR. */
*pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000; /* R14 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--;
#ifdef portPRELOAD_TASK_REGISTERS
{
*pxTopOfStack = ( portSTACK_TYPE ) 0x12121212; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x11111111; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x10101010; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x09090909; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x08080808; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x07070707; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x06060606; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x05050505; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x04040404; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x03030303; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x02020202; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x01010101; /* R1 */
pxTopOfStack--;
}
#else
{
pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;
}
#endif
/* Function parameters are passed in R0. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
pxTopOfStack--;
/* Set the status register for system mode, with interrupts enabled. */
*pxTopOfStack = ( portSTACK_TYPE ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR );
if( ( ( unsigned long ) pxCode & 0x01UL ) != 0x00 )
{
/* The task will start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
#ifdef __TI_VFP_SUPPORT__
{
pxTopOfStack--;
/* The last thing on the stack is the tasks ulUsingFPU value, which by
default is set to indicate that the stack frame does not include FPU
registers. */
*pxTopOfStack = pdFALSE;
}
#endif
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt(void)
{
/* Disable timer 0. */
portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
/* Use the internal counter. */
portRTI_TBCTRL_REG = 0x00000000U;
/* COMPSEL0 will use the RTIFRC0 counter. */
portRTI_COMPCTRL_REG = 0x00000000U;
/* Initialise the counter and the prescale counter registers. */
portRTI_CNT0_UC0_REG = 0x00000000U;
portRTI_CNT0_FRC0_REG = 0x00000000U;
/* Set Prescalar for RTI clock. */
portRTI_CNT0_CPUC0_REG = 0x00000001U;
portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
/* Clear interrupts. */
portRTI_INTFLAG_REG = 0x0007000FU;
portRTI_CLEARINTENA_REG = 0x00070F0FU;
/* Enable the compare 0 interrupt. */
portRTI_SETINTENA_REG = 0x00000001U;
portRTI_GCTRL_REG |= 0x00000001U;
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
portBASE_TYPE xPortStartScheduler(void)
{
/* Start the timer that generates the tick ISR. */
prvSetupTimerInterrupt();
/* Reset the critical section nesting count read to execute the first task. */
ulCriticalNesting = 0;
/* Start the first task. This is done from portASM.asm as ARM mode must be
used. */
vPortStartFirstTask();
/* Should not get here! */
return pdFAIL;
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
void vPortEndScheduler(void)
{
/* It is unlikely that the port will require this function as there
is nothing to return to. */
}
/*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */
__interrupt void vPortNonPreemptiveTick( void )
{
/* clear clock interrupt flag */
RTI->INTFLAG = 0x00000001;
/* Increment the tick count - this may make a delaying task ready
to run - but a context switch is not performed. */
vTaskIncrementTick();
}
#else
/*
**************************************************************************
* The preemptive scheduler ISR is written in assembler and can be found
* in the portASM.asm file. This will only get used if portUSE_PREEMPTION
* is set to 1 in portmacro.h
**************************************************************************
*/
void vPortPreemptiveTick( void );
#endif
/*-----------------------------------------------------------*/
/*
* Disable interrupts, and keep a count of the nesting depth.
*/
void vPortEnterCritical( void )
{
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */
ulCriticalNesting++;
}
/*-----------------------------------------------------------*/
/*
* Decrement the critical nesting count, and if it has reached zero, re-enable
* interrupts.
*/
void vPortExitCritical( void )
{
if( ulCriticalNesting > 0 )
{
/* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be
re-enabled. */
if( ulCriticalNesting == 0 )
{
/* Enable interrupts as per portENABLE_INTERRUPTS(). */
portENABLE_INTERRUPTS();
}
}
}
/*-----------------------------------------------------------*/
#if __TI_VFP_SUPPORT__
void vPortTaskUsesFPU( void )
{
extern void vPortInitialiseFPSCR( void );
/* A task is registering the fact that it needs an FPU context. Set the
FPU flag (saved as part of the task context. */
ulTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */
vPortInitialiseFPSCR();
}
#endif /* __TI_VFP_SUPPORT__ */
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,263 @@
;/*
; FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
;
;
; ***************************************************************************
; * *
; * FreeRTOS tutorial books are available in pdf and paperback. *
; * Complete, revised, and edited pdf reference manuals are also *
; * available. *
; * *
; * Purchasing FreeRTOS documentation will not only help you, by *
; * ensuring you get running as quickly as possible and with an *
; * in-depth knowledge of how to use FreeRTOS, it will also help *
; * the FreeRTOS project to continue with its mission of providing *
; * professional grade, cross platform, de facto standard solutions *
; * for microcontrollers - completely free of charge! *
; * *
; * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
; * *
; * Thank you for using FreeRTOS, and thank you for your support! *
; * *
; ***************************************************************************
;
;
; This file is part of the FreeRTOS distribution.
;
; FreeRTOS is free software; you can redistribute it and/or modify it under
; 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. FreeRTOS is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
; more details. You should have received a copy of the GNU General Public
; License and the FreeRTOS license exception along with FreeRTOS; if not it
; can be viewed here: http://www.freertos.org/a00114.html and also obtained
; by writing to Richard Barry, contact details for whom are available on the
; FreeRTOS WEB site.
;
; 1 tab == 4 spaces!
;
; http://www.FreeRTOS.org - Documentation, latest information, license and
; contact details.
;
; http://www.SafeRTOS.com - A version that is certified for use in safety
; critical systems.
;
; http://www.OpenRTOS.com - Commercial support, development, porting,
; licensing and training services.
;*/
.text
.arm
.ref vTaskSwitchContext
.ref vTaskIncrementTick
.ref ulTaskHasFPUContext
.ref pxCurrentTCB
;/*-----------------------------------------------------------*/
;
; Save Task Context
;
portSAVE_CONTEXT .macro
DSB
; Push R0 as we are going to use it
STMDB SP!, {R0}
; Set R0 to point to the task stack pointer.
STMDB SP,{SP}^
SUB SP, SP, #4
LDMIA SP!,{R0}
; Push the return address onto the stack.
STMDB R0!, {LR}
; Now LR has been saved, it can be used instead of R0.
MOV LR, R0
; Pop R0 so it can be saved onto the task stack.
LDMIA SP!, {R0}
; Push all the system mode registers onto the task stack.
STMDB LR,{R0-LR}^
SUB LR, LR, #60
; Push the SPSR onto the task stack.
MRS R0, SPSR
STMDB LR!, {R0}
.if (__TI_VFP_SUPPORT__)
;Determine if the task maintains an FPU context.
LDR R0, ulFPUContextConst
LDR R0, [R0]
; Test the flag
CMP R0, #0
; If the task is not using a floating point context then skip the
; saving of the FPU registers.
BEQ PC+3
FSTMDBD LR!, {D0-D15}
FMRX R1, FPSCR
STMFD LR!, {R1}
; Save the flag
STMDB LR!, {R0}
.endif
; Store the new top of stack for the task.
LDR R0, pxCurrentTCBConst
LDR R0, [R0]
STR LR, [R0]
.endm
;/*-----------------------------------------------------------*/
;
; Restore Task Context
;
portRESTORE_CONTEXT .macro
LDR R0, pxCurrentTCBConst
LDR R0, [R0]
LDR LR, [R0]
.if (__TI_VFP_SUPPORT__)
; The floating point context flag is the first thing on the stack.
LDR R0, ulFPUContextConst
LDMFD LR!, {R1}
STR R1, [R0]
; Test the flag
CMP R1, #0
; If the task is not using a floating point context then skip the
; VFP register loads.
BEQ PC+3
; Restore the floating point context.
LDMFD LR!, {R0}
FLDMIAD LR!, {D0-D15}
FMXR FPSCR, R0
.endif
; Get the SPSR from the stack.
LDMFD LR!, {R0}
MSR SPSR_CF, R0
; Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^
; Restore the return address.
LDR LR, [LR, #+60]
; And return - correcting the offset in the LR to obtain the
; correct address.
SUBS PC, LR, #4
.endm
;/*-----------------------------------------------------------*/
; Start the first task by restoring its context.
.def vPortStartFirstTask
vPortStartFirstTask:
portRESTORE_CONTEXT
;/*-----------------------------------------------------------*/
; Yield to another task.
.def vPortYieldProcessor
vPortYieldProcessor:
; Within an IRQ ISR the link register has an offset from the true return
; address. SWI doesn't do this. Add the offset manually so the ISR
; return code can be used.
ADD LR, LR, #4
; First save the context of the current task.
portSAVE_CONTEXT
; Select the next task to execute. */
BL vTaskSwitchContext
; Restore the context of the task selected to execute.
portRESTORE_CONTEXT
;/*-----------------------------------------------------------*/
; Yield to another task from within the FreeRTOS API
.def vPortYeildWithinAPI
vPortYeildWithinAPI:
; Save the context of the current task.
portSAVE_CONTEXT
; Clear SSI flag.
MOVW R0, #0xFFF4
MOVT R0, #0xFFFF
LDR R0, [R0]
; Select the next task to execute. */
BL vTaskSwitchContext
; Restore the context of the task selected to execute.
portRESTORE_CONTEXT
;/*-----------------------------------------------------------*/
; Preemptive Tick
.def vPortPreemptiveTick
vPortPreemptiveTick:
; Save the context of the current task.
portSAVE_CONTEXT
; Clear interrupt flag
MOVW R0, #0xFC88
MOVT R0, #0xFFFF
MOV R1, #1
STR R1, [R0]
; Increment the tick count, making any adjustments to the blocked lists
; that may be necessary.
BL vTaskIncrementTick
; Select the next task to execute.
BL vTaskSwitchContext
; Restore the context of the task selected to execute.
portRESTORE_CONTEXT
;-------------------------------------------------------------------------------
.def ulPortCountLeadingZeros
ulPortCountLeadingZeros:
CLZ R0, R0
BX LR
;-------------------------------------------------------------------------------
.if (__TI_VFP_SUPPORT__)
.def vPortInitialiseFPSCR
vPortInitialiseFPSCR:
MOV R0, #0
FMXR FPSCR, R0
BX LR
.endif ;__TI_VFP_SUPPORT__
pxCurrentTCBConst .word pxCurrentTCB
ulFPUContextConst .word ulTaskHasFPUContext
;-------------------------------------------------------------------------------

View file

@ -0,0 +1,145 @@
/*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
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. FreeRTOS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong? *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com.
*/
#ifndef __PORTMACRO_H__
#define __PORTMACRO_H__
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned long
#define portBASE_TYPE long
#if (configUSE_16_BIT_TICKS == 1)
typedef unsigned portSHORT portTickType;
#define portMAX_DELAY (portTickType) 0xFFFF
#else
typedef unsigned portLONG portTickType;
#define portMAX_DELAY (portTickType) 0xFFFFFFFFF
#endif
/* Architecture specifics. */
#define portSTACK_GROWTH (-1)
#define portTICK_RATE_MS ((portTickType) 1000 / configTICK_RATE_HZ)
#define portBYTE_ALIGNMENT 8
/* Critical section handling. */
extern void vPortEnterCritical(void);
extern void vPortExitCritical(void);
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() asm( " CPSID I" )
#define portENABLE_INTERRUPTS() asm( " CPSIE I" )
/* Scheduler utilities. */
#define portYIELD() _call_swi( 0 )
#define portSYS_SSIR1_REG ( * ( ( volatile unsigned long * ) 0xFFFFFFB0 ) )
#define portSYS_SSIR1_SSKEY ( 0x7500UL )
#define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; }
#define portYIELD_FROM_ISR() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; }
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Generic helper function. */
unsigned long ulPortCountLeadingZeros( unsigned long ulBitmap );
/* Check the configuration. */
#if( configMAX_PRIORITIES > 32 )
#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.
#endif
/* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
#endif /* __PORTMACRO_H__ */

View file

@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,17 +50,17 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
@ -79,17 +79,35 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#define configKERNEL_INTERRUPT_PRIORITY 255 #define configKERNEL_INTERRUPT_PRIORITY 255
#endif #endif
/* Constants required to manipulate the NVIC. */ #ifndef configSYSTICK_CLOCK_HZ
#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) static const unsigned long ulStoppedTimerCompensation = 45UL;
#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) #endif
#define portNVIC_SYSTICK_CLK 0x00000004 #else /* configSYSTICK_CLOCK_HZ */
#define portNVIC_SYSTICK_INT 0x00000002 #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_SYSTICK_ENABLE 0x00000001 /* Assumes the SysTick clock is slower than the CPU clock. */
#define portNVIC_PENDSVSET 0x10000000 static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) #endif
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) #endif /* configSYSTICK_CLOCK_HZ */
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
@ -119,6 +137,22 @@ void vPortSVCHandler( void ) __attribute__ (( naked ));
*/ */
static void prvPortStartFirstTask( void ) __attribute__ (( naked )); static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/*-----------------------------------------------------------*/
/*
* The number of SysTick increments that make up one tick period.
*/
static unsigned long ulTimerReloadValueForOneTick = 0;
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if configUSE_TICKLESS_IDLE == 1
static unsigned long xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -180,13 +214,13 @@ static void prvPortStartFirstTask( void )
*/ */
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
/* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
@ -213,7 +247,7 @@ void vPortEndScheduler( void )
void vPortYieldFromISR( void ) void vPortYieldFromISR( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -234,6 +268,34 @@ void vPortExitCritical( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( naked )) unsigned long ulPortSetInterruptMask( void )
{
__asm volatile \
( \
" mrs r0, basepri \n" \
" mov r1, %0 \n" \
" msr basepri, r1 \n" \
" bx lr \n" \
:: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1" \
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
return 0;
}
/*-----------------------------------------------------------*/
__attribute__(( naked )) void vPortClearInterruptMask( unsigned long ulNewMaskValue )
{
__asm volatile \
( \
" msr basepri, r0 \n" \
" bx lr \n" \
:::"r0" \
);
}
/*-----------------------------------------------------------*/
void xPortPendSVHandler( void ) void xPortPendSVHandler( void )
{ {
/* This is a naked function. */ /* This is a naked function. */
@ -271,30 +333,142 @@ void xPortPendSVHandler( void )
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
unsigned long ulDummy;
/* If using preemption, also force a context switch. */ /* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
#endif #endif
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); #if configUSE_TICKLESS_IDLE == 1
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
#endif
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{ {
vTaskIncrementTick(); vTaskIncrementTick();
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1
__attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;
/* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods, and the fraction of a tick period is
accounted for later. */
ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
/* If a context switch is pending then abandon the low power entry as
the context switch might have been pended by an external interrupt that
requires processing. */
if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )
{
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
}
else
{
/* Adjust the reload value to take into account that the current
time slice is already partially complete. */
ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. */
portPRE_SLEEP_PROCESSING();
__asm volatile( "wfi" );
portPOST_SLEEP_PROCESSING();
/* Stop SysTick. Again, the time the SysTick is stopped for is
accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
/* The tick interrupt has already executed, and the SysTick
count reloaded with the portNVIC_SYSTICK_LOAD_REG value.
Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of
this tick period. */
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be
processed as soon as this function exits, the tick value
maintained by the tick is stepped forward by one less than the
time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted. */
ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/* /*
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
void prvSetupTimerInterrupt( void ) void prvSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */
ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
#if configUSE_TICKLESS_IDLE == 1
xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
#endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -109,62 +109,36 @@ extern "C" {
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYieldFromISR( void ); extern void vPortYieldFromISR( void );
#define portYIELD() vPortYieldFromISR() #define portYIELD() vPortYieldFromISR()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
/*
* Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other
* registers. r0 is clobbered.
*/
#define portSET_INTERRUPT_MASK() \
__asm volatile \
( \
" mov r0, %0 \n" \
" msr basepri, r0 \n" \
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0" \
)
/*
* Set basepri back to 0 without effective other registers.
* r0 is clobbered. FAQ: Setting BASEPRI to 0 is not a bug. Please see
* http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing.
*/
#define portCLEAR_INTERRUPT_MASK() \
__asm volatile \
( \
" mov r0, #0 \n" \
" msr basepri, r0 \n" \
:::"r0" \
)
/* FAQ: Setting BASEPRI to 0 in portCLEAR_INTERRUPT_MASK_FROM_ISR() is not a
bug. Please see http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before
disagreeing. */
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern unsigned long ulPortSetInterruptMask( void );
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK() extern void vPortClearInterruptMask( unsigned long ulNewMaskValue );
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK() #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portENTER_CRITICAL() vPortEnterCritical() #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
#define portEXIT_CRITICAL() vPortExitCritical() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
#define portNOP() /* Tickless idle/low power functionality. */
extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
/*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Generic helper function. */ /* Generic helper function. */
@ -189,8 +163,12 @@ extern void vPortExitCritical( void );
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* taskRECORD_READY_PRIORITY */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
/* portNOP() is not required by this port. */
#define portNOP()
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,17 +50,17 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
@ -76,17 +76,35 @@
#error This port can only be used when the project options are configured to enable hardware floating point support. #error This port can only be used when the project options are configured to enable hardware floating point support.
#endif #endif
/* Constants required to manipulate the NVIC. */ #ifndef configSYSTICK_CLOCK_HZ
#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long * ) 0xe000e010 ) #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long * ) 0xe000e014 ) #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_INT_CTRL ( ( volatile unsigned long * ) 0xe000ed04 ) static const unsigned long ulStoppedTimerCompensation = 45UL;
#define portNVIC_SYSPRI2 ( ( volatile unsigned long * ) 0xe000ed20 ) #endif
#define portNVIC_SYSTICK_CLK 0x00000004 #else /* configSYSTICK_CLOCK_HZ */
#define portNVIC_SYSTICK_INT 0x00000002 #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_SYSTICK_ENABLE 0x00000001 /* Assumes the SysTick clock is slower than the CPU clock. */
#define portNVIC_PENDSVSET 0x10000000 static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) #endif
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) #endif /* configSYSTICK_CLOCK_HZ */
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */ #define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
@ -119,13 +137,28 @@ void vPortSVCHandler( void ) __attribute__ (( naked ));
/* /*
* Start first task is a separate function so it can be tested in isolation. * Start first task is a separate function so it can be tested in isolation.
*/ */
static void vPortStartFirstTask( void ) __attribute__ (( naked )); static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/* /*
* Function to enable the VFP. * Function to enable the VFP.
*/ */
static void vPortEnableVFP( void ) __attribute__ (( naked )); static void vPortEnableVFP( void ) __attribute__ (( naked ));
/*-----------------------------------------------------------*/
/*
* The number of SysTick increments that make up one tick period.
*/
static unsigned long ulTimerReloadValueForOneTick = 0;
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if configUSE_TICKLESS_IDLE == 1
static unsigned long xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -180,7 +213,7 @@ void vPortSVCHandler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void vPortStartFirstTask( void ) static void prvPortStartFirstTask( void )
{ {
__asm volatile( __asm volatile(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
@ -199,13 +232,13 @@ static void vPortStartFirstTask( void )
*/ */
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
@ -221,7 +254,7 @@ portBASE_TYPE xPortStartScheduler( void )
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
/* Start the first task. */ /* Start the first task. */
vPortStartFirstTask(); prvPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
@ -238,7 +271,7 @@ void vPortEndScheduler( void )
void vPortYieldFromISR( void ) void vPortYieldFromISR( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -259,6 +292,34 @@ void vPortExitCritical( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( naked )) unsigned long ulPortSetInterruptMask( void )
{
__asm volatile \
( \
" mrs r0, basepri \n" \
" mov r1, %0 \n" \
" msr basepri, r1 \n" \
" bx lr \n" \
:: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1" \
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
return 0;
}
/*-----------------------------------------------------------*/
__attribute__(( naked )) void vPortClearInterruptMask( unsigned long ulNewMaskValue )
{
__asm volatile \
( \
" msr basepri, r0 \n" \
" bx lr \n" \
:::"r0" \
);
}
/*-----------------------------------------------------------*/
void xPortPendSVHandler( void ) void xPortPendSVHandler( void )
{ {
/* This is a naked function. */ /* This is a naked function. */
@ -307,30 +368,143 @@ void xPortPendSVHandler( void )
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
unsigned long ulDummy;
/* If using preemption, also force a context switch. */ /* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
#endif #endif
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); #if configUSE_TICKLESS_IDLE == 1
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
#endif
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{ {
vTaskIncrementTick(); vTaskIncrementTick();
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1
__attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;
/* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods, and the fraction of a tick period is
accounted for later. */
ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
/* If a context switch is pending then abandon the low power entry as
the context switch might have been pended by an external interrupt that
requires processing. */
if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )
{
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
}
else
{
/* Adjust the reload value to take into account that the current
time slice is already partially complete. */
ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. */
portPRE_SLEEP_PROCESSING();
__asm volatile( "wfi" );
portPOST_SLEEP_PROCESSING();
/* Stop SysTick. Again, the time the SysTick is stopped for is
accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
/* The tick interrupt has already executed, and the SysTick
count reloaded with the portNVIC_SYSTICK_LOAD_REG value.
Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of
this tick period. */
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be
processed as soon as this function exits, the tick value
maintained by the tick is stepped forward by one less than the
time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted. */
ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/* /*
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
void prvSetupTimerInterrupt( void ) void prvSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */
ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
#if configUSE_TICKLESS_IDLE == 1
xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
#endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -115,48 +115,17 @@ extern void vPortYieldFromISR( void );
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
/*
* Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other
* registers. r0 is clobbered.
*/
#define portSET_INTERRUPT_MASK() \
__asm volatile \
( \
" mov r0, %0 \n" \
" msr basepri, r0 \n" \
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0" \
)
/*
* Set basepri back to 0 without effective other registers.
* r0 is clobbered. FAQ: Setting BASEPRI to 0 is not a bug. Please see
* http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing.
*/
#define portCLEAR_INTERRUPT_MASK() \
__asm volatile \
( \
" mov r0, #0 \n" \
" msr basepri, r0 \n" \
:::"r0" \
)
/* FAQ: Setting BASEPRI to 0 in portCLEAR_INTERRUPT_MASK_FROM_ISR() is not a
bug. Please see http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before
disagreeing. */
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern unsigned long ulPortSetInterruptMask( void );
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK() extern void vPortClearInterruptMask( unsigned long ulNewMaskValue );
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK() #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portENTER_CRITICAL() vPortEnterCritical() #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
#define portEXIT_CRITICAL() vPortExitCritical() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/* There are an uneven number of items on the initial stack, so /* There are an uneven number of items on the initial stack, so
portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
@ -164,16 +133,23 @@ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
#define portNOP() /* Tickless idle/low power functionality. */
extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
/*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Generic helper function. */ /* Generic helper function. */
__attribute__( ( always_inline ) ) static inline unsigned char ucPortCountLeadingZeros( ulBitmap ) __attribute__( ( always_inline ) ) static inline unsigned char ucPortCountLeadingZeros( unsigned long ulBitmap )
{ {
unsigned char ucReturn; unsigned char ucReturn;
@ -194,8 +170,12 @@ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* taskRECORD_READY_PRIORITY */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
/* portNOP() is not required by this port. */
#define portNOP()
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,6 +1,6 @@
/* /*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd. FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
*************************************************************************** ***************************************************************************
* * * *
@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,17 +50,17 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
@ -76,15 +76,33 @@
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif #endif
/* Constants required to manipulate the NVIC. */ #ifndef configSYSTICK_CLOCK_HZ
#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) static const unsigned long ulStoppedTimerCompensation = 45UL;
#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) #endif
#define portNVIC_SYSTICK_CLK 0x00000004 #else /* configSYSTICK_CLOCK_HZ */
#define portNVIC_SYSTICK_INT 0x00000002 #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_SYSTICK_ENABLE 0x00000001 /* Assumes the SysTick clock is slower than the CPU clock. */
#define portNVIC_PENDSVSET 0x10000000 static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
#endif
#endif /* configSYSTICK_CLOCK_HZ */
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) #define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) #define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )
@ -119,6 +137,21 @@ extern void vPortStartFirstTask( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*
* The number of SysTick increments that make up one tick period.
*/
static unsigned long ulTimerReloadValueForOneTick = 0;
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if configUSE_TICKLESS_IDLE == 1
static unsigned long xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
@ -146,13 +179,13 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0; uxCriticalNesting = 0;
@ -174,7 +207,7 @@ void vPortEndScheduler( void )
void vPortYieldFromISR( void ) void vPortYieldFromISR( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -197,30 +230,142 @@ void vPortExitCritical( void )
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
unsigned long ulDummy;
/* If using preemption, also force a context switch. */ /* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
#endif #endif
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); #if configUSE_TICKLESS_IDLE == 1
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
#endif
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{ {
vTaskIncrementTick(); vTaskIncrementTick();
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;
/* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods, and the fraction of a tick period is
accounted for later. */
ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
/* If a context switch is pending then abandon the low power entry as
the context switch might have been pended by an external interrupt that
requires processing. */
if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )
{
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
}
else
{
/* Adjust the reload value to take into account that the current
time slice is already partially complete. */
ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. */
portPRE_SLEEP_PROCESSING();
__WFI();
portPOST_SLEEP_PROCESSING();
/* Stop SysTick. Again, the time the SysTick is stopped for is
accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
/* The tick interrupt has already executed, and the SysTick
count reloaded with the portNVIC_SYSTICK_LOAD_REG value.
Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of
this tick period. */
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be
processed as soon as this function exits, the tick value
maintained by the tick is stepped forward by one less than the
time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted. */
ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/* /*
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
void prvSetupTimerInterrupt( void ) void prvSetupTimerInterrupt( void )
{ {
/* Configure the constants required to setup the tick interrupt. */
ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
#if configUSE_TICKLESS_IDLE == 1
xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
#endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,51 +50,36 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
#include <FreeRTOSConfig.h> #include <FreeRTOSConfig.h>
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
defined. The value zero should also ensure backward compatibility.
FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
#ifndef configKERNEL_INTERRUPT_PRIORITY
#define configKERNEL_INTERRUPT_PRIORITY 0
#endif
RSEG CODE:CODE(2) RSEG CODE:CODE(2)
thumb thumb
EXTERN vPortYieldFromISR
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
PUBLIC vSetMSP
PUBLIC xPortPendSVHandler PUBLIC xPortPendSVHandler
PUBLIC vPortSetInterruptMask PUBLIC ulPortSetInterruptMask
PUBLIC vPortClearInterruptMask PUBLIC vPortClearInterruptMask
PUBLIC vPortSVCHandler PUBLIC vPortSVCHandler
PUBLIC vPortStartFirstTask PUBLIC vPortStartFirstTask
/*-----------------------------------------------------------*/
vSetMSP
msr msp, r0
bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xPortPendSVHandler: xPortPendSVHandler:
@ -122,28 +107,26 @@ xPortPendSVHandler:
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortSetInterruptMask: ulPortSetInterruptMask:
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mrs r0, basepri
msr BASEPRI, r0 mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1
bx r14 bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortClearInterruptMask: vPortClearInterruptMask:
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see msr basepri, r0
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
mov r0, #0
msr BASEPRI, r0
bx r14 bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortSVCHandler; vPortSVCHandler:
/* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB ldr r3, =pxCurrentTCB
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] ldr r0, [r1]
/* Pop the core registers. */
ldmia r0!, {r4-r11} ldmia r0!, {r4-r11}
msr psp, r0 msr psp, r0
mov r0, #0 mov r0, #0

View file

@ -106,15 +106,13 @@ extern "C" {
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYieldFromISR( void ); extern void vPortYieldFromISR( void );
#define portYIELD() vPortYieldFromISR() #define portYIELD() vPortYieldFromISR()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
@ -131,32 +129,36 @@ extern void vPortYieldFromISR( void );
#include <intrinsics.h> #include <intrinsics.h>
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) )
#endif /* taskRECORD_READY_PRIORITY */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern void vPortSetInterruptMask( void );
extern void vPortClearInterruptMask( void );
#define portDISABLE_INTERRUPTS() vPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask()
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;vPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask();(void)x
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern unsigned long ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( unsigned long ulNewMask );
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x )
/*-----------------------------------------------------------*/
/* Tickless/low power functionality. */
extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
/* portNOP() is not required by this port. */
#define portNOP() #define portNOP()
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -1,6 +1,6 @@
/* /*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd. FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
*************************************************************************** ***************************************************************************
* * * *
@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,17 +50,17 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
@ -80,15 +80,33 @@
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif #endif
/* Constants required to manipulate the NVIC. */ #ifndef configSYSTICK_CLOCK_HZ
#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long * ) 0xe000e010 ) #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long * ) 0xe000e014 ) #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_INT_CTRL ( ( volatile unsigned long * ) 0xe000ed04 ) static const unsigned long ulStoppedTimerCompensation = 45UL;
#define portNVIC_SYSPRI2 ( ( volatile unsigned long * ) 0xe000ed20 ) #endif
#define portNVIC_SYSTICK_CLK 0x00000004 #else /* configSYSTICK_CLOCK_HZ */
#define portNVIC_SYSTICK_INT 0x00000002 #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_SYSTICK_ENABLE 0x00000001 /* Assumes the SysTick clock is slower than the CPU clock. */
#define portNVIC_PENDSVSET 0x10000000 static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
#endif
#endif /* configSYSTICK_CLOCK_HZ */
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) #define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) #define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )
@ -120,12 +138,27 @@ void xPortSysTickHandler( void );
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
/* /*
* Functions defined in portasm.s to enable the VFP. * Turn the VFP on.
*/ */
extern void vPortEnableVFP( void ); extern void vPortEnableVFP( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*
* The number of SysTick increments that make up one tick period.
*/
static unsigned long ulTimerReloadValueForOneTick = 0;
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if configUSE_TICKLESS_IDLE == 1
static unsigned long xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
@ -133,17 +166,17 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
interrupt. */ interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit /* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */ of interrupts, and to ensure alignment. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = 0; /* LR */
/* Save code space by skipping register initialisation. */ /* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
@ -154,7 +187,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
*pxTopOfStack = portINITIAL_EXEC_RETURN; *pxTopOfStack = portINITIAL_EXEC_RETURN;
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -165,22 +198,22 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0; uxCriticalNesting = 0;
/* Ensure the VFP is enabled - it should be anyway. */ /* Ensure the VFP is enabled - it should be anyway. */
vPortEnableVFP(); vPortEnableVFP();
/* Lazy save always. */ /* Lazy save always. */
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
/* Start the first task. */ /* Start the first task. */
vPortStartFirstTask(); vPortStartFirstTask();
@ -199,7 +232,7 @@ void vPortEndScheduler( void )
void vPortYieldFromISR( void ) void vPortYieldFromISR( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -222,30 +255,142 @@ void vPortExitCritical( void )
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
unsigned long ulDummy;
/* If using preemption, also force a context switch. */ /* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
#endif #endif
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); #if configUSE_TICKLESS_IDLE == 1
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
#endif
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{ {
vTaskIncrementTick(); vTaskIncrementTick();
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;
/* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods, and the fraction of a tick period is
accounted for later. */
ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
/* If a context switch is pending then abandon the low power entry as
the context switch might have been pended by an external interrupt that
requires processing. */
if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )
{
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
}
else
{
/* Adjust the reload value to take into account that the current
time slice is already partially complete. */
ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. */
portPRE_SLEEP_PROCESSING();
__WFI();
portPOST_SLEEP_PROCESSING();
/* Stop SysTick. Again, the time the SysTick is stopped for is
accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
/* The tick interrupt has already executed, and the SysTick
count reloaded with the portNVIC_SYSTICK_LOAD_REG value.
Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of
this tick period. */
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be
processed as soon as this function exits, the tick value
maintained by the tick is stepped forward by one less than the
time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted. */
ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/* /*
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
void prvSetupTimerInterrupt( void ) void prvSetupTimerInterrupt( void )
{ {
/* Configure the constants required to setup the tick interrupt. */
ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
#if configUSE_TICKLESS_IDLE == 1
xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
#endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -73,7 +73,7 @@
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
PUBLIC xPortPendSVHandler PUBLIC xPortPendSVHandler
PUBLIC vPortSetInterruptMask PUBLIC ulPortSetInterruptMask
PUBLIC vPortClearInterruptMask PUBLIC vPortClearInterruptMask
PUBLIC vPortSVCHandler PUBLIC vPortSVCHandler
PUBLIC vPortStartFirstTask PUBLIC vPortStartFirstTask
@ -127,20 +127,16 @@ xPortPendSVHandler:
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortSetInterruptMask: ulPortSetInterruptMask:
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mrs r0, basepri
msr BASEPRI, r0 mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1
bx r14 bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortClearInterruptMask: vPortClearInterruptMask:
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see msr basepri, r0
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
mov r0, #0
msr BASEPRI, r0
bx r14 bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -159,7 +155,7 @@ vPortSVCHandler:
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortStartFirstTask: vPortStartFirstTask
/* Use the NVIC offset register to locate the stack. */ /* Use the NVIC offset register to locate the stack. */
ldr r0, =0xE000ED08 ldr r0, =0xE000ED08
ldr r0, [r0] ldr r0, [r0]

View file

@ -106,15 +106,13 @@ extern "C" {
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYieldFromISR( void ); extern void vPortYieldFromISR( void );
#define portYIELD() vPortYieldFromISR() #define portYIELD() vPortYieldFromISR()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
@ -131,36 +129,42 @@ extern void vPortYieldFromISR( void );
#include <intrinsics.h> #include <intrinsics.h>
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) )
#endif /* taskRECORD_READY_PRIORITY */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern void vPortSetInterruptMask( void ); extern unsigned long ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( void ); extern void vPortClearInterruptMask( unsigned long ulNewMask );
#define portDISABLE_INTERRUPTS() vPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask() #define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x )
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */ /*-----------------------------------------------------------*/
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;vPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask();(void)x
/* There are an uneven number of items on the initial stack, so /* There are an uneven number of items on the initial stack, so
portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
#define portALIGNMENT_ASSERT_pxCurrentTCB ( void ) #define portALIGNMENT_ASSERT_pxCurrentTCB ( void )
/*-----------------------------------------------------------*/
/* Tickless/low power functionality. */
extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
/* portNOP() is not required by this port. */
#define portNOP() #define portNOP()
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -1,6 +1,6 @@
/* /*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd. FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
*************************************************************************** ***************************************************************************
* * * *
@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,17 +50,17 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
@ -69,7 +69,7 @@
* The simplest possible implementation of pvPortMalloc(). Note that this * The simplest possible implementation of pvPortMalloc(). Note that this
* implementation does NOT allow allocated memory to be freed again. * implementation does NOT allow allocated memory to be freed again.
* *
* See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the
* memory management pages of http://www.FreeRTOS.org for more information. * memory management pages of http://www.FreeRTOS.org for more information.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -92,7 +92,7 @@ static union xRTOS_HEAP
volatile portDOUBLE dDummy; volatile portDOUBLE dDummy;
#else #else
volatile unsigned long ulDummy; volatile unsigned long ulDummy;
#endif #endif
unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
} xHeap; } xHeap;
@ -101,7 +101,7 @@ static size_t xNextFreeByte = ( size_t ) 0;
void *pvPortMalloc( size_t xWantedSize ) void *pvPortMalloc( size_t xWantedSize )
{ {
void *pvReturn = NULL; void *pvReturn = NULL;
/* Ensure that blocks are always aligned to the required number of bytes. */ /* Ensure that blocks are always aligned to the required number of bytes. */
#if portBYTE_ALIGNMENT != 1 #if portBYTE_ALIGNMENT != 1
@ -121,11 +121,11 @@ void *pvReturn = NULL;
/* Return the next free byte then increment the index past this /* Return the next free byte then increment the index past this
block. */ block. */
pvReturn = &( xHeap.ucHeap[ xNextFreeByte ] ); pvReturn = &( xHeap.ucHeap[ xNextFreeByte ] );
xNextFreeByte += xWantedSize; xNextFreeByte += xWantedSize;
} }
} }
xTaskResumeAll(); xTaskResumeAll();
#if( configUSE_MALLOC_FAILED_HOOK == 1 ) #if( configUSE_MALLOC_FAILED_HOOK == 1 )
{ {
if( pvReturn == NULL ) if( pvReturn == NULL )
@ -134,7 +134,7 @@ void *pvReturn = NULL;
vApplicationMallocFailedHook(); vApplicationMallocFailedHook();
} }
} }
#endif #endif
return pvReturn; return pvReturn;
} }
@ -143,10 +143,10 @@ void *pvReturn = NULL;
void vPortFree( void *pv ) void vPortFree( void *pv )
{ {
/* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and /* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and
heap_4.c for alternative implementations, and the memory management pages of heap_4.c for alternative implementations, and the memory management pages of
http://www.FreeRTOS.org for more information. */ http://www.FreeRTOS.org for more information. */
( void ) pv; ( void ) pv;
/* Force an assert as it is invalid to call this function. */ /* Force an assert as it is invalid to call this function. */
configASSERT( pv == NULL ); configASSERT( pv == NULL );
} }

View file

@ -1,6 +1,6 @@
/* /*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd. FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
*************************************************************************** ***************************************************************************
* * * *
@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,17 +50,17 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
@ -80,17 +80,35 @@
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif #endif
/* Constants required to manipulate the NVIC. */ #ifndef configSYSTICK_CLOCK_HZ
#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) static const unsigned long ulStoppedTimerCompensation = 45UL;
#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) #endif
#define portNVIC_SYSTICK_CLK 0x00000004 #else /* configSYSTICK_CLOCK_HZ */
#define portNVIC_SYSTICK_INT 0x00000002 #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_SYSTICK_ENABLE 0x00000001 /* Assumes the SysTick clock is slower than the CPU clock. */
#define portNVIC_PENDSVSET 0x10000000 static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) #endif
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) #endif /* configSYSTICK_CLOCK_HZ */
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
@ -99,7 +117,7 @@
variable. */ variable. */
static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
/* /*
* Setup the timer to generate the tick interrupts. * Setup the timer to generate the tick interrupts.
*/ */
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
@ -114,12 +132,27 @@ void vPortSVCHandler( void );
/* /*
* Start first task is a separate function so it can be tested in isolation. * Start first task is a separate function so it can be tested in isolation.
*/ */
void vPortStartFirstTask( void ); static void prvStartFirstTask( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * The number of SysTick increments that make up one tick period.
*/
static unsigned long ulTimerReloadValueForOneTick = 0;
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if configUSE_TICKLESS_IDLE == 1
static unsigned long xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/ */
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{ {
@ -143,15 +176,15 @@ __asm void vPortSVCHandler( void )
{ {
PRESERVE8 PRESERVE8
ldr r3, =pxCurrentTCB /* Restore the context. */ ldr r3, =pxCurrentTCB /* Restore the context. */
ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
msr psp, r0 /* Restore the task stack pointer. */ msr psp, r0 /* Restore the task stack pointer. */
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
orr r14, #0xd orr r14, #0xd
bx r14 bx r14
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -173,24 +206,24 @@ __asm void vPortStartFirstTask( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
/* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0; uxCriticalNesting = 0;
/* Start the first task. */ /* Start the first task. */
vPortStartFirstTask(); prvStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
@ -207,7 +240,7 @@ void vPortEndScheduler( void )
void vPortYieldFromISR( void ) void vPortYieldFromISR( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -236,26 +269,26 @@ __asm void xPortPendSVHandler( void )
PRESERVE8 PRESERVE8
mrs r0, psp mrs r0, psp
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
ldr r2, [r3] ldr r2, [r3]
stmdb r0!, {r4-r11} /* Save the remaining registers. */ stmdb r0!, {r4-r11} /* Save the remaining registers. */
str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ str r0, [r2] /* Save the new top of stack into the first member of the TCB. */
stmdb sp!, {r3, r14} stmdb sp!, {r3, r14}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 msr basepri, r0
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
ldmia sp!, {r3, r14} ldmia sp!, {r3, r14}
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */
msr psp, r0 msr psp, r0
bx r14 bx r14
nop nop
} }
@ -263,51 +296,164 @@ __asm void xPortPendSVHandler( void )
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
unsigned long ulDummy;
/* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; {
/* If using preemption, also force a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
#endif #endif
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); #if configUSE_TICKLESS_IDLE == 1
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
#endif
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{ {
vTaskIncrementTick(); vTaskIncrementTick();
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;
/* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods, and the fraction of a tick period is
accounted for later. */
ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
/* If a context switch is pending then abandon the low power entry as
the context switch might have been pended by an external interrupt that
requires processing. */
if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )
{
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
}
else
{
/* Adjust the reload value to take into account that the current
time slice is already partially complete. */
ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. */
portPRE_SLEEP_PROCESSING();
__wfi();
portPOST_SLEEP_PROCESSING();
/* Stop SysTick. Again, the time the SysTick is stopped for is
accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
/* The tick interrupt has already executed, and the SysTick
count reloaded with the portNVIC_SYSTICK_LOAD_REG value.
Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of
this tick period. */
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be
processed as soon as this function exits, the tick value
maintained by the tick is stepped forward by one less than the
time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted. */
ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/* /*
* Setup the systick timer to generate the tick interrupts at the required * Setup the SysTick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
void prvSetupTimerInterrupt( void ) void prvSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */
ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
#if configUSE_TICKLESS_IDLE == 1
xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
#endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__asm void vPortSetInterruptMask( void ) __asm unsigned long ulPortSetInterruptMask( void )
{ {
PRESERVE8 PRESERVE8
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mrs r0, basepri
msr basepri, r0 mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1
bx r14 bx r14
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__asm void vPortClearInterruptMask( void ) __asm void vPortClearInterruptMask( unsigned long ulNewMask )
{ {
PRESERVE8 PRESERVE8
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
mov r0, #0
msr basepri, r0 msr basepri, r0
bx r14 bx r14
} }

View file

@ -1,6 +1,6 @@
/* /*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd. FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
*************************************************************************** ***************************************************************************
* * * *
@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,17 +50,17 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
@ -73,7 +73,7 @@ extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
* *
* The settings in this file configure FreeRTOS correctly for the * The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler. * given hardware and compiler.
@ -98,50 +98,41 @@ extern "C" {
typedef unsigned portLONG portTickType; typedef unsigned portLONG portTickType;
#define portMAX_DELAY ( portTickType ) 0xffffffff #define portMAX_DELAY ( portTickType ) 0xffffffff
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYield( void ); extern void vPortYield( void );
extern void vPortYieldFromISR( void ); extern void vPortYieldFromISR( void );
#define portYIELD() vPortYieldFromISR() #define portYIELD() vPortYieldFromISR()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern unsigned long ulPortSetInterruptMask( void );
extern void vPortSetInterruptMask( void ); extern void vPortClearInterruptMask( unsigned long ulNewMask );
extern void vPortClearInterruptMask( void );
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() vPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask() #define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;vPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask();(void)x
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Tickless/low power optimisations. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
/*-----------------------------------------------------------*/
#define portNOP()
/* Port specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
@ -154,11 +145,21 @@ http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
#endif /* taskRECORD_READY_PRIORITY */ #endif /* taskRECORD_READY_PRIORITY */
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
/* portNOP() is not required by this port. */
#define portNOP()
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,6 +1,6 @@
/* /*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd. FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
*************************************************************************** ***************************************************************************
* * * *
@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,17 +50,17 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
@ -72,7 +72,7 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#ifndef __TARGET_FPU_VFP #ifndef __TARGET_FPU_VFP
#error This port can only be used when the project options are configured to enable hardware floating point support. #error This port can only be used when the project options are configured to enable hardware floating point support.
#endif #endif
@ -80,17 +80,35 @@
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif #endif
/* Constants required to manipulate the NVIC. */ #ifndef configSYSTICK_CLOCK_HZ
#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) static const unsigned long ulStoppedTimerCompensation = 45UL;
#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) #endif
#define portNVIC_SYSTICK_CLK 0x00000004 #else /* configSYSTICK_CLOCK_HZ */
#define portNVIC_SYSTICK_INT 0x00000002 #if configUSE_TICKLESS_IDLE == 1
#define portNVIC_SYSTICK_ENABLE 0x00000001 /* Assumes the SysTick clock is slower than the CPU clock. */
#define portNVIC_PENDSVSET 0x10000000 static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) #endif
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) #endif /* configSYSTICK_CLOCK_HZ */
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */ #define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
@ -104,7 +122,7 @@
variable. */ variable. */
static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
/* /*
* Setup the timer to generate the tick interrupts. * Setup the timer to generate the tick interrupts.
*/ */
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
@ -125,27 +143,41 @@ static void prvStartFirstTask( void );
* Functions defined in portasm.s to enable the VFP. * Functions defined in portasm.s to enable the VFP.
*/ */
static void prvEnableVFP( void ); static void prvEnableVFP( void );
/*-----------------------------------------------------------*/
/*
* The number of SysTick increments that make up one tick period.
*/
static unsigned long ulTimerReloadValueForOneTick = 0;
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if configUSE_TICKLESS_IDLE == 1
static unsigned long xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
interrupt. */ interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit /* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */ of interrupts, and to ensure alignment. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = 0; /* LR */
/* Save code space by skipping register initialisation. */ /* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
@ -156,7 +188,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
*pxTopOfStack = portINITIAL_EXEC_RETURN; *pxTopOfStack = portINITIAL_EXEC_RETURN;
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -173,7 +205,7 @@ __asm void vPortSVCHandler( void )
ldmia r0!, {r4-r11, r14} ldmia r0!, {r4-r11, r14}
msr psp, r0 msr psp, r0
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
bx r14 bx r14
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -199,41 +231,41 @@ __asm void prvStartFirstTask( void )
__asm void prvEnableVFP( void ) __asm void prvEnableVFP( void )
{ {
PRESERVE8 PRESERVE8
/* The FPU enable bits are in the CPACR. */ /* The FPU enable bits are in the CPACR. */
ldr.w r0, =0xE000ED88 ldr.w r0, =0xE000ED88
ldr r1, [r0] ldr r1, [r0]
/* Enable CP10 and CP11 coprocessors, then save back. */ /* Enable CP10 and CP11 coprocessors, then save back. */
orr r1, r1, #( 0xf << 20 ) orr r1, r1, #( 0xf << 20 )
str r1, [r0] str r1, [r0]
bx r14 bx r14
nop nop
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
/* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0; uxCriticalNesting = 0;
/* Ensure the VFP is enabled - it should be anyway. */ /* Ensure the VFP is enabled - it should be anyway. */
prvEnableVFP(); prvEnableVFP();
/* Lazy save always. */ /* Lazy save always. */
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
/* Start the first task. */ /* Start the first task. */
prvStartFirstTask(); prvStartFirstTask();
@ -252,7 +284,7 @@ void vPortEndScheduler( void )
void vPortYieldFromISR( void ) void vPortYieldFromISR( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -281,11 +313,11 @@ __asm void xPortPendSVHandler( void )
PRESERVE8 PRESERVE8
mrs r0, psp mrs r0, psp
/* Get the location of the current TCB. */ /* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB ldr r3, =pxCurrentTCB
ldr r2, [r3] ldr r2, [r3]
/* Is the task using the FPU context? If so, push high vfp registers. */ /* Is the task using the FPU context? If so, push high vfp registers. */
tst r14, #0x10 tst r14, #0x10
@ -293,85 +325,198 @@ __asm void xPortPendSVHandler( void )
vstmdbeq r0!, {s16-s31} vstmdbeq r0!, {s16-s31}
/* Save the core registers. */ /* Save the core registers. */
stmdb r0!, {r4-r11, r14} stmdb r0!, {r4-r11, r14}
/* Save the new top of stack into the first member of the TCB. */ /* Save the new top of stack into the first member of the TCB. */
str r0, [r2] str r0, [r2]
stmdb sp!, {r3, r14} stmdb sp!, {r3, r14}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 msr basepri, r0
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
ldmia sp!, {r3, r14} ldmia sp!, {r3, r14}
/* The first item in pxCurrentTCB is the task top of stack. */ /* The first item in pxCurrentTCB is the task top of stack. */
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] ldr r0, [r1]
/* Pop the core registers. */ /* Pop the core registers. */
ldmia r0!, {r4-r11, r14} ldmia r0!, {r4-r11, r14}
/* Is the task using the FPU context? If so, pop the high vfp registers /* Is the task using the FPU context? If so, pop the high vfp registers
too. */ too. */
tst r14, #0x10 tst r14, #0x10
it eq it eq
vldmiaeq r0!, {s16-s31} vldmiaeq r0!, {s16-s31}
msr psp, r0 msr psp, r0
bx r14 bx r14
nop nop
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
unsigned long ulDummy;
/* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; {
/* If using preemption, also force a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
#endif #endif
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); #if configUSE_TICKLESS_IDLE == 1
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
#endif
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{ {
vTaskIncrementTick(); vTaskIncrementTick();
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;
/* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods, and the fraction of a tick period is
accounted for later. */
ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
/* If a context switch is pending then abandon the low power entry as
the context switch might have been pended by an external interrupt that
requires processing. */
if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )
{
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
}
else
{
/* Adjust the reload value to take into account that the current
time slice is already partially complete. */
ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. */
portPRE_SLEEP_PROCESSING();
__wfi();
portPOST_SLEEP_PROCESSING();
/* Stop SysTick. Again, the time the SysTick is stopped for is
accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
/* The tick interrupt has already executed, and the SysTick
count reloaded with the portNVIC_SYSTICK_LOAD_REG value.
Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of
this tick period. */
portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be
processed as soon as this function exits, the tick value
maintained by the tick is stepped forward by one less than the
time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted. */
ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/* /*
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
void prvSetupTimerInterrupt( void ) void prvSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */
ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
#if configUSE_TICKLESS_IDLE == 1
xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
#endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__asm void vPortSetInterruptMask( void ) __asm unsigned long ulPortSetInterruptMask( void )
{ {
PRESERVE8 PRESERVE8
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mrs r0, basepri
msr basepri, r0 mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1
bx r14 bx r14
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__asm void vPortClearInterruptMask( void ) __asm void vPortClearInterruptMask( unsigned long ulNewMask )
{ {
PRESERVE8 PRESERVE8
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
mov r0, #0
msr basepri, r0 msr basepri, r0
bx r14 bx r14
} }

View file

@ -106,46 +106,39 @@ extern "C" {
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYield( void ); extern void vPortYield( void );
extern void vPortYieldFromISR( void ); extern void vPortYieldFromISR( void );
#define portYIELD() vPortYieldFromISR() #define portYIELD() vPortYieldFromISR()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern unsigned long ulPortSetInterruptMask( void );
extern void vPortSetInterruptMask( void ); extern void vPortClearInterruptMask( unsigned long ulNewMask );
extern void vPortClearInterruptMask( void );
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() vPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask() #define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see /*-----------------------------------------------------------*/
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;vPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask();(void)x
/* There are an uneven number of items on the initial stack, so /* There are an uneven number of items on the initial stack, so
portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
#define portALIGNMENT_ASSERT_pxCurrentTCB ( void ) #define portALIGNMENT_ASSERT_pxCurrentTCB ( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Tickless/low power optimisations. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
/*-----------------------------------------------------------*/
#define portNOP()
/* Port specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
@ -158,11 +151,21 @@ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
#endif /* taskRECORD_READY_PRIORITY */ #endif /* taskRECORD_READY_PRIORITY */
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
/* portNOP() is not required by this port. */
#define portNOP()
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,6 +1,6 @@
/* /*
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd. FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
*************************************************************************** ***************************************************************************
* * * *
@ -40,7 +40,7 @@
FreeRTOS WEB site. FreeRTOS WEB site.
1 tab == 4 spaces! 1 tab == 4 spaces!
*************************************************************************** ***************************************************************************
* * * *
* Having a problem? Start by reading the FAQ "My application does * * Having a problem? Start by reading the FAQ "My application does *
@ -50,21 +50,21 @@
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information, http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details. license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool. including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com. the SafeRTOS brand: http://www.SafeRTOS.com.
*/ */
/* Standard includes. */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -74,6 +74,7 @@ all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */ task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "timers.h" #include "timers.h"
@ -82,39 +83,40 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* /*
* Macro to define the amount of stack available to the idle task. * Defines the size, in words, of the stack allocated to the idle task.
*/ */
#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE #define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
/* /*
* Task control block. A task control block (TCB) is allocated to each task, * Task control block. A task control block (TCB) is allocated for each task,
* and stores the context of the task. * and stores task state information, including a pointer to the task's context
* (the task's run time environment, including register values)
*/ */
typedef struct tskTaskControlBlock typedef struct tskTaskControlBlock
{ {
volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
#if ( portUSING_MPU_WRAPPERS == 1 ) #if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
#endif #endif
xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ xListItem xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ xListItem xEventListItem; /*< Used to reference a task from an event list. */
unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ unsigned portBASE_TYPE uxPriority; /*< The priority of the task. 0 is the lowest priority. */
portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */
signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */
#if ( portSTACK_GROWTH > 0 ) #if ( portSTACK_GROWTH > 0 )
portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ portSTACK_TYPE *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
#endif #endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 ) #if ( portCRITICAL_NESTING_IN_TCB == 1 )
unsigned portBASE_TYPE uxCriticalNesting; unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
#endif #endif
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
unsigned portBASE_TYPE uxTCBNumber; /*< This stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ unsigned portBASE_TYPE uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
unsigned portBASE_TYPE uxTaskNumber; /*< This stores a number specifically for use by third party trace code. */ unsigned portBASE_TYPE uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
#endif #endif
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
@ -126,15 +128,15 @@ typedef struct tskTaskControlBlock
#endif #endif
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ unsigned long ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
#endif #endif
} tskTCB; } tskTCB;
/* /*
* Some kernel aware debuggers require data to be viewed to be global, rather * Some kernel aware debuggers require the data the debugger needs access to to
* than file scope. * be global, rather than file scope.
*/ */
#ifdef portREMOVE_STATIC_QUALIFIER #ifdef portREMOVE_STATIC_QUALIFIER
#define static #define static
@ -144,7 +146,6 @@ typedef struct tskTaskControlBlock
PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL; PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
/* Lists for ready and blocked tasks. --------------------*/ /* Lists for ready and blocked tasks. --------------------*/
PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */ PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */
PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
@ -166,9 +167,9 @@ PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been r
#endif #endif
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
#endif #endif
/* File private variables. --------------------------------*/ /* File private variables. --------------------------------*/
@ -182,7 +183,7 @@ PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsi
PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U;
PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY; PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY;
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
@ -211,10 +212,13 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 0
/*
* uxTopReadyPriority holds the priority of the highest priority ready /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
* state task. performed in a generic way that is not optimised to any particular
*/ microcontroller architecture. */
/* uxTopReadyPriority holds the priority of the highest priority ready
state task. */
#define taskRECORD_READY_PRIORITY( uxPriority ) \ #define taskRECORD_READY_PRIORITY( uxPriority ) \
{ \ { \
if( ( uxPriority ) > uxTopReadyPriority ) \ if( ( uxPriority ) > uxTopReadyPriority ) \
@ -241,26 +245,46 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Define away portRESET_READY_PRIORITY() as it is not required in this /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
configuration. */ they are only required when a port optimised method of task selection is
being used. */
#define taskRESET_READY_PRIORITY( uxPriority )
#define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
performed in a way that is tailored to the particular microcontroller
architecture being used. */
/* A port optimised version is provided. Call the port defined macros. */ /* A port optimised version is provided. Call the port defined macros. */
#define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define taskSELECT_HIGHEST_PRIORITY_TASK() \ #define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \ { \
unsigned portBASE_TYPE uxTopPriority; \ unsigned portBASE_TYPE uxTopPriority; \
\ \
/* Find the highest priority queue that contains ready tasks. */ \ /* Find the highest priority queue that contains ready tasks. */ \
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */ } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
/*-----------------------------------------------------------*/
/* A port optimised version is provided, call it only if the TCB being reset
is being referenced from a ready list. If it is referenced from a delayed
or suspended list then it won't be in a ready list. */
#define taskRESET_READY_PRIORITY( uxPriority ) \
{ \
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \
{ \
portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
} \
}
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* /*
@ -270,9 +294,9 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
* executing task, then it will only be rescheduled after the currently * executing task, then it will only be rescheduled after the currently
* executing task has been rescheduled. * executing task has been rescheduled.
*/ */
#define prvAddTaskToReadyQueue( pxTCB ) \ #define prvAddTaskToReadyQueue( pxTCB ) \
traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -348,7 +372,7 @@ portTickType xItemValue; \
/* Callback function prototypes. --------------------------*/ /* Callback function prototypes. --------------------------*/
extern void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName ); extern void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName );
extern void vApplicationTickHook( void ); extern void vApplicationTickHook( void );
/* File private functions. --------------------------------*/ /* File private functions. --------------------------------*/
/* /*
@ -488,7 +512,7 @@ tskTCB * pxNewTCB;
#else #else
{ {
pxTopOfStack = pxNewTCB->pxStack; pxTopOfStack = pxNewTCB->pxStack;
/* Check the alignment of the stack buffer is correct. */ /* Check the alignment of the stack buffer is correct. */
configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
@ -526,7 +550,7 @@ tskTCB * pxNewTCB;
required.*/ required.*/
*pxCreatedTask = ( xTaskHandle ) pxNewTCB; *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
} }
/* We are going to manipulate the task queues to add this task to a /* We are going to manipulate the task queues to add this task to a
ready list, so must make sure no interrupts occur. */ ready list, so must make sure no interrupts occur. */
taskENTER_CRITICAL(); taskENTER_CRITICAL();
@ -630,7 +654,7 @@ tskTCB * pxNewTCB;
scheduler for the TCB and stack. */ scheduler for the TCB and stack. */
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
{ {
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
} }
/* Is the task waiting on an event also? */ /* Is the task waiting on an event also? */
@ -725,6 +749,9 @@ tskTCB * pxNewTCB;
both lists. */ both lists. */
if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
{ {
/* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called
directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
} }
@ -775,6 +802,9 @@ tskTCB * pxNewTCB;
both lists. */ both lists. */
if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
{ {
/* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called
directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
} }
prvAddCurrentTaskToDelayedList( xTimeToWake ); prvAddCurrentTaskToDelayedList( xTimeToWake );
@ -794,7 +824,7 @@ tskTCB * pxNewTCB;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( INCLUDE_eTaskStateGet == 1 ) #if ( INCLUDE_eTaskStateGet == 1 )
eTaskState eTaskStateGet( xTaskHandle pxTask ) eTaskState eTaskStateGet( xTaskHandle pxTask )
{ {
eTaskState eReturn; eTaskState eReturn;
@ -818,7 +848,7 @@ tskTCB * pxNewTCB;
if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) ) if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
{ {
/* The task being queried is referenced from one of the Blocked /* The task being queried is referenced from one of the Blocked
lists. */ lists. */
eReturn = eBlocked; eReturn = eBlocked;
} }
@ -826,7 +856,7 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
else if( pxStateList == &xSuspendedTaskList ) else if( pxStateList == &xSuspendedTaskList )
{ {
/* The task being queried is referenced from the suspended /* The task being queried is referenced from the suspended
list. */ list. */
eReturn = eSuspended; eReturn = eSuspended;
} }
@ -835,7 +865,7 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskDelete == 1 ) #if ( INCLUDE_vTaskDelete == 1 )
else if( pxStateList == &xTasksWaitingTermination ) else if( pxStateList == &xTasksWaitingTermination )
{ {
/* The task being queried is referenced from the deleted /* The task being queried is referenced from the deleted
tasks list. */ tasks list. */
eReturn = eDeleted; eReturn = eDeleted;
} }
@ -882,7 +912,7 @@ tskTCB * pxNewTCB;
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )
{ {
tskTCB *pxTCB; tskTCB *pxTCB;
unsigned portBASE_TYPE uxCurrentPriority; unsigned portBASE_TYPE uxCurrentPriority, uxPriorityUsedOnEntry;
portBASE_TYPE xYieldRequired = pdFALSE; portBASE_TYPE xYieldRequired = pdFALSE;
configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
@ -938,7 +968,10 @@ tskTCB * pxNewTCB;
xYieldRequired = pdTRUE; xYieldRequired = pdTRUE;
} }
/* Remember the ready list the task might be referenced from
before its uxPriority member is changed so the
taskRESET_READY_PRIORITY() macro can function correctly. */
uxPriorityUsedOnEntry = pxTCB->uxPriority;
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
{ {
@ -971,7 +1004,7 @@ tskTCB * pxNewTCB;
can do this even if the scheduler is suspended. */ can do this even if the scheduler is suspended. */
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
{ {
portRESET_READY_PRIORITY( uxCurrentPriority, uxTopReadyPriority ); taskRESET_READY_PRIORITY( uxPriorityUsedOnEntry );
} }
prvAddTaskToReadyQueue( pxTCB ); prvAddTaskToReadyQueue( pxTCB );
} }
@ -983,6 +1016,10 @@ tskTCB * pxNewTCB;
} }
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
/* Remove compiler warning about unused parameter when the port
optimised task selection is not being used. */
( void ) uxPriorityUsedOnEntry;
} }
#endif #endif
@ -1011,7 +1048,7 @@ tskTCB * pxNewTCB;
/* Remove task from the ready/delayed list and place in the suspended list. */ /* Remove task from the ready/delayed list and place in the suspended list. */
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
{ {
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
} }
/* Is the task waiting on an event also? */ /* Is the task waiting on an event also? */
@ -1228,7 +1265,7 @@ portBASE_TYPE xReturn;
macro must be defined to configure the timer/counter used to generate macro must be defined to configure the timer/counter used to generate
the run time counter time base. */ the run time counter time base. */
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
/* Setting up the timer tick is hardware specific and thus in the /* Setting up the timer tick is hardware specific and thus in the
portable interface. */ portable interface. */
if( xPortStartScheduler() != pdFALSE ) if( xPortStartScheduler() != pdFALSE )
@ -1266,6 +1303,30 @@ void vTaskSuspendAll( void )
} }
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
portTickType xTaskGetExpectedIdleTime( void )
{
portTickType xReturn;
if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
{
xReturn = 0;
}
else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
{
/* There are other idle priority tasks in the ready state. If
time slicing is used then the very next tick interrupt must be
processed. */
xReturn = 0;
}
else
{
xReturn = xNextTaskUnblockTime - xTickCount;
}
return xReturn;
}
/*----------------------------------------------------------*/
signed portBASE_TYPE xTaskResumeAll( void ) signed portBASE_TYPE xTaskResumeAll( void )
{ {
register tskTCB *pxTCB; register tskTCB *pxTCB;
@ -1488,7 +1549,7 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
/* Divide ulTotalRunTime by 100 to make the percentage caluclations /* Divide ulTotalRunTime by 100 to make the percentage caluclations
simpler in the prvGenerateRunTimeStatsForTasksInList() function. */ simpler in the prvGenerateRunTimeStatsForTasksInList() function. */
ulTotalRunTime /= 100UL; ulTotalRunTime /= 100UL;
/* Run through all the lists that could potentially contain a TCB, /* Run through all the lists that could potentially contain a TCB,
generating a table of run timer percentages in the provided generating a table of run timer percentages in the provided
buffer. */ buffer. */
@ -1551,8 +1612,15 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
configASSERT( ( xIdleTaskHandle != NULL ) ); configASSERT( ( xIdleTaskHandle != NULL ) );
return xIdleTaskHandle; return xIdleTaskHandle;
} }
#endif #endif
/*----------------------------------------------------------*/
void vTaskStepTick( portTickType xTicksToJump )
{
configASSERT( xTicksToJump <= xNextTaskUnblockTime );
xTickCount += xTicksToJump;
}
/*----------------------------------------------------------- /*-----------------------------------------------------------
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
@ -1566,6 +1634,7 @@ tskTCB * pxTCB;
/* Called by the portable layer each time a tick interrupt occurs. /* Called by the portable layer each time a tick interrupt occurs.
Increments the tick then checks to see if the new tick value will cause any Increments the tick then checks to see if the new tick value will cause any
tasks to be unblocked. */ tasks to be unblocked. */
traceTASK_INCREMENT_TICK( xTickCount );
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{ {
++xTickCount; ++xTickCount;
@ -1577,17 +1646,17 @@ tskTCB * pxTCB;
If there are any items in pxDelayedTaskList here then there is If there are any items in pxDelayedTaskList here then there is
an error! */ an error! */
configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );
pxTemp = pxDelayedTaskList; pxTemp = pxDelayedTaskList;
pxDelayedTaskList = pxOverflowDelayedTaskList; pxDelayedTaskList = pxOverflowDelayedTaskList;
pxOverflowDelayedTaskList = pxTemp; pxOverflowDelayedTaskList = pxTemp;
xNumOfOverflows++; xNumOfOverflows++;
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{ {
/* The new current delayed list is empty. Set /* The new current delayed list is empty. Set
xNextTaskUnblockTime to the maximum possible value so it is xNextTaskUnblockTime to the maximum possible value so it is
extremely unlikely that the extremely unlikely that the
if( xTickCount >= xNextTaskUnblockTime ) test will pass until if( xTickCount >= xNextTaskUnblockTime ) test will pass until
there is an item in the delayed list. */ there is an item in the delayed list. */
xNextTaskUnblockTime = portMAX_DELAY; xNextTaskUnblockTime = portMAX_DELAY;
@ -1629,8 +1698,6 @@ tskTCB * pxTCB;
} }
} }
#endif #endif
traceTASK_INCREMENT_TICK( xTickCount );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1732,17 +1799,17 @@ void vTaskSwitchContext( void )
else else
{ {
traceTASK_SWITCHED_OUT(); traceTASK_SWITCHED_OUT();
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
{ {
unsigned long ulTempCounter; unsigned long ulTempCounter;
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
portALT_GET_RUN_TIME_COUNTER_VALUE( ulTempCounter ); portALT_GET_RUN_TIME_COUNTER_VALUE( ulTempCounter );
#else #else
ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE(); ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
#endif #endif
/* Add the amount of time the task has been running to the accumulated /* Add the amount of time the task has been running to the accumulated
time so far. The time the task started running was stored in time so far. The time the task started running was stored in
ulTaskSwitchedInTime. Note that there is no overflow protection here ulTaskSwitchedInTime. Note that there is no overflow protection here
@ -1752,12 +1819,12 @@ void vTaskSwitchContext( void )
ulTaskSwitchedInTime = ulTempCounter; ulTaskSwitchedInTime = ulTempCounter;
} }
#endif #endif
taskFIRST_CHECK_FOR_STACK_OVERFLOW(); taskFIRST_CHECK_FOR_STACK_OVERFLOW();
taskSECOND_CHECK_FOR_STACK_OVERFLOW(); taskSECOND_CHECK_FOR_STACK_OVERFLOW();
taskSELECT_HIGHEST_PRIORITY_TASK(); taskSELECT_HIGHEST_PRIORITY_TASK();
traceTASK_SWITCHED_IN(); traceTASK_SWITCHED_IN();
} }
} }
@ -1782,6 +1849,8 @@ portTickType xTimeToWake;
exclusive access to the ready lists as the scheduler is locked. */ exclusive access to the ready lists as the scheduler is locked. */
if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
{ {
/* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
} }
@ -1826,7 +1895,7 @@ portTickType xTimeToWake;
designed for use by kernel code, and has special calling requirements - designed for use by kernel code, and has special calling requirements -
it should be called from a critical section. */ it should be called from a critical section. */
/* Place the event list item of the TCB in the appropriate event list. /* Place the event list item of the TCB in the appropriate event list.
In this case it is assume that this is the only task that is going to In this case it is assume that this is the only task that is going to
be waiting on this event list, so the faster vListInsertEnd() function be waiting on this event list, so the faster vListInsertEnd() function
@ -1838,6 +1907,8 @@ portTickType xTimeToWake;
function is called form a critical section. */ function is called form a critical section. */
if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
{ {
/* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
} }
@ -1846,7 +1917,7 @@ portTickType xTimeToWake;
xTimeToWake = xTickCount + xTicksToWait; xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake ); prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
#endif /* configUSE_TIMERS */ #endif /* configUSE_TIMERS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1865,7 +1936,7 @@ portBASE_TYPE xReturn;
If an event is for a queue that is locked then this function will never If an event is for a queue that is locked then this function will never
get called - the lock count on the queue will get modified instead. This get called - the lock count on the queue will get modified instead. This
means we can always expect exclusive access to the event list here. means we can always expect exclusive access to the event list here.
This function assumes that a check has already been made to ensure that This function assumes that a check has already been made to ensure that
pxEventList is not empty. */ pxEventList is not empty. */
pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
@ -1966,7 +2037,7 @@ void vTaskMissedYield( void )
{ {
unsigned portBASE_TYPE uxReturn; unsigned portBASE_TYPE uxReturn;
tskTCB *pxTCB; tskTCB *pxTCB;
if( xTask != NULL ) if( xTask != NULL )
{ {
pxTCB = ( tskTCB * ) xTask; pxTCB = ( tskTCB * ) xTask;
@ -1976,7 +2047,7 @@ void vTaskMissedYield( void )
{ {
uxReturn = 0U; uxReturn = 0U;
} }
return uxReturn; return uxReturn;
} }
#endif #endif
@ -1986,7 +2057,7 @@ void vTaskMissedYield( void )
void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ) void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )
{ {
tskTCB *pxTCB; tskTCB *pxTCB;
if( xTask != NULL ) if( xTask != NULL )
{ {
pxTCB = ( tskTCB * ) xTask; pxTCB = ( tskTCB * ) xTask;
@ -2057,6 +2128,48 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
vApplicationIdleHook(); vApplicationIdleHook();
} }
#endif #endif
#if ( configUSE_TICKLESS_IDLE == 1 )
{
portTickType xExpectedIdleTime;
/* If the expected idle time is 1 then the idle time would end at
the end of the current time slice. The idle time must be at least
2 to ensure any pended ticks between this point and the tick being
stopped can be legitimately stepped over when the tick suppression
routines returns. */
const portTickType xMinimumExpectedIdleTime = ( portTickType ) 2;
/* Don't enter low power if there are still tasks waiting
deletion. */
if( uxTasksDeleted == 0 )
{
/* It is not desirable to suspend then resume the scheduler on
each iteration of the idle task. Therefore, a preliminary
test of the expected idle time is performed without the
scheduler suspended. The result here is not necessarily
valid. */
xExpectedIdleTime = xTaskGetExpectedIdleTime();
if( xExpectedIdleTime >= xMinimumExpectedIdleTime )
{
vTaskSuspendAll();
{
/* Now the scheduler is suspended, the expected idle
time can be sampled again, and this time its value can
be used. */
configASSERT( xNextTaskUnblockTime >= xTickCount );
xExpectedIdleTime = xTaskGetExpectedIdleTime();
if( xExpectedIdleTime >= xMinimumExpectedIdleTime )
{
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
}
}
xTaskResumeAll();
}
}
}
#endif
} }
} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */ } /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */
@ -2144,7 +2257,7 @@ static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const
void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions ) void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
{ {
tskTCB *pxTCB; tskTCB *pxTCB;
if( xTaskToModify == pxCurrentTCB ) if( xTaskToModify == pxCurrentTCB )
{ {
xTaskToModify = NULL; xTaskToModify = NULL;
@ -2304,8 +2417,8 @@ tskTCB *pxNewTCB;
{ {
usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack ); usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
} }
#endif #endif
sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber ); sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber );
strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString ); strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString );
@ -2349,7 +2462,7 @@ tskTCB *pxNewTCB;
{ {
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{ {
sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage ); sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage );
} }
#else #else
{ {
@ -2365,7 +2478,7 @@ tskTCB *pxNewTCB;
consumed less than 1% of the total run time. */ consumed less than 1% of the total run time. */
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{ {
sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter ); sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter );
} }
#else #else
{ {
@ -2516,12 +2629,12 @@ tskTCB *pxNewTCB;
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
/* If the task being modified is in the ready state it will need to /* If the task being modified is in the ready state it will need to
be moved in to a new list. */ be moved into a new list. */
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
{ {
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
{ {
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
} }
/* Inherit the priority before being moved into the new list. */ /* Inherit the priority before being moved into the new list. */
@ -2556,7 +2669,7 @@ tskTCB *pxNewTCB;
Remove ourselves from the ready list we currently appear in. */ Remove ourselves from the ready list we currently appear in. */
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 ) if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
{ {
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
} }
/* Disinherit the priority before adding the task into the new /* Disinherit the priority before adding the task into the new
@ -2589,21 +2702,40 @@ tskTCB *pxNewTCB;
#if ( portCRITICAL_NESTING_IN_TCB == 1 ) #if ( portCRITICAL_NESTING_IN_TCB == 1 )
void vTaskExitCritical( void ) void vTaskExitCritical( void )
{
if( xSchedulerRunning != pdFALSE )
{ {
if( pxCurrentTCB->uxCriticalNesting > 0U ) if( xSchedulerRunning != pdFALSE )
{ {
( pxCurrentTCB->uxCriticalNesting )--; if( pxCurrentTCB->uxCriticalNesting > 0U )
if( pxCurrentTCB->uxCriticalNesting == 0U )
{ {
portENABLE_INTERRUPTS(); ( pxCurrentTCB->uxCriticalNesting )--;
if( pxCurrentTCB->uxCriticalNesting == 0U )
{
portENABLE_INTERRUPTS();
}
} }
} }
} }
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_TICKLESS_IDLE == 1 )
unsigned portBASE_TYPE uxTaskPendingTicksGet( portBASE_TYPE xResetOnExit )
{
unsigned portBASE_TYPE uxReturn;
uxReturn = uxMissedTicks;
if( xResetOnExit == pdTRUE )
{
uxMissedTicks = 0;
}
return uxReturn;
}
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/