Style: Revert uncrustify for portable directories (#122)

* Style: revert uncrustify portable directories

* Style: Uncrustify Some Portable files

Co-authored-by: Alfred Gedeon <gedeonag@amazon.com>
This commit is contained in:
alfred gedeon 2020-08-17 10:51:02 -07:00 committed by GitHub
parent a6da1cd0ce
commit 86653e2a1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
273 changed files with 64802 additions and 65931 deletions

View file

@ -22,7 +22,6 @@
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
@ -55,13 +54,13 @@
* on the secure side. The following are the valid configuration seetings:
*
* 1. Run FreeRTOS on the Secure Side:
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
*
* 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
*
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
*/
#if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
@ -612,7 +611,7 @@ static void prvTaskExitError( void )
extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__;
#else /* if defined( __ARMCC_VERSION ) */
#else /* if defined( __ARMCC_VERSION ) */
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[];
@ -802,22 +801,22 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
ulR0 = pulCallerStackAddress[ 0 ];
#if ( configENABLE_MPU == 1 )
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
#endif /* configENABLE_MPU */
configASSERT( xSecureContext != NULL );
@ -835,21 +834,21 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
case portSVC_START_SCHEDULER:
#if ( configENABLE_TRUSTZONE == 1 )
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
/* Initialize the secure context management system. */
SecureContext_Init();
}
/* Initialize the secure context management system. */
SecureContext_Init();
}
#endif /* configENABLE_TRUSTZONE */
#if ( configENABLE_FPU == 1 )
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
#endif /* configENABLE_FPU */
/* Setup the context of the first task so that the first task starts
@ -876,19 +875,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
}
}
/*-----------------------------------------------------------*/
/* *INDENT-OFF* */
#if ( configENABLE_MPU == 1 )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
#else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) /* PRIVILEGED_FUNCTION */
void * pvParameters ) /* PRIVILEGED_FUNCTION */
#endif /* configENABLE_MPU */
/* *INDENT-ON* */
{
/* Simulate the stack frame as it would be created by a context switch
* interrupt. */
@ -1051,7 +1051,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
int32_t lIndex = 0;
#if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */
extern uint32_t * __privileged_sram_start__;
@ -1079,8 +1081,8 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
* using a separate MPU region. This is needed because privileged
* SRAM is already protected using an MPU region and ARMv8-M does
* not allow overlapping MPU regions. */
if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ &&
ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ )
if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
{
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
@ -1089,7 +1091,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
/* Define the region that allows access to the stack. */
ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
( portMPU_REGION_NON_SHAREABLE ) |

View file

@ -26,22 +26,22 @@
*/
/*
* Changes from V1.00:
*
+ Call to taskYIELD() from within tick ISR has been replaced by the more
+ efficient portSWITCH_CONTEXT().
+ ISR function definitions renamed to include the prv prefix.
+
+ Changes from V2.6.1
+
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
+ macro to be consistent with the later ports.
*/
Changes from V1.00:
+ Call to taskYIELD() from within tick ISR has been replaced by the more
efficient portSWITCH_CONTEXT().
+ ISR function definitions renamed to include the prv prefix.
Changes from V2.6.1
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
macro to be consistent with the later ports.
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Flashlite 186
* port.
*----------------------------------------------------------*/
* Implementation of functions defined in portable.h for the Flashlite 186
* port.
*----------------------------------------------------------*/
#include <dos.h>
#include <stdlib.h>
@ -53,13 +53,13 @@
/*lint -e950 Non ANSI reserved words okay in this file only. */
#define portTIMER_EOI_TYPE ( 8 )
#define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE )
#define portTIMER_INT_NUMBER 0x12
#define portTIMER_EOI_TYPE ( 8 )
#define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE )
#define portTIMER_INT_NUMBER 0x12
#define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e )
#define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 )
#define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 )
#define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e )
#define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 )
#define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 )
/* Setup the hardware to generate the required tick frequency. */
static void prvSetTickFrequency( uint32_t ulTickRateHz );
@ -68,17 +68,15 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz );
static void prvExitFunction( void );
/* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */
#if ( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
* being used. */
static void __interrupt __far prvPreemptiveTick( void );
is being used. */
#if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
being used. */
static void __interrupt __far prvPreemptiveTick( void );
#else
/* Tick service routine used by the scheduler when cooperative scheduling is
* being used. */
static void __interrupt __far prvNonPreemptiveTick( void );
/* Tick service routine used by the scheduler when cooperative scheduling is
being used. */
static void __interrupt __far prvNonPreemptiveTick( void );
#endif
/* Trap routine used by taskYIELD() to manually cause a context switch. */
@ -90,9 +88,9 @@ static void __interrupt __far prvYieldProcessor( void );
static BaseType_t xSchedulerRunning = pdFALSE;
/* Points to the original routine installed on the vector we use for manual
* context switches. This is then used to restore the original routine during
* prvExitFunction(). */
static void( __interrupt __far * pxOldSwitchISR )();
context switches. This is then used to restore the original routine during
prvExitFunction(). */
static void ( __interrupt __far *pxOldSwitchISR )();
/* Used to restore the original DOS context when the scheduler is ended. */
static jmp_buf xJumpBuf;
@ -102,145 +100,145 @@ static jmp_buf xJumpBuf;
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
/* This is called with interrupts already disabled. */
/* This is called with interrupts already disabled. */
/* Remember what was on the interrupts we are going to use
* so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
/* Remember what was on the interrupts we are going to use
so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
/* Put our manual switch (yield) function on a known
* vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Put our manual switch (yield) function on a known
vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
#if ( configUSE_PREEMPTION == 1 )
{
/* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
}
#else
{
/* We want the timer interrupt to just increment the tick count. */
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
}
#endif
#if( configUSE_PREEMPTION == 1 )
{
/* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
}
#else
{
/* We want the timer interrupt to just increment the tick count. */
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
}
#endif
prvSetTickFrequency( configTICK_RATE_HZ );
prvSetTickFrequency( configTICK_RATE_HZ );
/* Clean up function if we want to return to DOS. */
if( setjmp( xJumpBuf ) != 0 )
{
prvExitFunction();
xSchedulerRunning = pdFALSE;
}
else
{
xSchedulerRunning = pdTRUE;
/* Clean up function if we want to return to DOS. */
if( setjmp( xJumpBuf ) != 0 )
{
prvExitFunction();
xSchedulerRunning = pdFALSE;
}
else
{
xSchedulerRunning = pdTRUE;
/* Kick off the scheduler by setting up the context of the first task. */
portFIRST_CONTEXT();
}
/* Kick off the scheduler by setting up the context of the first task. */
portFIRST_CONTEXT();
}
return xSchedulerRunning;
return xSchedulerRunning;
}
/*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */
#if ( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void )
{
/* Get the scheduler to update the task states following the tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT();
}
is being used. */
#if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void )
{
/* Get the scheduler to update the task states following the tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT();
}
/* Reset the PIC ready for the next time. */
portRESET_PIC();
}
#else /* if ( configUSE_PREEMPTION == 1 ) */
static void __interrupt __far prvNonPreemptiveTick( void )
{
/* Same as preemptive tick, but the cooperative scheduler is being used
* so we don't have to switch in the context of the next task. */
xTaskIncrementTick();
portRESET_PIC();
}
#endif /* if ( configUSE_PREEMPTION == 1 ) */
/* Reset the PIC ready for the next time. */
portRESET_PIC();
}
#else
static void __interrupt __far prvNonPreemptiveTick( void )
{
/* Same as preemptive tick, but the cooperative scheduler is being used
so we don't have to switch in the context of the next task. */
xTaskIncrementTick();
portRESET_PIC();
}
#endif
/*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void )
{
/* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT();
/* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT();
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Jump back to the processor state prior to starting the
* scheduler. This means we are not going to be using a
* task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 );
/* Jump back to the processor state prior to starting the
scheduler. This means we are not going to be using a
task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 );
}
/*-----------------------------------------------------------*/
static void prvExitFunction( void )
{
const uint16_t usTimerDisable = 0x0000;
uint16_t usTimer0Control;
const uint16_t usTimerDisable = 0x0000;
uint16_t usTimer0Control;
/* Interrupts should be disabled here anyway - but no
* harm in making sure. */
portDISABLE_INTERRUPTS();
/* Interrupts should be disabled here anyway - but no
harm in making sure. */
portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE )
{
/* Put back the switch interrupt routines that was in place
before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
}
if( xSchedulerRunning == pdTRUE )
{
/* Put back the switch interrupt routines that was in place
* before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
}
/* Disable the timer used for the tick to ensure the scheduler is
not called before restoring interrupts. There was previously nothing
on this timer so there is no old ISR to restore. */
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
/* Disable the timer used for the tick to ensure the scheduler is
* not called before restoring interrupts. There was previously nothing
* on this timer so there is no old ISR to restore. */
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
/* Restart the DOS tick. */
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
usTimer0Control |= portTIMER_INTERRUPT_ENABLE;
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
/* Restart the DOS tick. */
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
usTimer0Control |= portTIMER_INTERRUPT_ENABLE;
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
portENABLE_INTERRUPTS();
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
static void prvSetTickFrequency( uint32_t ulTickRateHz )
{
const uint16_t usMaxCountRegister = 0xff5a;
const uint16_t usTimerPriorityRegister = 0xff32;
const uint16_t usTimerEnable = 0xC000;
const uint16_t usRetrigger = 0x0001;
const uint16_t usTimerHighPriority = 0x0000;
uint16_t usTimer0Control;
const uint16_t usMaxCountRegister = 0xff5a;
const uint16_t usTimerPriorityRegister = 0xff32;
const uint16_t usTimerEnable = 0xC000;
const uint16_t usRetrigger = 0x0001;
const uint16_t usTimerHighPriority = 0x0000;
uint16_t usTimer0Control;
/* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */
const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL;
const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL;
uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );
portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority );
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );
portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority );
/* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE;
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
/* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE;
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
}
/*lint +e950 */

View file

@ -39,59 +39,59 @@
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE long
#define portLONG long
#define portSHORT int
#define portSTACK_TYPE uint16_t
#define portBASE_TYPE portSHORT
#define portCHAR char
#define portFLOAT float
#define portDOUBLE long
#define portLONG long
#define portSHORT int
#define portSTACK_TYPE uint16_t
#define portBASE_TYPE portSHORT
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
#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
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Critical section handling. */
#define portENTER_CRITICAL() \
__asm{ pushf } \
__asm{ cli } \
#define portENTER_CRITICAL() __asm{ pushf } \
__asm{ cli } \
#define portEXIT_CRITICAL() __asm{ popf }
#define portEXIT_CRITICAL() __asm{ popf }
#define portDISABLE_INTERRUPTS() __asm{ cli }
#define portDISABLE_INTERRUPTS() __asm{ cli }
#define portENABLE_INTERRUPTS() __asm{ sti }
#define portENABLE_INTERRUPTS() __asm{ sti }
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 2
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
#define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 2
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
/*-----------------------------------------------------------*/
/* Compiler specifics. */
#define portINPUT_BYTE( xAddr ) inp( xAddr )
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
#define portINPUT_WORD( xAddr ) inpw( xAddr )
#define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue )
#define portINPUT_BYTE( xAddr ) inp( xAddr )
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
#define portINPUT_WORD( xAddr ) inpw( xAddr )
#define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue )
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters )
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters )
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
#endif /* PORTMACRO_H */

View file

@ -26,16 +26,16 @@
*/
/*
* Changes from V2.6.1
*
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
+ macro to be consistent with the later ports.
+
+ Changes from V4.0.1
+
+ Add function prvSetTickFrequencyDefault() to set the DOS tick back to
+ its proper value when the scheduler exits.
*/
Changes from V2.6.1
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
macro to be consistent with the later ports.
Changes from V4.0.1
+ Add function prvSetTickFrequencyDefault() to set the DOS tick back to
its proper value when the scheduler exits.
*/
#include <stdlib.h>
#include <dos.h>
@ -46,13 +46,13 @@
#include "portasm.h"
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the industrial
* PC port.
*----------------------------------------------------------*/
* Implementation of functions defined in portable.h for the industrial
* PC port.
*----------------------------------------------------------*/
/*lint -e950 Non ANSI reserved words okay in this file only. */
#define portTIMER_INT_NUMBER 0x08
#define portTIMER_INT_NUMBER 0x08
/* Setup hardware for required tick interrupt rate. */
static void prvSetTickFrequency( uint32_t ulTickRateHz );
@ -61,29 +61,27 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz );
static void prvExitFunction( void );
/* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC
* directly. We chain to the DOS tick as close as possible to the standard DOS
* tick rate. */
directly. We chain to the DOS tick as close as possible to the standard DOS
tick rate. */
static void prvPortResetPIC( void );
/* The ISR used depends on whether the preemptive or cooperative
* scheduler is being used. */
#if ( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
* being used. */
static void __interrupt __far prvPreemptiveTick( void );
scheduler is being used. */
#if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
being used. */
static void __interrupt __far prvPreemptiveTick( void );
#else
/* Tick service routine used by the scheduler when cooperative scheduling is
* being used. */
static void __interrupt __far prvNonPreemptiveTick( void );
/* Tick service routine used by the scheduler when cooperative scheduling is
being used. */
static void __interrupt __far prvNonPreemptiveTick( void );
#endif
/* Trap routine used by taskYIELD() to manually cause a context switch. */
static void __interrupt __far prvYieldProcessor( void );
/* Set the tick frequency back so the floppy drive works correctly when the
* scheduler exits. */
scheduler exits. */
static void prvSetTickFrequencyDefault( void );
/*lint -e956 File scopes necessary here. */
@ -92,13 +90,13 @@ static void prvSetTickFrequencyDefault( void );
static int16_t sDOSTickCounter;
/* Set true when the vectors are set so the scheduler will service the tick. */
static BaseType_t xSchedulerRunning = pdFALSE;
static BaseType_t xSchedulerRunning = pdFALSE;
/* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */
static void( __interrupt __far * pxOldSwitchISR )();
static void ( __interrupt __far *pxOldSwitchISR )();
/* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */
static void( __interrupt __far * pxOldSwitchISRPlus1 )();
static void ( __interrupt __far *pxOldSwitchISRPlus1 )();
/* Used to restore the original DOS context when the scheduler is ended. */
static jmp_buf xJumpBuf;
@ -108,187 +106,183 @@ static jmp_buf xJumpBuf;
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
pxISR pxOriginalTickISR;
pxISR pxOriginalTickISR;
/* This is called with interrupts already disabled. */
/* This is called with interrupts already disabled. */
/* Remember what was on the interrupts we are going to use
so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER );
pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
/* Remember what was on the interrupts we are going to use
* so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER );
pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
prvSetTickFrequency( configTICK_RATE_HZ );
prvSetTickFrequency( configTICK_RATE_HZ );
/* Put our manual switch (yield) function on a known
vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Put our manual switch (yield) function on a known
* vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Put the old tick on a different interrupt number so we can
call it when we want. */
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR );
/* Put the old tick on a different interrupt number so we can
* call it when we want. */
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR );
/* The ISR used depends on whether the preemptive or cooperative
* scheduler is being used. */
#if ( configUSE_PREEMPTION == 1 )
{
/* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
}
#else
{
/* We want the timer interrupt to just increment the tick count. */
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
}
/* The ISR used depends on whether the preemptive or cooperative
scheduler is being used. */
#if( configUSE_PREEMPTION == 1 )
{
/* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
}
#else
{
/* We want the timer interrupt to just increment the tick count. */
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
}
#endif
/* Setup a counter that is used to call the DOS interrupt as close
* to it's original frequency as can be achieved given our chosen tick
* frequency. */
sDOSTickCounter = portTICKS_PER_DOS_TICK;
/* Setup a counter that is used to call the DOS interrupt as close
to it's original frequency as can be achieved given our chosen tick
frequency. */
sDOSTickCounter = portTICKS_PER_DOS_TICK;
/* Clean up function if we want to return to DOS. */
if( setjmp( xJumpBuf ) != 0 )
{
prvExitFunction();
xSchedulerRunning = pdFALSE;
}
else
{
xSchedulerRunning = pdTRUE;
/* Clean up function if we want to return to DOS. */
if( setjmp( xJumpBuf ) != 0 )
{
prvExitFunction();
xSchedulerRunning = pdFALSE;
}
else
{
xSchedulerRunning = pdTRUE;
/* Kick off the scheduler by setting up the context of the first task. */
portFIRST_CONTEXT();
}
/* Kick off the scheduler by setting up the context of the first task. */
portFIRST_CONTEXT();
}
return xSchedulerRunning;
return xSchedulerRunning;
}
/*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative
* scheduler is being used. */
#if ( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void )
{
/* Get the scheduler to update the task states following the tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT();
}
scheduler is being used. */
#if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void )
{
/* Get the scheduler to update the task states following the tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT();
}
/* Reset the PIC ready for the next time. */
prvPortResetPIC();
}
#else /* if ( configUSE_PREEMPTION == 1 ) */
static void __interrupt __far prvNonPreemptiveTick( void )
{
/* Same as preemptive tick, but the cooperative scheduler is being used
* so we don't have to switch in the context of the next task. */
xTaskIncrementTick();
prvPortResetPIC();
}
#endif /* if ( configUSE_PREEMPTION == 1 ) */
/* Reset the PIC ready for the next time. */
prvPortResetPIC();
}
#else
static void __interrupt __far prvNonPreemptiveTick( void )
{
/* Same as preemptive tick, but the cooperative scheduler is being used
so we don't have to switch in the context of the next task. */
xTaskIncrementTick();
prvPortResetPIC();
}
#endif
/*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void )
{
/* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT();
/* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT();
}
/*-----------------------------------------------------------*/
static void prvPortResetPIC( void )
{
/* We are going to call the DOS tick interrupt at as close a
* frequency to the normal DOS tick as possible. */
/* We are going to call the DOS tick interrupt at as close a
frequency to the normal DOS tick as possible. */
/* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */
--sDOSTickCounter;
if( sDOSTickCounter <= 0 )
{
sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK;
__asm {
int portSWITCH_INT_NUMBER + 1
};
}
else
{
/* Reset the PIC as the DOS tick is not being called to
* do it. */
__asm
{
mov al, 20H
out 20H, al
};
}
/* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */
--sDOSTickCounter;
if( sDOSTickCounter <= 0 )
{
sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK;
__asm{ int portSWITCH_INT_NUMBER + 1 };
}
else
{
/* Reset the PIC as the DOS tick is not being called to
do it. */
__asm
{
mov al, 20H
out 20H, al
};
}
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Jump back to the processor state prior to starting the
* scheduler. This means we are not going to be using a
* task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 );
/* Jump back to the processor state prior to starting the
scheduler. This means we are not going to be using a
task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 );
}
/*-----------------------------------------------------------*/
static void prvExitFunction( void )
{
void( __interrupt __far * pxOriginalTickISR )();
void ( __interrupt __far *pxOriginalTickISR )();
/* Interrupts should be disabled here anyway - but no
* harm in making sure. */
portDISABLE_INTERRUPTS();
/* Interrupts should be disabled here anyway - but no
harm in making sure. */
portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE )
{
/* Set the DOS tick back onto the timer ticker. */
pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
_dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR );
prvSetTickFrequencyDefault();
if( xSchedulerRunning == pdTRUE )
{
/* Set the DOS tick back onto the timer ticker. */
pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
_dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR );
prvSetTickFrequencyDefault();
/* Put back the switch interrupt routines that was in place
* before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 );
}
/* The tick timer is back how DOS wants it. We can re-enable
* interrupts without the scheduler being called. */
portENABLE_INTERRUPTS();
/* Put back the switch interrupt routines that was in place
before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 );
}
/* The tick timer is back how DOS wants it. We can re-enable
interrupts without the scheduler being called. */
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
static void prvSetTickFrequency( uint32_t ulTickRateHz )
{
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
uint32_t ulOutput;
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
uint32_t ulOutput;
/* Setup the 8245 to tick at the wanted frequency. */
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
ulOutput = ulPIT_CONST / ulTickRateHz;
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
ulOutput >>= 8;
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
/* Setup the 8245 to tick at the wanted frequency. */
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
ulOutput = ulPIT_CONST / ulTickRateHz;
portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) );
ulOutput >>= 8;
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
}
/*-----------------------------------------------------------*/
static void prvSetTickFrequencyDefault( void )
{
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
portOUTPUT_BYTE( usPIT0, 0 );
portOUTPUT_BYTE( usPIT0, 0 );
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
portOUTPUT_BYTE( usPIT0,0 );
portOUTPUT_BYTE( usPIT0,0 );
}
/*lint +e950 */

View file

@ -39,59 +39,59 @@
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT long
#define portDOUBLE long
#define portLONG long
#define portSHORT int
#define portSTACK_TYPE uint16_t
#define portBASE_TYPE portSHORT
#define portCHAR char
#define portFLOAT long
#define portDOUBLE long
#define portLONG long
#define portSHORT int
#define portSTACK_TYPE uint16_t
#define portBASE_TYPE portSHORT
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
#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
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Critical section management. */
#define portENTER_CRITICAL() \
__asm{ pushf } \
__asm{ cli } \
#define portENTER_CRITICAL() __asm{ pushf } \
__asm{ cli } \
#define portEXIT_CRITICAL() __asm{ popf }
#define portEXIT_CRITICAL() __asm{ popf }
#define portDISABLE_INTERRUPTS() __asm{ cli }
#define portDISABLE_INTERRUPTS() __asm{ cli }
#define portENABLE_INTERRUPTS() __asm{ sti }
#define portENABLE_INTERRUPTS() __asm{ sti }
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portDOS_TICK_RATE ( 18.20648 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) )
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
#define portBYTE_ALIGNMENT ( 2 )
#define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portDOS_TICK_RATE ( 18.20648 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) )
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
#define portBYTE_ALIGNMENT ( 2 )
/*-----------------------------------------------------------*/
/* Compiler specifics. */
#define portINPUT_BYTE( xAddr ) inp( xAddr )
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
#define portINPUT_BYTE( xAddr ) inp( xAddr )
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void * pvParameters )
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void * pvParameters )
#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
#endif /* PORTMACRO_H */

View file

@ -47,40 +47,41 @@ void portSWITCH_CONTEXT( void );
void portFIRST_CONTEXT( void );
/* There are slightly different versions depending on whether you are building
* to include debugger information. If debugger information is used then there
* are a couple of extra bytes left of the ISR stack (presumably for use by the
* debugger). The true stack pointer is then stored in the bp register. We add
* 2 to the stack pointer to remove the extra bytes before we restore our context. */
to include debugger information. If debugger information is used then there
are a couple of extra bytes left of the ISR stack (presumably for use by the
debugger). The true stack pointer is then stored in the bp register. We add
2 to the stack pointer to remove the extra bytes before we restore our context. */
#define portSWITCH_CONTEXT() \
asm { mov ax, seg pxCurrentTCB } \
asm { mov ds, ax } \
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
asm { mov es : 0x2[ bx ], ss } \
asm { mov es:[ bx ], sp } \
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
asm { mov ds, ax } \
asm { les bx, dword ptr pxCurrentTCB } \
asm { mov ss, es:[ bx + 2 ] } \
asm { mov sp, es:[ bx ] }
#define portSWITCH_CONTEXT() \
asm { mov ax, seg pxCurrentTCB } \
asm { mov ds, ax } \
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
asm { mov es:0x2[ bx ], ss } \
asm { mov es:[ bx ], sp } \
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
asm { mov ds, ax } \
asm { les bx, dword ptr pxCurrentTCB } \
asm { mov ss, es:[ bx + 2 ] } \
asm { mov sp, es:[ bx ] }
#define portFIRST_CONTEXT() \
__asm { mov ax, seg pxCurrentTCB } \
__asm { mov ds, ax } \
__asm { les bx, dword ptr pxCurrentTCB } \
__asm { mov ss, es:[ bx + 2 ] } \
__asm { mov sp, es:[ bx ] } \
__asm { pop bp } \
__asm { pop di } \
__asm { pop si } \
__asm { pop ds } \
__asm { pop es } \
__asm { pop dx } \
__asm { pop cx } \
__asm { pop bx } \
__asm { pop ax } \
__asm { iret }
#define portFIRST_CONTEXT() \
__asm { mov ax, seg pxCurrentTCB } \
__asm { mov ds, ax } \
__asm { les bx, dword ptr pxCurrentTCB } \
__asm { mov ss, es:[ bx + 2 ] } \
__asm { mov sp, es:[ bx ] } \
__asm { pop bp } \
__asm { pop di } \
__asm { pop si } \
__asm { pop ds } \
__asm { pop es } \
__asm { pop dx } \
__asm { pop cx } \
__asm { pop bx } \
__asm { pop ax } \
__asm { iret }
#endif /* ifndef PORT_ASM_H */
#endif

View file

@ -26,16 +26,16 @@
*/
/*
* Changes from V1.00:
*
+ pxPortInitialiseStack() now initialises the stack of new tasks to the
+ same format used by the compiler. This allows the compiler generated
+ interrupt mechanism to be used for context switches.
+
+ Changes from V2.6.1
+
+ Move usPortCheckFreeStackSpace() to tasks.c.
*/
Changes from V1.00:
+ pxPortInitialiseStack() now initialises the stack of new tasks to the
same format used by the compiler. This allows the compiler generated
interrupt mechanism to be used for context switches.
Changes from V2.6.1
+ Move usPortCheckFreeStackSpace() to tasks.c.
*/
#include <dos.h>
@ -45,79 +45,76 @@
/*-----------------------------------------------------------*/
/* 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 DS_Reg = 0;
StackType_t DS_Reg = 0;
/* 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 = 0x1111;
pxTopOfStack--;
*pxTopOfStack = 0x2222;
pxTopOfStack--;
*pxTopOfStack = 0x3333;
pxTopOfStack--;
*pxTopOfStack = 0x4444;
pxTopOfStack--;
*pxTopOfStack = 0x5555;
pxTopOfStack--;
*pxTopOfStack = 0x1111;
pxTopOfStack--;
*pxTopOfStack = 0x2222;
pxTopOfStack--;
*pxTopOfStack = 0x3333;
pxTopOfStack--;
*pxTopOfStack = 0x4444;
pxTopOfStack--;
*pxTopOfStack = 0x5555;
pxTopOfStack--;
/*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. */
/* We are going to start the scheduler using a return from interrupt
* instruction to load the program counter, so first there would be the
* function call with parameters preamble. */
/* We are going to start the scheduler using a return from interrupt
instruction to load the program counter, so first there would be the
function call with parameters preamble. */
*pxTopOfStack = FP_SEG( pvParameters );
pxTopOfStack--;
*pxTopOfStack = FP_OFF( pvParameters );
pxTopOfStack--;
*pxTopOfStack = FP_SEG( pxCode );
pxTopOfStack--;
*pxTopOfStack = FP_OFF( pxCode );
pxTopOfStack--;
*pxTopOfStack = FP_SEG( pvParameters );
pxTopOfStack--;
*pxTopOfStack = FP_OFF( pvParameters );
pxTopOfStack--;
*pxTopOfStack = FP_SEG( pxCode );
pxTopOfStack--;
*pxTopOfStack = FP_OFF( pxCode );
pxTopOfStack--;
/* Next the status register and interrupt return address. */
*pxTopOfStack = portINITIAL_SW;
pxTopOfStack--;
*pxTopOfStack = FP_SEG( pxCode );
pxTopOfStack--;
*pxTopOfStack = FP_OFF( pxCode );
pxTopOfStack--;
/* Next the status register and interrupt return address. */
*pxTopOfStack = portINITIAL_SW;
pxTopOfStack--;
*pxTopOfStack = FP_SEG( pxCode );
pxTopOfStack--;
*pxTopOfStack = FP_OFF( pxCode );
pxTopOfStack--;
/* The remaining registers would be pushed on the stack by our context
switch function. These are loaded with values simply to make debugging
easier. */
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */
pxTopOfStack--;
/* The remaining registers would be pushed on the stack by our context
* switch function. These are loaded with values simply to make debugging
* easier. */
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */
pxTopOfStack--;
/* We need the true data segment. */
__asm{ MOV DS_Reg, DS };
/* We need the true data segment. */
__asm {
MOV DS_Reg, DS
};
*pxTopOfStack = DS_Reg; /* DS */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x0123; /* SI */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */
*pxTopOfStack = DS_Reg; /* DS */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x0123; /* SI */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */
/*lint +e950 +e611 +e923 */
/*lint +e950 +e611 +e923 */
return pxTopOfStack;
return pxTopOfStack;
}
/*-----------------------------------------------------------*/

View file

@ -37,28 +37,28 @@ uint32_t ulCriticalNesting = 9999;
/*-----------------------------------------------------------*/
/* Registers required to configure the RTI. */
#define portRTI_GCTRL_REG ( *( ( volatile uint32_t * ) 0xFFFFFC00 ) )
#define portRTI_TBCTRL_REG ( *( ( volatile uint32_t * ) 0xFFFFFC04 ) )
#define portRTI_COMPCTRL_REG ( *( ( volatile uint32_t * ) 0xFFFFFC0C ) )
#define portRTI_CNT0_FRC0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC10 ) )
#define portRTI_CNT0_UC0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC14 ) )
#define portRTI_CNT0_CPUC0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC18 ) )
#define portRTI_CNT0_COMP0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC50 ) )
#define portRTI_CNT0_UDCP0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC54 ) )
#define portRTI_SETINTENA_REG ( *( ( volatile uint32_t * ) 0xFFFFFC80 ) )
#define portRTI_CLEARINTENA_REG ( *( ( volatile uint32_t * ) 0xFFFFFC84 ) )
#define portRTI_INTFLAG_REG ( *( ( volatile uint32_t * ) 0xFFFFFC88 ) )
#define portRTI_GCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC00 ) )
#define portRTI_TBCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC04 ) )
#define portRTI_COMPCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC0C ) )
#define portRTI_CNT0_FRC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC10 ) )
#define portRTI_CNT0_UC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC14 ) )
#define portRTI_CNT0_CPUC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC18 ) )
#define portRTI_CNT0_COMP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC50 ) )
#define portRTI_CNT0_UDCP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC54 ) )
#define portRTI_SETINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC80 ) )
#define portRTI_CLEARINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC84 ) )
#define portRTI_INTFLAG_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC88 ) )
/* Constants required to set up the initial stack of each task. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1F )
#define portINITIAL_FPSCR ( ( StackType_t ) 0x00 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0x04 )
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINITIAL_SPSR ( ( StackType_t ) 0x1F )
#define portINITIAL_FPSCR ( ( StackType_t ) 0x00 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0x04 )
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
/* The number of words on the stack frame between the saved Top Of Stack and
* R0 (in which the parameters are passed. */
#define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 )
R0 (in which the parameters are passed. */
#define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 )
/*-----------------------------------------------------------*/
@ -68,7 +68,7 @@ extern void vPortStartFirstTask( void );
/*-----------------------------------------------------------*/
/* Saved as part of the task context. Set to pdFALSE if the task does not
* require an FPU context. */
require an FPU context. */
uint32_t ulTaskHasFPUContext = 0;
/*-----------------------------------------------------------*/
@ -77,183 +77,181 @@ uint32_t ulTaskHasFPUContext = 0;
/*
* 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;
#if __TI_VFP_SUPPORT__
{
/* Ensure the stack is correctly aligned on exit. */
pxTopOfStack--;
}
#endif
#if __TI_VFP_SUPPORT__
{
/* Ensure the stack is correctly aligned on exit. */
pxTopOfStack--;
}
#endif
/* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */
/* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which is the start of the as
* the task has not executed yet. The offset is added to make the return
* address appear as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--;
/* First on the stack is the return address - which is the start of the as
the task has not executed yet. The offset is added to make the return
address appear as it would within an IRQ ISR. */
*pxTopOfStack = ( 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 ) 0x00000000; /* R14 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--;
#ifdef portPRELOAD_TASK_REGISTERS
{
*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--;
}
#else /* ifdef portPRELOAD_TASK_REGISTERS */
{
pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;
}
#endif /* ifdef portPRELOAD_TASK_REGISTERS */
#ifdef portPRELOAD_TASK_REGISTERS
{
*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--;
}
#else
{
pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;
}
#endif
/* Function parameters are passed in R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* Function parameters are passed in R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* Set the status register for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR );
/* Set the status register for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR );
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
{
/* The task will start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
{
/* The task will start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
#ifdef __TI_VFP_SUPPORT__
{
pxTopOfStack--;
#ifdef __TI_VFP_SUPPORT__
{
pxTopOfStack--;
/* The last thing on the stack is the tasks ulUsingFPU value, which by
* default is set to indicate that the stack frame does not include FPU
* registers. */
*pxTopOfStack = pdFALSE;
}
#endif
/* The last thing on the stack is the tasks ulUsingFPU value, which by
default is set to indicate that the stack frame does not include FPU
registers. */
*pxTopOfStack = pdFALSE;
}
#endif
return pxTopOfStack;
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void )
static void prvSetupTimerInterrupt(void)
{
/* Disable timer 0. */
portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
/* Disable timer 0. */
portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
/* Use the internal counter. */
portRTI_TBCTRL_REG = 0x00000000U;
/* Use the internal counter. */
portRTI_TBCTRL_REG = 0x00000000U;
/* COMPSEL0 will use the RTIFRC0 counter. */
portRTI_COMPCTRL_REG = 0x00000000U;
/* COMPSEL0 will use the RTIFRC0 counter. */
portRTI_COMPCTRL_REG = 0x00000000U;
/* Initialise the counter and the prescale counter registers. */
portRTI_CNT0_UC0_REG = 0x00000000U;
portRTI_CNT0_FRC0_REG = 0x00000000U;
/* Initialise the counter and the prescale counter registers. */
portRTI_CNT0_UC0_REG = 0x00000000U;
portRTI_CNT0_FRC0_REG = 0x00000000U;
/* Set Prescalar for RTI clock. */
portRTI_CNT0_CPUC0_REG = 0x00000001U;
portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
/* Set Prescalar for RTI clock. */
portRTI_CNT0_CPUC0_REG = 0x00000001U;
portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
/* Clear interrupts. */
portRTI_INTFLAG_REG = 0x0007000FU;
portRTI_CLEARINTENA_REG = 0x00070F0FU;
/* Clear interrupts. */
portRTI_INTFLAG_REG = 0x0007000FU;
portRTI_CLEARINTENA_REG = 0x00070F0FU;
/* Enable the compare 0 interrupt. */
portRTI_SETINTENA_REG = 0x00000001U;
portRTI_GCTRL_REG |= 0x00000001U;
/* Enable the compare 0 interrupt. */
portRTI_SETINTENA_REG = 0x00000001U;
portRTI_GCTRL_REG |= 0x00000001U;
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
BaseType_t xPortStartScheduler( void )
BaseType_t xPortStartScheduler(void)
{
/* Start the timer that generates the tick ISR. */
prvSetupTimerInterrupt();
/* Start the timer that generates the tick ISR. */
prvSetupTimerInterrupt();
/* Reset the critical section nesting count read to execute the first task. */
ulCriticalNesting = 0;
/* Reset the critical section nesting count read to execute the first task. */
ulCriticalNesting = 0;
/* Start the first task. This is done from portASM.asm as ARM mode must be
* used. */
vPortStartFirstTask();
/* Start the first task. This is done from portASM.asm as ARM mode must be
used. */
vPortStartFirstTask();
/* Should not get here! */
return pdFAIL;
/* Should not get here! */
return pdFAIL;
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
void vPortEndScheduler( void )
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 );
}
/*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */
__interrupt void vPortNonPreemptiveTick( void )
{
/* clear clock interrupt flag */
portRTI_INTFLAG_REG = 0x00000001;
/* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */
__interrupt void vPortNonPreemptiveTick( void )
{
/* clear clock interrupt flag */
portRTI_INTFLAG_REG = 0x00000001;
/* Increment the tick count - this may make a delaying task ready
* to run - but a context switch is not performed. */
xTaskIncrementTick();
}
/* Increment the tick count - this may make a delaying task ready
to run - but a context switch is not performed. */
xTaskIncrementTick();
}
#else /* if configUSE_PREEMPTION == 0 */
#else
/*
**************************************************************************
* The preemptive scheduler ISR is written in assembler and can be found
* in the portASM.asm file. This will only get used if portUSE_PREEMPTION
* is set to 1 in portmacro.h
**************************************************************************
*/
void vPortPreemptiveTick( void );
/*
**************************************************************************
* The preemptive scheduler ISR is written in assembler and can be found
* in the portASM.asm file. This will only get used if portUSE_PREEMPTION
* is set to 1 in portmacro.h
**************************************************************************
*/
void vPortPreemptiveTick( void );
#endif /* if configUSE_PREEMPTION == 0 */
#endif
/*-----------------------------------------------------------*/
@ -262,13 +260,13 @@ void vPortEndScheduler( void )
*/
void vPortEnterCritical( void )
{
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
portDISABLE_INTERRUPTS();
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */
ulCriticalNesting++;
/* 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++;
}
/*-----------------------------------------------------------*/
@ -278,36 +276,37 @@ void vPortEnterCritical( void )
*/
void vPortExitCritical( void )
{
if( ulCriticalNesting > 0 )
{
/* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--;
if( ulCriticalNesting > 0 )
{
/* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be
* re-enabled. */
if( ulCriticalNesting == 0 )
{
/* Enable interrupts as per portENABLE_INTERRUPTS(). */
portENABLE_INTERRUPTS();
}
}
/* If the nesting level has reached zero then interrupts should be
re-enabled. */
if( ulCriticalNesting == 0 )
{
/* Enable interrupts as per portENABLE_INTERRUPTS(). */
portENABLE_INTERRUPTS();
}
}
}
/*-----------------------------------------------------------*/
#if __TI_VFP_SUPPORT__
void vPortTaskUsesFPU( void )
{
extern void vPortInitialiseFPSCR( void );
void vPortTaskUsesFPU( void )
{
extern void vPortInitialiseFPSCR( void );
/* A task is registering the fact that it needs an FPU context. Set the
* FPU flag (saved as part of the task context. */
ulTaskHasFPUContext = pdTRUE;
/* A task is registering the fact that it needs an FPU context. Set the
FPU flag (saved as part of the task context. */
ulTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */
vPortInitialiseFPSCR();
}
/* Initialise the floating point status register. */
vPortInitialiseFPSCR();
}
#endif /* __TI_VFP_SUPPORT__ */
/*-----------------------------------------------------------*/

View file

@ -39,78 +39,79 @@
*/
/* 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
#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 ) 0xFFFFFFFFF
typedef uint32_t TickType_t;
#define portMAX_DELAY (TickType_t) 0xFFFFFFFFF
/* 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
/* 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 portSTACK_GROWTH (-1)
#define portTICK_PERIOD_MS ((TickType_t) 1000 / configTICK_RATE_HZ)
#define portBYTE_ALIGNMENT 8
/* Critical section handling. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() asm ( " CPSID I" )
#define portENABLE_INTERRUPTS() asm ( " CPSIE I" )
extern void vPortEnterCritical(void);
extern void vPortExitCritical(void);
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() asm( " CPSID I" )
#define portENABLE_INTERRUPTS() asm( " CPSIE I" )
/* Scheduler utilities. */
#pragma SWI_ALIAS( vPortYield, 0 )
extern void vPortYield( void );
#define portYIELD() vPortYield()
#define portSYS_SSIR1_REG ( *( ( volatile uint32_t * ) 0xFFFFFFB0 ) )
#define portSYS_SSIR1_SSKEY ( 0x7500UL )
#define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm ( " DSB " ); asm ( " ISB " ); }
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; }
#define portYIELD() vPortYield()
#define portSYS_SSIR1_REG ( * ( ( volatile uint32_t * ) 0xFFFFFFB0 ) )
#define portSYS_SSIR1_SSKEY ( 0x7500UL )
#define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm( " DSB " ); asm( " ISB " ); }
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ){ portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; }
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
/* Architecture specific optimisations. */
#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
/* 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 - __clz( ( uxReadyPriorities ) ) )
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
#endif /* __PORTMACRO_H__ */

View file

@ -1,48 +1,53 @@
; /*
* ; * FreeRTOS Kernel V10.3.1
* ; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* ; *
* ; * Permission is hereby granted, free of charge, to any person obtaining a copy of
* ; * this software and associated documentation files (the "Software"), to deal in
* ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions:
* ; *
* ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software.
* ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; *
* ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos
* ; *
* ; * 1 tab == 4 spaces!
* ; */
;/*
; * FreeRTOS Kernel V10.3.1
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
; *
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
; * this software and associated documentation files (the "Software"), to deal in
; * the Software without restriction, including without limitation the rights to
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
; * the Software, and to permit persons to whom the Software is furnished to do so,
; * subject to the following conditions:
; *
; * The above copyright notice and this permission notice shall be included in all
; * copies or substantial portions of the Software.
; *
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
; *
; * http://www.FreeRTOS.org
; * http://aws.amazon.com/freertos
; *
; * 1 tab == 4 spaces!
; */
.if $DEFINED( __LARGE_DATA_MODEL__ )
.define "pushm.a", pushm_x
.define "popm.a", popm_x
.define "push.a", push_x
.define "pop.a", pop_x
.define "mov.a", mov_x
.else
.define "pushm.w", pushm_x
.define "popm.w", popm_x
.define "push.w", push_x
.define "pop.w", pop_x
.define "mov.w", mov_x
.endif
.if $DEFINED( __LARGE_CODE_MODEL__ )
.define "calla", call_x
.define "reta", ret_x
.else
.define "call", call_x
.define "ret", ret_x
.endif
.if $DEFINED( __LARGE_DATA_MODEL__ )
.define "pushm.a", pushm_x
.define "popm.a", popm_x
.define "push.a", push_x
.define "pop.a", pop_x
.define "mov.a", mov_x
.else
.define "pushm.w", pushm_x
.define "popm.w", popm_x
.define "push.w", push_x
.define "pop.w", pop_x
.define "mov.w", mov_x
.endif
.if $DEFINED( __LARGE_CODE_MODEL__ )
.define "calla", call_x
.define "reta", ret_x
.else
.define "call", call_x
.define "ret", ret_x
.endif

View file

@ -30,28 +30,28 @@
#include "task.h"
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the MSP430X port.
*----------------------------------------------------------*/
* Implementation of functions defined in portable.h for the MSP430X 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 )
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;
/* 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 exited 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. */
time a critical section is entered the count is incremented. Each time a
critical section is exited 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;
/*-----------------------------------------------------------*/
@ -69,96 +69,94 @@ void vPortSetupTimerInterrupt( 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 )
{
uint16_t * pusTopOfStack;
uint32_t * pulTopOfStack, ulTemp;
uint16_t *pusTopOfStack;
uint32_t *pulTopOfStack, ulTemp;
/*
* 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--;
*/
/*
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.
/* Data types are need either 16 bits or 32 bits depending on the data
* and code model used. */
if( sizeof( pxCode ) == sizeof( uint16_t ) )
{
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
ulTemp = ( uint32_t ) pxCode;
*pusTopOfStack = ( uint16_t ) ulTemp;
}
else
{
/* Make room for a 20 bit value stored as a 32 bit value. */
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
pusTopOfStack--;
pulTopOfStack = ( uint32_t * ) pusTopOfStack;
*pulTopOfStack = ( uint32_t ) pxCode;
}
*pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x3333;
pxTopOfStack--;
*/
pusTopOfStack--;
*pusTopOfStack = portFLAGS_INT_ENABLED;
pusTopOfStack -= ( sizeof( StackType_t ) / 2 );
/* Data types are need either 16 bits or 32 bits depending on the data
and code model used. */
if( sizeof( pxCode ) == sizeof( uint16_t ) )
{
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
ulTemp = ( uint32_t ) pxCode;
*pusTopOfStack = ( uint16_t ) ulTemp;
}
else
{
/* Make room for a 20 bit value stored as a 32 bit value. */
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
pusTopOfStack--;
pulTopOfStack = ( uint32_t * ) pusTopOfStack;
*pulTopOfStack = ( uint32_t ) pxCode;
}
/* From here on the size of stacked items depends on the memory model. */
pxTopOfStack = ( StackType_t * ) pusTopOfStack;
pusTopOfStack--;
*pusTopOfStack = portFLAGS_INT_ENABLED;
pusTopOfStack -= ( sizeof( StackType_t ) / 2 );
/* From here on the size of stacked items depends on the memory model. */
pxTopOfStack = ( StackType_t * ) pusTopOfStack;
/* Next the general purpose registers. */
#ifdef PRELOAD_REGISTER_VALUES
*pxTopOfStack = ( StackType_t ) 0xffff;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xeeee;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xdddd;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xbbbb;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xaaaa;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x9999;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x8888;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x6666;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x4444;
pxTopOfStack--;
#else /* ifdef PRELOAD_REGISTER_VALUES */
pxTopOfStack -= 3;
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack -= 9;
#endif /* ifdef PRELOAD_REGISTER_VALUES */
/* Next the general purpose registers. */
#ifdef PRELOAD_REGISTER_VALUES
*pxTopOfStack = ( StackType_t ) 0xffff;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xeeee;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xdddd;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xbbbb;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xaaaa;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x9999;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x8888;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x6666;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x4444;
pxTopOfStack--;
#else
pxTopOfStack -= 3;
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack -= 9;
#endif
/* 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;
/* 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;
}
/*-----------------------------------------------------------*/
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. */
}
/*-----------------------------------------------------------*/
@ -167,21 +165,23 @@ void vPortEndScheduler( void )
*/
void vPortSetupTimerInterrupt( void )
{
vApplicationSetupTimerInterrupt();
vApplicationSetupTimerInterrupt();
}
/*-----------------------------------------------------------*/
#pragma vector=configTICK_VECTOR
interrupt void vTickISREntry( void )
{
extern void vPortTickISR( void );
extern void vPortTickISR( void );
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
#if configUSE_PREEMPTION == 1
extern void vPortPreemptiveTickISR( void );
vPortPreemptiveTickISR();
#else
extern void vPortCooperativeTickISR( void );
vPortCooperativeTickISR();
#endif
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
#if configUSE_PREEMPTION == 1
extern void vPortPreemptiveTickISR( void );
vPortPreemptiveTickISR();
#else
extern void vPortCooperativeTickISR( void );
vPortCooperativeTickISR();
#endif
}

View file

@ -42,72 +42,72 @@
#include "msp430.h"
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT int
#define portBASE_TYPE portSHORT
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT int
#define portBASE_TYPE portSHORT
/* The stack type changes depending on the data model. */
#ifdef __LARGE_DATA_MODEL__
#define portSTACK_TYPE uint32_t
#define portSTACK_TYPE uint32_t
#else
#define portSTACK_TYPE uint16_t
#define portPOINTER_SIZE_TYPE uint16_t
#define portSTACK_TYPE uint16_t
#define portPOINTER_SIZE_TYPE uint16_t
#endif
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
#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
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Interrupt control macros. */
#define portDISABLE_INTERRUPTS() _disable_interrupt(); _nop()
#define portENABLE_INTERRUPTS() _enable_interrupt(); _nop()
#define portDISABLE_INTERRUPTS() _disable_interrupt(); _nop()
#define portENABLE_INTERRUPTS() _enable_interrupt(); _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 usCriticalNesting 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 usCriticalNesting 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. */
@ -116,27 +116,28 @@ typedef unsigned short UBaseType_t;
* Manual context switch called by portYIELD or taskYIELD.
*/
extern void vPortYield( void );
#define portYIELD() vPortYield()
#define portYIELD() vPortYield()
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portBYTE_ALIGNMENT 2
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __no_operation()
#define portBYTE_ALIGNMENT 2
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __no_operation()
/*-----------------------------------------------------------*/
/* 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 )
extern void vTaskSwitchContext( void );
#define portYIELD_FROM_ISR( x ) if( x ) vPortYield()
#define portYIELD_FROM_ISR( x ) if( x ) vPortYield()
void vApplicationSetupTimerInterrupt( void );
/* sizeof( int ) != sizeof( long ) so a full printf() library is required if
* run time stats information is to be displayed. */
run time stats information is to be displayed. */
#define portLU_PRINTF_SPECIFIER_REQUIRED
#endif /* PORTMACRO_H */

View file

@ -30,158 +30,154 @@
#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)
/* The clock prescale into the timer peripheral. */
#define portPRESCALE_VALUE ( ( uint8_t ) 10 )
#define portPRESCALE_VALUE ( ( uint8_t ) 10 )
/* The clock frequency into the RTC. */
#define portRTC_CLOCK_HZ ( ( uint32_t ) 1000 )
#define portRTC_CLOCK_HZ ( ( uint32_t ) 1000 )
asm void interrupt VectorNumber_VL1swi vPortYieldISR( void );
static void prvSetupTimerInterrupt( void );
/* 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 )
{
uint32_t ulOriginalA5;
__asm {
MOVE.L A5, ulOriginalA5
};
uint32_t ulOriginalA5;
__asm{ MOVE.L A5, ulOriginalA5 };
*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. */
/* Parameter in A0. */
*( pxTopOfStack + 8 ) = ( StackType_t ) pvParameters;
/* Parameter in A0. */
*( pxTopOfStack + 8 ) = ( StackType_t ) pvParameters;
/* A5 must be maintained as it is resurved by the compiler. */
*( pxTopOfStack + 13 ) = ulOriginalA5;
/* A5 must be maintained as it is resurved by the compiler. */
*( pxTopOfStack + 13 ) = ulOriginalA5;
return pxTopOfStack;
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
extern void vPortStartFirstTask( void );
extern void vPortStartFirstTask( void );
ulCriticalNesting = 0UL;
ulCriticalNesting = 0UL;
/* Configure a timer to generate the tick interrupt. */
prvSetupTimerInterrupt();
/* Configure a timer to generate the tick interrupt. */
prvSetupTimerInterrupt();
/* Start the first task executing. */
vPortStartFirstTask();
/* Start the first task executing. */
vPortStartFirstTask();
return pdFALSE;
return pdFALSE;
}
/*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void )
{
/* Prescale by 1 - ie no prescale. */
RTCSC |= 8;
/* Compare match value. */
RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ;
/* Enable the RTC to generate interrupts - interrupts are already disabled
* when this code executes. */
RTCSC_RTIE = 1;
{
/* Prescale by 1 - ie no prescale. */
RTCSC |= 8;
/* Compare match value. */
RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ;
/* Enable the RTC to generate interrupts - interrupts are already disabled
when this code executes. */
RTCSC_RTIE = 1;
}
/*-----------------------------------------------------------*/
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( ulCriticalNesting == 0UL )
{
/* Guard against context switches being pended simultaneously with a
critical section being entered. */
do
{
portDISABLE_INTERRUPTS();
if( INTC_FRC == 0UL )
{
break;
}
if( INTC_FRC == 0UL )
{
break;
}
portENABLE_INTERRUPTS();
portENABLE_INTERRUPTS();
} while( 1 );
}
ulCriticalNesting++;
} 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. */
INTC_CFRC = 0x3E;
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. */
INTC_CFRC = 0x3E;
vTaskSwitchContext();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
}
/*-----------------------------------------------------------*/
void interrupt VectorNumber_Vrtc vPortTickISR( void )
{
uint32_t ulSavedInterruptMask;
uint32_t ulSavedInterruptMask;
/* Clear the interrupt. */
RTCSC |= RTCSC_RTIF_MASK;
/* Clear the interrupt. */
RTCSC |= RTCSC_RTIF_MASK;
/* Increment the RTOS tick. */
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
if( xTaskIncrementTick() != pdFALSE )
{
taskYIELD();
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
/* Increment the RTOS tick. */
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
if( xTaskIncrementTick() != pdFALSE )
{
taskYIELD();
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
}

View file

@ -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,73 +43,73 @@
*/
/* 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" )
/* Context switches are requested using the force register. */
#define portYIELD() INTC_SFRC = 0x3E; portNOP(); portNOP(); portNOP(); portNOP(); portNOP()
#define portYIELD() INTC_SFRC = 0x3E; portNOP(); portNOP(); portNOP(); 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 */

View file

@ -30,52 +30,50 @@
#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;
#define portSAVE_CONTEXT() \
lea.l( -60, % sp ), % sp; \
movem.l % d0 - % fp, ( % sp ); \
move.l pxCurrentTCB, % a0; \
move.l % sp, ( % a0 );
#define portSAVE_CONTEXT() \
lea.l (-60, %sp), %sp; \
movem.l %d0-%fp, (%sp); \
move.l pxCurrentTCB, %a0; \
move.l %sp, (%a0);
#define portRESTORE_CONTEXT() \
move.l pxCurrentTCB, % a0; \
move.l( % a0 ), % sp; \
movem.l( % sp ), % d0 - % fp; \
lea.l % sp@( 60 ), % sp; \
rte
#define portRESTORE_CONTEXT() \
move.l pxCurrentTCB, %a0; \
move.l (%a0), %sp; \
movem.l (%sp), %d0-%fp; \
lea.l %sp@(60), %sp; \
rte
/*-----------------------------------------------------------*/
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;
}
@ -83,68 +81,67 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
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( ulCriticalNesting == 0UL )
{
/* Guard against context switches being pended simultaneously with a
critical section being entered. */
do
{
portDISABLE_INTERRUPTS();
if( MCF_INTC0_INTFRCH == 0UL )
{
break;
}
if( MCF_INTC0_INTFRCH == 0UL )
{
break;
}
portENABLE_INTERRUPTS();
portENABLE_INTERRUPTS();
} while( 1 );
}
ulCriticalNesting++;
} 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 );
}
/*-----------------------------------------------------------*/

View file

@ -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,72 +43,72 @@
*/
/* 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() /* -32 as we are using the high word of the 64bit mask. */
#define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP() /* -32 as we are using the high word of the 64bit mask. */
/*-----------------------------------------------------------*/
/* 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 */

View file

@ -31,139 +31,137 @@
/*-----------------------------------------------------------
* 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 );
/* Interrupt service routines have to be in non-banked memory - as does the
* scheduler startup function. */
scheduler startup function. */
#pragma CODE_SEG __NEAR_SEG NON_BANKED
/* Manual context switch function. This is the SWI ISR. */
void interrupt vPortYield( void );
/* Manual context switch function. This is the SWI ISR. */
void interrupt vPortYield( void );
/* Tick context switch function. This is the timer ISR. */
void interrupt vPortTickInterrupt( void );
/* Simply called by xPortStartScheduler(). 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. */
static BaseType_t xBankedStartScheduler( void );
/* Tick context switch function. This is the timer ISR. */
void interrupt vPortTickInterrupt( void );
/* Simply called by xPortStartScheduler(). 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. */
static BaseType_t xBankedStartScheduler( void );
#pragma CODE_SEG DEFAULT
/* 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. */
/* 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 = 0xff;
/*-----------------------------------------------------------*/
/*
* 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 )
{
/*
* Place a few bytes of known values on the bottom of the stack.
* This can be uncommented to provide useful stack markers when debugging.
*
* pxTopOfStack = ( StackType_t ) 0x11;
* pxTopOfStack--;
* pxTopOfStack = ( StackType_t ) 0x22;
* pxTopOfStack--;
* pxTopOfStack = ( StackType_t ) 0x33;
* pxTopOfStack--;
*/
/*
Place a few bytes of known values on the bottom of the stack.
This can be uncommented to provide useful stack markers when debugging.
*pxTopOfStack = ( StackType_t ) 0x11;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x22;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x33;
pxTopOfStack--;
*/
/* 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--;
*pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pxCode ) ) + 0 );
pxTopOfStack--;
/* The address of the task function is placed in the stack byte at a time. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 1 );
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 0 );
pxTopOfStack--;
/* Next are all the registers that form part of the task context. */
/* Next are all the registers that form part of the task context. */
/* Y register */
*pxTopOfStack = ( StackType_t ) 0xff;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xee;
pxTopOfStack--;
/* Y register */
*pxTopOfStack = ( StackType_t ) 0xff;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xee;
pxTopOfStack--;
/* X register */
*pxTopOfStack = ( StackType_t ) 0xdd;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xcc;
pxTopOfStack--;
/* X register */
*pxTopOfStack = ( StackType_t ) 0xdd;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xcc;
pxTopOfStack--;
/* A register contains parameter high byte. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 );
pxTopOfStack--;
/* A register contains parameter high byte. */
*pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 0 );
pxTopOfStack--;
/* B register contains parameter low byte. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 );
pxTopOfStack--;
/* B register contains parameter low byte. */
*pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 1 );
pxTopOfStack--;
/* CCR: Note that when the task starts interrupts will be enabled since
"I" bit of CCR is cleared */
*pxTopOfStack = ( StackType_t ) 0x00;
pxTopOfStack--;
#ifdef BANKED_MODEL
/* The page of the task. */
*pxTopOfStack = ( StackType_t ) ( ( int ) pxCode );
pxTopOfStack--;
#endif
/* Finally the critical nesting depth is initialised with 0 (not within
a critical section). */
*pxTopOfStack = ( StackType_t ) 0x00;
/* CCR: Note that when the task starts interrupts will be enabled since
* "I" bit of CCR is cleared */
*pxTopOfStack = ( StackType_t ) 0x00;
pxTopOfStack--;
#ifdef BANKED_MODEL
/* The page of the task. */
*pxTopOfStack = ( StackType_t ) ( ( int ) pxCode );
pxTopOfStack--;
#endif
/* Finally the critical nesting depth is initialised with 0 (not within
* 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 )
{
TickTimer_SetFreqHz( configTICK_RATE_HZ );
TickTimer_Enable();
TickTimer_SetFreqHz( configTICK_RATE_HZ );
TickTimer_Enable();
}
/*-----------------------------------------------------------*/
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 xBankedStartScheduler() -
* 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 xBankedStartScheduler() -
which does use the CODE_SEG pragma. */
return xBankedStartScheduler();
return xBankedStartScheduler();
}
/*-----------------------------------------------------------*/
@ -171,18 +169,18 @@ BaseType_t xPortStartScheduler( void )
static BaseType_t xBankedStartScheduler( 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();
/* Simulate the end of an interrupt to start the scheduler off. */
__asm( "rti" );
/* Simulate the end of an interrupt to start the scheduler off. */
__asm( "rti" );
/* Should not get here! */
return pdFALSE;
/* Should not get here! */
return pdFALSE;
}
/*-----------------------------------------------------------*/
@ -196,42 +194,44 @@ static BaseType_t xBankedStartScheduler( void )
*/
void interrupt vPortYield( void )
{
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();
}
/*-----------------------------------------------------------*/
/*
* 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 interrupt vPortTickInterrupt( void )
{
#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 )
{
vTaskSwitchContext();
}
/* Increment the tick ... */
if( xTaskIncrementTick() != pdFALSE )
{
vTaskSwitchContext();
}
TFLG1 = 1;
TFLG1 = 1;
/* Restore the context of a task - which may be a different task
* to that interrupted. */
portRESTORE_CONTEXT();
}
#else /* if configUSE_PREEMPTION == 1 */
{
xTaskIncrementTick();
TFLG1 = 1;
}
#endif /* if configUSE_PREEMPTION == 1 */
/* Restore the context of a task - which may be a different task
to that interrupted. */
portRESTORE_CONTEXT();
}
#else
{
xTaskIncrementTick();
TFLG1 = 1;
}
#endif
}
#pragma CODE_SEG DEFAULT

View file

@ -40,38 +40,38 @@
*/
/* 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
#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
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 portNOP() __asm( "nop" );
#define portBYTE_ALIGNMENT 1
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portYIELD() __asm( "swi" );
#define portNOP() __asm( "nop" );
/*-----------------------------------------------------------*/
/* 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.
@ -79,29 +79,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. */
@ -117,71 +117,70 @@ typedef unsigned char UBaseType_t;
*/
#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() \
{ \
extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \
\
__asm( "ldx pxCurrentTCB" ); \
__asm( "lds 0, x" ); \
__asm( "pula" ); \
__asm( "staa uxCriticalNesting" ); \
__asm( "pula" ); \
__asm( "staa 0x30" ); /* 0x30 = PPAGE */ \
}
/*
* 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() \
{ \
extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \
\
__asm( "ldx pxCurrentTCB" ); \
__asm( "lds 0, x" ); \
__asm( "pula" ); \
__asm( "staa uxCriticalNesting" ); \
__asm( "pula" ); \
__asm( "staa 0x30" ); /* 0x30 = PPAGE */ \
}
/*
* 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() \
{ \
extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \
\
__asm( "ldaa 0x30" ); /* 0x30 = PPAGE */ \
__asm( "psha" ); \
__asm( "ldaa uxCriticalNesting" ); \
__asm( "psha" ); \
__asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \
}
#else
/*
* 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() \
{ \
extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \
\
__asm( "ldaa 0x30" ); /* 0x30 = PPAGE */ \
__asm( "psha" ); \
__asm( "ldaa uxCriticalNesting" ); \
__asm( "psha" ); \
__asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \
}
#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() \
{ \
extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \
\
__asm( "ldx pxCurrentTCB" ); \
__asm( "lds 0, x" ); \
__asm( "pula" ); \
__asm( "staa uxCriticalNesting" ); \
}
#define portRESTORE_CONTEXT() \
{ \
extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \
\
__asm( "ldx pxCurrentTCB" ); \
__asm( "lds 0, x" ); \
__asm( "pula" ); \
__asm( "staa uxCriticalNesting" ); \
}
#define portSAVE_CONTEXT() \
{ \
extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \
\
__asm( "ldaa uxCriticalNesting" ); \
__asm( "psha" ); \
__asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \
}
#endif /* ifdef BANKED_MODEL */
#define portSAVE_CONTEXT() \
{ \
extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \
\
__asm( "ldaa uxCriticalNesting" ); \
__asm( "psha" ); \
__asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \
}
#endif
/*
* Utility macro to call macros above in correct order in order to perform a
@ -189,14 +188,15 @@ typedef unsigned char UBaseType_t;
* the ISR does not use any local (stack) variables. If the ISR uses stack
* 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 )
#endif /* PORTMACRO_H */

View file

@ -27,13 +27,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>
@ -49,126 +49,124 @@
#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;
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;
#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. */
}
/*-----------------------------------------------------------*/
@ -177,63 +175,64 @@ 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...
*
* First at timer level */
portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS;
/* Enable the tick timer interrupt...
/* Then at the AIC level. */
AT91C_BASE_AIC->AIC_IECR = ( 1 << portTIMER_AIC_CHANNEL );
First at timer level */
portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS;
/* 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 );
}
/* Then at the AIC level. */
AT91C_BASE_AIC->AIC_IECR = (1 << portTIMER_AIC_CHANNEL);
/* Start tick timer... */
portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN;
/* 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;
}
/*-----------------------------------------------------------*/

View file

@ -27,17 +27,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. */
@ -45,18 +45,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.
*/
@ -65,93 +65,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 /* if configUSE_PREEMPTION == 0 */
#endif
/*-----------------------------------------------------------*/
/*
@ -162,71 +162,72 @@ 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. */
}
}
}

View file

@ -26,34 +26,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.
@ -66,42 +66,42 @@
*/
/* 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. */
@ -113,90 +113,90 @@
* 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. */
@ -207,48 +207,49 @@
* 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

View file

@ -1,50 +1,51 @@
/** ---------------------------------------------------------------------------- */
/** 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

View file

@ -27,12 +27,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>
@ -45,139 +45,137 @@
#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. */
}
/*-----------------------------------------------------------*/
@ -186,23 +184,30 @@ 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
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
/* 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
/* Configure the PIT period. */
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
extern void ( vNonPreemptiveTick ) ( void );
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vNonPreemptiveTick );
/* Enable the interrupt. Global interrupts are disables at this point so
* this is safe. */
#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. */
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS;
}
/*-----------------------------------------------------------*/

View file

@ -27,17 +27,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"
@ -46,17 +46,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
@ -67,9 +67,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();
}
/*-----------------------------------------------------------*/
@ -83,19 +83,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();
}
/*-----------------------------------------------------------*/
@ -106,49 +106,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 /* if configUSE_PREEMPTION == 0 */
#else
/* 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 /* if configUSE_PREEMPTION == 0 */
#endif
/*-----------------------------------------------------------*/
/*
@ -157,70 +157,71 @@ 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. */
}
}
}

View file

@ -26,34 +26,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.
@ -66,32 +66,32 @@
*/
/* 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" );
/*-----------------------------------------------------------*/
@ -104,92 +104,92 @@
* 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" )
/*-----------------------------------------------------------*/
@ -202,47 +202,48 @@
* 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 */

View file

@ -27,12 +27,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. */
@ -43,136 +43,134 @@
#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. */
}
/*-----------------------------------------------------------*/
@ -181,41 +179,43 @@ void vPortEndScheduler( void )
*/
static void prvSetupTimerInterrupt( void )
{
uint32_t ulCompareMatch;
uint32_t ulCompareMatch;
extern void ( vTickISR )( void );
extern void( vTickISR )( void );
/* 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;
/* 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;
/* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* 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;
/* 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;
/* Generate tick with timer 0 compare match. */
T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
/* Generate tick with timer 0 compare match. */
T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
/* 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. */
/* Setup the VIC for the timer. */
VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
VICVectAddr0 = ( int32_t ) vTickISR;
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
/* 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;
/* Start the timer - interrupts are disabled when this function is called
so it is okay to do this here. */
T0_TCR = portENABLE_TIMER;
}
/*-----------------------------------------------------------*/

View file

@ -27,45 +27,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
@ -76,9 +76,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();
}
/*-----------------------------------------------------------*/
@ -92,48 +92,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();
}
/*-----------------------------------------------------------*/
@ -145,71 +145,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. */
}
}
}

View file

@ -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,32 +43,32 @@
*/
/* 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" );
/*-----------------------------------------------------------*/
@ -81,92 +81,92 @@
* 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" )
/*-----------------------------------------------------------*/
@ -179,47 +179,48 @@
* 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 */

View file

@ -27,12 +27,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. */
@ -43,136 +43,134 @@
#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 ) 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;
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. */
}
/*-----------------------------------------------------------*/
@ -181,52 +179,55 @@ 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 */
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;
/* 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;
/* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* 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;
/* 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;
/* Generate tick with timer 0 compare match. */
T0MCR = (3 << 3); /* Reset timer on match and generate interrupt */
/* Generate tick with timer 0 compare match. */
T0MCR = ( 3 << 3 ); /* Reset timer on match and generate interrupt */
/* 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
/* Setup the VIC for the timer. */
VICIntEnable = 0x00000010;
VICVectCntl4 = 1;
/* 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;
/* Start the timer - interrupts are disabled when this function is called
so it is okay to do this here. */
T0TCR = portENABLE_TIMER;
}
/*-----------------------------------------------------------*/

View file

@ -27,29 +27,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.
*/
@ -58,39 +58,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.
*/
@ -98,46 +98,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 /* if configUSE_PREEMPTION == 0 */
#else
/* 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;
/* Ready for the next interrupt. */
T0IR = 2;
VICVectAddr = portCLEAR_VIC_INTERRUPT;
/* Restore the context of the new task. */
portRESTORE_CONTEXT();
}
/* Restore the context of the new task. */
portRESTORE_CONTEXT();
}
#endif /* if configUSE_PREEMPTION == 0 */
#endif
/*-----------------------------------------------------------*/
/*
@ -148,71 +148,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. */
}
}
}

View file

@ -26,34 +26,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.
@ -66,32 +66,32 @@
*/
/* 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" );
/*-----------------------------------------------------------*/
@ -104,92 +104,92 @@
* 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" )
/*-----------------------------------------------------------*/
@ -202,47 +202,48 @@
* 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 */

View file

@ -33,104 +33,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 )
/*-----------------------------------------------------------*/
@ -143,381 +143,376 @@ 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. */
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. */
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;
/* Counts the interrupt nesting depth. A context switch is only performed if
* if the nesting depth is 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.
*
* Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine how many priority bits are implemented in the GIC.
/* Determine the number of priority bits available. First write to
* all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to
all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Shift to the least significant bits. */
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
{
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
}
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
* value. */
/* Shift to the least significant bits. */
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
{
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
}
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 */
/* 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 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( ulAPSR == portEL1 )
#else
configASSERT( ulAPSR == portEL3 );
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 == 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 timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT();
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();
/* Start the first task executing. */
vPortRestoreTaskContext();
}
}
/* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT();
/* Start the first task executing. */
vPortRestoreTaskContext();
}
}
return 0;
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();
/* 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();
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;
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.
*
* 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 ) );
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.
/* 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 );
}
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 );
}
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/

View file

@ -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,169 +43,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 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 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
/*-----------------------------------------------------------
* 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 /* 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 */
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
/* 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 */

View file

@ -33,123 +33,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 )
/*-----------------------------------------------------------*/
@ -183,393 +183,386 @@ 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. */
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;
/* Counts the interrupt nesting depth. A context switch is only performed if
* if the nesting depth is 0. */
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.
*
* 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;
/* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro.
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{
/* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
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;
pxTopOfStack--;
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{
/* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
/* Next the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
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 the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
/* 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--;
#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 ) );
/* The task will start with a critical nesting count of 0 as interrupts are
enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
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 ) */
#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 ) );
return pxTopOfStack;
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;
}
/*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
/* 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 ).
for( ; ; )
{
}
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
uint32_t ulAPSR;
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.
*
* Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine how many priority bits are implemented in the GIC.
/* Determine the number of priority bits available. First write to
* all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to
all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Shift to the least significant bits. */
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
{
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
}
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
* value. */
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
/* Shift to the least significant bits. */
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
{
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
}
/* Restore the clobbered interrupt priority register to its original
* value. */
*pucFirstUserPriorityRegister = ulOriginalPriority;
}
#endif /* conifgASSERT_DEFINED */
/* 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 */
/* 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();
/* 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();
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;
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.
*
* 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 ) );
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.
/* 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 );
}
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 );
}
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
{
( void ) ulICCIAR;
configASSERT( ( volatile void * ) NULL );
( void ) ulICCIAR;
configASSERT( ( volatile void * ) NULL );
}

View file

@ -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,166 +43,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
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()
/* 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 )
#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 /* 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 */
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
/* 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 */

View file

@ -612,7 +612,7 @@ static void prvTaskExitError( void )
extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__;
#else /* if defined( __ARMCC_VERSION ) */
#else /* if defined( __ARMCC_VERSION ) */
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[];
@ -802,22 +802,22 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
ulR0 = pulCallerStackAddress[ 0 ];
#if ( configENABLE_MPU == 1 )
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
#endif /* configENABLE_MPU */
configASSERT( xSecureContext != NULL );
@ -835,21 +835,21 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
case portSVC_START_SCHEDULER:
#if ( configENABLE_TRUSTZONE == 1 )
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
/* Initialize the secure context management system. */
SecureContext_Init();
}
/* Initialize the secure context management system. */
SecureContext_Init();
}
#endif /* configENABLE_TRUSTZONE */
#if ( configENABLE_FPU == 1 )
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
#endif /* configENABLE_FPU */
/* Setup the context of the first task so that the first task starts
@ -882,12 +882,12 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
#else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) /* PRIVILEGED_FUNCTION */
void * pvParameters ) /* PRIVILEGED_FUNCTION */
#endif /* configENABLE_MPU */
{
/* Simulate the stack frame as it would be created by a context switch
@ -1051,7 +1051,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
int32_t lIndex = 0;
#if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */
extern uint32_t * __privileged_sram_start__;
@ -1079,8 +1081,8 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
* using a separate MPU region. This is needed because privileged
* SRAM is already protected using an MPU region and ARMv8-M does
* not allow overlapping MPU regions. */
if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ &&
ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ )
if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
{
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
@ -1089,7 +1091,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
/* Define the region that allows access to the stack. */
ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
( portMPU_REGION_NON_SHAREABLE ) |

View file

@ -55,13 +55,13 @@
* on the secure side. The following are the valid configuration seetings:
*
* 1. Run FreeRTOS on the Secure Side:
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
*
* 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
*
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
*/
#if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
@ -612,7 +612,7 @@ static void prvTaskExitError( void )
extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__;
#else /* if defined( __ARMCC_VERSION ) */
#else /* if defined( __ARMCC_VERSION ) */
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[];
@ -802,22 +802,22 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
ulR0 = pulCallerStackAddress[ 0 ];
#if ( configENABLE_MPU == 1 )
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
#endif /* configENABLE_MPU */
configASSERT( xSecureContext != NULL );
@ -835,21 +835,21 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
case portSVC_START_SCHEDULER:
#if ( configENABLE_TRUSTZONE == 1 )
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
/* Initialize the secure context management system. */
SecureContext_Init();
}
/* Initialize the secure context management system. */
SecureContext_Init();
}
#endif /* configENABLE_TRUSTZONE */
#if ( configENABLE_FPU == 1 )
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
#endif /* configENABLE_FPU */
/* Setup the context of the first task so that the first task starts
@ -877,18 +877,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
}
/*-----------------------------------------------------------*/
/* *INDENT-OFF* */
#if ( configENABLE_MPU == 1 )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
#else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) /* PRIVILEGED_FUNCTION */
void * pvParameters ) /* PRIVILEGED_FUNCTION */
#endif /* configENABLE_MPU */
/* *INDENT-ON* */
{
/* Simulate the stack frame as it would be created by a context switch
* interrupt. */
@ -1051,7 +1053,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
int32_t lIndex = 0;
#if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */
extern uint32_t * __privileged_sram_start__;
@ -1079,8 +1083,8 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
* using a separate MPU region. This is needed because privileged
* SRAM is already protected using an MPU region and ARMv8-M does
* not allow overlapping MPU regions. */
if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ &&
ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ )
if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
{
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
@ -1089,7 +1093,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
/* Define the region that allows access to the stack. */
ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
( portMPU_REGION_NON_SHAREABLE ) |

View file

@ -612,7 +612,7 @@ static void prvTaskExitError( void )
extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__;
#else /* if defined( __ARMCC_VERSION ) */
#else /* if defined( __ARMCC_VERSION ) */
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[];
@ -802,22 +802,22 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
ulR0 = pulCallerStackAddress[ 0 ];
#if ( configENABLE_MPU == 1 )
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
#endif /* configENABLE_MPU */
configASSERT( xSecureContext != NULL );
@ -835,21 +835,21 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
case portSVC_START_SCHEDULER:
#if ( configENABLE_TRUSTZONE == 1 )
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
/* Initialize the secure context management system. */
SecureContext_Init();
}
/* Initialize the secure context management system. */
SecureContext_Init();
}
#endif /* configENABLE_TRUSTZONE */
#if ( configENABLE_FPU == 1 )
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
#endif /* configENABLE_FPU */
/* Setup the context of the first task so that the first task starts
@ -877,18 +877,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
}
/*-----------------------------------------------------------*/
/* *INDENT-OFF* */
#if ( configENABLE_MPU == 1 )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
#else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) /* PRIVILEGED_FUNCTION */
void * pvParameters ) /* PRIVILEGED_FUNCTION */
#endif /* configENABLE_MPU */
/* *INDENT-ON* */
{
/* Simulate the stack frame as it would be created by a context switch
* interrupt. */
@ -1051,7 +1053,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
int32_t lIndex = 0;
#if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */
extern uint32_t * __privileged_sram_start__;
@ -1079,8 +1083,8 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
* using a separate MPU region. This is needed because privileged
* SRAM is already protected using an MPU region and ARMv8-M does
* not allow overlapping MPU regions. */
if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ &&
ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ )
if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
{
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
@ -1089,7 +1093,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
/* Define the region that allows access to the stack. */
ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
( portMPU_REGION_NON_SHAREABLE ) |

View file

@ -612,7 +612,7 @@ static void prvTaskExitError( void )
extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__;
#else /* if defined( __ARMCC_VERSION ) */
#else /* if defined( __ARMCC_VERSION ) */
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[];
@ -802,22 +802,22 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
ulR0 = pulCallerStackAddress[ 0 ];
#if ( configENABLE_MPU == 1 )
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
{
/* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* The task that raised the SVC is privileged if Bit[0]
* in the CONTROL register is 0. */
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
}
#endif /* configENABLE_MPU */
configASSERT( xSecureContext != NULL );
@ -835,21 +835,21 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
case portSVC_START_SCHEDULER:
#if ( configENABLE_TRUSTZONE == 1 )
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
{
/* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */
SecureInit_DePrioritizeNSExceptions();
/* Initialize the secure context management system. */
SecureContext_Init();
}
/* Initialize the secure context management system. */
SecureContext_Init();
}
#endif /* configENABLE_TRUSTZONE */
#if ( configENABLE_FPU == 1 )
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
{
/* Setup the Floating Point Unit (FPU). */
prvSetupFPU();
}
#endif /* configENABLE_FPU */
/* Setup the context of the first task so that the first task starts
@ -877,18 +877,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
}
/*-----------------------------------------------------------*/
/* *INDENT-OFF* */
#if ( configENABLE_MPU == 1 )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
#else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) /* PRIVILEGED_FUNCTION */
void * pvParameters ) /* PRIVILEGED_FUNCTION */
#endif /* configENABLE_MPU */
/* *INDENT-ON* */
{
/* Simulate the stack frame as it would be created by a context switch
* interrupt. */
@ -1051,7 +1053,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
int32_t lIndex = 0;
#if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */
extern uint32_t * __privileged_sram_start__;
@ -1079,8 +1083,8 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
* using a separate MPU region. This is needed because privileged
* SRAM is already protected using an MPU region and ARMv8-M does
* not allow overlapping MPU regions. */
if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ &&
ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ )
if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
{
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
@ -1089,7 +1093,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
{
/* Define the region that allows access to the stack. */
ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
( portMPU_REGION_NON_SHAREABLE ) |

View file

@ -360,14 +360,14 @@ static void prvRestoreContextOfFirstTask( void )
" str r3, [r2] \n"/* Disable MPU. */
" \n"
" ldr r2, =0xe000ed9c \n"/* Region Base Address register. */
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
" stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
" \n"
#if ( portTOTAL_NUM_REGIONS == 16 )
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
" stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
" stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
#endif /* portTOTAL_NUM_REGIONS == 16. */
" \n"
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
@ -584,14 +584,14 @@ void xPortPendSVHandler( void )
" str r3, [r2] \n"/* Disable MPU. */
" \n"
" ldr r2, =0xe000ed9c \n"/* Region Base Address register. */
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
" stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
" \n"
#if ( portTOTAL_NUM_REGIONS == 16 )
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
" stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
" stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
#endif /* portTOTAL_NUM_REGIONS == 16. */
" \n"
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
@ -941,10 +941,10 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
* be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority,
* Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid.
* and therefore also guaranteed to be invalid.
*
* FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible.

View file

@ -27,11 +27,14 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/*-----------------------------------------------------------
* Port specific definitions.
@ -44,169 +47,170 @@
*/
/* 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
#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 )
/* Location of the TEX,S,C,B bits in the MPU Region Attribute and Size
* Register (RASR). */
#define portMPU_RASR_TEX_S_C_B_LOCATION ( 16UL )
#define portMPU_RASR_TEX_S_C_B_MASK ( 0x3FUL )
#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 )
/* MPU settings that can be overriden in FreeRTOSConfig.h. */
#ifndef configTOTAL_MPU_REGIONS
/* Define to 8 for backward compatibility. */
#define configTOTAL_MPU_REGIONS ( 8UL )
#endif
/* Location of the TEX,S,C,B bits in the MPU Region Attribute and Size
* Register (RASR). */
#define portMPU_RASR_TEX_S_C_B_LOCATION ( 16UL )
#define portMPU_RASR_TEX_S_C_B_MASK ( 0x3FUL )
/*
* The TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits define the
* memory type, and where necessary the cacheable and shareable properties
* of the memory region.
*
* The TEX, C, and B bits together indicate the memory type of the region,
* and:
* - For Normal memory, the cacheable properties of the region.
* - For Device memory, whether the region is shareable.
*
* For Normal memory regions, the S bit indicates whether the region is
* shareable. For Strongly-ordered and Device memory, the S bit is ignored.
*
* See the following two tables for setting TEX, S, C and B bits for
* unprivileged flash, privileged flash and privileged RAM regions.
*
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| TEX | C | B | Memory type | Description or Normal region cacheability | Shareable? |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 0 | Strongly-ordered | Strongly ordered | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 1 | Device | Shared device | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 0 | Normal | Outer and inner write-through; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 1 | Normal | Outer and inner write-back; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 0 | Normal | Outer and inner Non-cacheable | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 0 | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 1 | Normal | Outer and inner write-back; write and read allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 0 | Device | Non-shared device | Not shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 1 | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 011 | X | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 1BB | A | A | Normal | Cached memory, with AA and BB indicating the inner and | Reserved |
| | | | | outer cacheability rules that must be exported on the | |
| | | | | bus. See the table below for the cacheability policy | |
| | | | | encoding. memory, BB=Outer policy, AA=Inner policy. | |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
/* MPU settings that can be overriden in FreeRTOSConfig.h. */
#ifndef configTOTAL_MPU_REGIONS
/* Define to 8 for backward compatibility. */
#define configTOTAL_MPU_REGIONS ( 8UL )
#endif
+-----------------------------------------+----------------------------------------+
| AA or BB subfield of {TEX,C,B} encoding | Cacheability policy |
+-----------------------------------------+----------------------------------------+
| 00 | Non-cacheable |
+-----------------------------------------+----------------------------------------+
| 01 | Write-back, write and read allocate |
+-----------------------------------------+----------------------------------------+
| 10 | Write-through, no write allocate |
+-----------------------------------------+----------------------------------------+
| 11 | Write-back, no write allocate |
+-----------------------------------------+----------------------------------------+
*/
/*
* The TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits define the
* memory type, and where necessary the cacheable and shareable properties
* of the memory region.
*
* The TEX, C, and B bits together indicate the memory type of the region,
* and:
* - For Normal memory, the cacheable properties of the region.
* - For Device memory, whether the region is shareable.
*
* For Normal memory regions, the S bit indicates whether the region is
* shareable. For Strongly-ordered and Device memory, the S bit is ignored.
*
* See the following two tables for setting TEX, S, C and B bits for
* unprivileged flash, privileged flash and privileged RAM regions.
*
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| TEX | C | B | Memory type | Description or Normal region cacheability | Shareable? |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 0 | Strongly-ordered | Strongly ordered | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 1 | Device | Shared device | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 0 | Normal | Outer and inner write-through; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 1 | Normal | Outer and inner write-back; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 0 | Normal | Outer and inner Non-cacheable | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 0 | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 1 | Normal | Outer and inner write-back; write and read allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 0 | Device | Non-shared device | Not shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 1 | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 011 | X | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 1BB | A | A | Normal | Cached memory, with AA and BB indicating the inner and | Reserved |
| | | | | outer cacheability rules that must be exported on the | |
| | | | | bus. See the table below for the cacheability policy | |
| | | | | encoding. memory, BB=Outer policy, AA=Inner policy. | |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
|
+-----------------------------------------+----------------------------------------+
| AA or BB subfield of {TEX,C,B} encoding | Cacheability policy |
+-----------------------------------------+----------------------------------------+
| 00 | Non-cacheable |
+-----------------------------------------+----------------------------------------+
| 01 | Write-back, write and read allocate |
+-----------------------------------------+----------------------------------------+
| 10 | Write-through, no write allocate |
+-----------------------------------------+----------------------------------------+
| 11 | Write-back, no write allocate |
+-----------------------------------------+----------------------------------------+
*/
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for flash
* region. */
#ifndef configTEX_S_C_B_FLASH
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_FLASH ( 0x07UL )
#endif
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for flash
* region. */
#ifndef configTEX_S_C_B_FLASH
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_FLASH ( 0x07UL )
#endif
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for RAM
* region. */
#ifndef configTEX_S_C_B_SRAM
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_SRAM ( 0x07UL )
#endif
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for RAM
* region. */
#ifndef configTEX_S_C_B_SRAM
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_SRAM ( 0x07UL )
#endif
#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 portTOTAL_NUM_REGIONS ( configTOTAL_MPU_REGIONS )
#define portNUM_CONFIGURABLE_REGIONS ( portTOTAL_NUM_REGIONS - portFIRST_CONFIGURABLE_REGION )
#define portLAST_CONFIGURABLE_REGION ( portTOTAL_NUM_REGIONS - 1 )
#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 portTOTAL_NUM_REGIONS ( configTOTAL_MPU_REGIONS )
#define portNUM_CONFIGURABLE_REGIONS ( portTOTAL_NUM_REGIONS - portFIRST_CONFIGURABLE_REGION )
#define portLAST_CONFIGURABLE_REGION ( portTOTAL_NUM_REGIONS - 1 )
#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() \
#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; \
@ -217,178 +221,181 @@
__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 )
#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;
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
{
uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
return ucReturn;
}
return ucReturn;
}
/* 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
#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 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 ) ) )
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( 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
#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 )
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" );
if( ulCurrentInterrupt == 0 )
{
uint32_t ulCurrentInterrupt;
BaseType_t xReturn;
/* Obtain the number of the currently executing interrupt. */
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
if( ulCurrentInterrupt == 0 )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
return xReturn;
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
/*-----------------------------------------------------------*/
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"
);
}
return xReturn;
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t 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
(
" mov %0, %1 \n"\
" msr basepri, %0 \n"\
" isb \n"\
" dsb \n"\
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
);
}
/* 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 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"
);
/* This return will not be reached but is necessary to prevent compiler
* warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
#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
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
{
__asm volatile
(
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "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
/*-----------------------------------------------------------*/
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

View file

@ -149,17 +149,18 @@
/* Adding the necessary stuff in order to be able to determine from C code wheter or not the IRQs are enabled at the processor level (not interrupt controller level) */
#define GET_CPSR() ({u32 rval = 0U; \
__asm__ __volatile__(\
"mrs %0, cpsr\n"\
: "=r" (rval)\
);\
rval;\
})
#define GET_CPSR() \
( { u32 rval = 0U; \
__asm__ __volatile__ ( \
"mrs %0, cpsr\n"\
: "=r" ( rval ) \
); \
rval; \
} )
#define CPSR_IRQ_ENABLE_MASK 0x80U
#define CPSR_IRQ_ENABLE_MASK 0x80U
#define IS_IRQ_DISABLED() ({unsigned int val = 0; val = (GET_CPSR() & CPSR_IRQ_ENABLE_MASK) ? 1 : 0; val;})
#define IS_IRQ_DISABLED() ( { unsigned int val = 0; val = ( GET_CPSR() & CPSR_IRQ_ENABLE_MASK ) ? 1 : 0; val; } )
/*-----------------------------------------------------------*/
/*
@ -482,12 +483,12 @@ uint32_t ulPortSetInterruptMask( void )
{
uint32_t ulReturn;
uint32_t wasIRQDisabled;
/* We keep track of if the IRQ are enabled in the CPU (as opposed to interrupts masked in the interrupt controller, like the intend of this function).
* This is very important because when the CPU is interrupted, among other things, the hardware clears the IRQ Enable bit in the CPSR of the IRQ CPU Mode in which
* we enter. */
wasIRQDisabled = IS_IRQ_DISABLED();
/* Interrupt in the CPU must be turned off while the ICCPMR is being
* updated. */
portCPU_IRQ_DISABLE();
@ -505,18 +506,20 @@ uint32_t ulPortSetInterruptMask( void )
"isb \n"::: "memory" );
}
/* Just like this function returns a value of wether or not the interrupts where masked in the interrupt controller in order to avoid race condition when
/* Just like this function returns a value of wether or not the interrupts where masked in the interrupt controller in order to avoid race condition when
* calling its matching vPortClearInterruptMask function, we needed a 'wasIRQDisabled' variable holding the state of the IRQ Enable bit in the CPSR in order
* to leave that bit in it's original state. Like mentioned above, hardware automatically clear the IRQEnable bit upon trapping into IRQ Mode, so the programmer
* to leave that bit in it's original state. Like mentioned above, hardware automatically clear the IRQEnable bit upon trapping into IRQ Mode, so the programmer
* cannot make assumption about it's state. Very rare, but very important race condition is avoided with this when this function is called in an ISR. The race
* condition in question was discovered when integrating tracealyzer code. Inside the function 'void vTaskSwitchContext( void )' in tasks.c, there is a macro 'traceTASK_SWITCHED_IN();'
* which gets replaced by something when using the tracing capabilities. That macro protects some critical section with matching calls to 'ulPortSetInterruptMask'
* which gets replaced by something when using the tracing capabilities. That macro protects some critical section with matching calls to 'ulPortSetInterruptMask'
* and 'vPortClearInterruptMask'. At the time of calling those functions, the interrupt mask is not set in the interrupt controller, thus the only protecting barrier
* against the CPU traping into recursive interrupt was the IRQ Enable bit in the CPSR. By not taking it into acount, the very code that protects the CPU against
* critical section violation just enabled it to happen : A SysTick was waiting to happen, and calling 'portCPU_IRQ_ENABLE' would enable it to occur... Thus triggering a
* against the CPU traping into recursive interrupt was the IRQ Enable bit in the CPSR. By not taking it into acount, the very code that protects the CPU against
* critical section violation just enabled it to happen : A SysTick was waiting to happen, and calling 'portCPU_IRQ_ENABLE' would enable it to occur... Thus triggering a
* switch of context while already performing a switch context. */
if(!wasIRQDisabled)
portCPU_IRQ_ENABLE();
if( !wasIRQDisabled )
{
portCPU_IRQ_ENABLE();
}
return ulReturn;
}

View file

@ -33,50 +33,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
/*-----------------------------------------------------------*/
@ -95,229 +95,225 @@ 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. */
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;
/* Counts the interrupt nesting depth. A context switch is only performed if
* if the nesting depth is 0. */
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.
*
* 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;
/* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro.
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{
/* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
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;
pxTopOfStack--;
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{
/* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
/* Next the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
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 the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
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 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 with a critical nesting count of 0 as interrupts are
enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--;
return 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;
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 ).
*
* 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();
/* 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 ).
for( ; ; )
{
}
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
uint32_t ulAPSR;
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" );
/* 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 );
ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE );
if( ulAPSR != portAPSR_USER_MODE )
{
/* Start the timer that generates the tick ISR. */
portDISABLE_INTERRUPTS();
configSETUP_TICK_INTERRUPT();
if( ulAPSR != portAPSR_USER_MODE )
{
/* Start the timer that generates the tick ISR. */
portDISABLE_INTERRUPTS();
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 )
{
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" );
}
/*-----------------------------------------------------------*/

View file

@ -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,141 +43,139 @@
*/
/* 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" );
__asm volatile ( "MRS %0, CPSR" : "=r" (ulCPSR) :: "memory" );
ulCPSR &= portINTERRUPT_ENABLE_BIT;
portDISABLE_INTERRUPTS();
return ulCPSR;
}
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()
#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 */

View file

@ -25,14 +25,14 @@
* 1 tab == 4 spaces!
*/
/*
*
* 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>
@ -41,135 +41,135 @@
#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" \
);
/*-----------------------------------------------------------*/
@ -179,147 +179,145 @@ 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. */
}
/*-----------------------------------------------------------*/
@ -327,36 +325,34 @@ 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();
portSAVE_CONTEXT();
if( xTaskIncrementTick() != pdFALSE )
{
vTaskSwitchContext();
}
portRESTORE_CONTEXT();
if( xTaskIncrementTick() != pdFALSE )
{
vTaskSwitchContext();
}
portRESTORE_CONTEXT();
asm volatile ( "ret" );
asm volatile ( "ret" );
}
/*-----------------------------------------------------------*/
@ -365,63 +361,66 @@ 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 /* 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();
*/
void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal ) );
void SIG_OUTPUT_COMPARE1A( void )
{
xTaskIncrementTick();
}
#endif

View file

@ -26,18 +26,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.
@ -50,59 +50,58 @@
*/
/* 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 */

View file

@ -1,5 +1,4 @@
/*This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief FreeRTOS port source for AVR32 UC3.
@ -53,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. */
@ -85,53 +84,55 @@ 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
/* Initialize the heap used by malloc. */
for( pxMem = &__heap_start__; pxMem < ( BaseType_t * ) &__heap_end__; )
{
*pxMem++ = 0xA5A5A5A5;
}
#endif
#if configHEAP_INIT
/* Give the used CPU clock frequency to Newlib, so it can work properly. */
set_cpu_hz( configCPU_CLOCK_HZ );
/* Initialize the heap used by malloc. */
for( pxMem = &__heap_start__; pxMem < ( BaseType_t * )&__heap_end__; )
{
*pxMem++ = 0xA5A5A5A5;
}
/* 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 }
};
#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 */
/* 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
}
/*-----------------------------------------------------------*/
@ -154,9 +155,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,96 +165,92 @@ 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
#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
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)
* clock cycles from now. */
prvScheduleNextTick();
#endif
/* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
calls in a critical section . */
portENTER_CRITICAL();
xTaskIncrementTick();
portEXIT_CRITICAL();
/* 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();
/* 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();
}
}
}
/*-----------------------------------------------------------*/
@ -263,182 +260,176 @@ __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 );
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;
/* 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 ) */
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
/*-----------------------------------------------------------*/
/* Setup the timer to generate the tick interrupts. */
static void prvSetupTimerInterrupt( void )
static void prvSetupTimerInterrupt(void)
{
#if ( configTICK_USE_TC == 1 )
volatile avr32_tc_t * tc = &AVR32_TC;
#if( configTICK_USE_TC==1 )
/* Options for waveform genration. */
tc_waveform_opt_t waveform_opt =
{
.channel = configTICK_TC_CHANNEL, /* Channel selection. */
volatile avr32_tc_t *tc = &AVR32_TC;
.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. */
// Options for waveform genration.
tc_waveform_opt_t waveform_opt =
{
.channel = configTICK_TC_CHANNEL, /* Channel selection. */
.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). */
.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. */
.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. */
.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). */
.burst = FALSE, /* Burst signal selection. */
.clki = FALSE, /* Clock inversion. */
.tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */
};
.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. */
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 ) */
.burst = FALSE, /* Burst signal selection. */
.clki = FALSE, /* Clock inversion. */
.tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */
};
/* Disable all interrupt/exception. */
portDISABLE_INTERRUPTS();
tc_interrupt_t tc_interrupt =
{
.etrgs=0,
.ldrbs=0,
.ldras=0,
.cpcs =1,
.cpbs =0,
.cpas =0,
.lovrs=0,
.covfs=0,
};
/* Register the compare interrupt handler to the interrupt controller and
* enable the compare interrupt. */
#endif
#if ( configTICK_USE_TC == 1 )
{
INTC_register_interrupt( &vTick, configTICK_TC_IRQ, INT0 );
/* Disable all interrupt/exception. */
portDISABLE_INTERRUPTS();
/* Initialize the timer/counter. */
tc_init_waveform( tc, &waveform_opt );
/* Register the compare interrupt handler to the interrupt controller and
enable the compare 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 );
#if( configTICK_USE_TC==1 )
{
INTC_register_interrupt(&vTick, configTICK_TC_IRQ, INT0);
tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt );
/* Initialize the timer/counter. */
tc_init_waveform(tc, &waveform_opt);
/* 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 ) */
/* 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
}

File diff suppressed because it is too large Load diff

View file

@ -34,18 +34,18 @@
#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 )
/*-----------------------------------------------------------*/
/* 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 RTOS_TCB_t;
extern volatile RTOS_TCB_t *volatile pxCurrentTCB;
extern volatile RTOS_TCB_t * volatile pxCurrentTCB;
/*-----------------------------------------------------------*/
@ -65,161 +65,163 @@ extern volatile RTOS_TCB_t *volatile pxCurrentTCB;
* 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" \
"in r0, __RAMPZ__ \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, __SP_L__ \n\t" \
"st x+, r0 \n\t" \
"in r0, __SP_H__ \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" \
"in r0, __RAMPZ__ \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, __SP_L__ \n\t" \
"st x+, r0 \n\t" \
"in r0, __SP_H__ \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.
*/
#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 __RAMPZ__, r0 \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 __RAMPZ__, r0 \n\t" \
"pop r0 \n\t" \
"out __SREG__, r0 \n\t" \
"pop r0 \n\t" );
/*-----------------------------------------------------------*/
/*
* Perform hardware setup to enable ticks from timer.
*/
static void prvSetupTimerInterrupt(void);
static void prvSetupTimerInterrupt( 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 )
{
uint16_t usAddress;
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
/* Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging. Uncomment if needed. */
// *pxTopOfStack = 0x11;
// pxTopOfStack--;
// *pxTopOfStack = 0x22;
// pxTopOfStack--;
// *pxTopOfStack = 0x33;
// pxTopOfStack--;
* This is just useful for debugging. Uncomment if needed. */
/* *pxTopOfStack = 0x11; */
/* pxTopOfStack--; */
/* *pxTopOfStack = 0x22; */
/* pxTopOfStack--; */
/* *pxTopOfStack = 0x33; */
/* 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);
* 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 = ( 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 */
* 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--;
*pxTopOfStack = ( StackType_t ) 0x00; /* RAMPZ */
*pxTopOfStack = ( StackType_t ) 0x00; /* RAMPZ */
pxTopOfStack--;
/* Now the remaining registers. The compiler expects R1 to be 0. */
*pxTopOfStack = (StackType_t)0x00; /* R1 */
*pxTopOfStack = ( StackType_t ) 0x00; /* R1 */
/* Leave R2 - R23 untouched */
pxTopOfStack -= 23;
/* Place the parameter on the stack in the expected location. */
usAddress = (uint16_t)pvParameters;
*pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff);
usAddress = ( uint16_t ) pvParameters;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff);
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
/* Leave register R26 - R31 untouched */
pxTopOfStack -= 7;
@ -230,7 +232,7 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler(void)
BaseType_t xPortStartScheduler( void )
{
/* Setup the hardware to generate the tick. */
prvSetupTimerInterrupt();
@ -239,15 +241,15 @@ BaseType_t xPortStartScheduler(void)
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");
* jump to the start of the task the context of which we have just restored. */
asm volatile ( "ret" );
/* Should not get here. */
return pdTRUE;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler(void)
void vPortEndScheduler( void )
{
/* vPortEndScheduler is not implemented in this port. */
}
@ -257,13 +259,13 @@ 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)
void vPortYield( void ) __attribute__( ( naked ) );
void vPortYield( void )
{
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();
asm volatile("ret");
asm volatile ( "ret" );
}
/*-----------------------------------------------------------*/
@ -271,13 +273,13 @@ void vPortYield(void)
* Manual context switch callable from ISRs. The first thing
* we do is save the registers so we can use a naked attribute.
*/
void vPortYieldFromISR(void) __attribute__((naked));
void vPortYieldFromISR(void)
void vPortYieldFromISR( void ) __attribute__( ( naked ) );
void vPortYieldFromISR( void )
{
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();
asm volatile("reti");
asm volatile ( "reti" );
}
/*-----------------------------------------------------------*/
@ -287,24 +289,26 @@ void vPortYieldFromISR(void)
* 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)
void vPortYieldFromTick( void ) __attribute__( ( naked ) );
void vPortYieldFromTick( void )
{
portSAVE_CONTEXT();
if (xTaskIncrementTick() != pdFALSE) {
if( xTaskIncrementTick() != pdFALSE )
{
vTaskSwitchContext();
}
portRESTORE_CONTEXT();
asm volatile("reti");
asm volatile ( "reti" );
}
/*-----------------------------------------------------------*/
/*
* Setup timer to generate a tick interrupt.
*/
static void prvSetupTimerInterrupt(void)
static void prvSetupTimerInterrupt( void )
{
TICK_init();
}
@ -317,26 +321,26 @@ static void prvSetupTimerInterrupt(void)
* the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved.
*/
ISR(TICK_INT_vect, ISR_NAKED)
{
/* Clear tick interrupt flag. */
CLR_INT(INT_FLAGS, INT_MASK);
ISR( TICK_INT_vect, ISR_NAKED )
{
/* Clear tick interrupt flag. */
CLR_INT( INT_FLAGS, INT_MASK );
vPortYieldFromTick();
vPortYieldFromTick();
asm volatile("reti");
}
#else
asm volatile ( "reti" );
}
#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();
*/
ISR(TICK_INT_vect)
{
/* Clear tick interrupt flag. */
INT_FLAGS = INT_MASK;
xTaskIncrementTick();
}
#endif
ISR( TICK_INT_vect )
{
/* Clear tick interrupt flag. */
INT_FLAGS = INT_MASK;
xTaskIncrementTick();
}
#endif /* if configUSE_PREEMPTION == 1 */

View file

@ -5,98 +5,104 @@
/*-----------------------------------------------------------*/
#define CLR_INT(FLAG_REG, FLAG_MASK) \
asm volatile( \
"push r16\n\t" \
"ldi r16, %1\n\t" \
"sts %0, r16\n\t" \
"pop r16\n\t" \
: \
: "i"(_SFR_MEM_ADDR(FLAG_REG)),"i"((uint8_t)(FLAG_MASK)) \
#define CLR_INT( FLAG_REG, FLAG_MASK ) \
asm volatile ( \
"push r16\n\t" \
"ldi r16, %1\n\t" \
"sts %0, r16\n\t" \
"pop r16\n\t" \
: \
: "i" ( _SFR_MEM_ADDR( FLAG_REG ) ), "i" ( ( uint8_t ) ( FLAG_MASK ) ) \
);
#if ( configUSE_TIMER_INSTANCE == 0 )
#define TICK_INT_vect TCB0_INT_vect
#define INT_FLAGS TCB0_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB0_INT_vect
#define INT_FLAGS TCB0_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB0.INTCTRL = TCB_CAPT_bm; \
TCB0.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() \
{ \
TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB0.INTCTRL = TCB_CAPT_bm; \
TCB0.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 1 )
#define TICK_INT_vect TCB1_INT_vect
#define INT_FLAGS TCB1_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB1_INT_vect
#define INT_FLAGS TCB1_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() \
{ \
TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB1.INTCTRL = TCB_CAPT_bm; \
TCB1.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() { \
TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB1.INTCTRL = TCB_CAPT_bm; \
TCB1.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 2 )
#define TICK_INT_vect TCB2_INT_vect
#define INT_FLAGS TCB2_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB2_INT_vect
#define INT_FLAGS TCB2_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() \
{ \
TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB2.INTCTRL = TCB_CAPT_bm; \
TCB2.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() { \
TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB2.INTCTRL = TCB_CAPT_bm; \
TCB2.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 3 )
#define TICK_INT_vect TCB3_INT_vect
#define INT_FLAGS TCB3_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB3_INT_vect
#define INT_FLAGS TCB3_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() \
{ \
TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB3.INTCTRL = TCB_CAPT_bm; \
TCB3.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() { \
TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB3.INTCTRL = TCB_CAPT_bm; \
TCB3.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 4 )
#define TICK_INT_vect TCB4_INT_vect
#define INT_FLAGS TCB4_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB4_INT_vect
#define INT_FLAGS TCB4_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB4.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB4.INTCTRL = TCB_CAPT_bm; \
TCB4.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() \
{ \
TCB4.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB4.INTCTRL = TCB_CAPT_bm; \
TCB4.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 5 )
#define TICK_INT_vect RTC_CNT_vect
#define INT_FLAGS RTC_INTFLAGS
#define INT_MASK RTC_OVF_bm
#define TICK_INT_vect RTC_CNT_vect
#define INT_FLAGS RTC_INTFLAGS
#define INT_MASK RTC_OVF_bm
/* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) )
#define TICK_init() { \
while (RTC.STATUS > 0); \
RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \
RTC.PER = RTC_PERIOD_HZ(configTICK_RATE_HZ); \
RTC.INTCTRL |= 1 << RTC_OVF_bp; \
}
/* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ( x ) ( 32768 * ( ( 1.0 / x ) ) )
#define TICK_init() \
{ \
while( RTC.STATUS > 0 ) {; } \
RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \
RTC.PER = RTC_PERIOD_HZ( configTICK_RATE_HZ ); \
RTC.INTCTRL |= 1 << RTC_OVF_bp; \
}
#else
#else /* if ( configUSE_TIMER_INSTANCE == 0 ) */
#undef TICK_INT_vect
#undef INT_FLAGS
#undef INT_MASK
#undef TICK_init()
#error Invalid timer setting.
#endif
#endif /* if ( configUSE_TIMER_INSTANCE == 0 ) */
/*-----------------------------------------------------------*/

View file

@ -23,14 +23,16 @@
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/*-----------------------------------------------------------
* Port specific definitions.
@ -43,64 +45,66 @@ 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
#define portPOINTER_SIZE_TYPE uint16_t
#define portPOINTER_SIZE_TYPE uint16_t
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
#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
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()
extern void vPortYieldFromISR(void) __attribute__((naked));
#define portYIELD_FROM_ISR() vPortYieldFromISR()
extern void vPortYieldFromISR( void ) __attribute__( ( naked ) );
#define portYIELD_FROM_ISR() vPortYieldFromISR()
/*-----------------------------------------------------------*/
/* 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
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

View file

@ -34,18 +34,18 @@
#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 )
/*-----------------------------------------------------------*/
/* 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 RTOS_TCB_t;
extern volatile RTOS_TCB_t *volatile pxCurrentTCB;
extern volatile RTOS_TCB_t * volatile pxCurrentTCB;
/*-----------------------------------------------------------*/
@ -65,155 +65,157 @@ extern volatile RTOS_TCB_t *volatile pxCurrentTCB;
* 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, __SP_L__ \n\t" \
"st x+, r0 \n\t" \
"in r0, __SP_H__ \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, __SP_L__ \n\t" \
"st x+, r0 \n\t" \
"in r0, __SP_H__ \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.
*/
#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" );
/*-----------------------------------------------------------*/
/*
* Perform hardware setup to enable ticks from timer.
*/
static void prvSetupTimerInterrupt(void);
static void prvSetupTimerInterrupt( 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 )
{
uint16_t usAddress;
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
/* Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging. Uncomment if needed. */
// *pxTopOfStack = 0x11;
// pxTopOfStack--;
// *pxTopOfStack = 0x22;
// pxTopOfStack--;
// *pxTopOfStack = 0x33;
// pxTopOfStack--;
* This is just useful for debugging. Uncomment if needed. */
/* *pxTopOfStack = 0x11; */
/* pxTopOfStack--; */
/* *pxTopOfStack = 0x22; */
/* pxTopOfStack--; */
/* *pxTopOfStack = 0x33; */
/* 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);
* 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 = ( 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 */
* 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 = ( StackType_t ) 0x00; /* R1 */
/* Leave R2 - R23 untouched */
pxTopOfStack -= 23;
/* Place the parameter on the stack in the expected location. */
usAddress = (uint16_t)pvParameters;
*pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff);
usAddress = ( uint16_t ) pvParameters;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff);
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
/* Leave register R26 - R31 untouched */
pxTopOfStack -= 7;
@ -224,7 +226,7 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler(void)
BaseType_t xPortStartScheduler( void )
{
/* Setup the hardware to generate the tick. */
prvSetupTimerInterrupt();
@ -233,15 +235,15 @@ BaseType_t xPortStartScheduler(void)
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");
* jump to the start of the task the context of which we have just restored. */
asm volatile ( "ret" );
/* Should not get here. */
return pdTRUE;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler(void)
void vPortEndScheduler( void )
{
/* vPortEndScheduler is not implemented in this port. */
}
@ -251,13 +253,13 @@ 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)
void vPortYield( void ) __attribute__( ( naked ) );
void vPortYield( void )
{
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();
asm volatile("ret");
asm volatile ( "ret" );
}
/*-----------------------------------------------------------*/
@ -265,13 +267,13 @@ void vPortYield(void)
* Manual context switch callable from ISRs. The first thing
* we do is save the registers so we can use a naked attribute.
*/
void vPortYieldFromISR(void) __attribute__((naked));
void vPortYieldFromISR(void)
void vPortYieldFromISR( void ) __attribute__( ( naked ) );
void vPortYieldFromISR( void )
{
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();
asm volatile("reti");
asm volatile ( "reti" );
}
/*-----------------------------------------------------------*/
@ -281,24 +283,26 @@ void vPortYieldFromISR(void)
* 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)
void vPortYieldFromTick( void ) __attribute__( ( naked ) );
void vPortYieldFromTick( void )
{
portSAVE_CONTEXT();
if (xTaskIncrementTick() != pdFALSE) {
if( xTaskIncrementTick() != pdFALSE )
{
vTaskSwitchContext();
}
portRESTORE_CONTEXT();
asm volatile("reti");
asm volatile ( "reti" );
}
/*-----------------------------------------------------------*/
/*
* Setup timer to generate a tick interrupt.
*/
static void prvSetupTimerInterrupt(void)
static void prvSetupTimerInterrupt( void )
{
TICK_init();
}
@ -311,26 +315,26 @@ static void prvSetupTimerInterrupt(void)
* the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved.
*/
ISR(TICK_INT_vect, ISR_NAKED)
{
/* Clear tick interrupt flag. */
CLR_INT(INT_FLAGS, INT_MASK);
ISR( TICK_INT_vect, ISR_NAKED )
{
/* Clear tick interrupt flag. */
CLR_INT( INT_FLAGS, INT_MASK );
vPortYieldFromTick();
vPortYieldFromTick();
asm volatile("reti");
}
#else
asm volatile ( "reti" );
}
#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();
*/
ISR(TICK_INT_vect)
{
/* Clear tick interrupt flag. */
INT_FLAGS = INT_MASK;
xTaskIncrementTick();
}
#endif
ISR( TICK_INT_vect )
{
/* Clear tick interrupt flag. */
INT_FLAGS = INT_MASK;
xTaskIncrementTick();
}
#endif /* if configUSE_PREEMPTION == 1 */

View file

@ -5,86 +5,91 @@
/*-----------------------------------------------------------*/
#define CLR_INT(FLAG_REG, FLAG_MASK) \
asm volatile( \
"push r16\n\t" \
"ldi r16, %1\n\t" \
"sts %0, r16\n\t" \
"pop r16\n\t" \
: \
: "i"(_SFR_MEM_ADDR(FLAG_REG)),"i"((uint8_t)(FLAG_MASK)) \
#define CLR_INT( FLAG_REG, FLAG_MASK ) \
asm volatile ( \
"push r16\n\t" \
"ldi r16, %1\n\t" \
"sts %0, r16\n\t" \
"pop r16\n\t" \
: \
: "i" ( _SFR_MEM_ADDR( FLAG_REG ) ), "i" ( ( uint8_t ) ( FLAG_MASK ) ) \
);
#if ( configUSE_TIMER_INSTANCE == 0 )
#define TICK_INT_vect TCB0_INT_vect
#define INT_FLAGS TCB0_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB0_INT_vect
#define INT_FLAGS TCB0_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB0.INTCTRL = TCB_CAPT_bm; \
TCB0.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() \
{ \
TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB0.INTCTRL = TCB_CAPT_bm; \
TCB0.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 1 )
#define TICK_INT_vect TCB1_INT_vect
#define INT_FLAGS TCB1_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB1_INT_vect
#define INT_FLAGS TCB1_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB1.INTCTRL = TCB_CAPT_bm; \
TCB1.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() \
{ \
TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB1.INTCTRL = TCB_CAPT_bm; \
TCB1.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 2 )
#define TICK_INT_vect TCB2_INT_vect
#define INT_FLAGS TCB2_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB2_INT_vect
#define INT_FLAGS TCB2_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB2.INTCTRL = TCB_CAPT_bm; \
TCB2.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() \
{ \
TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB2.INTCTRL = TCB_CAPT_bm; \
TCB2.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 3 )
#define TICK_INT_vect TCB3_INT_vect
#define INT_FLAGS TCB3_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_INT_vect TCB3_INT_vect
#define INT_FLAGS TCB3_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB3.INTCTRL = TCB_CAPT_bm; \
TCB3.CTRLA = TCB_ENABLE_bm; \
}
#define TICK_init() \
{ \
TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB3.INTCTRL = TCB_CAPT_bm; \
TCB3.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 4 )
#define TICK_INT_vect RTC_CNT_vect
#define INT_FLAGS RTC_INTFLAGS
#define INT_MASK RTC_OVF_bm
#define TICK_INT_vect RTC_CNT_vect
#define INT_FLAGS RTC_INTFLAGS
#define INT_MASK RTC_OVF_bm
/* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) )
#define TICK_init() { \
while (RTC.STATUS > 0); \
RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \
RTC.PER = RTC_PERIOD_HZ(configTICK_RATE_HZ); \
RTC.INTCTRL |= 1 << RTC_OVF_bp; \
}
/* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ( x ) ( 32768 * ( ( 1.0 / x ) ) )
#define TICK_init() \
{ \
while( RTC.STATUS > 0 ) {; } \
RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \
RTC.PER = RTC_PERIOD_HZ( configTICK_RATE_HZ ); \
RTC.INTCTRL |= 1 << RTC_OVF_bp; \
}
#else
#else /* if ( configUSE_TIMER_INSTANCE == 0 ) */
#undef TICK_INT_vect
#undef INT_FLAGS
#undef INT_MASK
#undef TICK_init()
#error Invalid timer setting.
#endif
#endif /* if ( configUSE_TIMER_INSTANCE == 0 ) */
/*-----------------------------------------------------------*/

View file

@ -23,14 +23,16 @@
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
/* *INDENT-ON* */
/*-----------------------------------------------------------
* Port specific definitions.
@ -43,64 +45,66 @@ 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
#define portPOINTER_SIZE_TYPE uint16_t
#define portPOINTER_SIZE_TYPE uint16_t
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
#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
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()
extern void vPortYieldFromISR(void) __attribute__((naked));
#define portYIELD_FROM_ISR() vPortYieldFromISR()
extern void vPortYieldFromISR( void ) __attribute__( ( naked ) );
#define portYIELD_FROM_ISR() vPortYieldFromISR()
/*-----------------------------------------------------------*/
/* 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 )
/* *INDENT-OFF* */
#ifdef __cplusplus
}
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

View file

@ -38,7 +38,7 @@
/*-----------------------------------------------------------*/
/* The initial PSR has the Previous Interrupt Enabled (PIEN) flag set. */
#define portINITIAL_PSR ( 0x00020000 )
#define portINITIAL_PSR ( 0x00020000 )
/*-----------------------------------------------------------*/
@ -48,100 +48,98 @@
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. */
}
/*-----------------------------------------------------------*/

View file

@ -26,13 +26,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.
@ -45,108 +45,108 @@
*/
/* 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 */

View file

@ -29,36 +29,34 @@
#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;
}
@ -66,67 +64,71 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
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( 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( MCF_INTC0_INTFRCL == 0UL )
{
break;
}
portENABLE_INTERRUPTS();
portENABLE_INTERRUPTS();
} while( 1 );
}
ulCriticalNesting++;
} 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 );
}

View file

@ -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,72 +43,72 @@
*/
/* 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 */

View file

@ -31,22 +31,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.
@ -56,167 +56,164 @@ 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;
/* This requires an even address. */
ulValue = ( uint32_t ) pxTopOfStack;
if( ulValue & 1UL )
{
pxTopOfStack = pxTopOfStack - 1;
}
if( ulValue & 1UL )
{
pxTopOfStack = pxTopOfStack - 1;
}
/* 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;
/* 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;
/* The initial stack mimics an interrupt stack. First there is the program
counter (24 bits). */
ulValue = ( uint32_t ) pxCode;
/* The initial stack mimics an interrupt stack. First there is the program
* counter (24 bits). */
ulValue = ( uint32_t ) pxCode;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
pxTopOfStack--;
ulValue >>= 8UL;
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
pxTopOfStack--;
ulValue >>= 8UL;
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
pxTopOfStack--;
ulValue >>= 8UL;
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
pxTopOfStack--;
ulValue >>= 8UL;
*pxTopOfStack = ( StackType_t ) ( ulValue & 0xff );
/* Followed by the CCR. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_CCR;
/* Followed by the CCR. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_CCR;
/* 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. */
/* 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. */
/* ER6 */
pxTopOfStack--;
*pxTopOfStack = 0x66;
pxTopOfStack--;
*pxTopOfStack = 0x66;
pxTopOfStack--;
*pxTopOfStack = 0x66;
pxTopOfStack--;
*pxTopOfStack = 0x66;
/* ER0 */
ulValue = ( uint32_t ) pvParameters;
/* ER6 */
pxTopOfStack--;
*pxTopOfStack = 0x66;
pxTopOfStack--;
*pxTopOfStack = 0x66;
pxTopOfStack--;
*pxTopOfStack = 0x66;
pxTopOfStack--;
*pxTopOfStack = 0x66;
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;
/* ER0 */
ulValue = ( uint32_t ) pvParameters;
/* ER2 */
pxTopOfStack--;
*pxTopOfStack = 0x22;
pxTopOfStack--;
*pxTopOfStack = 0x22;
pxTopOfStack--;
*pxTopOfStack = 0x22;
pxTopOfStack--;
*pxTopOfStack = 0x22;
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 );
/* ER3 */
pxTopOfStack--;
*pxTopOfStack = 0x33;
pxTopOfStack--;
*pxTopOfStack = 0x33;
pxTopOfStack--;
*pxTopOfStack = 0x33;
pxTopOfStack--;
*pxTopOfStack = 0x33;
/* ER1 */
pxTopOfStack--;
*pxTopOfStack = 0x11;
pxTopOfStack--;
*pxTopOfStack = 0x11;
pxTopOfStack--;
*pxTopOfStack = 0x11;
pxTopOfStack--;
*pxTopOfStack = 0x11;
/* ER4 */
pxTopOfStack--;
*pxTopOfStack = 0x44;
pxTopOfStack--;
*pxTopOfStack = 0x44;
pxTopOfStack--;
*pxTopOfStack = 0x44;
pxTopOfStack--;
*pxTopOfStack = 0x44;
/* ER2 */
pxTopOfStack--;
*pxTopOfStack = 0x22;
pxTopOfStack--;
*pxTopOfStack = 0x22;
pxTopOfStack--;
*pxTopOfStack = 0x22;
pxTopOfStack--;
*pxTopOfStack = 0x22;
/* ER5 */
pxTopOfStack--;
*pxTopOfStack = 0x55;
pxTopOfStack--;
*pxTopOfStack = 0x55;
pxTopOfStack--;
*pxTopOfStack = 0x55;
pxTopOfStack--;
*pxTopOfStack = 0x55;
/* 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;
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. */
}
/*-----------------------------------------------------------*/
@ -227,56 +224,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();
/*
* 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();
}
if( xTaskIncrementTick() != pdFALSE )
{
vTaskSwitchContext();
}
/* Clear the interrupt. */
TSR1 &= ~0x01;
/* Clear the interrupt. */
TSR1 &= ~0x01;
portRESTORE_STACK_POINTER();
}
portRESTORE_STACK_POINTER();
}
#else
#else /* if ( configUSE_PREEMPTION == 1 ) */
/*
* 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();
/*
* 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();
/* Clear the interrupt. */
TSR1 &= ~0x01;
}
/* Clear the interrupt. */
TSR1 &= ~0x01;
}
#endif /* if ( configUSE_PREEMPTION == 1 ) */
#endif
/*-----------------------------------------------------------*/
/*
@ -284,20 +281,23 @@ 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;
}
/*-----------------------------------------------------------*/

View file

@ -27,11 +27,11 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
@ -44,95 +44,95 @@
*/
/* 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 */

View file

@ -35,144 +35,143 @@
#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. */
/* 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 );
/* 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. */
/* Next are all the registers that form part of the task context. */
/* Y register */
*--pxTopOfStack = ( StackType_t ) 0xff;
*--pxTopOfStack = ( StackType_t ) 0xee;
/* 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 );
/* X register */
*--pxTopOfStack = ( StackType_t ) 0xdd;
*--pxTopOfStack = ( StackType_t ) 0xcc;
/* Next are all the registers that form part of the task context. */
/* A register contains parameter high byte. */
*--pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 0 );
/* Y register */
*--pxTopOfStack = ( StackType_t ) 0xff;
*--pxTopOfStack = ( StackType_t ) 0xee;
/* B register contains parameter low byte. */
*--pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 1 );
/* X register */
*--pxTopOfStack = ( StackType_t ) 0xdd;
*--pxTopOfStack = ( StackType_t ) 0xcc;
/* A register contains parameter high byte. */
*--pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 );
/* 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) */
/* B register contains parameter low byte. */
*--pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 );
/* tmp softregs used by GCC. Values right now don't matter. */
__asm( "\n\
/* 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\
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;
}
/*-----------------------------------------------------------*/
@ -186,53 +185,53 @@ BaseType_t xStartSchedulerNear( void )
*/
void vPortYield( void )
{
portISR_HEAD();
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. */
/* 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. */
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();
portISR_TAIL();
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 /* if configUSE_PREEMPTION == 1 */
{
xTaskIncrementTick();
}
#endif /* if configUSE_PREEMPTION == 1 */
/* Restore the context of a task - which may be a different task
to that interrupted. */
portRESTORE_CONTEXT();
}
#else
{
xTaskIncrementTick();
}
#endif
portISR_TAIL();
portISR_TAIL();
}

View file

@ -27,11 +27,11 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
@ -44,38 +44,38 @@
*/
/* 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.
@ -83,29 +83,29 @@
* 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. */
@ -120,16 +120,15 @@
* 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\
@ -138,17 +137,17 @@
\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\
@ -157,18 +156,18 @@
\n\
ldx pxCurrentTCB \n\
sts 0,x ; Stack \n\
" ); \
}
#else /* ifdef BANKED_MODEL */
" ); \
}
#else
/*
* 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\
@ -176,12 +175,12 @@
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\
@ -189,29 +188,29 @@
\n\
ldx pxCurrentTCB \n\
sts 0,x ; Stack \n\
" ); \
}
#endif /* ifdef BANKED_MODEL */
" ); \
}
#endif
/*
* 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\
@ -219,8 +218,8 @@
;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
@ -229,18 +228,19 @@
* 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 */

View file

@ -25,102 +25,103 @@
* 1 tab == 4 spaces!
*/
.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

View file

@ -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,255 +43,249 @@
*/
/* 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
#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
/* 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 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.
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
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.
/* 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
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
#ifndef configUSE_COMMON_INTERRUPT_ENTRY_POINT
/* There are two ways of implementing interrupt handlers:
/* 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
1) As standard C functions -
#ifndef configISR_STACK_SIZE
This method can only be used if configUSE_COMMON_INTERRUPT_ENTRY_POINT
is set to 1. The C function is installed using
xPortRegisterCInterruptHandler().
/* 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. */
This is the simplest of the two methods but incurs a slightly longer
interrupt entry time.
#error configISR_STACK_SIZE was not defined in FreeRTOSConfig.h.
#endif
2) By using an assembly stub that wraps the handler in the FreeRTOS
portFREERTOS_INTERRUPT_ENTRY and portFREERTOS_INTERRUPT_EXIT macros.
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
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
/* 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 configISR_STACK_SIZE
/* Interrupt entry code will switch the stack in use to a dedicated system
stack.
#ifndef configSUPPORT_FPU
#warning configSUPPORT_FPU was not defined in FreeRTOSConfig.h and has been defaulted to 0
#define configSUPPORT_FPU 0
#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
/* 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 */

View file

@ -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 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*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,64 +165,65 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
/*
* 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 /* if configUSE_PREEMPTION == 0 */
#else
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;
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
if( xTaskIncrementTick() != pdFALSE )
{
vTaskSwitchContext();
}
portRESTORE_CONTEXT();
}
#endif /* if configUSE_PREEMPTION == 0 */
void vPortEnterCritical()
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
@ -230,7 +231,8 @@ void vPortEnterCritical()
ulCriticalNesting++;
}
void vPortExitCritical()
void
vPortExitCritical()
{
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{
@ -238,17 +240,18 @@ void 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;
@ -256,7 +259,7 @@ BaseType_t xPortStartScheduler( void )
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;
@ -270,12 +273,13 @@ BaseType_t xPortStartScheduler( void )
}
/* 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 )
{
}

View file

@ -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 @@
* 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,66 +115,68 @@
* 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 */

View file

@ -26,10 +26,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>
@ -40,62 +40,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
@ -105,26 +105,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" \
);
/*-----------------------------------------------------------*/
/*
@ -134,194 +134,195 @@ 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.
*
* pxTopOfStack = ( StackType_t ) 0x1111;
* pxTopOfStack--;
* pxTopOfStack = ( StackType_t ) 0x2222;
* pxTopOfStack--;
* pxTopOfStack = ( StackType_t ) 0x3333;
* pxTopOfStack--;
*/
/*
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.
/* 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--;
*pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x3333;
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--;
/* 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--;
/* When the task starts is will expect to find the function parameter in
* R15. */
*pxTopOfStack = ( StackType_t ) pvParameters;
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--;
/* 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;
/* When the task starts is will expect to find the function parameter in
R15. */
*pxTopOfStack = ( StackType_t ) pvParameters;
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;
/* 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;
}
/*-----------------------------------------------------------*/
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 /* if configUSE_PREEMPTION == 1 */
#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();
*/
interrupt( TIMERA0_VECTOR ) prvTickISR( void );
interrupt( TIMERA0_VECTOR ) prvTickISR( void )
{
xTaskIncrementTick();
}
#endif /* 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

View file

@ -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,84 +43,85 @@
*/
/* 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 */

View file

@ -26,8 +26,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,33 +42,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;
/*-----------------------------------------------------------*/
@ -85,142 +85,140 @@ 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. */
}
/*-----------------------------------------------------------*/
@ -229,18 +227,17 @@ 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();
}
/*-----------------------------------------------------------*/
@ -249,26 +246,26 @@ void vPortYield( 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 );
}
/*-----------------------------------------------------------*/
@ -280,53 +277,57 @@ static void prvSetupTimerInterrupt( void )
*/
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 );
}
/*-----------------------------------------------------------*/

View file

@ -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,85 +43,84 @@
*/
/* 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 */

View file

@ -26,8 +26,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. */
@ -43,20 +43,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 )
/*-----------------------------------------------------------*/
/*
@ -72,27 +72,27 @@ 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. */
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. */
by the Xilinx library API functions. */
static XIntc xInterruptControllerInstance;
/*-----------------------------------------------------------*/
@ -103,174 +103,172 @@ 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;
/* 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. 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
#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 */
*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 ) 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 ) 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.
*
* 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();
/* Setup the hardware to generate the tick. Interrupts are disabled when
this function is called.
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
pulISRStack = ( uint32_t * ) _stack;
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();
/* 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;
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
pulISRStack = ( uint32_t * ) _stack;
/* Restore the context of the first task that is going to run. From here
* on, the created tasks will be executing. */
vPortStartFirstTask();
/* 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;
/* Should not get here as the tasks are now running! */
return pdFALSE;
/* 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;
}
/*-----------------------------------------------------------*/
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 );
}
/*-----------------------------------------------------------*/
@ -279,107 +277,104 @@ 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();
/* 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 );
}
if( lReturn == pdPASS )
{
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
}
configASSERT( lReturn );
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;
}
/*-----------------------------------------------------------*/
@ -387,69 +382,71 @@ static int32_t prvEnsureInterruptControllerIsInitialised( void )
* 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;
}
/*-----------------------------------------------------------*/

View file

@ -34,244 +34,249 @@
#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 )
case XEXC_ID_FPU:
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FPU see ulFSR value";
break;
#endif /* XPAR_MICROBLAZE_USE_FPU */
}
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
/* 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 );
case XEXC_ID_FPU :
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FPU see ulFSR value";
break;
/* Must not attempt to leave this function! */
for( ; ; )
{
portNOP();
}
}
#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();
}
}
/*-----------------------------------------------------------*/
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 ) */

View file

@ -26,15 +26,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.
@ -47,177 +47,175 @@
*/
/* 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 ) );
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
return ucReturn;
}
return ucReturn;
}
/* 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
/* 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 ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#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;
/*
@ -255,9 +253,7 @@
* 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 );
/*
@ -278,7 +274,7 @@
* 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
@ -298,7 +294,7 @@
* 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
@ -310,7 +306,7 @@
* 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
@ -323,7 +319,7 @@
* 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
@ -346,7 +342,7 @@
* 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
@ -362,11 +358,12 @@
* 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 */

View file

@ -26,8 +26,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. */
@ -43,20 +43,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 )
/*-----------------------------------------------------------*/
@ -73,27 +73,27 @@ 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. */
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. */
by the Xilinx library API functions. */
static XIntc xInterruptControllerInstance;
/*-----------------------------------------------------------*/
@ -104,175 +104,173 @@ 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 /* 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 ) 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
*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 /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
pxTopOfStack -= 13;
#endif /* ifdef portPRE_LOAD_STACK_FOR_DEBUGGING */
#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
/* 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.
*
* 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();
/* Setup the hardware to generate the tick. Interrupts are disabled when
this function is called.
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
pulISRStack = ( uint32_t * ) _stack;
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();
/* 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;
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
pulISRStack = ( uint32_t * ) _stack;
/* Restore the context of the first task that is going to run. From here
* on, the created tasks will be executing. */
vPortStartFirstTask();
/* 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;
/* Should not get here as the tasks are now running! */
return pdFALSE;
/* 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;
}
/*-----------------------------------------------------------*/
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 );
}
/*-----------------------------------------------------------*/
@ -281,113 +279,110 @@ 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();
/* 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();
}
if( lReturn == pdPASS )
{
/* Critical section protects read/modify/writer operation inside
* XIntc_Enable(). */
portENTER_CRITICAL();
{
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
}
portEXIT_CRITICAL();
}
configASSERT( lReturn );
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;
}
/*-----------------------------------------------------------*/
@ -395,69 +390,71 @@ static int32_t prvEnsureInterruptControllerIsInitialised( void )
* 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;
}
/*-----------------------------------------------------------*/

View file

@ -34,244 +34,249 @@
#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 )
case XEXC_ID_FPU:
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FPU see ulFSR value";
break;
#endif /* XPAR_MICROBLAZE_USE_FPU */
}
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
/* 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 );
case XEXC_ID_FPU :
xRegisterDump.pcExceptionCause = ( int8_t * const ) "XEXC_ID_FPU see ulFSR value";
break;
/* Must not attempt to leave this function! */
for( ; ; )
{
portNOP();
}
}
#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();
}
}
/*-----------------------------------------------------------*/
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 ) */

View file

@ -26,15 +26,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.
@ -47,177 +47,175 @@
*/
/* 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 ) );
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
return ucReturn;
}
return ucReturn;
}
/* 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
/* 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 ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#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;
/*
@ -255,9 +253,7 @@
* 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 );
/*
@ -278,7 +274,7 @@
* 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
@ -298,7 +294,7 @@
* 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
@ -310,7 +306,7 @@
* 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
@ -323,7 +319,7 @@
* 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
@ -346,7 +342,7 @@
* 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
@ -362,11 +358,12 @@
* 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 */

View file

@ -26,8 +26,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>
@ -43,11 +43,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 );
@ -55,80 +55,77 @@ 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 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 first task. */
asm volatile ( " movia r2, restore_sp_from_pxCurrentTCB \n"
" jmp r2 " );
/* Should not get here! */
return 0;
/* 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. */
}
/*-----------------------------------------------------------*/
@ -138,71 +135,69 @@ 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;
}
/*-----------------------------------------------------------*/

View file

@ -26,13 +26,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.
@ -45,64 +45,65 @@
*/
/* 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 */

View file

@ -26,19 +26,20 @@
*/
/* 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 ) ); \
}

View file

@ -26,8 +26,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. */
@ -42,19 +42,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_;
@ -90,177 +90,171 @@ 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 ];
/* 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 );
/* Which interrupts are pending? */
ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );
/* Call the registered handler. */
pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );
pxTable->Handler( pxTable->CallBackRef );
}
/* Check the next interrupt. */
ulInterruptMask <<= 0x01UL;
ulInterruptStatus >>= 0x01UL;
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;
}
}
/* 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;
}

View file

@ -26,13 +26,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.
@ -45,75 +45,74 @@
*/
/* 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 */

View file

@ -26,19 +26,20 @@
*/
/* 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 ) ); \
}

View file

@ -26,8 +26,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. */
@ -42,19 +42,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_;
@ -96,72 +96,68 @@ 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( ;; );
}
/*-----------------------------------------------------------*/
@ -170,97 +166,95 @@ 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;
}

View file

@ -26,13 +26,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.
@ -45,75 +45,74 @@
*/
/* 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 */

View file

@ -7,8 +7,8 @@
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and t
*
* o permit persons to whom the Software is furnished to do so,
o permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
@ -59,51 +59,51 @@
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
#define __FREERTOS_RISC_V_EXTENSIONS_H__
#define portasmHAS_MTIME 0
#define portasmHAS_MTIME 0
/* Constants to define the additional registers found on the Pulpino RI5KY. */
#define lpstart0 0x7b0
#define lpend0 0x7b1
#define lpcount0 0x7b2
#define lpstart1 0x7b4
#define lpend1 0x7b5
#define lpcount1 0x7b6
#define lpstart0 0x7b0
#define lpend0 0x7b1
#define lpcount0 0x7b2
#define lpstart1 0x7b4
#define lpend1 0x7b5
#define lpcount1 0x7b6
/* Six additional registers to save and restore, as per the #defines above. */
#define portasmADDITIONAL_CONTEXT_SIZE 6 /* Must be even number on 32-bit cores. */
#define portasmADDITIONAL_CONTEXT_SIZE 6 /* Must be even number on 32-bit cores. */
/* Save additional registers found on the Pulpino. */
.macro portasmSAVE_ADDITIONAL_REGISTERS
addi sp, sp, -( portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE ) /* Make room for the additional registers. */
csrr t0, lpstart0 /* Load additional registers into accessible temporary registers. */
csrr t1, lpend0
csrr t2, lpcount0
csrr t3, lpstart1
csrr t4, lpend1
csrr t5, lpcount1
sw t0, 1 * portWORD_SIZE( sp )
sw t1, 2 * portWORD_SIZE( sp )
sw t2, 3 * portWORD_SIZE( sp )
sw t3, 4 * portWORD_SIZE( sp )
sw t4, 5 * portWORD_SIZE( sp )
sw t5, 6 * portWORD_SIZE( sp )
.endm
addi sp, sp, -(portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE) /* Make room for the additional registers. */
csrr t0, lpstart0 /* Load additional registers into accessible temporary registers. */
csrr t1, lpend0
csrr t2, lpcount0
csrr t3, lpstart1
csrr t4, lpend1
csrr t5, lpcount1
sw t0, 1 * portWORD_SIZE( sp )
sw t1, 2 * portWORD_SIZE( sp )
sw t2, 3 * portWORD_SIZE( sp )
sw t3, 4 * portWORD_SIZE( sp )
sw t4, 5 * portWORD_SIZE( sp )
sw t5, 6 * portWORD_SIZE( sp )
.endm
/* Restore the additional registers found on the Pulpino. */
.macro portasmRESTORE_ADDITIONAL_REGISTERS
lw t0, 1 * portWORD_SIZE( sp ) /* Load additional registers into accessible temporary registers. */
lw t1, 2 * portWORD_SIZE( sp )
lw t2, 3 * portWORD_SIZE( sp )
lw t3, 4 * portWORD_SIZE( sp )
lw t4, 5 * portWORD_SIZE( sp )
lw t5, 6 * portWORD_SIZE( sp )
csrw lpstart0, t0
csrw lpend0, t1
csrw lpcount0, t2
csrw lpstart1, t3
csrw lpend1, t4
csrw lpcount1, t5
addi sp, sp, ( portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE ) /* Remove space added for additional registers. */
.endm
.macro portasmRESTORE_ADDITIONAL_REGISTERS
lw t0, 1 * portWORD_SIZE( sp ) /* Load additional registers into accessible temporary registers. */
lw t1, 2 * portWORD_SIZE( sp )
lw t2, 3 * portWORD_SIZE( sp )
lw t3, 4 * portWORD_SIZE( sp )
lw t4, 5 * portWORD_SIZE( sp )
lw t5, 6 * portWORD_SIZE( sp )
csrw lpstart0, t0
csrw lpend0, t1
csrw lpcount0, t2
csrw lpstart1, t3
csrw lpend1, t4
csrw lpcount1, t5
addi sp, sp, (portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE )/* Remove space added for additional registers. */
.endm
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */

View file

@ -53,16 +53,16 @@
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
#define __FREERTOS_RISC_V_EXTENSIONS_H__
#define portasmHAS_SIFIVE_CLINT 1
#define portasmHAS_MTIME 1
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
#define portasmHAS_SIFIVE_CLINT 1
#define portasmHAS_MTIME 1
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
.macro portasmSAVE_ADDITIONAL_REGISTERS
/* No additional registers to save, so this macro does nothing. */
.endm
/* No additional registers to save, so this macro does nothing. */
.endm
.macro portasmRESTORE_ADDITIONAL_REGISTERS
/* No additional registers to restore, so this macro does nothing. */
.endm
.macro portasmRESTORE_ADDITIONAL_REGISTERS
/* No additional registers to restore, so this macro does nothing. */
.endm
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */

View file

@ -26,8 +26,8 @@
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the RISC-V RV32 port.
*----------------------------------------------------------*/
* Implementation of functions defined in portable.h for the RISC-V RV32 port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
@ -38,44 +38,44 @@
#include "string.h"
#ifdef configCLINT_BASE_ADDRESS
#warning The configCLINT_BASE_ADDRESS constant has been deprecated. configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS are currently being derived from the (possibly 0) configCLINT_BASE_ADDRESS setting. Please update to define configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS dirctly in place of configCLINT_BASE_ADDRESS. See https: /*www.freertos.org/Using-FreeRTOS-on-RISC-V.html */
#warning The configCLINT_BASE_ADDRESS constant has been deprecated. configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS are currently being derived from the (possibly 0) configCLINT_BASE_ADDRESS setting. Please update to define configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS dirctly in place of configCLINT_BASE_ADDRESS. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
#endif
#ifndef configMTIME_BASE_ADDRESS
#warning configMTIME_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtime register then set configMTIME_BASE_ADDRESS to the mapped address. Otherwise set configMTIME_BASE_ADDRESS to 0. See https: /*www.freertos.org/Using-FreeRTOS-on-RISC-V.html */
#warning configMTIME_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtime register then set configMTIME_BASE_ADDRESS to the mapped address. Otherwise set configMTIME_BASE_ADDRESS to 0. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
#endif
#ifndef configMTIMECMP_BASE_ADDRESS
#warning configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtimecmp register then set configMTIMECMP_BASE_ADDRESS to the mapped address. Otherwise set configMTIMECMP_BASE_ADDRESS to 0. See https: /*www.freertos.org/Using-FreeRTOS-on-RISC-V.html */
#warning configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtimecmp register then set configMTIMECMP_BASE_ADDRESS to the mapped address. Otherwise set configMTIMECMP_BASE_ADDRESS to 0. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
#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
/* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS
* to use a statically allocated array as the interrupt stack. Alternative leave
* configISR_STACK_SIZE_WORDS undefined and update the linker script so that a
* linker variable names __freertos_irq_stack_top has the same value as the top
* of the stack used by main. Using the linker script method will repurpose the
* stack that was used by main before the scheduler was started for use as the
* interrupt stack after the scheduler has started. */
to use a statically allocated array as the interrupt stack. Alternative leave
configISR_STACK_SIZE_WORDS undefined and update the linker script so that a
linker variable names __freertos_irq_stack_top has the same value as the top
of the stack used by main. Using the linker script method will repurpose the
stack that was used by main before the scheduler was started for use as the
interrupt stack after the scheduler has started. */
#ifdef configISR_STACK_SIZE_WORDS
static __attribute__( ( aligned( 16 ) ) ) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] );
static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] );
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
* the task stacks, and so will legitimately appear in many positions within
* the ISR stack. */
#define portISR_STACK_FILL_BYTE 0xee
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
the task stacks, and so will legitimately appear in many positions within
the ISR stack. */
#define portISR_STACK_FILL_BYTE 0xee
#else
extern const uint32_t __freertos_irq_stack_top[];
const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
extern const uint32_t __freertos_irq_stack_top[];
const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
#endif
/*
@ -83,130 +83,130 @@
* file is weak to allow application writers to change the timer used to
* generate the tick interrupt.
*/
void vPortSetupTimerInterrupt( void ) __attribute__( ( weak ) );
void vPortSetupTimerInterrupt( void ) __attribute__(( weak ));
/*-----------------------------------------------------------*/
/* Used to program the machine timer compare register. */
uint64_t ullNextTime = 0ULL;
const uint64_t * pullNextTime = &ullNextTime;
const uint64_t *pullNextTime = &ullNextTime;
const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */
uint32_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS;
volatile uint64_t * pullMachineTimerCompareRegister = NULL;
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
* stack checking. A problem in the ISR stack will trigger an assert, not call the
* stack overflow hook function (because the stack overflow hook is specific to a
* task stack, not the ISR stack). */
stack checking. A problem in the ISR stack will trigger an assert, not call the
stack overflow hook function (because the stack overflow hook is specific to a
task stack, not the ISR stack). */
#if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 )
#warning This path not tested, or even compiled yet.
#warning This path not tested, or even compiled yet.
static const uint8_t ucExpectedStackBytes[] =
{
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE
}; \
static const uint8_t ucExpectedStackBytes[] = {
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE }; \
#define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) )
#else /* if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 ) */
/* Define the function away. */
#define portCHECK_ISR_STACK()
#define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) )
#else
/* Define the function away. */
#define portCHECK_ISR_STACK()
#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */
/*-----------------------------------------------------------*/
#if ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
#if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
void vPortSetupTimerInterrupt( void )
{
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
volatile uint32_t ulHartId;
void vPortSetupTimerInterrupt( void )
{
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
volatile uint32_t ulHartId;
__asm volatile ( "csrr %0, mhartid" : "=r" ( ulHartId ) );
__asm volatile( "csrr %0, mhartid" : "=r"( ulHartId ) );
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
do
{
ulCurrentTimeHigh = *pulTimeHigh;
ulCurrentTimeLow = *pulTimeLow;
} while( ulCurrentTimeHigh != *pulTimeHigh );
do
{
ulCurrentTimeHigh = *pulTimeHigh;
ulCurrentTimeLow = *pulTimeLow;
} while( ulCurrentTimeHigh != *pulTimeHigh );
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
*pullMachineTimerCompareRegister = ullNextTime;
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
*pullMachineTimerCompareRegister = ullNextTime;
/* Prepare the time to use after the next tick interrupt. */
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
}
/* Prepare the time to use after the next tick interrupt. */
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
}
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
extern void xPortStartFirstTask( void );
extern void xPortStartFirstTask( void );
#if ( configASSERT_DEFINED == 1 )
{
volatile uint32_t mtvec = 0;
#if( configASSERT_DEFINED == 1 )
{
volatile uint32_t mtvec = 0;
/* Check the least significant two bits of mtvec are 00 - indicating
* single vector mode. */
__asm volatile ( "csrr %0, mtvec" : "=r" ( mtvec ) );
configASSERT( ( mtvec & 0x03UL ) == 0 );
/* Check the least significant two bits of mtvec are 00 - indicating
single vector mode. */
__asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) );
configASSERT( ( mtvec & 0x03UL ) == 0 );
/* Check alignment of the interrupt stack - which is the same as the
* stack that was being used by main() prior to the scheduler being
* started. */
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
/* Check alignment of the interrupt stack - which is the same as the
stack that was being used by main() prior to the scheduler being
started. */
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
#ifdef configISR_STACK_SIZE_WORDS
{
memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );
}
#endif /* configISR_STACK_SIZE_WORDS */
}
#endif /* configASSERT_DEFINED */
#ifdef configISR_STACK_SIZE_WORDS
{
memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );
}
#endif /* configISR_STACK_SIZE_WORDS */
}
#endif /* configASSERT_DEFINED */
/* If there is a CLINT then it is ok to use the default implementation
* in this file, otherwise vPortSetupTimerInterrupt() must be implemented to
* configure whichever clock is to be used to generate the tick interrupt. */
vPortSetupTimerInterrupt();
/* If there is a CLINT then it is ok to use the default implementation
in this file, otherwise vPortSetupTimerInterrupt() must be implemented to
configure whichever clock is to be used to generate the tick interrupt. */
vPortSetupTimerInterrupt();
#if ( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
{
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
* for external interrupt. _RB_ What happens here when mtime is not present as
* with pulpino? */
__asm volatile ( "csrs mie, %0" ::"r" ( 0x880 ) );
}
#else
{
/* Enable external interrupts. */
__asm volatile ( "csrs mie, %0" ::"r" ( 0x800 ) );
}
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
#if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
{
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
for external interrupt. _RB_ What happens here when mtime is not present as
with pulpino? */
__asm volatile( "csrs mie, %0" :: "r"(0x880) );
}
#else
{
/* Enable external interrupts. */
__asm volatile( "csrs mie, %0" :: "r"(0x800) );
}
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
xPortStartFirstTask();
xPortStartFirstTask();
/* Should not get here as after calling xPortStartFirstTask() only tasks
* should be executing. */
return pdFAIL;
/* Should not get here as after calling xPortStartFirstTask() only tasks
should be executing. */
return pdFAIL;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented. */
for( ; ; )
{
}
/* Not implemented. */
for( ;; );
}

View file

@ -27,11 +27,11 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
@ -44,144 +44,143 @@
*/
/* Type definitions. */
#if __riscv_xlen == 64
#define portSTACK_TYPE uint64_t
#define portBASE_TYPE int64_t
#define portUBASE_TYPE uint64_t
#define portMAX_DELAY ( TickType_t ) 0xffffffffffffffffUL
#define portPOINTER_SIZE_TYPE uint64_t
#elif __riscv_xlen == 32
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE int32_t
#define portUBASE_TYPE uint32_t
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#else /* if __riscv_xlen == 64 */
#error Assembler did not define __riscv_xlen
#endif /* if __riscv_xlen == 64 */
#if __riscv_xlen == 64
#define portSTACK_TYPE uint64_t
#define portBASE_TYPE int64_t
#define portUBASE_TYPE uint64_t
#define portMAX_DELAY ( TickType_t ) 0xffffffffffffffffUL
#define portPOINTER_SIZE_TYPE uint64_t
#elif __riscv_xlen == 32
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE int32_t
#define portUBASE_TYPE uint32_t
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#else
#error Assembler did not define __riscv_xlen
#endif
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef portUBASE_TYPE UBaseType_t;
typedef portUBASE_TYPE TickType_t;
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef portUBASE_TYPE UBaseType_t;
typedef portUBASE_TYPE TickType_t;
/* Legacy type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
/* 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
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#ifdef __riscv64
#error This is the RV32 port that has not yet been adapted for 64.
#define portBYTE_ALIGNMENT 16
#else
#define portBYTE_ALIGNMENT 16
#endif
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#ifdef __riscv64
#error This is the RV32 port that has not yet been adapted for 64.
#define portBYTE_ALIGNMENT 16
#else
#define portBYTE_ALIGNMENT 16
#endif
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
extern void vTaskSwitchContext( void );
#define portYIELD() __asm volatile ( "ecall" );
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
extern void vTaskSwitchContext( void );
#define portYIELD() __asm volatile( "ecall" );
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Critical section management. */
#define portCRITICAL_NESTING_IN_TCB 1
extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void );
#define portCRITICAL_NESTING_IN_TCB 1
extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
#define portDISABLE_INTERRUPTS() __asm volatile ( "csrc mstatus, 8" )
#define portENABLE_INTERRUPTS() __asm volatile ( "csrs mstatus, 8" )
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
#define portDISABLE_INTERRUPTS() __asm volatile( "csrc mstatus, 8" )
#define portENABLE_INTERRUPTS() __asm volatile( "csrs mstatus, 8" )
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()
/*-----------------------------------------------------------*/
/* 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 )
/* 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
/* 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 - __builtin_clz( uxReadyPriorities ) )
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - __builtin_clz( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
/* 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 )
/*-----------------------------------------------------------*/
#define portNOP() __asm volatile ( " nop " )
#define portNOP() __asm volatile ( " nop " )
#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
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
/*-----------------------------------------------------------*/
/* configCLINT_BASE_ADDRESS is a legacy definition that was replaced by the
* configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS definitions. For
* backward compatibility derive the newer definitions from the old if the old
* definition is found. */
#if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 )
/* Legacy case where configCLINT_BASE_ADDRESS was defined as 0 to indicate
* there was no CLINT. Equivalent now is to set the MTIME and MTIMECMP
* addresses to 0. */
#define configMTIME_BASE_ADDRESS ( 0 )
#define configMTIMECMP_BASE_ADDRESS ( 0 )
#elif defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS )
/* Legacy case where configCLINT_BASE_ADDRESS was set to the base address of
* the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses
* from the CLINT address. */
#define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL )
#define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL )
#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS )
#error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https: /*www.freertos.org/Using-FreeRTOS-on-RISC-V.html */
#endif /* if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 ) */
configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS definitions. For
backward compatibility derive the newer definitions from the old if the old
definition is found. */
#if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 )
/* Legacy case where configCLINT_BASE_ADDRESS was defined as 0 to indicate
there was no CLINT. Equivalent now is to set the MTIME and MTIMECMP
addresses to 0. */
#define configMTIME_BASE_ADDRESS ( 0 )
#define configMTIMECMP_BASE_ADDRESS ( 0 )
#elif defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS )
/* Legacy case where configCLINT_BASE_ADDRESS was set to the base address of
the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses
from the CLINT address. */
#define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL )
#define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL )
#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS )
#error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
#endif
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -26,8 +26,8 @@
*/
/* Variables used by scheduler */
.extern _pxCurrentTCB
.extern _usCriticalNesting
.extern _pxCurrentTCB
.extern _usCriticalNesting
/*
* portSAVE_CONTEXT MACRO
@ -35,47 +35,47 @@
* memory mode) registers the usCriticalNesting Value and the Stack Pointer
* of the active Task onto the task stack
*/
.macro portSAVE_CONTEXT
.macro portSAVE_CONTEXT
SEL RB0
SEL RB0
/* Save AX Register to stack. */
PUSH AX
PUSH HL
/* Save CS register. */
MOV A, CS
XCH A, X
/* Save ES register. */
MOV A, ES
PUSH AX
/* Save the remaining general purpose registers from bank 0. */
PUSH DE
PUSH BC
/* Save the other register banks - only necessary in the GCC port. */
SEL RB1
PUSH AX
PUSH BC
PUSH DE
PUSH HL
SEL RB2
PUSH AX
PUSH BC
PUSH DE
PUSH HL
/* Registers in bank 3 are for ISR use only so don't need saving. */
SEL RB0
/* Save the usCriticalNesting value. */
MOVW AX, !_usCriticalNesting
PUSH AX
/* Save the Stack pointer. */
MOVW AX, !_pxCurrentTCB
MOVW HL, AX
MOVW AX, SP
MOVW[ HL ], AX
/* Switch stack pointers. */
movw sp, # _stack /* Set stack pointer */
/* Save AX Register to stack. */
PUSH AX
PUSH HL
/* Save CS register. */
MOV A, CS
XCH A, X
/* Save ES register. */
MOV A, ES
PUSH AX
/* Save the remaining general purpose registers from bank 0. */
PUSH DE
PUSH BC
/* Save the other register banks - only necessary in the GCC port. */
SEL RB1
PUSH AX
PUSH BC
PUSH DE
PUSH HL
SEL RB2
PUSH AX
PUSH BC
PUSH DE
PUSH HL
/* Registers in bank 3 are for ISR use only so don't need saving. */
SEL RB0
/* Save the usCriticalNesting value. */
MOVW AX, !_usCriticalNesting
PUSH AX
/* Save the Stack pointer. */
MOVW AX, !_pxCurrentTCB
MOVW HL, AX
MOVW AX, SP
MOVW [HL], AX
/* Switch stack pointers. */
movw sp,#_stack /* Set stack pointer */
.endm
.endm
/*
@ -84,43 +84,43 @@ movw sp, # _stack /* Set stack pointer */
* general purpose registers and the CS and ES (only in far memory mode)
* of the selected task from the task stack
*/
.macro portRESTORE_CONTEXT MACRO
SEL RB0
/* Restore the Stack pointer. */
MOVW AX, !_pxCurrentTCB
MOVW HL, AX
MOVW AX, [ HL ]
MOVW SP, AX
/* Restore usCriticalNesting value. */
POP AX
MOVW !_usCriticalNesting, AX
.macro portRESTORE_CONTEXT MACRO
SEL RB0
/* Restore the Stack pointer. */
MOVW AX, !_pxCurrentTCB
MOVW HL, AX
MOVW AX, [HL]
MOVW SP, AX
/* Restore usCriticalNesting value. */
POP AX
MOVW !_usCriticalNesting, AX
/* Restore the alternative register banks - only necessary in the GCC
port. Register bank 3 is dedicated for interrupts use so is not saved or
restored. */
SEL RB2
POP HL
POP DE
POP BC
POP AX
SEL RB1
POP HL
POP DE
POP BC
POP AX
SEL RB0
/* Restore the necessary general purpose registers. */
POP BC
POP DE
/* Restore the ES register. */
POP AX
MOV ES, A
/* Restore the CS register. */
XCH A, X
MOV CS, A
/* Restore general purpose register HL. */
POP HL
/* Restore AX. */
POP AX
/* Restore the alternative register banks - only necessary in the GCC
* port. Register bank 3 is dedicated for interrupts use so is not saved or
* restored. */
SEL RB2
POP HL
POP DE
POP BC
POP AX
SEL RB1
POP HL
POP DE
POP BC
POP AX
SEL RB0
/* Restore the necessary general purpose registers. */
POP BC
POP DE
/* Restore the ES register. */
POP AX
MOV ES, A
/* Restore the CS register. */
XCH A, X
MOV CS, A
/* Restore general purpose register HL. */
POP HL
/* Restore AX. */
POP AX
.endm
.endm

View file

@ -30,8 +30,8 @@
#include "task.h"
/* The critical nesting value is initialised to a non zero value to ensure
* interrupts don't accidentally become enabled before the scheduler is started. */
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
interrupts don't accidentally become enabled before the scheduler is started. */
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
/* Initial PSW value allocated to a newly created task.
* 11000110
@ -44,16 +44,16 @@
* |--------------------- Zero Flag set
* ---------------------- Global Interrupt Flag set (enabled)
*/
#define portPSW ( 0xc6UL )
#define portPSW ( 0xc6UL )
/* 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 exited 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 that could cause problems during the startup
* sequence. */
a critical section is entered the count is incremented. Each time a critical
section is exited 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 that could cause problems during the startup
sequence. */
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
/*-----------------------------------------------------------*/
@ -61,7 +61,7 @@ volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
/*
* Sets up the periodic ISR used for the RTOS tick.
*/
__attribute__( ( weak ) ) void vApplicationSetupTimerInterrupt( void );
__attribute__((weak)) void vApplicationSetupTimerInterrupt( void );
/*
* Starts the scheduler by loading the context of the first task to run.
@ -77,136 +77,135 @@ extern void vPortStartFirstTask( 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 )
{
uint32_t * pulLocal;
uint32_t *pulLocal;
/* Stack type and pointers to the stack type are both 2 bytes. */
/* Stack type and pointers to the stack type are both 2 bytes. */
/* Parameters are passed in on the stack, and written using a 32bit value
* hence a space is left for the second two bytes. */
pxTopOfStack--;
/* Parameters are passed in on the stack, and written using a 32bit value
hence a space is left for the second two bytes. */
pxTopOfStack--;
/* Write in the parameter value. */
pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( StackType_t ) pvParameters;
pxTopOfStack--;
/* Write in the parameter value. */
pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( StackType_t ) pvParameters;
pxTopOfStack--;
/* The return address, leaving space for the first two bytes of the
* 32-bit value. */
pxTopOfStack--;
pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( uint32_t ) 0;
pxTopOfStack--;
/* The return address, leaving space for the first two bytes of the
32-bit value. */
pxTopOfStack--;
pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( uint32_t ) 0;
pxTopOfStack--;
/* The start address / PSW value is also written in as a 32bit value,
* so leave a space for the second two bytes. */
pxTopOfStack--;
/* The start address / PSW value is also written in as a 32bit value,
so leave a space for the second two bytes. */
pxTopOfStack--;
/* Task function start address combined with the PSW. */
pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--;
/* Task function start address combined with the PSW. */
pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--;
/* An initial value for the AX register. */
*pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--;
/* An initial value for the AX register. */
*pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--;
/* An initial value for the HL register. */
*pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--;
/* An initial value for the HL register. */
*pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--;
/* CS and ES registers. */
*pxTopOfStack = ( StackType_t ) 0x0F00;
pxTopOfStack--;
/* CS and ES registers. */
*pxTopOfStack = ( StackType_t ) 0x0F00;
pxTopOfStack--;
/* The remaining general purpose registers bank 0 (DE and BC) and the other
* two register banks...register bank 3 is dedicated for use by interrupts so
* is not saved as part of the task context. */
pxTopOfStack -= 10;
/* The remaining general purpose registers bank 0 (DE and BC) and the other
two register banks...register bank 3 is dedicated for use by interrupts so
is not saved as part of the task context. */
pxTopOfStack -= 10;
/* Finally the critical section nesting count is set to zero when the task
* first starts. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Finally the critical section nesting count is set to zero when the task
first starts. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Return a pointer to the top of the stack that has beene generated so it
* can be stored in the task control block for the task. */
return pxTopOfStack;
/* Return a pointer to the top of the stack that has beene generated so it
can be stored in the task control block for the task. */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
portBASE_TYPE xPortStartScheduler( void )
{
/* Setup the hardware to generate the tick. Interrupts are disabled when
* this function is called. */
vApplicationSetupTimerInterrupt();
/* Setup the hardware to generate the tick. Interrupts are disabled when
this function is called. */
vApplicationSetupTimerInterrupt();
/* Restore the context of the first task that is going to run. */
vPortStartFirstTask();
/* Restore the context of the first task that is going to run. */
vPortStartFirstTask();
/* Execution should not reach here as the tasks are now running! */
return pdTRUE;
/* Execution should not reach here as the tasks are now running! */
return pdTRUE;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* It is unlikely that the RL78 port will get stopped. */
/* It is unlikely that the RL78 port will get stopped. */
}
/*-----------------------------------------------------------*/
__attribute__( ( weak ) ) void vApplicationSetupTimerInterrupt( void )
__attribute__((weak)) void vApplicationSetupTimerInterrupt( void )
{
const uint16_t usClockHz = 15000UL; /* Internal clock. */
const uint16_t usCompareMatch = ( usClockHz / configTICK_RATE_HZ ) + 1UL;
const uint16_t usClockHz = 15000UL; /* Internal clock. */
const uint16_t usCompareMatch = ( usClockHz / configTICK_RATE_HZ ) + 1UL;
/* Use the internal 15K clock. */
OSMC = ( unsigned char ) 0x16;
/* Use the internal 15K clock. */
OSMC = ( unsigned char ) 0x16;
#ifdef RTCEN
{
/* Supply the interval timer clock. */
RTCEN = ( unsigned char ) 1U;
#ifdef RTCEN
{
/* Supply the interval timer clock. */
RTCEN = ( unsigned char ) 1U;
/* Disable INTIT interrupt. */
ITMK = ( unsigned char ) 1;
/* Disable INTIT interrupt. */
ITMK = ( unsigned char ) 1;
/* Disable ITMC operation. */
ITMC = ( unsigned char ) 0x0000;
/* Disable ITMC operation. */
ITMC = ( unsigned char ) 0x0000;
/* Clear INIT interrupt. */
ITIF = ( unsigned char ) 0;
/* Clear INIT interrupt. */
ITIF = ( unsigned char ) 0;
/* Set interval and enable interrupt operation. */
ITMC = usCompareMatch | 0x8000U;
/* Set interval and enable interrupt operation. */
ITMC = usCompareMatch | 0x8000U;
/* Enable INTIT interrupt. */
ITMK = ( unsigned char ) 0;
}
#endif /* ifdef RTCEN */
/* Enable INTIT interrupt. */
ITMK = ( unsigned char ) 0;
}
#endif
#ifdef TMKAEN
{
/* Supply the interval timer clock. */
TMKAEN = ( unsigned char ) 1U;
#ifdef TMKAEN
{
/* Supply the interval timer clock. */
TMKAEN = ( unsigned char ) 1U;
/* Disable INTIT interrupt. */
TMKAMK = ( unsigned char ) 1;
/* Disable INTIT interrupt. */
TMKAMK = ( unsigned char ) 1;
/* Disable ITMC operation. */
ITMC = ( unsigned char ) 0x0000;
/* Disable ITMC operation. */
ITMC = ( unsigned char ) 0x0000;
/* Clear INIT interrupt. */
TMKAIF = ( unsigned char ) 0;
/* Clear INIT interrupt. */
TMKAIF = ( unsigned char ) 0;
/* Set interval and enable interrupt operation. */
ITMC = usCompareMatch | 0x8000U;
/* Set interval and enable interrupt operation. */
ITMC = usCompareMatch | 0x8000U;
/* Enable INTIT interrupt. */
TMKAMK = ( unsigned char ) 0;
}
#endif /* ifdef TMKAEN */
/* Enable INTIT interrupt. */
TMKAMK = ( unsigned char ) 0;
}
#endif
}
/*-----------------------------------------------------------*/

View file

@ -40,81 +40,82 @@
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint16_t
#define portBASE_TYPE short
#define portPOINTER_SIZE_TYPE uint16_t
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint16_t
#define portBASE_TYPE short
#define portPOINTER_SIZE_TYPE uint16_t
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
#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
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Interrupt control macros. */
#define portDISABLE_INTERRUPTS() __asm volatile ( "DI" )
#define portENABLE_INTERRUPTS() __asm volatile ( "EI" )
#define portDISABLE_INTERRUPTS() __asm volatile ( "DI" )
#define portENABLE_INTERRUPTS() __asm volatile ( "EI" )
/*-----------------------------------------------------------*/
/* Critical section control macros. */
#define portNO_CRITICAL_SECTION_NESTING ( ( unsigned short ) 0 )
#define portNO_CRITICAL_SECTION_NESTING ( ( unsigned short ) 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. */
#define portYIELD() __asm volatile ( "BRK" )
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()
#define portNOP() __asm volatile ( "NOP" )
#define portYIELD() __asm volatile ( "BRK" )
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()
#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 )
#endif /* PORTMACRO_H */

File diff suppressed because it is too large Load diff

View file

@ -27,11 +27,11 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
@ -44,100 +44,101 @@
*/
/* Type definitions - these are a bit legacy and not really used now, other than
* portSTACK_TYPE and portBASE_TYPE. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
portSTACK_TYPE and portBASE_TYPE. */
#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
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */
#define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __asm volatile ( "NOP" )
#define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */
#define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __asm volatile( "NOP" )
/* Save clobbered register, set ITU SWINR (at address 0x872E0), read the value
* back to ensure it is set before continuing, then restore the clobbered
* register. */
#define portYIELD() \
__asm volatile \
( \
"MOV.L #0x872E0, r5 \n\t"\
"MOV.B #1, [r5] \n\t"\
"MOV.L [r5], r5 \n\t"\
::: "r5" \
)
back to ensure it is set before continuing, then restore the clobbered
register. */
#define portYIELD() \
__asm volatile \
( \
"MOV.L #0x872E0, r5 \n\t" \
"MOV.B #1, [r5] \n\t" \
"MOV.L [r5], r5 \n\t" \
::: "r5" \
)
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) { portYIELD(); }
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) { portYIELD(); }
/* These macros should not be called directly, but through the
* taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is
* performed if configASSERT() is defined to ensure an assertion handler does not
* inadvertently attempt to lower the IPL when the call to assert was triggered
* because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY
* when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API
* functions are those that end in FromISR. FreeRTOS maintains a separate
* interrupt API to ensure API function and interrupt entry is as fast and as
* simple as possible. */
#define portENABLE_INTERRUPTS() __asm volatile ( "MVTIPL #0")
#ifdef configASSERT
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( ulPortGetIPL() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#define portDISABLE_INTERRUPTS() if( ulPortGetIPL() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __asm volatile ( "MVTIPL %0"::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#else
#define portDISABLE_INTERRUPTS() __asm volatile ( "MVTIPL %0"::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#endif
taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is
performed if configASSERT() is defined to ensure an assertion handler does not
inadvertently attempt to lower the IPL when the call to assert was triggered
because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY
when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API
functions are those that end in FromISR. FreeRTOS maintains a separate
interrupt API to ensure API function and interrupt entry is as fast and as
simple as possible. */
#define portENABLE_INTERRUPTS() __asm volatile ( "MVTIPL #0" )
#ifdef configASSERT
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( ulPortGetIPL() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#define portDISABLE_INTERRUPTS() if( ulPortGetIPL() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )
#else
#define portDISABLE_INTERRUPTS() __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )
#endif
/* Critical nesting counts are stored in the TCB. */
#define portCRITICAL_NESTING_IN_TCB ( 1 )
#define portCRITICAL_NESTING_IN_TCB ( 1 )
/* The critical nesting functions defined within tasks.c. */
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()
/* As this port allows interrupt nesting... */
uint32_t ulPortGetIPL( void ) __attribute__( ( naked ) );
void vPortSetIPL( uint32_t ulNewIPL ) __attribute__( ( naked ) );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortGetIPL(); portDISABLE_INTERRUPTS()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) vPortSetIPL( uxSavedInterruptStatus )
uint32_t ulPortGetIPL( void ) __attribute__((naked));
void vPortSetIPL( uint32_t ulNewIPL ) __attribute__((naked));
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortGetIPL(); portDISABLE_INTERRUPTS()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) vPortSetIPL( uxSavedInterruptStatus )
/* Tickless idle/low power functionality. */
#if configUSE_TICKLESS_IDLE == 1
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
#endif
#if configUSE_TICKLESS_IDLE == 1
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
#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 )
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -26,8 +26,8 @@
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the SH2A port.
*----------------------------------------------------------*/
* Implementation of functions defined in portable.h for the SH2A port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
@ -42,17 +42,17 @@
/*-----------------------------------------------------------*/
/* Tasks should start with interrupts enabled and in Supervisor mode, therefore
* PSW is set with U and I set, and PM and IPL clear. */
PSW is set with U and I set, and PM and IPL clear. */
#define portINITIAL_PSW ( ( StackType_t ) 0x00030000 )
#define portINITIAL_FPSW ( ( StackType_t ) 0x00000100 )
/* These macros allow a critical section to be added around the call to
* xTaskIncrementTick(), which is only ever called from interrupts at the kernel
* priority - ie a known priority. Therefore these local macros are a slight
* optimisation compared to calling the global SET/CLEAR_INTERRUPT_MASK macros,
* which would require the old IPL to be read first and stored in a local variable. */
#define portDISABLE_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0"::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#define portENABLE_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0"::"i" ( configKERNEL_INTERRUPT_PRIORITY ) )
xTaskIncrementTick(), which is only ever called from interrupts at the kernel
priority - ie a known priority. Therefore these local macros are a slight
optimisation compared to calling the global SET/CLEAR_INTERRUPT_MASK macros,
which would require the old IPL to be read first and stored in a local variable. */
#define portDISABLE_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )
#define portENABLE_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0" ::"i"(configKERNEL_INTERRUPT_PRIORITY) )
/*-----------------------------------------------------------*/
@ -60,308 +60,299 @@
* Function to start the first task executing - written in asm code as direct
* access to registers is required.
*/
static void prvStartFirstTask( void ) __attribute__( ( naked ) );
static void prvStartFirstTask( void ) __attribute__((naked));
/*
* Software interrupt handler. Performs the actual context switch (saving and
* restoring of registers). Written in asm code as direct register access is
* required.
*/
void vSoftwareInterruptISR( void ) __attribute__( ( naked ) );
void vSoftwareInterruptISR( void ) __attribute__((naked));
/*
* The tick interrupt handler.
*/
void vTickISR( void ) __attribute__( ( interrupt ) );
void vTickISR( void ) __attribute__((interrupt));
/*-----------------------------------------------------------*/
extern void * pxCurrentTCB;
extern void *pxCurrentTCB;
/*-----------------------------------------------------------*/
/*
* 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 )
{
/* R0 is not included as it is the stack pointer. */
/* R0 is not included as it is the stack pointer. */
*pxTopOfStack = 0x00;
pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSW;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode;
*pxTopOfStack = 0x00;
pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSW;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode;
/* When debugging it can be useful if every register is set to a known
* value. Otherwise code space can be saved by just setting the registers
* that need to be set. */
#ifdef USE_FULL_REGISTER_INITIALISATION
{
pxTopOfStack--;
*pxTopOfStack = 0xffffffff; /* r15. */
pxTopOfStack--;
*pxTopOfStack = 0xeeeeeeee;
pxTopOfStack--;
*pxTopOfStack = 0xdddddddd;
pxTopOfStack--;
*pxTopOfStack = 0xcccccccc;
pxTopOfStack--;
*pxTopOfStack = 0xbbbbbbbb;
pxTopOfStack--;
*pxTopOfStack = 0xaaaaaaaa;
pxTopOfStack--;
*pxTopOfStack = 0x99999999;
pxTopOfStack--;
*pxTopOfStack = 0x88888888;
pxTopOfStack--;
*pxTopOfStack = 0x77777777;
pxTopOfStack--;
*pxTopOfStack = 0x66666666;
pxTopOfStack--;
*pxTopOfStack = 0x55555555;
pxTopOfStack--;
*pxTopOfStack = 0x44444444;
pxTopOfStack--;
*pxTopOfStack = 0x33333333;
pxTopOfStack--;
*pxTopOfStack = 0x22222222;
pxTopOfStack--;
}
#else /* ifdef USE_FULL_REGISTER_INITIALISATION */
{
pxTopOfStack -= 15;
}
#endif /* ifdef USE_FULL_REGISTER_INITIALISATION */
/* When debugging it can be useful if every register is set to a known
value. Otherwise code space can be saved by just setting the registers
that need to be set. */
#ifdef USE_FULL_REGISTER_INITIALISATION
{
pxTopOfStack--;
*pxTopOfStack = 0xffffffff; /* r15. */
pxTopOfStack--;
*pxTopOfStack = 0xeeeeeeee;
pxTopOfStack--;
*pxTopOfStack = 0xdddddddd;
pxTopOfStack--;
*pxTopOfStack = 0xcccccccc;
pxTopOfStack--;
*pxTopOfStack = 0xbbbbbbbb;
pxTopOfStack--;
*pxTopOfStack = 0xaaaaaaaa;
pxTopOfStack--;
*pxTopOfStack = 0x99999999;
pxTopOfStack--;
*pxTopOfStack = 0x88888888;
pxTopOfStack--;
*pxTopOfStack = 0x77777777;
pxTopOfStack--;
*pxTopOfStack = 0x66666666;
pxTopOfStack--;
*pxTopOfStack = 0x55555555;
pxTopOfStack--;
*pxTopOfStack = 0x44444444;
pxTopOfStack--;
*pxTopOfStack = 0x33333333;
pxTopOfStack--;
*pxTopOfStack = 0x22222222;
pxTopOfStack--;
}
#else
{
pxTopOfStack -= 15;
}
#endif
*pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_FPSW;
pxTopOfStack--;
*pxTopOfStack = 0x12345678; /* Accumulator. */
pxTopOfStack--;
*pxTopOfStack = 0x87654321; /* Accumulator. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_FPSW;
pxTopOfStack--;
*pxTopOfStack = 0x12345678; /* Accumulator. */
pxTopOfStack--;
*pxTopOfStack = 0x87654321; /* Accumulator. */
return pxTopOfStack;
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
extern void vApplicationSetupTimerInterrupt( void );
extern void vApplicationSetupTimerInterrupt( void );
/* Use pxCurrentTCB just so it does not get optimised away. */
if( pxCurrentTCB != NULL )
{
/* Call an application function to set up the timer that will generate the
* tick interrupt. This way the application can decide which peripheral to
* use. A demo application is provided to show a suitable example. */
vApplicationSetupTimerInterrupt();
/* Use pxCurrentTCB just so it does not get optimised away. */
if( pxCurrentTCB != NULL )
{
/* Call an application function to set up the timer that will generate the
tick interrupt. This way the application can decide which peripheral to
use. A demo application is provided to show a suitable example. */
vApplicationSetupTimerInterrupt();
/* Enable the software interrupt. */
_IEN( _ICU_SWINT ) = 1;
/* Enable the software interrupt. */
_IEN( _ICU_SWINT ) = 1;
/* Ensure the software interrupt is clear. */
_IR( _ICU_SWINT ) = 0;
/* Ensure the software interrupt is clear. */
_IR( _ICU_SWINT ) = 0;
/* Ensure the software interrupt is set to the kernel priority. */
_IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;
/* Ensure the software interrupt is set to the kernel priority. */
_IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;
/* Start the first task. */
prvStartFirstTask();
}
/* Start the first task. */
prvStartFirstTask();
}
/* Should not get here. */
return pdFAIL;
/* Should not get here. */
return pdFAIL;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */
configASSERT( pxCurrentTCB == NULL );
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT( pxCurrentTCB == NULL );
}
/*-----------------------------------------------------------*/
static void prvStartFirstTask( void )
{
__asm volatile
(
__asm volatile
(
/* When starting the scheduler there is nothing that needs moving to the
interrupt stack because the function is not called from an interrupt.
Just ensure the current stack is the user stack. */
"SETPSW U \n" \
/* When starting the scheduler there is nothing that needs moving to the
* interrupt stack because the function is not called from an interrupt.
* Just ensure the current stack is the user stack. */
"SETPSW U \n"\
/* Obtain the location of the stack associated with which ever task
pxCurrentTCB is currently pointing to. */
"MOV.L #_pxCurrentTCB, R15 \n" \
"MOV.L [R15], R15 \n" \
"MOV.L [R15], R0 \n" \
/* Restore the registers from the stack of the task pointed to by
pxCurrentTCB. */
"POP R15 \n" \
/* Obtain the location of the stack associated with which ever task
* pxCurrentTCB is currently pointing to. */
"MOV.L #_pxCurrentTCB, R15 \n"\
"MOV.L [R15], R15 \n"\
"MOV.L [R15], R0 \n"\
/* Accumulator low 32 bits. */
"MVTACLO R15 \n" \
"POP R15 \n" \
/* Accumulator high 32 bits. */
"MVTACHI R15 \n" \
"POP R15 \n" \
/* Restore the registers from the stack of the task pointed to by
* pxCurrentTCB. */
"POP R15 \n"\
/* Floating point status word. */
"MVTC R15, FPSW \n" \
/* Accumulator low 32 bits. */
"MVTACLO R15 \n"\
"POP R15 \n"\
/* R1 to R15 - R0 is not included as it is the SP. */
"POPM R1-R15 \n" \
/* Accumulator high 32 bits. */
"MVTACHI R15 \n"\
"POP R15 \n"\
/* Floating point status word. */
"MVTC R15, FPSW \n"\
/* R1 to R15 - R0 is not included as it is the SP. */
"POPM R1-R15 \n"\
/* This pops the remaining registers. */
"RTE \n"\
"NOP \n"\
"NOP \n"
);
/* This pops the remaining registers. */
"RTE \n" \
"NOP \n" \
"NOP \n"
);
}
/*-----------------------------------------------------------*/
void vSoftwareInterruptISR( void )
{
__asm volatile
(
/* Re-enable interrupts. */
"SETPSW I \n"\
__asm volatile
(
/* Re-enable interrupts. */
"SETPSW I \n" \
/* Move the data that was automatically pushed onto the interrupt stack when
the interrupt occurred from the interrupt stack to the user stack.
/* Move the data that was automatically pushed onto the interrupt stack when
* the interrupt occurred from the interrupt stack to the user stack.
*
* R15 is saved before it is clobbered. */
"PUSH.L R15 \n"\
R15 is saved before it is clobbered. */
"PUSH.L R15 \n" \
/* Read the user stack pointer. */
"MVFC USP, R15 \n"\
/* Read the user stack pointer. */
"MVFC USP, R15 \n" \
/* Move the address down to the data being moved. */
"SUB #12, R15 \n"\
"MVTC R15, USP \n"\
/* Move the address down to the data being moved. */
"SUB #12, R15 \n" \
"MVTC R15, USP \n" \
/* Copy the data across, R15, then PC, then PSW. */
"MOV.L [ R0 ], [ R15 ] \n"\
"MOV.L 4[ R0 ], 4[ R15 ] \n"\
"MOV.L 8[ R0 ], 8[ R15 ] \n"\
/* Copy the data across, R15, then PC, then PSW. */
"MOV.L [ R0 ], [ R15 ] \n" \
"MOV.L 4[ R0 ], 4[ R15 ] \n" \
"MOV.L 8[ R0 ], 8[ R15 ] \n" \
/* Move the interrupt stack pointer to its new correct position. */
"ADD #12, R0 \n"\
/* Move the interrupt stack pointer to its new correct position. */
"ADD #12, R0 \n" \
/* All the rest of the registers are saved directly to the user stack. */
"SETPSW U \n"\
/* All the rest of the registers are saved directly to the user stack. */
"SETPSW U \n" \
/* Save the rest of the general registers (R15 has been saved already). */
"PUSHM R1-R14 \n"\
/* Save the rest of the general registers (R15 has been saved already). */
"PUSHM R1-R14 \n" \
/* Save the FPSW and accumulator. */
"MVFC FPSW, R15 \n"\
"PUSH.L R15 \n"\
"MVFACHI R15 \n"\
"PUSH.L R15 \n"\
/* Save the FPSW and accumulator. */
"MVFC FPSW, R15 \n" \
"PUSH.L R15 \n" \
"MVFACHI R15 \n" \
"PUSH.L R15 \n" \
/* Middle word. */
"MVFACMI R15 \n"\
/* Middle word. */
"MVFACMI R15 \n" \
/* Shifted left as it is restored to the low order word. */
"SHLL #16, R15 \n"\
"PUSH.L R15 \n"\
/* Shifted left as it is restored to the low order word. */
"SHLL #16, R15 \n" \
"PUSH.L R15 \n" \
/* Save the stack pointer to the TCB. */
"MOV.L #_pxCurrentTCB, R15 \n"\
"MOV.L [ R15 ], R15 \n"\
"MOV.L R0, [ R15 ] \n"\
/* Save the stack pointer to the TCB. */
"MOV.L #_pxCurrentTCB, R15 \n" \
"MOV.L [ R15 ], R15 \n" \
"MOV.L R0, [ R15 ] \n" \
/* Ensure the interrupt mask is set to the syscall priority while the kernel
structures are being accessed. */
"MVTIPL %0 \n" \
/* Ensure the interrupt mask is set to the syscall priority while the kernel
* structures are being accessed. */
"MVTIPL %0 \n"\
/* Select the next task to run. */
"BSR.A _vTaskSwitchContext \n" \
/* Select the next task to run. */
"BSR.A _vTaskSwitchContext \n"\
/* Reset the interrupt mask as no more data structure access is required. */
"MVTIPL %1 \n" \
/* Reset the interrupt mask as no more data structure access is required. */
"MVTIPL %1 \n"\
/* Load the stack pointer of the task that is now selected as the Running
state task from its TCB. */
"MOV.L #_pxCurrentTCB,R15 \n" \
"MOV.L [ R15 ], R15 \n" \
"MOV.L [ R15 ], R0 \n" \
/* Load the stack pointer of the task that is now selected as the Running
* state task from its TCB. */
"MOV.L #_pxCurrentTCB,R15 \n"\
"MOV.L [ R15 ], R15 \n"\
"MOV.L [ R15 ], R0 \n"\
/* Restore the context of the new task. The PSW (Program Status Word) and
* PC will be popped by the RTE instruction. */
"POP R15 \n"\
"MVTACLO R15 \n"\
"POP R15 \n"\
"MVTACHI R15 \n"\
"POP R15 \n"\
"MVTC R15, FPSW \n"\
"POPM R1-R15 \n"\
"RTE \n"\
"NOP \n"\
"NOP "
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ), "i" ( configKERNEL_INTERRUPT_PRIORITY )
);
/* Restore the context of the new task. The PSW (Program Status Word) and
PC will be popped by the RTE instruction. */
"POP R15 \n" \
"MVTACLO R15 \n" \
"POP R15 \n" \
"MVTACHI R15 \n" \
"POP R15 \n" \
"MVTC R15, FPSW \n" \
"POPM R1-R15 \n" \
"RTE \n" \
"NOP \n" \
"NOP "
:: "i"(configMAX_SYSCALL_INTERRUPT_PRIORITY), "i"(configKERNEL_INTERRUPT_PRIORITY)
);
}
/*-----------------------------------------------------------*/
void vTickISR( void )
{
/* Re-enabled interrupts. */
__asm volatile ( "SETPSW I");
/* Re-enabled interrupts. */
__asm volatile( "SETPSW I" );
/* Increment the tick, and perform any processing the new tick value
* necessitates. Ensure IPL is at the max syscall value first. */
portDISABLE_INTERRUPTS_FROM_KERNEL_ISR();
{
if( xTaskIncrementTick() != pdFALSE )
{
taskYIELD();
}
}
portENABLE_INTERRUPTS_FROM_KERNEL_ISR();
/* Increment the tick, and perform any processing the new tick value
necessitates. Ensure IPL is at the max syscall value first. */
portDISABLE_INTERRUPTS_FROM_KERNEL_ISR();
{
if( xTaskIncrementTick() != pdFALSE )
{
taskYIELD();
}
}
portENABLE_INTERRUPTS_FROM_KERNEL_ISR();
}
/*-----------------------------------------------------------*/
uint32_t ulPortGetIPL( void )
{
__asm volatile
(
"MVFC PSW, R1 \n"\
"SHLR #24, R1 \n"\
"RTS "
);
__asm volatile
(
"MVFC PSW, R1 \n" \
"SHLR #24, R1 \n" \
"RTS "
);
/* This will never get executed, but keeps the compiler from complaining. */
return 0;
/* This will never get executed, but keeps the compiler from complaining. */
return 0;
}
/*-----------------------------------------------------------*/
void vPortSetIPL( uint32_t ulNewIPL )
{
__asm volatile
(
"PUSH R5 \n"\
"MVFC PSW, R5 \n"\
"SHLL #24, R1 \n"\
"AND #-0F000001H, R5 \n"\
"OR R1, R5 \n"\
"MVTC R5, PSW \n"\
"POP R5 \n"\
"RTS "
);
__asm volatile
(
"PUSH R5 \n" \
"MVFC PSW, R5 \n" \
"SHLL #24, R1 \n" \
"AND #-0F000001H, R5 \n" \
"OR R1, R5 \n" \
"MVTC R5, PSW \n" \
"POP R5 \n" \
"RTS "
);
}

View file

@ -27,11 +27,11 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
@ -44,94 +44,95 @@
*/
/* Type definitions - these are a bit legacy and not really used now, other than
* portSTACK_TYPE and portBASE_TYPE. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
portSTACK_TYPE and portBASE_TYPE. */
#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
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */
#define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __asm volatile ( "NOP" )
#define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */
#define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __asm volatile( "NOP" )
/* Yield equivalent to "*portITU_SWINTR = 0x01; ( void ) *portITU_SWINTR;"
* where portITU_SWINTR is the location of the software interrupt register
* (0x000872E0). Don't rely on the assembler to select a register, so instead
* save and restore clobbered registers manually. */
#define portYIELD() \
__asm volatile \
( \
"PUSH.L R10 \n"\
"MOV.L #0x872E0, R10 \n"\
"MOV.B #0x1, [R10] \n"\
"MOV.L [R10], R10 \n"\
"POP R10 \n"\
)
where portITU_SWINTR is the location of the software interrupt register
(0x000872E0). Don't rely on the assembler to select a register, so instead
save and restore clobbered registers manually. */
#define portYIELD() \
__asm volatile \
( \
"PUSH.L R10 \n" \
"MOV.L #0x872E0, R10 \n" \
"MOV.B #0x1, [R10] \n" \
"MOV.L [R10], R10 \n" \
"POP R10 \n" \
)
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) portYIELD()
/* These macros should not be called directly, but through the
* taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is
* performed if configASSERT() is defined to ensure an assertion handler does not
* inadvertently attempt to lower the IPL when the call to assert was triggered
* because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY
* when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API
* functions are those that end in FromISR. FreeRTOS maintains a separate
* interrupt API to ensure API function and interrupt entry is as fast and as
* simple as possible. */
#define portENABLE_INTERRUPTS() __asm volatile ( "MVTIPL #0")
#ifdef configASSERT
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( ulPortGetIPL() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#define portDISABLE_INTERRUPTS() if( ulPortGetIPL() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __asm volatile ( "MVTIPL %0"::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#else
#define portDISABLE_INTERRUPTS() __asm volatile ( "MVTIPL %0"::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#endif
taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is
performed if configASSERT() is defined to ensure an assertion handler does not
inadvertently attempt to lower the IPL when the call to assert was triggered
because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY
when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API
functions are those that end in FromISR. FreeRTOS maintains a separate
interrupt API to ensure API function and interrupt entry is as fast and as
simple as possible. */
#define portENABLE_INTERRUPTS() __asm volatile ( "MVTIPL #0" )
#ifdef configASSERT
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( ulPortGetIPL() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#define portDISABLE_INTERRUPTS() if( ulPortGetIPL() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )
#else
#define portDISABLE_INTERRUPTS() __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )
#endif
/* Critical nesting counts are stored in the TCB. */
#define portCRITICAL_NESTING_IN_TCB ( 1 )
#define portCRITICAL_NESTING_IN_TCB ( 1 )
/* The critical nesting functions defined within tasks.c. */
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()
/* As this port allows interrupt nesting... */
uint32_t ulPortGetIPL( void ) __attribute__( ( naked ) );
void vPortSetIPL( uint32_t ulNewIPL ) __attribute__( ( naked ) );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortGetIPL(); portDISABLE_INTERRUPTS()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) vPortSetIPL( uxSavedInterruptStatus )
uint32_t ulPortGetIPL( void ) __attribute__((naked));
void vPortSetIPL( uint32_t ulNewIPL ) __attribute__((naked));
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortGetIPL(); portDISABLE_INTERRUPTS()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) vPortSetIPL( uxSavedInterruptStatus )
/*-----------------------------------------------------------*/
/* 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 */

View file

@ -26,8 +26,8 @@
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the SH2A port.
*----------------------------------------------------------*/
* Implementation of functions defined in portable.h for the SH2A port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
@ -42,17 +42,17 @@
/*-----------------------------------------------------------*/
/* Tasks should start with interrupts enabled and in Supervisor mode, therefore
* PSW is set with U and I set, and PM and IPL clear. */
PSW is set with U and I set, and PM and IPL clear. */
#define portINITIAL_PSW ( ( StackType_t ) 0x00030000 )
#define portINITIAL_FPSW ( ( StackType_t ) 0x00000100 )
/* These macros allow a critical section to be added around the call to
* xTaskIncrementTick(), which is only ever called from interrupts at the kernel
* priority - ie a known priority. Therefore these local macros are a slight
* optimisation compared to calling the global SET/CLEAR_INTERRUPT_MASK macros,
* which would require the old IPL to be read first and stored in a local variable. */
#define portMASK_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
#define portUNMASK_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0" ::"i" ( configKERNEL_INTERRUPT_PRIORITY ) )
xTaskIncrementTick(), which is only ever called from interrupts at the kernel
priority - ie a known priority. Therefore these local macros are a slight
optimisation compared to calling the global SET/CLEAR_INTERRUPT_MASK macros,
which would require the old IPL to be read first and stored in a local variable. */
#define portMASK_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )
#define portUNMASK_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0" ::"i"(configKERNEL_INTERRUPT_PRIORITY) )
/*-----------------------------------------------------------*/
@ -60,357 +60,348 @@
* Function to start the first task executing - written in asm code as direct
* access to registers is required.
*/
static void prvStartFirstTask( void ) __attribute__( ( naked ) );
static void prvStartFirstTask( void ) __attribute__((naked));
/*
* Software interrupt handler. Performs the actual context switch (saving and
* restoring of registers). Written in asm code as direct register access is
* required.
*/
void vSoftwareInterruptISR( void ) __attribute__( ( naked ) );
void vSoftwareInterruptISR( void ) __attribute__((naked));
/*
* The tick interrupt handler.
*/
void vTickISR( void ) __attribute__( ( interrupt ) );
void vTickISR( void ) __attribute__((interrupt));
/*-----------------------------------------------------------*/
extern void * pxCurrentTCB;
extern void *pxCurrentTCB;
/*-----------------------------------------------------------*/
/*
* 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 )
{
/* R0 is not included as it is the stack pointer. */
/* R0 is not included as it is the stack pointer. */
*pxTopOfStack = 0x00;
pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSW;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode;
*pxTopOfStack = 0x00;
pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSW;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode;
/* When debugging it can be useful if every register is set to a known
* value. Otherwise code space can be saved by just setting the registers
* that need to be set. */
#ifdef USE_FULL_REGISTER_INITIALISATION
{
pxTopOfStack--;
*pxTopOfStack = 0xffffffff; /* r15. */
pxTopOfStack--;
*pxTopOfStack = 0xeeeeeeee;
pxTopOfStack--;
*pxTopOfStack = 0xdddddddd;
pxTopOfStack--;
*pxTopOfStack = 0xcccccccc;
pxTopOfStack--;
*pxTopOfStack = 0xbbbbbbbb;
pxTopOfStack--;
*pxTopOfStack = 0xaaaaaaaa;
pxTopOfStack--;
*pxTopOfStack = 0x99999999;
pxTopOfStack--;
*pxTopOfStack = 0x88888888;
pxTopOfStack--;
*pxTopOfStack = 0x77777777;
pxTopOfStack--;
*pxTopOfStack = 0x66666666;
pxTopOfStack--;
*pxTopOfStack = 0x55555555;
pxTopOfStack--;
*pxTopOfStack = 0x44444444;
pxTopOfStack--;
*pxTopOfStack = 0x33333333;
pxTopOfStack--;
*pxTopOfStack = 0x22222222;
pxTopOfStack--;
}
#else /* ifdef USE_FULL_REGISTER_INITIALISATION */
{
pxTopOfStack -= 15;
}
#endif /* ifdef USE_FULL_REGISTER_INITIALISATION */
/* When debugging it can be useful if every register is set to a known
value. Otherwise code space can be saved by just setting the registers
that need to be set. */
#ifdef USE_FULL_REGISTER_INITIALISATION
{
pxTopOfStack--;
*pxTopOfStack = 0xffffffff; /* r15. */
pxTopOfStack--;
*pxTopOfStack = 0xeeeeeeee;
pxTopOfStack--;
*pxTopOfStack = 0xdddddddd;
pxTopOfStack--;
*pxTopOfStack = 0xcccccccc;
pxTopOfStack--;
*pxTopOfStack = 0xbbbbbbbb;
pxTopOfStack--;
*pxTopOfStack = 0xaaaaaaaa;
pxTopOfStack--;
*pxTopOfStack = 0x99999999;
pxTopOfStack--;
*pxTopOfStack = 0x88888888;
pxTopOfStack--;
*pxTopOfStack = 0x77777777;
pxTopOfStack--;
*pxTopOfStack = 0x66666666;
pxTopOfStack--;
*pxTopOfStack = 0x55555555;
pxTopOfStack--;
*pxTopOfStack = 0x44444444;
pxTopOfStack--;
*pxTopOfStack = 0x33333333;
pxTopOfStack--;
*pxTopOfStack = 0x22222222;
pxTopOfStack--;
}
#else
{
pxTopOfStack -= 15;
}
#endif
*pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_FPSW;
pxTopOfStack--;
*pxTopOfStack = 0x11111111; /* Accumulator 0. */
pxTopOfStack--;
*pxTopOfStack = 0x22222222; /* Accumulator 0. */
pxTopOfStack--;
*pxTopOfStack = 0x33333333; /* Accumulator 0. */
pxTopOfStack--;
*pxTopOfStack = 0x44444444; /* Accumulator 1. */
pxTopOfStack--;
*pxTopOfStack = 0x55555555; /* Accumulator 1. */
pxTopOfStack--;
*pxTopOfStack = 0x66666666; /* Accumulator 1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_FPSW;
pxTopOfStack--;
*pxTopOfStack = 0x11111111; /* Accumulator 0. */
pxTopOfStack--;
*pxTopOfStack = 0x22222222; /* Accumulator 0. */
pxTopOfStack--;
*pxTopOfStack = 0x33333333; /* Accumulator 0. */
pxTopOfStack--;
*pxTopOfStack = 0x44444444; /* Accumulator 1. */
pxTopOfStack--;
*pxTopOfStack = 0x55555555; /* Accumulator 1. */
pxTopOfStack--;
*pxTopOfStack = 0x66666666; /* Accumulator 1. */
return pxTopOfStack;
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
extern void vApplicationSetupTimerInterrupt( void );
extern void vApplicationSetupTimerInterrupt( void );
/* Use pxCurrentTCB just so it does not get optimised away. */
if( pxCurrentTCB != NULL )
{
/* Call an application function to set up the timer that will generate the
* tick interrupt. This way the application can decide which peripheral to
* use. A demo application is provided to show a suitable example. */
vApplicationSetupTimerInterrupt();
/* Use pxCurrentTCB just so it does not get optimised away. */
if( pxCurrentTCB != NULL )
{
/* Call an application function to set up the timer that will generate the
tick interrupt. This way the application can decide which peripheral to
use. A demo application is provided to show a suitable example. */
vApplicationSetupTimerInterrupt();
/* Enable the software interrupt. */
_IEN( _ICU_SWINT ) = 1;
/* Enable the software interrupt. */
_IEN( _ICU_SWINT ) = 1;
/* Ensure the software interrupt is clear. */
_IR( _ICU_SWINT ) = 0;
/* Ensure the software interrupt is clear. */
_IR( _ICU_SWINT ) = 0;
/* Ensure the software interrupt is set to the kernel priority. */
_IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;
/* Ensure the software interrupt is set to the kernel priority. */
_IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;
/* Start the first task. */
prvStartFirstTask();
}
/* Start the first task. */
prvStartFirstTask();
}
/* Should not get here. */
return pdFAIL;
/* Should not get here. */
return pdFAIL;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */
configASSERT( pxCurrentTCB == NULL );
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT( pxCurrentTCB == NULL );
}
/*-----------------------------------------------------------*/
static void prvStartFirstTask( void )
{
__asm volatile
(
__asm volatile
(
/* When starting the scheduler there is nothing that needs moving to the
interrupt stack because the function is not called from an interrupt.
Just ensure the current stack is the user stack. */
"SETPSW U \n" \
/* When starting the scheduler there is nothing that needs moving to the
* interrupt stack because the function is not called from an interrupt.
* Just ensure the current stack is the user stack. */
"SETPSW U \n"\
/* Obtain the location of the stack associated with which ever task
pxCurrentTCB is currently pointing to. */
"MOV.L #_pxCurrentTCB, R15 \n" \
"MOV.L [R15], R15 \n" \
"MOV.L [R15], R0 \n" \
/* Restore the registers from the stack of the task pointed to by
pxCurrentTCB. */
"POP R15 \n" \
/* Obtain the location of the stack associated with which ever task
* pxCurrentTCB is currently pointing to. */
"MOV.L #_pxCurrentTCB, R15 \n"\
"MOV.L [R15], R15 \n"\
"MOV.L [R15], R0 \n"\
/* Accumulator low 32 bits. */
"MVTACLO R15, A0 \n" \
"POP R15 \n" \
/* Accumulator high 32 bits. */
"MVTACHI R15, A0 \n" \
"POP R15 \n" \
/* Restore the registers from the stack of the task pointed to by
* pxCurrentTCB. */
"POP R15 \n"\
/* Accumulator guard. */
"MVTACGU R15, A0 \n" \
"POP R15 \n" \
/* Accumulator low 32 bits. */
"MVTACLO R15, A0 \n"\
"POP R15 \n"\
/* Accumulator low 32 bits. */
"MVTACLO R15, A1 \n" \
"POP R15 \n" \
/* Accumulator high 32 bits. */
"MVTACHI R15, A0 \n"\
"POP R15 \n"\
/* Accumulator high 32 bits. */
"MVTACHI R15, A1 \n" \
"POP R15 \n" \
/* Accumulator guard. */
"MVTACGU R15, A0 \n"\
"POP R15 \n"\
/* Accumulator guard. */
"MVTACGU R15, A1 \n" \
"POP R15 \n" \
/* Accumulator low 32 bits. */
"MVTACLO R15, A1 \n"\
"POP R15 \n"\
/* Floating point status word. */
"MVTC R15, FPSW \n" \
/* Accumulator high 32 bits. */
"MVTACHI R15, A1 \n"\
"POP R15 \n"\
/* R1 to R15 - R0 is not included as it is the SP. */
"POPM R1-R15 \n" \
/* Accumulator guard. */
"MVTACGU R15, A1 \n"\
"POP R15 \n"\
/* Floating point status word. */
"MVTC R15, FPSW \n"\
/* R1 to R15 - R0 is not included as it is the SP. */
"POPM R1-R15 \n"\
/* This pops the remaining registers. */
"RTE \n"\
"NOP \n"\
"NOP \n"
);
/* This pops the remaining registers. */
"RTE \n" \
"NOP \n" \
"NOP \n"
);
}
/*-----------------------------------------------------------*/
void vSoftwareInterruptISR( void )
{
__asm volatile
(
/* Re-enable interrupts. */
"SETPSW I \n"\
__asm volatile
(
/* Re-enable interrupts. */
"SETPSW I \n" \
/* Move the data that was automatically pushed onto the interrupt stack when
the interrupt occurred from the interrupt stack to the user stack.
/* Move the data that was automatically pushed onto the interrupt stack when
* the interrupt occurred from the interrupt stack to the user stack.
*
* R15 is saved before it is clobbered. */
"PUSH.L R15 \n"\
R15 is saved before it is clobbered. */
"PUSH.L R15 \n" \
/* Read the user stack pointer. */
"MVFC USP, R15 \n"\
/* Read the user stack pointer. */
"MVFC USP, R15 \n" \
/* Move the address down to the data being moved. */
"SUB #12, R15 \n"\
"MVTC R15, USP \n"\
/* Move the address down to the data being moved. */
"SUB #12, R15 \n" \
"MVTC R15, USP \n" \
/* Copy the data across, R15, then PC, then PSW. */
"MOV.L [ R0 ], [ R15 ] \n"\
"MOV.L 4[ R0 ], 4[ R15 ] \n"\
"MOV.L 8[ R0 ], 8[ R15 ] \n"\
/* Copy the data across, R15, then PC, then PSW. */
"MOV.L [ R0 ], [ R15 ] \n" \
"MOV.L 4[ R0 ], 4[ R15 ] \n" \
"MOV.L 8[ R0 ], 8[ R15 ] \n" \
/* Move the interrupt stack pointer to its new correct position. */
"ADD #12, R0 \n"\
/* Move the interrupt stack pointer to its new correct position. */
"ADD #12, R0 \n" \
/* All the rest of the registers are saved directly to the user stack. */
"SETPSW U \n"\
/* All the rest of the registers are saved directly to the user stack. */
"SETPSW U \n" \
/* Save the rest of the general registers (R15 has been saved already). */
"PUSHM R1-R14 \n"\
/* Save the rest of the general registers (R15 has been saved already). */
"PUSHM R1-R14 \n" \
/* Save the FPSW and accumulator. */
"MVFC FPSW, R15 \n"\
"PUSH.L R15 \n"\
"MVFACGU #0, A1, R15 \n"\
"PUSH.L R15 \n"\
"MVFACHI #0, A1, R15 \n"\
"PUSH.L R15 \n"\
/* Low order word. */
"MVFACLO #0, A1, R15 \n"\
"PUSH.L R15 \n"\
"MVFACGU #0, A0, R15 \n"\
"PUSH.L R15 \n"\
"MVFACHI #0, A0, R15 \n"\
"PUSH.L R15 \n"\
/* Low order word. */
"MVFACLO #0, A0, R15 \n"\
"PUSH.L R15 \n"\
/* Save the FPSW and accumulator. */
"MVFC FPSW, R15 \n" \
"PUSH.L R15 \n" \
"MVFACGU #0, A1, R15 \n" \
"PUSH.L R15 \n" \
"MVFACHI #0, A1, R15 \n" \
"PUSH.L R15 \n" \
/* Low order word. */
"MVFACLO #0, A1, R15 \n" \
"PUSH.L R15 \n" \
"MVFACGU #0, A0, R15 \n" \
"PUSH.L R15 \n" \
"MVFACHI #0, A0, R15 \n" \
"PUSH.L R15 \n" \
/* Low order word. */
"MVFACLO #0, A0, R15 \n" \
"PUSH.L R15 \n" \
/* Save the stack pointer to the TCB. */
"MOV.L #_pxCurrentTCB, R15 \n"\
"MOV.L [ R15 ], R15 \n"\
"MOV.L R0, [ R15 ] \n"\
/* Save the stack pointer to the TCB. */
"MOV.L #_pxCurrentTCB, R15 \n" \
"MOV.L [ R15 ], R15 \n" \
"MOV.L R0, [ R15 ] \n" \
/* Ensure the interrupt mask is set to the syscall priority while the kernel
structures are being accessed. */
"MVTIPL %0 \n" \
/* Ensure the interrupt mask is set to the syscall priority while the kernel
* structures are being accessed. */
"MVTIPL %0 \n"\
/* Select the next task to run. */
"BSR.A _vTaskSwitchContext \n" \
/* Select the next task to run. */
"BSR.A _vTaskSwitchContext \n"\
/* Reset the interrupt mask as no more data structure access is required. */
"MVTIPL %1 \n" \
/* Reset the interrupt mask as no more data structure access is required. */
"MVTIPL %1 \n"\
/* Load the stack pointer of the task that is now selected as the Running
state task from its TCB. */
"MOV.L #_pxCurrentTCB,R15 \n" \
"MOV.L [ R15 ], R15 \n" \
"MOV.L [ R15 ], R0 \n" \
/* Restore the context of the new task. The PSW (Program Status Word) and
PC will be popped by the RTE instruction. */
"POP R15 \n" \
/* Load the stack pointer of the task that is now selected as the Running
* state task from its TCB. */
"MOV.L #_pxCurrentTCB,R15 \n"\
"MOV.L [ R15 ], R15 \n"\
"MOV.L [ R15 ], R0 \n"\
/* Accumulator low 32 bits. */
"MVTACLO R15, A0 \n" \
"POP R15 \n" \
/* Accumulator high 32 bits. */
"MVTACHI R15, A0 \n" \
"POP R15 \n" \
/* Restore the context of the new task. The PSW (Program Status Word) and
* PC will be popped by the RTE instruction. */
"POP R15 \n"\
/* Accumulator guard. */
"MVTACGU R15, A0 \n" \
"POP R15 \n" \
/* Accumulator low 32 bits. */
"MVTACLO R15, A0 \n"\
"POP R15 \n"\
/* Accumulator low 32 bits. */
"MVTACLO R15, A1 \n" \
"POP R15 \n" \
/* Accumulator high 32 bits. */
"MVTACHI R15, A0 \n"\
"POP R15 \n"\
/* Accumulator high 32 bits. */
"MVTACHI R15, A1 \n" \
"POP R15 \n" \
/* Accumulator guard. */
"MVTACGU R15, A0 \n"\
"POP R15 \n"\
/* Accumulator low 32 bits. */
"MVTACLO R15, A1 \n"\
"POP R15 \n"\
/* Accumulator high 32 bits. */
"MVTACHI R15, A1 \n"\
"POP R15 \n"\
/* Accumulator guard. */
"MVTACGU R15, A1 \n"\
"POP R15 \n"\
"MVTC R15, FPSW \n"\
"POPM R1-R15 \n"\
"RTE \n"\
"NOP \n"\
"NOP "
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ), "i" ( configKERNEL_INTERRUPT_PRIORITY )
);
/* Accumulator guard. */
"MVTACGU R15, A1 \n" \
"POP R15 \n" \
"MVTC R15, FPSW \n" \
"POPM R1-R15 \n" \
"RTE \n" \
"NOP \n" \
"NOP "
:: "i"(configMAX_SYSCALL_INTERRUPT_PRIORITY), "i"(configKERNEL_INTERRUPT_PRIORITY)
);
}
/*-----------------------------------------------------------*/
void vTickISR( void )
{
/* Re-enabled interrupts. */
__asm volatile ( "SETPSW I");
/* Re-enabled interrupts. */
__asm volatile( "SETPSW I" );
/* Increment the tick, and perform any processing the new tick value
* necessitates. Ensure IPL is at the max syscall value first. */
portMASK_INTERRUPTS_FROM_KERNEL_ISR();
{
if( xTaskIncrementTick() != pdFALSE )
{
taskYIELD();
}
}
portUNMASK_INTERRUPTS_FROM_KERNEL_ISR();
/* Increment the tick, and perform any processing the new tick value
necessitates. Ensure IPL is at the max syscall value first. */
portMASK_INTERRUPTS_FROM_KERNEL_ISR();
{
if( xTaskIncrementTick() != pdFALSE )
{
taskYIELD();
}
}
portUNMASK_INTERRUPTS_FROM_KERNEL_ISR();
}
/*-----------------------------------------------------------*/
uint32_t ulPortGetIPL( void )
{
__asm volatile
(
"MVFC PSW, R1 \n"\
"SHLR #24, R1 \n"\
"RTS "
);
__asm volatile
(
"MVFC PSW, R1 \n" \
"SHLR #24, R1 \n" \
"RTS "
);
/* This will never get executed, but keeps the compiler from complaining. */
return 0;
/* This will never get executed, but keeps the compiler from complaining. */
return 0;
}
/*-----------------------------------------------------------*/
void vPortSetIPL( uint32_t ulNewIPL )
{
__asm volatile
(
"PUSH R5 \n"\
"MVFC PSW, R5 \n"\
"SHLL #24, R1 \n"\
"AND #-0F000001H, R5 \n"\
"OR R1, R5 \n"\
"MVTC R5, PSW \n"\
"POP R5 \n"\
"RTS "
);
__asm volatile
(
"PUSH R5 \n" \
"MVFC PSW, R5 \n" \
"SHLL #24, R1 \n" \
"AND #-0F000001H, R5 \n" \
"OR R1, R5 \n" \
"MVTC R5, PSW \n" \
"POP R5 \n" \
"RTS "
);
}

Some files were not shown because too many files have changed in this diff Show more