From df8b68880e95da96c7defaa9337be1d8473463ad Mon Sep 17 00:00:00 2001 From: richardbarry Date: Fri, 28 Nov 2008 15:41:07 +0000 Subject: [PATCH] New demo being added - work in progress. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@587 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/portable/IAR/AtmelSAM9XE/ISR_Support.h | 78 +++++ Source/portable/IAR/AtmelSAM9XE/port.c | 280 ++++++++++++++++++ Source/portable/IAR/AtmelSAM9XE/portasm.s79 | 58 ++++ Source/portable/IAR/AtmelSAM9XE/portmacro.h | 131 ++++++++ 4 files changed, 547 insertions(+) create mode 100644 Source/portable/IAR/AtmelSAM9XE/ISR_Support.h create mode 100644 Source/portable/IAR/AtmelSAM9XE/port.c create mode 100644 Source/portable/IAR/AtmelSAM9XE/portasm.s79 create mode 100644 Source/portable/IAR/AtmelSAM9XE/portmacro.h diff --git a/Source/portable/IAR/AtmelSAM9XE/ISR_Support.h b/Source/portable/IAR/AtmelSAM9XE/ISR_Support.h new file mode 100644 index 000000000..4a32f3976 --- /dev/null +++ b/Source/portable/IAR/AtmelSAM9XE/ISR_Support.h @@ -0,0 +1,78 @@ + EXTERN pxCurrentTCB + EXTERN ulCriticalNesting + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Context save and restore macro definitions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +portSAVE_CONTEXT MACRO + + ; Push R0 as we are going to use the register. + STMDB SP!, {R0} + + ; Set R0 to point to the task stack pointer. + STMDB SP, {SP}^ + NOP + SUB SP, SP, #4 + LDMIA SP!, {R0} + + ; Push the return address onto the stack. + STMDB R0!, {LR} + + ; Now we have saved LR we can use it instead of R0. + MOV LR, R0 + + ; Pop R0 so we can save it onto the system mode stack. + LDMIA SP!, {R0} + + ; Push all the system mode registers onto the task stack. + STMDB LR, {R0-LR}^ + NOP + SUB LR, LR, #60 + + ; Push the SPSR onto the task stack. + MRS R0, SPSR + STMDB LR!, {R0} + + LDR R0, =ulCriticalNesting + LDR R0, [R0] + STMDB LR!, {R0} + + ; Store the new top of stack for the task. + LDR R1, =pxCurrentTCB + LDR R0, [R1] + STR LR, [R0] + + ENDM + + +portRESTORE_CONTEXT MACRO + + ; Set the LR to the task stack. + LDR R1, =pxCurrentTCB + LDR R0, [R1] + LDR LR, [R0] + + ; The critical nesting depth is the first item on the stack. + ; Load it into the ulCriticalNesting variable. + LDR R0, =ulCriticalNesting + LDMFD LR!, {R1} + STR R1, [R0] + + ; Get the SPSR from the stack. + LDMFD LR!, {R0} + MSR SPSR_cxsf, R0 + + ; Restore all system mode registers for the task. + LDMFD LR, {R0-R14}^ + NOP + + ; Restore the return address. + LDR LR, [LR, #+60] + + ; And return - correcting the offset in the LR to obtain the + ; correct address. + SUBS PC, LR, #4 + + ENDM + diff --git a/Source/portable/IAR/AtmelSAM9XE/port.c b/Source/portable/IAR/AtmelSAM9XE/port.c new file mode 100644 index 000000000..0004c97b5 --- /dev/null +++ b/Source/portable/IAR/AtmelSAM9XE/port.c @@ -0,0 +1,280 @@ +/* + FreeRTOS.org V5.1.1 - Copyright (C) 2003-2008 Richard Barry. + + This file is part of the FreeRTOS.org distribution. + + FreeRTOS.org 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.org 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.org; 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.org, 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. + + *************************************************************************** + *************************************************************************** + * * + * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, * + * and even write all or part of your application on your behalf. * + * See http://www.OpenRTOS.com for details of the services we provide to * + * expedite your project. * + * * + *************************************************************************** + *************************************************************************** + + 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. +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the Atmel ARM7 port. + *----------------------------------------------------------*/ + + +/* Standard includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Hardware includes. */ +#include +#include +#include +#include +#include +#include +#include +#include + +/*-----------------------------------------------------------*/ + +/* Constants required to setup the initial stack. */ +#define portINITIAL_SPSR ( ( portSTACK_TYPE ) 0x3f ) /* System mode, THUMB mode, interrupts enabled. */ +#define portINSTRUCTION_SIZE ( ( portSTACK_TYPE ) 4 ) + +/* Constants required to setup the PIT. */ +#define port1MHz_IN_Hz ( 1000000ul ) +#define port1SECOND_IN_uS ( 1000000ul ) + +/* Constants required to handle critical sections. */ +#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 ) + + +#define portINT_LEVEL_SENSITIVE 0 +#define portPIT_ENABLE ( ( unsigned portSHORT ) 0x1 << 24 ) +#define portPIT_INT_ENABLE ( ( unsigned portSHORT ) 0x1 << 25 ) +/*-----------------------------------------------------------*/ + +/* Setup the PIT to generate the tick interrupts. */ +static void prvSetupTimerInterrupt( void ); + +/* ulCriticalNesting will get set to zero when the first task starts. It +cannot be initialised to 0 as this will cause interrupts to be enabled +during the kernel initialisation process. */ +unsigned portLONG ulCriticalNesting = ( unsigned portLONG ) 9999; + +/*-----------------------------------------------------------*/ + +/* + * Initialise the stack of a task to look exactly as if a call to + * portSAVE_CONTEXT had been called. + * + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ +portSTACK_TYPE *pxOriginalTOS; + + pxOriginalTOS = pxTopOfStack; + + /* 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 = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE; + pxTopOfStack--; + + *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaaaaaa; /* R14 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x12121212; /* R12 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111; /* R11 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x10101010; /* R10 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x09090909; /* R9 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x08080808; /* R8 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x07070707; /* R7 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x06060606; /* R6 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x05050505; /* R5 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x04040404; /* R4 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x03030303; /* R3 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x02020202; /* R2 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x01010101; /* R1 */ + pxTopOfStack--; + + /* When the task starts is will expect to find the function parameter in + R0. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack--; + + /* The status register is set for system mode, with interrupts enabled. */ + *pxTopOfStack = ( portSTACK_TYPE ) portINITIAL_SPSR; + pxTopOfStack--; + + /* 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_NESTING; + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xPortStartScheduler( void ) +{ +extern void vPortStartFirstTask( void ); + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); + + /* Start the first task. */ + vPortStartFirstTask(); + + /* 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. */ +} +/*-----------------------------------------------------------*/ + +#if configUSE_PREEMPTION == 0 + + /* The cooperative scheduler requires a normal IRQ service routine to + simply increment the system tick. */ + static __arm __irq void vPortNonPreemptiveTick( void ); + static __arm __irq void vPortNonPreemptiveTick( void ) + { + unsigned portLONG 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. */ + vTaskIncrementTick(); + + /* Clear the PIT interrupt. */ + ulDummy = AT91C_BASE_PITC->PITC_PIVR; + + /* End the interrupt in the AIC. */ + AT91C_BASE_AIC->AIC_EOICR = ulDummy; + } + +#else + + /* Currently the IAR port requires the preemptive tick function to be + defined in an asm file. */ + +#endif + +/*-----------------------------------------------------------*/ + +static void prvSetupTimerInterrupt( void ) +{ +const unsigned portLONG ulPeriodIn_uS = ( 1 / configTICK_RATE_HZ ) * port1SECOND_IN_uS; + + /* Setup the PIT for the required frequency. */ + PIT_Init( ulPeriodIn_uS, BOARD_MCK / port1MHz_IN_Hz ); + + /* Setup the PIT interrupt. */ + AIC_DisableIT( AT91C_ID_SYS ); + + #if configUSE_PREEMPTION == 0 + AIC_ConfigureIT( AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, vPortNonPreemptiveTick ); + #else + extern void ( vPortPreemptiveTick )( void ); + AIC_ConfigureIT( AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, vPortPreemptiveTick ); + #endif + + AIC_EnableIT( AT91C_ID_SYS ); + PIT_EnableIT(); + + /* Enable the PIT itself. */ + PIT_Enable(); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + /* Disable interrupts first! */ + __disable_irq(); + + /* 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 the nesting level has reached zero then interrupts should be + re-enabled. */ + if( ulCriticalNesting == portNO_CRITICAL_NESTING ) + { + __enable_irq(); + } + } +} +/*-----------------------------------------------------------*/ + + + + + + diff --git a/Source/portable/IAR/AtmelSAM9XE/portasm.s79 b/Source/portable/IAR/AtmelSAM9XE/portasm.s79 new file mode 100644 index 000000000..da118fb55 --- /dev/null +++ b/Source/portable/IAR/AtmelSAM9XE/portasm.s79 @@ -0,0 +1,58 @@ + RSEG ICODE:CODE + CODE32 + + EXTERN vTaskSwitchContext + EXTERN vTaskIncrementTick + + PUBLIC vPortYieldProcessor + PUBLIC vPortPreemptiveTick + PUBLIC vPortStartFirstTask + +#include "ISR_Support.h" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Starting the first task is just a matter of restoring the context that +; was created by pxPortInitialiseStack(). +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +vPortStartFirstTask: + portRESTORE_CONTEXT + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Manual context switch function. This is the SWI hander. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +vPortYieldProcessor: + ADD LR, LR, #4 ; Add 4 to the LR to make the LR appear exactly + ; as if the context was saved during and IRQ + ; handler. + + portSAVE_CONTEXT ; Save the context of the current task... + LDR R0, =vTaskSwitchContext ; before selecting the next task to execute. + mov lr, pc + BX R0 + portRESTORE_CONTEXT ; Restore the context of the selected task. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Preemptive context switch function. This will only ever get installed if +; portUSE_PREEMPTION is set to 1 in portmacro.h. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +vPortPreemptiveTick: + portSAVE_CONTEXT ; Save the context of the current task. + + LDR R0, =vTaskIncrementTick ; Increment the tick count - this may wake a task. + mov lr, pc + BX R0 + LDR R0, =vTaskSwitchContext ; Select the next task to execute. + mov lr, pc + BX R0 +#if 0 + LDR R14, =AT91C_BASE_PITC ; Clear the PIT interrupt + LDR R0, [R14, #PITC_PIVR ] + + LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC + STR R14, [R14, #AIC_EOICR] +#endif + portRESTORE_CONTEXT ; Restore the context of the selected task. + + + END + diff --git a/Source/portable/IAR/AtmelSAM9XE/portmacro.h b/Source/portable/IAR/AtmelSAM9XE/portmacro.h new file mode 100644 index 000000000..089ad8e6a --- /dev/null +++ b/Source/portable/IAR/AtmelSAM9XE/portmacro.h @@ -0,0 +1,131 @@ +/* + FreeRTOS.org V5.1.1 - Copyright (C) 2003-2008 Richard Barry. + + This file is part of the FreeRTOS.org distribution. + + FreeRTOS.org 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.org 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.org; 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.org, 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. + + *************************************************************************** + *************************************************************************** + * * + * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, * + * and even write all or part of your application on your behalf. * + * See http://www.OpenRTOS.com for details of the services we provide to * + * expedite your project. * + * * + *************************************************************************** + *************************************************************************** + + 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 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE unsigned portLONG +#define portBASE_TYPE portLONG + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef unsigned portSHORT portTickType; + #define portMAX_DELAY ( portTickType ) 0xffff +#else + typedef unsigned portLONG portTickType; + #define portMAX_DELAY ( portTickType ) 0xffffffff +#endif +/*-----------------------------------------------------------*/ + +/* Hardware specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portYIELD() asm ( "SWI 0" ) +#define portNOP() asm ( "NOP" ) +/*-----------------------------------------------------------*/ + +/* Critical section handling. */ +__arm __interwork void vPortDisableInterruptsFromThumb( void ); +__arm __interwork void vPortEnableInterruptsFromThumb( void ); +__arm __interwork void vPortEnterCritical( void ); +__arm __interwork void vPortExitCritical( void ); + +#define portDISABLE_INTERRUPTS() __disable_irq() +#define portENABLE_INTERRUPTS() __enable_irq() +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +/*-----------------------------------------------------------*/ + +/* Task utilities. */ +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ +{ \ +extern void vTaskSwitchContext( void ); \ + \ + if( xSwitchRequired ) \ + { \ + vTaskSwitchContext(); \ + } \ +} +/*-----------------------------------------------------------*/ + + +/* 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 ) + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + + -- 2.39.2