mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-20 05:21:59 -04:00
Add tickless idle support in Cortex-M ports.
Change CCS R4 directory name.
This commit is contained in:
parent
6ec4c7cecb
commit
e03ab659f3
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
350
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/port.c
Normal file
350
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/port.c
Normal 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__ */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
263
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portASM.asm
Normal file
263
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portASM.asm
Normal 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
|
||||||
|
;-------------------------------------------------------------------------------
|
||||||
|
|
145
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portmacro.h
Normal file
145
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portmacro.h
Normal 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__ */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -185,8 +219,8 @@ portBASE_TYPE xPortStartScheduler( void )
|
||||||
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;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -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 portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||||
|
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
|
||||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. */
|
||||||
|
@ -203,9 +236,9 @@ portBASE_TYPE xPortStartScheduler( void )
|
||||||
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;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -115,46 +115,15 @@ 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 portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||||
|
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
|
||||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,8 +179,8 @@ 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. */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -66,34 +66,19 @@
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -165,8 +198,8 @@ 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. */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
||||||
|
@ -114,7 +132,22 @@ 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 );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -178,9 +211,9 @@ __asm void vPortStartFirstTask( void )
|
||||||
*/
|
*/
|
||||||
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. */
|
||||||
|
@ -190,7 +223,7 @@ portBASE_TYPE xPortStartScheduler( void )
|
||||||
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;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,42 +106,33 @@ 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()
|
||||||
/* 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. */
|
||||||
|
@ -158,7 +149,17 @@ http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
|
||||||
#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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
||||||
|
@ -125,6 +143,20 @@ 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 */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -218,8 +250,8 @@ __asm void prvEnableVFP( void )
|
||||||
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. */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -327,51 +359,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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. */
|
||||||
|
@ -162,7 +155,17 @@ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
|
||||||
#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
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
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. */
|
||||||
|
@ -167,7 +168,7 @@ PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been r
|
||||||
|
|
||||||
#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
|
||||||
|
|
||||||
|
@ -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,12 +245,18 @@ 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 )
|
||||||
|
|
||||||
|
@ -258,9 +268,23 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
|
||||||
\
|
\
|
||||||
/* 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 ); \
|
||||||
|
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
|
||||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
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 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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 );
|
||||||
|
@ -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? */
|
||||||
|
@ -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;
|
||||||
|
@ -1553,6 +1614,13 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
#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;
|
||||||
|
@ -1629,8 +1698,6 @@ tskTCB * pxTCB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
traceTASK_INCREMENT_TICK( xTickCount );
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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. */
|
||||||
|
|
||||||
|
@ -2521,7 +2634,7 @@ tskTCB *pxNewTCB;
|
||||||
{
|
{
|
||||||
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
|
||||||
|
@ -2608,6 +2721,25 @@ void vTaskExitCritical( void )
|
||||||
#endif
|
#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
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue