mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2026-01-17 07:10:37 -05:00
Style: uncrusitfy
This commit is contained in:
parent
a5dbc2b1de
commit
718178c68a
406 changed files with 108795 additions and 106323 deletions
|
|
@ -26,13 +26,13 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Atmel AT91R40008
|
||||
* port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the Atmel AT91R40008
|
||||
* port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
|
@ -48,124 +48,126 @@
|
|||
#include "tc.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
#define portTICK_PRIORITY_6 ( 6 )
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
#define portTICK_PRIORITY_6 ( 6 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
StackType_t * pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
* is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
* start of the task. The offset is added to make the return address appear
|
||||
* as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
* R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
* system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
pxTopOfStack--;
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
pxTopOfStack--;
|
||||
|
||||
return pxTopOfStack;
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
* means the interrupt flags cannot always be stored on the stack and will
|
||||
* instead be stored in a variable, which is then saved as part of the
|
||||
* tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
* is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -174,64 +176,63 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
volatile uint32_t ulDummy;
|
||||
volatile uint32_t ulDummy;
|
||||
|
||||
/* Enable clock to the tick timer... */
|
||||
AT91C_BASE_PS->PS_PCER = portTIMER_CLK_ENABLE_BIT;
|
||||
/* Enable clock to the tick timer... */
|
||||
AT91C_BASE_PS->PS_PCER = portTIMER_CLK_ENABLE_BIT;
|
||||
|
||||
/* Stop the tick timer... */
|
||||
portTIMER_REG_BASE_PTR->TC_CCR = TC_CLKDIS;
|
||||
/* Stop the tick timer... */
|
||||
portTIMER_REG_BASE_PTR->TC_CCR = TC_CLKDIS;
|
||||
|
||||
/* Start with tick timer interrupts disabled... */
|
||||
portTIMER_REG_BASE_PTR->TC_IDR = 0xFFFFFFFF;
|
||||
/* Start with tick timer interrupts disabled... */
|
||||
portTIMER_REG_BASE_PTR->TC_IDR = 0xFFFFFFFF;
|
||||
|
||||
/* Clear any pending tick timer interrupts... */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
/* Clear any pending tick timer interrupts... */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
/* Store interrupt handler function address in tick timer vector register...
|
||||
The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vPreemptiveTick;
|
||||
}
|
||||
#else // else use cooperative scheduler
|
||||
{
|
||||
extern void ( vNonPreemptiveTick )( void );
|
||||
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
/* Store interrupt handler function address in tick timer vector register...
|
||||
* The ISR installed depends on whether the preemptive or cooperative
|
||||
* scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
extern void( vPreemptiveTick )( void );
|
||||
AT91C_BASE_AIC->AIC_SVR[ portTIMER_AIC_CHANNEL ] = ( uint32_t ) vPreemptiveTick;
|
||||
}
|
||||
#else // else use cooperative scheduler
|
||||
{
|
||||
extern void( vNonPreemptiveTick )( void );
|
||||
AT91C_BASE_AIC->AIC_SVR[ portTIMER_AIC_CHANNEL ] = ( uint32_t ) vNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Tick timer interrupt level-sensitive, priority 6... */
|
||||
AT91C_BASE_AIC->AIC_SMR[ portTIMER_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | portTICK_PRIORITY_6;
|
||||
/* Tick timer interrupt level-sensitive, priority 6... */
|
||||
AT91C_BASE_AIC->AIC_SMR[ portTIMER_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | portTICK_PRIORITY_6;
|
||||
|
||||
/* Enable the tick timer interrupt...
|
||||
/* Enable the tick timer interrupt...
|
||||
*
|
||||
* First at timer level */
|
||||
portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS;
|
||||
|
||||
First at timer level */
|
||||
portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS;
|
||||
/* Then at the AIC level. */
|
||||
AT91C_BASE_AIC->AIC_IECR = ( 1 << portTIMER_AIC_CHANNEL );
|
||||
|
||||
/* Then at the AIC level. */
|
||||
AT91C_BASE_AIC->AIC_IECR = (1 << portTIMER_AIC_CHANNEL);
|
||||
/* Calculate timer compare value to achieve the desired tick rate... */
|
||||
if( ( configCPU_CLOCK_HZ / ( configTICK_RATE_HZ * 2 ) ) <= 0xFFFF )
|
||||
{
|
||||
/* The tick rate is fast enough for us to use the faster timer input
|
||||
* clock (main clock / 2). */
|
||||
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK2 | TC_BURST_NONE | TC_CPCTRG;
|
||||
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / ( configTICK_RATE_HZ * 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We must use a slower timer input clock (main clock / 8) because the
|
||||
* tick rate is too slow for the faster input clock. */
|
||||
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK8 | TC_BURST_NONE | TC_CPCTRG;
|
||||
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / ( configTICK_RATE_HZ * 8 );
|
||||
}
|
||||
|
||||
/* Calculate timer compare value to achieve the desired tick rate... */
|
||||
if( (configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2) ) <= 0xFFFF )
|
||||
{
|
||||
/* The tick rate is fast enough for us to use the faster timer input
|
||||
clock (main clock / 2). */
|
||||
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK2 | TC_BURST_NONE | TC_CPCTRG;
|
||||
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We must use a slower timer input clock (main clock / 8) because the
|
||||
tick rate is too slow for the faster input clock. */
|
||||
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK8 | TC_BURST_NONE | TC_CPCTRG;
|
||||
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 8);
|
||||
}
|
||||
|
||||
/* Start tick timer... */
|
||||
portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN;
|
||||
/* Start tick timer... */
|
||||
portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
|
|||
|
|
@ -26,17 +26,17 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
* Changes from V3.2.4
|
||||
*
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
+ than each line having its own asm block.
|
||||
*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
|
|
@ -44,18 +44,18 @@
|
|||
#include "task.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portCLEAR_AIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
#define portCLEAR_AIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
void vPortYieldProcessor( void ) __attribute__( ( interrupt( "SWI" ), naked ) );
|
||||
|
||||
/*
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
|
|
@ -64,93 +64,93 @@ void vPortISRStartFirstTask( void );
|
|||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
* called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
asm volatile ( "ADD LR, LR, #4" );
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
* address, but an SWI ISR does not. Add the offset manually so the same
|
||||
* ISR return code can be used in both cases. */
|
||||
asm volatile ( "ADD LR, LR, #4");
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
static volatile uint32_t ulDummy;
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
* simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__( ( interrupt( "IRQ" ) ) );
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
static volatile uint32_t ulDummy;
|
||||
|
||||
/* Clear tick timer interrupt indication. */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
/* Clear tick timer interrupt indication. */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
xTaskIncrementTick();
|
||||
xTaskIncrementTick();
|
||||
|
||||
/* Acknowledge the interrupt at AIC level... */
|
||||
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
|
||||
}
|
||||
/* Acknowledge the interrupt at AIC level... */
|
||||
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
|
||||
}
|
||||
|
||||
#else /* else preemption is turned on */
|
||||
#else /* else preemption is turned on */
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
* saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__( ( naked ) );
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* WARNING - Do not use local (stack) variables here. Use globals
|
||||
if you must! */
|
||||
static volatile uint32_t ulDummy;
|
||||
/* WARNING - Do not use local (stack) variables here. Use globals
|
||||
* if you must! */
|
||||
static volatile uint32_t ulDummy;
|
||||
|
||||
/* Clear tick timer interrupt indication. */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
/* Clear tick timer interrupt indication. */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
* task that is ready to run. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt at AIC level... */
|
||||
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
|
||||
/* Acknowledge the interrupt at AIC level... */
|
||||
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* if configUSE_PREEMPTION == 0 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
@ -161,72 +161,71 @@ void vPortYieldProcessor( void )
|
|||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t"/* Pop R0. */
|
||||
"BX R14"); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t"/* Pop R0. */
|
||||
"BX R14"); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
* different optimisation levels. The interrupt flags can therefore not always
|
||||
* be saved to the stack. Instead the critical section nesting level is stored
|
||||
* in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0}"); /* Pop R0. */
|
||||
|
||||
/* 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++;
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* 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 == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
* re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0}"); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,34 +25,34 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
* Changes from V3.2.3
|
||||
*
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
+
|
||||
+ Changes from V3.2.4
|
||||
+
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
+ replaced them with hard coded registers. This will ensure the
|
||||
+ assembler does not select the link register as the temp register as
|
||||
+ was occasionally happening previously.
|
||||
+
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
+ than each line having its own asm block.
|
||||
+
|
||||
+ Changes from V4.5.0
|
||||
+
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
+ and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
+ should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
+ macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -65,42 +65,42 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portYIELD() asm volatile ( "SWI 0" )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portYIELD() asm volatile ( "SWI 0" )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
|
||||
/*
|
||||
* These define the timer to use for generating the tick interrupt.
|
||||
* They are put in this file so they can be shared between "port.c"
|
||||
* and "portisr.c".
|
||||
*/
|
||||
#define portTIMER_REG_BASE_PTR AT91C_BASE_TC0
|
||||
#define portTIMER_CLK_ENABLE_BIT AT91C_PS_TC0
|
||||
#define portTIMER_AIC_CHANNEL ( ( uint32_t ) 4 )
|
||||
#define portTIMER_REG_BASE_PTR AT91C_BASE_TC0
|
||||
#define portTIMER_CLK_ENABLE_BIT AT91C_PS_TC0
|
||||
#define portTIMER_AIC_CHANNEL ( ( uint32_t ) 4 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
|
@ -112,90 +112,90 @@ typedef unsigned long UBaseType_t;
|
|||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"LDR LR, [R0] \n\t"\
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t"\
|
||||
"LDMFD LR!, {R1} \n\t"\
|
||||
"STR R1, [R0] \n\t"\
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t"\
|
||||
"MSR SPSR, R0 \n\t"\
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t"\
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t"\
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t"\
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
"SUB SP, SP, #4 \n\t"\
|
||||
"LDMIA SP!,{R0} \n\t"\
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t"\
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t"\
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t"\
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
"SUB LR, LR, #60 \n\t"\
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t"\
|
||||
"STMDB LR!, {R0} \n\t"\
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"STMDB LR!, {R0} \n\t"\
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"STR LR, [R0] \n\t"\
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
|
||||
/* Critical section handling. */
|
||||
|
||||
|
|
@ -206,49 +206,48 @@ extern volatile uint32_t ulCriticalNesting; \
|
|||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */\
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */\
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */\
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */\
|
||||
"LDMIA SP!, {R0} ") /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */\
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */\
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */\
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */\
|
||||
"LDMIA SP!, {R0} ") /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,51 +1,50 @@
|
|||
//* ----------------------------------------------------------------------------
|
||||
//* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
//* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
//* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
//* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
//* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
//* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* File Name : lib_AT91SAM7X256.h
|
||||
//* Object : AT91SAM7X256 inlined functions
|
||||
//* Generated : AT91 SW Application Group 05/20/2005 (16:22:29)
|
||||
//*
|
||||
//* CVS Reference : /lib_dbgu.h/1.1/Fri Jan 31 12:18:40 2003//
|
||||
//* CVS Reference : /lib_pmc_SAM7X.h/1.1/Tue Feb 1 08:32:10 2005//
|
||||
//* CVS Reference : /lib_VREG_6085B.h/1.1/Tue Feb 1 16:20:47 2005//
|
||||
//* CVS Reference : /lib_rstc_6098A.h/1.1/Wed Oct 6 10:39:20 2004//
|
||||
//* CVS Reference : /lib_ssc.h/1.4/Fri Jan 31 12:19:20 2003//
|
||||
//* CVS Reference : /lib_wdtc_6080A.h/1.1/Wed Oct 6 10:38:30 2004//
|
||||
//* CVS Reference : /lib_usart.h/1.5/Thu Nov 21 16:01:54 2002//
|
||||
//* CVS Reference : /lib_spi2.h/1.1/Mon Aug 25 14:23:52 2003//
|
||||
//* CVS Reference : /lib_pitc_6079A.h/1.2/Tue Nov 9 14:43:56 2004//
|
||||
//* CVS Reference : /lib_aic_6075b.h/1.1/Fri May 20 14:01:19 2005//
|
||||
//* CVS Reference : /lib_aes_6149a.h/1.1/Mon Jan 17 07:43:09 2005//
|
||||
//* CVS Reference : /lib_twi.h/1.3/Mon Jul 19 14:27:58 2004//
|
||||
//* CVS Reference : /lib_adc.h/1.6/Fri Oct 17 09:12:38 2003//
|
||||
//* CVS Reference : /lib_rttc_6081A.h/1.1/Wed Oct 6 10:39:38 2004//
|
||||
//* CVS Reference : /lib_udp.h/1.4/Wed Feb 16 08:39:34 2005//
|
||||
//* CVS Reference : /lib_des3_6150a.h/1.1/Mon Jan 17 09:19:19 2005//
|
||||
//* CVS Reference : /lib_tc_1753b.h/1.1/Fri Jan 31 12:20:02 2003//
|
||||
//* CVS Reference : /lib_MC_SAM7X.h/1.1/Thu Mar 25 15:19:14 2004//
|
||||
//* CVS Reference : /lib_pio.h/1.3/Fri Jan 31 12:18:56 2003//
|
||||
//* CVS Reference : /lib_can_AT91.h/1.4/Fri Oct 17 09:12:50 2003//
|
||||
//* CVS Reference : /lib_PWM_SAM.h/1.3/Thu Jan 22 10:10:50 2004//
|
||||
//* CVS Reference : /lib_pdc.h/1.2/Tue Jul 2 13:29:40 2002//
|
||||
//* ----------------------------------------------------------------------------
|
||||
/** ---------------------------------------------------------------------------- */
|
||||
/** ATMEL Microcontroller Software Support - ROUSSET - */
|
||||
/** ---------------------------------------------------------------------------- */
|
||||
/** DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */
|
||||
/** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
|
||||
/** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */
|
||||
/** DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */
|
||||
/** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
|
||||
/** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
|
||||
/** OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
|
||||
/** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
|
||||
/** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
|
||||
/** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
/** ---------------------------------------------------------------------------- */
|
||||
/** File Name : lib_AT91SAM7X256.h */
|
||||
/** Object : AT91SAM7X256 inlined functions */
|
||||
/** Generated : AT91 SW Application Group 05/20/2005 (16:22:29) */
|
||||
/** */
|
||||
/** CVS Reference : /lib_dbgu.h/1.1/Fri Jan 31 12:18:40 2003// */
|
||||
/** CVS Reference : /lib_pmc_SAM7X.h/1.1/Tue Feb 1 08:32:10 2005// */
|
||||
/** CVS Reference : /lib_VREG_6085B.h/1.1/Tue Feb 1 16:20:47 2005// */
|
||||
/** CVS Reference : /lib_rstc_6098A.h/1.1/Wed Oct 6 10:39:20 2004// */
|
||||
/** CVS Reference : /lib_ssc.h/1.4/Fri Jan 31 12:19:20 2003// */
|
||||
/** CVS Reference : /lib_wdtc_6080A.h/1.1/Wed Oct 6 10:38:30 2004// */
|
||||
/** CVS Reference : /lib_usart.h/1.5/Thu Nov 21 16:01:54 2002// */
|
||||
/** CVS Reference : /lib_spi2.h/1.1/Mon Aug 25 14:23:52 2003// */
|
||||
/** CVS Reference : /lib_pitc_6079A.h/1.2/Tue Nov 9 14:43:56 2004// */
|
||||
/** CVS Reference : /lib_aic_6075b.h/1.1/Fri May 20 14:01:19 2005// */
|
||||
/** CVS Reference : /lib_aes_6149a.h/1.1/Mon Jan 17 07:43:09 2005// */
|
||||
/** CVS Reference : /lib_twi.h/1.3/Mon Jul 19 14:27:58 2004// */
|
||||
/** CVS Reference : /lib_adc.h/1.6/Fri Oct 17 09:12:38 2003// */
|
||||
/** CVS Reference : /lib_rttc_6081A.h/1.1/Wed Oct 6 10:39:38 2004// */
|
||||
/** CVS Reference : /lib_udp.h/1.4/Wed Feb 16 08:39:34 2005// */
|
||||
/** CVS Reference : /lib_des3_6150a.h/1.1/Mon Jan 17 09:19:19 2005// */
|
||||
/** CVS Reference : /lib_tc_1753b.h/1.1/Fri Jan 31 12:20:02 2003// */
|
||||
/** CVS Reference : /lib_MC_SAM7X.h/1.1/Thu Mar 25 15:19:14 2004// */
|
||||
/** CVS Reference : /lib_pio.h/1.3/Fri Jan 31 12:18:56 2003// */
|
||||
/** CVS Reference : /lib_can_AT91.h/1.4/Fri Oct 17 09:12:50 2003// */
|
||||
/** CVS Reference : /lib_PWM_SAM.h/1.3/Thu Jan 22 10:10:50 2004// */
|
||||
/** CVS Reference : /lib_pdc.h/1.2/Tue Jul 2 13:29:40 2002// */
|
||||
/** ---------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_AIC_ConfigureIt
|
||||
//* \brief Interrupt Handler Initialization
|
||||
//*----------------------------------------------------------------------------
|
||||
|
||||
/**---------------------------------------------------------------------------- */
|
||||
/** \fn AT91F_AIC_ConfigureIt */
|
||||
/** \brief Interrupt Handler Initialization */
|
||||
/**---------------------------------------------------------------------------- */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -26,12 +26,12 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
|
@ -44,137 +44,139 @@
|
|||
#include "AT91SAM7X256.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the PIT. */
|
||||
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
|
||||
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
|
||||
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
|
||||
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
|
||||
|
||||
#define portINT_LEVEL_SENSITIVE 0
|
||||
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
|
||||
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
|
||||
#define portINT_LEVEL_SENSITIVE 0
|
||||
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
|
||||
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
StackType_t * pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
* is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
/* 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 in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
* start of the task. The offset is added to make the return address appear
|
||||
* as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
* R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
* system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
pxTopOfStack--;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
* means the interrupt flags cannot always be stored on the stack and will
|
||||
* instead be stored in a variable, which is then saved as part of the
|
||||
* tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
* is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -183,30 +185,23 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
AT91PS_PITC pxPIT = AT91C_BASE_PITC;
|
||||
AT91PS_PITC pxPIT = AT91C_BASE_PITC;
|
||||
|
||||
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
|
||||
on whether the preemptive or cooperative scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 0
|
||||
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
|
||||
* on whether the preemptive or cooperative scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 0
|
||||
extern void( vNonPreemptiveTick ) ( void );
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void ( * )( void ) )vNonPreemptiveTick );
|
||||
#else
|
||||
extern void( vPreemptiveTick )( void );
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void ( * )( void ) )vPreemptiveTick );
|
||||
#endif
|
||||
|
||||
extern void ( vNonPreemptiveTick ) ( void );
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vNonPreemptiveTick );
|
||||
/* Configure the PIT period. */
|
||||
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
|
||||
|
||||
#else
|
||||
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPreemptiveTick );
|
||||
|
||||
#endif
|
||||
|
||||
/* Configure the PIT period. */
|
||||
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
|
||||
|
||||
/* Enable the interrupt. Global interrupts are disables at this point so
|
||||
this is safe. */
|
||||
/* Enable the interrupt. Global interrupts are disables at this point so
|
||||
* this is safe. */
|
||||
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,17 +26,17 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
* Changes from V3.2.4
|
||||
*
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
+ than each line having its own asm block.
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
|
@ -45,17 +45,17 @@
|
|||
#include "AT91SAM7X256.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
void vPortYieldProcessor( void ) __attribute__( ( interrupt( "SWI" ), naked ) );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
|
|
@ -66,9 +66,9 @@ void vPortISRStartFirstTask( void );
|
|||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
* called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -82,19 +82,19 @@ void vPortISRStartFirstTask( void )
|
|||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
* address, but an SWI ISR does not. Add the offset manually so the same
|
||||
* ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4");
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -105,49 +105,49 @@ void vPortYieldProcessor( void )
|
|||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
uint32_t ulDummy;
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
* simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__( ( interrupt( "IRQ" ) ) );
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
uint32_t ulDummy;
|
||||
|
||||
/* Increment the tick count - which may wake some tasks but as the
|
||||
preemptive scheduler is not being used any woken task is not given
|
||||
processor time no matter what its priority. */
|
||||
xTaskIncrementTick();
|
||||
/* Increment the tick count - which may wake some tasks but as the
|
||||
* preemptive scheduler is not being used any woken task is not given
|
||||
* processor time no matter what its priority. */
|
||||
xTaskIncrementTick();
|
||||
|
||||
/* Clear the PIT interrupt. */
|
||||
ulDummy = AT91C_BASE_PITC->PITC_PIVR;
|
||||
/* Clear the PIT interrupt. */
|
||||
ulDummy = AT91C_BASE_PITC->PITC_PIVR;
|
||||
|
||||
/* End the interrupt in the AIC. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = ulDummy;
|
||||
}
|
||||
/* End the interrupt in the AIC. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = ulDummy;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* if configUSE_PREEMPTION == 0 */
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
* saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__( ( naked ) );
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the tick count - this may wake a task. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
/* Increment the tick count - this may wake a task. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* End the interrupt in the AIC. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR;
|
||||
/* End the interrupt in the AIC. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR;
|
||||
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* if configUSE_PREEMPTION == 0 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
@ -156,71 +156,70 @@ void vPortYieldProcessor( void )
|
|||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t"/* Pop R0. */
|
||||
"BX R14"); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t"/* Pop R0. */
|
||||
"BX R14"); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
* different optimisation levels. The interrupt flags can therefore not always
|
||||
* be saved to the stack. Instead the critical section nesting level is stored
|
||||
* in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0}"); /* Pop R0. */
|
||||
|
||||
/* 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++;
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* 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 == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
* re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0}"); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,34 +25,34 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
* Changes from V3.2.3
|
||||
*
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
+
|
||||
+ Changes from V3.2.4
|
||||
+
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
+ replaced them with hard coded registers. This will ensure the
|
||||
+ assembler does not select the link register as the temp register as
|
||||
+ was occasionally happening previously.
|
||||
+
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
+ than each line having its own asm block.
|
||||
+
|
||||
+ Changes from V4.5.0
|
||||
+
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
+ and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
+ should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
+ macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -65,32 +65,32 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
@ -103,92 +103,92 @@ typedef unsigned long UBaseType_t;
|
|||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"LDR LR, [R0] \n\t"\
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t"\
|
||||
"LDMFD LR!, {R1} \n\t"\
|
||||
"STR R1, [R0] \n\t"\
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t"\
|
||||
"MSR SPSR, R0 \n\t"\
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t"\
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t"\
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t"\
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
"SUB SP, SP, #4 \n\t"\
|
||||
"LDMIA SP!,{R0} \n\t"\
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t"\
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t"\
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t"\
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
"SUB LR, LR, #60 \n\t"\
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t"\
|
||||
"STMDB LR!, {R0} \n\t"\
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"STMDB LR!, {R0} \n\t"\
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"STR LR, [R0] \n\t"\
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
@ -201,48 +201,47 @@ extern volatile uint32_t ulCriticalNesting; \
|
|||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */\
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */\
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */\
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */\
|
||||
"LDMIA SP!, {R0} ") /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */\
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */\
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */\
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */\
|
||||
"LDMIA SP!, {R0} ") /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
|
|
@ -42,134 +42,136 @@
|
|||
#include "task.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the VIC for the tick ISR. */
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
StackType_t * pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
* is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
/* 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 in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
* start of the task. The offset is added to make the return address appear
|
||||
* as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
* R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
* system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
pxTopOfStack--;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
* means the interrupt flags cannot always be stored on the stack and will
|
||||
* instead be stored in a variable, which is then saved as part of the
|
||||
* tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
* is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -178,43 +180,41 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
extern void ( vTickISR )( void );
|
||||
uint32_t ulCompareMatch;
|
||||
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
defaulted to zero but can be used if necessary. */
|
||||
T0_PR = portPRESCALE_VALUE;
|
||||
extern void( vTickISR )( void );
|
||||
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
* defaulted to zero but can be used if necessary. */
|
||||
T0_PR = portPRESCALE_VALUE;
|
||||
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
T0_MR0 = ulCompareMatch;
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
* in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
T0_MR0 = ulCompareMatch;
|
||||
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );
|
||||
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
|
||||
|
||||
/* The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
|
||||
|
||||
VICVectAddr0 = ( int32_t ) vTickISR;
|
||||
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );
|
||||
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
|
||||
|
||||
/* Start the timer - interrupts are disabled when this function is called
|
||||
so it is okay to do this here. */
|
||||
T0_TCR = portENABLE_TIMER;
|
||||
/* The ISR installed depends on whether the preemptive or cooperative
|
||||
* scheduler is being used. */
|
||||
|
||||
VICVectAddr0 = ( int32_t ) vTickISR;
|
||||
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
|
||||
|
||||
/* Start the timer - interrupts are disabled when this function is called
|
||||
* so it is okay to do this here. */
|
||||
T0_TCR = portENABLE_TIMER;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,45 +26,45 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V2.5.2
|
||||
|
||||
+ The critical section management functions have been changed. These no
|
||||
longer modify the stack and are safe to use at all optimisation levels.
|
||||
The functions are now also the same for both ARM and THUMB modes.
|
||||
|
||||
Changes from V2.6.0
|
||||
|
||||
+ Removed the 'static' from the definition of vNonPreemptiveTick() to
|
||||
allow the demo to link when using the cooperative scheduler.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
* Changes from V2.5.2
|
||||
*
|
||||
+ The critical section management functions have been changed. These no
|
||||
+ longer modify the stack and are safe to use at all optimisation levels.
|
||||
+ The functions are now also the same for both ARM and THUMB modes.
|
||||
+
|
||||
+ Changes from V2.6.0
|
||||
+
|
||||
+ Removed the 'static' from the definition of vNonPreemptiveTick() to
|
||||
+ allow the demo to link when using the cooperative scheduler.
|
||||
+
|
||||
+ Changes from V3.2.4
|
||||
+
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
+ than each line having its own asm block.
|
||||
*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
void vPortYieldProcessor( void ) __attribute__( ( interrupt( "SWI" ), naked ) );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
|
|
@ -75,9 +75,9 @@ void vPortISRStartFirstTask( void );
|
|||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
* called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -91,48 +91,48 @@ void vPortISRStartFirstTask( void )
|
|||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
* address, but an SWI ISR does not. Add the offset manually so the same
|
||||
* ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4");
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
__asm volatile ( "bl vTaskSwitchContext" );
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
__asm volatile ( "bl vTaskSwitchContext" );
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick.
|
||||
*/
|
||||
void vTickISR( void ) __attribute__((naked));
|
||||
void vTickISR( void ) __attribute__( ( naked ) );
|
||||
void vTickISR( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
__asm volatile
|
||||
(
|
||||
" bl xTaskIncrementTick \t\n" \
|
||||
" cmp r0, #0 \t\n" \
|
||||
" beq SkipContextSwitch \t\n" \
|
||||
" bl vTaskSwitchContext \t\n" \
|
||||
"SkipContextSwitch: \t\n"
|
||||
);
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
* task that is ready to run. */
|
||||
__asm volatile
|
||||
(
|
||||
" bl xTaskIncrementTick \t\n"\
|
||||
" cmp r0, #0 \t\n"\
|
||||
" beq SkipContextSwitch \t\n"\
|
||||
" bl vTaskSwitchContext \t\n"\
|
||||
"SkipContextSwitch: \t\n"
|
||||
);
|
||||
|
||||
/* Ready for the next interrupt. */
|
||||
T0_IR = portTIMER_MATCH_ISR_BIT;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
/* Ready for the next interrupt. */
|
||||
T0_IR = portTIMER_MATCH_ISR_BIT;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -144,71 +144,71 @@ void vTickISR( void )
|
|||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t"/* Pop R0. */
|
||||
"BX R14"); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t"/* Pop R0. */
|
||||
"BX R14"); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
* different optimisation levels. The interrupt flags can therefore not always
|
||||
* be saved to the stack. Instead the critical section nesting level is stored
|
||||
* in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0}"); /* Pop R0. */
|
||||
|
||||
/* 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++;
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* 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 == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
* re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0}"); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,32 +42,32 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
@ -80,92 +80,92 @@ typedef unsigned long UBaseType_t;
|
|||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"LDR LR, [R0] \n\t"\
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t"\
|
||||
"LDMFD LR!, {R1} \n\t"\
|
||||
"STR R1, [R0] \n\t"\
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t"\
|
||||
"MSR SPSR, R0 \n\t"\
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t"\
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t"\
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t"\
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
"SUB SP, SP, #4 \n\t"\
|
||||
"LDMIA SP!,{R0} \n\t"\
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t"\
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t"\
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t"\
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
"SUB LR, LR, #60 \n\t"\
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t"\
|
||||
"STMDB LR!, {R0} \n\t"\
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"STMDB LR!, {R0} \n\t"\
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"STR LR, [R0] \n\t"\
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
@ -178,48 +178,47 @@ extern void vTaskSwitchContext( void );
|
|||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */\
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */\
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */\
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */\
|
||||
"LDMIA SP!, {R0} ") /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */\
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */\
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */\
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */\
|
||||
"LDMIA SP!, {R0} ") /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
|
|
@ -42,134 +42,136 @@
|
|||
#include "task.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the VIC for the tick ISR. */
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
StackType_t * pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
* is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
* start of the task. The offset is added to make the return address appear
|
||||
* as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
* R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
* system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
pxTopOfStack--;
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
pxTopOfStack--;
|
||||
|
||||
return pxTopOfStack;
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
* means the interrupt flags cannot always be stored on the stack and will
|
||||
* instead be stored in a variable, which is then saved as part of the
|
||||
* tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
* is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -178,55 +180,52 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
uint32_t ulCompareMatch;
|
||||
|
||||
PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2);
|
||||
T0TCR = 2; /* Stop and reset the timer */
|
||||
T0CTCR = 0; /* Timer mode */
|
||||
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
defaulted to zero but can be used if necessary. */
|
||||
T0PR = portPRESCALE_VALUE;
|
||||
PCLKSEL0 = ( PCLKSEL0 & ( ~( 0x3 << 2 ) ) ) | ( 0x01 << 2 );
|
||||
T0TCR = 2; /* Stop and reset the timer */
|
||||
T0CTCR = 0; /* Timer mode */
|
||||
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
* defaulted to zero but can be used if necessary. */
|
||||
T0PR = portPRESCALE_VALUE;
|
||||
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
T0MR1 = ulCompareMatch;
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0MCR = (3 << 3); /* Reset timer on match and generate interrupt */
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
* in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
T0MR1 = ulCompareMatch;
|
||||
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntEnable = 0x00000010;
|
||||
|
||||
/* The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
VICVectAddr4 = ( int32_t ) vPreemptiveTick;
|
||||
}
|
||||
#else
|
||||
{
|
||||
extern void ( vNonPreemptiveTick )( void );
|
||||
VICVectAddr4 = ( int32_t ) vNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0MCR = ( 3 << 3 ); /* Reset timer on match and generate interrupt */
|
||||
|
||||
VICVectCntl4 = 1;
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntEnable = 0x00000010;
|
||||
|
||||
/* Start the timer - interrupts are disabled when this function is called
|
||||
so it is okay to do this here. */
|
||||
T0TCR = portENABLE_TIMER;
|
||||
/* The ISR installed depends on whether the preemptive or cooperative
|
||||
* scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
extern void( vPreemptiveTick )( void );
|
||||
VICVectAddr4 = ( int32_t ) vPreemptiveTick;
|
||||
}
|
||||
#else
|
||||
{
|
||||
extern void( vNonPreemptiveTick )( void );
|
||||
VICVectAddr4 = ( int32_t ) vNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
|
||||
VICVectCntl4 = 1;
|
||||
|
||||
/* Start the timer - interrupts are disabled when this function is called
|
||||
* so it is okay to do this here. */
|
||||
T0TCR = portENABLE_TIMER;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,29 +26,29 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
void vPortYieldProcessor( void ) __attribute__( ( interrupt( "SWI" ), naked ) );
|
||||
|
||||
/*
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
|
|
@ -57,39 +57,39 @@ void vPortISRStartFirstTask( void );
|
|||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
* called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
* address, but an SWI ISR does not. Add the offset manually so the same
|
||||
* ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4");
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
__asm volatile( "bl vTaskSwitchContext" );
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
__asm volatile ( "bl vTaskSwitchContext");
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
|
|
@ -97,46 +97,46 @@ void vPortYieldProcessor( void )
|
|||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
T0IR = 2;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
}
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
* simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__( ( interrupt( "IRQ" ) ) );
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
T0IR = 2;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* if configUSE_PREEMPTION == 0 */
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
* saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__( ( naked ) );
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
__asm volatile
|
||||
(
|
||||
" bl xTaskIncrementTick \t\n" \
|
||||
" cmp r0, #0 \t\n" \
|
||||
" beq SkipContextSwitch \t\n" \
|
||||
" bl vTaskSwitchContext \t\n" \
|
||||
"SkipContextSwitch: \t\n"
|
||||
);
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
* task that is ready to run. */
|
||||
__asm volatile
|
||||
(
|
||||
" bl xTaskIncrementTick \t\n"\
|
||||
" cmp r0, #0 \t\n"\
|
||||
" beq SkipContextSwitch \t\n"\
|
||||
" bl vTaskSwitchContext \t\n"\
|
||||
"SkipContextSwitch: \t\n"
|
||||
);
|
||||
|
||||
/* Ready for the next interrupt. */
|
||||
T0IR = 2;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/* Ready for the next interrupt. */
|
||||
T0IR = 2;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
|
||||
#endif
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif /* if configUSE_PREEMPTION == 0 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
@ -147,71 +147,71 @@ void vPortYieldProcessor( void )
|
|||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t"/* Pop R0. */
|
||||
"BX R14"); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t"/* Pop R0. */
|
||||
"BX R14"); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
* different optimisation levels. The interrupt flags can therefore not always
|
||||
* be saved to the stack. Instead the critical section nesting level is stored
|
||||
* in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0}"); /* Pop R0. */
|
||||
|
||||
/* 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++;
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* 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 == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
* re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t"/* Push R0. */
|
||||
"MRS R0, CPSR \n\t"/* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t"/* Write back modified value. */
|
||||
"LDMIA SP!, {R0}"); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,34 +25,34 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
* Changes from V3.2.3
|
||||
*
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
+
|
||||
+ Changes from V3.2.4
|
||||
+
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
+ replaced them with hard coded registers. This will ensure the
|
||||
+ assembler does not select the link register as the temp register as
|
||||
+ was occasionally happening previously.
|
||||
+
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
+ than each line having its own asm block.
|
||||
+
|
||||
+ Changes from V4.5.0
|
||||
+
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
+ and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
+ should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
+ macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -65,32 +65,32 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
@ -103,92 +103,92 @@ typedef unsigned long UBaseType_t;
|
|||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"LDR LR, [R0] \n\t"\
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t"\
|
||||
"LDMFD LR!, {R1} \n\t"\
|
||||
"STR R1, [R0] \n\t"\
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t"\
|
||||
"MSR SPSR, R0 \n\t"\
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t"\
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t"\
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t"\
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
"SUB SP, SP, #4 \n\t"\
|
||||
"LDMIA SP!,{R0} \n\t"\
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t"\
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t"\
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t"\
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t"\
|
||||
"NOP \n\t"\
|
||||
"SUB LR, LR, #60 \n\t"\
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t"\
|
||||
"STMDB LR!, {R0} \n\t"\
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"STMDB LR!, {R0} \n\t"\
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t"\
|
||||
"LDR R0, [R0] \n\t"\
|
||||
"STR LR, [R0] \n\t"\
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
@ -201,48 +201,47 @@ extern volatile uint32_t ulCriticalNesting; \
|
|||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */\
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */\
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */\
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */\
|
||||
"LDMIA SP!, {R0} ") /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */\
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */\
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */\
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */\
|
||||
"LDMIA SP!, {R0} ") /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -32,104 +32,104 @@
|
|||
#include "task.h"
|
||||
|
||||
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
|
||||
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
|
||||
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif /* configSETUP_TICK_INTERRUPT */
|
||||
|
||||
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* 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
|
||||
/* 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
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/* In case security extensions are implemented. */
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#endif
|
||||
|
||||
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
|
||||
portmacro.h. */
|
||||
* portmacro.h. */
|
||||
#ifndef configCLEAR_TICK_INTERRUPT
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
|
||||
* this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
|
||||
|
||||
/* In all GICs 255 can be written to the priority mask register to unmask all
|
||||
(but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
* (but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
|
||||
/* Tasks are not created with a floating point context, but can be given a
|
||||
floating point context after they have been created. A variable is stored as
|
||||
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
does not have an FPU context, or any other value if the task does have an FPU
|
||||
context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
* floating point context after they have been created. A variable is stored as
|
||||
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
* does not have an FPU context, or any other value if the task does have an FPU
|
||||
* context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the initial task context. */
|
||||
#define portSP_ELx ( ( StackType_t ) 0x01 )
|
||||
#define portSP_EL0 ( ( StackType_t ) 0x00 )
|
||||
#define portSP_ELx ( ( StackType_t ) 0x01 )
|
||||
#define portSP_EL0 ( ( StackType_t ) 0x00 )
|
||||
|
||||
#if defined( GUEST )
|
||||
#define portEL1 ( ( StackType_t ) 0x04 )
|
||||
#define portINITIAL_PSTATE ( portEL1 | portSP_EL0 )
|
||||
#define portEL1 ( ( StackType_t ) 0x04 )
|
||||
#define portINITIAL_PSTATE ( portEL1 | portSP_EL0 )
|
||||
#else
|
||||
#define portEL3 ( ( StackType_t ) 0x0c )
|
||||
/* At the time of writing, the BSP only supports EL3. */
|
||||
#define portINITIAL_PSTATE ( portEL3 | portSP_EL0 )
|
||||
#define portEL3 ( ( StackType_t ) 0x0c )
|
||||
/* At the time of writing, the BSP only supports EL3. */
|
||||
#define portINITIAL_PSTATE ( portEL3 | portSP_EL0 )
|
||||
#endif
|
||||
|
||||
|
||||
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
|
||||
point is zero. */
|
||||
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
|
||||
* point is zero. */
|
||||
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x0C )
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x0C )
|
||||
|
||||
/* The I bit in the DAIF bits. */
|
||||
#define portDAIF_I ( 0x80 )
|
||||
#define portDAIF_I ( 0x80 )
|
||||
|
||||
/* Macro to unmask all interrupt priorities. */
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
|
||||
__asm volatile ( "DSB SY \n" \
|
||||
"ISB SY \n" ); \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
}
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
|
||||
__asm volatile ( "DSB SY \n" \
|
||||
"ISB SY \n"); \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
}
|
||||
|
||||
/* Hardware specifics used when sanity checking the configuration. */
|
||||
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
|
||||
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -142,376 +142,381 @@ extern void vPortRestoreTaskContext( void );
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* A variable is used to keep track of the critical section nesting. This
|
||||
variable has to be stored as part of the task context and must be initialised to
|
||||
a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
the scheduler starts. As it is stored as part of the task context it will
|
||||
automatically be set to 0 when the first task is started. */
|
||||
volatile uint64_t ullCriticalNesting = 9999ULL;
|
||||
* variable has to be stored as part of the task context and must be initialised to
|
||||
* a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
* the scheduler starts. As it is stored as part of the task context it will
|
||||
* automatically be set to 0 when the first task is started. */
|
||||
volatile uint64_t ullCriticalNesting = 9999ULL;
|
||||
|
||||
/* Saved as part of the task context. If ullPortTaskHasFPUContext is non-zero
|
||||
then floating point context must be saved and restored for the task. */
|
||||
uint64_t ullPortTaskHasFPUContext = pdFALSE;
|
||||
* then floating point context must be saved and restored for the task. */
|
||||
uint64_t ullPortTaskHasFPUContext = pdFALSE;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
uint64_t ullPortYieldRequired = pdFALSE;
|
||||
uint64_t ullPortYieldRequired = pdFALSE;
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||
if the nesting depth is 0. */
|
||||
uint64_t ullPortInterruptNesting = 0;
|
||||
* if the nesting depth is 0. */
|
||||
uint64_t ullPortInterruptNesting = 0;
|
||||
|
||||
/* Used in the ASM code. */
|
||||
__attribute__(( used )) const uint64_t ullICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint64_t ullICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint64_t ullICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__attribute__( ( used ) ) const uint64_t ullICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint64_t ullICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint64_t ullICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0101010101010101ULL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0303030303030303ULL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0202020202020202ULL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0505050505050505ULL; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0404040404040404ULL; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0707070707070707ULL; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0606060606060606ULL; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0909090909090909ULL; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0808080808080808ULL; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1111111111111111ULL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1010101010101010ULL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1313131313131313ULL; /* R13 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1212121212121212ULL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1515151515151515ULL; /* R15 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1414141414141414ULL; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1717171717171717ULL; /* R17 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1616161616161616ULL; /* R16 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1919191919191919ULL; /* R19 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1818181818181818ULL; /* R18 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2121212121212121ULL; /* R21 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2020202020202020ULL; /* R20 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2323232323232323ULL; /* R23 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2222222222222222ULL; /* R22 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2525252525252525ULL; /* R25 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2424242424242424ULL; /* R24 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2727272727272727ULL; /* R27 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2626262626262626ULL; /* R26 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2929292929292929ULL; /* R29 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2828282828282828ULL; /* R28 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
|
||||
pxTopOfStack--;
|
||||
/* First all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0101010101010101ULL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0303030303030303ULL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0202020202020202ULL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0505050505050505ULL; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0404040404040404ULL; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0707070707070707ULL; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0606060606060606ULL; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0909090909090909ULL; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0808080808080808ULL; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1111111111111111ULL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1010101010101010ULL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1313131313131313ULL; /* R13 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1212121212121212ULL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1515151515151515ULL; /* R15 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1414141414141414ULL; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1717171717171717ULL; /* R17 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1616161616161616ULL; /* R16 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1919191919191919ULL; /* R19 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1818181818181818ULL; /* R18 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2121212121212121ULL; /* R21 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2020202020202020ULL; /* R20 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2323232323232323ULL; /* R23 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2222222222222222ULL; /* R22 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2525252525252525ULL; /* R25 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2424242424242424ULL; /* R24 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2727272727272727ULL; /* R27 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2626262626262626ULL; /* R26 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2929292929292929ULL; /* R29 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2828282828282828ULL; /* R28 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = portINITIAL_PSTATE;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_PSTATE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
* enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The task will start without a floating point context. A task that uses
|
||||
the floating point hardware must call vPortTaskUsesFPU() before executing
|
||||
any floating point instructions. */
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
/* The task will start without a floating point context. A task that uses
|
||||
* the floating point hardware must call vPortTaskUsesFPU() before executing
|
||||
* any floating point instructions. */
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
uint32_t ulAPSR;
|
||||
uint32_t ulAPSR;
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine how many priority bits are implemented in the GIC.
|
||||
/* Determine how many priority bits are implemented in the GIC.
|
||||
*
|
||||
* Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
/* Determine the number of priority bits available. First write to
|
||||
* all possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Determine the number of priority bits available. First write to
|
||||
all possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
/* Shift to the least significant bits. */
|
||||
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
|
||||
{
|
||||
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
/* Shift to the least significant bits. */
|
||||
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
|
||||
{
|
||||
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
|
||||
}
|
||||
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
|
||||
* value. */
|
||||
|
||||
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
|
||||
value. */
|
||||
|
||||
configASSERT( ucMaxPriorityValue >= portLOWEST_INTERRUPT_PRIORITY );
|
||||
configASSERT( ucMaxPriorityValue >= portLOWEST_INTERRUPT_PRIORITY );
|
||||
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
* value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
|
||||
/* At the time of writing, the BSP only supports EL3. */
|
||||
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
/* At the time of writing, the BSP only supports EL3. */
|
||||
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
|
||||
#if defined( GUEST )
|
||||
#warning Building for execution as a guest under XEN. THIS IS NOT A FULLY TESTED PATH.
|
||||
configASSERT( ulAPSR == portEL1 );
|
||||
if( ulAPSR == portEL1 )
|
||||
#else
|
||||
configASSERT( ulAPSR == portEL3 );
|
||||
if( ulAPSR == portEL3 )
|
||||
#endif
|
||||
{
|
||||
/* Only continue if the binary point value is set to its lowest possible
|
||||
setting. See the comments in vPortValidateInterruptPriority() below for
|
||||
more information. */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
#if defined( GUEST )
|
||||
#warning Building for execution as a guest under XEN. THIS IS NOT A FULLY TESTED PATH.
|
||||
configASSERT( ulAPSR == portEL1 );
|
||||
|
||||
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
{
|
||||
/* Interrupts are turned off in the CPU itself to ensure a tick does
|
||||
not execute while the scheduler is being started. Interrupts are
|
||||
automatically turned back on in the CPU when the first task starts
|
||||
executing. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( ulAPSR == portEL1 )
|
||||
#else
|
||||
configASSERT( ulAPSR == portEL3 );
|
||||
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
if( ulAPSR == portEL3 )
|
||||
#endif
|
||||
{
|
||||
/* Only continue if the binary point value is set to its lowest possible
|
||||
* setting. See the comments in vPortValidateInterruptPriority() below for
|
||||
* more information. */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
}
|
||||
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
{
|
||||
/* Interrupts are turned off in the CPU itself to ensure a tick does
|
||||
* not execute while the scheduler is being started. Interrupts are
|
||||
* automatically turned back on in the CPU when the first task starts
|
||||
* executing. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
return 0;
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ullCriticalNesting == 1000ULL );
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ullCriticalNesting == 1000ULL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Mask interrupts up to the max syscall interrupt priority. */
|
||||
uxPortSetInterruptMask();
|
||||
/* Mask interrupts up to the max syscall interrupt priority. */
|
||||
uxPortSetInterruptMask();
|
||||
|
||||
/* Now interrupts are disabled ullCriticalNesting can be accessed
|
||||
directly. Increment ullCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ullCriticalNesting++;
|
||||
/* Now interrupts are disabled ullCriticalNesting can be accessed
|
||||
* directly. Increment ullCriticalNesting to keep a count of how many times
|
||||
* portENTER_CRITICAL() has been called. */
|
||||
ullCriticalNesting++;
|
||||
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
assert() if it is being called from an interrupt context. Only API
|
||||
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
the critical nesting count is 1 to protect against recursive calls if the
|
||||
assert function also uses a critical section. */
|
||||
if( ullCriticalNesting == 1ULL )
|
||||
{
|
||||
configASSERT( ullPortInterruptNesting == 0 );
|
||||
}
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
* assert() if it is being called from an interrupt context. Only API
|
||||
* functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
* the critical nesting count is 1 to protect against recursive calls if the
|
||||
* assert function also uses a critical section. */
|
||||
if( ullCriticalNesting == 1ULL )
|
||||
{
|
||||
configASSERT( ullPortInterruptNesting == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ullCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ullCriticalNesting--;
|
||||
if( ullCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
* exited. */
|
||||
ullCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ullCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
* priorities must be re-enabled. */
|
||||
if( ullCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
* should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
/* Must be the lowest possible priority. */
|
||||
#if !defined( QEMU )
|
||||
{
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER == ( uint32_t ) ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
}
|
||||
#endif
|
||||
/* Must be the lowest possible priority. */
|
||||
#if !defined( QEMU )
|
||||
{
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER == ( uint32_t ) ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Interrupts should not be enabled before this point. */
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
uint32_t ulMaskBits;
|
||||
/* Interrupts should not be enabled before this point. */
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
uint32_t ulMaskBits;
|
||||
|
||||
__asm volatile( "mrs %0, daif" : "=r"( ulMaskBits ) :: "memory" );
|
||||
configASSERT( ( ulMaskBits & portDAIF_I ) != 0 );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
__asm volatile ( "mrs %0, daif" : "=r" ( ulMaskBits )::"memory" );
|
||||
configASSERT( ( ulMaskBits & portDAIF_I ) != 0 );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
so there is no need to save and restore the current mask value. It is
|
||||
necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
updated. */
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb sy \n"
|
||||
"isb sy \n" ::: "memory" );
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
* handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
* so there is no need to save and restore the current mask value. It is
|
||||
* necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
* updated. */
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb sy \n"
|
||||
"isb sy \n"::: "memory" );
|
||||
|
||||
/* Ok to enable interrupts after the interrupt source has been cleared. */
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
portENABLE_INTERRUPTS();
|
||||
/* Ok to enable interrupts after the interrupt source has been cleared. */
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ullPortYieldRequired = pdTRUE;
|
||||
}
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ullPortYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
FPU flag (which is saved as part of the task context). */
|
||||
ullPortTaskHasFPUContext = pdTRUE;
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
* FPU flag (which is saved as part of the task context). */
|
||||
ullPortTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Consider initialising the FPSR here - but probably not necessary in
|
||||
AArch64. */
|
||||
/* Consider initialising the FPSR here - but probably not necessary in
|
||||
* AArch64. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )
|
||||
{
|
||||
if( uxNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
if( uxNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxPortSetInterruptMask( void )
|
||||
{
|
||||
uint32_t ulReturn;
|
||||
uint32_t ulReturn;
|
||||
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
updated. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb sy \n"
|
||||
"isb sy \n" ::: "memory" );
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
* updated. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
return ulReturn;
|
||||
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb sy \n"
|
||||
"isb sy \n"::: "memory" );
|
||||
}
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
return ulReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
* an interrupt that has been assigned a priority above
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
* function. ISR safe FreeRTOS API functions must *only* be called
|
||||
* from interrupts that have been assigned a priority at or below
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*
|
||||
* Numerically low interrupt priority numbers represent logically high
|
||||
* interrupt priorities, therefore the priority of the interrupt must
|
||||
* be set to a value equal to or numerically *higher* than
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*
|
||||
* FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
* interrupt entry is as fast and simple as possible. */
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible. */
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
|
||||
/* Priority grouping: The interrupt controller (GIC) allows the bits
|
||||
that define each interrupt's priority to be split between bits that
|
||||
define the interrupt's pre-emption priority bits and bits that define
|
||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
to be pre-emption priority bits. The following assertion will fail if
|
||||
this is not the case (if some bits represent a sub-priority).
|
||||
|
||||
The priority grouping is configured by the GIC's binary point register
|
||||
(ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
|
||||
possible value (which may be above 0). */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
}
|
||||
/* Priority grouping: The interrupt controller (GIC) allows the bits
|
||||
* that define each interrupt's priority to be split between bits that
|
||||
* define the interrupt's pre-emption priority bits and bits that define
|
||||
* the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
* to be pre-emption priority bits. The following assertion will fail if
|
||||
* this is not the case (if some bits represent a sub-priority).
|
||||
*
|
||||
* The priority grouping is configured by the GIC's binary point register
|
||||
* (ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
|
||||
* possible value (which may be above 0). */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,169 +42,169 @@
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE size_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE size_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef portBASE_TYPE BaseType_t;
|
||||
typedef uint64_t UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef portBASE_TYPE BaseType_t;
|
||||
typedef uint64_t UBaseType_t;
|
||||
|
||||
typedef uint64_t TickType_t;
|
||||
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffffffffff )
|
||||
typedef uint64_t TickType_t;
|
||||
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffffffffff )
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 16
|
||||
#define portPOINTER_SIZE_TYPE uint64_t
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 16
|
||||
#define portPOINTER_SIZE_TYPE uint64_t
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint64_t ullPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ullPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern uint64_t ullPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ullPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#if defined( GUEST )
|
||||
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
|
||||
#else
|
||||
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
|
||||
#endif
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#if defined( GUEST )
|
||||
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
|
||||
#else
|
||||
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
|
||||
#endif
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern UBaseType_t uxPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern UBaseType_t uxPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
* not required for this port but included in case common demo code that uses these
|
||||
* macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
* handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
* before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* 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 ) )
|
||||
/* 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 - __builtin_clz( uxReadyPriorities ) )
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE __inline
|
||||
#define portNOP() __asm volatile ( "NOP" )
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
* number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
|
||||
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -32,123 +32,123 @@
|
|||
#include "task.h"
|
||||
|
||||
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
|
||||
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
|
||||
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif /* configSETUP_TICK_INTERRUPT */
|
||||
|
||||
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* 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
|
||||
/* 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
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/* In case security extensions are implemented. */
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#endif
|
||||
|
||||
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
|
||||
portmacro.h. */
|
||||
* portmacro.h. */
|
||||
#ifndef configCLEAR_TICK_INTERRUPT
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
* this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
/* In all GICs 255 can be written to the priority mask register to unmask all
|
||||
(but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
* (but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
|
||||
/* Tasks are not created with a floating point context, but can be given a
|
||||
floating point context after they have been created. A variable is stored as
|
||||
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
does not have an FPU context, or any other value if the task does have an FPU
|
||||
context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
* floating point context after they have been created. A variable is stored as
|
||||
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
* does not have an FPU context, or any other value if the task does have an FPU
|
||||
* context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the initial task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINTERRUPT_ENABLE_BIT ( 0x80UL )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINTERRUPT_ENABLE_BIT ( 0x80UL )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
|
||||
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
|
||||
point is zero. */
|
||||
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
|
||||
* point is zero. */
|
||||
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
|
||||
/* The value of the mode bits in the APSR when the CPU is executing in user
|
||||
mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
* mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
|
||||
/* The critical section macros only mask interrupts up to an application
|
||||
determined priority level. Sometimes it is necessary to turn interrupt off in
|
||||
the CPU itself before modifying certain hardware registers. */
|
||||
#define portCPU_IRQ_DISABLE() \
|
||||
__asm volatile ( "CPSID i" ::: "memory" ); \
|
||||
__asm volatile ( "DSB" ); \
|
||||
__asm volatile ( "ISB" );
|
||||
* determined priority level. Sometimes it is necessary to turn interrupt off in
|
||||
* the CPU itself before modifying certain hardware registers. */
|
||||
#define portCPU_IRQ_DISABLE() \
|
||||
__asm volatile ( "CPSID i" ::: "memory" ); \
|
||||
__asm volatile ( "DSB" ); \
|
||||
__asm volatile ( "ISB" );
|
||||
|
||||
#define portCPU_IRQ_ENABLE() \
|
||||
__asm volatile ( "CPSIE i" ::: "memory" ); \
|
||||
__asm volatile ( "DSB" ); \
|
||||
__asm volatile ( "ISB" );
|
||||
#define portCPU_IRQ_ENABLE() \
|
||||
__asm volatile ( "CPSIE i" ::: "memory" ); \
|
||||
__asm volatile ( "DSB" ); \
|
||||
__asm volatile ( "ISB" );
|
||||
|
||||
|
||||
/* Macro to unmask all interrupt priorities. */
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
portCPU_IRQ_DISABLE(); \
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
|
||||
__asm volatile ( "DSB \n" \
|
||||
"ISB \n" ); \
|
||||
portCPU_IRQ_ENABLE(); \
|
||||
}
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
portCPU_IRQ_DISABLE(); \
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
|
||||
__asm volatile ( "DSB \n" \
|
||||
"ISB \n"); \
|
||||
portCPU_IRQ_ENABLE(); \
|
||||
}
|
||||
|
||||
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
|
||||
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
|
||||
|
||||
/* Let the user override the pre-loading of the initial LR with the address of
|
||||
prvTaskExitError() in case it messes up unwinding of the stack in the
|
||||
debugger. */
|
||||
* prvTaskExitError() in case it messes up unwinding of the stack in the
|
||||
* debugger. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/* The space on the stack required to hold the FPU registers. This is 32 64-bit
|
||||
registers, plus a 32-bit status register. */
|
||||
#define portFPU_REGISTER_WORDS ( ( 32 * 2 ) + 1 )
|
||||
* registers, plus a 32-bit status register. */
|
||||
#define portFPU_REGISTER_WORDS ( ( 32 * 2 ) + 1 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -182,386 +182,393 @@ static void prvTaskExitError( void );
|
|||
* FPU registers to be saved on interrupt entry their IRQ handler must be
|
||||
* called vApplicationIRQHandler().
|
||||
*/
|
||||
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__((weak) );
|
||||
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__( ( weak ) );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* A variable is used to keep track of the critical section nesting. This
|
||||
variable has to be stored as part of the task context and must be initialised to
|
||||
a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
the scheduler starts. As it is stored as part of the task context it will
|
||||
automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
* variable has to be stored as part of the task context and must be initialised to
|
||||
* a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
* the scheduler starts. As it is stored as part of the task context it will
|
||||
* automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then
|
||||
a floating point context must be saved and restored for the task. */
|
||||
* a floating point context must be saved and restored for the task. */
|
||||
volatile uint32_t ulPortTaskHasFPUContext = pdFALSE;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
volatile uint32_t ulPortYieldRequired = pdFALSE;
|
||||
volatile uint32_t ulPortYieldRequired = pdFALSE;
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||
if the nesting depth is 0. */
|
||||
volatile uint32_t ulPortInterruptNesting = 0UL;
|
||||
* if the nesting depth is 0. */
|
||||
volatile uint32_t ulPortInterruptNesting = 0UL;
|
||||
|
||||
/* Used in the asm file. */
|
||||
__attribute__(( used )) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__attribute__( ( used ) ) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro.
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro.
|
||||
*
|
||||
* The fist real value on the stack is the status register, which is set for
|
||||
* system mode, with interrupts enabled. A few NULLs are added first to ensure
|
||||
* GDB does not try decoding a non-existent return address. */
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
The fist real value on the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. A few NULLs are added first to ensure
|
||||
GDB does not try decoding a non-existent return address. */
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
|
||||
{
|
||||
/* The task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
|
||||
{
|
||||
/* The task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
pxTopOfStack--;
|
||||
|
||||
pxTopOfStack--;
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
* enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
#if ( configUSE_TASK_FPU_SUPPORT == 1 )
|
||||
{
|
||||
/* The task will start without a floating point context. A task that
|
||||
* uses the floating point hardware must call vPortTaskUsesFPU() before
|
||||
* executing any floating point instructions. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
}
|
||||
#elif ( configUSE_TASK_FPU_SUPPORT == 2 )
|
||||
{
|
||||
/* The task will start with a floating point context. Leave enough
|
||||
* space for the registers - and ensure they are initialised to 0. */
|
||||
pxTopOfStack -= portFPU_REGISTER_WORDS;
|
||||
memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
|
||||
|
||||
#if( configUSE_TASK_FPU_SUPPORT == 1 )
|
||||
{
|
||||
/* The task will start without a floating point context. A task that
|
||||
uses the floating point hardware must call vPortTaskUsesFPU() before
|
||||
executing any floating point instructions. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
}
|
||||
#elif( configUSE_TASK_FPU_SUPPORT == 2 )
|
||||
{
|
||||
/* The task will start with a floating point context. Leave enough
|
||||
space for the registers - and ensure they are initialised to 0. */
|
||||
pxTopOfStack -= portFPU_REGISTER_WORDS;
|
||||
memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = pdTRUE;
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
}
|
||||
#else /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
|
||||
{
|
||||
#error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined.
|
||||
}
|
||||
#endif /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = pdTRUE;
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
}
|
||||
#else
|
||||
{
|
||||
#error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined.
|
||||
}
|
||||
#endif
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
its caller as there is nothing to return to. If a task wants to exit it
|
||||
should instead call vTaskDelete( NULL ).
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
* its caller as there is nothing to return to. If a task wants to exit it
|
||||
* should instead call vTaskDelete( NULL ).
|
||||
*
|
||||
* Artificially force an assert() to be triggered if configASSERT() is
|
||||
* defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( ulPortInterruptNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
Artificially force an assert() to be triggered if configASSERT() is
|
||||
defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( ulPortInterruptNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
for( ; ; )
|
||||
{
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
uint32_t ulAPSR;
|
||||
uint32_t ulAPSR;
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine how many priority bits are implemented in the GIC.
|
||||
/* Determine how many priority bits are implemented in the GIC.
|
||||
*
|
||||
* Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
/* Determine the number of priority bits available. First write to
|
||||
* all possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Determine the number of priority bits available. First write to
|
||||
all possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
/* Shift to the least significant bits. */
|
||||
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
|
||||
{
|
||||
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
/* Shift to the least significant bits. */
|
||||
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
|
||||
{
|
||||
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
|
||||
}
|
||||
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
|
||||
* value. */
|
||||
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
|
||||
|
||||
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
|
||||
value. */
|
||||
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
* value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) :: "memory" );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
* Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
|
||||
if( ulAPSR != portAPSR_USER_MODE )
|
||||
{
|
||||
/* Only continue if the binary point value is set to its lowest possible
|
||||
setting. See the comments in vPortValidateInterruptPriority() below for
|
||||
more information. */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
if( ulAPSR != portAPSR_USER_MODE )
|
||||
{
|
||||
/* Only continue if the binary point value is set to its lowest possible
|
||||
* setting. See the comments in vPortValidateInterruptPriority() below for
|
||||
* more information. */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
|
||||
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
{
|
||||
/* Interrupts are turned off in the CPU itself to ensure tick does
|
||||
not execute while the scheduler is being started. Interrupts are
|
||||
automatically turned back on in the CPU when the first task starts
|
||||
executing. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
{
|
||||
/* Interrupts are turned off in the CPU itself to ensure tick does
|
||||
* not execute while the scheduler is being started. Interrupts are
|
||||
* automatically turned back on in the CPU when the first task starts
|
||||
* executing. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
}
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
}
|
||||
|
||||
/* Will only get here if vTaskStartScheduler() was called with the CPU in
|
||||
a non-privileged mode or the binary point register was not set to its lowest
|
||||
possible value. prvTaskExitError() is referenced to prevent a compiler
|
||||
warning about it being defined but not referenced in the case that the user
|
||||
defines their own exit address. */
|
||||
( void ) prvTaskExitError;
|
||||
return 0;
|
||||
/* Will only get here if vTaskStartScheduler() was called with the CPU in
|
||||
* a non-privileged mode or the binary point register was not set to its lowest
|
||||
* possible value. prvTaskExitError() is referenced to prevent a compiler
|
||||
* warning about it being defined but not referenced in the case that the user
|
||||
* defines their own exit address. */
|
||||
( void ) prvTaskExitError;
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Mask interrupts up to the max syscall interrupt priority. */
|
||||
ulPortSetInterruptMask();
|
||||
/* Mask interrupts up to the max syscall interrupt priority. */
|
||||
ulPortSetInterruptMask();
|
||||
|
||||
/* 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++;
|
||||
/* 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++;
|
||||
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
assert() if it is being called from an interrupt context. Only API
|
||||
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
the critical nesting count is 1 to protect against recursive calls if the
|
||||
assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
* assert() if it is being called from an interrupt context. Only API
|
||||
* functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
* the critical nesting count is 1 to protect against recursive calls if the
|
||||
* assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
* exited. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
* priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
* should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
so there is no need to save and restore the current mask value. It is
|
||||
necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
updated. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb \n"
|
||||
"isb \n" ::: "memory" );
|
||||
portCPU_IRQ_ENABLE();
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
* handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
* so there is no need to save and restore the current mask value. It is
|
||||
* necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
* updated. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb \n"
|
||||
"isb \n"::: "memory" );
|
||||
portCPU_IRQ_ENABLE();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TASK_FPU_SUPPORT != 2 )
|
||||
#if ( configUSE_TASK_FPU_SUPPORT != 2 )
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
FPU flag (which is saved as part of the task context). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
* FPU flag (which is saved as part of the task context). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Initialise the floating point status register. */
|
||||
__asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) : "memory" );
|
||||
}
|
||||
/* Initialise the floating point status register. */
|
||||
__asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
|
||||
}
|
||||
|
||||
#endif /* configUSE_TASK_FPU_SUPPORT */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortClearInterruptMask( uint32_t ulNewMaskValue )
|
||||
{
|
||||
if( ulNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
if( ulNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulPortSetInterruptMask( void )
|
||||
{
|
||||
uint32_t ulReturn;
|
||||
uint32_t ulReturn;
|
||||
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
updated. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb \n"
|
||||
"isb \n" ::: "memory" );
|
||||
}
|
||||
portCPU_IRQ_ENABLE();
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
* updated. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
|
||||
return ulReturn;
|
||||
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb \n"
|
||||
"isb \n"::: "memory" );
|
||||
}
|
||||
|
||||
portCPU_IRQ_ENABLE();
|
||||
|
||||
return ulReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
* an interrupt that has been assigned a priority above
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
* function. ISR safe FreeRTOS API functions must *only* be called
|
||||
* from interrupts that have been assigned a priority at or below
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*
|
||||
* Numerically low interrupt priority numbers represent logically high
|
||||
* interrupt priorities, therefore the priority of the interrupt must
|
||||
* be set to a value equal to or numerically *higher* than
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*
|
||||
* FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
* interrupt entry is as fast and simple as possible. */
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible. */
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
|
||||
/* Priority grouping: The interrupt controller (GIC) allows the bits
|
||||
that define each interrupt's priority to be split between bits that
|
||||
define the interrupt's pre-emption priority bits and bits that define
|
||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
to be pre-emption priority bits. The following assertion will fail if
|
||||
this is not the case (if some bits represent a sub-priority).
|
||||
|
||||
The priority grouping is configured by the GIC's binary point register
|
||||
(ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
|
||||
possible value (which may be above 0). */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
}
|
||||
/* Priority grouping: The interrupt controller (GIC) allows the bits
|
||||
* that define each interrupt's priority to be split between bits that
|
||||
* define the interrupt's pre-emption priority bits and bits that define
|
||||
* the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
* to be pre-emption priority bits. The following assertion will fail if
|
||||
* this is not the case (if some bits represent a sub-priority).
|
||||
*
|
||||
* The priority grouping is configured by the GIC's binary point register
|
||||
* (ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
|
||||
* possible value (which may be above 0). */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
|
||||
{
|
||||
( void ) ulICCIAR;
|
||||
configASSERT( ( volatile void * ) NULL );
|
||||
( void ) ulICCIAR;
|
||||
configASSERT( ( volatile void * ) NULL );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,166 +42,166 @@
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0" ::: "memory" );
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0" ::: "memory" );
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
* not required for this port but included in case common demo code that uses these
|
||||
* macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
* handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are
|
||||
created without an FPU context and must call vPortTaskUsesFPU() to give
|
||||
themselves an FPU context before using any FPU instructions. If
|
||||
configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
|
||||
by default. */
|
||||
#if( configUSE_TASK_FPU_SUPPORT != 2 )
|
||||
void vPortTaskUsesFPU( void );
|
||||
#else
|
||||
/* Each task has an FPU context already, so define this function away to
|
||||
nothing to prevent it being called accidentally. */
|
||||
#define vPortTaskUsesFPU()
|
||||
#endif
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
* created without an FPU context and must call vPortTaskUsesFPU() to give
|
||||
* themselves an FPU context before using any FPU instructions. If
|
||||
* configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
|
||||
* by default. */
|
||||
#if ( configUSE_TASK_FPU_SUPPORT != 2 )
|
||||
void vPortTaskUsesFPU( void );
|
||||
#else
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
/* Each task has an FPU context already, so define this function away to
|
||||
* nothing to prevent it being called accidentally. */
|
||||
#define vPortTaskUsesFPU()
|
||||
#endif
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* 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 ) )
|
||||
/* 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 = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE __inline
|
||||
#define portNOP() __asm volatile ( "NOP" )
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
* number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
|
||||
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,48 +25,48 @@
|
|||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM0 port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the ARM CM0 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to manipulate the NVIC. */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
#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 portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
#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 portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
|
||||
/* The systick is a 24-bit counter. */
|
||||
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||
|
||||
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||
occurred while the SysTick counter is stopped during tickless idle
|
||||
calculations. */
|
||||
* occurred while the SysTick counter is stopped during tickless idle
|
||||
* calculations. */
|
||||
#ifndef portMISSED_COUNTS_FACTOR
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
#endif
|
||||
|
||||
/* Let the user override the pre-loading of the initial LR with the address of
|
||||
prvTaskExitError() in case it messes up unwinding of the stack in the
|
||||
debugger. */
|
||||
* prvTaskExitError() in case it messes up unwinding of the stack in the
|
||||
* debugger. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -79,14 +79,14 @@ void vPortSetupTimerInterrupt( void );
|
|||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void xPortPendSVHandler( void ) __attribute__ (( naked ));
|
||||
void xPortPendSVHandler( void ) __attribute__( ( naked ) );
|
||||
void xPortSysTickHandler( void );
|
||||
void vPortSVCHandler( void );
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
static void vPortStartFirstTask( void ) __attribute__ (( naked ));
|
||||
static void vPortStartFirstTask( void ) __attribute__( ( naked ) );
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
|
|
@ -96,32 +96,32 @@ static void prvTaskExitError( void );
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
* variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The number of SysTick increments that make up one tick period.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulTimerCountsForOneTick = 0;
|
||||
* The number of SysTick increments that make up one tick period.
|
||||
*/
|
||||
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulTimerCountsForOneTick = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* 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 uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||
* power functionality only.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulStoppedTimerCompensation = 0;
|
||||
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulStoppedTimerCompensation = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -129,81 +129,84 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
|||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
interrupt. */
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 8; /* R11..R4. */
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 8; /* R11..R4. */
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
volatile uint32_t ulDummy = 0UL;
|
||||
volatile uint32_t ulDummy = 0UL;
|
||||
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
its caller as there is nothing to return to. If a task wants to exit it
|
||||
should instead call vTaskDelete( NULL ).
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
* its caller as there is nothing to return to. If a task wants to exit it
|
||||
* should instead call vTaskDelete( NULL ).
|
||||
*
|
||||
* Artificially force an assert() to be triggered if configASSERT() is
|
||||
* defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( uxCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
Artificially force an assert() to be triggered if configASSERT() is
|
||||
defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( uxCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
while( ulDummy == 0 )
|
||||
{
|
||||
/* This file calls prvTaskExitError() after the scheduler has been
|
||||
started to remove a compiler warning about the function being defined
|
||||
but never called. ulDummy is used purely to quieten other warnings
|
||||
about code appearing after this function is called - making ulDummy
|
||||
volatile makes the compiler think the function could return and
|
||||
therefore not output an 'unreachable code' warning for code that appears
|
||||
after it. */
|
||||
}
|
||||
while( ulDummy == 0 )
|
||||
{
|
||||
/* This file calls prvTaskExitError() after the scheduler has been
|
||||
* started to remove a compiler warning about the function being defined
|
||||
* but never called. ulDummy is used purely to quieten other warnings
|
||||
* about code appearing after this function is called - making ulDummy
|
||||
* volatile makes the compiler think the function could return and
|
||||
* therefore not output an 'unreachable code' warning for code that appears
|
||||
* after it. */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler( void )
|
||||
{
|
||||
/* This function is no longer used, but retained for backward
|
||||
compatibility. */
|
||||
/* This function is no longer used, but retained for backward
|
||||
* compatibility. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortStartFirstTask( void )
|
||||
{
|
||||
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
|
||||
table offset register that can be used to locate the initial stack value.
|
||||
Not all M0 parts have the application vector table at address 0. */
|
||||
__asm volatile(
|
||||
" .syntax unified \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */
|
||||
" ldr r3, [r2] \n"
|
||||
" ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" movs r0, #2 \n" /* Switch to the psp stack. */
|
||||
" msr CONTROL, r0 \n"
|
||||
" isb \n"
|
||||
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
|
||||
" mov lr, r5 \n" /* lr is now in r5. */
|
||||
" pop {r3} \n" /* Return address is now in r3. */
|
||||
" pop {r2} \n" /* Pop and discard XPSR. */
|
||||
" cpsie i \n" /* The first task has its context and interrupts can be enabled. */
|
||||
" bx r3 \n" /* Finally, jump to the user defined task code. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB "
|
||||
);
|
||||
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
|
||||
* table offset register that can be used to locate the initial stack value.
|
||||
* Not all M0 parts have the application vector table at address 0. */
|
||||
__asm volatile (
|
||||
" .syntax unified \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Obtain location of pxCurrentTCB. */
|
||||
" ldr r3, [r2] \n"
|
||||
" ldr r0, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" movs r0, #2 \n"/* Switch to the psp stack. */
|
||||
" msr CONTROL, r0 \n"
|
||||
" isb \n"
|
||||
" pop {r0-r5} \n"/* Pop the registers that are saved automatically. */
|
||||
" mov lr, r5 \n"/* lr is now in r5. */
|
||||
" pop {r3} \n"/* Return address is now in r3. */
|
||||
" pop {r2} \n"/* Pop and discard XPSR. */
|
||||
" cpsie i \n"/* The first task has its context and interrupts can be enabled. */
|
||||
" bx r3 \n"/* Finally, jump to the user defined task code. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB "
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -212,158 +215,159 @@ void vPortStartFirstTask( void )
|
|||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should never get here as the tasks will now be executing! Call the task
|
||||
exit error function to prevent compiler warnings about a static function
|
||||
not being called in the case that the application writer overrides this
|
||||
functionality by defining configTASK_RETURN_ADDRESS. Call
|
||||
vTaskSwitchContext() so link time optimisation does not remove the
|
||||
symbol. */
|
||||
vTaskSwitchContext();
|
||||
prvTaskExitError();
|
||||
/* Should never get here as the tasks will now be executing! Call the task
|
||||
* exit error function to prevent compiler warnings about a static function
|
||||
* not being called in the case that the application writer overrides this
|
||||
* functionality by defining configTASK_RETURN_ADDRESS. Call
|
||||
* vTaskSwitchContext() so link time optimisation does not remove the
|
||||
* symbol. */
|
||||
vTaskSwitchContext();
|
||||
prvTaskExitError();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYield( void )
|
||||
{
|
||||
/* Set a PendSV to request a context switch. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
/* Set a PendSV to request a context switch. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is completely
|
||||
within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
/* Barriers are normally not required but do ensure the code is completely
|
||||
* within the specified behaviour for the architecture. */
|
||||
__asm volatile ( "dsb" ::: "memory" );
|
||||
__asm volatile ( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
__asm volatile ( "dsb" ::: "memory" );
|
||||
__asm volatile ( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMaskFromISR( void )
|
||||
{
|
||||
__asm volatile(
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr "
|
||||
::: "memory"
|
||||
);
|
||||
__asm volatile (
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr "
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask )
|
||||
{
|
||||
__asm volatile(
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr "
|
||||
::: "memory"
|
||||
);
|
||||
__asm volatile (
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr "
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortPendSVHandler( void )
|
||||
{
|
||||
/* This is a naked function. */
|
||||
/* This is a naked function. */
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" mrs r0, psp \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
|
||||
" ldr r2, [r3] \n"
|
||||
" \n"
|
||||
" subs r0, r0, #32 \n" /* Make space for the remaining low registers. */
|
||||
" str r0, [r2] \n" /* Save the new top of stack. */
|
||||
" stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n" /* Store the high registers. */
|
||||
" mov r5, r9 \n"
|
||||
" mov r6, r10 \n"
|
||||
" mov r7, r11 \n"
|
||||
" stmia r0!, {r4-r7} \n"
|
||||
" \n"
|
||||
" push {r3, r14} \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */
|
||||
" \n"
|
||||
" ldr r1, [r2] \n"
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" adds r0, r0, #16 \n" /* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n" /* Pop the high registers. */
|
||||
" mov r8, r4 \n"
|
||||
" mov r9, r5 \n"
|
||||
" mov r10, r6 \n"
|
||||
" mov r11, r7 \n"
|
||||
" \n"
|
||||
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
|
||||
" \n"
|
||||
" subs r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */
|
||||
" ldmia r0!, {r4-r7} \n" /* Pop low registers. */
|
||||
" \n"
|
||||
" bx r3 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB "
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" mrs r0, psp \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
|
||||
" ldr r2, [r3] \n"
|
||||
" \n"
|
||||
" subs r0, r0, #32 \n"/* Make space for the remaining low registers. */
|
||||
" str r0, [r2] \n"/* Save the new top of stack. */
|
||||
" stmia r0!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* Store the high registers. */
|
||||
" mov r5, r9 \n"
|
||||
" mov r6, r10 \n"
|
||||
" mov r7, r11 \n"
|
||||
" stmia r0!, {r4-r7} \n"
|
||||
" \n"
|
||||
" push {r3, r14} \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" pop {r2, r3} \n"/* lr goes in r3. r2 now holds tcb pointer. */
|
||||
" \n"
|
||||
" ldr r1, [r2] \n"
|
||||
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" adds r0, r0, #16 \n"/* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n"/* Pop the high registers. */
|
||||
" mov r8, r4 \n"
|
||||
" mov r9, r5 \n"
|
||||
" mov r10, r6 \n"
|
||||
" mov r11, r7 \n"
|
||||
" \n"
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" \n"
|
||||
" subs r0, r0, #32 \n"/* Go back for the low registers that are not automatically restored. */
|
||||
" ldmia r0!, {r4-r7} \n"/* Pop low registers. */
|
||||
" \n"
|
||||
" bx r3 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB "
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
uint32_t ulPreviousMask;
|
||||
uint32_t ulPreviousMask;
|
||||
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -371,189 +375,192 @@ uint32_t ulPreviousMask;
|
|||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||
__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
{
|
||||
ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR;
|
||||
}
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||
{
|
||||
ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR;
|
||||
}
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Stop and reset the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
/* Stop and reset the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||
|
||||
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||
TickType_t xModifiableIdleTime;
|
||||
__attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||
TickType_t xModifiableIdleTime;
|
||||
|
||||
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||
{
|
||||
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||
}
|
||||
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||
{
|
||||
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||
}
|
||||
|
||||
/* 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_ENABLE_BIT;
|
||||
/* 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_ENABLE_BIT;
|
||||
|
||||
/* 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. */
|
||||
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||
{
|
||||
ulReloadValue -= ulStoppedTimerCompensation;
|
||||
}
|
||||
/* 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. */
|
||||
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||
|
||||
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||
method as that will mask interrupts that should exit sleep mode. */
|
||||
__asm volatile( "cpsid i" ::: "memory" );
|
||||
__asm volatile( "dsb" );
|
||||
__asm volatile( "isb" );
|
||||
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||
{
|
||||
ulReloadValue -= ulStoppedTimerCompensation;
|
||||
}
|
||||
|
||||
/* If a context switch is pending or a task is waiting for the scheduler
|
||||
to be unsuspended then abandon the low power entry. */
|
||||
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||
{
|
||||
/* Restart from whatever is left in the count register to complete
|
||||
this tick period. */
|
||||
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||
* method as that will mask interrupts that should exit sleep mode. */
|
||||
__asm volatile ( "cpsid i" ::: "memory" );
|
||||
__asm volatile ( "dsb" );
|
||||
__asm volatile ( "isb" );
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
/* If a context switch is pending or a task is waiting for the scheduler
|
||||
* to be unsuspended then abandon the low power entry. */
|
||||
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||
{
|
||||
/* Restart from whatever is left in the count register to complete
|
||||
* this tick period. */
|
||||
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* Reset the reload register to the value required for normal tick
|
||||
periods. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
above. */
|
||||
__asm volatile( "cpsie i" ::: "memory" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the new reload value. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||
/* Reset the reload register to the value required for normal tick
|
||||
* periods. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Clear the SysTick count flag and set the count value back to
|
||||
zero. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
* above. */
|
||||
__asm volatile ( "cpsie i" ::: "memory" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the new reload value. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
/* Clear the SysTick count flag and set the count value back to
|
||||
* zero. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||
set its parameter to 0 to indicate that its implementation contains
|
||||
its own wait for interrupt or wait for event instruction, and so wfi
|
||||
should not be executed again. However, the original expected idle
|
||||
time variable must remain unmodified, so a copy is taken. */
|
||||
xModifiableIdleTime = xExpectedIdleTime;
|
||||
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
if( xModifiableIdleTime > 0 )
|
||||
{
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "wfi" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||
out of sleep mode to execute immediately. see comments above
|
||||
__disable_interrupt() call above. */
|
||||
__asm volatile( "cpsie i" ::: "memory" );
|
||||
__asm volatile( "dsb" );
|
||||
__asm volatile( "isb" );
|
||||
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||
* set its parameter to 0 to indicate that its implementation contains
|
||||
* its own wait for interrupt or wait for event instruction, and so wfi
|
||||
* should not be executed again. However, the original expected idle
|
||||
* time variable must remain unmodified, so a copy is taken. */
|
||||
xModifiableIdleTime = xExpectedIdleTime;
|
||||
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
|
||||
/* Disable interrupts again because the clock is about to be stopped
|
||||
and interrupts that execute while the clock is stopped will increase
|
||||
any slippage between the time maintained by the RTOS and calendar
|
||||
time. */
|
||||
__asm volatile( "cpsid i" ::: "memory" );
|
||||
__asm volatile( "dsb" );
|
||||
__asm volatile( "isb" );
|
||||
if( xModifiableIdleTime > 0 )
|
||||
{
|
||||
__asm volatile ( "dsb" ::: "memory" );
|
||||
__asm volatile ( "wfi" );
|
||||
__asm volatile ( "isb" );
|
||||
}
|
||||
|
||||
/* Disable the SysTick clock without reading the
|
||||
portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. 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 );
|
||||
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
|
||||
/* Determine if the SysTick clock has already counted to zero and
|
||||
been set back to the current reload value (the reload back being
|
||||
correct for the entire expected idle time) or if the SysTick is yet
|
||||
to count to zero (in which case an interrupt other than the SysTick
|
||||
must have brought the system out of sleep mode). */
|
||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||
{
|
||||
uint32_t ulCalculatedLoadValue;
|
||||
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||
* out of sleep mode to execute immediately. see comments above
|
||||
* __disable_interrupt() call above. */
|
||||
__asm volatile ( "cpsie i" ::: "memory" );
|
||||
__asm volatile ( "dsb" );
|
||||
__asm volatile ( "isb" );
|
||||
|
||||
/* The tick interrupt is already pending, and the SysTick count
|
||||
reloaded with ulReloadValue. Reset the
|
||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||
period. */
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||
/* Disable interrupts again because the clock is about to be stopped
|
||||
* and interrupts that execute while the clock is stopped will increase
|
||||
* any slippage between the time maintained by the RTOS and calendar
|
||||
* time. */
|
||||
__asm volatile ( "cpsid i" ::: "memory" );
|
||||
__asm volatile ( "dsb" );
|
||||
__asm volatile ( "isb" );
|
||||
|
||||
/* Don't allow a tiny value, or values that have somehow
|
||||
underflowed because the post sleep hook did something
|
||||
that took too long. */
|
||||
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||
{
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||
}
|
||||
/* Disable the SysTick clock without reading the
|
||||
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. 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 );
|
||||
|
||||
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||
/* Determine if the SysTick clock has already counted to zero and
|
||||
* been set back to the current reload value (the reload back being
|
||||
* correct for the entire expected idle time) or if the SysTick is yet
|
||||
* to count to zero (in which case an interrupt other than the SysTick
|
||||
* must have brought the system out of sleep mode). */
|
||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||
{
|
||||
uint32_t ulCalculatedLoadValue;
|
||||
|
||||
/* 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 rounded to complete tick
|
||||
periods (not the ulReload value which accounted for part
|
||||
ticks). */
|
||||
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
/* The tick interrupt is already pending, and the SysTick count
|
||||
* reloaded with ulReloadValue. Reset the
|
||||
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||
* period. */
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||
|
||||
/* How many complete tick periods passed while the processor
|
||||
was waiting? */
|
||||
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||
/* Don't allow a tiny value, or values that have somehow
|
||||
* underflowed because the post sleep hook did something
|
||||
* that took too long. */
|
||||
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||
{
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||
}
|
||||
|
||||
/* The reload value is set to whatever fraction of a single tick
|
||||
period remains. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||
}
|
||||
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||
|
||||
/* 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_ENABLE_BIT;
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
/* 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 rounded to complete tick
|
||||
* periods (not the ulReload value which accounted for part
|
||||
* ticks). */
|
||||
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* Exit with interrpts enabled. */
|
||||
__asm volatile( "cpsie i" ::: "memory" );
|
||||
}
|
||||
}
|
||||
/* How many complete tick periods passed while the processor
|
||||
* was waiting? */
|
||||
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||
|
||||
/* The reload value is set to whatever fraction of a single tick
|
||||
* period remains. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||
}
|
||||
|
||||
/* 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_ENABLE_BIT;
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Exit with interrpts enabled. */
|
||||
__asm volatile ( "cpsie i" ::: "memory" );
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -43,82 +43,81 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
extern void vPortYield( void );
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
extern void vPortYield( void );
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__((naked));
|
||||
extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__((naked));
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) );
|
||||
extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__( ( naked ) );
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMaskFromISR( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 portNOP()
|
||||
#define portNOP()
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -38,415 +38,415 @@
|
|||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n" /* r5 = 1. */
|
||||
" bics r4, r5 \n" /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n" /* r5 = 4. */
|
||||
" str r5, [r2] \n" /* Program RNR = 4. */
|
||||
" ldmia r3!, {r6,r7} \n" /* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n" /* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n" /* r5 = 5. */
|
||||
" str r5, [r2] \n" /* Program RNR = 5. */
|
||||
" ldmia r3!, {r6,r7} \n" /* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n" /* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n" /* r5 = 6. */
|
||||
" str r5, [r2] \n" /* Program RNR = 6. */
|
||||
" ldmia r3!, {r6,r7} \n" /* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n" /* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n" /* r5 = 7. */
|
||||
" str r5, [r2] \n" /* Program RNR = 7. */
|
||||
" ldmia r3!, {r6,r7} \n" /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n" /* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n" /* r5 = 1. */
|
||||
" orrs r4, r5 \n" /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n" /* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n" /* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n" /* r1 = 2. */
|
||||
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n" /* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n" /* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" bics r0, r1 \n" /* Clear the bit 0. */
|
||||
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" bics r0, r1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" orrs r0, r1 \n" /* r0 = r0 | r1. */
|
||||
" msr control, r0 \n" /* CONTROL = r0. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
:::"r0", "r1", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" orrs r0, r1 \n"/* r0 = r0 | r1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n" /* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
:: "i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" mrs r1, psp \n" /* Read PSP in r1. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r2] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n" /* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"
|
||||
" pop {r0-r3} \n" /* LR is now in r3. */
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" lsls r2, r3, #25 \n" /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #16 \n" /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mrs r3, control \n" /* r3 = CONTROL. */
|
||||
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #48 \n" /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" adds r1, r1, #16 \n" /* r1 = r1 + 16. */
|
||||
" stmia r1!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n" /* r4 = r8. */
|
||||
" mov r5, r9 \n" /* r5 = r9. */
|
||||
" mov r6, r10 \n" /* r6 = r10. */
|
||||
" mov r7, r11 \n" /* r7 = r11. */
|
||||
" stmia r1!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mrs r3, control \n" /* r3 = CONTROL. */
|
||||
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */
|
||||
" subs r1, r1, #48 \n" /* r1 = r1 - 48. */
|
||||
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r7} \n" /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n" /* r4 = r8. */
|
||||
" mov r5, r9 \n" /* r5 = r9. */
|
||||
" mov r6, r10 \n" /* r6 = r10. */
|
||||
" mov r7, r11 \n" /* r7 = r11. */
|
||||
" stmia r1!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n" /* r5 = 1. */
|
||||
" bics r4, r5 \n" /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n" /* r5 = 4. */
|
||||
" str r5, [r2] \n" /* Program RNR = 4. */
|
||||
" ldmia r3!, {r6,r7} \n" /* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n" /* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n" /* r5 = 5. */
|
||||
" str r5, [r2] \n" /* Program RNR = 5. */
|
||||
" ldmia r3!, {r6,r7} \n" /* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n" /* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n" /* r5 = 6. */
|
||||
" str r5, [r2] \n" /* Program RNR = 6. */
|
||||
" ldmia r3!, {r6,r7} \n" /* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n" /* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n" /* r5 = 7. */
|
||||
" str r5, [r2] \n" /* Program RNR = 7. */
|
||||
" ldmia r3!, {r6,r7} \n" /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n" /* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n" /* r5 = 1. */
|
||||
" orrs r4, r5 \n" /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r0, r2-r4} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n" /* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n" /* LR = r4. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n" /* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r4} \n"
|
||||
" bl SecureContext_LoadContext \n" /* Restore the secure context. */
|
||||
" pop {r1,r4} \n"
|
||||
" mov lr, r4 \n" /* LR = r4. */
|
||||
" lsls r2, r4, #25 \n" /* r2 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r1!, {r0, r2-r3} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n" /* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r3} \n"
|
||||
" bl SecureContext_LoadContext \n" /* Restore the secure context. */
|
||||
" pop {r1,r3} \n"
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" lsls r2, r3, #25 \n" /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" adds r1, r1, #16 \n" /* Move to the high registers. */
|
||||
" ldmia r1!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n" /* r8 = r4. */
|
||||
" mov r9, r5 \n" /* r9 = r5. */
|
||||
" mov r10, r6 \n" /* r10 = r6. */
|
||||
" mov r11, r7 \n" /* r11 = r7. */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" subs r1, r1, #32 \n" /* Go back to the low registers. */
|
||||
" ldmia r1!, {r4-r7} \n" /* Restore the low registers that are not automatically restored. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" mrs r1, psp \n"/* Read PSP in r1. */
|
||||
" ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r2] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n"/* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"
|
||||
" pop {r0-r3} \n"/* LR is now in r3. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r2, r3, #25 \n"/* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r1, [r2] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r1, [r2] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r1, r1, #16 \n"/* r1 = r1 + 16. */
|
||||
" stmia r1!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" subs r1, r1, #48 \n"/* r1 = r1 - 48. */
|
||||
" stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r0, r2-r4} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. */
|
||||
" pop {r1,r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r2, r4, #25 \n"/* r2 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r1!, {r0, r2-r3} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r3} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. */
|
||||
" pop {r1,r3} \n"
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r2, r3, #25 \n"/* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" adds r1, r1, #16 \n"/* Move to the high registers. */
|
||||
" ldmia r1!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r1 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r1, r1, #32 \n"/* Go back to the low registers. */
|
||||
" ldmia r1!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" svc %0 \n" /* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n" /* Return. */
|
||||
:: "i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" svc %0 \n"/* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r1, [r0] \n" /* The first item in the TCB is the top of the stack. */
|
||||
" ldr r0, [r1] \n" /* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r0, #0 \n" /* Raise svc if task's xSecureContext is not NULL. */
|
||||
" beq free_secure_context \n"
|
||||
" bx lr \n" /* There is no secure context (xSecureContext is NULL). */
|
||||
" free_secure_context: \n"
|
||||
" svc %0 \n" /* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n" /* Return. */
|
||||
:: "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r1, [r0] \n"/* The first item in the TCB is the top of the stack. */
|
||||
" ldr r0, [r1] \n"/* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r0, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
|
||||
" beq free_secure_context \n"
|
||||
" bx lr \n"/* There is no secure context (xSecureContext is NULL). */
|
||||
" free_secure_context: \n"
|
||||
" svc %0 \n"/* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@
|
|||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
|
|
@ -57,7 +57,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
|||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
|
|
@ -67,32 +67,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
|||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
|
|
@ -100,13 +100,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
|||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -41,109 +41,109 @@ extern "C" {
|
|||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
|
|
@ -155,155 +155,157 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
|
|||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Tickless idle/low power functionality.
|
||||
*/
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
@ -58,146 +58,148 @@
|
|||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t *pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t *pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t *pucStackStart; /**< First location of the stack memory. */
|
||||
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t * pucStackStart; /**< First location of the stack memory. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged.. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged.. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged )
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t *pucStackMemory = NULL;
|
||||
uint32_t ulIPSR;
|
||||
SecureContextHandle_t xSecureContextHandle = NULL;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t *pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
uint8_t * pucStackMemory = NULL;
|
||||
uint32_t ulIPSR;
|
||||
SecureContextHandle_t xSecureContextHandle = NULL;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
uint32_t * pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Allocate the context structure. */
|
||||
xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
if( xSecureContextHandle != NULL )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize );
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Allocate the context structure. */
|
||||
xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte because the hardware decrements the stack
|
||||
* pointer before writing i.e. if stack pointer is 0x2, a push
|
||||
* operation will decrement the stack pointer to 0x1 and then
|
||||
* write at 0x1. */
|
||||
xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
if( xSecureContextHandle != NULL )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize );
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContextHandle->pucStackLimit = pucStackMemory;
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte because the hardware decrements the stack
|
||||
* pointer before writing i.e. if stack pointer is 0x2, a push
|
||||
* operation will decrement the stack pointer to 0x1 and then
|
||||
* write at 0x1. */
|
||||
xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContextHandle->pucStackLimit = pucStackMemory;
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the context to avoid memory leak and make sure to return
|
||||
* NULL to indicate failure. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
xSecureContextHandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the context to avoid memory leak and make sure to return
|
||||
* NULL to indicate failure. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
xSecureContextHandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Ensure that valid parameters are passed. */
|
||||
secureportASSERT( xSecureContextHandle != NULL );
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Ensure that valid parameters are passed. */
|
||||
secureportASSERT( xSecureContextHandle != NULL );
|
||||
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContextHandle->pucStackLimit );
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContextHandle->pucStackLimit );
|
||||
|
||||
/* Free the context itself. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
}
|
||||
/* Free the context itself. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -36,13 +36,13 @@
|
|||
/**
|
||||
* @brief PSP value when no task's context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Opaque handle.
|
||||
*/
|
||||
struct SecureContext;
|
||||
typedef struct SecureContext* SecureContextHandle_t;
|
||||
typedef struct SecureContext * SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
@ -68,10 +68,11 @@ void SecureContext_Init( void );
|
|||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged );
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -30,61 +30,61 @@
|
|||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
:::"r0", "r1", "r2"
|
||||
);
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n"/* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n"/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n"/* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n"/* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n"/* PSPLIM = r2. */
|
||||
" msr psp, r1 \n"/* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
::: "r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
" stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
:: "i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n"/* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n"/* r1 = PSP. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n"/* r2 = CONTROL. */
|
||||
" subs r1, r1, #4 \n"/* Make space for the CONTROL value on the stack. */
|
||||
" str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
" stmia r1!, {r2} \n"/* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" movs r1, %0 \n"/* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n"/* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n"/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -36,37 +36,38 @@
|
|||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
|
|
@ -76,8 +77,8 @@
|
|||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK *pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ static void prvHeapInit( void );
|
|||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
@ -108,13 +109,13 @@ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( s
|
|||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart, *pxEnd = NULL;
|
||||
static BlockLink_t xStart, * pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
|
|
@ -124,326 +125,329 @@ static size_t xMinimumEverFreeBytesRemaining = 0U;
|
|||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t *pxFirstFreeBlock;
|
||||
uint8_t *pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
uint8_t * pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t *pxIterator;
|
||||
uint8_t *puc;
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc( size_t xWantedSize )
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||
void *pvReturn = NULL;
|
||||
BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
#if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
#if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void *pv )
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t *puc = ( uint8_t * ) pv;
|
||||
BlockLink_t *pxLink;
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@
|
|||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void *pvPortMalloc( size_t xWantedSize );
|
||||
void * pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void *pv );
|
||||
void vPortFree( void * pv );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
|
|
|
|||
|
|
@ -36,69 +36,69 @@
|
|||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~ ( secureinitFPCCR_LSPENS_MASK );
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -30,103 +30,103 @@
|
|||
/**
|
||||
* @brief Byte alignment requirements.
|
||||
*/
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
|
||||
/**
|
||||
* @brief Macro to declare a function as non-secure callable.
|
||||
*/
|
||||
#if defined( __IAR_SYSTEMS_ICC__ )
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#else
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used))
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Set the non-secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the PSP value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSP to the given value.
|
||||
*/
|
||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSPLIM to the given value.
|
||||
*/
|
||||
#define secureportSET_PSPLIM( pucStackLimit ) \
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the NonSecure MSP to the given value.
|
||||
*/
|
||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the CONTROL register to the given value.
|
||||
*/
|
||||
#define secureportSET_CONTROL( ulControl ) \
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
|
||||
* variable.
|
||||
*/
|
||||
#define secureportREAD_IPSR( ulIPSR ) \
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to enable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to disable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
|
||||
/**
|
||||
* @brief Disable secure interrupts.
|
||||
*/
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Disable non-secure interrupts.
|
||||
*
|
||||
* This effectively disables context switches.
|
||||
*/
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Enable non-secure interrupts.
|
||||
*/
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Assert definition.
|
||||
*/
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ;; ); \
|
||||
}
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ; ; ) {; } \
|
||||
}
|
||||
|
||||
#endif /* __SECURE_PORT_MACROS_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -38,328 +38,328 @@
|
|||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n" /* r4 = 1. */
|
||||
" bics r3, r4 \n" /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
" str r3, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n" /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r4, #4 \n" /* r4 = 4. */
|
||||
" str r4, [r2] \n" /* Program RNR = 4. */
|
||||
" ldmia r1!, {r5,r6} \n" /* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n" /* Write first set of RBAR/RLAR registers. */
|
||||
" movs r4, #5 \n" /* r4 = 5. */
|
||||
" str r4, [r2] \n" /* Program RNR = 5. */
|
||||
" ldmia r1!, {r5,r6} \n" /* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n" /* Write second set of RBAR/RLAR registers. */
|
||||
" movs r4, #6 \n" /* r4 = 6. */
|
||||
" str r4, [r2] \n" /* Program RNR = 6. */
|
||||
" ldmia r1!, {r5,r6} \n" /* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n" /* Write third set of RBAR/RLAR registers. */
|
||||
" movs r4, #7 \n" /* r4 = 7. */
|
||||
" str r4, [r2] \n" /* Program RNR = 7. */
|
||||
" ldmia r1!, {r5,r6} \n" /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n" /* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n" /* r4 = 1. */
|
||||
" orrs r3, r4 \n" /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
" str r3, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
|
||||
" msr control, r2 \n" /* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n" /* r1 = 2. */
|
||||
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r2 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r4, #5 \n"/* r4 = 5. */
|
||||
" str r4, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r4, #6 \n"/* r4 = 6. */
|
||||
" str r4, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r4, #7 \n"/* r4 = 7. */
|
||||
" str r4, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r2 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r2 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n" /* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n" /* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" bics r0, r1 \n" /* Clear the bit 0. */
|
||||
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" bics r0, r1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" movs r1, #1 \n" /* r1 = 1. */
|
||||
" orrs r0, r1 \n" /* r0 = r0 | r1. */
|
||||
" msr control, r0 \n" /* CONTROL = r0. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
:::"r0", "r1", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" orrs r0, r1 \n"/* r0 = r0 | r1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n" /* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
:: "i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, psp \n" /* Read PSP in r0. */
|
||||
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" subs r0, r0, #44 \n" /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r0, [r1] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n" /* r1 = PSPLIM. */
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmia r0!, {r1-r7} \n" /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
|
||||
" mov r4, r8 \n" /* r4 = r8. */
|
||||
" mov r5, r9 \n" /* r5 = r9. */
|
||||
" mov r6, r10 \n" /* r6 = r10. */
|
||||
" mov r7, r11 \n" /* r7 = r11. */
|
||||
" stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r0, r0, #40 \n" /* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r0, [r1] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmia r0!, {r2-r7} \n" /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||
" mov r4, r8 \n" /* r4 = r8. */
|
||||
" mov r5, r9 \n" /* r5 = r9. */
|
||||
" mov r6, r10 \n" /* r6 = r10. */
|
||||
" mov r7, r11 \n" /* r7 = r11. */
|
||||
" stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n" /* r4 = 1. */
|
||||
" bics r3, r4 \n" /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
" str r3, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n" /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r4, #4 \n" /* r4 = 4. */
|
||||
" str r4, [r2] \n" /* Program RNR = 4. */
|
||||
" ldmia r1!, {r5,r6} \n" /* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n" /* Write first set of RBAR/RLAR registers. */
|
||||
" movs r4, #5 \n" /* r4 = 5. */
|
||||
" str r4, [r2] \n" /* Program RNR = 5. */
|
||||
" ldmia r1!, {r5,r6} \n" /* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n" /* Write second set of RBAR/RLAR registers. */
|
||||
" movs r4, #6 \n" /* r4 = 6. */
|
||||
" str r4, [r2] \n" /* Program RNR = 6. */
|
||||
" ldmia r1!, {r5,r6} \n" /* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n" /* Write third set of RBAR/RLAR registers. */
|
||||
" movs r4, #7 \n" /* r4 = 7. */
|
||||
" str r4, [r2] \n" /* Program RNR = 7. */
|
||||
" ldmia r1!, {r5,r6} \n" /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n" /* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n" /* r4 = 1. */
|
||||
" orrs r3, r4 \n" /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
" str r3, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" adds r0, r0, #28 \n" /* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n" /* r8 = r4. */
|
||||
" mov r9, r5 \n" /* r9 = r5. */
|
||||
" mov r10, r6 \n" /* r10 = r6. */
|
||||
" mov r11, r7 \n" /* r11 = r7. */
|
||||
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
|
||||
" subs r0, r0, #44 \n" /* Move to the starting of the saved context. */
|
||||
" ldmia r0!, {r1-r7} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
|
||||
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r2 \n" /* Restore the CONTROL register value for the task. */
|
||||
" bx r3 \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" adds r0, r0, #24 \n" /* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n" /* r8 = r4. */
|
||||
" mov r9, r5 \n" /* r9 = r5. */
|
||||
" mov r10, r6 \n" /* r10 = r6. */
|
||||
" mov r11, r7 \n" /* r11 = r7. */
|
||||
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
|
||||
" subs r0, r0, #40 \n" /* Move to the starting of the saved context. */
|
||||
" ldmia r0!, {r2-r7} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" bx r3 \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, psp \n"/* Read PSP in r0. */
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r2, control \n"/* r2 = CONTROL. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r4, #5 \n"/* r4 = 5. */
|
||||
" str r4, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r4, #6 \n"/* r4 = 6. */
|
||||
" str r4, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r4, #7 \n"/* r4 = 7. */
|
||||
" str r4, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" adds r0, r0, #28 \n"/* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r0, r0, #44 \n"/* Move to the starting of the saved context. */
|
||||
" ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */
|
||||
" bx r3 \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" adds r0, r0, #24 \n"/* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r0, r0, #40 \n"/* Move to the starting of the saved context. */
|
||||
" ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" bx r3 \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@
|
|||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
|
|
@ -57,7 +57,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
|||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
|
|
@ -67,32 +67,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
|||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
|
|
@ -100,13 +100,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
|||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -41,109 +41,109 @@ extern "C" {
|
|||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
|
|
@ -155,155 +155,157 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
|
|||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Tickless idle/low power functionality.
|
||||
*/
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -43,203 +43,203 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ::: "memory" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
* within the specified behaviour for the architecture. */\
|
||||
__asm volatile ( "dsb" ::: "memory" ); \
|
||||
__asm volatile ( "isb" ); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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 )
|
||||
* 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
return ucReturn;
|
||||
}
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
|
||||
/* 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
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* 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 ) )
|
||||
/* 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
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/* 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 ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n"\
|
||||
" msr basepri, %0 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n"\
|
||||
" mov %1, %2 \n"\
|
||||
" msr basepri, %1 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
* warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -40,370 +40,370 @@
|
|||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n" /* r4 = 4. */
|
||||
" str r4, [r2] \n" /* Program RNR = 4. */
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n" /* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n" /* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n" /* r1 = 2. */
|
||||
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n" /* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||
" bic r0, #1 \n" /* Clear the bit 0. */
|
||||
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" bic r0, #1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" orr r0, #1 \n" /* r0 = r0 | 1. */
|
||||
" msr control, r0 \n" /* CONTROL = r0. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
:::"r0", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" orr r0, #1 \n"/* r0 = r0 | 1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n" /* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
:: "i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n" /* Return. */
|
||||
:: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, r0 \n" /* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n" /* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, r0 \n"/* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" mrs r1, psp \n" /* Read PSP in r1. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r2] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n" /* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"
|
||||
" pop {r0-r3} \n" /* LR is now in r3. */
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" lsls r2, r3, #25 \n" /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #16 \n" /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mrs r3, control \n" /* r3 = CONTROL. */
|
||||
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */
|
||||
#if( configENABLE_FPU == 1 )
|
||||
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r1!, {s16-s31} \n" /* Store the FPU registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #48 \n" /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" adds r1, r1, #16 \n" /* r1 = r1 + 16. */
|
||||
" stm r1, {r4-r11} \n" /* Store the registers that are not saved automatically. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mrs r3, control \n" /* r3 = CONTROL. */
|
||||
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */
|
||||
" subs r1, r1, #16 \n" /* r1 = r1 - 16. */
|
||||
" stm r1, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" adds r1, r1, #12 \n" /* r1 = r1 + 12. */
|
||||
" stm r1, {r4-r11} \n" /* Store the registers that are not saved automatically. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" subs r1, r1, #12 \n" /* r1 = r1 - 12. */
|
||||
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n" /* r0 = 0. */
|
||||
" msr basepri, r0 \n" /* Enable interrupts. */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n" /* r4 = 4. */
|
||||
" str r4, [r2] \n" /* Program RNR = 4. */
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r0, r2-r4} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n" /* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n" /* LR = r4. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n" /* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r4} \n"
|
||||
" bl SecureContext_LoadContext \n" /* Restore the secure context. */
|
||||
" pop {r1,r4} \n"
|
||||
" mov lr, r4 \n" /* LR = r4. */
|
||||
" lsls r2, r4, #25 \n" /* r2 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r1!, {r0, r2-r3} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n" /* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r3} \n"
|
||||
" bl SecureContext_LoadContext \n" /* Restore the secure context. */
|
||||
" pop {r1,r3} \n"
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" lsls r2, r3, #25 \n" /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" ldmia r1!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
|
||||
#if( configENABLE_FPU == 1 )
|
||||
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r1!, {s16-s31} \n" /* Restore the FPU registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
:: "i"( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" mrs r1, psp \n"/* Read PSP in r1. */
|
||||
" ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r2] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n"/* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"
|
||||
" pop {r0-r3} \n"/* LR is now in r3. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r2, r3, #25 \n"/* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r1, [r2] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r1, [r2] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r1!, {s16-s31} \n"/* Store the FPU registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r1, r1, #16 \n"/* r1 = r1 + 16. */
|
||||
" stm r1, {r4-r11} \n"/* Store the registers that are not saved automatically. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" subs r1, r1, #16 \n"/* r1 = r1 - 16. */
|
||||
" stm r1, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r1, r1, #12 \n"/* r1 = r1 + 12. */
|
||||
" stm r1, {r4-r11} \n"/* Store the registers that are not saved automatically. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" subs r1, r1, #12 \n"/* r1 = r1 - 12. */
|
||||
" stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"/* r0 = 0. */
|
||||
" msr basepri, r0 \n"/* Enable interrupts. */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r0, r2-r4} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. */
|
||||
" pop {r1,r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r2, r4, #25 \n"/* r2 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r1!, {r0, r2-r3} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r3} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. */
|
||||
" pop {r1,r3} \n"
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r2, r3, #25 \n"/* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" ldmia r1!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r1!, {s16-s31} \n"/* Restore the FPU registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
" msr psp, r1 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" svc %0 \n" /* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n" /* Return. */
|
||||
:: "i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" svc %0 \n"/* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r1, [r0] \n" /* The first item in the TCB is the top of the stack. */
|
||||
" ldr r0, [r1] \n" /* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r0, #0 \n" /* Raise svc if task's xSecureContext is not NULL. */
|
||||
" it ne \n"
|
||||
" svcne %0 \n" /* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n" /* Return. */
|
||||
:: "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r1, [r0] \n"/* The first item in the TCB is the top of the stack. */
|
||||
" ldr r0, [r1] \n"/* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r0, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
|
||||
" it ne \n"
|
||||
" svcne %0 \n"/* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@
|
|||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
|
|
@ -57,7 +57,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
|||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
|
|
@ -67,32 +67,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
|||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
|
|
@ -100,13 +100,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
|||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -41,109 +41,109 @@ extern "C" {
|
|||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
|
|
@ -155,155 +155,157 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
|
|||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Tickless idle/low power functionality.
|
||||
*/
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
@ -58,146 +58,148 @@
|
|||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t *pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t *pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t *pucStackStart; /**< First location of the stack memory. */
|
||||
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t * pucStackStart; /**< First location of the stack memory. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged.. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged.. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged )
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t *pucStackMemory = NULL;
|
||||
uint32_t ulIPSR;
|
||||
SecureContextHandle_t xSecureContextHandle = NULL;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t *pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
uint8_t * pucStackMemory = NULL;
|
||||
uint32_t ulIPSR;
|
||||
SecureContextHandle_t xSecureContextHandle = NULL;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
uint32_t * pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Allocate the context structure. */
|
||||
xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
if( xSecureContextHandle != NULL )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize );
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Allocate the context structure. */
|
||||
xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte because the hardware decrements the stack
|
||||
* pointer before writing i.e. if stack pointer is 0x2, a push
|
||||
* operation will decrement the stack pointer to 0x1 and then
|
||||
* write at 0x1. */
|
||||
xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
if( xSecureContextHandle != NULL )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize );
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContextHandle->pucStackLimit = pucStackMemory;
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte because the hardware decrements the stack
|
||||
* pointer before writing i.e. if stack pointer is 0x2, a push
|
||||
* operation will decrement the stack pointer to 0x1 and then
|
||||
* write at 0x1. */
|
||||
xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContextHandle->pucStackLimit = pucStackMemory;
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the context to avoid memory leak and make sure to return
|
||||
* NULL to indicate failure. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
xSecureContextHandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the context to avoid memory leak and make sure to return
|
||||
* NULL to indicate failure. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
xSecureContextHandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Ensure that valid parameters are passed. */
|
||||
secureportASSERT( xSecureContextHandle != NULL );
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Ensure that valid parameters are passed. */
|
||||
secureportASSERT( xSecureContextHandle != NULL );
|
||||
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContextHandle->pucStackLimit );
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContextHandle->pucStackLimit );
|
||||
|
||||
/* Free the context itself. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
}
|
||||
/* Free the context itself. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -36,13 +36,13 @@
|
|||
/**
|
||||
* @brief PSP value when no task's context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Opaque handle.
|
||||
*/
|
||||
struct SecureContext;
|
||||
typedef struct SecureContext* SecureContextHandle_t;
|
||||
typedef struct SecureContext * SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
@ -68,10 +68,11 @@ void SecureContext_Init( void );
|
|||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged );
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -32,56 +32,56 @@
|
|||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
:::"r0", "r1", "r2"
|
||||
);
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n"/* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n"/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n"/* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n"/* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n"/* PSPLIM = r2. */
|
||||
" msr psp, r1 \n"/* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
::: "r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
#if( configENABLE_FPU == 1 )
|
||||
" vstmdb r1!, {s0} \n" /* Trigger the defferred stacking of FPU registers. */
|
||||
" vldmia r1!, {s0} \n" /* Nullify the effect of the pervious statement. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" stmdb r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
:: "i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n"/* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n"/* r1 = PSP. */
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
" vstmdb r1!, {s0} \n"/* Trigger the defferred stacking of FPU registers. */
|
||||
" vldmia r1!, {s0} \n"/* Nullify the effect of the pervious statement. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n"/* r2 = CONTROL. */
|
||||
" stmdb r1!, {r2} \n"/* Store CONTROL value on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
" movs r1, %0 \n"/* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n"/* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n"/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -36,37 +36,38 @@
|
|||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
|
|
@ -76,8 +77,8 @@
|
|||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK *pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ static void prvHeapInit( void );
|
|||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
@ -108,13 +109,13 @@ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( s
|
|||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart, *pxEnd = NULL;
|
||||
static BlockLink_t xStart, * pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
|
|
@ -124,326 +125,329 @@ static size_t xMinimumEverFreeBytesRemaining = 0U;
|
|||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t *pxFirstFreeBlock;
|
||||
uint8_t *pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
uint8_t * pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t *pxIterator;
|
||||
uint8_t *puc;
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc( size_t xWantedSize )
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||
void *pvReturn = NULL;
|
||||
BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
#if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
#if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void *pv )
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t *puc = ( uint8_t * ) pv;
|
||||
BlockLink_t *pxLink;
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@
|
|||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void *pvPortMalloc( size_t xWantedSize );
|
||||
void * pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void *pv );
|
||||
void vPortFree( void * pv );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
|
|
|
|||
|
|
@ -36,69 +36,69 @@
|
|||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~ ( secureinitFPCCR_LSPENS_MASK );
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -30,103 +30,103 @@
|
|||
/**
|
||||
* @brief Byte alignment requirements.
|
||||
*/
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
|
||||
/**
|
||||
* @brief Macro to declare a function as non-secure callable.
|
||||
*/
|
||||
#if defined( __IAR_SYSTEMS_ICC__ )
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#else
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used))
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Set the non-secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the PSP value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSP to the given value.
|
||||
*/
|
||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSPLIM to the given value.
|
||||
*/
|
||||
#define secureportSET_PSPLIM( pucStackLimit ) \
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the NonSecure MSP to the given value.
|
||||
*/
|
||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the CONTROL register to the given value.
|
||||
*/
|
||||
#define secureportSET_CONTROL( ulControl ) \
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
|
||||
* variable.
|
||||
*/
|
||||
#define secureportREAD_IPSR( ulIPSR ) \
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to enable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to disable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
|
||||
/**
|
||||
* @brief Disable secure interrupts.
|
||||
*/
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Disable non-secure interrupts.
|
||||
*
|
||||
* This effectively disables context switches.
|
||||
*/
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Enable non-secure interrupts.
|
||||
*/
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Assert definition.
|
||||
*/
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ;; ); \
|
||||
}
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ; ; ) {; } \
|
||||
}
|
||||
|
||||
#endif /* __SECURE_PORT_MACROS_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -40,276 +40,276 @@
|
|||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r3, [r1] \n" /* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r3, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #4 \n" /* r3 = 4. */
|
||||
" str r3, [r2] \n" /* Program RNR = 4. */
|
||||
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
|
||||
" msr control, r2 \n" /* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n" /* r1 = 2. */
|
||||
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r2 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r3, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #4 \n"/* r3 = 4. */
|
||||
" str r3, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r2 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r2 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n" /* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||
" bic r0, #1 \n" /* Clear the bit 0. */
|
||||
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" bic r0, #1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" orr r0, #1 \n" /* r0 = r0 | 1. */
|
||||
" msr control, r0 \n" /* CONTROL = r0. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
:::"r0", "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" orr r0, #1 \n"/* r0 = r0 | 1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n" /* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
:: "i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n" /* Return. */
|
||||
:: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, r0 \n" /* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n" /* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, r0 \n"/* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, psp \n" /* Read PSP in r0. */
|
||||
#if( configENABLE_FPU == 1 )
|
||||
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r0!, {s16-s31} \n" /* Store the FPU registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" mrs r1, psplim \n" /* r1 = PSPLIM. */
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r0!, {r1-r11} \n" /* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
|
||||
#else /* configENABLE_MPU */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" str r0, [r1] \n" /* Save the new top of stack in TCB. */
|
||||
" \n"
|
||||
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n" /* r0 = 0. */
|
||||
" msr basepri, r0 \n" /* Enable interrupts. */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r3, [r1] \n" /* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r3, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #4 \n" /* r3 = 4. */
|
||||
" str r3, [r2] \n" /* Program RNR = 4. */
|
||||
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldmia r0!, {r1-r11} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_FPU == 1 )
|
||||
" tst r3, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r0!, {s16-s31} \n" /* Restore the FPU registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r2 \n" /* Restore the CONTROL register value for the task. */
|
||||
#else /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
|
||||
" bx r3 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
:: "i"( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, psp \n"/* Read PSP in r0. */
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r0!, {s16-s31} \n"/* Store the FPU registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r2, control \n"/* r2 = CONTROL. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
|
||||
#else /* configENABLE_MPU */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" \n"
|
||||
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"/* r0 = 0. */
|
||||
" msr basepri, r0 \n"/* Enable interrupts. */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r3, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #4 \n"/* r3 = 4. */
|
||||
" str r3, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
" tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r0!, {s16-s31} \n"/* Restore the FPU registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */
|
||||
#else /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" bx r3 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@
|
|||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
|
|
@ -57,7 +57,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
|||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
|
|
@ -67,32 +67,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
|||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
|
|
@ -100,13 +100,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
|||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -41,109 +41,109 @@ extern "C" {
|
|||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
|
|
@ -155,155 +155,157 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
|
|||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Tickless idle/low power functionality.
|
||||
*/
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -43,265 +43,265 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* MPU specific constants. */
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
|
||||
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " ::: "r0", "memory" )
|
||||
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " ::: "r0", "memory" )
|
||||
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
uint32_t ulRegionBaseAddress;
|
||||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
uint32_t ulRegionBaseAddress;
|
||||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
|
||||
/* Plus 1 to create space for the stack region. */
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||
} xMPU_SETTINGS;
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* SVC numbers for various services. */
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) : "memory" )
|
||||
#define portYIELD_WITHIN_API() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ::: "memory" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
#define portYIELD() __asm volatile ( " SVC %0 \n"::"i" ( portSVC_YIELD ) : "memory" )
|
||||
#define portYIELD_WITHIN_API() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
* within the specified behaviour for the architecture. */\
|
||||
__asm volatile ( "dsb" ::: "memory" ); \
|
||||
__asm volatile ( "isb" ); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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 )
|
||||
* 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
return ucReturn;
|
||||
}
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
|
||||
/* 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
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* 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 ) )
|
||||
/* 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
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/* 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 ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
extern BaseType_t xIsPrivileged( void );
|
||||
extern void vResetPrivilege( void );
|
||||
extern BaseType_t xIsPrivileged( void );
|
||||
extern void vResetPrivilege( void );
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n"\
|
||||
" msr basepri, %0 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n"\
|
||||
" mov %1, %2 \n"\
|
||||
" msr basepri, %1 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
* warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security. https://www.freertos.org/FreeRTOS-V10.3.x.html"
|
||||
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||
#endif
|
||||
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security. https: /*www.freertos.org/FreeRTOS-V10.3.x.html" */
|
||||
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -43,201 +43,201 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ::: "memory" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
* within the specified behaviour for the architecture. */\
|
||||
__asm volatile ( "dsb" ::: "memory" ); \
|
||||
__asm volatile ( "isb" ); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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 )
|
||||
* 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
return ucReturn;
|
||||
}
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
|
||||
/* 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
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* 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 ) )
|
||||
/* 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
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/* 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 ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n"\
|
||||
" msr basepri, %0 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n"\
|
||||
" mov %1, %2 \n"\
|
||||
" msr basepri, %1 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
* warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -43,265 +43,265 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* MPU specific constants. */
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
|
||||
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " ::: "r0", "memory" )
|
||||
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " ::: "r0", "memory" )
|
||||
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
uint32_t ulRegionBaseAddress;
|
||||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
uint32_t ulRegionBaseAddress;
|
||||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
|
||||
/* Plus 1 to create space for the stack region. */
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||
} xMPU_SETTINGS;
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* SVC numbers for various services. */
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) : "memory" )
|
||||
#define portYIELD_WITHIN_API() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ::: "memory" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
#define portYIELD() __asm volatile ( " SVC %0 \n"::"i" ( portSVC_YIELD ) : "memory" )
|
||||
#define portYIELD_WITHIN_API() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
* within the specified behaviour for the architecture. */\
|
||||
__asm volatile ( "dsb" ::: "memory" ); \
|
||||
__asm volatile ( "isb" ); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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 )
|
||||
* 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
return ucReturn;
|
||||
}
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
|
||||
/* 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
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* 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 ) )
|
||||
/* 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
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/* 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 ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
extern BaseType_t xIsPrivileged( void );
|
||||
extern void vResetPrivilege( void );
|
||||
extern BaseType_t xIsPrivileged( void );
|
||||
extern void vResetPrivilege( void );
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n"\
|
||||
" msr basepri, %0 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n"\
|
||||
" mov %1, %2 \n"\
|
||||
" msr basepri, %1 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
* warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security. https://www.freertos.org/FreeRTOS-V10.3.x.html"
|
||||
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||
#endif
|
||||
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security. https: /*www.freertos.org/FreeRTOS-V10.3.x.html" */
|
||||
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -43,205 +43,205 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ::: "memory" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
* within the specified behaviour for the architecture. */\
|
||||
__asm volatile ( "dsb" ::: "memory" ); \
|
||||
__asm volatile ( "isb" ); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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 )
|
||||
* 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
return ucReturn;
|
||||
}
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
|
||||
/* 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
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* 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 ) )
|
||||
/* 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
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/* 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 ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" cpsid i \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
" cpsie i \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n"\
|
||||
" cpsid i \n"\
|
||||
" msr basepri, %0 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
" cpsie i \n"\
|
||||
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" cpsid i \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
" cpsie i \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n"\
|
||||
" mov %1, %2 \n"\
|
||||
" cpsid i \n"\
|
||||
" msr basepri, %1 \n"\
|
||||
" isb \n"\
|
||||
" dsb \n"\
|
||||
" cpsie i \n"\
|
||||
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
* warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -32,118 +32,118 @@
|
|||
#include "task.h"
|
||||
|
||||
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
|
||||
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. Refer to Cortex-A equivalent: http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
|
||||
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. Refer to Cortex-A equivalent: http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. Refer to Cortex-A equivalent: http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. Refer to Cortex-A equivalent: http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif /* configSETUP_TICK_INTERRUPT */
|
||||
|
||||
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. Refer to Cortex-A equivalent: http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* 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
|
||||
/* 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
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/* In case security extensions are implemented. */
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#endif
|
||||
|
||||
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
|
||||
portmacro.h. */
|
||||
* portmacro.h. */
|
||||
#ifndef configCLEAR_TICK_INTERRUPT
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
* this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
/* In all GICs 255 can be written to the priority mask register to unmask all
|
||||
(but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
* (but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
|
||||
/* Tasks are not created with a floating point context, but can be given a
|
||||
floating point context after they have been created. A variable is stored as
|
||||
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
does not have an FPU context, or any other value if the task does have an FPU
|
||||
context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
* floating point context after they have been created. A variable is stored as
|
||||
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
* does not have an FPU context, or any other value if the task does have an FPU
|
||||
* context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the initial task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINTERRUPT_ENABLE_BIT ( 0x80UL )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINTERRUPT_ENABLE_BIT ( 0x80UL )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
|
||||
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
|
||||
point is zero. */
|
||||
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
|
||||
* point is zero. */
|
||||
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
|
||||
/* The value of the mode bits in the APSR when the CPU is executing in user
|
||||
mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
* mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
|
||||
/* The critical section macros only mask interrupts up to an application
|
||||
determined priority level. Sometimes it is necessary to turn interrupt off in
|
||||
the CPU itself before modifying certain hardware registers. */
|
||||
#define portCPU_IRQ_DISABLE() \
|
||||
__asm volatile ( "CPSID i" ::: "memory" ); \
|
||||
__asm volatile ( "DSB" ); \
|
||||
__asm volatile ( "ISB" );
|
||||
* determined priority level. Sometimes it is necessary to turn interrupt off in
|
||||
* the CPU itself before modifying certain hardware registers. */
|
||||
#define portCPU_IRQ_DISABLE() \
|
||||
__asm volatile ( "CPSID i" ::: "memory" ); \
|
||||
__asm volatile ( "DSB" ); \
|
||||
__asm volatile ( "ISB" );
|
||||
|
||||
#define portCPU_IRQ_ENABLE() \
|
||||
__asm volatile ( "CPSIE i" ::: "memory" ); \
|
||||
__asm volatile ( "DSB" ); \
|
||||
__asm volatile ( "ISB" );
|
||||
#define portCPU_IRQ_ENABLE() \
|
||||
__asm volatile ( "CPSIE i" ::: "memory" ); \
|
||||
__asm volatile ( "DSB" ); \
|
||||
__asm volatile ( "ISB" );
|
||||
|
||||
|
||||
/* Macro to unmask all interrupt priorities. */
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
portCPU_IRQ_DISABLE(); \
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
|
||||
__asm volatile ( "DSB \n" \
|
||||
"ISB \n" ); \
|
||||
portCPU_IRQ_ENABLE(); \
|
||||
}
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
portCPU_IRQ_DISABLE(); \
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
|
||||
__asm volatile ( "DSB \n" \
|
||||
"ISB \n"); \
|
||||
portCPU_IRQ_ENABLE(); \
|
||||
}
|
||||
|
||||
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
|
||||
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
|
||||
|
||||
/* Let the user override the pre-loading of the initial LR with the address of
|
||||
prvTaskExitError() in case is messes up unwinding of the stack in the
|
||||
debugger. */
|
||||
* prvTaskExitError() in case is messes up unwinding of the stack in the
|
||||
* debugger. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -162,363 +162,368 @@ static void prvTaskExitError( void );
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* A variable is used to keep track of the critical section nesting. This
|
||||
variable has to be stored as part of the task context and must be initialised to
|
||||
a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
the scheduler starts. As it is stored as part of the task context it will
|
||||
automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
* variable has to be stored as part of the task context and must be initialised to
|
||||
* a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
* the scheduler starts. As it is stored as part of the task context it will
|
||||
* automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then
|
||||
a floating point context must be saved and restored for the task. */
|
||||
uint32_t ulPortTaskHasFPUContext = pdFALSE;
|
||||
* a floating point context must be saved and restored for the task. */
|
||||
uint32_t ulPortTaskHasFPUContext = pdFALSE;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
uint32_t ulPortYieldRequired = pdFALSE;
|
||||
uint32_t ulPortYieldRequired = pdFALSE;
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||
if the nesting depth is 0. */
|
||||
uint32_t ulPortInterruptNesting = 0UL;
|
||||
* if the nesting depth is 0. */
|
||||
uint32_t ulPortInterruptNesting = 0UL;
|
||||
|
||||
/* Used in asm code. */
|
||||
__attribute__(( used )) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__attribute__( ( used ) ) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro.
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro.
|
||||
*
|
||||
* The fist real value on the stack is the status register, which is set for
|
||||
* system mode, with interrupts enabled. A few NULLs are added first to ensure
|
||||
* GDB does not try decoding a non-existent return address. */
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
The fist real value on the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. A few NULLs are added first to ensure
|
||||
GDB does not try decoding a non-existent return address. */
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
|
||||
{
|
||||
/* The task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
|
||||
{
|
||||
/* The task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
pxTopOfStack--;
|
||||
|
||||
pxTopOfStack--;
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
* enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
/* The task will start without a floating point context. A task that uses
|
||||
* the floating point hardware must call vPortTaskUsesFPU() before executing
|
||||
* any floating point instructions. */
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
|
||||
/* The task will start without a floating point context. A task that uses
|
||||
the floating point hardware must call vPortTaskUsesFPU() before executing
|
||||
any floating point instructions. */
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
its caller as there is nothing to return to. If a task wants to exit it
|
||||
should instead call vTaskDelete( NULL ).
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
* its caller as there is nothing to return to. If a task wants to exit it
|
||||
* should instead call vTaskDelete( NULL ).
|
||||
*
|
||||
* Artificially force an assert() to be triggered if configASSERT() is
|
||||
* defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( ulPortInterruptNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
Artificially force an assert() to be triggered if configASSERT() is
|
||||
defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( ulPortInterruptNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
for( ; ; )
|
||||
{
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
|
||||
uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine how many priority bits are implemented in the GIC.
|
||||
/* Determine how many priority bits are implemented in the GIC.
|
||||
*
|
||||
* Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
/* Determine the number of priority bits available. First write to
|
||||
* all possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Determine the number of priority bits available. First write to
|
||||
all possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
/* Shift to the least significant bits. */
|
||||
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
|
||||
{
|
||||
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
|
||||
|
||||
/* Shift to the least significant bits. */
|
||||
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
|
||||
{
|
||||
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
|
||||
/* If ulCycles reaches 0 then ucMaxPriorityValue must have been
|
||||
* read as 0, indicating a misconfiguration. */
|
||||
ulCycles--;
|
||||
|
||||
/* If ulCycles reaches 0 then ucMaxPriorityValue must have been
|
||||
read as 0, indicating a misconfiguration. */
|
||||
ulCycles--;
|
||||
if( ulCycles == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( ulCycles == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
|
||||
value. */
|
||||
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
|
||||
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
|
||||
* value. */
|
||||
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
* value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) :: "memory" );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
* Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
|
||||
if( ulAPSR != portAPSR_USER_MODE )
|
||||
{
|
||||
/* Only continue if the binary point value is set to its lowest possible
|
||||
setting. See the comments in vPortValidateInterruptPriority() below for
|
||||
more information. */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
if( ulAPSR != portAPSR_USER_MODE )
|
||||
{
|
||||
/* Only continue if the binary point value is set to its lowest possible
|
||||
* setting. See the comments in vPortValidateInterruptPriority() below for
|
||||
* more information. */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
|
||||
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
{
|
||||
/* Interrupts are turned off in the CPU itself to ensure tick does
|
||||
not execute while the scheduler is being started. Interrupts are
|
||||
automatically turned back on in the CPU when the first task starts
|
||||
executing. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
{
|
||||
/* Interrupts are turned off in the CPU itself to ensure tick does
|
||||
* not execute while the scheduler is being started. Interrupts are
|
||||
* automatically turned back on in the CPU when the first task starts
|
||||
* executing. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
}
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
}
|
||||
|
||||
/* Will only get here if vTaskStartScheduler() was called with the CPU in
|
||||
a non-privileged mode or the binary point register was not set to its lowest
|
||||
possible value. prvTaskExitError() is referenced to prevent a compiler
|
||||
warning about it being defined but not referenced in the case that the user
|
||||
defines their own exit address. */
|
||||
( void ) prvTaskExitError;
|
||||
return 0;
|
||||
/* Will only get here if vTaskStartScheduler() was called with the CPU in
|
||||
* a non-privileged mode or the binary point register was not set to its lowest
|
||||
* possible value. prvTaskExitError() is referenced to prevent a compiler
|
||||
* warning about it being defined but not referenced in the case that the user
|
||||
* defines their own exit address. */
|
||||
( void ) prvTaskExitError;
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Mask interrupts up to the max syscall interrupt priority. */
|
||||
ulPortSetInterruptMask();
|
||||
/* Mask interrupts up to the max syscall interrupt priority. */
|
||||
ulPortSetInterruptMask();
|
||||
|
||||
/* 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++;
|
||||
/* 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++;
|
||||
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
assert() if it is being called from an interrupt context. Only API
|
||||
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
the critical nesting count is 1 to protect against recursive calls if the
|
||||
assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
* assert() if it is being called from an interrupt context. Only API
|
||||
* functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
* the critical nesting count is 1 to protect against recursive calls if the
|
||||
* assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
* exited. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
* priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
* should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
so there is no need to save and restore the current mask value. It is
|
||||
necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
updated. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb \n"
|
||||
"isb \n" ::: "memory" );
|
||||
portCPU_IRQ_ENABLE();
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
* handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
* so there is no need to save and restore the current mask value. It is
|
||||
* necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
* updated. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb \n"
|
||||
"isb \n"::: "memory" );
|
||||
portCPU_IRQ_ENABLE();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
FPU flag (which is saved as part of the task context). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
* FPU flag (which is saved as part of the task context). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Initialise the floating point status register. */
|
||||
__asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) : "memory" );
|
||||
/* Initialise the floating point status register. */
|
||||
__asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortClearInterruptMask( uint32_t ulNewMaskValue )
|
||||
{
|
||||
if( ulNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
if( ulNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulPortSetInterruptMask( void )
|
||||
{
|
||||
uint32_t ulReturn;
|
||||
uint32_t ulReturn;
|
||||
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
updated. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb \n"
|
||||
"isb \n" ::: "memory" );
|
||||
}
|
||||
portCPU_IRQ_ENABLE();
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
* updated. */
|
||||
portCPU_IRQ_DISABLE();
|
||||
|
||||
return ulReturn;
|
||||
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm volatile ( "dsb \n"
|
||||
"isb \n"::: "memory" );
|
||||
}
|
||||
|
||||
portCPU_IRQ_ENABLE();
|
||||
|
||||
return ulReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
* an interrupt that has been assigned a priority above
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
* function. ISR safe FreeRTOS API functions must *only* be called
|
||||
* from interrupts that have been assigned a priority at or below
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*
|
||||
* Numerically low interrupt priority numbers represent logically high
|
||||
* interrupt priorities, therefore the priority of the interrupt must
|
||||
* be set to a value equal to or numerically *higher* than
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*
|
||||
* FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
* interrupt entry is as fast and simple as possible. */
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible. */
|
||||
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
|
||||
/* Priority grouping: The interrupt controller (GIC) allows the bits
|
||||
that define each interrupt's priority to be split between bits that
|
||||
define the interrupt's pre-emption priority bits and bits that define
|
||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
to be pre-emption priority bits. The following assertion will fail if
|
||||
this is not the case (if some bits represent a sub-priority).
|
||||
|
||||
The priority grouping is configured by the GIC's binary point register
|
||||
(ICCBPR). Writing 0 to ICCBPR will ensure it is set to its lowest
|
||||
possible value (which may be above 0). */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
}
|
||||
/* Priority grouping: The interrupt controller (GIC) allows the bits
|
||||
* that define each interrupt's priority to be split between bits that
|
||||
* define the interrupt's pre-emption priority bits and bits that define
|
||||
* the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
* to be pre-emption priority bits. The following assertion will fail if
|
||||
* this is not the case (if some bits represent a sub-priority).
|
||||
*
|
||||
* The priority grouping is configured by the GIC's binary point register
|
||||
* (ICCBPR). Writing 0 to ICCBPR will ensure it is set to its lowest
|
||||
* possible value (which may be above 0). */
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,153 +42,152 @@
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0" ::: "memory" );
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0" ::: "memory" );
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
* not required for this port but included in case common demo code that uses these
|
||||
* macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
* handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
* before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* 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 ) )
|
||||
/* 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 - __builtin_clz( uxReadyPriorities ) )
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portNOP() __asm volatile ( "NOP" )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
* number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
|
||||
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -32,50 +32,50 @@
|
|||
#include "task.h"
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* 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
|
||||
/* 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
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt.
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt.
|
||||
#endif
|
||||
|
||||
#ifndef configCLEAR_TICK_INTERRUPT
|
||||
#error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt.
|
||||
#error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt.
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
* this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
/* Tasks are not created with a floating point context, but can be given a
|
||||
floating point context after they have been created. A variable is stored as
|
||||
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
does not have an FPU context, or any other value if the task does have an FPU
|
||||
context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
* floating point context after they have been created. A variable is stored as
|
||||
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
* does not have an FPU context, or any other value if the task does have an FPU
|
||||
* context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the initial task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
|
||||
/* The value of the mode bits in the APSR when the CPU is executing in user
|
||||
mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
* mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
|
||||
/* Let the user override the pre-loading of the initial LR with the address of
|
||||
prvTaskExitError() in case it messes up unwinding of the stack in the
|
||||
debugger. */
|
||||
* prvTaskExitError() in case it messes up unwinding of the stack in the
|
||||
* debugger. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -94,225 +94,229 @@ static void prvTaskExitError( void );
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* A variable is used to keep track of the critical section nesting. This
|
||||
variable has to be stored as part of the task context and must be initialised to
|
||||
a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
the scheduler starts. As it is stored as part of the task context it will
|
||||
automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
* variable has to be stored as part of the task context and must be initialised to
|
||||
* a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
* the scheduler starts. As it is stored as part of the task context it will
|
||||
* automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then
|
||||
a floating point context must be saved and restored for the task. */
|
||||
* a floating point context must be saved and restored for the task. */
|
||||
volatile uint32_t ulPortTaskHasFPUContext = pdFALSE;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
volatile uint32_t ulPortYieldRequired = pdFALSE;
|
||||
volatile uint32_t ulPortYieldRequired = pdFALSE;
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||
if the nesting depth is 0. */
|
||||
volatile uint32_t ulPortInterruptNesting = 0UL;
|
||||
* if the nesting depth is 0. */
|
||||
volatile uint32_t ulPortInterruptNesting = 0UL;
|
||||
|
||||
/* Used in the asm file to clear an interrupt. */
|
||||
__attribute__(( used )) const uint32_t ulICCEOIR = configEOI_ADDRESS;
|
||||
__attribute__( ( used ) ) const uint32_t ulICCEOIR = configEOI_ADDRESS;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro.
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro.
|
||||
*
|
||||
* The fist real value on the stack is the status register, which is set for
|
||||
* system mode, with interrupts enabled. A few NULLs are added first to ensure
|
||||
* GDB does not try decoding a non-existent return address. */
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
The fist real value on the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. A few NULLs are added first to ensure
|
||||
GDB does not try decoding a non-existent return address. */
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
|
||||
{
|
||||
/* The task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
|
||||
{
|
||||
/* The task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
pxTopOfStack--;
|
||||
|
||||
pxTopOfStack--;
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
* enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
/* The task will start without a floating point context. A task that uses
|
||||
* the floating point hardware must call vPortTaskUsesFPU() before executing
|
||||
* any floating point instructions. */
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
|
||||
/* The task will start without a floating point context. A task that uses
|
||||
the floating point hardware must call vPortTaskUsesFPU() before executing
|
||||
any floating point instructions. */
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
its caller as there is nothing to return to. If a task wants to exit it
|
||||
should instead call vTaskDelete( NULL ).
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
* its caller as there is nothing to return to. If a task wants to exit it
|
||||
* should instead call vTaskDelete( NULL ).
|
||||
*
|
||||
* Artificially force an assert() to be triggered if configASSERT() is
|
||||
* defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( ulPortInterruptNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
Artificially force an assert() to be triggered if configASSERT() is
|
||||
defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( ulPortInterruptNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
for( ; ; )
|
||||
{
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
uint32_t ulAPSR;
|
||||
uint32_t ulAPSR;
|
||||
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) :: "memory" );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
* Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" );
|
||||
|
||||
if( ulAPSR != portAPSR_USER_MODE )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
if( ulAPSR != portAPSR_USER_MODE )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
/* Will only get here if vTaskStartScheduler() was called with the CPU in
|
||||
a non-privileged mode or the binary point register was not set to its lowest
|
||||
possible value. prvTaskExitError() is referenced to prevent a compiler
|
||||
warning about it being defined but not referenced in the case that the user
|
||||
defines their own exit address. */
|
||||
( void ) prvTaskExitError;
|
||||
return 0;
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
|
||||
/* Will only get here if vTaskStartScheduler() was called with the CPU in
|
||||
* a non-privileged mode or the binary point register was not set to its lowest
|
||||
* possible value. prvTaskExitError() is referenced to prevent a compiler
|
||||
* warning about it being defined but not referenced in the case that the user
|
||||
* defines their own exit address. */
|
||||
( void ) prvTaskExitError;
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
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++;
|
||||
/* 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++;
|
||||
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
assert() if it is being called from an interrupt context. Only API
|
||||
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
the critical nesting count is 1 to protect against recursive calls if the
|
||||
assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
* assert() if it is being called from an interrupt context. Only API
|
||||
* functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
* the critical nesting count is 1 to protect against recursive calls if the
|
||||
* assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
* exited. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
* priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
* should be unmasked. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
uint32_t ulInterruptStatus;
|
||||
uint32_t ulInterruptStatus;
|
||||
|
||||
ulInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
ulInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulInterruptStatus );
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulInterruptStatus );
|
||||
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
FPU flag (which is saved as part of the task context). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
* FPU flag (which is saved as part of the task context). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Initialise the floating point status register. */
|
||||
__asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) : "memory" );
|
||||
/* Initialise the floating point status register. */
|
||||
__asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,139 +42,141 @@
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern volatile uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern volatile uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0 \n" \
|
||||
"ISB " ::: "memory" );
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() \
|
||||
__asm volatile ( "SWI 0 \n"\
|
||||
"ISB "::: "memory" );
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
/* The I bit within the CPSR. */
|
||||
#define portINTERRUPT_ENABLE_BIT ( 1 << 7 )
|
||||
#define portINTERRUPT_ENABLE_BIT ( 1 << 7 )
|
||||
|
||||
/* In the absence of a priority mask register, these functions and macros
|
||||
globally enable and disable interrupts. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( "CPSIE i \n" ::: "memory" );
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( "CPSID i \n" \
|
||||
"DSB \n" \
|
||||
"ISB " ::: "memory" );
|
||||
* globally enable and disable interrupts. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( "CPSIE i \n"::: "memory" );
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( "CPSID i \n" \
|
||||
"DSB \n" \
|
||||
"ISB "::: "memory" );
|
||||
|
||||
__attribute__( ( always_inline ) ) static __inline uint32_t portINLINE_SET_INTERRUPT_MASK_FROM_ISR( void )
|
||||
{
|
||||
volatile uint32_t ulCPSR;
|
||||
__attribute__( ( always_inline ) ) static __inline uint32_t portINLINE_SET_INTERRUPT_MASK_FROM_ISR( void )
|
||||
{
|
||||
volatile uint32_t ulCPSR;
|
||||
|
||||
__asm volatile ( "MRS %0, CPSR" : "=r" (ulCPSR) :: "memory" );
|
||||
ulCPSR &= portINTERRUPT_ENABLE_BIT;
|
||||
portDISABLE_INTERRUPTS();
|
||||
return ulCPSR;
|
||||
}
|
||||
__asm volatile ( "MRS %0, CPSR" : "=r" ( ulCPSR )::"memory" );
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() portINLINE_SET_INTERRUPT_MASK_FROM_ISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) if( x == 0 ) portENABLE_INTERRUPTS()
|
||||
ulCPSR &= portINTERRUPT_ENABLE_BIT;
|
||||
portDISABLE_INTERRUPTS();
|
||||
return ulCPSR;
|
||||
}
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() portINLINE_SET_INTERRUPT_MASK_FROM_ISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) if( x == 0 ) portENABLE_INTERRUPTS()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
* not required for this port but included in case common demo code that uses these
|
||||
* macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
* handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
* before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* 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 ) )
|
||||
/* 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 = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE __inline
|
||||
#define portNOP() __asm volatile ( "NOP" )
|
||||
#define portINLINE __inline
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Changes from V2.6.0
|
||||
|
||||
+ AVR port - Replaced the inb() and outb() functions with direct memory
|
||||
access. This allows the port to be built with the 20050414 build of
|
||||
WinAVR.
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* Changes from V2.6.0
|
||||
*
|
||||
+ AVR port - Replaced the inb() and outb() functions with direct memory
|
||||
+ access. This allows the port to be built with the 20050414 build of
|
||||
+ WinAVR.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
|
@ -40,135 +40,135 @@ Changes from V2.6.0
|
|||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the AVR port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the AVR port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Start tasks with interrupts enables. */
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x80 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x80 )
|
||||
|
||||
/* Hardware constants for timer 1. */
|
||||
#define portCLEAR_COUNTER_ON_MATCH ( ( uint8_t ) 0x08 )
|
||||
#define portPRESCALE_64 ( ( uint8_t ) 0x03 )
|
||||
#define portCLOCK_PRESCALER ( ( uint32_t ) 64 )
|
||||
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE ( ( uint8_t ) 0x10 )
|
||||
#define portCLEAR_COUNTER_ON_MATCH ( ( uint8_t ) 0x08 )
|
||||
#define portPRESCALE_64 ( ( uint8_t ) 0x03 )
|
||||
#define portCLOCK_PRESCALER ( ( uint32_t ) 64 )
|
||||
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE ( ( uint8_t ) 0x10 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* We require the address of the pxCurrentTCB variable, but don't want to know
|
||||
any details of its type. */
|
||||
* any details of its type. */
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Macro to save all the general purpose registers, the save the stack pointer
|
||||
* into the TCB.
|
||||
*
|
||||
* The first thing we do is save the flags then disable interrupts. This is to
|
||||
* guard our stack against having a context switch interrupt after we have already
|
||||
* pushed the registers onto the stack - causing the 32 registers to be on the
|
||||
* stack twice.
|
||||
*
|
||||
* into the TCB.
|
||||
*
|
||||
* The first thing we do is save the flags then disable interrupts. This is to
|
||||
* guard our stack against having a context switch interrupt after we have already
|
||||
* pushed the registers onto the stack - causing the 32 registers to be on the
|
||||
* stack twice.
|
||||
*
|
||||
* r1 is set to zero as the compiler expects it to be thus, however some
|
||||
* of the math routines make use of R1.
|
||||
*
|
||||
* of the math routines make use of R1.
|
||||
*
|
||||
* The interrupts will have been disabled during the call to portSAVE_CONTEXT()
|
||||
* so we need not worry about reading/writing to the stack pointer.
|
||||
* so we need not worry about reading/writing to the stack pointer.
|
||||
*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm volatile ( "push r0 \n\t" \
|
||||
"in r0, __SREG__ \n\t" \
|
||||
"cli \n\t" \
|
||||
"push r0 \n\t" \
|
||||
"push r1 \n\t" \
|
||||
"clr r1 \n\t" \
|
||||
"push r2 \n\t" \
|
||||
"push r3 \n\t" \
|
||||
"push r4 \n\t" \
|
||||
"push r5 \n\t" \
|
||||
"push r6 \n\t" \
|
||||
"push r7 \n\t" \
|
||||
"push r8 \n\t" \
|
||||
"push r9 \n\t" \
|
||||
"push r10 \n\t" \
|
||||
"push r11 \n\t" \
|
||||
"push r12 \n\t" \
|
||||
"push r13 \n\t" \
|
||||
"push r14 \n\t" \
|
||||
"push r15 \n\t" \
|
||||
"push r16 \n\t" \
|
||||
"push r17 \n\t" \
|
||||
"push r18 \n\t" \
|
||||
"push r19 \n\t" \
|
||||
"push r20 \n\t" \
|
||||
"push r21 \n\t" \
|
||||
"push r22 \n\t" \
|
||||
"push r23 \n\t" \
|
||||
"push r24 \n\t" \
|
||||
"push r25 \n\t" \
|
||||
"push r26 \n\t" \
|
||||
"push r27 \n\t" \
|
||||
"push r28 \n\t" \
|
||||
"push r29 \n\t" \
|
||||
"push r30 \n\t" \
|
||||
"push r31 \n\t" \
|
||||
"lds r26, pxCurrentTCB \n\t" \
|
||||
"lds r27, pxCurrentTCB + 1 \n\t" \
|
||||
"in r0, 0x3d \n\t" \
|
||||
"st x+, r0 \n\t" \
|
||||
"in r0, 0x3e \n\t" \
|
||||
"st x+, r0 \n\t" \
|
||||
);
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm volatile ( "push r0 \n\t"\
|
||||
"in r0, __SREG__ \n\t"\
|
||||
"cli \n\t"\
|
||||
"push r0 \n\t"\
|
||||
"push r1 \n\t"\
|
||||
"clr r1 \n\t"\
|
||||
"push r2 \n\t"\
|
||||
"push r3 \n\t"\
|
||||
"push r4 \n\t"\
|
||||
"push r5 \n\t"\
|
||||
"push r6 \n\t"\
|
||||
"push r7 \n\t"\
|
||||
"push r8 \n\t"\
|
||||
"push r9 \n\t"\
|
||||
"push r10 \n\t"\
|
||||
"push r11 \n\t"\
|
||||
"push r12 \n\t"\
|
||||
"push r13 \n\t"\
|
||||
"push r14 \n\t"\
|
||||
"push r15 \n\t"\
|
||||
"push r16 \n\t"\
|
||||
"push r17 \n\t"\
|
||||
"push r18 \n\t"\
|
||||
"push r19 \n\t"\
|
||||
"push r20 \n\t"\
|
||||
"push r21 \n\t"\
|
||||
"push r22 \n\t"\
|
||||
"push r23 \n\t"\
|
||||
"push r24 \n\t"\
|
||||
"push r25 \n\t"\
|
||||
"push r26 \n\t"\
|
||||
"push r27 \n\t"\
|
||||
"push r28 \n\t"\
|
||||
"push r29 \n\t"\
|
||||
"push r30 \n\t"\
|
||||
"push r31 \n\t"\
|
||||
"lds r26, pxCurrentTCB \n\t"\
|
||||
"lds r27, pxCurrentTCB + 1 \n\t"\
|
||||
"in r0, 0x3d \n\t"\
|
||||
"st x+, r0 \n\t"\
|
||||
"in r0, 0x3e \n\t"\
|
||||
"st x+, r0 \n\t"\
|
||||
);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Opposite to portSAVE_CONTEXT(). Interrupts will have been disabled during
|
||||
* the context save so we can write to the stack pointer.
|
||||
* the context save so we can write to the stack pointer.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm volatile ( "lds r26, pxCurrentTCB \n\t" \
|
||||
"lds r27, pxCurrentTCB + 1 \n\t" \
|
||||
"ld r28, x+ \n\t" \
|
||||
"out __SP_L__, r28 \n\t" \
|
||||
"ld r29, x+ \n\t" \
|
||||
"out __SP_H__, r29 \n\t" \
|
||||
"pop r31 \n\t" \
|
||||
"pop r30 \n\t" \
|
||||
"pop r29 \n\t" \
|
||||
"pop r28 \n\t" \
|
||||
"pop r27 \n\t" \
|
||||
"pop r26 \n\t" \
|
||||
"pop r25 \n\t" \
|
||||
"pop r24 \n\t" \
|
||||
"pop r23 \n\t" \
|
||||
"pop r22 \n\t" \
|
||||
"pop r21 \n\t" \
|
||||
"pop r20 \n\t" \
|
||||
"pop r19 \n\t" \
|
||||
"pop r18 \n\t" \
|
||||
"pop r17 \n\t" \
|
||||
"pop r16 \n\t" \
|
||||
"pop r15 \n\t" \
|
||||
"pop r14 \n\t" \
|
||||
"pop r13 \n\t" \
|
||||
"pop r12 \n\t" \
|
||||
"pop r11 \n\t" \
|
||||
"pop r10 \n\t" \
|
||||
"pop r9 \n\t" \
|
||||
"pop r8 \n\t" \
|
||||
"pop r7 \n\t" \
|
||||
"pop r6 \n\t" \
|
||||
"pop r5 \n\t" \
|
||||
"pop r4 \n\t" \
|
||||
"pop r3 \n\t" \
|
||||
"pop r2 \n\t" \
|
||||
"pop r1 \n\t" \
|
||||
"pop r0 \n\t" \
|
||||
"out __SREG__, r0 \n\t" \
|
||||
"pop r0 \n\t" \
|
||||
);
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm volatile ( "lds r26, pxCurrentTCB \n\t"\
|
||||
"lds r27, pxCurrentTCB + 1 \n\t"\
|
||||
"ld r28, x+ \n\t"\
|
||||
"out __SP_L__, r28 \n\t"\
|
||||
"ld r29, x+ \n\t"\
|
||||
"out __SP_H__, r29 \n\t"\
|
||||
"pop r31 \n\t"\
|
||||
"pop r30 \n\t"\
|
||||
"pop r29 \n\t"\
|
||||
"pop r28 \n\t"\
|
||||
"pop r27 \n\t"\
|
||||
"pop r26 \n\t"\
|
||||
"pop r25 \n\t"\
|
||||
"pop r24 \n\t"\
|
||||
"pop r23 \n\t"\
|
||||
"pop r22 \n\t"\
|
||||
"pop r21 \n\t"\
|
||||
"pop r20 \n\t"\
|
||||
"pop r19 \n\t"\
|
||||
"pop r18 \n\t"\
|
||||
"pop r17 \n\t"\
|
||||
"pop r16 \n\t"\
|
||||
"pop r15 \n\t"\
|
||||
"pop r14 \n\t"\
|
||||
"pop r13 \n\t"\
|
||||
"pop r12 \n\t"\
|
||||
"pop r11 \n\t"\
|
||||
"pop r10 \n\t"\
|
||||
"pop r9 \n\t"\
|
||||
"pop r8 \n\t"\
|
||||
"pop r7 \n\t"\
|
||||
"pop r6 \n\t"\
|
||||
"pop r5 \n\t"\
|
||||
"pop r4 \n\t"\
|
||||
"pop r3 \n\t"\
|
||||
"pop r2 \n\t"\
|
||||
"pop r1 \n\t"\
|
||||
"pop r0 \n\t"\
|
||||
"out __SREG__, r0 \n\t"\
|
||||
"pop r0 \n\t"\
|
||||
);
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -178,145 +178,147 @@ extern volatile TCB_t * volatile pxCurrentTCB;
|
|||
static void prvSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
uint16_t usAddress;
|
||||
uint16_t usAddress;
|
||||
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging. */
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
* This is just useful for debugging. */
|
||||
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Simulate how the stack would look after a call to vPortYield() generated by
|
||||
the compiler. */
|
||||
/* Simulate how the stack would look after a call to vPortYield() generated by
|
||||
* the compiler. */
|
||||
|
||||
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
|
||||
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
|
||||
|
||||
/* The start of the task code will be popped off the stack last, so place
|
||||
it on first. */
|
||||
usAddress = ( uint16_t ) pxCode;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
/* The start of the task code will be popped off the stack last, so place
|
||||
* it on first. */
|
||||
usAddress = ( uint16_t ) pxCode;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
|
||||
usAddress >>= 8;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
usAddress >>= 8;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next simulate the stack as if after a call to portSAVE_CONTEXT().
|
||||
portSAVE_CONTEXT places the flags on the stack immediately after r0
|
||||
to ensure the interrupts get disabled as soon as possible, and so ensuring
|
||||
the stack use is minimal should a context switch interrupt occur. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pxTopOfStack--;
|
||||
/* Next simulate the stack as if after a call to portSAVE_CONTEXT().
|
||||
* portSAVE_CONTEXT places the flags on the stack immediately after r0
|
||||
* to ensure the interrupts get disabled as soon as possible, and so ensuring
|
||||
* the stack use is minimal should a context switch interrupt occur. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pxTopOfStack--;
|
||||
|
||||
|
||||
/* Now the remaining registers. The compiler expects R1 to be 0. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x13; /* R13 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x14; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x15; /* R15 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x16; /* R16 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x17; /* R17 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x18; /* R18 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x19; /* R19 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x20; /* R20 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x21; /* R21 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x22; /* R22 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x23; /* R23 */
|
||||
pxTopOfStack--;
|
||||
/* Now the remaining registers. The compiler expects R1 to be 0. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x13; /* R13 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x14; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x15; /* R15 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x16; /* R16 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x17; /* R17 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x18; /* R18 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x19; /* R19 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x20; /* R20 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x21; /* R21 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x22; /* R22 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x23; /* R23 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Place the parameter on the stack in the expected location. */
|
||||
usAddress = ( uint16_t ) pvParameters;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
/* Place the parameter on the stack in the expected location. */
|
||||
usAddress = ( uint16_t ) pvParameters;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
|
||||
usAddress >>= 8;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
usAddress >>= 8;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x26; /* R26 X */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x27; /* R27 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x28; /* R28 Y */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x29; /* R29 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x30; /* R30 Z */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x031; /* R31 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x26; /* R26 X */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x27; /* R27 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x28; /* R28 Y */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x29; /* R29 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x30; /* R30 Z */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x031; /* R31 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/*lint +e950 +e611 +e923 */
|
||||
/*lint +e950 +e611 +e923 */
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Setup the hardware to generate the tick. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Setup the hardware to generate the tick. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Simulate a function call end as generated by the compiler. We will now
|
||||
jump to the start of the task the context of which we have just restored. */
|
||||
asm volatile ( "ret" );
|
||||
/* Simulate a function call end as generated by the compiler. We will now
|
||||
* jump to the start of the task the context of which we have just restored. */
|
||||
asm volatile ( "ret" );
|
||||
|
||||
/* Should not get here. */
|
||||
return pdTRUE;
|
||||
/* Should not get here. */
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the AVR port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
/* It is unlikely that the AVR port will get stopped. If required simply
|
||||
* disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -324,34 +326,36 @@ void vPortEndScheduler( void )
|
|||
* Manual context switch. The first thing we do is save the registers so we
|
||||
* can use a naked attribute.
|
||||
*/
|
||||
void vPortYield( void ) __attribute__ ( ( naked ) );
|
||||
void vPortYield( void ) __attribute__( ( naked ) );
|
||||
void vPortYield( void )
|
||||
{
|
||||
portSAVE_CONTEXT();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT();
|
||||
portSAVE_CONTEXT();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
asm volatile ( "ret" );
|
||||
asm volatile ( "ret" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Context switch function used by the tick. This must be identical to
|
||||
* Context switch function used by the tick. This must be identical to
|
||||
* vPortYield() from the call to vTaskSwitchContext() onwards. The only
|
||||
* difference from vPortYield() is the tick count is incremented as the
|
||||
* call comes from the tick ISR.
|
||||
*/
|
||||
void vPortYieldFromTick( void ) __attribute__ ( ( naked ) );
|
||||
void vPortYieldFromTick( void ) __attribute__( ( naked ) );
|
||||
void vPortYieldFromTick( void )
|
||||
{
|
||||
portSAVE_CONTEXT();
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
portRESTORE_CONTEXT();
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
asm volatile ( "ret" );
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
asm volatile ( "ret" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -360,66 +364,63 @@ void vPortYieldFromTick( void )
|
|||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
uint8_t ucHighByte, ucLowByte;
|
||||
uint32_t ulCompareMatch;
|
||||
uint8_t ucHighByte, ucLowByte;
|
||||
|
||||
/* Using 16bit timer 1 to generate the tick. Correct fuses must be
|
||||
selected for the configCPU_CLOCK_HZ clock. */
|
||||
/* Using 16bit timer 1 to generate the tick. Correct fuses must be
|
||||
* selected for the configCPU_CLOCK_HZ clock. */
|
||||
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* We only have 16 bits so have to scale to get our required tick rate. */
|
||||
ulCompareMatch /= portCLOCK_PRESCALER;
|
||||
/* We only have 16 bits so have to scale to get our required tick rate. */
|
||||
ulCompareMatch /= portCLOCK_PRESCALER;
|
||||
|
||||
/* Adjust for correct value. */
|
||||
ulCompareMatch -= ( uint32_t ) 1;
|
||||
/* Adjust for correct value. */
|
||||
ulCompareMatch -= ( uint32_t ) 1;
|
||||
|
||||
/* Setup compare match value for compare match A. Interrupts are disabled
|
||||
before this is called so we need not worry here. */
|
||||
ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
|
||||
ulCompareMatch >>= 8;
|
||||
ucHighByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
|
||||
OCR1AH = ucHighByte;
|
||||
OCR1AL = ucLowByte;
|
||||
/* Setup compare match value for compare match A. Interrupts are disabled
|
||||
* before this is called so we need not worry here. */
|
||||
ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
|
||||
ulCompareMatch >>= 8;
|
||||
ucHighByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
|
||||
OCR1AH = ucHighByte;
|
||||
OCR1AL = ucLowByte;
|
||||
|
||||
/* Setup clock source and compare match behaviour. */
|
||||
ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64;
|
||||
TCCR1B = ucLowByte;
|
||||
/* Setup clock source and compare match behaviour. */
|
||||
ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64;
|
||||
TCCR1B = ucLowByte;
|
||||
|
||||
/* Enable the interrupt - this is okay as interrupt are currently globally
|
||||
disabled. */
|
||||
ucLowByte = TIMSK;
|
||||
ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
|
||||
TIMSK = ucLowByte;
|
||||
/* Enable the interrupt - this is okay as interrupt are currently globally
|
||||
* disabled. */
|
||||
ucLowByte = TIMSK;
|
||||
ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
|
||||
TIMSK = ucLowByte;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_PREEMPTION == 1
|
||||
|
||||
/*
|
||||
* Tick ISR for preemptive scheduler. We can use a naked attribute as
|
||||
* the context is saved at the start of vPortYieldFromTick(). The tick
|
||||
* count is incremented after the context is saved.
|
||||
*/
|
||||
void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal, naked ) );
|
||||
void SIG_OUTPUT_COMPARE1A( void )
|
||||
{
|
||||
vPortYieldFromTick();
|
||||
asm volatile ( "reti" );
|
||||
}
|
||||
/*
|
||||
* Tick ISR for preemptive scheduler. We can use a naked attribute as
|
||||
* the context is saved at the start of vPortYieldFromTick(). The tick
|
||||
* count is incremented after the context is saved.
|
||||
*/
|
||||
void SIG_OUTPUT_COMPARE1A( void ) __attribute__( ( signal, naked ) );
|
||||
void SIG_OUTPUT_COMPARE1A( void )
|
||||
{
|
||||
vPortYieldFromTick();
|
||||
asm volatile ( "reti" );
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* Tick ISR for the cooperative scheduler. All this does is increment the
|
||||
* tick count. We don't need to switch context, this can only be done by
|
||||
* manual calls to taskYIELD();
|
||||
*/
|
||||
void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal ) );
|
||||
void SIG_OUTPUT_COMPARE1A( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Tick ISR for the cooperative scheduler. All this does is increment the
|
||||
* tick count. We don't need to switch context, this can only be done by
|
||||
* manual calls to taskYIELD();
|
||||
*/
|
||||
void SIG_OUTPUT_COMPARE1A( void ) __attribute__( ( signal ) );
|
||||
void SIG_OUTPUT_COMPARE1A( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
#endif /* if configUSE_PREEMPTION == 1 */
|
||||
|
|
|
|||
|
|
@ -25,18 +25,18 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
Changes from V1.2.3
|
||||
|
||||
+ portCPU_CLOSK_HZ definition changed to 8MHz base 10, previously it
|
||||
base 16.
|
||||
*/
|
||||
* Changes from V1.2.3
|
||||
*
|
||||
+ portCPU_CLOSK_HZ definition changed to 8MHz base 10, previously it
|
||||
+ base 16.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -49,58 +49,59 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
#define portENTER_CRITICAL() asm volatile ( "in __tmp_reg__, __SREG__" :: ); \
|
||||
asm volatile ( "cli" :: ); \
|
||||
asm volatile ( "push __tmp_reg__" :: )
|
||||
#define portENTER_CRITICAL() \
|
||||
asm volatile ( "in __tmp_reg__, __SREG__"::); \
|
||||
asm volatile ( "cli" ::); \
|
||||
asm volatile ( "push __tmp_reg__"::)
|
||||
|
||||
#define portEXIT_CRITICAL() asm volatile ( "pop __tmp_reg__" :: ); \
|
||||
asm volatile ( "out __SREG__, __tmp_reg__" :: )
|
||||
#define portEXIT_CRITICAL() \
|
||||
asm volatile ( "pop __tmp_reg__"::); \
|
||||
asm volatile ( "out __SREG__, __tmp_reg__"::)
|
||||
|
||||
#define portDISABLE_INTERRUPTS() asm volatile ( "cli" :: );
|
||||
#define portENABLE_INTERRUPTS() asm volatile ( "sei" :: );
|
||||
#define portDISABLE_INTERRUPTS() asm volatile ( "cli" ::);
|
||||
#define portENABLE_INTERRUPTS() asm volatile ( "sei" ::);
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
#define portNOP() asm volatile ( "nop" );
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
#define portNOP() asm volatile ( "nop" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Kernel utilities. */
|
||||
extern void vPortYield( void ) __attribute__ ( ( naked ) );
|
||||
#define portYIELD() vPortYield()
|
||||
extern void vPortYield( void ) __attribute__( ( naked ) );
|
||||
#define portYIELD() vPortYield()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/*This file has been prepared for Doxygen automatic documentation generation.*/
|
||||
|
||||
/*! \file *********************************************************************
|
||||
*
|
||||
* \brief FreeRTOS port source for AVR32 UC3.
|
||||
|
|
@ -51,23 +52,23 @@
|
|||
/* AVR32 UC3 includes. */
|
||||
#include <avr32/io.h>
|
||||
#include "gpio.h"
|
||||
#if( configTICK_USE_TC==1 )
|
||||
#include "tc.h"
|
||||
#if ( configTICK_USE_TC == 1 )
|
||||
#include "tc.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SR ( ( StackType_t ) 0x00400000 ) /* AVR32 : [M2:M0]=001 I1M=0 I0M=0, GM=0 */
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0 )
|
||||
#define portINITIAL_SR ( ( StackType_t ) 0x00400000 ) /* AVR32 : [M2:M0]=001 I1M=0 I0M=0, GM=0 */
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0 )
|
||||
|
||||
/* Each task maintains its own critical nesting variable. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
#if( configTICK_USE_TC==0 )
|
||||
static void prvScheduleNextTick( void );
|
||||
#if ( configTICK_USE_TC == 0 )
|
||||
static void prvScheduleNextTick( void );
|
||||
#else
|
||||
static void prvClearTcInt( void );
|
||||
static void prvClearTcInt( void );
|
||||
#endif
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
|
|
@ -83,55 +84,53 @@ static void prvSetupTimerInterrupt( void );
|
|||
* vectors are not compatible with the SCALL management in the current FreeRTOS
|
||||
* port. More low-level initializations are besides added here.
|
||||
*/
|
||||
void _init_startup(void)
|
||||
void _init_startup( void )
|
||||
{
|
||||
/* Import the Exception Vector Base Address. */
|
||||
extern void _evba;
|
||||
/* Import the Exception Vector Base Address. */
|
||||
extern void _evba;
|
||||
|
||||
#if configHEAP_INIT
|
||||
extern void __heap_start__;
|
||||
extern void __heap_end__;
|
||||
BaseType_t *pxMem;
|
||||
#endif
|
||||
#if configHEAP_INIT
|
||||
extern void __heap_start__;
|
||||
extern void __heap_end__;
|
||||
BaseType_t * pxMem;
|
||||
#endif
|
||||
|
||||
/* Load the Exception Vector Base Address in the corresponding system register. */
|
||||
Set_system_register( AVR32_EVBA, ( int ) &_evba );
|
||||
/* Load the Exception Vector Base Address in the corresponding system register. */
|
||||
Set_system_register( AVR32_EVBA, ( int ) &_evba );
|
||||
|
||||
/* Enable exceptions. */
|
||||
ENABLE_ALL_EXCEPTIONS();
|
||||
/* Enable exceptions. */
|
||||
ENABLE_ALL_EXCEPTIONS();
|
||||
|
||||
/* Initialize interrupt handling. */
|
||||
INTC_init_interrupts();
|
||||
/* Initialize interrupt handling. */
|
||||
INTC_init_interrupts();
|
||||
|
||||
#if configHEAP_INIT
|
||||
#if configHEAP_INIT
|
||||
/* Initialize the heap used by malloc. */
|
||||
for( pxMem = &__heap_start__; pxMem < ( BaseType_t * ) &__heap_end__; )
|
||||
{
|
||||
*pxMem++ = 0xA5A5A5A5;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the heap used by malloc. */
|
||||
for( pxMem = &__heap_start__; pxMem < ( BaseType_t * )&__heap_end__; )
|
||||
{
|
||||
*pxMem++ = 0xA5A5A5A5;
|
||||
}
|
||||
/* Give the used CPU clock frequency to Newlib, so it can work properly. */
|
||||
set_cpu_hz( configCPU_CLOCK_HZ );
|
||||
|
||||
#endif
|
||||
/* Code section present if and only if the debug trace is activated. */
|
||||
#if configDBG
|
||||
{
|
||||
static const gpio_map_t DBG_USART_GPIO_MAP =
|
||||
{
|
||||
{ configDBG_USART_RX_PIN, configDBG_USART_RX_FUNCTION },
|
||||
{ configDBG_USART_TX_PIN, configDBG_USART_TX_FUNCTION }
|
||||
};
|
||||
|
||||
/* Give the used CPU clock frequency to Newlib, so it can work properly. */
|
||||
set_cpu_hz( configCPU_CLOCK_HZ );
|
||||
|
||||
/* Code section present if and only if the debug trace is activated. */
|
||||
#if configDBG
|
||||
{
|
||||
static const gpio_map_t DBG_USART_GPIO_MAP =
|
||||
{
|
||||
{ configDBG_USART_RX_PIN, configDBG_USART_RX_FUNCTION },
|
||||
{ configDBG_USART_TX_PIN, configDBG_USART_TX_FUNCTION }
|
||||
};
|
||||
|
||||
/* Initialize the USART used for the debug trace with the configured parameters. */
|
||||
set_usart_base( ( void * ) configDBG_USART );
|
||||
gpio_enable_module( DBG_USART_GPIO_MAP,
|
||||
sizeof( DBG_USART_GPIO_MAP ) / sizeof( DBG_USART_GPIO_MAP[0] ) );
|
||||
usart_init( configDBG_USART_BAUDRATE );
|
||||
}
|
||||
#endif
|
||||
/* Initialize the USART used for the debug trace with the configured parameters. */
|
||||
set_usart_base( ( void * ) configDBG_USART );
|
||||
gpio_enable_module( DBG_USART_GPIO_MAP,
|
||||
sizeof( DBG_USART_GPIO_MAP ) / sizeof( DBG_USART_GPIO_MAP[ 0 ] ) );
|
||||
usart_init( configDBG_USART_BAUDRATE );
|
||||
}
|
||||
#endif /* if configDBG */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -154,9 +153,9 @@ void _init_startup(void)
|
|||
* safe section as memory allocation management uses global data.
|
||||
* See the aforementioned details.
|
||||
*/
|
||||
void __malloc_lock(struct _reent *ptr)
|
||||
void __malloc_lock( struct _reent * ptr )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
vTaskSuspendAll();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -164,92 +163,96 @@ void __malloc_lock(struct _reent *ptr)
|
|||
* a safe section as memory allocation management uses global data.
|
||||
* See the aforementioned details.
|
||||
*/
|
||||
void __malloc_unlock(struct _reent *ptr)
|
||||
void __malloc_unlock( struct _reent * ptr )
|
||||
{
|
||||
xTaskResumeAll();
|
||||
xTaskResumeAll();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Added as there is no such function in FreeRTOS. */
|
||||
void *pvPortRealloc( void *pv, size_t xWantedSize )
|
||||
void * pvPortRealloc( void * pv,
|
||||
size_t xWantedSize )
|
||||
{
|
||||
void *pvReturn;
|
||||
void * pvReturn;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
pvReturn = realloc( pv, xWantedSize );
|
||||
}
|
||||
xTaskResumeAll();
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
pvReturn = realloc( pv, xWantedSize );
|
||||
}
|
||||
xTaskResumeAll();
|
||||
|
||||
return pvReturn;
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
* simply increment the system tick. */
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is saved
|
||||
on entry as part of the context switch. */
|
||||
__attribute__((__naked__)) static void vTick( void )
|
||||
* on entry as part of the context switch. */
|
||||
__attribute__( ( __naked__ ) ) static void vTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT_OS_INT();
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT_OS_INT();
|
||||
|
||||
#if( configTICK_USE_TC==1 )
|
||||
/* Clear the interrupt flag. */
|
||||
prvClearTcInt();
|
||||
#else
|
||||
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)
|
||||
clock cycles from now. */
|
||||
prvScheduleNextTick();
|
||||
#endif
|
||||
#if ( configTICK_USE_TC == 1 )
|
||||
/* Clear the interrupt flag. */
|
||||
prvClearTcInt();
|
||||
#else
|
||||
|
||||
/* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
|
||||
calls in a critical section . */
|
||||
portENTER_CRITICAL();
|
||||
xTaskIncrementTick();
|
||||
portEXIT_CRITICAL();
|
||||
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)
|
||||
* clock cycles from now. */
|
||||
prvScheduleNextTick();
|
||||
#endif
|
||||
|
||||
/* Restore the context of the "elected task". */
|
||||
portRESTORE_CONTEXT_OS_INT();
|
||||
/* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
|
||||
* calls in a critical section . */
|
||||
portENTER_CRITICAL();
|
||||
xTaskIncrementTick();
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* Restore the context of the "elected task". */
|
||||
portRESTORE_CONTEXT_OS_INT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__attribute__((__naked__)) void SCALLYield( void )
|
||||
__attribute__( ( __naked__ ) ) void SCALLYield( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT_SCALL();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT_SCALL();
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT_SCALL();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT_SCALL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
__attribute__((__noinline__)) void vPortEnterCritical( void )
|
||||
* different optimisation levels. The interrupt flags can therefore not always
|
||||
* be saved to the stack. Instead the critical section nesting level is stored
|
||||
* in a variable, which is then saved as part of the stack context. */
|
||||
__attribute__( ( __noinline__ ) ) void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts */
|
||||
portDISABLE_INTERRUPTS();
|
||||
/* Disable 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++;
|
||||
/* 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++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__attribute__((__noinline__)) void vPortExitCritical( void )
|
||||
__attribute__( ( __noinline__ ) ) void vPortExitCritical( void )
|
||||
{
|
||||
if(ulCriticalNesting > portNO_CRITICAL_NESTING)
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable all interrupt/exception. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable all interrupt/exception. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -259,176 +262,182 @@ __attribute__((__noinline__)) void vPortExitCritical( void )
|
|||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* When the task starts, it will expect to find the function parameter in R12. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x08080808; /* R8 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x09090909; /* R9 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x0A0A0A0A; /* R10 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x0B0B0B0B; /* R11 */
|
||||
*pxTopOfStack-- = ( StackType_t ) pvParameters; /* R12 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xDEADBEEF; /* R14/LR */
|
||||
*pxTopOfStack-- = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; /* R15/PC */
|
||||
*pxTopOfStack-- = ( StackType_t ) portINITIAL_SR; /* SR */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xFF0000FF; /* R0 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x01010101; /* R1 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x02020202; /* R2 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x03030303; /* R3 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x04040404; /* R4 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x05050505; /* R5 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x06060606; /* R6 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x07070707; /* R7 */
|
||||
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_NESTING; /* ulCriticalNesting */
|
||||
/* When the task starts, it will expect to find the function parameter in R12. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x08080808; /* R8 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x09090909; /* R9 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x0A0A0A0A; /* R10 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x0B0B0B0B; /* R11 */
|
||||
*pxTopOfStack-- = ( StackType_t ) pvParameters; /* R12 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xDEADBEEF; /* R14/LR */
|
||||
*pxTopOfStack-- = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; /* R15/PC */
|
||||
*pxTopOfStack-- = ( StackType_t ) portINITIAL_SR; /* SR */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xFF0000FF; /* R0 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x01010101; /* R1 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x02020202; /* R2 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x03030303; /* R3 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x04040404; /* R4 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x05050505; /* R5 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x06060606; /* R6 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x07070707; /* R7 */
|
||||
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_NESTING; /* ulCriticalNesting */
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Start the first task. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the AVR32 port will require this function as there
|
||||
is nothing to return to. */
|
||||
/* It is unlikely that the AVR32 port will require this function as there
|
||||
* is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)
|
||||
clock cycles from now. */
|
||||
#if( configTICK_USE_TC==0 )
|
||||
static void prvScheduleFirstTick(void)
|
||||
{
|
||||
uint32_t lCycles;
|
||||
* clock cycles from now. */
|
||||
#if ( configTICK_USE_TC == 0 )
|
||||
static void prvScheduleFirstTick( void )
|
||||
{
|
||||
uint32_t lCycles;
|
||||
|
||||
lCycles = Get_system_register(AVR32_COUNT);
|
||||
lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);
|
||||
// If lCycles ends up to be 0, make it 1 so that the COMPARE and exception
|
||||
// generation feature does not get disabled.
|
||||
if(0 == lCycles)
|
||||
{
|
||||
lCycles++;
|
||||
}
|
||||
Set_system_register(AVR32_COMPARE, lCycles);
|
||||
}
|
||||
|
||||
__attribute__((__noinline__)) static void prvScheduleNextTick(void)
|
||||
{
|
||||
uint32_t lCycles, lCount;
|
||||
lCycles = Get_system_register( AVR32_COUNT );
|
||||
lCycles += ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
|
||||
lCycles = Get_system_register(AVR32_COMPARE);
|
||||
lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);
|
||||
// If lCycles ends up to be 0, make it 1 so that the COMPARE and exception
|
||||
// generation feature does not get disabled.
|
||||
if(0 == lCycles)
|
||||
{
|
||||
lCycles++;
|
||||
}
|
||||
lCount = Get_system_register(AVR32_COUNT);
|
||||
if( lCycles < lCount )
|
||||
{ // We missed a tick, recover for the next.
|
||||
lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);
|
||||
}
|
||||
Set_system_register(AVR32_COMPARE, lCycles);
|
||||
}
|
||||
#else
|
||||
__attribute__((__noinline__)) static void prvClearTcInt(void)
|
||||
{
|
||||
AVR32_TC.channel[configTICK_TC_CHANNEL].sr;
|
||||
}
|
||||
#endif
|
||||
/* If lCycles ends up to be 0, make it 1 so that the COMPARE and exception */
|
||||
/* generation feature does not get disabled. */
|
||||
if( 0 == lCycles )
|
||||
{
|
||||
lCycles++;
|
||||
}
|
||||
|
||||
Set_system_register( AVR32_COMPARE, lCycles );
|
||||
}
|
||||
|
||||
__attribute__( ( __noinline__ ) ) static void prvScheduleNextTick( void )
|
||||
{
|
||||
uint32_t lCycles, lCount;
|
||||
|
||||
lCycles = Get_system_register( AVR32_COMPARE );
|
||||
lCycles += ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
|
||||
/* If lCycles ends up to be 0, make it 1 so that the COMPARE and exception */
|
||||
/* generation feature does not get disabled. */
|
||||
if( 0 == lCycles )
|
||||
{
|
||||
lCycles++;
|
||||
}
|
||||
|
||||
lCount = Get_system_register( AVR32_COUNT );
|
||||
|
||||
if( lCycles < lCount )
|
||||
{ /* We missed a tick, recover for the next. */
|
||||
lCycles += ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
}
|
||||
|
||||
Set_system_register( AVR32_COMPARE, lCycles );
|
||||
}
|
||||
#else /* if ( configTICK_USE_TC == 0 ) */
|
||||
__attribute__( ( __noinline__ ) ) static void prvClearTcInt( void )
|
||||
{
|
||||
AVR32_TC.channel[ configTICK_TC_CHANNEL ].sr;
|
||||
}
|
||||
#endif /* if ( configTICK_USE_TC == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt(void)
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
#if( configTICK_USE_TC==1 )
|
||||
#if ( configTICK_USE_TC == 1 )
|
||||
volatile avr32_tc_t * tc = &AVR32_TC;
|
||||
|
||||
volatile avr32_tc_t *tc = &AVR32_TC;
|
||||
/* Options for waveform genration. */
|
||||
tc_waveform_opt_t waveform_opt =
|
||||
{
|
||||
.channel = configTICK_TC_CHANNEL, /* Channel selection. */
|
||||
|
||||
// Options for waveform genration.
|
||||
tc_waveform_opt_t waveform_opt =
|
||||
{
|
||||
.channel = configTICK_TC_CHANNEL, /* Channel selection. */
|
||||
.bswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOB. */
|
||||
.beevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOB. */
|
||||
.bcpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOB. */
|
||||
.bcpb = TC_EVT_EFFECT_NOOP, /* RB compare effect on TIOB. */
|
||||
|
||||
.bswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOB. */
|
||||
.beevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOB. */
|
||||
.bcpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOB. */
|
||||
.bcpb = TC_EVT_EFFECT_NOOP, /* RB compare effect on TIOB. */
|
||||
.aswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOA. */
|
||||
.aeevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOA. */
|
||||
.acpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOA: toggle. */
|
||||
.acpa = TC_EVT_EFFECT_NOOP, /* RA compare effect on TIOA: toggle (other possibilities are none, set and clear). */
|
||||
|
||||
.aswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOA. */
|
||||
.aeevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOA. */
|
||||
.acpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOA: toggle. */
|
||||
.acpa = TC_EVT_EFFECT_NOOP, /* RA compare effect on TIOA: toggle (other possibilities are none, set and clear). */
|
||||
.wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, /* Waveform selection: Up mode without automatic trigger on RC compare. */
|
||||
.enetrg = FALSE, /* External event trigger enable. */
|
||||
.eevt = 0, /* External event selection. */
|
||||
.eevtedg = TC_SEL_NO_EDGE, /* External event edge selection. */
|
||||
.cpcdis = FALSE, /* Counter disable when RC compare. */
|
||||
.cpcstop = FALSE, /* Counter clock stopped with RC compare. */
|
||||
|
||||
.wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,/* Waveform selection: Up mode without automatic trigger on RC compare. */
|
||||
.enetrg = FALSE, /* External event trigger enable. */
|
||||
.eevt = 0, /* External event selection. */
|
||||
.eevtedg = TC_SEL_NO_EDGE, /* External event edge selection. */
|
||||
.cpcdis = FALSE, /* Counter disable when RC compare. */
|
||||
.cpcstop = FALSE, /* Counter clock stopped with RC compare. */
|
||||
.burst = FALSE, /* Burst signal selection. */
|
||||
.clki = FALSE, /* Clock inversion. */
|
||||
.tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */
|
||||
};
|
||||
|
||||
.burst = FALSE, /* Burst signal selection. */
|
||||
.clki = FALSE, /* Clock inversion. */
|
||||
.tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */
|
||||
};
|
||||
tc_interrupt_t tc_interrupt =
|
||||
{
|
||||
.etrgs = 0,
|
||||
.ldrbs = 0,
|
||||
.ldras = 0,
|
||||
.cpcs = 1,
|
||||
.cpbs = 0,
|
||||
.cpas = 0,
|
||||
.lovrs = 0,
|
||||
.covfs = 0,
|
||||
};
|
||||
#endif /* if ( configTICK_USE_TC == 1 ) */
|
||||
|
||||
tc_interrupt_t tc_interrupt =
|
||||
{
|
||||
.etrgs=0,
|
||||
.ldrbs=0,
|
||||
.ldras=0,
|
||||
.cpcs =1,
|
||||
.cpbs =0,
|
||||
.cpas =0,
|
||||
.lovrs=0,
|
||||
.covfs=0,
|
||||
};
|
||||
/* Disable all interrupt/exception. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
#endif
|
||||
/* Register the compare interrupt handler to the interrupt controller and
|
||||
* enable the compare interrupt. */
|
||||
|
||||
/* Disable all interrupt/exception. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
#if ( configTICK_USE_TC == 1 )
|
||||
{
|
||||
INTC_register_interrupt( &vTick, configTICK_TC_IRQ, INT0 );
|
||||
|
||||
/* Register the compare interrupt handler to the interrupt controller and
|
||||
enable the compare interrupt. */
|
||||
/* Initialize the timer/counter. */
|
||||
tc_init_waveform( tc, &waveform_opt );
|
||||
|
||||
#if( configTICK_USE_TC==1 )
|
||||
{
|
||||
INTC_register_interrupt(&vTick, configTICK_TC_IRQ, INT0);
|
||||
/* Set the compare triggers.
|
||||
* Remember TC counter is 16-bits, so counting second is not possible!
|
||||
* That's why we configure it to count ms. */
|
||||
tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4 ) / configTICK_RATE_HZ );
|
||||
|
||||
/* Initialize the timer/counter. */
|
||||
tc_init_waveform(tc, &waveform_opt);
|
||||
tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt );
|
||||
|
||||
/* Set the compare triggers.
|
||||
Remember TC counter is 16-bits, so counting second is not possible!
|
||||
That's why we configure it to count ms. */
|
||||
tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4) / configTICK_RATE_HZ );
|
||||
|
||||
tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt );
|
||||
|
||||
/* Start the timer/counter. */
|
||||
tc_start(tc, configTICK_TC_CHANNEL);
|
||||
}
|
||||
#else
|
||||
{
|
||||
INTC_register_interrupt(&vTick, AVR32_CORE_COMPARE_IRQ, INT0);
|
||||
prvScheduleFirstTick();
|
||||
}
|
||||
#endif
|
||||
/* Start the timer/counter. */
|
||||
tc_start( tc, configTICK_TC_CHANNEL );
|
||||
}
|
||||
#else /* if ( configTICK_USE_TC == 1 ) */
|
||||
{
|
||||
INTC_register_interrupt( &vTick, AVR32_CORE_COMPARE_IRQ, INT0 );
|
||||
prvScheduleFirstTick();
|
||||
}
|
||||
#endif /* if ( configTICK_USE_TC == 1 ) */
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -37,7 +37,7 @@
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The initial PSR has the Previous Interrupt Enabled (PIEN) flag set. */
|
||||
#define portINITIAL_PSR ( 0x00020000 )
|
||||
#define portINITIAL_PSR ( 0x00020000 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -47,98 +47,100 @@
|
|||
static void prvSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Make space on the stack for the context - this leaves a couple of spaces
|
||||
empty. */
|
||||
pxTopOfStack -= 20;
|
||||
/* Make space on the stack for the context - this leaves a couple of spaces
|
||||
* empty. */
|
||||
pxTopOfStack -= 20;
|
||||
|
||||
/* Fill the registers with known values to assist debugging. */
|
||||
pxTopOfStack[ 16 ] = 0;
|
||||
pxTopOfStack[ 15 ] = portINITIAL_PSR;
|
||||
pxTopOfStack[ 14 ] = ( uint32_t ) pxCode;
|
||||
pxTopOfStack[ 13 ] = 0x00000000UL; /* R15. */
|
||||
pxTopOfStack[ 12 ] = 0x00000000UL; /* R14. */
|
||||
pxTopOfStack[ 11 ] = 0x0d0d0d0dUL;
|
||||
pxTopOfStack[ 10 ] = 0x0c0c0c0cUL;
|
||||
pxTopOfStack[ 9 ] = 0x0b0b0b0bUL;
|
||||
pxTopOfStack[ 8 ] = 0x0a0a0a0aUL;
|
||||
pxTopOfStack[ 7 ] = 0x09090909UL;
|
||||
pxTopOfStack[ 6 ] = 0x08080808UL;
|
||||
pxTopOfStack[ 5 ] = 0x07070707UL;
|
||||
pxTopOfStack[ 4 ] = 0x06060606UL;
|
||||
pxTopOfStack[ 3 ] = 0x05050505UL;
|
||||
pxTopOfStack[ 2 ] = 0x04040404UL;
|
||||
pxTopOfStack[ 1 ] = 0x03030303UL;
|
||||
pxTopOfStack[ 0 ] = ( uint32_t ) pvParameters;
|
||||
/* Fill the registers with known values to assist debugging. */
|
||||
pxTopOfStack[ 16 ] = 0;
|
||||
pxTopOfStack[ 15 ] = portINITIAL_PSR;
|
||||
pxTopOfStack[ 14 ] = ( uint32_t ) pxCode;
|
||||
pxTopOfStack[ 13 ] = 0x00000000UL; /* R15. */
|
||||
pxTopOfStack[ 12 ] = 0x00000000UL; /* R14. */
|
||||
pxTopOfStack[ 11 ] = 0x0d0d0d0dUL;
|
||||
pxTopOfStack[ 10 ] = 0x0c0c0c0cUL;
|
||||
pxTopOfStack[ 9 ] = 0x0b0b0b0bUL;
|
||||
pxTopOfStack[ 8 ] = 0x0a0a0a0aUL;
|
||||
pxTopOfStack[ 7 ] = 0x09090909UL;
|
||||
pxTopOfStack[ 6 ] = 0x08080808UL;
|
||||
pxTopOfStack[ 5 ] = 0x07070707UL;
|
||||
pxTopOfStack[ 4 ] = 0x06060606UL;
|
||||
pxTopOfStack[ 3 ] = 0x05050505UL;
|
||||
pxTopOfStack[ 2 ] = 0x04040404UL;
|
||||
pxTopOfStack[ 1 ] = 0x03030303UL;
|
||||
pxTopOfStack[ 0 ] = ( uint32_t ) pvParameters;
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Set-up the timer interrupt. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Set-up the timer interrupt. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Integrated Interrupt Controller: Enable all interrupts. */
|
||||
ic->ien = 1;
|
||||
/* Integrated Interrupt Controller: Enable all interrupts. */
|
||||
ic->ien = 1;
|
||||
|
||||
/* Restore callee saved registers. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore callee saved registers. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Should not get here. */
|
||||
return 0;
|
||||
/* Should not get here. */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Enable timer interrupts */
|
||||
counter1->reload = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1;
|
||||
counter1->value = counter1->reload;
|
||||
counter1->mask = 1;
|
||||
/* Enable timer interrupts */
|
||||
counter1->reload = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1;
|
||||
counter1->value = counter1->reload;
|
||||
counter1->mask = 1;
|
||||
|
||||
/* Set the IRQ Handler priority and enable it. */
|
||||
irq[ IRQ_COUNTER1 ].ien = 1;
|
||||
/* Set the IRQ Handler priority and enable it. */
|
||||
irq[ IRQ_COUNTER1 ].ien = 1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Trap 31 handler. */
|
||||
void interrupt31_handler( void ) __attribute__((naked));
|
||||
void interrupt31_handler( void ) __attribute__( ( naked ) );
|
||||
void interrupt31_handler( void )
|
||||
{
|
||||
portSAVE_CONTEXT();
|
||||
__asm volatile ( "call vTaskSwitchContext" );
|
||||
portRESTORE_CONTEXT();
|
||||
portSAVE_CONTEXT();
|
||||
__asm volatile ( "call vTaskSwitchContext" );
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvProcessTick( void ) __attribute__((noinline));
|
||||
static void prvProcessTick( void ) __attribute__( ( noinline ) );
|
||||
static void prvProcessTick( void )
|
||||
{
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Clear the Tick Interrupt. */
|
||||
counter1->expired = 0;
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Clear the Tick Interrupt. */
|
||||
counter1->expired = 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Timer 1 interrupt handler, used for tick interrupt. */
|
||||
void interrupt7_handler( void ) __attribute__((naked));
|
||||
void interrupt7_handler( void ) __attribute__( ( naked ) );
|
||||
void interrupt7_handler( void )
|
||||
{
|
||||
portSAVE_CONTEXT();
|
||||
prvProcessTick();
|
||||
portRESTORE_CONTEXT();
|
||||
portSAVE_CONTEXT();
|
||||
prvProcessTick();
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Nothing to do. Unlikely to want to end. */
|
||||
/* Nothing to do. Unlikely to want to end. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -44,108 +44,108 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portNOP() __asm__ volatile ( "mov r0, r0" )
|
||||
#define portCRITICAL_NESTING_IN_TCB 1
|
||||
#define portIRQ_TRAP_YIELD 31
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portNOP() __asm__ volatile ( "mov r0, r0" )
|
||||
#define portCRITICAL_NESTING_IN_TCB 1
|
||||
#define portIRQ_TRAP_YIELD 31
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
extern void vPortYield( void );
|
||||
extern void vPortYield( void );
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define portYIELD() asm __volatile__( " trap #%0 "::"i"(portIRQ_TRAP_YIELD):"memory")
|
||||
#define portYIELD() asm __volatile__ ( " trap #%0 " : : "i" ( portIRQ_TRAP_YIELD ) : "memory" )
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
#define portDISABLE_INTERRUPTS() cpu_int_disable()
|
||||
#define portENABLE_INTERRUPTS() cpu_int_enable()
|
||||
#define portDISABLE_INTERRUPTS() cpu_int_disable()
|
||||
#define portENABLE_INTERRUPTS() cpu_int_enable()
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken != pdFALSE ) vTaskSwitchContext()
|
||||
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken != pdFALSE ) vTaskSwitchContext()
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm __volatile__ \
|
||||
( \
|
||||
"sub r1, #68 \n" /* Make space on the stack for the context. */ \
|
||||
"std r2, [r1] + 0 \n" \
|
||||
"stq r4, [r1] + 8 \n" \
|
||||
"stq r8, [r1] + 24 \n" \
|
||||
"stq r12, [r1] + 40 \n" \
|
||||
"mov r6, rtt \n" \
|
||||
"mov r7, psr \n" \
|
||||
"std r6, [r1] + 56 \n" \
|
||||
"movhi r2, #16384 \n" /* Set the pointer to the IC. */ \
|
||||
"ldub r3, [r2] + 2 \n" /* Load the current interrupt mask. */ \
|
||||
"st r3, [r1]+ 64 \n" /* Store the interrupt mask on the stack. */ \
|
||||
"ld r2, [r0]+short(pxCurrentTCB) \n" /* Load the pointer to the TCB. */ \
|
||||
"st r1, [r2] \n" /* Save the stack pointer into the TCB. */ \
|
||||
"mov r14, r1 \n" /* Compiler expects r14 to be set to the function stack. */ \
|
||||
);
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm __volatile__ \
|
||||
( \
|
||||
"sub r1, #68 \n"/* Make space on the stack for the context. */ \
|
||||
"std r2, [r1] + 0 \n" \
|
||||
"stq r4, [r1] + 8 \n" \
|
||||
"stq r8, [r1] + 24 \n" \
|
||||
"stq r12, [r1] + 40 \n" \
|
||||
"mov r6, rtt \n" \
|
||||
"mov r7, psr \n" \
|
||||
"std r6, [r1] + 56 \n" \
|
||||
"movhi r2, #16384 \n" /* Set the pointer to the IC. */ \
|
||||
"ldub r3, [r2] + 2 \n" /* Load the current interrupt mask. */ \
|
||||
"st r3, [r1]+ 64 \n" /* Store the interrupt mask on the stack. */ \
|
||||
"ld r2, [r0]+short(pxCurrentTCB) \n"/* Load the pointer to the TCB. */ \
|
||||
"st r1, [r2] \n" /* Save the stack pointer into the TCB. */ \
|
||||
"mov r14, r1 \n" /* Compiler expects r14 to be set to the function stack. */ \
|
||||
);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm __volatile__( \
|
||||
"ld r2, [r0]+short(pxCurrentTCB) \n" /* Load the TCB to find the stack pointer and context. */ \
|
||||
"ld r1, [r2] \n" \
|
||||
"movhi r2, #16384 \n" /* Set the pointer to the IC. */ \
|
||||
"ld r3, [r1] + 64 \n" /* Load the previous interrupt mask. */ \
|
||||
"stb r3, [r2] + 2 \n" /* Set the current interrupt mask to be the previous. */ \
|
||||
"ldd r6, [r1] + 56 \n" /* Restore context. */ \
|
||||
"mov rtt, r6 \n" \
|
||||
"mov psr, r7 \n" \
|
||||
"ldd r2, [r1] + 0 \n" \
|
||||
"ldq r4, [r1] + 8 \n" \
|
||||
"ldq r8, [r1] + 24 \n" \
|
||||
"ldq r12, [r1] + 40 \n" \
|
||||
"add r1, #68 \n" \
|
||||
"rti \n" \
|
||||
);
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm __volatile__ ( \
|
||||
"ld r2, [r0]+short(pxCurrentTCB) \n"/* Load the TCB to find the stack pointer and context. */\
|
||||
"ld r1, [r2] \n" \
|
||||
"movhi r2, #16384 \n" /* Set the pointer to the IC. */ \
|
||||
"ld r3, [r1] + 64 \n" /* Load the previous interrupt mask. */ \
|
||||
"stb r3, [r2] + 2 \n" /* Set the current interrupt mask to be the previous. */ \
|
||||
"ldd r6, [r1] + 56 \n" /* Restore context. */ \
|
||||
"mov rtt, r6 \n" \
|
||||
"mov psr, r7 \n" \
|
||||
"ldd r2, [r1] + 0 \n" \
|
||||
"ldq r4, [r1] + 8 \n" \
|
||||
"ldq r8, [r1] + 24 \n" \
|
||||
"ldq r12, [r1] + 40 \n" \
|
||||
"add r1, #68 \n" \
|
||||
"rti \n" \
|
||||
);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -28,34 +28,36 @@
|
|||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
|
||||
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
|
||||
|
||||
/* Supervisor mode set. */
|
||||
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
|
||||
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000 )
|
||||
|
||||
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
|
||||
will be set to 0 prior to the first task being started. */
|
||||
* will be set to 0 prior to the first task being started. */
|
||||
static uint32_t ulCriticalNesting = 0x9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = (StackType_t) 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Exception stack frame starts with the return address. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
/* Exception stack frame starts with the return address. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER );
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x0; /*FP*/
|
||||
pxTopOfStack -= 14; /* A5 to D0. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x0; /*FP*/
|
||||
pxTopOfStack -= 14; /* A5 to D0. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
|
|
@ -63,71 +65,67 @@ StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t p
|
|||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void vPortStartFirstTask( void );
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
ulCriticalNesting = 0UL;
|
||||
ulCriticalNesting = 0UL;
|
||||
|
||||
/* Configure the interrupts used by this port. */
|
||||
vApplicationSetupInterrupts();
|
||||
/* Configure the interrupts used by this port. */
|
||||
vApplicationSetupInterrupts();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortStartFirstTask();
|
||||
/* Start the first task executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
return pdFALSE;
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented as there is nothing to return to. */
|
||||
/* Not implemented as there is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting == 0UL )
|
||||
{
|
||||
/* Guard against context switches being pended simultaneously with a
|
||||
critical section being entered. */
|
||||
do
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( MCF_INTC0_INTFRCL == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( ulCriticalNesting == 0UL )
|
||||
{
|
||||
/* Guard against context switches being pended simultaneously with a
|
||||
* critical section being entered. */
|
||||
do
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
if( MCF_INTC0_INTFRCL == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
} while( 1 );
|
||||
}
|
||||
ulCriticalNesting++;
|
||||
portENABLE_INTERRUPTS();
|
||||
} while( 1 );
|
||||
}
|
||||
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
ulCriticalNesting--;
|
||||
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYieldHandler( void )
|
||||
{
|
||||
uint32_t ulSavedInterruptMask;
|
||||
uint32_t ulSavedInterruptMask;
|
||||
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
/* Note this will clear all forced interrupts - this is done for speed. */
|
||||
MCF_INTC0_INTFRCL = 0;
|
||||
vTaskSwitchContext();
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
/* Note this will clear all forced interrupts - this is done for speed. */
|
||||
MCF_INTC0_INTFRCL = 0;
|
||||
vTaskSwitchContext();
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,72 +42,72 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH -1
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH -1
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
/*-----------------------------------------------------------*/
|
||||
uint32_t ulPortSetIPL( uint32_t );
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
|
||||
uint32_t ulPortSetIPL( uint32_t );
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
|
||||
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
|
||||
extern void vPortClearInterruptMaskFromISR( UBaseType_t );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
|
||||
extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
|
||||
extern void vPortClearInterruptMaskFromISR( UBaseType_t );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
#define portNOP() asm volatile ( "nop" )
|
||||
#define portNOP() asm volatile ( "nop" )
|
||||
|
||||
/* Note this will overwrite all other bits in the force register, it is done this way for speed. */
|
||||
#define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP()
|
||||
#define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
portYIELD(); \
|
||||
}
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
portYIELD(); \
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -30,22 +30,22 @@
|
|||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the H8S port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the H8S port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* When the task starts interrupts should be enabled. */
|
||||
#define portINITIAL_CCR ( ( StackType_t ) 0x00 )
|
||||
#define portINITIAL_CCR ( ( StackType_t ) 0x00 )
|
||||
|
||||
/* Hardware specific constants used to generate the RTOS tick from the TPU. */
|
||||
#define portCLEAR_ON_TGRA_COMPARE_MATCH ( ( uint8_t ) 0x20 )
|
||||
#define portCLOCK_DIV_64 ( ( uint8_t ) 0x03 )
|
||||
#define portCLOCK_DIV ( ( uint32_t ) 64 )
|
||||
#define portTGRA_INTERRUPT_ENABLE ( ( uint8_t ) 0x01 )
|
||||
#define portTIMER_CHANNEL ( ( uint8_t ) 0x02 )
|
||||
#define portMSTP13 ( ( uint16_t ) 0x2000 )
|
||||
#define portCLEAR_ON_TGRA_COMPARE_MATCH ( ( uint8_t ) 0x20 )
|
||||
#define portCLOCK_DIV_64 ( ( uint8_t ) 0x03 )
|
||||
#define portCLOCK_DIV ( ( uint32_t ) 64 )
|
||||
#define portTGRA_INTERRUPT_ENABLE ( ( uint8_t ) 0x01 )
|
||||
#define portTIMER_CHANNEL ( ( uint8_t ) 0x02 )
|
||||
#define portMSTP13 ( ( uint16_t ) 0x2000 )
|
||||
|
||||
/*
|
||||
* Setup TPU channel one for the RTOS tick at the requested frequency.
|
||||
|
|
@ -55,164 +55,167 @@ static void prvSetupTimerInterrupt( void );
|
|||
/*
|
||||
* The ISR used by portYIELD(). This is installed as a trap handler.
|
||||
*/
|
||||
void vPortYield( void ) __attribute__ ( ( saveall, interrupt_handler ) );
|
||||
void vPortYield( void ) __attribute__( ( saveall, interrupt_handler ) );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
uint32_t ulValue;
|
||||
uint32_t ulValue;
|
||||
|
||||
/* This requires an even address. */
|
||||
ulValue = ( uint32_t ) pxTopOfStack;
|
||||
if( ulValue & 1UL )
|
||||
{
|
||||
pxTopOfStack = pxTopOfStack - 1;
|
||||
}
|
||||
/* This requires an even address. */
|
||||
ulValue = ( uint32_t ) pxTopOfStack;
|
||||
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xaa;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xbb;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xcc;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xdd;
|
||||
if( ulValue & 1UL )
|
||||
{
|
||||
pxTopOfStack = pxTopOfStack - 1;
|
||||
}
|
||||
|
||||
/* The initial stack mimics an interrupt stack. First there is the program
|
||||
counter (24 bits). */
|
||||
ulValue = ( uint32_t ) pxCode;
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
* This is just useful for debugging. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xaa;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xbb;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xcc;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xdd;
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
/* The initial stack mimics an interrupt stack. First there is the program
|
||||
* counter (24 bits). */
|
||||
ulValue = ( uint32_t ) pxCode;
|
||||
|
||||
/* Followed by the CCR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_CCR;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
|
||||
/* Next all the general purpose registers - with the parameters being passed
|
||||
in ER0. The parameter order must match that used by the compiler when the
|
||||
"saveall" function attribute is used. */
|
||||
/* Followed by the CCR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_CCR;
|
||||
|
||||
/* ER6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x66;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x66;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x66;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x66;
|
||||
|
||||
/* ER0 */
|
||||
ulValue = ( uint32_t ) pvParameters;
|
||||
/* Next all the general purpose registers - with the parameters being passed
|
||||
* in ER0. The parameter order must match that used by the compiler when the
|
||||
* "saveall" function attribute is used. */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
|
||||
/* ER1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
/* ER6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x66;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x66;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x66;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x66;
|
||||
|
||||
/* ER2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
/* ER0 */
|
||||
ulValue = ( uint32_t ) pvParameters;
|
||||
|
||||
/* ER3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
pxTopOfStack--;
|
||||
ulValue >>= 8UL;
|
||||
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
|
||||
|
||||
/* ER4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x44;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x44;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x44;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x44;
|
||||
/* ER1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x11;
|
||||
|
||||
/* ER5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x55;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x55;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x55;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x55;
|
||||
/* ER2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
|
||||
return pxTopOfStack;
|
||||
/* ER3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
|
||||
/* ER4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x44;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x44;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x44;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x44;
|
||||
|
||||
/* ER5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x55;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x55;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x55;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x55;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void * pxCurrentTCB;
|
||||
extern void * pxCurrentTCB;
|
||||
|
||||
/* Setup the hardware to generate the tick. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Setup the hardware to generate the tick. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task that is going to run. This
|
||||
mirrors the function epilogue code generated by the compiler when the
|
||||
"saveall" function attribute is used. */
|
||||
asm volatile (
|
||||
"MOV.L @_pxCurrentTCB, ER6 \n\t"
|
||||
"MOV.L @ER6, ER7 \n\t"
|
||||
"LDM.L @SP+, (ER4-ER5) \n\t"
|
||||
"LDM.L @SP+, (ER0-ER3) \n\t"
|
||||
"MOV.L @ER7+, ER6 \n\t"
|
||||
"RTE \n\t"
|
||||
);
|
||||
/* Restore the context of the first task that is going to run. This
|
||||
* mirrors the function epilogue code generated by the compiler when the
|
||||
* "saveall" function attribute is used. */
|
||||
asm volatile (
|
||||
"MOV.L @_pxCurrentTCB, ER6 \n\t"
|
||||
"MOV.L @ER6, ER7 \n\t"
|
||||
"LDM.L @SP+, (ER4-ER5) \n\t"
|
||||
"LDM.L @SP+, (ER0-ER3) \n\t"
|
||||
"MOV.L @ER7+, ER6 \n\t"
|
||||
"RTE \n\t"
|
||||
);
|
||||
|
||||
( void ) pxCurrentTCB;
|
||||
( void ) pxCurrentTCB;
|
||||
|
||||
/* Should not get here. */
|
||||
return pdTRUE;
|
||||
/* Should not get here. */
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the h8 port will get stopped. */
|
||||
/* It is unlikely that the h8 port will get stopped. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -223,56 +226,56 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
void vPortYield( void )
|
||||
{
|
||||
portSAVE_STACK_POINTER();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_STACK_POINTER();
|
||||
portSAVE_STACK_POINTER();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_STACK_POINTER();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt handler installed for the RTOS tick depends on whether the
|
||||
* preemptive or cooperative scheduler is being used.
|
||||
/*
|
||||
* The interrupt handler installed for the RTOS tick depends on whether the
|
||||
* preemptive or cooperative scheduler is being used.
|
||||
*/
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
#if ( configUSE_PREEMPTION == 1 )
|
||||
|
||||
/*
|
||||
* The preemptive scheduler is used so the ISR calls vTaskSwitchContext().
|
||||
* The function prologue saves the context so all we have to do is save
|
||||
* the stack pointer.
|
||||
*/
|
||||
void vTickISR( void ) __attribute__ ( ( saveall, interrupt_handler ) );
|
||||
void vTickISR( void )
|
||||
{
|
||||
portSAVE_STACK_POINTER();
|
||||
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
/*
|
||||
* The preemptive scheduler is used so the ISR calls vTaskSwitchContext().
|
||||
* The function prologue saves the context so all we have to do is save
|
||||
* the stack pointer.
|
||||
*/
|
||||
void vTickISR( void ) __attribute__( ( saveall, interrupt_handler ) );
|
||||
void vTickISR( void )
|
||||
{
|
||||
portSAVE_STACK_POINTER();
|
||||
|
||||
/* Clear the interrupt. */
|
||||
TSR1 &= ~0x01;
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
portRESTORE_STACK_POINTER();
|
||||
}
|
||||
/* Clear the interrupt. */
|
||||
TSR1 &= ~0x01;
|
||||
|
||||
#else
|
||||
portRESTORE_STACK_POINTER();
|
||||
}
|
||||
|
||||
/*
|
||||
* The cooperative scheduler is being used so all we have to do is
|
||||
* periodically increment the tick. This can just be a normal ISR and
|
||||
* the "saveall" attribute is not required.
|
||||
*/
|
||||
void vTickISR( void ) __attribute__ ( ( interrupt_handler ) );
|
||||
void vTickISR( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
#else /* if ( configUSE_PREEMPTION == 1 ) */
|
||||
|
||||
/* Clear the interrupt. */
|
||||
TSR1 &= ~0x01;
|
||||
}
|
||||
/*
|
||||
* The cooperative scheduler is being used so all we have to do is
|
||||
* periodically increment the tick. This can just be a normal ISR and
|
||||
* the "saveall" attribute is not required.
|
||||
*/
|
||||
void vTickISR( void ) __attribute__( ( interrupt_handler ) );
|
||||
void vTickISR( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
|
||||
#endif
|
||||
/* Clear the interrupt. */
|
||||
TSR1 &= ~0x01;
|
||||
}
|
||||
|
||||
#endif /* if ( configUSE_PREEMPTION == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
@ -280,23 +283,20 @@ void vPortYield( void )
|
|||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
const uint32_t ulCompareMatch = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) / portCLOCK_DIV;
|
||||
const uint32_t ulCompareMatch = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) / portCLOCK_DIV;
|
||||
|
||||
/* Turn the module on. */
|
||||
MSTPCR &= ~portMSTP13;
|
||||
/* Turn the module on. */
|
||||
MSTPCR &= ~portMSTP13;
|
||||
|
||||
/* Configure timer 1. */
|
||||
TCR1 = portCLEAR_ON_TGRA_COMPARE_MATCH | portCLOCK_DIV_64;
|
||||
/* Configure timer 1. */
|
||||
TCR1 = portCLEAR_ON_TGRA_COMPARE_MATCH | portCLOCK_DIV_64;
|
||||
|
||||
/* Configure the compare match value for a tick of configTICK_RATE_HZ. */
|
||||
TGR1A = ulCompareMatch;
|
||||
/* Configure the compare match value for a tick of configTICK_RATE_HZ. */
|
||||
TGR1A = ulCompareMatch;
|
||||
|
||||
/* Start the timer and enable the interrupt - we can do this here as
|
||||
interrupts are globally disabled when this function is called. */
|
||||
TIER1 |= portTGRA_INTERRUPT_ENABLE;
|
||||
TSTR |= portTIMER_CHANNEL;
|
||||
/* Start the timer and enable the interrupt - we can do this here as
|
||||
* interrupts are globally disabled when this function is called. */
|
||||
TIER1 |= portTGRA_INTERRUPT_ENABLE;
|
||||
TSTR |= portTIMER_CHANNEL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -43,95 +43,95 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portYIELD() asm volatile( "TRAPA #0" )
|
||||
#define portNOP() asm volatile( "NOP" )
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portYIELD() asm volatile ( "TRAPA #0" )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
#define portENABLE_INTERRUPTS() asm volatile( "ANDC #0x7F, CCR" );
|
||||
#define portDISABLE_INTERRUPTS() asm volatile( "ORC #0x80, CCR" );
|
||||
#define portENABLE_INTERRUPTS() asm volatile ( "ANDC #0x7F, CCR");
|
||||
#define portDISABLE_INTERRUPTS() asm volatile ( "ORC #0x80, CCR" );
|
||||
|
||||
/* Push the CCR then disable interrupts. */
|
||||
#define portENTER_CRITICAL() asm volatile( "STC CCR, @-ER7" ); \
|
||||
portDISABLE_INTERRUPTS();
|
||||
#define portENTER_CRITICAL() \
|
||||
asm volatile ( "STC CCR, @-ER7" ); \
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Pop the CCR to set the interrupt masking back to its previous state. */
|
||||
#define portEXIT_CRITICAL() asm volatile( "LDC @ER7+, CCR" );
|
||||
#define portEXIT_CRITICAL() asm volatile ( "LDC @ER7+, CCR" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Context switch macros. These macros are very simple as the context
|
||||
is saved simply by selecting the saveall attribute of the context switch
|
||||
interrupt service routines. These macros save and restore the stack
|
||||
pointer to the TCB. */
|
||||
* is saved simply by selecting the saveall attribute of the context switch
|
||||
* interrupt service routines. These macros save and restore the stack
|
||||
* pointer to the TCB. */
|
||||
|
||||
#define portSAVE_STACK_POINTER() \
|
||||
extern void* pxCurrentTCB; \
|
||||
\
|
||||
asm volatile( \
|
||||
"MOV.L @_pxCurrentTCB, ER5 \n\t" \
|
||||
"MOV.L ER7, @ER5 \n\t" \
|
||||
); \
|
||||
( void ) pxCurrentTCB;
|
||||
#define portSAVE_STACK_POINTER() \
|
||||
extern void * pxCurrentTCB; \
|
||||
\
|
||||
asm volatile ( \
|
||||
"MOV.L @_pxCurrentTCB, ER5 \n\t"\
|
||||
"MOV.L ER7, @ER5 \n\t"\
|
||||
); \
|
||||
( void ) pxCurrentTCB;
|
||||
|
||||
|
||||
#define portRESTORE_STACK_POINTER() \
|
||||
extern void* pxCurrentTCB; \
|
||||
\
|
||||
asm volatile( \
|
||||
"MOV.L @_pxCurrentTCB, ER5 \n\t" \
|
||||
"MOV.L @ER5, ER7 \n\t" \
|
||||
); \
|
||||
( void ) pxCurrentTCB;
|
||||
#define portRESTORE_STACK_POINTER() \
|
||||
extern void * pxCurrentTCB; \
|
||||
\
|
||||
asm volatile ( \
|
||||
"MOV.L @_pxCurrentTCB, ER5 \n\t"\
|
||||
"MOV.L @ER5, ER7 \n\t"\
|
||||
); \
|
||||
( void ) pxCurrentTCB;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Macros to allow a context switch from within an application ISR. */
|
||||
|
||||
#define portENTER_SWITCHING_ISR() portSAVE_STACK_POINTER(); {
|
||||
|
||||
#define portEXIT_SWITCHING_ISR( x ) \
|
||||
if( x ) \
|
||||
{ \
|
||||
extern void vTaskSwitchContext( void ); \
|
||||
vTaskSwitchContext(); \
|
||||
} \
|
||||
} portRESTORE_STACK_POINTER();
|
||||
#define portENTER_SWITCHING_ISR() portSAVE_STACK_POINTER(); {
|
||||
#define portEXIT_SWITCHING_ISR( x ) \
|
||||
if( x ) \
|
||||
{ \
|
||||
extern void vTaskSwitchContext( void ); \
|
||||
vTaskSwitchContext(); \
|
||||
} \
|
||||
} \
|
||||
portRESTORE_STACK_POINTER();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -34,143 +34,144 @@
|
|||
#include <sys/ports_def.h>
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the HCS12 port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the HCS12 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Configure a timer to generate the RTOS tick at the frequency specified
|
||||
* Configure a timer to generate the RTOS tick at the frequency specified
|
||||
* within FreeRTOSConfig.h.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/* NOTE: Interrupt service routines must be in non-banked memory - as does the
|
||||
scheduler startup function. */
|
||||
#define ATTR_NEAR __attribute__((near))
|
||||
* scheduler startup function. */
|
||||
#define ATTR_NEAR __attribute__( ( near ) )
|
||||
|
||||
/* Manual context switch function. This is the SWI ISR. */
|
||||
// __attribute__((interrupt))
|
||||
/* __attribute__((interrupt)) */
|
||||
void ATTR_NEAR vPortYield( void );
|
||||
|
||||
/* Tick context switch function. This is the timer ISR. */
|
||||
// __attribute__((interrupt))
|
||||
/* __attribute__((interrupt)) */
|
||||
void ATTR_NEAR vPortTickInterrupt( void );
|
||||
|
||||
/* Function in non-banked memory which actually switches to first task. */
|
||||
BaseType_t ATTR_NEAR xStartSchedulerNear( void );
|
||||
|
||||
/* Calls to portENTER_CRITICAL() can be nested. When they are nested the
|
||||
critical section should not be left (i.e. interrupts should not be re-enabled)
|
||||
until the nesting depth reaches 0. This variable simply tracks the nesting
|
||||
depth. Each task maintains it's own critical nesting depth variable so
|
||||
uxCriticalNesting is saved and restored from the task stack during a context
|
||||
switch. */
|
||||
volatile UBaseType_t uxCriticalNesting = 0x80; // un-initialized
|
||||
/* Calls to portENTER_CRITICAL() can be nested. When they are nested the
|
||||
* critical section should not be left (i.e. interrupts should not be re-enabled)
|
||||
* until the nesting depth reaches 0. This variable simply tracks the nesting
|
||||
* depth. Each task maintains it's own critical nesting depth variable so
|
||||
* uxCriticalNesting is saved and restored from the task stack during a context
|
||||
* switch. */
|
||||
volatile UBaseType_t uxCriticalNesting = 0x80; /* un-initialized */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro. In this case the stack as
|
||||
* expected by the HCS12 RTI instruction. */
|
||||
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. In this case the stack as
|
||||
expected by the HCS12 RTI instruction. */
|
||||
/* The address of the task function is placed in the stack byte at a time. */
|
||||
*pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pxCode ) ) + 1 );
|
||||
*--pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pxCode ) ) + 0 );
|
||||
|
||||
/* Next are all the registers that form part of the task context. */
|
||||
|
||||
/* The address of the task function is placed in the stack byte at a time. */
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 1 );
|
||||
*--pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 0 );
|
||||
/* Y register */
|
||||
*--pxTopOfStack = ( StackType_t ) 0xff;
|
||||
*--pxTopOfStack = ( StackType_t ) 0xee;
|
||||
|
||||
/* Next are all the registers that form part of the task context. */
|
||||
/* X register */
|
||||
*--pxTopOfStack = ( StackType_t ) 0xdd;
|
||||
*--pxTopOfStack = ( StackType_t ) 0xcc;
|
||||
|
||||
/* Y register */
|
||||
*--pxTopOfStack = ( StackType_t ) 0xff;
|
||||
*--pxTopOfStack = ( StackType_t ) 0xee;
|
||||
/* A register contains parameter high byte. */
|
||||
*--pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 0 );
|
||||
|
||||
/* X register */
|
||||
*--pxTopOfStack = ( StackType_t ) 0xdd;
|
||||
*--pxTopOfStack = ( StackType_t ) 0xcc;
|
||||
|
||||
/* A register contains parameter high byte. */
|
||||
*--pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 );
|
||||
/* B register contains parameter low byte. */
|
||||
*--pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 1 );
|
||||
|
||||
/* B register contains parameter low byte. */
|
||||
*--pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 );
|
||||
/* CCR: Note that when the task starts interrupts will be enabled since
|
||||
* "I" bit of CCR is cleared */
|
||||
*--pxTopOfStack = ( StackType_t ) 0x80; /* keeps Stop disabled (MCU default) */
|
||||
|
||||
/* CCR: Note that when the task starts interrupts will be enabled since
|
||||
"I" bit of CCR is cleared */
|
||||
*--pxTopOfStack = ( StackType_t ) 0x80; // keeps Stop disabled (MCU default)
|
||||
|
||||
/* tmp softregs used by GCC. Values right now don't matter. */
|
||||
__asm("\n\
|
||||
/* tmp softregs used by GCC. Values right now don't matter. */
|
||||
__asm( "\n\
|
||||
movw _.frame, 2,-%0 \n\
|
||||
movw _.tmp, 2,-%0 \n\
|
||||
movw _.z, 2,-%0 \n\
|
||||
movw _.xy, 2,-%0 \n\
|
||||
;movw _.d2, 2,-%0 \n\
|
||||
;movw _.d1, 2,-%0 \n\
|
||||
": "=A"(pxTopOfStack) : "0"(pxTopOfStack) );
|
||||
" : "=A" ( pxTopOfStack ) : "0" ( pxTopOfStack ) );
|
||||
|
||||
#ifdef BANKED_MODEL
|
||||
/* The page of the task. */
|
||||
*--pxTopOfStack = 0x30; // can only directly start in PPAGE 0x30
|
||||
#endif
|
||||
|
||||
/* The critical nesting depth is initialised with 0 (meaning not in
|
||||
a critical section). */
|
||||
*--pxTopOfStack = ( StackType_t ) 0x00;
|
||||
#ifdef BANKED_MODEL
|
||||
/* The page of the task. */
|
||||
*--pxTopOfStack = 0x30; /* can only directly start in PPAGE 0x30 */
|
||||
#endif
|
||||
|
||||
/* The critical nesting depth is initialised with 0 (meaning not in
|
||||
* a critical section). */
|
||||
*--pxTopOfStack = ( StackType_t ) 0x00;
|
||||
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the HCS12 port will get stopped. */
|
||||
/* It is unlikely that the HCS12 port will get stopped. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Enable hardware RTI timer */
|
||||
/* Ignores configTICK_RATE_HZ */
|
||||
RTICTL = 0x50; // 16 MHz xtal: 976.56 Hz, 1024mS
|
||||
CRGINT |= 0x80; // RTIE
|
||||
/* Enable hardware RTI timer */
|
||||
/* Ignores configTICK_RATE_HZ */
|
||||
RTICTL = 0x50; /* 16 MHz xtal: 976.56 Hz, 1024mS */
|
||||
CRGINT |= 0x80; /* RTIE */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* xPortStartScheduler() does not start the scheduler directly because
|
||||
the header file containing the xPortStartScheduler() prototype is part
|
||||
of the common kernel code, and therefore cannot use the CODE_SEG pragma.
|
||||
Instead it simply calls the locally defined xNearStartScheduler() -
|
||||
which does use the CODE_SEG pragma. */
|
||||
/* xPortStartScheduler() does not start the scheduler directly because
|
||||
* the header file containing the xPortStartScheduler() prototype is part
|
||||
* of the common kernel code, and therefore cannot use the CODE_SEG pragma.
|
||||
* Instead it simply calls the locally defined xNearStartScheduler() -
|
||||
* which does use the CODE_SEG pragma. */
|
||||
|
||||
int16_t register d;
|
||||
__asm ("jmp xStartSchedulerNear ; will never return": "=d"(d));
|
||||
return d;
|
||||
int16_t register d;
|
||||
|
||||
__asm( "jmp xStartSchedulerNear ; will never return": "=d" ( d ) );
|
||||
return d;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xStartSchedulerNear( void )
|
||||
{
|
||||
/* Configure the timer that will generate the RTOS tick. Interrupts are
|
||||
disabled when this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Configure the timer that will generate the RTOS tick. Interrupts are
|
||||
* disabled when this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the first task. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
portISR_TAIL();
|
||||
portISR_TAIL();
|
||||
|
||||
/* Should not get here! */
|
||||
return pdFALSE;
|
||||
/* Should not get here! */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -184,53 +185,53 @@ BaseType_t xStartSchedulerNear( void )
|
|||
*/
|
||||
void vPortYield( void )
|
||||
{
|
||||
portISR_HEAD();
|
||||
/* NOTE: This is the trap routine (swi) although not defined as a trap.
|
||||
It will fill the stack the same way as an ISR in order to mix preemtion
|
||||
and cooperative yield. */
|
||||
portISR_HEAD();
|
||||
|
||||
portSAVE_CONTEXT();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT();
|
||||
/* NOTE: This is the trap routine (swi) although not defined as a trap.
|
||||
* It will fill the stack the same way as an ISR in order to mix preemtion
|
||||
* and cooperative yield. */
|
||||
|
||||
portISR_TAIL();
|
||||
portSAVE_CONTEXT();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
portISR_TAIL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* RTOS tick interrupt service routine. If the cooperative scheduler is
|
||||
* being used then this simply increments the tick count. If the
|
||||
* RTOS tick interrupt service routine. If the cooperative scheduler is
|
||||
* being used then this simply increments the tick count. If the
|
||||
* preemptive scheduler is being used a context switch can occur.
|
||||
*/
|
||||
void vPortTickInterrupt( void )
|
||||
{
|
||||
portISR_HEAD();
|
||||
portISR_HEAD();
|
||||
|
||||
/* Clear tick timer flag */
|
||||
CRGFLG = 0x80;
|
||||
/* Clear tick timer flag */
|
||||
CRGFLG = 0x80;
|
||||
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
/* A context switch might happen so save the context. */
|
||||
portSAVE_CONTEXT();
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
/* A context switch might happen so save the context. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the tick ... */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* A context switch is necessary. */
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
/* Increment the tick ... */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* A context switch is necessary. */
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Restore the context of a task - which may be a different task
|
||||
to that interrupted. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
#else
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
#endif
|
||||
/* Restore the context of a task - which may be a different task
|
||||
* to that interrupted. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
#else /* if configUSE_PREEMPTION == 1 */
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
#endif /* if configUSE_PREEMPTION == 1 */
|
||||
|
||||
portISR_TAIL();
|
||||
portISR_TAIL();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -43,38 +43,38 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portYIELD() __asm( "swi" );
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portYIELD() __asm( "swi" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
#define portENABLE_INTERRUPTS() __asm( "cli" )
|
||||
#define portDISABLE_INTERRUPTS() __asm( "sei" )
|
||||
#define portENABLE_INTERRUPTS() __asm( "cli" )
|
||||
#define portDISABLE_INTERRUPTS() __asm( "sei" )
|
||||
|
||||
/*
|
||||
* Disable interrupts before incrementing the count of critical section nesting.
|
||||
|
|
@ -82,29 +82,29 @@ typedef unsigned char UBaseType_t;
|
|||
* re-enabled. Once interrupts are disabled the nesting count can be accessed
|
||||
* directly. Each task maintains its own nesting count.
|
||||
*/
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts are disabled so we can access the nesting count directly. If the
|
||||
* nesting is found to be 0 (no nesting) then we are leaving the critical
|
||||
* section and interrupts can be re-enabled.
|
||||
*/
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
|
@ -119,15 +119,16 @@ typedef unsigned char UBaseType_t;
|
|||
* register is also stored as part of the tasks context.
|
||||
*/
|
||||
|
||||
#ifdef BANKED_MODEL
|
||||
/*
|
||||
* Load the stack pointer for the task, then pull the critical nesting
|
||||
* count and PPAGE register from the stack. The remains of the
|
||||
* context are restored by the RTI instruction.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
#ifdef BANKED_MODEL
|
||||
|
||||
/*
|
||||
* Load the stack pointer for the task, then pull the critical nesting
|
||||
* count and PPAGE register from the stack. The remains of the
|
||||
* context are restored by the RTI instruction.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
.globl pxCurrentTCB ; void * \n\
|
||||
.globl uxCriticalNesting ; char \n\
|
||||
\n\
|
||||
|
|
@ -136,17 +137,17 @@ typedef unsigned char UBaseType_t;
|
|||
\n\
|
||||
movb 1,sp+,uxCriticalNesting \n\
|
||||
movb 1,sp+,0x30 ; PPAGE \n\
|
||||
" ); \
|
||||
}
|
||||
" ); \
|
||||
}
|
||||
|
||||
/*
|
||||
* By the time this macro is called the processor has already stacked the
|
||||
* registers. Simply stack the nesting count and PPAGE value, then save
|
||||
* the task stack pointer.
|
||||
*/
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
/*
|
||||
* By the time this macro is called the processor has already stacked the
|
||||
* registers. Simply stack the nesting count and PPAGE value, then save
|
||||
* the task stack pointer.
|
||||
*/
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
.globl pxCurrentTCB ; void * \n\
|
||||
.globl uxCriticalNesting ; char \n\
|
||||
\n\
|
||||
|
|
@ -155,18 +156,18 @@ typedef unsigned char UBaseType_t;
|
|||
\n\
|
||||
ldx pxCurrentTCB \n\
|
||||
sts 0,x ; Stack \n\
|
||||
" ); \
|
||||
}
|
||||
#else
|
||||
" ); \
|
||||
}
|
||||
#else /* ifdef BANKED_MODEL */
|
||||
|
||||
/*
|
||||
* These macros are as per the BANKED versions above, but without saving
|
||||
* and restoring the PPAGE register.
|
||||
*/
|
||||
/*
|
||||
* These macros are as per the BANKED versions above, but without saving
|
||||
* and restoring the PPAGE register.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
.globl pxCurrentTCB ; void * \n\
|
||||
.globl uxCriticalNesting ; char \n\
|
||||
\n\
|
||||
|
|
@ -174,12 +175,12 @@ typedef unsigned char UBaseType_t;
|
|||
lds 0,x ; Stack \n\
|
||||
\n\
|
||||
movb 1,sp+,uxCriticalNesting \n\
|
||||
" ); \
|
||||
}
|
||||
" ); \
|
||||
}
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
.globl pxCurrentTCB ; void * \n\
|
||||
.globl uxCriticalNesting ; char \n\
|
||||
\n\
|
||||
|
|
@ -187,29 +188,29 @@ typedef unsigned char UBaseType_t;
|
|||
\n\
|
||||
ldx pxCurrentTCB \n\
|
||||
sts 0,x ; Stack \n\
|
||||
" ); \
|
||||
}
|
||||
#endif
|
||||
" ); \
|
||||
}
|
||||
#endif /* ifdef BANKED_MODEL */
|
||||
|
||||
/*
|
||||
* Utility macros to save/restore correct software registers for GCC. This is
|
||||
* useful when GCC does not generate appropriate ISR head/tail code.
|
||||
*/
|
||||
#define portISR_HEAD() \
|
||||
{ \
|
||||
__asm(" \n\
|
||||
#define portISR_HEAD() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
movw _.frame, 2,-sp \n\
|
||||
movw _.tmp, 2,-sp \n\
|
||||
movw _.z, 2,-sp \n\
|
||||
movw _.xy, 2,-sp \n\
|
||||
;movw _.d2, 2,-sp \n\
|
||||
;movw _.d1, 2,-sp \n\
|
||||
"); \
|
||||
}
|
||||
" ); \
|
||||
}
|
||||
|
||||
#define portISR_TAIL() \
|
||||
{ \
|
||||
__asm(" \n\
|
||||
#define portISR_TAIL() \
|
||||
{ \
|
||||
__asm( " \n\
|
||||
movw 2,sp+, _.xy \n\
|
||||
movw 2,sp+, _.z \n\
|
||||
movw 2,sp+, _.tmp \n\
|
||||
|
|
@ -217,8 +218,8 @@ typedef unsigned char UBaseType_t;
|
|||
;movw 2,sp+, _.d1 \n\
|
||||
;movw 2,sp+, _.d2 \n\
|
||||
rti \n\
|
||||
"); \
|
||||
}
|
||||
" ); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility macro to call macros above in correct order in order to perform a
|
||||
|
|
@ -227,19 +228,18 @@ typedef unsigned char UBaseType_t;
|
|||
* variables portYIELD() should be used in it's place.
|
||||
*/
|
||||
|
||||
#define portTASK_SWITCH_FROM_ISR() \
|
||||
portSAVE_CONTEXT(); \
|
||||
vTaskSwitchContext(); \
|
||||
portRESTORE_CONTEXT();
|
||||
#define portTASK_SWITCH_FROM_ISR() \
|
||||
portSAVE_CONTEXT(); \
|
||||
vTaskSwitchContext(); \
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -24,103 +24,102 @@
|
|||
*
|
||||
*/
|
||||
|
||||
.extern ulTopOfSystemStack
|
||||
.extern ulInterruptNesting
|
||||
.extern ulTopOfSystemStack
|
||||
.extern ulInterruptNesting
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portFREERTOS_INTERRUPT_ENTRY
|
||||
.macro portFREERTOS_INTERRUPT_ENTRY
|
||||
|
||||
/* Save general purpose registers. */
|
||||
pusha
|
||||
/* Save general purpose registers. */
|
||||
pusha
|
||||
|
||||
/* If ulInterruptNesting is zero the rest of the task context will need
|
||||
saving and a stack switch might be required. */
|
||||
movl ulInterruptNesting, %eax
|
||||
test %eax, %eax
|
||||
jne 2f
|
||||
/* If ulInterruptNesting is zero the rest of the task context will need
|
||||
* saving and a stack switch might be required. */
|
||||
movl ulInterruptNesting, % eax
|
||||
test % eax, % eax
|
||||
jne 2f
|
||||
|
||||
/* Interrupts are not nested, so save the rest of the task context. */
|
||||
.if configSUPPORT_FPU == 1
|
||||
/* Interrupts are not nested, so save the rest of the task context. */
|
||||
.if configSUPPORT_FPU == 1
|
||||
|
||||
/* If the task has a buffer allocated to save the FPU context then
|
||||
save the FPU context now. */
|
||||
movl pucPortTaskFPUContextBuffer, %eax
|
||||
test %eax, %eax
|
||||
je 1f
|
||||
fnsave ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
|
||||
fwait
|
||||
/* If the task has a buffer allocated to save the FPU context then
|
||||
* save the FPU context now. */
|
||||
movl pucPortTaskFPUContextBuffer, % eax
|
||||
test % eax, % eax
|
||||
je 1f
|
||||
fnsave( % eax ) /* Save FLOP context into ucTempFPUBuffer array. */
|
||||
fwait
|
||||
|
||||
1:
|
||||
/* Save the address of the FPU context, if any. */
|
||||
push pucPortTaskFPUContextBuffer
|
||||
1 :
|
||||
/* Save the address of the FPU context, if any. */
|
||||
push pucPortTaskFPUContextBuffer
|
||||
|
||||
.endif /* configSUPPORT_FPU */
|
||||
.endif /* configSUPPORT_FPU */
|
||||
|
||||
/* Find the TCB. */
|
||||
movl pxCurrentTCB, %eax
|
||||
/* Find the TCB. */
|
||||
movl pxCurrentTCB, % eax
|
||||
|
||||
/* Stack location is first item in the TCB. */
|
||||
movl %esp, (%eax)
|
||||
/* Stack location is first item in the TCB. */
|
||||
movl % esp, ( % eax )
|
||||
|
||||
/* Switch stacks. */
|
||||
movl ulTopOfSystemStack, %esp
|
||||
movl %esp, %ebp
|
||||
/* Switch stacks. */
|
||||
movl ulTopOfSystemStack, % esp
|
||||
movl % esp, % ebp
|
||||
|
||||
2:
|
||||
/* Increment nesting count. */
|
||||
add $1, ulInterruptNesting
|
||||
2 :
|
||||
/* Increment nesting count. */
|
||||
add $1, ulInterruptNesting
|
||||
|
||||
.endm
|
||||
.endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portINTERRUPT_EPILOGUE
|
||||
.macro portINTERRUPT_EPILOGUE
|
||||
|
||||
cli
|
||||
sub $1, ulInterruptNesting
|
||||
cli
|
||||
sub $1, ulInterruptNesting
|
||||
|
||||
/* If the nesting has unwound to zero. */
|
||||
movl ulInterruptNesting, %eax
|
||||
test %eax, %eax
|
||||
jne 2f
|
||||
/* If the nesting has unwound to zero. */
|
||||
movl ulInterruptNesting, % eax
|
||||
test % eax, % eax
|
||||
jne 2f
|
||||
|
||||
/* If a yield was requested then select a new TCB now. */
|
||||
movl ulPortYieldPending, %eax
|
||||
test %eax, %eax
|
||||
je 1f
|
||||
movl $0, ulPortYieldPending
|
||||
call vTaskSwitchContext
|
||||
/* If a yield was requested then select a new TCB now. */
|
||||
movl ulPortYieldPending, % eax
|
||||
test % eax, % eax
|
||||
je 1f
|
||||
movl $0, ulPortYieldPending
|
||||
call vTaskSwitchContext
|
||||
|
||||
1:
|
||||
/* Stack location is first item in the TCB. */
|
||||
movl pxCurrentTCB, %eax
|
||||
movl (%eax), %esp
|
||||
1 :
|
||||
/* Stack location is first item in the TCB. */
|
||||
movl pxCurrentTCB, % eax movl( % eax ), % esp
|
||||
|
||||
.if configSUPPORT_FPU == 1
|
||||
.if configSUPPORT_FPU == 1
|
||||
|
||||
/* Restore address of task's FPU context buffer. */
|
||||
pop pucPortTaskFPUContextBuffer
|
||||
/* Restore address of task's FPU context buffer. */
|
||||
pop pucPortTaskFPUContextBuffer
|
||||
|
||||
/* If the task has a buffer allocated in which its FPU context is saved,
|
||||
then restore it now. */
|
||||
movl pucPortTaskFPUContextBuffer, %eax
|
||||
test %eax, %eax
|
||||
je 1f
|
||||
frstor ( %eax )
|
||||
1:
|
||||
.endif
|
||||
/* If the task has a buffer allocated in which its FPU context is saved,
|
||||
* then restore it now. */
|
||||
movl pucPortTaskFPUContextBuffer, % eax
|
||||
test % eax, % eax
|
||||
je 1f
|
||||
frstor( % eax )
|
||||
1 :
|
||||
.endif
|
||||
|
||||
2:
|
||||
popa
|
||||
2 :
|
||||
popa
|
||||
|
||||
.endm
|
||||
.endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portFREERTOS_INTERRUPT_EXIT
|
||||
.macro portFREERTOS_INTERRUPT_EXIT
|
||||
|
||||
portINTERRUPT_EPILOGUE
|
||||
/* EOI. */
|
||||
movl $0x00, (0xFEE000B0)
|
||||
iret
|
||||
portINTERRUPT_EPILOGUE
|
||||
/* EOI. */
|
||||
movl $0x00, ( 0xFEE000B0 )
|
||||
iret
|
||||
|
||||
.endm
|
||||
.endm
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,249 +42,255 @@
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffUL )
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffUL )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 32
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 32
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* The interrupt priority (for vectors 16 to 255) is determined using vector/16.
|
||||
The quotient is rounded to the nearest integer with 1 being the lowest priority
|
||||
and 15 is the highest. Therefore the following two interrupts are at the lowest
|
||||
priority. *NOTE 1* If the yield vector is changed then it must also be changed
|
||||
in the portYIELD_INTERRUPT definition immediately below. */
|
||||
#define portAPIC_TIMER_INT_VECTOR ( 0x21 )
|
||||
#define portAPIC_YIELD_INT_VECTOR ( 0x20 )
|
||||
* The quotient is rounded to the nearest integer with 1 being the lowest priority
|
||||
* and 15 is the highest. Therefore the following two interrupts are at the lowest
|
||||
* priority. *NOTE 1* If the yield vector is changed then it must also be changed
|
||||
* in the portYIELD_INTERRUPT definition immediately below. */
|
||||
#define portAPIC_TIMER_INT_VECTOR ( 0x21 )
|
||||
#define portAPIC_YIELD_INT_VECTOR ( 0x20 )
|
||||
|
||||
/* Build yield interrupt instruction. */
|
||||
#define portYIELD_INTERRUPT "int $0x20"
|
||||
#define portYIELD_INTERRUPT "int $0x20"
|
||||
|
||||
/* APIC register addresses. */
|
||||
#define portAPIC_EOI ( *( ( volatile uint32_t * ) 0xFEE000B0UL ) )
|
||||
#define portAPIC_EOI ( *( ( volatile uint32_t * ) 0xFEE000B0UL ) )
|
||||
|
||||
/* APIC bit definitions. */
|
||||
#define portAPIC_ENABLE_BIT ( 1UL << 8UL )
|
||||
#define portAPIC_TIMER_PERIODIC ( 1UL << 17UL )
|
||||
#define portAPIC_DISABLE ( 1UL << 16UL )
|
||||
#define portAPIC_NMI ( 4 << 8)
|
||||
#define portAPIC_DIV_16 ( 0x03 )
|
||||
#define portAPIC_ENABLE_BIT ( 1UL << 8UL )
|
||||
#define portAPIC_TIMER_PERIODIC ( 1UL << 17UL )
|
||||
#define portAPIC_DISABLE ( 1UL << 16UL )
|
||||
#define portAPIC_NMI ( 4 << 8 )
|
||||
#define portAPIC_DIV_16 ( 0x03 )
|
||||
|
||||
/* Define local API register addresses. */
|
||||
#define portAPIC_ID_REGISTER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x20UL ) ) )
|
||||
#define portAPIC_SPURIOUS_INT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xF0UL ) ) )
|
||||
#define portAPIC_LVT_TIMER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x320UL ) ) )
|
||||
#define portAPIC_TIMER_INITIAL_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x380UL ) ) )
|
||||
#define portAPIC_TIMER_CURRENT_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x390UL ) ) )
|
||||
#define portAPIC_TASK_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x80UL ) ) )
|
||||
#define portAPIC_LVT_ERROR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x370UL ) ) )
|
||||
#define portAPIC_ERROR_STATUS ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x280UL ) ) )
|
||||
#define portAPIC_LDR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xD0UL ) ) )
|
||||
#define portAPIC_TMRDIV ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x3E0UL ) ) )
|
||||
#define portAPIC_LVT_PERF ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x340UL ) ) )
|
||||
#define portAPIC_LVT_LINT0 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x350UL ) ) )
|
||||
#define portAPIC_LVT_LINT1 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x360UL ) ) )
|
||||
#define portAPIC_ID_REGISTER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x20UL ) ) )
|
||||
#define portAPIC_SPURIOUS_INT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xF0UL ) ) )
|
||||
#define portAPIC_LVT_TIMER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x320UL ) ) )
|
||||
#define portAPIC_TIMER_INITIAL_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x380UL ) ) )
|
||||
#define portAPIC_TIMER_CURRENT_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x390UL ) ) )
|
||||
#define portAPIC_TASK_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x80UL ) ) )
|
||||
#define portAPIC_LVT_ERROR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x370UL ) ) )
|
||||
#define portAPIC_ERROR_STATUS ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x280UL ) ) )
|
||||
#define portAPIC_LDR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xD0UL ) ) )
|
||||
#define portAPIC_TMRDIV ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x3E0UL ) ) )
|
||||
#define portAPIC_LVT_PERF ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x340UL ) ) )
|
||||
#define portAPIC_LVT_LINT0 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x350UL ) ) )
|
||||
#define portAPIC_LVT_LINT1 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x360UL ) ) )
|
||||
|
||||
/* Don't yield if inside a critical section - instead hold the yield pending
|
||||
so it is performed when the critical section is exited. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile uint32_t ulPortYieldPending; \
|
||||
if( ulCriticalNesting != 0 ) \
|
||||
{ \
|
||||
ulPortYieldPending = pdTRUE; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
__asm volatile( portYIELD_INTERRUPT ); \
|
||||
} \
|
||||
}
|
||||
* so it is performed when the critical section is exited. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile uint32_t ulPortYieldPending; \
|
||||
if( ulCriticalNesting != 0 ) \
|
||||
{ \
|
||||
ulPortYieldPending = pdTRUE; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
__asm volatile ( portYIELD_INTERRUPT ); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch - pend a yield if
|
||||
xSwithcRequired is not false. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern volatile uint32_t ulPortYieldPending; \
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldPending = 1; \
|
||||
} \
|
||||
}
|
||||
* xSwithcRequired is not false. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern volatile uint32_t ulPortYieldPending; \
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldPending = 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Same as portEND_SWITCHING_ISR() - take your pick which name to use. */
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Critical sections for use in interrupts. */
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile( "cli" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile( "sti" )
|
||||
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( "cli" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( "sti" )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
* not required for this port but included in case common demo code that uses these
|
||||
* macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \
|
||||
__asm volatile( "bsr %1, %0\n\t" \
|
||||
:"=r"(uxTopPriority) : "rm"(uxReadyPriorities) : "cc" )
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \
|
||||
__asm volatile ( "bsr %1, %0\n\t" \
|
||||
: "=r" ( uxTopPriority ) : "rm" ( uxReadyPriorities ) : "cc" )
|
||||
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portNOP() __asm volatile ( "NOP" )
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Misc
|
||||
*----------------------------------------------------------*/
|
||||
* Misc
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#define portNUM_VECTORS 256
|
||||
#define portMAX_PRIORITY 15
|
||||
typedef void ( *ISR_Handler_t ) ( void );
|
||||
#define portNUM_VECTORS 256
|
||||
#define portMAX_PRIORITY 15
|
||||
typedef void ( * ISR_Handler_t ) ( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
#ifndef configSUPPORT_FPU
|
||||
#define configSUPPORT_FPU 0
|
||||
#endif
|
||||
* before any floating point instructions are executed. */
|
||||
#ifndef configSUPPORT_FPU
|
||||
#define configSUPPORT_FPU 0
|
||||
#endif
|
||||
|
||||
#if configSUPPORT_FPU == 1
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
#endif
|
||||
#if configSUPPORT_FPU == 1
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
#endif
|
||||
|
||||
/* See the comments under the configUSE_COMMON_INTERRUPT_ENTRY_POINT definition
|
||||
below. */
|
||||
BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber );
|
||||
BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler, uint32_t ulVectorNumber );
|
||||
* below. */
|
||||
BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler,
|
||||
uint32_t ulVectorNumber );
|
||||
BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler,
|
||||
uint32_t ulVectorNumber );
|
||||
|
||||
#ifndef configAPIC_BASE
|
||||
/* configAPIC_BASE_ADDRESS sets the base address of the local APIC. It can
|
||||
be overridden in FreeRTOSConfig.h should it not be constant. */
|
||||
#define configAPIC_BASE 0xFEE00000UL
|
||||
#endif
|
||||
#ifndef configAPIC_BASE
|
||||
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
/* The FreeRTOS scheduling algorithm selects the task that will enter the
|
||||
Running state. configUSE_PORT_OPTIMISED_TASK_SELECTION is used to set how
|
||||
that is done.
|
||||
/* configAPIC_BASE_ADDRESS sets the base address of the local APIC. It can
|
||||
* be overridden in FreeRTOSConfig.h should it not be constant. */
|
||||
#define configAPIC_BASE 0xFEE00000UL
|
||||
#endif
|
||||
|
||||
If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 0 then the task to
|
||||
enter the Running state is selected using a portable algorithm written in
|
||||
C. This is the slowest method, but the algorithm does not restrict the
|
||||
maximum number of unique RTOS task priorities that are available.
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
|
||||
If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 1 then the task to
|
||||
enter the Running state is selected using a single assembly instruction.
|
||||
This is the fastest method, but restricts the maximum number of unique RTOS
|
||||
task priorities to 32 (the same task priority can be assigned to any number
|
||||
of RTOS tasks). */
|
||||
#warning configUSE_PORT_OPTIMISED_TASK_SELECTION was not defined in FreeRTOSConfig.h and has been defaulted to 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
/* The FreeRTOS scheduling algorithm selects the task that will enter the
|
||||
* Running state. configUSE_PORT_OPTIMISED_TASK_SELECTION is used to set how
|
||||
* that is done.
|
||||
*
|
||||
* If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 0 then the task to
|
||||
* enter the Running state is selected using a portable algorithm written in
|
||||
* C. This is the slowest method, but the algorithm does not restrict the
|
||||
* maximum number of unique RTOS task priorities that are available.
|
||||
*
|
||||
* If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 1 then the task to
|
||||
* enter the Running state is selected using a single assembly instruction.
|
||||
* This is the fastest method, but restricts the maximum number of unique RTOS
|
||||
* task priorities to 32 (the same task priority can be assigned to any number
|
||||
* of RTOS tasks). */
|
||||
#warning configUSE_PORT_OPTIMISED_TASK_SELECTION was not defined in FreeRTOSConfig.h and has been defaulted to 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_COMMON_INTERRUPT_ENTRY_POINT
|
||||
/* There are two ways of implementing interrupt handlers:
|
||||
#ifndef configUSE_COMMON_INTERRUPT_ENTRY_POINT
|
||||
|
||||
1) As standard C functions -
|
||||
/* There are two ways of implementing interrupt handlers:
|
||||
*
|
||||
* 1) As standard C functions -
|
||||
*
|
||||
* This method can only be used if configUSE_COMMON_INTERRUPT_ENTRY_POINT
|
||||
* is set to 1. The C function is installed using
|
||||
* xPortRegisterCInterruptHandler().
|
||||
*
|
||||
* This is the simplest of the two methods but incurs a slightly longer
|
||||
* interrupt entry time.
|
||||
*
|
||||
* 2) By using an assembly stub that wraps the handler in the FreeRTOS
|
||||
* portFREERTOS_INTERRUPT_ENTRY and portFREERTOS_INTERRUPT_EXIT macros.
|
||||
*
|
||||
* This method can always be used. It is slightly more complex than
|
||||
* method 1 but benefits from a faster interrupt entry time. */
|
||||
#warning configUSE_COMMON_INTERRUPT_ENTRY_POINT was not defined in FreeRTOSConfig.h and has been defaulted to 1.
|
||||
#define configUSE_COMMON_INTERRUPT_ENTRY_POINT 1
|
||||
#endif
|
||||
|
||||
This method can only be used if configUSE_COMMON_INTERRUPT_ENTRY_POINT
|
||||
is set to 1. The C function is installed using
|
||||
xPortRegisterCInterruptHandler().
|
||||
#ifndef configISR_STACK_SIZE
|
||||
|
||||
This is the simplest of the two methods but incurs a slightly longer
|
||||
interrupt entry time.
|
||||
/* Interrupt entry code will switch the stack in use to a dedicated system
|
||||
* stack.
|
||||
*
|
||||
* configISR_STACK_SIZE defines the number of 32-bit values that can be stored
|
||||
* on the system stack, and must be large enough to hold a potentially nested
|
||||
* interrupt stack frame. */
|
||||
|
||||
2) By using an assembly stub that wraps the handler in the FreeRTOS
|
||||
portFREERTOS_INTERRUPT_ENTRY and portFREERTOS_INTERRUPT_EXIT macros.
|
||||
#error configISR_STACK_SIZE was not defined in FreeRTOSConfig.h.
|
||||
#endif
|
||||
|
||||
This method can always be used. It is slightly more complex than
|
||||
method 1 but benefits from a faster interrupt entry time. */
|
||||
#warning configUSE_COMMON_INTERRUPT_ENTRY_POINT was not defined in FreeRTOSConfig.h and has been defaulted to 1.
|
||||
#define configUSE_COMMON_INTERRUPT_ENTRY_POINT 1
|
||||
#endif
|
||||
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
|
||||
|
||||
#ifndef configISR_STACK_SIZE
|
||||
/* Interrupt entry code will switch the stack in use to a dedicated system
|
||||
stack.
|
||||
/* Interrupt safe FreeRTOS functions (those that end in "FromISR" must not
|
||||
* be called from an interrupt that has a priority above that set by
|
||||
* configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#warning configMAX_API_CALL_INTERRUPT_PRIORITY was not defined in FreeRTOSConfig.h and has been defaulted to 10
|
||||
#define configMAX_API_CALL_INTERRUPT_PRIORITY 10
|
||||
#endif
|
||||
|
||||
configISR_STACK_SIZE defines the number of 32-bit values that can be stored
|
||||
on the system stack, and must be large enough to hold a potentially nested
|
||||
interrupt stack frame. */
|
||||
|
||||
#error configISR_STACK_SIZE was not defined in FreeRTOSConfig.h.
|
||||
#endif
|
||||
|
||||
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
|
||||
/* Interrupt safe FreeRTOS functions (those that end in "FromISR" must not
|
||||
be called from an interrupt that has a priority above that set by
|
||||
configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#warning configMAX_API_CALL_INTERRUPT_PRIORITY was not defined in FreeRTOSConfig.h and has been defaulted to 10
|
||||
#define configMAX_API_CALL_INTERRUPT_PRIORITY 10
|
||||
#endif
|
||||
|
||||
#ifndef configSUPPORT_FPU
|
||||
#warning configSUPPORT_FPU was not defined in FreeRTOSConfig.h and has been defaulted to 0
|
||||
#define configSUPPORT_FPU 0
|
||||
#endif
|
||||
#ifndef configSUPPORT_FPU
|
||||
#warning configSUPPORT_FPU was not defined in FreeRTOSConfig.h and has been defaulted to 0
|
||||
#define configSUPPORT_FPU 0
|
||||
#endif
|
||||
|
||||
/* The value written to the task priority register to raise the interrupt mask
|
||||
to the maximum from which FreeRTOS API calls can be made. */
|
||||
#define portAPIC_PRIORITY_SHIFT ( 4UL )
|
||||
#define portAPIC_MAX_SUB_PRIORITY ( 0x0fUL )
|
||||
#define portMAX_API_CALL_PRIORITY ( ( configMAX_API_CALL_INTERRUPT_PRIORITY << portAPIC_PRIORITY_SHIFT ) | portAPIC_MAX_SUB_PRIORITY )
|
||||
* to the maximum from which FreeRTOS API calls can be made. */
|
||||
#define portAPIC_PRIORITY_SHIFT ( 4UL )
|
||||
#define portAPIC_MAX_SUB_PRIORITY ( 0x0fUL )
|
||||
#define portMAX_API_CALL_PRIORITY ( ( configMAX_API_CALL_INTERRUPT_PRIORITY << portAPIC_PRIORITY_SHIFT ) | portAPIC_MAX_SUB_PRIORITY )
|
||||
|
||||
/* Asserts if interrupt safe FreeRTOS functions are called from a priority
|
||||
above the max system call interrupt priority. */
|
||||
#define portAPIC_PROCESSOR_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xA0UL ) ) )
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( portAPIC_PROCESSOR_PRIORITY ) <= ( portMAX_API_CALL_PRIORITY ) )
|
||||
* above the max system call interrupt priority. */
|
||||
#define portAPIC_PROCESSOR_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xA0UL ) ) )
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( portAPIC_PROCESSOR_PRIORITY ) <= ( portMAX_API_CALL_PRIORITY ) )
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,55 +1,55 @@
|
|||
/*
|
||||
FreeRTOS V4.1.1 - Copyright (C) 2003-2006 Richard Barry.
|
||||
MCF5235 Port - Copyright (C) 2006 Christian Walter.
|
||||
|
||||
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** as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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
|
||||
along with FreeRTOS; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes FreeRTOS, without being obliged to provide
|
||||
the source code for any proprietary components. See the licensing section
|
||||
of http://www.FreeRTOS.org for full details of how and when the exception
|
||||
can be applied.
|
||||
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* This is a concise, step by step, 'hands on' guide that describes both *
|
||||
* general multitasking concepts and FreeRTOS specifics. It presents and *
|
||||
* explains numerous examples that are written using the FreeRTOS API. *
|
||||
* Full source code for all the examples is provided in an accompanying *
|
||||
* .zip file. *
|
||||
* *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
|
||||
Please ensure to read the configuration and relevant port sections of the
|
||||
online documentation.
|
||||
|
||||
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.
|
||||
*/
|
||||
* FreeRTOS V4.1.1 - Copyright (C) 2003-2006 Richard Barry.
|
||||
* MCF5235 Port - Copyright (C) 2006 Christian Walter.
|
||||
*
|
||||
* 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** as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* along with FreeRTOS; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* A special exception to the GPL can be applied should you wish to distribute
|
||||
* a combined work that includes FreeRTOS, without being obliged to provide
|
||||
* the source code for any proprietary components. See the licensing section
|
||||
* of http://www.FreeRTOS.org for full details of how and when the exception
|
||||
* can be applied.
|
||||
*
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* This is a concise, step by step, 'hands on' guide that describes both *
|
||||
* general multitasking concepts and FreeRTOS specifics. It presents and *
|
||||
* explains numerous examples that are written using the FreeRTOS API. *
|
||||
* Full source code for all the examples is provided in an accompanying *
|
||||
* .zip file. *
|
||||
* *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
*
|
||||
* Please ensure to read the configuration and relevant port sections of the
|
||||
* online documentation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
@ -58,52 +58,52 @@
|
|||
#include "task.h"
|
||||
|
||||
/* ------------------------ Types ----------------------------------------- */
|
||||
typedef volatile uint32_t vuint32;
|
||||
typedef volatile uint16_t vuint16;
|
||||
typedef volatile uint8_t vuint8;
|
||||
typedef volatile uint32_t vuint32;
|
||||
typedef volatile uint16_t vuint16;
|
||||
typedef volatile uint8_t vuint8;
|
||||
|
||||
/* ------------------------ Defines --------------------------------------- */
|
||||
#define portVECTOR_TABLE __RAMVEC
|
||||
#define portVECTOR_SYSCALL ( 32 + portTRAP_YIELD )
|
||||
#define portVECTOR_TIMER ( 64 + 36 )
|
||||
#define portVECTOR_TABLE __RAMVEC
|
||||
#define portVECTOR_SYSCALL ( 32 + portTRAP_YIELD )
|
||||
#define portVECTOR_TIMER ( 64 + 36 )
|
||||
|
||||
#define MCF_PIT_PRESCALER 512UL
|
||||
#define MCF_PIT_TIMER_TICKS ( FSYS_2 / MCF_PIT_PRESCALER )
|
||||
#define MCF_PIT_MODULUS_REGISTER(freq) ( MCF_PIT_TIMER_TICKS / ( freq ) - 1UL)
|
||||
#define MCF_PIT_PRESCALER 512UL
|
||||
#define MCF_PIT_TIMER_TICKS ( FSYS_2 / MCF_PIT_PRESCALER )
|
||||
#define MCF_PIT_MODULUS_REGISTER( freq ) ( MCF_PIT_TIMER_TICKS / ( freq ) - 1UL )
|
||||
|
||||
#define MCF_PIT_PMR0 ( *( vuint16 * )( void * )( &__IPSBAR[ 0x150002 ] ) )
|
||||
#define MCF_PIT_PCSR0 ( *( vuint16 * )( void * )( &__IPSBAR[ 0x150000 ] ) )
|
||||
#define MCF_PIT_PCSR_PRE(x) ( ( ( x ) & 0x000F ) << 8 )
|
||||
#define MCF_PIT_PCSR_EN ( 0x0001 )
|
||||
#define MCF_PIT_PCSR_RLD ( 0x0002 )
|
||||
#define MCF_PIT_PCSR_PIF ( 0x0004 )
|
||||
#define MCF_PIT_PCSR_PIE ( 0x0008 )
|
||||
#define MCF_PIT_PCSR_OVW ( 0x0010 )
|
||||
#define MCF_INTC0_ICR36 ( *( vuint8 * )( void * )( &__IPSBAR[ 0x000C64 ] ) )
|
||||
#define MCF_INTC0_IMRH ( *( vuint32 * )( void * )( &__IPSBAR[ 0x000C08 ] ) )
|
||||
#define MCF_INTC0_IMRH_INT_MASK36 ( 0x00000010 )
|
||||
#define MCF_INTC0_IMRH_MASKALL ( 0x00000001 )
|
||||
#define MCF_INTC0_ICRn_IP(x) ( ( ( x ) & 0x07 ) << 0 )
|
||||
#define MCF_INTC0_ICRn_IL(x) ( ( ( x ) & 0x07 ) << 3 )
|
||||
#define MCF_PIT_PMR0 ( *( vuint16 * ) ( void * ) ( &__IPSBAR[ 0x150002 ] ) )
|
||||
#define MCF_PIT_PCSR0 ( *( vuint16 * ) ( void * ) ( &__IPSBAR[ 0x150000 ] ) )
|
||||
#define MCF_PIT_PCSR_PRE( x ) ( ( ( x ) & 0x000F ) << 8 )
|
||||
#define MCF_PIT_PCSR_EN ( 0x0001 )
|
||||
#define MCF_PIT_PCSR_RLD ( 0x0002 )
|
||||
#define MCF_PIT_PCSR_PIF ( 0x0004 )
|
||||
#define MCF_PIT_PCSR_PIE ( 0x0008 )
|
||||
#define MCF_PIT_PCSR_OVW ( 0x0010 )
|
||||
#define MCF_INTC0_ICR36 ( *( vuint8 * ) ( void * ) ( &__IPSBAR[ 0x000C64 ] ) )
|
||||
#define MCF_INTC0_IMRH ( *( vuint32 * ) ( void * ) ( &__IPSBAR[ 0x000C08 ] ) )
|
||||
#define MCF_INTC0_IMRH_INT_MASK36 ( 0x00000010 )
|
||||
#define MCF_INTC0_IMRH_MASKALL ( 0x00000001 )
|
||||
#define MCF_INTC0_ICRn_IP( x ) ( ( ( x ) & 0x07 ) << 0 )
|
||||
#define MCF_INTC0_ICRn_IL( x ) ( ( ( x ) & 0x07 ) << 3 )
|
||||
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint32_t ) 10 )
|
||||
|
||||
/* ------------------------ Static variables ------------------------------ */
|
||||
volatile uint32_t ulCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
volatile uint32_t ulCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
|
||||
/* ------------------------ Static functions ------------------------------ */
|
||||
#if configUSE_PREEMPTION == 0
|
||||
static void prvPortPreemptiveTick ( void ) __attribute__ ((interrupt_handler));
|
||||
static void prvPortPreemptiveTick( void ) __attribute__( ( interrupt_handler ) );
|
||||
#else
|
||||
static void prvPortPreemptiveTick ( void );
|
||||
static void prvPortPreemptiveTick( void );
|
||||
#endif
|
||||
|
||||
/* ------------------------ Start implementation -------------------------- */
|
||||
|
||||
StackType_t *
|
||||
pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode,
|
||||
void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Place the parameter on the stack in the expected location. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
|
|
@ -129,35 +129,35 @@ pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode,
|
|||
*pxTopOfStack = 0;
|
||||
*pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xA6; /* A6 / FP */
|
||||
*pxTopOfStack = ( StackType_t ) 0xA6; /* A6 / FP */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xA5; /* A5 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xA5; /* A5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xA4; /* A4 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xA4; /* A4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xA3; /* A3 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xA3; /* A3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xA2; /* A2 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xA2; /* A2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xA1; /* A1 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xA1; /* A1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xA0; /* A0 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xA0; /* A0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xD7; /* D7 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xD7; /* D7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xD6; /* D6 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xD6; /* D6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xD5; /* D5 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xD5; /* D5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xD4; /* D4 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xD4; /* D4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xD3; /* D3 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xD3; /* D3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xD2; /* D2 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xD2; /* D2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xD1; /* D1 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xD1; /* D1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xD0; /* D0 */
|
||||
*pxTopOfStack = ( StackType_t ) 0xD0; /* D0 */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
|
|
@ -165,65 +165,64 @@ pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode,
|
|||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*/
|
||||
static void
|
||||
prvPortYield( void )
|
||||
static void prvPortYield( void )
|
||||
{
|
||||
asm volatile ( "move.w #0x2700, %sr\n\t" );
|
||||
#if _GCC_USES_FP == 1
|
||||
asm volatile ( "unlk %fp\n\t" );
|
||||
#endif
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT( );
|
||||
#if _GCC_USES_FP == 1
|
||||
asm volatile ( "unlk %fp\n\t" );
|
||||
#endif
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext( );
|
||||
vTaskSwitchContext();
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT( );
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
static void
|
||||
prvPortPreemptiveTick ( void )
|
||||
{
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
* simply increment the system tick.
|
||||
*/
|
||||
static void prvPortPreemptiveTick( void )
|
||||
{
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
* simply increment the system tick.
|
||||
*/
|
||||
|
||||
xTaskIncrementTick();
|
||||
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIF;
|
||||
}
|
||||
xTaskIncrementTick();
|
||||
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIF;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* if configUSE_PREEMPTION == 0 */
|
||||
|
||||
static void
|
||||
prvPortPreemptiveTick( void )
|
||||
{
|
||||
asm volatile ( "move.w #0x2700, %sr\n\t" );
|
||||
#if _GCC_USES_FP == 1
|
||||
asm volatile ( "unlk %fp\n\t" );
|
||||
#endif
|
||||
portSAVE_CONTEXT( );
|
||||
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIF;
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext( );
|
||||
}
|
||||
portRESTORE_CONTEXT( );
|
||||
}
|
||||
#endif
|
||||
static void prvPortPreemptiveTick( void )
|
||||
{
|
||||
asm volatile ( "move.w #0x2700, %sr\n\t" );
|
||||
#if _GCC_USES_FP == 1
|
||||
asm volatile ( "unlk %fp\n\t" );
|
||||
#endif
|
||||
portSAVE_CONTEXT();
|
||||
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIF;
|
||||
|
||||
void
|
||||
vPortEnterCritical()
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
#endif /* if configUSE_PREEMPTION == 0 */
|
||||
|
||||
void vPortEnterCritical()
|
||||
{
|
||||
/* FIXME: We should store the old IPL here - How are we supposed to do
|
||||
* this.
|
||||
*/
|
||||
( void )portSET_IPL( portIPL_MAX );
|
||||
( void ) portSET_IPL( portIPL_MAX );
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
* directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
|
|
@ -231,8 +230,7 @@ vPortEnterCritical()
|
|||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void
|
||||
vPortExitCritical()
|
||||
void vPortExitCritical()
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
|
|
@ -240,46 +238,44 @@ vPortExitCritical()
|
|||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
* re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
( void )portSET_IPL( 0 );
|
||||
( void ) portSET_IPL( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseType_t
|
||||
xPortStartScheduler( void )
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void ( *portVECTOR_TABLE[ ] ) ( );
|
||||
extern void ( * portVECTOR_TABLE[] ) ();
|
||||
|
||||
/* Add entry in vector table for yield system call. */
|
||||
portVECTOR_TABLE[ portVECTOR_SYSCALL ] = prvPortYield;
|
||||
/* Add entry in vector table for periodic timer. */
|
||||
portVECTOR_TABLE[ portVECTOR_TIMER ] = prvPortPreemptiveTick;
|
||||
portVECTOR_TABLE[ portVECTOR_TIMER ] = prvPortPreemptiveTick;
|
||||
|
||||
/* Configure the timer for the system clock. */
|
||||
if ( configTICK_RATE_HZ > 0)
|
||||
if( configTICK_RATE_HZ > 0 )
|
||||
{
|
||||
/* Configure prescaler */
|
||||
MCF_PIT_PCSR0 = MCF_PIT_PCSR_PRE( 0x9 ) | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_OVW;
|
||||
MCF_PIT_PCSR0 = MCF_PIT_PCSR_PRE( 0x9 ) | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_OVW;
|
||||
/* Initialize the periodic timer interrupt. */
|
||||
MCF_PIT_PMR0 = MCF_PIT_MODULUS_REGISTER( configTICK_RATE_HZ );
|
||||
MCF_PIT_PMR0 = MCF_PIT_MODULUS_REGISTER( configTICK_RATE_HZ );
|
||||
/* Configure interrupt priority and level and unmask interrupt. */
|
||||
MCF_INTC0_ICR36 = MCF_INTC0_ICRn_IL( 0x1 ) | MCF_INTC0_ICRn_IP( 0x1 );
|
||||
MCF_INTC0_IMRH &= ~( MCF_INTC0_IMRH_INT_MASK36 | MCF_INTC0_IMRH_MASKALL );
|
||||
/* Enable interrupts */
|
||||
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_EN | MCF_PIT_PCSR_PIF;
|
||||
MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_EN | MCF_PIT_PCSR_PIF;
|
||||
}
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
portRESTORE_CONTEXT( );
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Should not get here. */
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
void
|
||||
vPortEndScheduler( void )
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,91 +1,91 @@
|
|||
/*
|
||||
FreeRTOS V4.1.1 - Copyright (C) 2003-2006 Richard Barry.
|
||||
MCF5235 Port - Copyright (C) 2006 Christian Walter.
|
||||
|
||||
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** as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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
|
||||
along with FreeRTOS; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes FreeRTOS, without being obliged to provide
|
||||
the source code for any proprietary components. See the licensing section
|
||||
of http://www.FreeRTOS.org for full details of how and when the exception
|
||||
can be applied.
|
||||
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* This is a concise, step by step, 'hands on' guide that describes both *
|
||||
* general multitasking concepts and FreeRTOS specifics. It presents and *
|
||||
* explains numerous examples that are written using the FreeRTOS API. *
|
||||
* Full source code for all the examples is provided in an accompanying *
|
||||
* .zip file. *
|
||||
* *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
|
||||
Please ensure to read the configuration and relevant port sections of the
|
||||
online documentation.
|
||||
|
||||
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.
|
||||
*/
|
||||
* FreeRTOS V4.1.1 - Copyright (C) 2003-2006 Richard Barry.
|
||||
* MCF5235 Port - Copyright (C) 2006 Christian Walter.
|
||||
*
|
||||
* 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** as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* along with FreeRTOS; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* A special exception to the GPL can be applied should you wish to distribute
|
||||
* a combined work that includes FreeRTOS, without being obliged to provide
|
||||
* the source code for any proprietary components. See the licensing section
|
||||
* of http://www.FreeRTOS.org for full details of how and when the exception
|
||||
* can be applied.
|
||||
*
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* This is a concise, step by step, 'hands on' guide that describes both *
|
||||
* general multitasking concepts and FreeRTOS specifics. It presents and *
|
||||
* explains numerous examples that are written using the FreeRTOS API. *
|
||||
* Full source code for all the examples is provided in an accompanying *
|
||||
* .zip file. *
|
||||
* *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
*
|
||||
* Please ensure to read the configuration and relevant port sections of the
|
||||
* online documentation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ------------------------ Data types for Coldfire ----------------------- */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE unsigned int
|
||||
#define portBASE_TYPE int
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE unsigned int
|
||||
#define portBASE_TYPE int
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
|
||||
/* ------------------------ Architecture specifics ------------------------ */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
|
||||
#define portTRAP_YIELD 0 /* Trap 0 */
|
||||
#define portIPL_MAX 7 /* Only NMI interrupt 7 allowed. */
|
||||
#define portTRAP_YIELD 0 /* Trap 0 */
|
||||
#define portIPL_MAX 7 /* Only NMI interrupt 7 allowed. */
|
||||
|
||||
/* ------------------------ FreeRTOS macros for port ---------------------- */
|
||||
|
||||
|
|
@ -97,17 +97,17 @@ typedef unsigned long UBaseType_t;
|
|||
* the stack for the CPU registers and other task dependent values (e.g
|
||||
* ulCriticalNesting) and updates the top of the stack in the TCB.
|
||||
*/
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm volatile ( /* reserve space for task state. */ \
|
||||
"lea.l (-64, %sp), %sp\n\t" \
|
||||
/* push data register %d0-%d7/%a0-%a6 on stack. */ \
|
||||
"movem.l %d0-%d7/%a0-%a6, (%sp)\n\t" \
|
||||
/* push ulCriticalNesting counter on stack. */ \
|
||||
"lea.l (60, %sp), %a0\n\t" \
|
||||
"move.l ulCriticalNesting, (%a0)\n\t" \
|
||||
/* set the new top of the stack in the TCB. */ \
|
||||
"move.l pxCurrentTCB, %a0\n\t" \
|
||||
"move.l %sp, (%a0)");
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm volatile ( /* reserve space for task state. */ \
|
||||
"lea.l (-64, %sp), %sp\n\t" \
|
||||
/* push data register %d0-%d7/%a0-%a6 on stack. */ \
|
||||
"movem.l %d0-%d7/%a0-%a6, (%sp)\n\t" \
|
||||
/* push ulCriticalNesting counter on stack. */ \
|
||||
"lea.l (60, %sp), %a0\n\t" \
|
||||
"move.l ulCriticalNesting, (%a0)\n\t" \
|
||||
/* set the new top of the stack in the TCB. */ \
|
||||
"move.l pxCurrentTCB, %a0\n\t" \
|
||||
"move.l %sp, (%a0)" );
|
||||
|
||||
/*.
|
||||
* This function restores the current active and continues its execution.
|
||||
|
|
@ -115,68 +115,66 @@ typedef unsigned long UBaseType_t;
|
|||
* task dependent values (e.g ulCriticalNesting). Finally execution
|
||||
* is continued by executing an rte instruction.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm volatile ( "move.l pxCurrentTCB, %sp\n\t" \
|
||||
"move.l (%sp), %sp\n\t" \
|
||||
/* stack pointer now points to the saved registers. */ \
|
||||
"movem.l (%sp), %d0-%d7/%a0-%a6\n\t" \
|
||||
/* restore ulCriticalNesting counter from stack. */ \
|
||||
"lea.l (%sp, 60), %sp\n\t" \
|
||||
"move.l (%sp)+, ulCriticalNesting\n\t" \
|
||||
/* stack pointer now points to exception frame. */ \
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm volatile ( "move.l pxCurrentTCB, %sp\n\t" \
|
||||
"move.l (%sp), %sp\n\t" \
|
||||
/* stack pointer now points to the saved registers. */ \
|
||||
"movem.l (%sp), %d0-%d7/%a0-%a6\n\t" \
|
||||
/* restore ulCriticalNesting counter from stack. */ \
|
||||
"lea.l (%sp, 60), %sp\n\t" \
|
||||
"move.l (%sp)+, ulCriticalNesting\n\t" \
|
||||
/* stack pointer now points to exception frame. */ \
|
||||
"rte\n\t" );
|
||||
|
||||
#define portENTER_CRITICAL() \
|
||||
#define portENTER_CRITICAL() \
|
||||
vPortEnterCritical();
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
#define portEXIT_CRITICAL() \
|
||||
vPortExitCritical();
|
||||
|
||||
#define portSET_IPL( xIPL ) \
|
||||
#define portSET_IPL( xIPL ) \
|
||||
asm_set_ipl( xIPL )
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
do { ( void )portSET_IPL( portIPL_MAX ); } while( 0 )
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
do { ( void )portSET_IPL( 0 ); } while( 0 )
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
do { ( void ) portSET_IPL( portIPL_MAX ); } while( 0 )
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
do { ( void ) portSET_IPL( 0 ); } while( 0 )
|
||||
|
||||
#define portYIELD() \
|
||||
asm volatile ( " trap %0\n\t" : : "i"(portTRAP_YIELD) )
|
||||
#define portYIELD() \
|
||||
asm volatile ( " trap %0\n\t" : : "i" ( portTRAP_YIELD ) )
|
||||
|
||||
#define portNOP() \
|
||||
#define portNOP() \
|
||||
asm volatile ( "nop\n\t" )
|
||||
|
||||
#define portENTER_SWITCHING_ISR() \
|
||||
asm volatile ( "move.w #0x2700, %sr" ); \
|
||||
/* Save the context of the interrupted task. */ \
|
||||
portSAVE_CONTEXT( ); \
|
||||
#define portENTER_SWITCHING_ISR() \
|
||||
asm volatile ( "move.w #0x2700, %sr" ); \
|
||||
/* Save the context of the interrupted task. */ \
|
||||
portSAVE_CONTEXT(); \
|
||||
{
|
||||
|
||||
#define portEXIT_SWITCHING_ISR( SwitchRequired ) \
|
||||
/* If a switch is required we call vTaskSwitchContext(). */ \
|
||||
if( SwitchRequired ) \
|
||||
{ \
|
||||
vTaskSwitchContext( ); \
|
||||
} \
|
||||
} \
|
||||
portRESTORE_CONTEXT( );
|
||||
#define portEXIT_SWITCHING_ISR( SwitchRequired ) \
|
||||
/* If a switch is required we call vTaskSwitchContext(). */ \
|
||||
if( SwitchRequired ) \
|
||||
{ \
|
||||
vTaskSwitchContext(); \
|
||||
} \
|
||||
} \
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* ------------------------ Function prototypes --------------------------- */
|
||||
void vPortEnterCritical( void );
|
||||
void vPortExitCritical( void );
|
||||
int asm_set_ipl( uint32_t int uiNewIPL );
|
||||
void vPortEnterCritical( void );
|
||||
void vPortExitCritical( void );
|
||||
int asm_set_ipl( uint32_t int uiNewIPL );
|
||||
|
||||
/* ------------------------ Compiler specifics ---------------------------- */
|
||||
#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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
Changes from V2.5.2
|
||||
|
||||
+ usCriticalNesting now has a volatile qualifier.
|
||||
*/
|
||||
* Changes from V2.5.2
|
||||
*
|
||||
+ usCriticalNesting now has a volatile qualifier.
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
|
@ -39,62 +39,62 @@
|
|||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MSP430 port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the MSP430 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Constants required for hardware setup. The tick ISR runs off the ACLK,
|
||||
not the MCLK. */
|
||||
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
|
||||
/* Constants required for hardware setup. The tick ISR runs off the ACLK,
|
||||
* not the MCLK. */
|
||||
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
|
||||
|
||||
/* We require the address of the pxCurrentTCB variable, but don't want to know
|
||||
any details of its type. */
|
||||
* any details of its type. */
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
|
||||
/* Most ports implement critical sections by placing the interrupt flags on
|
||||
the stack before disabling interrupts. Exiting the critical section is then
|
||||
simply a case of popping the flags from the stack. As mspgcc does not use
|
||||
a frame pointer this cannot be done as modifying the stack will clobber all
|
||||
the stack variables. Instead each task maintains a count of the critical
|
||||
section nesting depth. Each time a critical section is entered the count is
|
||||
incremented. Each time a critical section is left the count is decremented -
|
||||
with interrupts only being re-enabled if the count is zero.
|
||||
|
||||
usCriticalNesting will get set to zero when the scheduler starts, but must
|
||||
not be initialised to zero as this will cause problems during the startup
|
||||
sequence. */
|
||||
* the stack before disabling interrupts. Exiting the critical section is then
|
||||
* simply a case of popping the flags from the stack. As mspgcc does not use
|
||||
* a frame pointer this cannot be done as modifying the stack will clobber all
|
||||
* the stack variables. Instead each task maintains a count of the critical
|
||||
* section nesting depth. Each time a critical section is entered the count is
|
||||
* incremented. Each time a critical section is left the count is decremented -
|
||||
* with interrupts only being re-enabled if the count is zero.
|
||||
*
|
||||
* usCriticalNesting will get set to zero when the scheduler starts, but must
|
||||
* not be initialised to zero as this will cause problems during the startup
|
||||
* sequence. */
|
||||
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macro to save a task context to the task stack. This simply pushes all the
|
||||
* general purpose msp430 registers onto the stack, followed by the
|
||||
* usCriticalNesting value used by the task. Finally the resultant stack
|
||||
* pointer value is saved into the task control block so it can be retrieved
|
||||
/*
|
||||
* Macro to save a task context to the task stack. This simply pushes all the
|
||||
* general purpose msp430 registers onto the stack, followed by the
|
||||
* usCriticalNesting value used by the task. Finally the resultant stack
|
||||
* pointer value is saved into the task control block so it can be retrieved
|
||||
* the next time the task executes.
|
||||
*/
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm volatile ( "push r4 \n\t" \
|
||||
"push r5 \n\t" \
|
||||
"push r6 \n\t" \
|
||||
"push r7 \n\t" \
|
||||
"push r8 \n\t" \
|
||||
"push r9 \n\t" \
|
||||
"push r10 \n\t" \
|
||||
"push r11 \n\t" \
|
||||
"push r12 \n\t" \
|
||||
"push r13 \n\t" \
|
||||
"push r14 \n\t" \
|
||||
"push r15 \n\t" \
|
||||
"mov.w usCriticalNesting, r14 \n\t" \
|
||||
"push r14 \n\t" \
|
||||
"mov.w pxCurrentTCB, r12 \n\t" \
|
||||
"mov.w r1, @r12 \n\t" \
|
||||
);
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm volatile ( "push r4 \n\t"\
|
||||
"push r5 \n\t"\
|
||||
"push r6 \n\t"\
|
||||
"push r7 \n\t"\
|
||||
"push r8 \n\t"\
|
||||
"push r9 \n\t"\
|
||||
"push r10 \n\t"\
|
||||
"push r11 \n\t"\
|
||||
"push r12 \n\t"\
|
||||
"push r13 \n\t"\
|
||||
"push r14 \n\t"\
|
||||
"push r15 \n\t"\
|
||||
"mov.w usCriticalNesting, r14 \n\t"\
|
||||
"push r14 \n\t"\
|
||||
"mov.w pxCurrentTCB, r12 \n\t"\
|
||||
"mov.w r1, @r12 \n\t"\
|
||||
);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Macro to restore a task context from the task stack. This is effectively
|
||||
* the reverse of portSAVE_CONTEXT(). First the stack pointer value is
|
||||
* loaded from the task control block. Next the value for usCriticalNesting
|
||||
|
|
@ -104,26 +104,26 @@ volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
|||
* The bic instruction ensures there are no low power bits set in the status
|
||||
* register that is about to be popped from the stack.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm volatile ( "mov.w pxCurrentTCB, r12 \n\t" \
|
||||
"mov.w @r12, r1 \n\t" \
|
||||
"pop r15 \n\t" \
|
||||
"mov.w r15, usCriticalNesting \n\t" \
|
||||
"pop r15 \n\t" \
|
||||
"pop r14 \n\t" \
|
||||
"pop r13 \n\t" \
|
||||
"pop r12 \n\t" \
|
||||
"pop r11 \n\t" \
|
||||
"pop r10 \n\t" \
|
||||
"pop r9 \n\t" \
|
||||
"pop r8 \n\t" \
|
||||
"pop r7 \n\t" \
|
||||
"pop r6 \n\t" \
|
||||
"pop r5 \n\t" \
|
||||
"pop r4 \n\t" \
|
||||
"bic #(0xf0),0(r1) \n\t" \
|
||||
"reti \n\t" \
|
||||
);
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm volatile ( "mov.w pxCurrentTCB, r12 \n\t"\
|
||||
"mov.w @r12, r1 \n\t"\
|
||||
"pop r15 \n\t" \
|
||||
"mov.w r15, usCriticalNesting \n\t"\
|
||||
"pop r15 \n\t" \
|
||||
"pop r14 \n\t" \
|
||||
"pop r13 \n\t" \
|
||||
"pop r12 \n\t" \
|
||||
"pop r11 \n\t" \
|
||||
"pop r10 \n\t" \
|
||||
"pop r9 \n\t" \
|
||||
"pop r8 \n\t" \
|
||||
"pop r7 \n\t" \
|
||||
"pop r6 \n\t" \
|
||||
"pop r5 \n\t" \
|
||||
"pop r4 \n\t" \
|
||||
"bic #(0xf0),0(r1) \n\t" \
|
||||
"reti \n\t"\
|
||||
);
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
@ -133,195 +133,194 @@ volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
|||
static void prvSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/*
|
||||
Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging and can be included if required.
|
||||
/*
|
||||
* Place a few bytes of known values on the bottom of the stack.
|
||||
* This is just useful for debugging and can be included if required.
|
||||
*
|
||||
* pxTopOfStack = ( StackType_t ) 0x1111;
|
||||
* pxTopOfStack--;
|
||||
* pxTopOfStack = ( StackType_t ) 0x2222;
|
||||
* pxTopOfStack--;
|
||||
* pxTopOfStack = ( StackType_t ) 0x3333;
|
||||
* pxTopOfStack--;
|
||||
*/
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x1111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x2222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x3333;
|
||||
pxTopOfStack--;
|
||||
*/
|
||||
/* The msp430 automatically pushes the PC then SR onto the stack before
|
||||
* executing an ISR. We want the stack to look just as if this has happened
|
||||
* so place a pointer to the start of the task on the stack first - followed
|
||||
* by the flags we want the task to use when it starts up. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The msp430 automatically pushes the PC then SR onto the stack before
|
||||
executing an ISR. We want the stack to look just as if this has happened
|
||||
so place a pointer to the start of the task on the stack first - followed
|
||||
by the flags we want the task to use when it starts up. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pxTopOfStack--;
|
||||
/* Next the general purpose registers. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x4444;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x6666;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x7777;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x8888;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x9999;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaa;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xbbbb;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xcccc;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xdddd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xeeee;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the general purpose registers. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x4444;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x6666;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x7777;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x8888;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x9999;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaa;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xbbbb;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xcccc;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xdddd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xeeee;
|
||||
pxTopOfStack--;
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
* R15. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R15. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
/* The code generated by the mspgcc compiler does not maintain separate
|
||||
* stack and frame pointers. The portENTER_CRITICAL macro cannot therefore
|
||||
* use the stack as per other ports. Instead a variable is used to keep
|
||||
* track of the critical section nesting. This variable has to be stored
|
||||
* as part of the task context and is initially set to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
/* The code generated by the mspgcc compiler does not maintain separate
|
||||
stack and frame pointers. The portENTER_CRITICAL macro cannot therefore
|
||||
use the stack as per other ports. Instead a variable is used to keep
|
||||
track of the critical section nesting. This variable has to be stored
|
||||
as part of the task context and is initially set to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
/* Return a pointer to the top of the stack we have generated so this can
|
||||
be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
/* Return a pointer to the top of the stack we have generated so this can
|
||||
* be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
* this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdTRUE;
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the MSP430 port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
/* It is unlikely that the MSP430 port will get stopped. If required simply
|
||||
* disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Manual context switch called by portYIELD or taskYIELD.
|
||||
* Manual context switch called by portYIELD or taskYIELD.
|
||||
*
|
||||
* The first thing we do is save the registers so we can use a naked attribute.
|
||||
*/
|
||||
void vPortYield( void ) __attribute__ ( ( naked ) );
|
||||
void vPortYield( void ) __attribute__( ( naked ) );
|
||||
void vPortYield( void )
|
||||
{
|
||||
/* We want the stack of the task being saved to look exactly as if the task
|
||||
was saved during a pre-emptive RTOS tick ISR. Before calling an ISR the
|
||||
msp430 places the status register onto the stack. As this is a function
|
||||
call and not an ISR we have to do this manually. */
|
||||
asm volatile ( "push r2" );
|
||||
_DINT();
|
||||
/* We want the stack of the task being saved to look exactly as if the task
|
||||
* was saved during a pre-emptive RTOS tick ISR. Before calling an ISR the
|
||||
* msp430 places the status register onto the stack. As this is a function
|
||||
* call and not an ISR we have to do this manually. */
|
||||
asm volatile ( "push r2");
|
||||
_DINT();
|
||||
|
||||
/* Save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
/* Save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Switch to the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
/* Switch to the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Hardware initialisation to generate the RTOS tick. This uses timer 0
|
||||
* but could alternatively use the watchdog timer or timer 1.
|
||||
* but could alternatively use the watchdog timer or timer 1.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Ensure the timer is stopped. */
|
||||
TACTL = 0;
|
||||
/* Ensure the timer is stopped. */
|
||||
TACTL = 0;
|
||||
|
||||
/* Run the timer of the ACLK. */
|
||||
TACTL = TASSEL_1;
|
||||
/* Run the timer of the ACLK. */
|
||||
TACTL = TASSEL_1;
|
||||
|
||||
/* Clear everything to start with. */
|
||||
TACTL |= TACLR;
|
||||
/* Clear everything to start with. */
|
||||
TACTL |= TACLR;
|
||||
|
||||
/* Set the compare match value according to the tick rate we want. */
|
||||
TACCR0 = portACLK_FREQUENCY_HZ / configTICK_RATE_HZ;
|
||||
/* Set the compare match value according to the tick rate we want. */
|
||||
TACCR0 = portACLK_FREQUENCY_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Enable the interrupts. */
|
||||
TACCTL0 = CCIE;
|
||||
/* Enable the interrupts. */
|
||||
TACCTL0 = CCIE;
|
||||
|
||||
/* Start up clean. */
|
||||
TACTL |= TACLR;
|
||||
/* Start up clean. */
|
||||
TACTL |= TACLR;
|
||||
|
||||
/* Up mode. */
|
||||
TACTL |= MC_1;
|
||||
/* Up mode. */
|
||||
TACTL |= MC_1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* The interrupt service routine used depends on whether the pre-emptive
|
||||
* scheduler is being used or not.
|
||||
*/
|
||||
|
||||
#if configUSE_PREEMPTION == 1
|
||||
|
||||
/*
|
||||
* Tick ISR for preemptive scheduler. We can use a naked attribute as
|
||||
* the context is saved at the start of vPortYieldFromTick(). The tick
|
||||
* count is incremented after the context is saved.
|
||||
*/
|
||||
interrupt (TIMERA0_VECTOR) prvTickISR( void ) __attribute__ ( ( naked ) );
|
||||
interrupt (TIMERA0_VECTOR) prvTickISR( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
/*
|
||||
* Tick ISR for preemptive scheduler. We can use a naked attribute as
|
||||
* the context is saved at the start of vPortYieldFromTick(). The tick
|
||||
* count is incremented after the context is saved.
|
||||
*/
|
||||
interrupt( TIMERA0_VECTOR ) prvTickISR( void ) __attribute__( ( naked ) );
|
||||
interrupt( TIMERA0_VECTOR ) prvTickISR( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the tick count then switch to the highest priority task
|
||||
that is ready to run. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
/* Increment the tick count then switch to the highest priority task
|
||||
* that is ready to run. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* if configUSE_PREEMPTION == 1 */
|
||||
|
||||
/*
|
||||
* Tick ISR for the cooperative scheduler. All this does is increment the
|
||||
* tick count. We don't need to switch context, this can only be done by
|
||||
* manual calls to taskYIELD();
|
||||
*/
|
||||
interrupt (TIMERA0_VECTOR) prvTickISR( void );
|
||||
interrupt (TIMERA0_VECTOR) prvTickISR( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Tick ISR for the cooperative scheduler. All this does is increment the
|
||||
* tick count. We don't need to switch context, this can only be done by
|
||||
* manual calls to taskYIELD();
|
||||
*/
|
||||
interrupt( TIMERA0_VECTOR ) prvTickISR( void );
|
||||
interrupt( TIMERA0_VECTOR ) prvTickISR( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
#endif /* if configUSE_PREEMPTION == 1 */
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,85 +42,84 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portBASE_TYPE short
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portBASE_TYPE short
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros. */
|
||||
#define portDISABLE_INTERRUPTS() asm volatile ( "DINT" ); asm volatile ( "NOP" )
|
||||
#define portENABLE_INTERRUPTS() asm volatile ( "EINT" ); asm volatile ( "NOP" )
|
||||
#define portDISABLE_INTERRUPTS() asm volatile ( "DINT" ); asm volatile ( "NOP" )
|
||||
#define portENABLE_INTERRUPTS() asm volatile ( "EINT" ); asm volatile ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section control macros. */
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
|
||||
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
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. */ \
|
||||
usCriticalNesting++; \
|
||||
}
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
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. */ \
|
||||
usCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
/* Decrement the nesting count as we are leaving a critical section. */ \
|
||||
usCriticalNesting--; \
|
||||
\
|
||||
/* If the nesting level has reached zero then interrupts should be */ \
|
||||
/* re-enabled. */ \
|
||||
if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
/* Decrement the nesting count as we are leaving a critical section. */ \
|
||||
usCriticalNesting--; \
|
||||
\
|
||||
/* If the nesting level has reached zero then interrupts should be */ \
|
||||
/* re-enabled. */ \
|
||||
if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
extern void vPortYield( void ) __attribute__ ( ( naked ) );
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
extern void vPortYield( void ) __attribute__( ( naked ) );
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardwware specifics. */
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MicroBlaze port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the MicroBlaze port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
|
|
@ -41,33 +41,33 @@
|
|||
#include <xintc_i.h>
|
||||
#include <xtmrctr.h>
|
||||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 to use this port.
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 to use this port.
|
||||
#endif
|
||||
|
||||
/* Tasks are started with interrupts enabled. */
|
||||
#define portINITIAL_MSR_STATE ( ( StackType_t ) 0x02 )
|
||||
#define portINITIAL_MSR_STATE ( ( StackType_t ) 0x02 )
|
||||
|
||||
/* Tasks are started with a critical section nesting of 0 - however prior
|
||||
to the scheduler being commenced we don't want the critical nesting level
|
||||
to reach zero, so it is initialised to a high value. */
|
||||
#define portINITIAL_NESTING_VALUE ( 0xff )
|
||||
* to the scheduler being commenced we don't want the critical nesting level
|
||||
* to reach zero, so it is initialised to a high value. */
|
||||
#define portINITIAL_NESTING_VALUE ( 0xff )
|
||||
|
||||
/* Our hardware setup only uses one counter. */
|
||||
#define portCOUNTER_0 0
|
||||
#define portCOUNTER_0 0
|
||||
|
||||
/* The stack used by the ISR is filled with a known value to assist in
|
||||
debugging. */
|
||||
#define portISR_STACK_FILL_VALUE 0x55555555
|
||||
* debugging. */
|
||||
#define portISR_STACK_FILL_VALUE 0x55555555
|
||||
|
||||
/* Counts the nesting depth of calls to portENTER_CRITICAL(). Each task
|
||||
maintains it's own count, so this variable is saved as part of the task
|
||||
context. */
|
||||
* maintains it's own count, so this variable is saved as part of the task
|
||||
* context. */
|
||||
volatile UBaseType_t uxCriticalNesting = portINITIAL_NESTING_VALUE;
|
||||
|
||||
/* To limit the amount of stack required by each task, this port uses a
|
||||
separate stack for interrupts. */
|
||||
uint32_t *pulISRStack;
|
||||
* separate stack for interrupts. */
|
||||
uint32_t * pulISRStack;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -84,140 +84,142 @@ static void prvSetupTimerInterrupt( void );
|
|||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
extern void *_SDA2_BASE_, *_SDA_BASE_;
|
||||
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
|
||||
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_;
|
||||
extern void * _SDA2_BASE_, * _SDA_BASE_;
|
||||
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
|
||||
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_;
|
||||
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
This is essential for the Microblaze port and these lines must
|
||||
not be omitted. The parameter value will overwrite the
|
||||
0x22222222 value during the function prologue. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x22222222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x33333333;
|
||||
pxTopOfStack--;
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
* This is essential for the Microblaze port and these lines must
|
||||
* not be omitted. The parameter value will overwrite the
|
||||
* 0x22222222 value during the function prologue. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x22222222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x33333333;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* First stack an initial value for the critical section nesting. This
|
||||
is initialised to zero as tasks are started with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R0. */
|
||||
/* First stack an initial value for the critical section nesting. This
|
||||
* is initialised to zero as tasks are started with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R0. */
|
||||
|
||||
/* Place an initial value for all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ulR2; /* R2 - small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03; /* R3. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04; /* R4. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;/* R5 contains the function call parameters. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06; /* R6. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07; /* R7. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08; /* R8. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09; /* R9. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0a; /* R10. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0b; /* R11. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0c; /* R12. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ulR13; /* R13 - small data read write area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* R14. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0f; /* R15. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10; /* R16. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11; /* R17. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12; /* R18. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x13; /* R19. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x14; /* R20. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x15; /* R21. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x16; /* R22. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x17; /* R23. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x18; /* R24. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x19; /* R25. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1a; /* R26. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1b; /* R27. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1c; /* R28. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1d; /* R29. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1e; /* R30. */
|
||||
pxTopOfStack--;
|
||||
/* Place an initial value for all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ulR2; /* R2 - small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03; /* R3. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04; /* R4. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R5 contains the function call parameters. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06; /* R6. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07; /* R7. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08; /* R8. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09; /* R9. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0a; /* R10. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0b; /* R11. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0c; /* R12. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ulR13; /* R13 - small data read write area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* R14. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0f; /* R15. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10; /* R16. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11; /* R17. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12; /* R18. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x13; /* R19. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x14; /* R20. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x15; /* R21. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x16; /* R22. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x17; /* R23. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x18; /* R24. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x19; /* R25. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1a; /* R26. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1b; /* R27. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1c; /* R28. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1d; /* R29. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1e; /* R30. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The MSR is stacked between R30 and R31. */
|
||||
*pxTopOfStack = portINITIAL_MSR_STATE;
|
||||
pxTopOfStack--;
|
||||
/* The MSR is stacked between R30 and R31. */
|
||||
*pxTopOfStack = portINITIAL_MSR_STATE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x1f; /* R31. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1f; /* R31. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Return a pointer to the top of the stack we have generated so this can
|
||||
be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
/* Return a pointer to the top of the stack we have generated so this can
|
||||
* be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void ( __FreeRTOS_interrupt_Handler )( void );
|
||||
extern void ( vStartFirstTask )( void );
|
||||
extern void( __FreeRTOS_interrupt_Handler )( void );
|
||||
extern void( vStartFirstTask )( void );
|
||||
|
||||
|
||||
/* Setup the FreeRTOS interrupt handler. Code copied from crt0.s. */
|
||||
asm volatile ( "la r6, r0, __FreeRTOS_interrupt_handler \n\t" \
|
||||
"sw r6, r1, r0 \n\t" \
|
||||
"lhu r7, r1, r0 \n\t" \
|
||||
"shi r7, r0, 0x12 \n\t" \
|
||||
"shi r6, r0, 0x16 " );
|
||||
/* Setup the FreeRTOS interrupt handler. Code copied from crt0.s. */
|
||||
asm volatile ( "la r6, r0, __FreeRTOS_interrupt_handler \n\t"\
|
||||
"sw r6, r1, r0 \n\t"\
|
||||
"lhu r7, r1, r0 \n\t"\
|
||||
"shi r7, r0, 0x12 \n\t"\
|
||||
"shi r6, r0, 0x16 " );
|
||||
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
* this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Allocate the stack to be used by the interrupt handler. */
|
||||
pulISRStack = ( uint32_t * ) pvPortMalloc( configMINIMAL_STACK_SIZE * sizeof( StackType_t ) );
|
||||
/* Allocate the stack to be used by the interrupt handler. */
|
||||
pulISRStack = ( uint32_t * ) pvPortMalloc( configMINIMAL_STACK_SIZE * sizeof( StackType_t ) );
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
if( pulISRStack != NULL )
|
||||
{
|
||||
/* Fill the ISR stack with a known value to facilitate debugging. */
|
||||
memset( pulISRStack, portISR_STACK_FILL_VALUE, configMINIMAL_STACK_SIZE * sizeof( StackType_t ) );
|
||||
pulISRStack += ( configMINIMAL_STACK_SIZE - 1 );
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
if( pulISRStack != NULL )
|
||||
{
|
||||
/* Fill the ISR stack with a known value to facilitate debugging. */
|
||||
memset( pulISRStack, portISR_STACK_FILL_VALUE, configMINIMAL_STACK_SIZE * sizeof( StackType_t ) );
|
||||
pulISRStack += ( configMINIMAL_STACK_SIZE - 1 );
|
||||
|
||||
/* Kick off the first task. */
|
||||
vStartFirstTask();
|
||||
}
|
||||
/* Kick off the first task. */
|
||||
vStartFirstTask();
|
||||
}
|
||||
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented. */
|
||||
/* Not implemented. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -226,17 +228,18 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
void vPortYield( void )
|
||||
{
|
||||
extern void VPortYieldASM( void );
|
||||
extern void VPortYieldASM( void );
|
||||
|
||||
/* Perform the context switch in a critical section to assure it is
|
||||
not interrupted by the tick ISR. It is not a problem to do this as
|
||||
each task maintains it's own interrupt status. */
|
||||
portENTER_CRITICAL();
|
||||
/* Jump directly to the yield function to ensure there is no
|
||||
compiler generated prologue code. */
|
||||
asm volatile ( "bralid r14, VPortYieldASM \n\t" \
|
||||
"or r0, r0, r0 \n\t" );
|
||||
portEXIT_CRITICAL();
|
||||
/* Perform the context switch in a critical section to assure it is
|
||||
* not interrupted by the tick ISR. It is not a problem to do this as
|
||||
* each task maintains it's own interrupt status. */
|
||||
portENTER_CRITICAL();
|
||||
|
||||
/* Jump directly to the yield function to ensure there is no
|
||||
* compiler generated prologue code. */
|
||||
asm volatile ( "bralid r14, VPortYieldASM \n\t"\
|
||||
"or r0, r0, r0 \n\t");
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -245,26 +248,26 @@ extern void VPortYieldASM( void );
|
|||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
XTmrCtr xTimer;
|
||||
const uint32_t ulCounterValue = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
UBaseType_t uxMask;
|
||||
XTmrCtr xTimer;
|
||||
const uint32_t ulCounterValue = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
UBaseType_t uxMask;
|
||||
|
||||
/* The OPB timer1 is used to generate the tick. Use the provided library
|
||||
functions to enable the timer and set the tick frequency. */
|
||||
XTmrCtr_mDisable( XPAR_OPB_TIMER_1_BASEADDR, XPAR_OPB_TIMER_1_DEVICE_ID );
|
||||
XTmrCtr_Initialize( &xTimer, XPAR_OPB_TIMER_1_DEVICE_ID );
|
||||
XTmrCtr_mSetLoadReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, ulCounterValue );
|
||||
XTmrCtr_mSetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, XTC_CSR_LOAD_MASK | XTC_CSR_INT_OCCURED_MASK );
|
||||
/* The OPB timer1 is used to generate the tick. Use the provided library
|
||||
* functions to enable the timer and set the tick frequency. */
|
||||
XTmrCtr_mDisable( XPAR_OPB_TIMER_1_BASEADDR, XPAR_OPB_TIMER_1_DEVICE_ID );
|
||||
XTmrCtr_Initialize( &xTimer, XPAR_OPB_TIMER_1_DEVICE_ID );
|
||||
XTmrCtr_mSetLoadReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, ulCounterValue );
|
||||
XTmrCtr_mSetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, XTC_CSR_LOAD_MASK | XTC_CSR_INT_OCCURED_MASK );
|
||||
|
||||
/* Set the timer interrupt enable bit while maintaining the other bit
|
||||
states. */
|
||||
uxMask = XIntc_In32( ( XPAR_OPB_INTC_0_BASEADDR + XIN_IER_OFFSET ) );
|
||||
uxMask |= XPAR_OPB_TIMER_1_INTERRUPT_MASK;
|
||||
XIntc_Out32( ( XPAR_OPB_INTC_0_BASEADDR + XIN_IER_OFFSET ), ( uxMask ) );
|
||||
/* Set the timer interrupt enable bit while maintaining the other bit
|
||||
* states. */
|
||||
uxMask = XIntc_In32( ( XPAR_OPB_INTC_0_BASEADDR + XIN_IER_OFFSET ) );
|
||||
uxMask |= XPAR_OPB_TIMER_1_INTERRUPT_MASK;
|
||||
XIntc_Out32( ( XPAR_OPB_INTC_0_BASEADDR + XIN_IER_OFFSET ), ( uxMask ) );
|
||||
|
||||
XTmrCtr_Start( &xTimer, XPAR_OPB_TIMER_1_DEVICE_ID );
|
||||
XTmrCtr_mSetControlStatusReg(XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK | XTC_CSR_INT_OCCURED_MASK );
|
||||
XIntc_mAckIntr( XPAR_INTC_SINGLE_BASEADDR, 1 );
|
||||
XTmrCtr_Start( &xTimer, XPAR_OPB_TIMER_1_DEVICE_ID );
|
||||
XTmrCtr_mSetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK | XTC_CSR_INT_OCCURED_MASK );
|
||||
XIntc_mAckIntr( XPAR_INTC_SINGLE_BASEADDR, 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -276,57 +279,53 @@ UBaseType_t uxMask;
|
|||
*/
|
||||
void vTaskISRHandler( void )
|
||||
{
|
||||
static uint32_t ulPending;
|
||||
static uint32_t ulPending;
|
||||
|
||||
/* Which interrupts are pending? */
|
||||
ulPending = XIntc_In32( ( XPAR_INTC_SINGLE_BASEADDR + XIN_IVR_OFFSET ) );
|
||||
/* Which interrupts are pending? */
|
||||
ulPending = XIntc_In32( ( XPAR_INTC_SINGLE_BASEADDR + XIN_IVR_OFFSET ) );
|
||||
|
||||
if( ulPending < XPAR_INTC_MAX_NUM_INTR_INPUTS )
|
||||
{
|
||||
static XIntc_VectorTableEntry *pxTablePtr;
|
||||
static XIntc_Config *pxConfig;
|
||||
static uint32_t ulInterruptMask;
|
||||
if( ulPending < XPAR_INTC_MAX_NUM_INTR_INPUTS )
|
||||
{
|
||||
static XIntc_VectorTableEntry * pxTablePtr;
|
||||
static XIntc_Config * pxConfig;
|
||||
static uint32_t ulInterruptMask;
|
||||
|
||||
ulInterruptMask = ( uint32_t ) 1 << ulPending;
|
||||
ulInterruptMask = ( uint32_t ) 1 << ulPending;
|
||||
|
||||
/* Get the configuration data using the device ID */
|
||||
pxConfig = &XIntc_ConfigTable[ ( uint32_t ) XPAR_INTC_SINGLE_DEVICE_ID ];
|
||||
/* Get the configuration data using the device ID */
|
||||
pxConfig = &XIntc_ConfigTable[ ( uint32_t ) XPAR_INTC_SINGLE_DEVICE_ID ];
|
||||
|
||||
pxTablePtr = &( pxConfig->HandlerTable[ ulPending ] );
|
||||
if( pxConfig->AckBeforeService & ( ulInterruptMask ) )
|
||||
{
|
||||
XIntc_mAckIntr( pxConfig->BaseAddress, ulInterruptMask );
|
||||
pxTablePtr->Handler( pxTablePtr->CallBackRef );
|
||||
}
|
||||
else
|
||||
{
|
||||
pxTablePtr->Handler( pxTablePtr->CallBackRef );
|
||||
XIntc_mAckIntr( pxConfig->BaseAddress, ulInterruptMask );
|
||||
}
|
||||
}
|
||||
pxTablePtr = &( pxConfig->HandlerTable[ ulPending ] );
|
||||
|
||||
if( pxConfig->AckBeforeService & ( ulInterruptMask ) )
|
||||
{
|
||||
XIntc_mAckIntr( pxConfig->BaseAddress, ulInterruptMask );
|
||||
pxTablePtr->Handler( pxTablePtr->CallBackRef );
|
||||
}
|
||||
else
|
||||
{
|
||||
pxTablePtr->Handler( pxTablePtr->CallBackRef );
|
||||
XIntc_mAckIntr( pxConfig->BaseAddress, ulInterruptMask );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Handler for the timer interrupt.
|
||||
*/
|
||||
void vTickISR( void *pvBaseAddress )
|
||||
void vTickISR( void * pvBaseAddress )
|
||||
{
|
||||
uint32_t ulCSR;
|
||||
uint32_t ulCSR;
|
||||
|
||||
/* Increment the RTOS tick - this might cause a task to unblock. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
/* Increment the RTOS tick - this might cause a task to unblock. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Clear the timer interrupt */
|
||||
ulCSR = XTmrCtr_mGetControlStatusReg(XPAR_OPB_TIMER_1_BASEADDR, 0);
|
||||
XTmrCtr_mSetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, ulCSR );
|
||||
/* Clear the timer interrupt */
|
||||
ulCSR = XTmrCtr_mGetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, 0 );
|
||||
XTmrCtr_mSetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, ulCSR );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -42,84 +42,85 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros. */
|
||||
void microblaze_disable_interrupts( void );
|
||||
void microblaze_enable_interrupts( void );
|
||||
#define portDISABLE_INTERRUPTS() microblaze_disable_interrupts()
|
||||
#define portENABLE_INTERRUPTS() microblaze_enable_interrupts()
|
||||
void microblaze_disable_interrupts( void );
|
||||
void microblaze_enable_interrupts( void );
|
||||
#define portDISABLE_INTERRUPTS() microblaze_disable_interrupts()
|
||||
#define portENABLE_INTERRUPTS() microblaze_enable_interrupts()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section macros. */
|
||||
void vPortEnterCritical( void );
|
||||
void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() { \
|
||||
extern UBaseType_t uxCriticalNesting; \
|
||||
microblaze_disable_interrupts(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
void vPortEnterCritical( void );
|
||||
void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern UBaseType_t uxCriticalNesting; \
|
||||
microblaze_disable_interrupts(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() { \
|
||||
extern UBaseType_t uxCriticalNesting; \
|
||||
/* Interrupts are disabled, so we can */ \
|
||||
/* access the variable directly. */ \
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
/* The nesting has unwound and we \
|
||||
can enable interrupts again. */ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern UBaseType_t uxCriticalNesting; \
|
||||
/* Interrupts are disabled, so we can */ \
|
||||
/* access the variable directly. */ \
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
/* The nesting has unwound and we \
|
||||
* can enable interrupts again. */ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
void vTaskSwitchContext();
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
void vTaskSwitchContext();
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MicroBlaze port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the MicroBlaze port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
|
|
@ -42,20 +42,20 @@
|
|||
#include <microblaze_exceptions_g.h>
|
||||
|
||||
/* Tasks are started with a critical section nesting of 0 - however, prior to
|
||||
the scheduler being commenced interrupts should not be enabled, so the critical
|
||||
nesting variable is initialised to a non-zero value. */
|
||||
#define portINITIAL_NESTING_VALUE ( 0xff )
|
||||
* the scheduler being commenced interrupts should not be enabled, so the critical
|
||||
* nesting variable is initialised to a non-zero value. */
|
||||
#define portINITIAL_NESTING_VALUE ( 0xff )
|
||||
|
||||
/* The bit within the MSR register that enabled/disables interrupts and
|
||||
exceptions respectively. */
|
||||
#define portMSR_IE ( 0x02U )
|
||||
#define portMSR_EE ( 0x100U )
|
||||
/* The bit within the MSR register that enabled/disables interrupts and
|
||||
* exceptions respectively. */
|
||||
#define portMSR_IE ( 0x02U )
|
||||
#define portMSR_EE ( 0x100U )
|
||||
|
||||
/* If the floating point unit is included in the MicroBlaze build, then the
|
||||
FSR register is saved as part of the task context. portINITIAL_FSR is the value
|
||||
given to the FSR register when the initial context is set up for a task being
|
||||
created. */
|
||||
#define portINITIAL_FSR ( 0U )
|
||||
* FSR register is saved as part of the task context. portINITIAL_FSR is the value
|
||||
* given to the FSR register when the initial context is set up for a task being
|
||||
* created. */
|
||||
#define portINITIAL_FSR ( 0U )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
@ -71,28 +71,28 @@ static int32_t prvEnsureInterruptControllerIsInitialised( void );
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Counts the nesting depth of calls to portENTER_CRITICAL(). Each task
|
||||
maintains its own count, so this variable is saved as part of the task
|
||||
context. */
|
||||
volatile UBaseType_t uxCriticalNesting = portINITIAL_NESTING_VALUE;
|
||||
* maintains its own count, so this variable is saved as part of the task
|
||||
* context. */
|
||||
volatile UBaseType_t uxCriticalNesting = portINITIAL_NESTING_VALUE;
|
||||
|
||||
/* This port uses a separate stack for interrupts. This prevents the stack of
|
||||
every task needing to be large enough to hold an entire interrupt stack on top
|
||||
of the task stack. */
|
||||
uint32_t *pulISRStack;
|
||||
* every task needing to be large enough to hold an entire interrupt stack on top
|
||||
* of the task stack. */
|
||||
uint32_t * pulISRStack;
|
||||
|
||||
/* If an interrupt requests a context switch, then ulTaskSwitchRequested will
|
||||
get set to 1. ulTaskSwitchRequested is inspected just before the main interrupt
|
||||
handler exits. If, at that time, ulTaskSwitchRequested is set to 1, the kernel
|
||||
will call vTaskSwitchContext() to ensure the task that runs immediately after
|
||||
the interrupt exists is the highest priority task that is able to run. This is
|
||||
an unusual mechanism, but is used for this port because a single interrupt can
|
||||
cause the servicing of multiple peripherals - and it is inefficient to call
|
||||
vTaskSwitchContext() multiple times as each peripheral is serviced. */
|
||||
* get set to 1. ulTaskSwitchRequested is inspected just before the main interrupt
|
||||
* handler exits. If, at that time, ulTaskSwitchRequested is set to 1, the kernel
|
||||
* will call vTaskSwitchContext() to ensure the task that runs immediately after
|
||||
* the interrupt exists is the highest priority task that is able to run. This is
|
||||
* an unusual mechanism, but is used for this port because a single interrupt can
|
||||
* cause the servicing of multiple peripherals - and it is inefficient to call
|
||||
* vTaskSwitchContext() multiple times as each peripheral is serviced. */
|
||||
volatile uint32_t ulTaskSwitchRequested = 0UL;
|
||||
|
||||
/* The instance of the interrupt controller used by this port. This is required
|
||||
by the Xilinx library API functions. */
|
||||
static XIntc xInterruptControllerInstance;
|
||||
* by the Xilinx library API functions. */
|
||||
static XIntc xInterruptControllerInstance;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -102,172 +102,174 @@ static XIntc xInterruptControllerInstance;
|
|||
*
|
||||
* See the portable.h header file.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
extern void *_SDA2_BASE_, *_SDA_BASE_;
|
||||
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
|
||||
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_;
|
||||
extern void * _SDA2_BASE_, * _SDA_BASE_;
|
||||
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
|
||||
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_;
|
||||
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
This is essential for the Microblaze port and these lines must
|
||||
not be omitted. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
* This is essential for the Microblaze port and these lines must
|
||||
* not be omitted. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
|
||||
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
/* The FSR value placed in the initial task context is just 0. */
|
||||
*pxTopOfStack = portINITIAL_FSR;
|
||||
pxTopOfStack--;
|
||||
#endif
|
||||
#if ( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
/* The FSR value placed in the initial task context is just 0. */
|
||||
*pxTopOfStack = portINITIAL_FSR;
|
||||
pxTopOfStack--;
|
||||
#endif
|
||||
|
||||
/* The MSR value placed in the initial task context should have interrupts
|
||||
disabled. Each task will enable interrupts automatically when it enters
|
||||
the running state for the first time. */
|
||||
*pxTopOfStack = mfmsr() & ~portMSR_IE;
|
||||
|
||||
#if( MICROBLAZE_EXCEPTIONS_ENABLED == 1 )
|
||||
{
|
||||
/* Ensure exceptions are enabled for the task. */
|
||||
*pxTopOfStack |= portMSR_EE;
|
||||
}
|
||||
#endif
|
||||
/* The MSR value placed in the initial task context should have interrupts
|
||||
* disabled. Each task will enable interrupts automatically when it enters
|
||||
* the running state for the first time. */
|
||||
*pxTopOfStack = mfmsr() & ~portMSR_IE;
|
||||
|
||||
pxTopOfStack--;
|
||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 )
|
||||
{
|
||||
/* Ensure exceptions are enabled for the task. */
|
||||
*pxTopOfStack |= portMSR_EE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* First stack an initial value for the critical section nesting. This
|
||||
is initialised to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* R0 is always zero. */
|
||||
/* R1 is the SP. */
|
||||
/* First stack an initial value for the critical section nesting. This
|
||||
* is initialised to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00;
|
||||
|
||||
/* Place an initial value for all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ulR2; /* R2 - read only small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 - return values and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 - return values and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;/* R5 contains the function call parameters. */
|
||||
/* R0 is always zero. */
|
||||
/* R1 is the SP. */
|
||||
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 - other parameters and temporaries. Used as the return address from vPortTaskEntryPoint. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08; /* R8 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0a; /* R10 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0b; /* R11 - temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0c; /* R12 - temporaries. */
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack-= 8;
|
||||
#endif
|
||||
/* Place an initial value for all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ulR2; /* R2 - read only small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 - return values and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 - return values and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R5 contains the function call parameters. */
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) ulR13; /* R13 - read/write small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* R14 - return address for interrupt. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL; /* R15 - return address for subroutine. */
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 - other parameters and temporaries. Used as the return address from vPortTaskEntryPoint. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08; /* R8 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0a; /* R10 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0b; /* R11 - temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0c; /* R12 - temporaries. */
|
||||
pxTopOfStack--;
|
||||
#else /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
|
||||
pxTopOfStack -= 8;
|
||||
#endif /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
|
||||
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10; /* R16 - return address for trap (debugger). */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11; /* R17 - return address for exceptions, if configured. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 4;
|
||||
#endif
|
||||
*pxTopOfStack = ( StackType_t ) ulR13; /* R13 - read/write small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* R14 - return address for interrupt. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL; /* R15 - return address for subroutine. */
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R19 - must be saved across function calls. Callee-save. Seems to be interpreted as the frame pointer. */
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10; /* R16 - return address for trap (debugger). */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11; /* R17 - return address for exceptions, if configured. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 4;
|
||||
#endif
|
||||
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x14; /* R20 - reserved for storing a pointer to the Global Offset Table (GOT) in Position Independent Code (PIC). Non-volatile in non-PIC code. Must be saved across function calls. Callee-save. Not used by FreeRTOS. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x15; /* R21 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x16; /* R22 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x17; /* R23 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x18; /* R24 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x19; /* R25 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1a; /* R26 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1b; /* R27 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1c; /* R28 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1d; /* R29 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 13;
|
||||
#endif
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R19 - must be saved across function calls. Callee-save. Seems to be interpreted as the frame pointer. */
|
||||
|
||||
/* Return a pointer to the top of the stack that has been generated so this
|
||||
can be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x14; /* R20 - reserved for storing a pointer to the Global Offset Table (GOT) in Position Independent Code (PIC). Non-volatile in non-PIC code. Must be saved across function calls. Callee-save. Not used by FreeRTOS. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x15; /* R21 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x16; /* R22 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x17; /* R23 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x18; /* R24 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x19; /* R25 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1a; /* R26 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1b; /* R27 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1c; /* R28 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1d; /* R29 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
#else /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
|
||||
pxTopOfStack -= 13;
|
||||
#endif /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
|
||||
|
||||
/* Return a pointer to the top of the stack that has been generated so this
|
||||
* can be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void ( vPortStartFirstTask )( void );
|
||||
extern uint32_t _stack[];
|
||||
extern void( vPortStartFirstTask )( void );
|
||||
extern uint32_t _stack[];
|
||||
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
this function is called.
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
* this function is called.
|
||||
*
|
||||
* This port uses an application defined callback function to install the tick
|
||||
* interrupt handler because the kernel will run on lots of different
|
||||
* MicroBlaze and FPGA configurations - not all of which will have the same
|
||||
* timer peripherals defined or available. An example definition of
|
||||
* vApplicationSetupTimerInterrupt() is provided in the official demo
|
||||
* application that accompanies this port. */
|
||||
vApplicationSetupTimerInterrupt();
|
||||
|
||||
This port uses an application defined callback function to install the tick
|
||||
interrupt handler because the kernel will run on lots of different
|
||||
MicroBlaze and FPGA configurations - not all of which will have the same
|
||||
timer peripherals defined or available. An example definition of
|
||||
vApplicationSetupTimerInterrupt() is provided in the official demo
|
||||
application that accompanies this port. */
|
||||
vApplicationSetupTimerInterrupt();
|
||||
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
|
||||
pulISRStack = ( uint32_t * ) _stack;
|
||||
|
||||
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
|
||||
pulISRStack = ( uint32_t * ) _stack;
|
||||
/* Ensure there is enough space for the functions called from the interrupt
|
||||
* service routines to write back into the stack frame of the caller. */
|
||||
pulISRStack -= 2;
|
||||
|
||||
/* Ensure there is enough space for the functions called from the interrupt
|
||||
service routines to write back into the stack frame of the caller. */
|
||||
pulISRStack -= 2;
|
||||
/* Restore the context of the first task that is going to run. From here
|
||||
* on, the created tasks will be executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Restore the context of the first task that is going to run. From here
|
||||
on, the created tasks will be executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -276,104 +278,107 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
void vPortYield( void )
|
||||
{
|
||||
extern void VPortYieldASM( void );
|
||||
extern void VPortYieldASM( void );
|
||||
|
||||
/* Perform the context switch in a critical section to assure it is
|
||||
not interrupted by the tick ISR. It is not a problem to do this as
|
||||
each task maintains its own interrupt status. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Jump directly to the yield function to ensure there is no
|
||||
compiler generated prologue code. */
|
||||
asm volatile ( "bralid r14, VPortYieldASM \n\t" \
|
||||
"or r0, r0, r0 \n\t" );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
/* Perform the context switch in a critical section to assure it is
|
||||
* not interrupted by the tick ISR. It is not a problem to do this as
|
||||
* each task maintains its own interrupt status. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Jump directly to the yield function to ensure there is no
|
||||
* compiler generated prologue code. */
|
||||
asm volatile ( "bralid r14, VPortYieldASM \n\t"\
|
||||
"or r0, r0, r0 \n\t");
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnableInterrupt( uint8_t ucInterruptID )
|
||||
{
|
||||
int32_t lReturn;
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to enable an interrupt in the interrupt
|
||||
controller because the interrupt controller instance variable is private
|
||||
to this file. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
|
||||
}
|
||||
/* An API function is provided to enable an interrupt in the interrupt
|
||||
* controller because the interrupt controller instance variable is private
|
||||
* to this file. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
|
||||
configASSERT( lReturn );
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
|
||||
}
|
||||
|
||||
configASSERT( lReturn );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortDisableInterrupt( uint8_t ucInterruptID )
|
||||
{
|
||||
int32_t lReturn;
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to disable an interrupt in the interrupt
|
||||
controller because the interrupt controller instance variable is private
|
||||
to this file. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
/* An API function is provided to disable an interrupt in the interrupt
|
||||
* controller because the interrupt controller instance variable is private
|
||||
* to this file. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
XIntc_Disable( &xInterruptControllerInstance, ucInterruptID );
|
||||
}
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
XIntc_Disable( &xInterruptControllerInstance, ucInterruptID );
|
||||
}
|
||||
|
||||
configASSERT( lReturn );
|
||||
configASSERT( lReturn );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID,
|
||||
XInterruptHandler pxHandler,
|
||||
void * pvCallBackRef )
|
||||
{
|
||||
int32_t lReturn;
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to install an interrupt handler because the
|
||||
interrupt controller instance variable is private to this file. */
|
||||
/* An API function is provided to install an interrupt handler because the
|
||||
* interrupt controller instance variable is private to this file. */
|
||||
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );
|
||||
}
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );
|
||||
}
|
||||
|
||||
if( lReturn == XST_SUCCESS )
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
if( lReturn == XST_SUCCESS )
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
|
||||
configASSERT( lReturn == pdPASS );
|
||||
configASSERT( lReturn == pdPASS );
|
||||
|
||||
return lReturn;
|
||||
return lReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t prvEnsureInterruptControllerIsInitialised( void )
|
||||
{
|
||||
static int32_t lInterruptControllerInitialised = pdFALSE;
|
||||
int32_t lReturn;
|
||||
static int32_t lInterruptControllerInitialised = pdFALSE;
|
||||
int32_t lReturn;
|
||||
|
||||
/* Ensure the interrupt controller instance variable is initialised before
|
||||
it is used, and that the initialisation only happens once. */
|
||||
if( lInterruptControllerInitialised != pdTRUE )
|
||||
{
|
||||
lReturn = prvInitialiseInterruptController();
|
||||
/* Ensure the interrupt controller instance variable is initialised before
|
||||
* it is used, and that the initialisation only happens once. */
|
||||
if( lInterruptControllerInitialised != pdTRUE )
|
||||
{
|
||||
lReturn = prvInitialiseInterruptController();
|
||||
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lInterruptControllerInitialised = pdTRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lInterruptControllerInitialised = pdTRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
|
||||
return lReturn;
|
||||
return lReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -381,71 +386,69 @@ int32_t lReturn;
|
|||
* Handler for the timer interrupt. This is the handler that the application
|
||||
* defined callback function vApplicationSetupTimerInterrupt() should install.
|
||||
*/
|
||||
void vPortTickISR( void *pvUnused )
|
||||
void vPortTickISR( void * pvUnused )
|
||||
{
|
||||
extern void vApplicationClearTimerInterrupt( void );
|
||||
extern void vApplicationClearTimerInterrupt( void );
|
||||
|
||||
/* Ensure the unused parameter does not generate a compiler warning. */
|
||||
( void ) pvUnused;
|
||||
/* Ensure the unused parameter does not generate a compiler warning. */
|
||||
( void ) pvUnused;
|
||||
|
||||
/* This port uses an application defined callback function to clear the tick
|
||||
interrupt because the kernel will run on lots of different MicroBlaze and
|
||||
FPGA configurations - not all of which will have the same timer peripherals
|
||||
defined or available. An example definition of
|
||||
vApplicationClearTimerInterrupt() is provided in the official demo
|
||||
application that accompanies this port. */
|
||||
vApplicationClearTimerInterrupt();
|
||||
/* This port uses an application defined callback function to clear the tick
|
||||
* interrupt because the kernel will run on lots of different MicroBlaze and
|
||||
* FPGA configurations - not all of which will have the same timer peripherals
|
||||
* defined or available. An example definition of
|
||||
* vApplicationClearTimerInterrupt() is provided in the official demo
|
||||
* application that accompanies this port. */
|
||||
vApplicationClearTimerInterrupt();
|
||||
|
||||
/* Increment the RTOS tick - this might cause a task to unblock. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
|
||||
ulTaskSwitchRequested = 1;
|
||||
}
|
||||
/* Increment the RTOS tick - this might cause a task to unblock. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
|
||||
ulTaskSwitchRequested = 1;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t prvInitialiseInterruptController( void )
|
||||
{
|
||||
int32_t lStatus;
|
||||
int32_t lStatus;
|
||||
|
||||
lStatus = XIntc_Initialize( &xInterruptControllerInstance, configINTERRUPT_CONTROLLER_TO_USE );
|
||||
lStatus = XIntc_Initialize( &xInterruptControllerInstance, configINTERRUPT_CONTROLLER_TO_USE );
|
||||
|
||||
if( lStatus == XST_SUCCESS )
|
||||
{
|
||||
/* Initialise the exception table. */
|
||||
Xil_ExceptionInit();
|
||||
if( lStatus == XST_SUCCESS )
|
||||
{
|
||||
/* Initialise the exception table. */
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/* Service all pending interrupts each time the handler is entered. */
|
||||
XIntc_SetIntrSvcOption( xInterruptControllerInstance.BaseAddress, XIN_SVC_ALL_ISRS_OPTION );
|
||||
/* Service all pending interrupts each time the handler is entered. */
|
||||
XIntc_SetIntrSvcOption( xInterruptControllerInstance.BaseAddress, XIN_SVC_ALL_ISRS_OPTION );
|
||||
|
||||
/* Install exception handlers if the MicroBlaze is configured to handle
|
||||
exceptions, and the application defined constant
|
||||
configINSTALL_EXCEPTION_HANDLERS is set to 1. */
|
||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
|
||||
{
|
||||
vPortExceptionsInstallHandlers();
|
||||
}
|
||||
#endif /* MICROBLAZE_EXCEPTIONS_ENABLED */
|
||||
/* Install exception handlers if the MicroBlaze is configured to handle
|
||||
* exceptions, and the application defined constant
|
||||
* configINSTALL_EXCEPTION_HANDLERS is set to 1. */
|
||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
|
||||
{
|
||||
vPortExceptionsInstallHandlers();
|
||||
}
|
||||
#endif /* MICROBLAZE_EXCEPTIONS_ENABLED */
|
||||
|
||||
/* Start the interrupt controller. Interrupts are enabled when the
|
||||
scheduler starts. */
|
||||
lStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE );
|
||||
/* Start the interrupt controller. Interrupts are enabled when the
|
||||
* scheduler starts. */
|
||||
lStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE );
|
||||
|
||||
if( lStatus == XST_SUCCESS )
|
||||
{
|
||||
lStatus = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStatus = pdFAIL;
|
||||
}
|
||||
}
|
||||
if( lStatus == XST_SUCCESS )
|
||||
{
|
||||
lStatus = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStatus = pdFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
configASSERT( lStatus == pdPASS );
|
||||
configASSERT( lStatus == pdPASS );
|
||||
|
||||
return lStatus;
|
||||
return lStatus;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,249 +33,244 @@
|
|||
#include <microblaze_exceptions_g.h>
|
||||
|
||||
/* The Xilinx library defined exception entry point stacks a number of
|
||||
registers. These definitions are offsets from the stack pointer to the various
|
||||
stacked register values. */
|
||||
#define portexR3_STACK_OFFSET 4
|
||||
#define portexR4_STACK_OFFSET 5
|
||||
#define portexR5_STACK_OFFSET 6
|
||||
#define portexR6_STACK_OFFSET 7
|
||||
#define portexR7_STACK_OFFSET 8
|
||||
#define portexR8_STACK_OFFSET 9
|
||||
#define portexR9_STACK_OFFSET 10
|
||||
#define portexR10_STACK_OFFSET 11
|
||||
#define portexR11_STACK_OFFSET 12
|
||||
#define portexR12_STACK_OFFSET 13
|
||||
#define portexR15_STACK_OFFSET 16
|
||||
#define portexR18_STACK_OFFSET 19
|
||||
#define portexMSR_STACK_OFFSET 20
|
||||
#define portexR19_STACK_OFFSET -1
|
||||
* registers. These definitions are offsets from the stack pointer to the various
|
||||
* stacked register values. */
|
||||
#define portexR3_STACK_OFFSET 4
|
||||
#define portexR4_STACK_OFFSET 5
|
||||
#define portexR5_STACK_OFFSET 6
|
||||
#define portexR6_STACK_OFFSET 7
|
||||
#define portexR7_STACK_OFFSET 8
|
||||
#define portexR8_STACK_OFFSET 9
|
||||
#define portexR9_STACK_OFFSET 10
|
||||
#define portexR10_STACK_OFFSET 11
|
||||
#define portexR11_STACK_OFFSET 12
|
||||
#define portexR12_STACK_OFFSET 13
|
||||
#define portexR15_STACK_OFFSET 16
|
||||
#define portexR18_STACK_OFFSET 19
|
||||
#define portexMSR_STACK_OFFSET 20
|
||||
#define portexR19_STACK_OFFSET -1
|
||||
|
||||
/* This is defined to equal the size, in bytes, of the stack frame generated by
|
||||
the Xilinx standard library exception entry point. It is required to determine
|
||||
the stack pointer value prior to the exception being entered. */
|
||||
#define portexASM_HANDLER_STACK_FRAME_SIZE 84UL
|
||||
* the Xilinx standard library exception entry point. It is required to determine
|
||||
* the stack pointer value prior to the exception being entered. */
|
||||
#define portexASM_HANDLER_STACK_FRAME_SIZE 84UL
|
||||
|
||||
/* The number of bytes a MicroBlaze instruction consumes. */
|
||||
#define portexINSTRUCTION_SIZE 4
|
||||
#define portexINSTRUCTION_SIZE 4
|
||||
|
||||
/* Exclude this entire file if the MicroBlaze is not configured to handle
|
||||
exceptions, or the application defined configuration constant
|
||||
configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||
* exceptions, or the application defined configuration constant
|
||||
* configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
|
||||
|
||||
/* This variable is set in the exception entry code, before
|
||||
vPortExceptionHandler is called. */
|
||||
uint32_t *pulStackPointerOnFunctionEntry = NULL;
|
||||
* vPortExceptionHandler is called. */
|
||||
uint32_t * pulStackPointerOnFunctionEntry = NULL;
|
||||
|
||||
/* This is the structure that is filled with the MicroBlaze context as it
|
||||
existed immediately prior to the exception occurrence. A pointer to this
|
||||
structure is passed into the vApplicationExceptionRegisterDump() callback
|
||||
function, if one is defined. */
|
||||
static xPortRegisterDump xRegisterDump;
|
||||
* existed immediately prior to the exception occurrence. A pointer to this
|
||||
* structure is passed into the vApplicationExceptionRegisterDump() callback
|
||||
* function, if one is defined. */
|
||||
static xPortRegisterDump xRegisterDump;
|
||||
|
||||
/* This is the FreeRTOS exception handler that is installed for all exception
|
||||
types. It is called from vPortExceptionHanlderEntry() - which is itself defined
|
||||
in portasm.S. */
|
||||
void vPortExceptionHandler( void *pvExceptionID );
|
||||
extern void vPortExceptionHandlerEntry( void *pvExceptionID );
|
||||
* types. It is called from vPortExceptionHanlderEntry() - which is itself defined
|
||||
* in portasm.S. */
|
||||
void vPortExceptionHandler( void * pvExceptionID );
|
||||
extern void vPortExceptionHandlerEntry( void * pvExceptionID );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* vApplicationExceptionRegisterDump() is a callback function that the
|
||||
application can optionally define to receive a populated xPortRegisterDump
|
||||
structure. If the application chooses not to define a version of
|
||||
vApplicationExceptionRegisterDump() then this weekly defined default
|
||||
implementation will be called instead. */
|
||||
extern void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ) __attribute__((weak));
|
||||
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
|
||||
{
|
||||
( void ) xRegisterDump;
|
||||
* application can optionally define to receive a populated xPortRegisterDump
|
||||
* structure. If the application chooses not to define a version of
|
||||
* vApplicationExceptionRegisterDump() then this weekly defined default
|
||||
* implementation will be called instead. */
|
||||
extern void vApplicationExceptionRegisterDump( xPortRegisterDump * xRegisterDump ) __attribute__( ( weak ) );
|
||||
void vApplicationExceptionRegisterDump( xPortRegisterDump * xRegisterDump )
|
||||
{
|
||||
( void ) xRegisterDump;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
portNOP();
|
||||
}
|
||||
}
|
||||
for( ; ; )
|
||||
{
|
||||
portNOP();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExceptionHandler( void *pvExceptionID )
|
||||
{
|
||||
extern void *pxCurrentTCB;
|
||||
void vPortExceptionHandler( void * pvExceptionID )
|
||||
{
|
||||
extern void * pxCurrentTCB;
|
||||
|
||||
/* Fill an xPortRegisterDump structure with the MicroBlaze context as it
|
||||
was immediately before the exception occurrence. */
|
||||
/* Fill an xPortRegisterDump structure with the MicroBlaze context as it
|
||||
* was immediately before the exception occurrence. */
|
||||
|
||||
/* First fill in the name and handle of the task that was in the Running
|
||||
state when the exception occurred. */
|
||||
xRegisterDump.xCurrentTaskHandle = pxCurrentTCB;
|
||||
xRegisterDump.pcCurrentTaskName = pcTaskGetName( NULL );
|
||||
/* First fill in the name and handle of the task that was in the Running
|
||||
* state when the exception occurred. */
|
||||
xRegisterDump.xCurrentTaskHandle = pxCurrentTCB;
|
||||
xRegisterDump.pcCurrentTaskName = pcTaskGetName( NULL );
|
||||
|
||||
configASSERT( pulStackPointerOnFunctionEntry );
|
||||
configASSERT( pulStackPointerOnFunctionEntry );
|
||||
|
||||
/* Obtain the values of registers that were stacked prior to this function
|
||||
being called, and may have changed since they were stacked. */
|
||||
xRegisterDump.ulR3 = pulStackPointerOnFunctionEntry[ portexR3_STACK_OFFSET ];
|
||||
xRegisterDump.ulR4 = pulStackPointerOnFunctionEntry[ portexR4_STACK_OFFSET ];
|
||||
xRegisterDump.ulR5 = pulStackPointerOnFunctionEntry[ portexR5_STACK_OFFSET ];
|
||||
xRegisterDump.ulR6 = pulStackPointerOnFunctionEntry[ portexR6_STACK_OFFSET ];
|
||||
xRegisterDump.ulR7 = pulStackPointerOnFunctionEntry[ portexR7_STACK_OFFSET ];
|
||||
xRegisterDump.ulR8 = pulStackPointerOnFunctionEntry[ portexR8_STACK_OFFSET ];
|
||||
xRegisterDump.ulR9 = pulStackPointerOnFunctionEntry[ portexR9_STACK_OFFSET ];
|
||||
xRegisterDump.ulR10 = pulStackPointerOnFunctionEntry[ portexR10_STACK_OFFSET ];
|
||||
xRegisterDump.ulR11 = pulStackPointerOnFunctionEntry[ portexR11_STACK_OFFSET ];
|
||||
xRegisterDump.ulR12 = pulStackPointerOnFunctionEntry[ portexR12_STACK_OFFSET ];
|
||||
xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ];
|
||||
xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ];
|
||||
xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ];
|
||||
xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];
|
||||
/* Obtain the values of registers that were stacked prior to this function
|
||||
* being called, and may have changed since they were stacked. */
|
||||
xRegisterDump.ulR3 = pulStackPointerOnFunctionEntry[ portexR3_STACK_OFFSET ];
|
||||
xRegisterDump.ulR4 = pulStackPointerOnFunctionEntry[ portexR4_STACK_OFFSET ];
|
||||
xRegisterDump.ulR5 = pulStackPointerOnFunctionEntry[ portexR5_STACK_OFFSET ];
|
||||
xRegisterDump.ulR6 = pulStackPointerOnFunctionEntry[ portexR6_STACK_OFFSET ];
|
||||
xRegisterDump.ulR7 = pulStackPointerOnFunctionEntry[ portexR7_STACK_OFFSET ];
|
||||
xRegisterDump.ulR8 = pulStackPointerOnFunctionEntry[ portexR8_STACK_OFFSET ];
|
||||
xRegisterDump.ulR9 = pulStackPointerOnFunctionEntry[ portexR9_STACK_OFFSET ];
|
||||
xRegisterDump.ulR10 = pulStackPointerOnFunctionEntry[ portexR10_STACK_OFFSET ];
|
||||
xRegisterDump.ulR11 = pulStackPointerOnFunctionEntry[ portexR11_STACK_OFFSET ];
|
||||
xRegisterDump.ulR12 = pulStackPointerOnFunctionEntry[ portexR12_STACK_OFFSET ];
|
||||
xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ];
|
||||
xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ];
|
||||
xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ];
|
||||
xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];
|
||||
|
||||
/* Obtain the value of all other registers. */
|
||||
xRegisterDump.ulR2_small_data_area = mfgpr( R2 );
|
||||
xRegisterDump.ulR13_read_write_small_data_area = mfgpr( R13 );
|
||||
xRegisterDump.ulR14_return_address_from_interrupt = mfgpr( R14 );
|
||||
xRegisterDump.ulR16_return_address_from_trap = mfgpr( R16 );
|
||||
xRegisterDump.ulR17_return_address_from_exceptions = mfgpr( R17 );
|
||||
xRegisterDump.ulR20 = mfgpr( R20 );
|
||||
xRegisterDump.ulR21 = mfgpr( R21 );
|
||||
xRegisterDump.ulR22 = mfgpr( R22 );
|
||||
xRegisterDump.ulR23 = mfgpr( R23 );
|
||||
xRegisterDump.ulR24 = mfgpr( R24 );
|
||||
xRegisterDump.ulR25 = mfgpr( R25 );
|
||||
xRegisterDump.ulR26 = mfgpr( R26 );
|
||||
xRegisterDump.ulR27 = mfgpr( R27 );
|
||||
xRegisterDump.ulR28 = mfgpr( R28 );
|
||||
xRegisterDump.ulR29 = mfgpr( R29 );
|
||||
xRegisterDump.ulR30 = mfgpr( R30 );
|
||||
xRegisterDump.ulR31 = mfgpr( R31 );
|
||||
xRegisterDump.ulR1_SP = ( ( uint32_t ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
|
||||
xRegisterDump.ulEAR = mfear();
|
||||
xRegisterDump.ulESR = mfesr();
|
||||
xRegisterDump.ulEDR = mfedr();
|
||||
/* Obtain the value of all other registers. */
|
||||
xRegisterDump.ulR2_small_data_area = mfgpr( R2 );
|
||||
xRegisterDump.ulR13_read_write_small_data_area = mfgpr( R13 );
|
||||
xRegisterDump.ulR14_return_address_from_interrupt = mfgpr( R14 );
|
||||
xRegisterDump.ulR16_return_address_from_trap = mfgpr( R16 );
|
||||
xRegisterDump.ulR17_return_address_from_exceptions = mfgpr( R17 );
|
||||
xRegisterDump.ulR20 = mfgpr( R20 );
|
||||
xRegisterDump.ulR21 = mfgpr( R21 );
|
||||
xRegisterDump.ulR22 = mfgpr( R22 );
|
||||
xRegisterDump.ulR23 = mfgpr( R23 );
|
||||
xRegisterDump.ulR24 = mfgpr( R24 );
|
||||
xRegisterDump.ulR25 = mfgpr( R25 );
|
||||
xRegisterDump.ulR26 = mfgpr( R26 );
|
||||
xRegisterDump.ulR27 = mfgpr( R27 );
|
||||
xRegisterDump.ulR28 = mfgpr( R28 );
|
||||
xRegisterDump.ulR29 = mfgpr( R29 );
|
||||
xRegisterDump.ulR30 = mfgpr( R30 );
|
||||
xRegisterDump.ulR31 = mfgpr( R31 );
|
||||
xRegisterDump.ulR1_SP = ( ( uint32_t ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
|
||||
xRegisterDump.ulEAR = mfear();
|
||||
xRegisterDump.ulESR = mfesr();
|
||||
xRegisterDump.ulEDR = mfedr();
|
||||
|
||||
/* Move the saved program counter back to the instruction that was executed
|
||||
when the exception occurred. This is only valid for certain types of
|
||||
exception. */
|
||||
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_exceptions - portexINSTRUCTION_SIZE;
|
||||
/* Move the saved program counter back to the instruction that was executed
|
||||
* when the exception occurred. This is only valid for certain types of
|
||||
* exception. */
|
||||
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_exceptions - portexINSTRUCTION_SIZE;
|
||||
|
||||
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
{
|
||||
xRegisterDump.ulFSR = mffsr();
|
||||
}
|
||||
#else
|
||||
{
|
||||
xRegisterDump.ulFSR = 0UL;
|
||||
}
|
||||
#endif
|
||||
#if ( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
{
|
||||
xRegisterDump.ulFSR = mffsr();
|
||||
}
|
||||
#else
|
||||
{
|
||||
xRegisterDump.ulFSR = 0UL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Also fill in a string that describes what type of exception this is.
|
||||
The string uses the same ID names as defined in the MicroBlaze standard
|
||||
library exception header files. */
|
||||
switch( ( uint32_t ) pvExceptionID )
|
||||
{
|
||||
case XEXC_ID_FSL :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FSL";
|
||||
break;
|
||||
/* Also fill in a string that describes what type of exception this is.
|
||||
* The string uses the same ID names as defined in the MicroBlaze standard
|
||||
* library exception header files. */
|
||||
switch( ( uint32_t ) pvExceptionID )
|
||||
{
|
||||
case XEXC_ID_FSL:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FSL";
|
||||
break;
|
||||
|
||||
case XEXC_ID_UNALIGNED_ACCESS :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_UNALIGNED_ACCESS";
|
||||
break;
|
||||
case XEXC_ID_UNALIGNED_ACCESS:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_UNALIGNED_ACCESS";
|
||||
break;
|
||||
|
||||
case XEXC_ID_ILLEGAL_OPCODE :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_ILLEGAL_OPCODE";
|
||||
break;
|
||||
case XEXC_ID_ILLEGAL_OPCODE:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_ILLEGAL_OPCODE";
|
||||
break;
|
||||
|
||||
case XEXC_ID_M_AXI_I_EXCEPTION :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_M_AXI_I_EXCEPTION or XEXC_ID_IPLB_EXCEPTION";
|
||||
break;
|
||||
case XEXC_ID_M_AXI_I_EXCEPTION:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_M_AXI_I_EXCEPTION or XEXC_ID_IPLB_EXCEPTION";
|
||||
break;
|
||||
|
||||
case XEXC_ID_M_AXI_D_EXCEPTION :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_M_AXI_D_EXCEPTION or XEXC_ID_DPLB_EXCEPTION";
|
||||
break;
|
||||
case XEXC_ID_M_AXI_D_EXCEPTION:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_M_AXI_D_EXCEPTION or XEXC_ID_DPLB_EXCEPTION";
|
||||
break;
|
||||
|
||||
case XEXC_ID_DIV_BY_ZERO :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_DIV_BY_ZERO";
|
||||
break;
|
||||
case XEXC_ID_DIV_BY_ZERO:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_DIV_BY_ZERO";
|
||||
break;
|
||||
|
||||
case XEXC_ID_STACK_VIOLATION :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_STACK_VIOLATION or XEXC_ID_MMU";
|
||||
break;
|
||||
case XEXC_ID_STACK_VIOLATION:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_STACK_VIOLATION or XEXC_ID_MMU";
|
||||
break;
|
||||
|
||||
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
#if ( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
case XEXC_ID_FPU:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FPU see ulFSR value";
|
||||
break;
|
||||
#endif /* XPAR_MICROBLAZE_USE_FPU */
|
||||
}
|
||||
|
||||
case XEXC_ID_FPU :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FPU see ulFSR value";
|
||||
break;
|
||||
/* vApplicationExceptionRegisterDump() is a callback function that the
|
||||
* application can optionally define to receive the populated xPortRegisterDump
|
||||
* structure. If the application chooses not to define a version of
|
||||
* vApplicationExceptionRegisterDump() then the weekly defined default
|
||||
* implementation within this file will be called instead. */
|
||||
vApplicationExceptionRegisterDump( &xRegisterDump );
|
||||
|
||||
#endif /* XPAR_MICROBLAZE_USE_FPU */
|
||||
}
|
||||
|
||||
/* vApplicationExceptionRegisterDump() is a callback function that the
|
||||
application can optionally define to receive the populated xPortRegisterDump
|
||||
structure. If the application chooses not to define a version of
|
||||
vApplicationExceptionRegisterDump() then the weekly defined default
|
||||
implementation within this file will be called instead. */
|
||||
vApplicationExceptionRegisterDump( &xRegisterDump );
|
||||
|
||||
/* Must not attempt to leave this function! */
|
||||
for( ;; )
|
||||
{
|
||||
portNOP();
|
||||
}
|
||||
}
|
||||
/* Must not attempt to leave this function! */
|
||||
for( ; ; )
|
||||
{
|
||||
portNOP();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExceptionsInstallHandlers( void )
|
||||
{
|
||||
static uint32_t ulHandlersAlreadyInstalled = pdFALSE;
|
||||
void vPortExceptionsInstallHandlers( void )
|
||||
{
|
||||
static uint32_t ulHandlersAlreadyInstalled = pdFALSE;
|
||||
|
||||
if( ulHandlersAlreadyInstalled == pdFALSE )
|
||||
{
|
||||
ulHandlersAlreadyInstalled = pdTRUE;
|
||||
if( ulHandlersAlreadyInstalled == pdFALSE )
|
||||
{
|
||||
ulHandlersAlreadyInstalled = pdTRUE;
|
||||
|
||||
#if XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_UNALIGNED_ACCESS, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_UNALIGNED_ACCESS );
|
||||
#endif /* XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS*/
|
||||
#if XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_UNALIGNED_ACCESS, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_UNALIGNED_ACCESS );
|
||||
#endif /* XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS*/
|
||||
|
||||
#if XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_ILLEGAL_OPCODE, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_ILLEGAL_OPCODE );
|
||||
#endif /* XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_ILLEGAL_OPCODE, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_ILLEGAL_OPCODE );
|
||||
#endif /* XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_M_AXI_I_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_I_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_M_AXI_I_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_I_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_M_AXI_D_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_D_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_M_AXI_D_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_D_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_IPLB_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_IPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_IPLB_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_IPLB_BUS_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_IPLB_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_IPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_IPLB_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_IPLB_BUS_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_DPLB_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_DPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DPLB_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_DPLB_BUS_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_DPLB_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_DPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DPLB_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_DPLB_BUS_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_DIV_BY_ZERO, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DIV_BY_ZERO );
|
||||
#endif /* XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_DIV_BY_ZERO, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DIV_BY_ZERO );
|
||||
#endif /* XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_FPU_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_FPU, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FPU );
|
||||
#endif /* XPAR_MICROBLAZE_FPU_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_FPU_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_FPU, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FPU );
|
||||
#endif /* XPAR_MICROBLAZE_FPU_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_FSL_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_FSL, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FSL );
|
||||
#endif /* XPAR_MICROBLAZE_FSL_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_FSL_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_FSL, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FSL );
|
||||
#endif /* XPAR_MICROBLAZE_FSL_EXCEPTION */
|
||||
|
||||
microblaze_enable_exceptions();
|
||||
}
|
||||
}
|
||||
microblaze_enable_exceptions();
|
||||
}
|
||||
}
|
||||
|
||||
/* Exclude the entire file if the MicroBlaze is not configured to handle
|
||||
exceptions, or the application defined configuration item
|
||||
configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||
* exceptions, or the application defined configuration item
|
||||
* configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||
#endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,15 +25,15 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* BSP includes. */
|
||||
#include <mb_interface.h>
|
||||
#include <xparameters.h>
|
||||
#include <mb_interface.h>
|
||||
#include <xparameters.h>
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -46,175 +46,177 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros and functions. */
|
||||
void microblaze_disable_interrupts( void );
|
||||
void microblaze_enable_interrupts( void );
|
||||
#define portDISABLE_INTERRUPTS() microblaze_disable_interrupts()
|
||||
#define portENABLE_INTERRUPTS() microblaze_enable_interrupts()
|
||||
void microblaze_disable_interrupts( void );
|
||||
void microblaze_enable_interrupts( void );
|
||||
#define portDISABLE_INTERRUPTS() microblaze_disable_interrupts()
|
||||
#define portENABLE_INTERRUPTS() microblaze_enable_interrupts()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section macros. */
|
||||
void vPortEnterCritical( void );
|
||||
void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() { \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
microblaze_disable_interrupts(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
void vPortEnterCritical( void );
|
||||
void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
microblaze_disable_interrupts(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() { \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
/* Interrupts are disabled, so we can */ \
|
||||
/* access the variable directly. */ \
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
/* The nesting has unwound and we \
|
||||
can enable interrupts again. */ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
/* Interrupts are disabled, so we can */ \
|
||||
/* access the variable directly. */ \
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
/* The nesting has unwound and we \
|
||||
* can enable interrupts again. */ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The yield macro maps directly to the vPortYield() function. */
|
||||
void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
/* portYIELD_FROM_ISR() does not directly call vTaskSwitchContext(), but instead
|
||||
sets a flag to say that a yield has been requested. The interrupt exit code
|
||||
then checks this flag, and calls vTaskSwitchContext() before restoring a task
|
||||
context, if the flag is not false. This is done to prevent multiple calls to
|
||||
vTaskSwitchContext() being made from a single interrupt, as a single interrupt
|
||||
can result in multiple peripherals being serviced. */
|
||||
extern volatile uint32_t ulTaskSwitchRequested;
|
||||
#define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) ulTaskSwitchRequested = 1
|
||||
* sets a flag to say that a yield has been requested. The interrupt exit code
|
||||
* then checks this flag, and calls vTaskSwitchContext() before restoring a task
|
||||
* context, if the flag is not false. This is done to prevent multiple calls to
|
||||
* vTaskSwitchContext() being made from a single interrupt, as a single interrupt
|
||||
* can result in multiple peripherals being serviced. */
|
||||
extern volatile uint32_t ulTaskSwitchRequested;
|
||||
#define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) ulTaskSwitchRequested = 1
|
||||
|
||||
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
|
||||
return ucReturn;
|
||||
}
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( 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
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* 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 ) )
|
||||
/* 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 = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The following structure is used by the FreeRTOS exception handler. It is
|
||||
filled with the MicroBlaze context as it was at the time the exception occurred.
|
||||
This is done as an aid to debugging exception occurrences. */
|
||||
typedef struct PORT_REGISTER_DUMP
|
||||
{
|
||||
/* The following structure members hold the values of the MicroBlaze
|
||||
registers at the time the exception was raised. */
|
||||
uint32_t ulR1_SP;
|
||||
uint32_t ulR2_small_data_area;
|
||||
uint32_t ulR3;
|
||||
uint32_t ulR4;
|
||||
uint32_t ulR5;
|
||||
uint32_t ulR6;
|
||||
uint32_t ulR7;
|
||||
uint32_t ulR8;
|
||||
uint32_t ulR9;
|
||||
uint32_t ulR10;
|
||||
uint32_t ulR11;
|
||||
uint32_t ulR12;
|
||||
uint32_t ulR13_read_write_small_data_area;
|
||||
uint32_t ulR14_return_address_from_interrupt;
|
||||
uint32_t ulR15_return_address_from_subroutine;
|
||||
uint32_t ulR16_return_address_from_trap;
|
||||
uint32_t ulR17_return_address_from_exceptions; /* The exception entry code will copy the BTR into R17 if the exception occurred in the delay slot of a branch instruction. */
|
||||
uint32_t ulR18;
|
||||
uint32_t ulR19;
|
||||
uint32_t ulR20;
|
||||
uint32_t ulR21;
|
||||
uint32_t ulR22;
|
||||
uint32_t ulR23;
|
||||
uint32_t ulR24;
|
||||
uint32_t ulR25;
|
||||
uint32_t ulR26;
|
||||
uint32_t ulR27;
|
||||
uint32_t ulR28;
|
||||
uint32_t ulR29;
|
||||
uint32_t ulR30;
|
||||
uint32_t ulR31;
|
||||
uint32_t ulPC;
|
||||
uint32_t ulESR;
|
||||
uint32_t ulMSR;
|
||||
uint32_t ulEAR;
|
||||
uint32_t ulFSR;
|
||||
uint32_t ulEDR;
|
||||
* filled with the MicroBlaze context as it was at the time the exception occurred.
|
||||
* This is done as an aid to debugging exception occurrences. */
|
||||
typedef struct PORT_REGISTER_DUMP
|
||||
{
|
||||
/* The following structure members hold the values of the MicroBlaze
|
||||
* registers at the time the exception was raised. */
|
||||
uint32_t ulR1_SP;
|
||||
uint32_t ulR2_small_data_area;
|
||||
uint32_t ulR3;
|
||||
uint32_t ulR4;
|
||||
uint32_t ulR5;
|
||||
uint32_t ulR6;
|
||||
uint32_t ulR7;
|
||||
uint32_t ulR8;
|
||||
uint32_t ulR9;
|
||||
uint32_t ulR10;
|
||||
uint32_t ulR11;
|
||||
uint32_t ulR12;
|
||||
uint32_t ulR13_read_write_small_data_area;
|
||||
uint32_t ulR14_return_address_from_interrupt;
|
||||
uint32_t ulR15_return_address_from_subroutine;
|
||||
uint32_t ulR16_return_address_from_trap;
|
||||
uint32_t ulR17_return_address_from_exceptions; /* The exception entry code will copy the BTR into R17 if the exception occurred in the delay slot of a branch instruction. */
|
||||
uint32_t ulR18;
|
||||
uint32_t ulR19;
|
||||
uint32_t ulR20;
|
||||
uint32_t ulR21;
|
||||
uint32_t ulR22;
|
||||
uint32_t ulR23;
|
||||
uint32_t ulR24;
|
||||
uint32_t ulR25;
|
||||
uint32_t ulR26;
|
||||
uint32_t ulR27;
|
||||
uint32_t ulR28;
|
||||
uint32_t ulR29;
|
||||
uint32_t ulR30;
|
||||
uint32_t ulR31;
|
||||
uint32_t ulPC;
|
||||
uint32_t ulESR;
|
||||
uint32_t ulMSR;
|
||||
uint32_t ulEAR;
|
||||
uint32_t ulFSR;
|
||||
uint32_t ulEDR;
|
||||
|
||||
/* A human readable description of the exception cause. The strings used
|
||||
are the same as the #define constant names found in the
|
||||
microblaze_exceptions_i.h header file */
|
||||
int8_t *pcExceptionCause;
|
||||
/* A human readable description of the exception cause. The strings used
|
||||
* are the same as the #define constant names found in the
|
||||
* microblaze_exceptions_i.h header file */
|
||||
int8_t * pcExceptionCause;
|
||||
|
||||
/* The human readable name of the task that was running at the time the
|
||||
exception occurred. This is the name that was given to the task when the
|
||||
task was created using the FreeRTOS xTaskCreate() API function. */
|
||||
char *pcCurrentTaskName;
|
||||
/* The human readable name of the task that was running at the time the
|
||||
* exception occurred. This is the name that was given to the task when the
|
||||
* task was created using the FreeRTOS xTaskCreate() API function. */
|
||||
char * pcCurrentTaskName;
|
||||
|
||||
/* The handle of the task that was running a the time the exception
|
||||
occurred. */
|
||||
void * xCurrentTaskHandle;
|
||||
|
||||
} xPortRegisterDump;
|
||||
/* The handle of the task that was running a the time the exception
|
||||
* occurred. */
|
||||
void * xCurrentTaskHandle;
|
||||
} xPortRegisterDump;
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -252,7 +254,9 @@ typedef struct PORT_REGISTER_DUMP
|
|||
* pdPASS is returned if the function executes successfully. Any other value
|
||||
* being returned indicates that the function did not execute correctly.
|
||||
*/
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef );
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID,
|
||||
XInterruptHandler pxHandler,
|
||||
void * pvCallBackRef );
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -273,7 +277,7 @@ BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandle
|
|||
* XPAR_INTC_0_GPIO_1_VEC_ID - for the button inputs.
|
||||
*
|
||||
*/
|
||||
void vPortEnableInterrupt( uint8_t ucInterruptID );
|
||||
void vPortEnableInterrupt( uint8_t ucInterruptID );
|
||||
|
||||
/*
|
||||
* Disables the interrupt, within the interrupt controller, for the peripheral
|
||||
|
|
@ -293,7 +297,7 @@ void vPortEnableInterrupt( uint8_t ucInterruptID );
|
|||
* XPAR_INTC_0_GPIO_1_VEC_ID - for the button inputs.
|
||||
*
|
||||
*/
|
||||
void vPortDisableInterrupt( uint8_t ucInterruptID );
|
||||
void vPortDisableInterrupt( uint8_t ucInterruptID );
|
||||
|
||||
/*
|
||||
* This is an application defined callback function used to install the tick
|
||||
|
|
@ -305,7 +309,7 @@ void vPortDisableInterrupt( uint8_t ucInterruptID );
|
|||
* The name of the interrupt handler that should be installed is vPortTickISR(),
|
||||
* which the function below declares as an extern.
|
||||
*/
|
||||
void vApplicationSetupTimerInterrupt( void );
|
||||
void vApplicationSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* This is an application defined callback function used to clear whichever
|
||||
|
|
@ -318,7 +322,7 @@ void vApplicationSetupTimerInterrupt( void );
|
|||
* implementation should not require modification provided the example definition
|
||||
* of vApplicationSetupTimerInterrupt() is also not modified.
|
||||
*/
|
||||
void vApplicationClearTimerInterrupt( void );
|
||||
void vApplicationClearTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* vPortExceptionsInstallHandlers() is only available when the MicroBlaze
|
||||
|
|
@ -341,7 +345,7 @@ void vApplicationClearTimerInterrupt( void );
|
|||
* See the description of vApplicationExceptionRegisterDump() for information
|
||||
* on the processing performed by the FreeRTOS exception handler.
|
||||
*/
|
||||
void vPortExceptionsInstallHandlers( void );
|
||||
void vPortExceptionsInstallHandlers( void );
|
||||
|
||||
/*
|
||||
* The FreeRTOS exception handler fills an xPortRegisterDump structure (defined
|
||||
|
|
@ -357,12 +361,11 @@ void vPortExceptionsInstallHandlers( void );
|
|||
* register dump information. For example, an implementation could be provided
|
||||
* that wrote the register dump data to a display, or a UART port.
|
||||
*/
|
||||
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump );
|
||||
void vApplicationExceptionRegisterDump( xPortRegisterDump * xRegisterDump );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MicroBlaze port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the MicroBlaze port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
|
|
@ -42,20 +42,20 @@
|
|||
#include <microblaze_exceptions_g.h>
|
||||
|
||||
/* Tasks are started with a critical section nesting of 0 - however, prior to
|
||||
the scheduler being commenced interrupts should not be enabled, so the critical
|
||||
nesting variable is initialised to a non-zero value. */
|
||||
#define portINITIAL_NESTING_VALUE ( 0xff )
|
||||
* the scheduler being commenced interrupts should not be enabled, so the critical
|
||||
* nesting variable is initialised to a non-zero value. */
|
||||
#define portINITIAL_NESTING_VALUE ( 0xff )
|
||||
|
||||
/* The bit within the MSR register that enabled/disables interrupts and
|
||||
exceptions respectively. */
|
||||
#define portMSR_IE ( 0x02U )
|
||||
#define portMSR_EE ( 0x100U )
|
||||
* exceptions respectively. */
|
||||
#define portMSR_IE ( 0x02U )
|
||||
#define portMSR_EE ( 0x100U )
|
||||
|
||||
/* If the floating point unit is included in the MicroBlaze build, then the
|
||||
FSR register is saved as part of the task context. portINITIAL_FSR is the value
|
||||
given to the FSR register when the initial context is set up for a task being
|
||||
created. */
|
||||
#define portINITIAL_FSR ( 0U )
|
||||
* FSR register is saved as part of the task context. portINITIAL_FSR is the value
|
||||
* given to the FSR register when the initial context is set up for a task being
|
||||
* created. */
|
||||
#define portINITIAL_FSR ( 0U )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -72,28 +72,28 @@ static int32_t prvEnsureInterruptControllerIsInitialised( void );
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Counts the nesting depth of calls to portENTER_CRITICAL(). Each task
|
||||
maintains its own count, so this variable is saved as part of the task
|
||||
context. */
|
||||
volatile UBaseType_t uxCriticalNesting = portINITIAL_NESTING_VALUE;
|
||||
* maintains its own count, so this variable is saved as part of the task
|
||||
* context. */
|
||||
volatile UBaseType_t uxCriticalNesting = portINITIAL_NESTING_VALUE;
|
||||
|
||||
/* This port uses a separate stack for interrupts. This prevents the stack of
|
||||
every task needing to be large enough to hold an entire interrupt stack on top
|
||||
of the task stack. */
|
||||
uint32_t *pulISRStack;
|
||||
* every task needing to be large enough to hold an entire interrupt stack on top
|
||||
* of the task stack. */
|
||||
uint32_t * pulISRStack;
|
||||
|
||||
/* If an interrupt requests a context switch, then ulTaskSwitchRequested will
|
||||
get set to 1. ulTaskSwitchRequested is inspected just before the main interrupt
|
||||
handler exits. If, at that time, ulTaskSwitchRequested is set to 1, the kernel
|
||||
will call vTaskSwitchContext() to ensure the task that runs immediately after
|
||||
the interrupt exists is the highest priority task that is able to run. This is
|
||||
an unusual mechanism, but is used for this port because a single interrupt can
|
||||
cause the servicing of multiple peripherals - and it is inefficient to call
|
||||
vTaskSwitchContext() multiple times as each peripheral is serviced. */
|
||||
* get set to 1. ulTaskSwitchRequested is inspected just before the main interrupt
|
||||
* handler exits. If, at that time, ulTaskSwitchRequested is set to 1, the kernel
|
||||
* will call vTaskSwitchContext() to ensure the task that runs immediately after
|
||||
* the interrupt exists is the highest priority task that is able to run. This is
|
||||
* an unusual mechanism, but is used for this port because a single interrupt can
|
||||
* cause the servicing of multiple peripherals - and it is inefficient to call
|
||||
* vTaskSwitchContext() multiple times as each peripheral is serviced. */
|
||||
volatile uint32_t ulTaskSwitchRequested = 0UL;
|
||||
|
||||
/* The instance of the interrupt controller used by this port. This is required
|
||||
by the Xilinx library API functions. */
|
||||
static XIntc xInterruptControllerInstance;
|
||||
* by the Xilinx library API functions. */
|
||||
static XIntc xInterruptControllerInstance;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -103,173 +103,175 @@ static XIntc xInterruptControllerInstance;
|
|||
*
|
||||
* See the portable.h header file.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
extern void *_SDA2_BASE_, *_SDA_BASE_;
|
||||
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
|
||||
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_;
|
||||
extern void _start1( void );
|
||||
extern void * _SDA2_BASE_, * _SDA_BASE_;
|
||||
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
|
||||
const uint32_t ulR13 = ( uint32_t ) &_SDA_BASE_;
|
||||
extern void _start1( void );
|
||||
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
This is essential for the Microblaze port and these lines must
|
||||
not be omitted. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
* This is essential for the Microblaze port and these lines must
|
||||
* not be omitted. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000;
|
||||
pxTopOfStack--;
|
||||
|
||||
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
/* The FSR value placed in the initial task context is just 0. */
|
||||
*pxTopOfStack = portINITIAL_FSR;
|
||||
pxTopOfStack--;
|
||||
#endif
|
||||
#if ( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
/* The FSR value placed in the initial task context is just 0. */
|
||||
*pxTopOfStack = portINITIAL_FSR;
|
||||
pxTopOfStack--;
|
||||
#endif
|
||||
|
||||
/* The MSR value placed in the initial task context should have interrupts
|
||||
disabled. Each task will enable interrupts automatically when it enters
|
||||
the running state for the first time. */
|
||||
*pxTopOfStack = mfmsr() & ~portMSR_IE;
|
||||
/* The MSR value placed in the initial task context should have interrupts
|
||||
* disabled. Each task will enable interrupts automatically when it enters
|
||||
* the running state for the first time. */
|
||||
*pxTopOfStack = mfmsr() & ~portMSR_IE;
|
||||
|
||||
#if( MICROBLAZE_EXCEPTIONS_ENABLED == 1 )
|
||||
{
|
||||
/* Ensure exceptions are enabled for the task. */
|
||||
*pxTopOfStack |= portMSR_EE;
|
||||
}
|
||||
#endif
|
||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 )
|
||||
{
|
||||
/* Ensure exceptions are enabled for the task. */
|
||||
*pxTopOfStack |= portMSR_EE;
|
||||
}
|
||||
#endif
|
||||
|
||||
pxTopOfStack--;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* First stack an initial value for the critical section nesting. This
|
||||
is initialised to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00;
|
||||
/* First stack an initial value for the critical section nesting. This
|
||||
* is initialised to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00;
|
||||
|
||||
/* R0 is always zero. */
|
||||
/* R1 is the SP. */
|
||||
/* R0 is always zero. */
|
||||
/* R1 is the SP. */
|
||||
|
||||
/* Place an initial value for all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ulR2; /* R2 - read only small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 - return values and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 - return values and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;/* R5 contains the function call parameters. */
|
||||
/* Place an initial value for all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) ulR2; /* R2 - read only small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 - return values and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 - return values and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R5 contains the function call parameters. */
|
||||
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL; /* R8 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0a; /* R10 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0b; /* R11 - temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0c; /* R12 - temporaries. */
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack-= 8;
|
||||
#endif
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) NULL; /* R8 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0a; /* R10 - other parameters and temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0b; /* R11 - temporaries. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0c; /* R12 - temporaries. */
|
||||
pxTopOfStack--;
|
||||
#else /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
|
||||
pxTopOfStack -= 8;
|
||||
#endif /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) ulR13; /* R13 - read/write small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* R14 - return address for interrupt. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) _start1; /* R15 - return address for subroutine. */
|
||||
*pxTopOfStack = ( StackType_t ) ulR13; /* R13 - read/write small data area. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* R14 - return address for interrupt. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) _start1; /* R15 - return address for subroutine. */
|
||||
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10; /* R16 - return address for trap (debugger). */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11; /* R17 - return address for exceptions, if configured. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 4;
|
||||
#endif
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10; /* R16 - return address for trap (debugger). */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11; /* R17 - return address for exceptions, if configured. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 4;
|
||||
#endif
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R19 - must be saved across function calls. Callee-save. Seems to be interpreted as the frame pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R19 - must be saved across function calls. Callee-save. Seems to be interpreted as the frame pointer. */
|
||||
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x14; /* R20 - reserved for storing a pointer to the Global Offset Table (GOT) in Position Independent Code (PIC). Non-volatile in non-PIC code. Must be saved across function calls. Callee-save. Not used by FreeRTOS. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x15; /* R21 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x16; /* R22 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x17; /* R23 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x18; /* R24 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x19; /* R25 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1a; /* R26 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1b; /* R27 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1c; /* R28 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1d; /* R29 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 13;
|
||||
#endif
|
||||
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x14; /* R20 - reserved for storing a pointer to the Global Offset Table (GOT) in Position Independent Code (PIC). Non-volatile in non-PIC code. Must be saved across function calls. Callee-save. Not used by FreeRTOS. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x15; /* R21 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x16; /* R22 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x17; /* R23 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x18; /* R24 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x19; /* R25 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1a; /* R26 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1b; /* R27 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1c; /* R28 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1d; /* R29 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */
|
||||
pxTopOfStack--;
|
||||
#else /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
|
||||
pxTopOfStack -= 13;
|
||||
#endif /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
|
||||
|
||||
/* Return a pointer to the top of the stack that has been generated so this
|
||||
can be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
/* Return a pointer to the top of the stack that has been generated so this
|
||||
* can be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void ( vPortStartFirstTask )( void );
|
||||
extern uint32_t _stack[];
|
||||
extern void( vPortStartFirstTask )( void );
|
||||
extern uint32_t _stack[];
|
||||
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
this function is called.
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
* this function is called.
|
||||
*
|
||||
* This port uses an application defined callback function to install the tick
|
||||
* interrupt handler because the kernel will run on lots of different
|
||||
* MicroBlaze and FPGA configurations - not all of which will have the same
|
||||
* timer peripherals defined or available. An example definition of
|
||||
* vApplicationSetupTimerInterrupt() is provided in the official demo
|
||||
* application that accompanies this port. */
|
||||
vApplicationSetupTimerInterrupt();
|
||||
|
||||
This port uses an application defined callback function to install the tick
|
||||
interrupt handler because the kernel will run on lots of different
|
||||
MicroBlaze and FPGA configurations - not all of which will have the same
|
||||
timer peripherals defined or available. An example definition of
|
||||
vApplicationSetupTimerInterrupt() is provided in the official demo
|
||||
application that accompanies this port. */
|
||||
vApplicationSetupTimerInterrupt();
|
||||
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
|
||||
pulISRStack = ( uint32_t * ) _stack;
|
||||
|
||||
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
|
||||
pulISRStack = ( uint32_t * ) _stack;
|
||||
/* Ensure there is enough space for the functions called from the interrupt
|
||||
* service routines to write back into the stack frame of the caller. */
|
||||
pulISRStack -= 2;
|
||||
|
||||
/* Ensure there is enough space for the functions called from the interrupt
|
||||
service routines to write back into the stack frame of the caller. */
|
||||
pulISRStack -= 2;
|
||||
/* Restore the context of the first task that is going to run. From here
|
||||
* on, the created tasks will be executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Restore the context of the first task that is going to run. From here
|
||||
on, the created tasks will be executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -278,110 +280,113 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
void vPortYield( void )
|
||||
{
|
||||
extern void VPortYieldASM( void );
|
||||
extern void VPortYieldASM( void );
|
||||
|
||||
/* Perform the context switch in a critical section to assure it is
|
||||
not interrupted by the tick ISR. It is not a problem to do this as
|
||||
each task maintains its own interrupt status. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Jump directly to the yield function to ensure there is no
|
||||
compiler generated prologue code. */
|
||||
asm volatile ( "bralid r14, VPortYieldASM \n\t" \
|
||||
"or r0, r0, r0 \n\t" );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
/* Perform the context switch in a critical section to assure it is
|
||||
* not interrupted by the tick ISR. It is not a problem to do this as
|
||||
* each task maintains its own interrupt status. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Jump directly to the yield function to ensure there is no
|
||||
* compiler generated prologue code. */
|
||||
asm volatile ( "bralid r14, VPortYieldASM \n\t"\
|
||||
"or r0, r0, r0 \n\t");
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnableInterrupt( uint8_t ucInterruptID )
|
||||
{
|
||||
int32_t lReturn;
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to enable an interrupt in the interrupt
|
||||
controller because the interrupt controller instance variable is private
|
||||
to this file. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
/* Critical section protects read/modify/writer operation inside
|
||||
XIntc_Enable(). */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
/* An API function is provided to enable an interrupt in the interrupt
|
||||
* controller because the interrupt controller instance variable is private
|
||||
* to this file. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
|
||||
configASSERT( lReturn );
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
/* Critical section protects read/modify/writer operation inside
|
||||
* XIntc_Enable(). */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
configASSERT( lReturn );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortDisableInterrupt( uint8_t ucInterruptID )
|
||||
{
|
||||
int32_t lReturn;
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to disable an interrupt in the interrupt
|
||||
controller because the interrupt controller instance variable is private
|
||||
to this file. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
/* An API function is provided to disable an interrupt in the interrupt
|
||||
* controller because the interrupt controller instance variable is private
|
||||
* to this file. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
XIntc_Disable( &xInterruptControllerInstance, ucInterruptID );
|
||||
}
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
XIntc_Disable( &xInterruptControllerInstance, ucInterruptID );
|
||||
}
|
||||
|
||||
configASSERT( lReturn );
|
||||
configASSERT( lReturn );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID,
|
||||
XInterruptHandler pxHandler,
|
||||
void * pvCallBackRef )
|
||||
{
|
||||
int32_t lReturn;
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to install an interrupt handler because the
|
||||
interrupt controller instance variable is private to this file. */
|
||||
/* An API function is provided to install an interrupt handler because the
|
||||
* interrupt controller instance variable is private to this file. */
|
||||
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );
|
||||
}
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );
|
||||
}
|
||||
|
||||
if( lReturn == XST_SUCCESS )
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
if( lReturn == XST_SUCCESS )
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
|
||||
configASSERT( lReturn == pdPASS );
|
||||
configASSERT( lReturn == pdPASS );
|
||||
|
||||
return lReturn;
|
||||
return lReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t prvEnsureInterruptControllerIsInitialised( void )
|
||||
{
|
||||
static int32_t lInterruptControllerInitialised = pdFALSE;
|
||||
int32_t lReturn;
|
||||
static int32_t lInterruptControllerInitialised = pdFALSE;
|
||||
int32_t lReturn;
|
||||
|
||||
/* Ensure the interrupt controller instance variable is initialised before
|
||||
it is used, and that the initialisation only happens once. */
|
||||
if( lInterruptControllerInitialised != pdTRUE )
|
||||
{
|
||||
lReturn = prvInitialiseInterruptController();
|
||||
/* Ensure the interrupt controller instance variable is initialised before
|
||||
* it is used, and that the initialisation only happens once. */
|
||||
if( lInterruptControllerInitialised != pdTRUE )
|
||||
{
|
||||
lReturn = prvInitialiseInterruptController();
|
||||
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lInterruptControllerInitialised = pdTRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lInterruptControllerInitialised = pdTRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
|
||||
return lReturn;
|
||||
return lReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -389,71 +394,69 @@ int32_t lReturn;
|
|||
* Handler for the timer interrupt. This is the handler that the application
|
||||
* defined callback function vApplicationSetupTimerInterrupt() should install.
|
||||
*/
|
||||
void vPortTickISR( void *pvUnused )
|
||||
void vPortTickISR( void * pvUnused )
|
||||
{
|
||||
extern void vApplicationClearTimerInterrupt( void );
|
||||
extern void vApplicationClearTimerInterrupt( void );
|
||||
|
||||
/* Ensure the unused parameter does not generate a compiler warning. */
|
||||
( void ) pvUnused;
|
||||
/* Ensure the unused parameter does not generate a compiler warning. */
|
||||
( void ) pvUnused;
|
||||
|
||||
/* This port uses an application defined callback function to clear the tick
|
||||
interrupt because the kernel will run on lots of different MicroBlaze and
|
||||
FPGA configurations - not all of which will have the same timer peripherals
|
||||
defined or available. An example definition of
|
||||
vApplicationClearTimerInterrupt() is provided in the official demo
|
||||
application that accompanies this port. */
|
||||
vApplicationClearTimerInterrupt();
|
||||
/* This port uses an application defined callback function to clear the tick
|
||||
* interrupt because the kernel will run on lots of different MicroBlaze and
|
||||
* FPGA configurations - not all of which will have the same timer peripherals
|
||||
* defined or available. An example definition of
|
||||
* vApplicationClearTimerInterrupt() is provided in the official demo
|
||||
* application that accompanies this port. */
|
||||
vApplicationClearTimerInterrupt();
|
||||
|
||||
/* Increment the RTOS tick - this might cause a task to unblock. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
|
||||
ulTaskSwitchRequested = 1;
|
||||
}
|
||||
/* Increment the RTOS tick - this might cause a task to unblock. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
|
||||
ulTaskSwitchRequested = 1;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t prvInitialiseInterruptController( void )
|
||||
{
|
||||
int32_t lStatus;
|
||||
int32_t lStatus;
|
||||
|
||||
lStatus = XIntc_Initialize( &xInterruptControllerInstance, configINTERRUPT_CONTROLLER_TO_USE );
|
||||
lStatus = XIntc_Initialize( &xInterruptControllerInstance, configINTERRUPT_CONTROLLER_TO_USE );
|
||||
|
||||
if( lStatus == XST_SUCCESS )
|
||||
{
|
||||
/* Initialise the exception table. */
|
||||
Xil_ExceptionInit();
|
||||
if( lStatus == XST_SUCCESS )
|
||||
{
|
||||
/* Initialise the exception table. */
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/* Service all pending interrupts each time the handler is entered. */
|
||||
XIntc_SetIntrSvcOption( xInterruptControllerInstance.BaseAddress, XIN_SVC_ALL_ISRS_OPTION );
|
||||
/* Service all pending interrupts each time the handler is entered. */
|
||||
XIntc_SetIntrSvcOption( xInterruptControllerInstance.BaseAddress, XIN_SVC_ALL_ISRS_OPTION );
|
||||
|
||||
/* Install exception handlers if the MicroBlaze is configured to handle
|
||||
exceptions, and the application defined constant
|
||||
configINSTALL_EXCEPTION_HANDLERS is set to 1. */
|
||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
|
||||
{
|
||||
vPortExceptionsInstallHandlers();
|
||||
}
|
||||
#endif /* MICROBLAZE_EXCEPTIONS_ENABLED */
|
||||
/* Install exception handlers if the MicroBlaze is configured to handle
|
||||
* exceptions, and the application defined constant
|
||||
* configINSTALL_EXCEPTION_HANDLERS is set to 1. */
|
||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
|
||||
{
|
||||
vPortExceptionsInstallHandlers();
|
||||
}
|
||||
#endif /* MICROBLAZE_EXCEPTIONS_ENABLED */
|
||||
|
||||
/* Start the interrupt controller. Interrupts are enabled when the
|
||||
scheduler starts. */
|
||||
lStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE );
|
||||
/* Start the interrupt controller. Interrupts are enabled when the
|
||||
* scheduler starts. */
|
||||
lStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE );
|
||||
|
||||
if( lStatus == XST_SUCCESS )
|
||||
{
|
||||
lStatus = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStatus = pdFAIL;
|
||||
}
|
||||
}
|
||||
if( lStatus == XST_SUCCESS )
|
||||
{
|
||||
lStatus = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStatus = pdFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
configASSERT( lStatus == pdPASS );
|
||||
configASSERT( lStatus == pdPASS );
|
||||
|
||||
return lStatus;
|
||||
return lStatus;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,249 +33,244 @@
|
|||
#include <microblaze_exceptions_g.h>
|
||||
|
||||
/* The Xilinx library defined exception entry point stacks a number of
|
||||
registers. These definitions are offsets from the stack pointer to the various
|
||||
stacked register values. */
|
||||
#define portexR3_STACK_OFFSET 4
|
||||
#define portexR4_STACK_OFFSET 5
|
||||
#define portexR5_STACK_OFFSET 6
|
||||
#define portexR6_STACK_OFFSET 7
|
||||
#define portexR7_STACK_OFFSET 8
|
||||
#define portexR8_STACK_OFFSET 9
|
||||
#define portexR9_STACK_OFFSET 10
|
||||
#define portexR10_STACK_OFFSET 11
|
||||
#define portexR11_STACK_OFFSET 12
|
||||
#define portexR12_STACK_OFFSET 13
|
||||
#define portexR15_STACK_OFFSET 16
|
||||
#define portexR18_STACK_OFFSET 19
|
||||
#define portexMSR_STACK_OFFSET 20
|
||||
#define portexR19_STACK_OFFSET -1
|
||||
* registers. These definitions are offsets from the stack pointer to the various
|
||||
* stacked register values. */
|
||||
#define portexR3_STACK_OFFSET 4
|
||||
#define portexR4_STACK_OFFSET 5
|
||||
#define portexR5_STACK_OFFSET 6
|
||||
#define portexR6_STACK_OFFSET 7
|
||||
#define portexR7_STACK_OFFSET 8
|
||||
#define portexR8_STACK_OFFSET 9
|
||||
#define portexR9_STACK_OFFSET 10
|
||||
#define portexR10_STACK_OFFSET 11
|
||||
#define portexR11_STACK_OFFSET 12
|
||||
#define portexR12_STACK_OFFSET 13
|
||||
#define portexR15_STACK_OFFSET 16
|
||||
#define portexR18_STACK_OFFSET 19
|
||||
#define portexMSR_STACK_OFFSET 20
|
||||
#define portexR19_STACK_OFFSET -1
|
||||
|
||||
/* This is defined to equal the size, in bytes, of the stack frame generated by
|
||||
the Xilinx standard library exception entry point. It is required to determine
|
||||
the stack pointer value prior to the exception being entered. */
|
||||
#define portexASM_HANDLER_STACK_FRAME_SIZE 84UL
|
||||
* the Xilinx standard library exception entry point. It is required to determine
|
||||
* the stack pointer value prior to the exception being entered. */
|
||||
#define portexASM_HANDLER_STACK_FRAME_SIZE 84UL
|
||||
|
||||
/* The number of bytes a MicroBlaze instruction consumes. */
|
||||
#define portexINSTRUCTION_SIZE 4
|
||||
#define portexINSTRUCTION_SIZE 4
|
||||
|
||||
/* Exclude this entire file if the MicroBlaze is not configured to handle
|
||||
exceptions, or the application defined configuration constant
|
||||
configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||
* exceptions, or the application defined configuration constant
|
||||
* configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
|
||||
|
||||
/* This variable is set in the exception entry code, before
|
||||
vPortExceptionHandler is called. */
|
||||
uint32_t *pulStackPointerOnFunctionEntry = NULL;
|
||||
* vPortExceptionHandler is called. */
|
||||
uint32_t * pulStackPointerOnFunctionEntry = NULL;
|
||||
|
||||
/* This is the structure that is filled with the MicroBlaze context as it
|
||||
existed immediately prior to the exception occurrence. A pointer to this
|
||||
structure is passed into the vApplicationExceptionRegisterDump() callback
|
||||
function, if one is defined. */
|
||||
static xPortRegisterDump xRegisterDump;
|
||||
* existed immediately prior to the exception occurrence. A pointer to this
|
||||
* structure is passed into the vApplicationExceptionRegisterDump() callback
|
||||
* function, if one is defined. */
|
||||
static xPortRegisterDump xRegisterDump;
|
||||
|
||||
/* This is the FreeRTOS exception handler that is installed for all exception
|
||||
types. It is called from vPortExceptionHanlderEntry() - which is itself defined
|
||||
in portasm.S. */
|
||||
void vPortExceptionHandler( void *pvExceptionID );
|
||||
extern void vPortExceptionHandlerEntry( void *pvExceptionID );
|
||||
* types. It is called from vPortExceptionHanlderEntry() - which is itself defined
|
||||
* in portasm.S. */
|
||||
void vPortExceptionHandler( void * pvExceptionID );
|
||||
extern void vPortExceptionHandlerEntry( void * pvExceptionID );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* vApplicationExceptionRegisterDump() is a callback function that the
|
||||
application can optionally define to receive a populated xPortRegisterDump
|
||||
structure. If the application chooses not to define a version of
|
||||
vApplicationExceptionRegisterDump() then this weekly defined default
|
||||
implementation will be called instead. */
|
||||
extern void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ) __attribute__((weak));
|
||||
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
|
||||
{
|
||||
( void ) xRegisterDump;
|
||||
* application can optionally define to receive a populated xPortRegisterDump
|
||||
* structure. If the application chooses not to define a version of
|
||||
* vApplicationExceptionRegisterDump() then this weekly defined default
|
||||
* implementation will be called instead. */
|
||||
extern void vApplicationExceptionRegisterDump( xPortRegisterDump * xRegisterDump ) __attribute__( ( weak ) );
|
||||
void vApplicationExceptionRegisterDump( xPortRegisterDump * xRegisterDump )
|
||||
{
|
||||
( void ) xRegisterDump;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
portNOP();
|
||||
}
|
||||
}
|
||||
for( ; ; )
|
||||
{
|
||||
portNOP();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExceptionHandler( void *pvExceptionID )
|
||||
{
|
||||
extern void *pxCurrentTCB;
|
||||
void vPortExceptionHandler( void * pvExceptionID )
|
||||
{
|
||||
extern void * pxCurrentTCB;
|
||||
|
||||
/* Fill an xPortRegisterDump structure with the MicroBlaze context as it
|
||||
was immediately before the exception occurrence. */
|
||||
/* Fill an xPortRegisterDump structure with the MicroBlaze context as it
|
||||
* was immediately before the exception occurrence. */
|
||||
|
||||
/* First fill in the name and handle of the task that was in the Running
|
||||
state when the exception occurred. */
|
||||
xRegisterDump.xCurrentTaskHandle = pxCurrentTCB;
|
||||
xRegisterDump.pcCurrentTaskName = pcTaskGetName( NULL );
|
||||
/* First fill in the name and handle of the task that was in the Running
|
||||
* state when the exception occurred. */
|
||||
xRegisterDump.xCurrentTaskHandle = pxCurrentTCB;
|
||||
xRegisterDump.pcCurrentTaskName = pcTaskGetName( NULL );
|
||||
|
||||
configASSERT( pulStackPointerOnFunctionEntry );
|
||||
configASSERT( pulStackPointerOnFunctionEntry );
|
||||
|
||||
/* Obtain the values of registers that were stacked prior to this function
|
||||
being called, and may have changed since they were stacked. */
|
||||
xRegisterDump.ulR3 = pulStackPointerOnFunctionEntry[ portexR3_STACK_OFFSET ];
|
||||
xRegisterDump.ulR4 = pulStackPointerOnFunctionEntry[ portexR4_STACK_OFFSET ];
|
||||
xRegisterDump.ulR5 = pulStackPointerOnFunctionEntry[ portexR5_STACK_OFFSET ];
|
||||
xRegisterDump.ulR6 = pulStackPointerOnFunctionEntry[ portexR6_STACK_OFFSET ];
|
||||
xRegisterDump.ulR7 = pulStackPointerOnFunctionEntry[ portexR7_STACK_OFFSET ];
|
||||
xRegisterDump.ulR8 = pulStackPointerOnFunctionEntry[ portexR8_STACK_OFFSET ];
|
||||
xRegisterDump.ulR9 = pulStackPointerOnFunctionEntry[ portexR9_STACK_OFFSET ];
|
||||
xRegisterDump.ulR10 = pulStackPointerOnFunctionEntry[ portexR10_STACK_OFFSET ];
|
||||
xRegisterDump.ulR11 = pulStackPointerOnFunctionEntry[ portexR11_STACK_OFFSET ];
|
||||
xRegisterDump.ulR12 = pulStackPointerOnFunctionEntry[ portexR12_STACK_OFFSET ];
|
||||
xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ];
|
||||
xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ];
|
||||
xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ];
|
||||
xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];
|
||||
/* Obtain the values of registers that were stacked prior to this function
|
||||
* being called, and may have changed since they were stacked. */
|
||||
xRegisterDump.ulR3 = pulStackPointerOnFunctionEntry[ portexR3_STACK_OFFSET ];
|
||||
xRegisterDump.ulR4 = pulStackPointerOnFunctionEntry[ portexR4_STACK_OFFSET ];
|
||||
xRegisterDump.ulR5 = pulStackPointerOnFunctionEntry[ portexR5_STACK_OFFSET ];
|
||||
xRegisterDump.ulR6 = pulStackPointerOnFunctionEntry[ portexR6_STACK_OFFSET ];
|
||||
xRegisterDump.ulR7 = pulStackPointerOnFunctionEntry[ portexR7_STACK_OFFSET ];
|
||||
xRegisterDump.ulR8 = pulStackPointerOnFunctionEntry[ portexR8_STACK_OFFSET ];
|
||||
xRegisterDump.ulR9 = pulStackPointerOnFunctionEntry[ portexR9_STACK_OFFSET ];
|
||||
xRegisterDump.ulR10 = pulStackPointerOnFunctionEntry[ portexR10_STACK_OFFSET ];
|
||||
xRegisterDump.ulR11 = pulStackPointerOnFunctionEntry[ portexR11_STACK_OFFSET ];
|
||||
xRegisterDump.ulR12 = pulStackPointerOnFunctionEntry[ portexR12_STACK_OFFSET ];
|
||||
xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ];
|
||||
xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ];
|
||||
xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ];
|
||||
xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];
|
||||
|
||||
/* Obtain the value of all other registers. */
|
||||
xRegisterDump.ulR2_small_data_area = mfgpr( R2 );
|
||||
xRegisterDump.ulR13_read_write_small_data_area = mfgpr( R13 );
|
||||
xRegisterDump.ulR14_return_address_from_interrupt = mfgpr( R14 );
|
||||
xRegisterDump.ulR16_return_address_from_trap = mfgpr( R16 );
|
||||
xRegisterDump.ulR17_return_address_from_exceptions = mfgpr( R17 );
|
||||
xRegisterDump.ulR20 = mfgpr( R20 );
|
||||
xRegisterDump.ulR21 = mfgpr( R21 );
|
||||
xRegisterDump.ulR22 = mfgpr( R22 );
|
||||
xRegisterDump.ulR23 = mfgpr( R23 );
|
||||
xRegisterDump.ulR24 = mfgpr( R24 );
|
||||
xRegisterDump.ulR25 = mfgpr( R25 );
|
||||
xRegisterDump.ulR26 = mfgpr( R26 );
|
||||
xRegisterDump.ulR27 = mfgpr( R27 );
|
||||
xRegisterDump.ulR28 = mfgpr( R28 );
|
||||
xRegisterDump.ulR29 = mfgpr( R29 );
|
||||
xRegisterDump.ulR30 = mfgpr( R30 );
|
||||
xRegisterDump.ulR31 = mfgpr( R31 );
|
||||
xRegisterDump.ulR1_SP = ( ( uint32_t ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
|
||||
xRegisterDump.ulEAR = mfear();
|
||||
xRegisterDump.ulESR = mfesr();
|
||||
xRegisterDump.ulEDR = mfedr();
|
||||
/* Obtain the value of all other registers. */
|
||||
xRegisterDump.ulR2_small_data_area = mfgpr( R2 );
|
||||
xRegisterDump.ulR13_read_write_small_data_area = mfgpr( R13 );
|
||||
xRegisterDump.ulR14_return_address_from_interrupt = mfgpr( R14 );
|
||||
xRegisterDump.ulR16_return_address_from_trap = mfgpr( R16 );
|
||||
xRegisterDump.ulR17_return_address_from_exceptions = mfgpr( R17 );
|
||||
xRegisterDump.ulR20 = mfgpr( R20 );
|
||||
xRegisterDump.ulR21 = mfgpr( R21 );
|
||||
xRegisterDump.ulR22 = mfgpr( R22 );
|
||||
xRegisterDump.ulR23 = mfgpr( R23 );
|
||||
xRegisterDump.ulR24 = mfgpr( R24 );
|
||||
xRegisterDump.ulR25 = mfgpr( R25 );
|
||||
xRegisterDump.ulR26 = mfgpr( R26 );
|
||||
xRegisterDump.ulR27 = mfgpr( R27 );
|
||||
xRegisterDump.ulR28 = mfgpr( R28 );
|
||||
xRegisterDump.ulR29 = mfgpr( R29 );
|
||||
xRegisterDump.ulR30 = mfgpr( R30 );
|
||||
xRegisterDump.ulR31 = mfgpr( R31 );
|
||||
xRegisterDump.ulR1_SP = ( ( uint32_t ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
|
||||
xRegisterDump.ulEAR = mfear();
|
||||
xRegisterDump.ulESR = mfesr();
|
||||
xRegisterDump.ulEDR = mfedr();
|
||||
|
||||
/* Move the saved program counter back to the instruction that was executed
|
||||
when the exception occurred. This is only valid for certain types of
|
||||
exception. */
|
||||
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_exceptions - portexINSTRUCTION_SIZE;
|
||||
/* Move the saved program counter back to the instruction that was executed
|
||||
* when the exception occurred. This is only valid for certain types of
|
||||
* exception. */
|
||||
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_exceptions - portexINSTRUCTION_SIZE;
|
||||
|
||||
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
{
|
||||
xRegisterDump.ulFSR = mffsr();
|
||||
}
|
||||
#else
|
||||
{
|
||||
xRegisterDump.ulFSR = 0UL;
|
||||
}
|
||||
#endif
|
||||
#if ( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
{
|
||||
xRegisterDump.ulFSR = mffsr();
|
||||
}
|
||||
#else
|
||||
{
|
||||
xRegisterDump.ulFSR = 0UL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Also fill in a string that describes what type of exception this is.
|
||||
The string uses the same ID names as defined in the MicroBlaze standard
|
||||
library exception header files. */
|
||||
switch( ( uint32_t ) pvExceptionID )
|
||||
{
|
||||
case XEXC_ID_FSL :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FSL";
|
||||
break;
|
||||
/* Also fill in a string that describes what type of exception this is.
|
||||
* The string uses the same ID names as defined in the MicroBlaze standard
|
||||
* library exception header files. */
|
||||
switch( ( uint32_t ) pvExceptionID )
|
||||
{
|
||||
case XEXC_ID_FSL:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FSL";
|
||||
break;
|
||||
|
||||
case XEXC_ID_UNALIGNED_ACCESS :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_UNALIGNED_ACCESS";
|
||||
break;
|
||||
case XEXC_ID_UNALIGNED_ACCESS:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_UNALIGNED_ACCESS";
|
||||
break;
|
||||
|
||||
case XEXC_ID_ILLEGAL_OPCODE :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_ILLEGAL_OPCODE";
|
||||
break;
|
||||
case XEXC_ID_ILLEGAL_OPCODE:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_ILLEGAL_OPCODE";
|
||||
break;
|
||||
|
||||
case XEXC_ID_M_AXI_I_EXCEPTION :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_M_AXI_I_EXCEPTION or XEXC_ID_IPLB_EXCEPTION";
|
||||
break;
|
||||
case XEXC_ID_M_AXI_I_EXCEPTION:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_M_AXI_I_EXCEPTION or XEXC_ID_IPLB_EXCEPTION";
|
||||
break;
|
||||
|
||||
case XEXC_ID_M_AXI_D_EXCEPTION :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_M_AXI_D_EXCEPTION or XEXC_ID_DPLB_EXCEPTION";
|
||||
break;
|
||||
case XEXC_ID_M_AXI_D_EXCEPTION:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_M_AXI_D_EXCEPTION or XEXC_ID_DPLB_EXCEPTION";
|
||||
break;
|
||||
|
||||
case XEXC_ID_DIV_BY_ZERO :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_DIV_BY_ZERO";
|
||||
break;
|
||||
case XEXC_ID_DIV_BY_ZERO:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_DIV_BY_ZERO";
|
||||
break;
|
||||
|
||||
case XEXC_ID_STACK_VIOLATION :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_STACK_VIOLATION or XEXC_ID_MMU";
|
||||
break;
|
||||
case XEXC_ID_STACK_VIOLATION:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_STACK_VIOLATION or XEXC_ID_MMU";
|
||||
break;
|
||||
|
||||
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
#if ( XPAR_MICROBLAZE_USE_FPU != 0 )
|
||||
case XEXC_ID_FPU:
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FPU see ulFSR value";
|
||||
break;
|
||||
#endif /* XPAR_MICROBLAZE_USE_FPU */
|
||||
}
|
||||
|
||||
case XEXC_ID_FPU :
|
||||
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FPU see ulFSR value";
|
||||
break;
|
||||
/* vApplicationExceptionRegisterDump() is a callback function that the
|
||||
* application can optionally define to receive the populated xPortRegisterDump
|
||||
* structure. If the application chooses not to define a version of
|
||||
* vApplicationExceptionRegisterDump() then the weekly defined default
|
||||
* implementation within this file will be called instead. */
|
||||
vApplicationExceptionRegisterDump( &xRegisterDump );
|
||||
|
||||
#endif /* XPAR_MICROBLAZE_USE_FPU */
|
||||
}
|
||||
|
||||
/* vApplicationExceptionRegisterDump() is a callback function that the
|
||||
application can optionally define to receive the populated xPortRegisterDump
|
||||
structure. If the application chooses not to define a version of
|
||||
vApplicationExceptionRegisterDump() then the weekly defined default
|
||||
implementation within this file will be called instead. */
|
||||
vApplicationExceptionRegisterDump( &xRegisterDump );
|
||||
|
||||
/* Must not attempt to leave this function! */
|
||||
for( ;; )
|
||||
{
|
||||
portNOP();
|
||||
}
|
||||
}
|
||||
/* Must not attempt to leave this function! */
|
||||
for( ; ; )
|
||||
{
|
||||
portNOP();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExceptionsInstallHandlers( void )
|
||||
{
|
||||
static uint32_t ulHandlersAlreadyInstalled = pdFALSE;
|
||||
void vPortExceptionsInstallHandlers( void )
|
||||
{
|
||||
static uint32_t ulHandlersAlreadyInstalled = pdFALSE;
|
||||
|
||||
if( ulHandlersAlreadyInstalled == pdFALSE )
|
||||
{
|
||||
ulHandlersAlreadyInstalled = pdTRUE;
|
||||
if( ulHandlersAlreadyInstalled == pdFALSE )
|
||||
{
|
||||
ulHandlersAlreadyInstalled = pdTRUE;
|
||||
|
||||
#if XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_UNALIGNED_ACCESS, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_UNALIGNED_ACCESS );
|
||||
#endif /* XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS*/
|
||||
#if XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_UNALIGNED_ACCESS, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_UNALIGNED_ACCESS );
|
||||
#endif /* XPAR_MICROBLAZE_UNALIGNED_EXCEPTIONS*/
|
||||
|
||||
#if XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_ILLEGAL_OPCODE, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_ILLEGAL_OPCODE );
|
||||
#endif /* XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_ILLEGAL_OPCODE, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_ILLEGAL_OPCODE );
|
||||
#endif /* XPAR_MICROBLAZE_ILL_OPCODE_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_M_AXI_I_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_I_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_M_AXI_I_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_I_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_M_AXI_I_BUS_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_M_AXI_D_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_D_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_M_AXI_D_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_M_AXI_D_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_M_AXI_D_BUS_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_IPLB_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_IPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_IPLB_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_IPLB_BUS_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_IPLB_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_IPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_IPLB_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_IPLB_BUS_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_DPLB_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_DPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DPLB_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_DPLB_BUS_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_DPLB_BUS_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_DPLB_EXCEPTION, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DPLB_EXCEPTION );
|
||||
#endif /* XPAR_MICROBLAZE_DPLB_BUS_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_DIV_BY_ZERO, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DIV_BY_ZERO );
|
||||
#endif /* XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_DIV_BY_ZERO, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_DIV_BY_ZERO );
|
||||
#endif /* XPAR_MICROBLAZE_DIV_ZERO_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_FPU_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_FPU, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FPU );
|
||||
#endif /* XPAR_MICROBLAZE_FPU_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_FPU_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_FPU, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FPU );
|
||||
#endif /* XPAR_MICROBLAZE_FPU_EXCEPTION */
|
||||
|
||||
#if XPAR_MICROBLAZE_FSL_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_FSL, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FSL );
|
||||
#endif /* XPAR_MICROBLAZE_FSL_EXCEPTION */
|
||||
#if XPAR_MICROBLAZE_FSL_EXCEPTION == 1
|
||||
microblaze_register_exception_handler( XEXC_ID_FSL, vPortExceptionHandlerEntry, ( void * ) XEXC_ID_FSL );
|
||||
#endif /* XPAR_MICROBLAZE_FSL_EXCEPTION */
|
||||
|
||||
microblaze_enable_exceptions();
|
||||
}
|
||||
}
|
||||
microblaze_enable_exceptions();
|
||||
}
|
||||
}
|
||||
|
||||
/* Exclude the entire file if the MicroBlaze is not configured to handle
|
||||
exceptions, or the application defined configuration item
|
||||
configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||
* exceptions, or the application defined configuration item
|
||||
* configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||
#endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,15 +25,15 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* BSP includes. */
|
||||
#include <mb_interface.h>
|
||||
#include <xparameters.h>
|
||||
#include <mb_interface.h>
|
||||
#include <xparameters.h>
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -46,175 +46,177 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros and functions. */
|
||||
void microblaze_disable_interrupts( void );
|
||||
void microblaze_enable_interrupts( void );
|
||||
#define portDISABLE_INTERRUPTS() microblaze_disable_interrupts()
|
||||
#define portENABLE_INTERRUPTS() microblaze_enable_interrupts()
|
||||
void microblaze_disable_interrupts( void );
|
||||
void microblaze_enable_interrupts( void );
|
||||
#define portDISABLE_INTERRUPTS() microblaze_disable_interrupts()
|
||||
#define portENABLE_INTERRUPTS() microblaze_enable_interrupts()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section macros. */
|
||||
void vPortEnterCritical( void );
|
||||
void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() { \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
microblaze_disable_interrupts(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
void vPortEnterCritical( void );
|
||||
void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
microblaze_disable_interrupts(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() { \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
/* Interrupts are disabled, so we can */ \
|
||||
/* access the variable directly. */ \
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
/* The nesting has unwound and we \
|
||||
can enable interrupts again. */ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
/* Interrupts are disabled, so we can */ \
|
||||
/* access the variable directly. */ \
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
/* The nesting has unwound and we \
|
||||
* can enable interrupts again. */ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The yield macro maps directly to the vPortYield() function. */
|
||||
void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
/* portYIELD_FROM_ISR() does not directly call vTaskSwitchContext(), but instead
|
||||
sets a flag to say that a yield has been requested. The interrupt exit code
|
||||
then checks this flag, and calls vTaskSwitchContext() before restoring a task
|
||||
context, if the flag is not false. This is done to prevent multiple calls to
|
||||
vTaskSwitchContext() being made from a single interrupt, as a single interrupt
|
||||
can result in multiple peripherals being serviced. */
|
||||
extern volatile uint32_t ulTaskSwitchRequested;
|
||||
#define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) ulTaskSwitchRequested = 1
|
||||
* sets a flag to say that a yield has been requested. The interrupt exit code
|
||||
* then checks this flag, and calls vTaskSwitchContext() before restoring a task
|
||||
* context, if the flag is not false. This is done to prevent multiple calls to
|
||||
* vTaskSwitchContext() being made from a single interrupt, as a single interrupt
|
||||
* can result in multiple peripherals being serviced. */
|
||||
extern volatile uint32_t ulTaskSwitchRequested;
|
||||
#define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) ulTaskSwitchRequested = 1
|
||||
|
||||
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
|
||||
return ucReturn;
|
||||
}
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( 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
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* 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 ) )
|
||||
/* 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 = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The following structure is used by the FreeRTOS exception handler. It is
|
||||
filled with the MicroBlaze context as it was at the time the exception occurred.
|
||||
This is done as an aid to debugging exception occurrences. */
|
||||
typedef struct PORT_REGISTER_DUMP
|
||||
{
|
||||
/* The following structure members hold the values of the MicroBlaze
|
||||
registers at the time the exception was raised. */
|
||||
uint32_t ulR1_SP;
|
||||
uint32_t ulR2_small_data_area;
|
||||
uint32_t ulR3;
|
||||
uint32_t ulR4;
|
||||
uint32_t ulR5;
|
||||
uint32_t ulR6;
|
||||
uint32_t ulR7;
|
||||
uint32_t ulR8;
|
||||
uint32_t ulR9;
|
||||
uint32_t ulR10;
|
||||
uint32_t ulR11;
|
||||
uint32_t ulR12;
|
||||
uint32_t ulR13_read_write_small_data_area;
|
||||
uint32_t ulR14_return_address_from_interrupt;
|
||||
uint32_t ulR15_return_address_from_subroutine;
|
||||
uint32_t ulR16_return_address_from_trap;
|
||||
uint32_t ulR17_return_address_from_exceptions; /* The exception entry code will copy the BTR into R17 if the exception occurred in the delay slot of a branch instruction. */
|
||||
uint32_t ulR18;
|
||||
uint32_t ulR19;
|
||||
uint32_t ulR20;
|
||||
uint32_t ulR21;
|
||||
uint32_t ulR22;
|
||||
uint32_t ulR23;
|
||||
uint32_t ulR24;
|
||||
uint32_t ulR25;
|
||||
uint32_t ulR26;
|
||||
uint32_t ulR27;
|
||||
uint32_t ulR28;
|
||||
uint32_t ulR29;
|
||||
uint32_t ulR30;
|
||||
uint32_t ulR31;
|
||||
uint32_t ulPC;
|
||||
uint32_t ulESR;
|
||||
uint32_t ulMSR;
|
||||
uint32_t ulEAR;
|
||||
uint32_t ulFSR;
|
||||
uint32_t ulEDR;
|
||||
* filled with the MicroBlaze context as it was at the time the exception occurred.
|
||||
* This is done as an aid to debugging exception occurrences. */
|
||||
typedef struct PORT_REGISTER_DUMP
|
||||
{
|
||||
/* The following structure members hold the values of the MicroBlaze
|
||||
* registers at the time the exception was raised. */
|
||||
uint32_t ulR1_SP;
|
||||
uint32_t ulR2_small_data_area;
|
||||
uint32_t ulR3;
|
||||
uint32_t ulR4;
|
||||
uint32_t ulR5;
|
||||
uint32_t ulR6;
|
||||
uint32_t ulR7;
|
||||
uint32_t ulR8;
|
||||
uint32_t ulR9;
|
||||
uint32_t ulR10;
|
||||
uint32_t ulR11;
|
||||
uint32_t ulR12;
|
||||
uint32_t ulR13_read_write_small_data_area;
|
||||
uint32_t ulR14_return_address_from_interrupt;
|
||||
uint32_t ulR15_return_address_from_subroutine;
|
||||
uint32_t ulR16_return_address_from_trap;
|
||||
uint32_t ulR17_return_address_from_exceptions; /* The exception entry code will copy the BTR into R17 if the exception occurred in the delay slot of a branch instruction. */
|
||||
uint32_t ulR18;
|
||||
uint32_t ulR19;
|
||||
uint32_t ulR20;
|
||||
uint32_t ulR21;
|
||||
uint32_t ulR22;
|
||||
uint32_t ulR23;
|
||||
uint32_t ulR24;
|
||||
uint32_t ulR25;
|
||||
uint32_t ulR26;
|
||||
uint32_t ulR27;
|
||||
uint32_t ulR28;
|
||||
uint32_t ulR29;
|
||||
uint32_t ulR30;
|
||||
uint32_t ulR31;
|
||||
uint32_t ulPC;
|
||||
uint32_t ulESR;
|
||||
uint32_t ulMSR;
|
||||
uint32_t ulEAR;
|
||||
uint32_t ulFSR;
|
||||
uint32_t ulEDR;
|
||||
|
||||
/* A human readable description of the exception cause. The strings used
|
||||
are the same as the #define constant names found in the
|
||||
microblaze_exceptions_i.h header file */
|
||||
int8_t *pcExceptionCause;
|
||||
/* A human readable description of the exception cause. The strings used
|
||||
* are the same as the #define constant names found in the
|
||||
* microblaze_exceptions_i.h header file */
|
||||
int8_t * pcExceptionCause;
|
||||
|
||||
/* The human readable name of the task that was running at the time the
|
||||
exception occurred. This is the name that was given to the task when the
|
||||
task was created using the FreeRTOS xTaskCreate() API function. */
|
||||
char *pcCurrentTaskName;
|
||||
/* The human readable name of the task that was running at the time the
|
||||
* exception occurred. This is the name that was given to the task when the
|
||||
* task was created using the FreeRTOS xTaskCreate() API function. */
|
||||
char * pcCurrentTaskName;
|
||||
|
||||
/* The handle of the task that was running a the time the exception
|
||||
occurred. */
|
||||
void * xCurrentTaskHandle;
|
||||
|
||||
} xPortRegisterDump;
|
||||
/* The handle of the task that was running a the time the exception
|
||||
* occurred. */
|
||||
void * xCurrentTaskHandle;
|
||||
} xPortRegisterDump;
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -252,7 +254,9 @@ typedef struct PORT_REGISTER_DUMP
|
|||
* pdPASS is returned if the function executes successfully. Any other value
|
||||
* being returned indicates that the function did not execute correctly.
|
||||
*/
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef );
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID,
|
||||
XInterruptHandler pxHandler,
|
||||
void * pvCallBackRef );
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -273,7 +277,7 @@ BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandle
|
|||
* XPAR_INTC_0_GPIO_1_VEC_ID - for the button inputs.
|
||||
*
|
||||
*/
|
||||
void vPortEnableInterrupt( uint8_t ucInterruptID );
|
||||
void vPortEnableInterrupt( uint8_t ucInterruptID );
|
||||
|
||||
/*
|
||||
* Disables the interrupt, within the interrupt controller, for the peripheral
|
||||
|
|
@ -293,7 +297,7 @@ void vPortEnableInterrupt( uint8_t ucInterruptID );
|
|||
* XPAR_INTC_0_GPIO_1_VEC_ID - for the button inputs.
|
||||
*
|
||||
*/
|
||||
void vPortDisableInterrupt( uint8_t ucInterruptID );
|
||||
void vPortDisableInterrupt( uint8_t ucInterruptID );
|
||||
|
||||
/*
|
||||
* This is an application defined callback function used to install the tick
|
||||
|
|
@ -305,7 +309,7 @@ void vPortDisableInterrupt( uint8_t ucInterruptID );
|
|||
* The name of the interrupt handler that should be installed is vPortTickISR(),
|
||||
* which the function below declares as an extern.
|
||||
*/
|
||||
void vApplicationSetupTimerInterrupt( void );
|
||||
void vApplicationSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* This is an application defined callback function used to clear whichever
|
||||
|
|
@ -318,7 +322,7 @@ void vApplicationSetupTimerInterrupt( void );
|
|||
* implementation should not require modification provided the example definition
|
||||
* of vApplicationSetupTimerInterrupt() is also not modified.
|
||||
*/
|
||||
void vApplicationClearTimerInterrupt( void );
|
||||
void vApplicationClearTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* vPortExceptionsInstallHandlers() is only available when the MicroBlaze
|
||||
|
|
@ -341,7 +345,7 @@ void vApplicationClearTimerInterrupt( void );
|
|||
* See the description of vApplicationExceptionRegisterDump() for information
|
||||
* on the processing performed by the FreeRTOS exception handler.
|
||||
*/
|
||||
void vPortExceptionsInstallHandlers( void );
|
||||
void vPortExceptionsInstallHandlers( void );
|
||||
|
||||
/*
|
||||
* The FreeRTOS exception handler fills an xPortRegisterDump structure (defined
|
||||
|
|
@ -357,12 +361,11 @@ void vPortExceptionsInstallHandlers( void );
|
|||
* register dump information. For example, an implementation could be provided
|
||||
* that wrote the register dump data to a display, or a UART port.
|
||||
*/
|
||||
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump );
|
||||
void vApplicationExceptionRegisterDump( xPortRegisterDump * xRegisterDump );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the NIOS2 port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the NIOS2 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Standard Includes. */
|
||||
#include <string.h>
|
||||
|
|
@ -42,11 +42,11 @@
|
|||
#include "task.h"
|
||||
|
||||
/* Interrupts are enabled. */
|
||||
#define portINITIAL_ESTATUS ( StackType_t ) 0x01
|
||||
#define portINITIAL_ESTATUS ( StackType_t ) 0x01
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
|
@ -54,77 +54,80 @@ static void prvSetupTimerInterrupt( void );
|
|||
/*
|
||||
* Call back for the alarm function.
|
||||
*/
|
||||
void vPortSysTickHandler( void * context, alt_u32 id );
|
||||
void vPortSysTickHandler( void * context,
|
||||
alt_u32 id );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvReadGp( uint32_t *ulValue )
|
||||
static void prvReadGp( uint32_t * ulValue )
|
||||
{
|
||||
asm( "stw gp, (%0)" :: "r"(ulValue) );
|
||||
asm ( "stw gp, (%0)" ::"r" ( ulValue ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxFramePointer = pxTopOfStack - 1;
|
||||
StackType_t xGlobalPointer;
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
StackType_t * pxFramePointer = pxTopOfStack - 1;
|
||||
StackType_t xGlobalPointer;
|
||||
|
||||
prvReadGp( &xGlobalPointer );
|
||||
prvReadGp( &xGlobalPointer );
|
||||
|
||||
/* End of stack marker. */
|
||||
*pxTopOfStack = 0xdeadbeef;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) pxFramePointer;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) pxFramePointer;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = xGlobalPointer;
|
||||
|
||||
|
||||
*pxTopOfStack = xGlobalPointer;
|
||||
|
||||
/* Space for R23 to R16. */
|
||||
pxTopOfStack -= 9;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = portINITIAL_ESTATUS;
|
||||
*pxTopOfStack = portINITIAL_ESTATUS;
|
||||
|
||||
/* Space for R15 to R5. */
|
||||
/* Space for R15 to R5. */
|
||||
pxTopOfStack -= 12;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
|
||||
/* Space for R3 to R1, muldiv and RA. */
|
||||
pxTopOfStack -= 5;
|
||||
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
asm volatile ( " movia r2, restore_sp_from_pxCurrentTCB \n"
|
||||
" jmp r2 " );
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
/* Start the first task. */
|
||||
asm volatile ( " movia r2, restore_sp_from_pxCurrentTCB \n"
|
||||
" jmp r2 " );
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the NIOS2 port will require this function as there
|
||||
is nothing to return to. */
|
||||
/* It is unlikely that the NIOS2 port will require this function as there
|
||||
* is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -134,69 +137,71 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Try to register the interrupt handler. */
|
||||
if ( -EINVAL == alt_irq_register( SYS_CLK_IRQ, 0x0, vPortSysTickHandler ) )
|
||||
{
|
||||
/* Failed to install the Interrupt Handler. */
|
||||
asm( "break" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK );
|
||||
IOWR_ALTERA_AVALON_TIMER_PERIODL( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) & 0xFFFF );
|
||||
IOWR_ALTERA_AVALON_TIMER_PERIODH( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) >> 16 );
|
||||
IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_CONT_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK | ALTERA_AVALON_TIMER_CONTROL_ITO_MSK );
|
||||
}
|
||||
/* Try to register the interrupt handler. */
|
||||
if( -EINVAL == alt_irq_register( SYS_CLK_IRQ, 0x0, vPortSysTickHandler ) )
|
||||
{
|
||||
/* Failed to install the Interrupt Handler. */
|
||||
asm ( "break" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK );
|
||||
IOWR_ALTERA_AVALON_TIMER_PERIODL( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) & 0xFFFF );
|
||||
IOWR_ALTERA_AVALON_TIMER_PERIODH( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) >> 16 );
|
||||
IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_CONT_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK | ALTERA_AVALON_TIMER_CONTROL_ITO_MSK );
|
||||
}
|
||||
|
||||
/* Clear any already pending interrupts generated by the Timer. */
|
||||
IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
|
||||
/* Clear any already pending interrupts generated by the Timer. */
|
||||
IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSysTickHandler( void * context, alt_u32 id )
|
||||
void vPortSysTickHandler( void * context,
|
||||
alt_u32 id )
|
||||
{
|
||||
/* Increment the kernel tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Increment the kernel tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Clear the interrupt. */
|
||||
IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
|
||||
}
|
||||
|
||||
/* Clear the interrupt. */
|
||||
IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/** This function is a re-implementation of the Altera provided function.
|
||||
* The function is re-implemented to prevent it from enabling an interrupt
|
||||
* when it is registered. Interrupts should only be enabled after the FreeRTOS.org
|
||||
* kernel has its scheduler started so that contexts are saved and switched
|
||||
* kernel has its scheduler started so that contexts are saved and switched
|
||||
* correctly.
|
||||
*/
|
||||
int alt_irq_register( alt_u32 id, void* context, void (*handler)(void*, alt_u32) )
|
||||
int alt_irq_register( alt_u32 id,
|
||||
void * context,
|
||||
void ( * handler )( void *, alt_u32 ) )
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
alt_irq_context status;
|
||||
int rc = -EINVAL;
|
||||
alt_irq_context status;
|
||||
|
||||
if (id < ALT_NIRQ)
|
||||
{
|
||||
/*
|
||||
* interrupts are disabled while the handler tables are updated to ensure
|
||||
* that an interrupt doesn't occur while the tables are in an inconsistent
|
||||
* state.
|
||||
*/
|
||||
|
||||
status = alt_irq_disable_all ();
|
||||
|
||||
alt_irq[id].handler = handler;
|
||||
alt_irq[id].context = context;
|
||||
|
||||
rc = (handler) ? alt_irq_enable (id): alt_irq_disable (id);
|
||||
|
||||
/* alt_irq_enable_all(status); This line is removed to prevent the interrupt from being immediately enabled. */
|
||||
}
|
||||
|
||||
return rc;
|
||||
if( id < ALT_NIRQ )
|
||||
{
|
||||
/*
|
||||
* interrupts are disabled while the handler tables are updated to ensure
|
||||
* that an interrupt doesn't occur while the tables are in an inconsistent
|
||||
* state.
|
||||
*/
|
||||
|
||||
status = alt_irq_disable_all();
|
||||
|
||||
alt_irq[ id ].handler = handler;
|
||||
alt_irq[ id ].context = context;
|
||||
|
||||
rc = ( handler ) ? alt_irq_enable( id ) : alt_irq_disable( id );
|
||||
|
||||
/* alt_irq_enable_all(status); This line is removed to prevent the interrupt from being immediately enabled. */
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sys/alt_irq.h"
|
||||
#include "sys/alt_irq.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -44,65 +44,64 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
#define portCRITICAL_NESTING_IN_TCB 1
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
#define portCRITICAL_NESTING_IN_TCB 1
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD() asm volatile ( "trap" );
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD() asm volatile ( "trap" );
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()
|
||||
|
||||
|
||||
/* Include the port_asm.S file where the Context saving/restoring is defined. */
|
||||
__asm__( "\n\t.globl save_context" );
|
||||
__asm__ ( "\n\t.globl save_context");
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() alt_irq_disable_all()
|
||||
#define portENABLE_INTERRUPTS() alt_irq_enable_all( 0x01 );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
#define portDISABLE_INTERRUPTS() alt_irq_disable_all()
|
||||
#define portENABLE_INTERRUPTS() alt_irq_enable_all( 0x01 );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,20 +25,19 @@
|
|||
*/
|
||||
|
||||
/* When switching out a task, if the task tag contains a buffer address then
|
||||
save the flop context into the buffer. */
|
||||
#define traceTASK_SWITCHED_OUT() \
|
||||
if( pxCurrentTCB->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
extern void vPortSaveFPURegisters( void * ); \
|
||||
vPortSaveFPURegisters( ( void * ) ( pxCurrentTCB->pxTaskTag ) ); \
|
||||
}
|
||||
* save the flop context into the buffer. */
|
||||
#define traceTASK_SWITCHED_OUT() \
|
||||
if( pxCurrentTCB->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
extern void vPortSaveFPURegisters( void * ); \
|
||||
vPortSaveFPURegisters( ( void * ) ( pxCurrentTCB->pxTaskTag ) ); \
|
||||
}
|
||||
|
||||
/* When switching in a task, if the task tag contains a buffer address then
|
||||
load the flop context from the buffer. */
|
||||
#define traceTASK_SWITCHED_IN() \
|
||||
if( pxCurrentTCB->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
extern void vPortRestoreFPURegisters( void * ); \
|
||||
vPortRestoreFPURegisters( ( void * ) ( pxCurrentTCB->pxTaskTag ) ); \
|
||||
}
|
||||
|
||||
* load the flop context from the buffer. */
|
||||
#define traceTASK_SWITCHED_IN() \
|
||||
if( pxCurrentTCB->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
extern void vPortRestoreFPURegisters( void * ); \
|
||||
vPortRestoreFPURegisters( ( void * ) ( pxCurrentTCB->pxTaskTag ) ); \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the PPC405 port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the PPC405 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
|
|
@ -41,19 +41,19 @@
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Definitions to set the initial MSR of each task. */
|
||||
#define portCRITICAL_INTERRUPT_ENABLE ( 1UL << 17UL )
|
||||
#define portEXTERNAL_INTERRUPT_ENABLE ( 1UL << 15UL )
|
||||
#define portMACHINE_CHECK_ENABLE ( 1UL << 12UL )
|
||||
#define portCRITICAL_INTERRUPT_ENABLE ( 1UL << 17UL )
|
||||
#define portEXTERNAL_INTERRUPT_ENABLE ( 1UL << 15UL )
|
||||
#define portMACHINE_CHECK_ENABLE ( 1UL << 12UL )
|
||||
|
||||
#if configUSE_FPU == 1
|
||||
#define portAPU_PRESENT ( 1UL << 25UL )
|
||||
#define portFCM_FPU_PRESENT ( 1UL << 13UL )
|
||||
#define portAPU_PRESENT ( 1UL << 25UL )
|
||||
#define portFCM_FPU_PRESENT ( 1UL << 13UL )
|
||||
#else
|
||||
#define portAPU_PRESENT ( 0UL )
|
||||
#define portFCM_FPU_PRESENT ( 0UL )
|
||||
#define portAPU_PRESENT ( 0UL )
|
||||
#define portFCM_FPU_PRESENT ( 0UL )
|
||||
#endif
|
||||
|
||||
#define portINITIAL_MSR ( portCRITICAL_INTERRUPT_ENABLE | portEXTERNAL_INTERRUPT_ENABLE | portMACHINE_CHECK_ENABLE | portAPU_PRESENT | portFCM_FPU_PRESENT )
|
||||
#define portINITIAL_MSR ( portCRITICAL_INTERRUPT_ENABLE | portEXTERNAL_INTERRUPT_ENABLE | portMACHINE_CHECK_ENABLE | portAPU_PRESENT | portFCM_FPU_PRESENT )
|
||||
|
||||
|
||||
extern const unsigned _SDA_BASE_;
|
||||
|
|
@ -89,171 +89,177 @@ static XIntc xInterruptController;
|
|||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if the task had been
|
||||
* interrupted.
|
||||
*
|
||||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Place a known value at the bottom of the stack for debugging. */
|
||||
*pxTopOfStack = 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
/* Place a known value at the bottom of the stack for debugging. */
|
||||
*pxTopOfStack = 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* EABI stack frame. */
|
||||
pxTopOfStack -= 20; /* Previous backchain and LR, R31 to R4 inclusive. */
|
||||
/* EABI stack frame. */
|
||||
pxTopOfStack -= 20; /* Previous backchain and LR, R31 to R4 inclusive. */
|
||||
|
||||
/* Parameters in R13. */
|
||||
*pxTopOfStack = ( StackType_t ) &_SDA_BASE_; /* address of the first small data area */
|
||||
pxTopOfStack -= 10;
|
||||
/* Parameters in R13. */
|
||||
*pxTopOfStack = ( StackType_t ) &_SDA_BASE_; /* address of the first small data area */
|
||||
pxTopOfStack -= 10;
|
||||
|
||||
/* Parameters in R3. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
/* Parameters in R3. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Parameters in R2. */
|
||||
*pxTopOfStack = ( StackType_t ) &_SDA2_BASE_; /* address of the second small data area */
|
||||
pxTopOfStack--;
|
||||
/* Parameters in R2. */
|
||||
*pxTopOfStack = ( StackType_t ) &_SDA2_BASE_; /* address of the second small data area */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* R1 is the stack pointer so is omitted. */
|
||||
/* R1 is the stack pointer so is omitted. */
|
||||
|
||||
*pxTopOfStack = 0x10000001UL;; /* R0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* USPRG0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* CR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* XER. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* CTR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) vPortEndScheduler; /* LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* SRR0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_MSR;/* SRR1. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) vPortEndScheduler;/* Next LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL;/* Backchain. */
|
||||
*pxTopOfStack = 0x10000001UL; /* R0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* USPRG0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* CR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* XER. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* CTR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) vPortEndScheduler; /* LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* SRR0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_MSR; /* SRR1. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) vPortEndScheduler; /* Next LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* Backchain. */
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
prvSetupTimerInterrupt();
|
||||
XExc_RegisterHandler( XEXC_ID_SYSTEM_CALL, ( XExceptionHandler ) vPortYield, ( void * ) 0 );
|
||||
vPortStartFirstTask();
|
||||
prvSetupTimerInterrupt();
|
||||
XExc_RegisterHandler( XEXC_ID_SYSTEM_CALL, ( XExceptionHandler ) vPortYield, ( void * ) 0 );
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented. */
|
||||
for( ;; );
|
||||
/* Not implemented. */
|
||||
for( ; ; )
|
||||
{
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Hardware initialisation to generate the RTOS tick.
|
||||
* Hardware initialisation to generate the RTOS tick.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
const uint32_t ulInterval = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
|
||||
const uint32_t ulInterval = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
|
||||
|
||||
XTime_PITClearInterrupt();
|
||||
XTime_FITClearInterrupt();
|
||||
XTime_WDTClearInterrupt();
|
||||
XTime_WDTDisableInterrupt();
|
||||
XTime_FITDisableInterrupt();
|
||||
XTime_PITClearInterrupt();
|
||||
XTime_FITClearInterrupt();
|
||||
XTime_WDTClearInterrupt();
|
||||
XTime_WDTDisableInterrupt();
|
||||
XTime_FITDisableInterrupt();
|
||||
|
||||
XExc_RegisterHandler( XEXC_ID_PIT_INT, ( XExceptionHandler ) vPortTickISR, ( void * ) 0 );
|
||||
XExc_RegisterHandler( XEXC_ID_PIT_INT, ( XExceptionHandler ) vPortTickISR, ( void * ) 0 );
|
||||
|
||||
XTime_PITEnableAutoReload();
|
||||
XTime_PITSetInterval( ulInterval );
|
||||
XTime_PITEnableInterrupt();
|
||||
XTime_PITEnableAutoReload();
|
||||
XTime_PITSetInterval( ulInterval );
|
||||
XTime_PITEnableInterrupt();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRHandler( void *pvNullDoNotUse )
|
||||
void vPortISRHandler( void * pvNullDoNotUse )
|
||||
{
|
||||
uint32_t ulInterruptStatus, ulInterruptMask = 1UL;
|
||||
BaseType_t xInterruptNumber;
|
||||
XIntc_Config *pxInterruptController;
|
||||
XIntc_VectorTableEntry *pxTable;
|
||||
uint32_t ulInterruptStatus, ulInterruptMask = 1UL;
|
||||
BaseType_t xInterruptNumber;
|
||||
XIntc_Config * pxInterruptController;
|
||||
XIntc_VectorTableEntry * pxTable;
|
||||
|
||||
/* Just to remove compiler warning. */
|
||||
( void ) pvNullDoNotUse;
|
||||
/* Just to remove compiler warning. */
|
||||
( void ) pvNullDoNotUse;
|
||||
|
||||
/* Get the configuration by using the device ID - in this case it is
|
||||
assumed that only one interrupt controller is being used. */
|
||||
pxInterruptController = &XIntc_ConfigTable[ XPAR_XPS_INTC_0_DEVICE_ID ];
|
||||
|
||||
/* Which interrupts are pending? */
|
||||
ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );
|
||||
|
||||
for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ )
|
||||
{
|
||||
if( ulInterruptStatus & 0x01UL )
|
||||
{
|
||||
/* Clear the pending interrupt. */
|
||||
XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask );
|
||||
/* Get the configuration by using the device ID - in this case it is
|
||||
* assumed that only one interrupt controller is being used. */
|
||||
pxInterruptController = &XIntc_ConfigTable[ XPAR_XPS_INTC_0_DEVICE_ID ];
|
||||
|
||||
/* Call the registered handler. */
|
||||
pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );
|
||||
pxTable->Handler( pxTable->CallBackRef );
|
||||
}
|
||||
|
||||
/* Check the next interrupt. */
|
||||
ulInterruptMask <<= 0x01UL;
|
||||
ulInterruptStatus >>= 0x01UL;
|
||||
/* Which interrupts are pending? */
|
||||
ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );
|
||||
|
||||
/* Have we serviced all interrupts? */
|
||||
if( ulInterruptStatus == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ )
|
||||
{
|
||||
if( ulInterruptStatus & 0x01UL )
|
||||
{
|
||||
/* Clear the pending interrupt. */
|
||||
XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask );
|
||||
|
||||
/* Call the registered handler. */
|
||||
pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );
|
||||
pxTable->Handler( pxTable->CallBackRef );
|
||||
}
|
||||
|
||||
/* Check the next interrupt. */
|
||||
ulInterruptMask <<= 0x01UL;
|
||||
ulInterruptStatus >>= 0x01UL;
|
||||
|
||||
/* Have we serviced all interrupts? */
|
||||
if( ulInterruptStatus == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSetupInterruptController( void )
|
||||
{
|
||||
extern void vPortISRWrapper( void );
|
||||
extern void vPortISRWrapper( void );
|
||||
|
||||
/* Perform all library calls necessary to initialise the exception table
|
||||
and interrupt controller. This assumes only one interrupt controller is in
|
||||
use. */
|
||||
XExc_mDisableExceptions( XEXC_NON_CRITICAL );
|
||||
XExc_Init();
|
||||
/* Perform all library calls necessary to initialise the exception table
|
||||
* and interrupt controller. This assumes only one interrupt controller is in
|
||||
* use. */
|
||||
XExc_mDisableExceptions( XEXC_NON_CRITICAL );
|
||||
XExc_Init();
|
||||
|
||||
/* The library functions save the context - we then jump to a wrapper to
|
||||
save the stack into the TCB. The wrapper then calls the handler defined
|
||||
above. */
|
||||
XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, ( XExceptionHandler ) vPortISRWrapper, NULL );
|
||||
XIntc_Initialize( &xInterruptController, XPAR_XPS_INTC_0_DEVICE_ID );
|
||||
XIntc_Start( &xInterruptController, XIN_REAL_MODE );
|
||||
/* The library functions save the context - we then jump to a wrapper to
|
||||
* save the stack into the TCB. The wrapper then calls the handler defined
|
||||
* above. */
|
||||
XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, ( XExceptionHandler ) vPortISRWrapper, NULL );
|
||||
XIntc_Initialize( &xInterruptController, XPAR_XPS_INTC_0_DEVICE_ID );
|
||||
XIntc_Start( &xInterruptController, XIN_REAL_MODE );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID,
|
||||
XInterruptHandler pxHandler,
|
||||
void * pvCallBackRef )
|
||||
{
|
||||
BaseType_t xReturn = pdFAIL;
|
||||
BaseType_t xReturn = pdFAIL;
|
||||
|
||||
/* This function is defined here so the scope of xInterruptController can
|
||||
remain within this file. */
|
||||
/* This function is defined here so the scope of xInterruptController can
|
||||
* remain within this file. */
|
||||
|
||||
if( XST_SUCCESS == XIntc_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef ) )
|
||||
{
|
||||
XIntc_Enable( &xInterruptController, ucInterruptID );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
if( XST_SUCCESS == XIntc_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef ) )
|
||||
{
|
||||
XIntc_Enable( &xInterruptController, ucInterruptID );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
return xReturn;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@
|
|||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#include "xexception_l.h"
|
||||
#include "xexception_l.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
|
|
@ -44,74 +44,75 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This port uses the critical nesting count from the TCB rather than
|
||||
maintaining a separate value and then saving this value in the task stack. */
|
||||
#define portCRITICAL_NESTING_IN_TCB 1
|
||||
* maintaining a separate value and then saving this value in the task stack. */
|
||||
#define portCRITICAL_NESTING_IN_TCB 1
|
||||
|
||||
/* Interrupt control macros. */
|
||||
#define portDISABLE_INTERRUPTS() XExc_mDisableExceptions( XEXC_NON_CRITICAL );
|
||||
#define portENABLE_INTERRUPTS() XExc_mEnableExceptions( XEXC_NON_CRITICAL );
|
||||
#define portDISABLE_INTERRUPTS() XExc_mDisableExceptions( XEXC_NON_CRITICAL );
|
||||
#define portENABLE_INTERRUPTS() XExc_mEnableExceptions( XEXC_NON_CRITICAL );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section macros. */
|
||||
void vTaskEnterCritical( void );
|
||||
void vTaskExitCritical( void );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
void vTaskEnterCritical( void );
|
||||
void vTaskExitCritical( void );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
void vPortYield( void );
|
||||
#define portYIELD() asm volatile ( "SC \n\t NOP" )
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
void vPortYield( void );
|
||||
#define portYIELD() asm volatile ( "SC \n\t NOP" )
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
|
||||
/* There are 32 * 32bit floating point regieters, plus the FPSCR to save. */
|
||||
#define portNO_FLOP_REGISTERS_TO_SAVE ( 32 + 1 )
|
||||
#define portNO_FLOP_REGISTERS_TO_SAVE ( 32 + 1 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( 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 )
|
||||
|
||||
/* Port specific interrupt handling functions. */
|
||||
void vPortSetupInterruptController( void );
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef );
|
||||
void vPortSetupInterruptController( void );
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID,
|
||||
XInterruptHandler pxHandler,
|
||||
void * pvCallBackRef );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,20 +25,19 @@
|
|||
*/
|
||||
|
||||
/* When switching out a task, if the task tag contains a buffer address then
|
||||
save the flop context into the buffer. */
|
||||
#define traceTASK_SWITCHED_OUT() \
|
||||
if( pxCurrentTCB->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
extern void vPortSaveFPURegisters( void * ); \
|
||||
vPortSaveFPURegisters( ( void * ) ( pxCurrentTCB->pxTaskTag ) ); \
|
||||
}
|
||||
* save the flop context into the buffer. */
|
||||
#define traceTASK_SWITCHED_OUT() \
|
||||
if( pxCurrentTCB->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
extern void vPortSaveFPURegisters( void * ); \
|
||||
vPortSaveFPURegisters( ( void * ) ( pxCurrentTCB->pxTaskTag ) ); \
|
||||
}
|
||||
|
||||
/* When switching in a task, if the task tag contains a buffer address then
|
||||
load the flop context from the buffer. */
|
||||
#define traceTASK_SWITCHED_IN() \
|
||||
if( pxCurrentTCB->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
extern void vPortRestoreFPURegisters( void * ); \
|
||||
vPortRestoreFPURegisters( ( void * ) ( pxCurrentTCB->pxTaskTag ) ); \
|
||||
}
|
||||
|
||||
* load the flop context from the buffer. */
|
||||
#define traceTASK_SWITCHED_IN() \
|
||||
if( pxCurrentTCB->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
extern void vPortRestoreFPURegisters( void * ); \
|
||||
vPortRestoreFPURegisters( ( void * ) ( pxCurrentTCB->pxTaskTag ) ); \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the PPC440 port.
|
||||
*----------------------------------------------------------*/
|
||||
* Implementation of functions defined in portable.h for the PPC440 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
|
|
@ -41,19 +41,19 @@
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Definitions to set the initial MSR of each task. */
|
||||
#define portCRITICAL_INTERRUPT_ENABLE ( 1UL << 17UL )
|
||||
#define portEXTERNAL_INTERRUPT_ENABLE ( 1UL << 15UL )
|
||||
#define portMACHINE_CHECK_ENABLE ( 1UL << 12UL )
|
||||
#define portCRITICAL_INTERRUPT_ENABLE ( 1UL << 17UL )
|
||||
#define portEXTERNAL_INTERRUPT_ENABLE ( 1UL << 15UL )
|
||||
#define portMACHINE_CHECK_ENABLE ( 1UL << 12UL )
|
||||
|
||||
#if configUSE_FPU == 1
|
||||
#define portAPU_PRESENT ( 1UL << 25UL )
|
||||
#define portFCM_FPU_PRESENT ( 1UL << 13UL )
|
||||
#define portAPU_PRESENT ( 1UL << 25UL )
|
||||
#define portFCM_FPU_PRESENT ( 1UL << 13UL )
|
||||
#else
|
||||
#define portAPU_PRESENT ( 0UL )
|
||||
#define portFCM_FPU_PRESENT ( 0UL )
|
||||
#define portAPU_PRESENT ( 0UL )
|
||||
#define portFCM_FPU_PRESENT ( 0UL )
|
||||
#endif
|
||||
|
||||
#define portINITIAL_MSR ( portCRITICAL_INTERRUPT_ENABLE | portEXTERNAL_INTERRUPT_ENABLE | portMACHINE_CHECK_ENABLE | portAPU_PRESENT | portFCM_FPU_PRESENT )
|
||||
#define portINITIAL_MSR ( portCRITICAL_INTERRUPT_ENABLE | portEXTERNAL_INTERRUPT_ENABLE | portMACHINE_CHECK_ENABLE | portAPU_PRESENT | portFCM_FPU_PRESENT )
|
||||
|
||||
|
||||
extern const unsigned _SDA_BASE_;
|
||||
|
|
@ -95,68 +95,72 @@ static XIntc xInterruptController;
|
|||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters )
|
||||
{
|
||||
/* Place a known value at the bottom of the stack for debugging. */
|
||||
*pxTopOfStack = 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
/* Place a known value at the bottom of the stack for debugging. */
|
||||
*pxTopOfStack = 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* EABI stack frame. */
|
||||
pxTopOfStack -= 20; /* Previous backchain and LR, R31 to R4 inclusive. */
|
||||
/* EABI stack frame. */
|
||||
pxTopOfStack -= 20; /* Previous backchain and LR, R31 to R4 inclusive. */
|
||||
|
||||
/* Parameters in R13. */
|
||||
*pxTopOfStack = ( StackType_t ) &_SDA_BASE_; /* address of the first small data area */
|
||||
pxTopOfStack -= 10;
|
||||
/* Parameters in R13. */
|
||||
*pxTopOfStack = ( StackType_t ) &_SDA_BASE_; /* address of the first small data area */
|
||||
pxTopOfStack -= 10;
|
||||
|
||||
/* Parameters in R3. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
/* Parameters in R3. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Parameters in R2. */
|
||||
*pxTopOfStack = ( StackType_t ) &_SDA2_BASE_; /* address of the second small data area */
|
||||
pxTopOfStack--;
|
||||
/* Parameters in R2. */
|
||||
*pxTopOfStack = ( StackType_t ) &_SDA2_BASE_; /* address of the second small data area */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* R1 is the stack pointer so is omitted. */
|
||||
/* R1 is the stack pointer so is omitted. */
|
||||
|
||||
*pxTopOfStack = 0x10000001UL;; /* R0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* USPRG0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* CR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* XER. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* CTR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) vPortEndScheduler; /* LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* SRR0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_MSR;/* SRR1. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) vPortEndScheduler;/* Next LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL;/* Backchain. */
|
||||
*pxTopOfStack = 0x10000001UL; /* R0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* USPRG0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* CR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* XER. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* CTR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) vPortEndScheduler; /* LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* SRR0. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_MSR; /* SRR1. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) vPortEndScheduler; /* Next LR. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x00000000UL; /* Backchain. */
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
prvSetupTimerInterrupt();
|
||||
XExc_RegisterHandler( XEXC_ID_SYSTEM_CALL, ( XExceptionHandler ) vPortYield, ( void * ) 0 );
|
||||
vPortStartFirstTask();
|
||||
prvSetupTimerInterrupt();
|
||||
XExc_RegisterHandler( XEXC_ID_SYSTEM_CALL, ( XExceptionHandler ) vPortYield, ( void * ) 0 );
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented. */
|
||||
for( ;; );
|
||||
/* Not implemented. */
|
||||
for( ; ; )
|
||||
{
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -165,95 +169,97 @@ void vPortEndScheduler( void )
|
|||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
const uint32_t ulInterval = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
|
||||
const uint32_t ulInterval = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );
|
||||
|
||||
XTime_DECClearInterrupt();
|
||||
XTime_FITClearInterrupt();
|
||||
XTime_WDTClearInterrupt();
|
||||
XTime_WDTDisableInterrupt();
|
||||
XTime_FITDisableInterrupt();
|
||||
XTime_DECClearInterrupt();
|
||||
XTime_FITClearInterrupt();
|
||||
XTime_WDTClearInterrupt();
|
||||
XTime_WDTDisableInterrupt();
|
||||
XTime_FITDisableInterrupt();
|
||||
|
||||
XExc_RegisterHandler( XEXC_ID_DEC_INT, ( XExceptionHandler ) vPortTickISR, ( void * ) 0 );
|
||||
XExc_RegisterHandler( XEXC_ID_DEC_INT, ( XExceptionHandler ) vPortTickISR, ( void * ) 0 );
|
||||
|
||||
XTime_DECEnableAutoReload();
|
||||
XTime_DECSetInterval( ulInterval );
|
||||
XTime_DECEnableInterrupt();
|
||||
XTime_DECEnableAutoReload();
|
||||
XTime_DECSetInterval( ulInterval );
|
||||
XTime_DECEnableInterrupt();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRHandler( void *pvNullDoNotUse )
|
||||
void vPortISRHandler( void * pvNullDoNotUse )
|
||||
{
|
||||
uint32_t ulInterruptStatus, ulInterruptMask = 1UL;
|
||||
BaseType_t xInterruptNumber;
|
||||
XIntc_Config *pxInterruptController;
|
||||
XIntc_VectorTableEntry *pxTable;
|
||||
uint32_t ulInterruptStatus, ulInterruptMask = 1UL;
|
||||
BaseType_t xInterruptNumber;
|
||||
XIntc_Config * pxInterruptController;
|
||||
XIntc_VectorTableEntry * pxTable;
|
||||
|
||||
/* Just to remove compiler warning. */
|
||||
( void ) pvNullDoNotUse;
|
||||
/* Just to remove compiler warning. */
|
||||
( void ) pvNullDoNotUse;
|
||||
|
||||
/* Get the configuration by using the device ID - in this case it is
|
||||
assumed that only one interrupt controller is being used. */
|
||||
pxInterruptController = &XIntc_ConfigTable[ XPAR_XPS_INTC_0_DEVICE_ID ];
|
||||
/* Get the configuration by using the device ID - in this case it is
|
||||
* assumed that only one interrupt controller is being used. */
|
||||
pxInterruptController = &XIntc_ConfigTable[ XPAR_XPS_INTC_0_DEVICE_ID ];
|
||||
|
||||
/* Which interrupts are pending? */
|
||||
ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );
|
||||
/* Which interrupts are pending? */
|
||||
ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );
|
||||
|
||||
for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ )
|
||||
{
|
||||
if( ulInterruptStatus & 0x01UL )
|
||||
{
|
||||
/* Clear the pending interrupt. */
|
||||
XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask );
|
||||
for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ )
|
||||
{
|
||||
if( ulInterruptStatus & 0x01UL )
|
||||
{
|
||||
/* Clear the pending interrupt. */
|
||||
XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask );
|
||||
|
||||
/* Call the registered handler. */
|
||||
pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );
|
||||
pxTable->Handler( pxTable->CallBackRef );
|
||||
}
|
||||
/* Call the registered handler. */
|
||||
pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );
|
||||
pxTable->Handler( pxTable->CallBackRef );
|
||||
}
|
||||
|
||||
/* Check the next interrupt. */
|
||||
ulInterruptMask <<= 0x01UL;
|
||||
ulInterruptStatus >>= 0x01UL;
|
||||
/* Check the next interrupt. */
|
||||
ulInterruptMask <<= 0x01UL;
|
||||
ulInterruptStatus >>= 0x01UL;
|
||||
|
||||
/* Have we serviced all interrupts? */
|
||||
if( ulInterruptStatus == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Have we serviced all interrupts? */
|
||||
if( ulInterruptStatus == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSetupInterruptController( void )
|
||||
{
|
||||
extern void vPortISRWrapper( void );
|
||||
extern void vPortISRWrapper( void );
|
||||
|
||||
/* Perform all library calls necessary to initialise the exception table
|
||||
and interrupt controller. This assumes only one interrupt controller is in
|
||||
use. */
|
||||
XExc_mDisableExceptions( XEXC_NON_CRITICAL );
|
||||
XExc_Init();
|
||||
/* Perform all library calls necessary to initialise the exception table
|
||||
* and interrupt controller. This assumes only one interrupt controller is in
|
||||
* use. */
|
||||
XExc_mDisableExceptions( XEXC_NON_CRITICAL );
|
||||
XExc_Init();
|
||||
|
||||
/* The library functions save the context - we then jump to a wrapper to
|
||||
save the stack into the TCB. The wrapper then calls the handler defined
|
||||
above. */
|
||||
XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, ( XExceptionHandler ) vPortISRWrapper, NULL );
|
||||
XIntc_Initialize( &xInterruptController, XPAR_XPS_INTC_0_DEVICE_ID );
|
||||
XIntc_Start( &xInterruptController, XIN_REAL_MODE );
|
||||
/* The library functions save the context - we then jump to a wrapper to
|
||||
* save the stack into the TCB. The wrapper then calls the handler defined
|
||||
* above. */
|
||||
XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, ( XExceptionHandler ) vPortISRWrapper, NULL );
|
||||
XIntc_Initialize( &xInterruptController, XPAR_XPS_INTC_0_DEVICE_ID );
|
||||
XIntc_Start( &xInterruptController, XIN_REAL_MODE );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID,
|
||||
XInterruptHandler pxHandler,
|
||||
void * pvCallBackRef )
|
||||
{
|
||||
BaseType_t xReturn = pdFAIL;
|
||||
BaseType_t xReturn = pdFAIL;
|
||||
|
||||
/* This function is defined here so the scope of xInterruptController can
|
||||
remain within this file. */
|
||||
/* This function is defined here so the scope of xInterruptController can
|
||||
* remain within this file. */
|
||||
|
||||
if( XST_SUCCESS == XIntc_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef ) )
|
||||
{
|
||||
XIntc_Enable( &xInterruptController, ucInterruptID );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
if( XST_SUCCESS == XIntc_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef ) )
|
||||
{
|
||||
XIntc_Enable( &xInterruptController, ucInterruptID );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
return xReturn;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue