From 53f70762de0aaa9132dfba554a3ff2102583cd96 Mon Sep 17 00:00:00 2001 From: rtel Date: Wed, 22 Jan 2014 15:39:58 +0000 Subject: [PATCH] Carry on working on the Cortex-A/GCC port layer - still a work in progress. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2171 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- FreeRTOS/Source/portable/GCC/ARM_CA9/port.c | 81 +++++++-- .../Source/portable/GCC/ARM_CA9/portASM.S | 172 ++++++++++++++---- .../Source/portable/GCC/ARM_CA9/portASM.h | 145 --------------- 3 files changed, 209 insertions(+), 189 deletions(-) delete mode 100644 FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.h diff --git a/FreeRTOS/Source/portable/GCC/ARM_CA9/port.c b/FreeRTOS/Source/portable/GCC/ARM_CA9/port.c index 5a354b335..84a6d1db9 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CA9/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CA9/port.c @@ -110,6 +110,10 @@ #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #endif +#ifndef configINSTALL_FREERTOS_VECTOR_TABLE + #warning configINSTALL_FREERTOS_VECTOR_TABLE was undefined. Defaulting configINSTALL_FREERTOS_VECTOR_TABLE to 0. +#endif + /* A critical section is exited when the critical section nesting count reaches this value. */ #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) @@ -126,7 +130,8 @@ 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, interrupts enabled. */ +#warning FIQ is disabled +#define portINITIAL_SPSR ( ( StackType_t ) 0x5f ) /* System mode, ARM mode, IRQ enabled FIQ disabled. 1f is required to enable FIQ. */ #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portINTERRUPT_ENABLE_BIT ( 0x80UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL ) @@ -146,12 +151,20 @@ mode. */ #define portCLEAR_INTERRUPT_MASK() \ { \ __asm volatile ( "cpsid i" ); \ + __asm volatile ( "dsb" ); \ + __asm volatile ( "isb" ); \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ __asm( "DSB \n" \ "ISB \n" ); \ __asm volatile( "cpsie i" ); \ + __asm volatile ( "dsb" ); \ + __asm volatile ( "isb" ); \ } +#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portBIT_0_SET ( ( uint8_t ) 0x01 ) + /*-----------------------------------------------------------*/ /* @@ -182,6 +195,8 @@ uint32_t ulPortInterruptNesting = 0UL; __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 ); /*-----------------------------------------------------------*/ @@ -264,12 +279,54 @@ BaseType_t xPortStartScheduler( void ) { 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; + + /* Determine how many priority bits are implemented in the GIC. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to + all possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Shift to the least significant bits. */ + while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET ) + { + ucMaxPriorityValue >>= ( uint8_t ) 0x01; + } + + /* 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 ) ); ulAPSR &= portAPSR_MODE_BITS_MASK; configASSERT( ulAPSR != portAPSR_USER_MODE ); + #if configINSTALL_FREERTOS_VECTOR_TABLE == 1 + { + vPortInstallFreeRTOSVectorTable(); + } + #endif + + if( ulAPSR != portAPSR_USER_MODE ) { /* Only continue if the binary point value is set to its lowest possible @@ -282,7 +339,7 @@ uint32_t ulAPSR; /* Start the timer that generates the tick ISR. */ configSETUP_TICK_INTERRUPT(); - __asm volatile( "cpsie i" ); +// __asm volatile( "cpsie i" ); vPortRestoreTaskContext(); } } @@ -340,10 +397,14 @@ void FreeRTOS_Tick_Handler( void ) 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. */ __asm volatile( "cpsid i" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); __asm( "dsb \n" "isb \n" - "cpsie i "); + "cpsie i \n" + "dsb \n" + "isb" ); /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) @@ -383,6 +444,8 @@ uint32_t ulPortSetInterruptMask( void ) uint32_t ulReturn; __asm volatile ( "cpsid i" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); if( portICCPMR_PRIORITY_MASK_REGISTER == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) { /* Interrupts were already masked. */ @@ -396,6 +459,8 @@ uint32_t ulReturn; "isb \n" ); } __asm volatile ( "cpsie i" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); return ulReturn; } @@ -441,13 +506,3 @@ uint32_t ulReturn; #endif /* configASSERT_DEFINED */ /*-----------------------------------------------------------*/ -void vPortRestoreTaskContext( void ) -{ -} - -void vPortRestoreContext( void ) -{ -} -/*-----------------------------------------------------------*/ - - diff --git a/FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.S b/FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.S index f0ecbf97d..072e45e54 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.S +++ b/FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.S @@ -53,40 +53,124 @@ */ - .org 0 .text .set SYS_MODE, 0x1f .set SVC_MODE, 0x13 .set IRQ_MODE, 0x12 - .extern _boot - .extern vTaskSwitchContext .extern ulICCIAR .extern ulICCEOIR + .extern ulMaxAPIPriorityMask + .extern ulICCPMR + .extern _freertos_vector_table - .global _vector_table + .global FreeRTOS_vector_table .global FIQInterrupt .global Undefined .global PrefetchAbortHandler .global DataAbortInterrupt + + .extern pxCurrentTCB + .extern XIntc_DeviceInterruptHandler + .extern vTaskSwitchContext + .extern uxCriticalNesting + .extern pulISRStack + .extern ulTaskSwitchRequested + .extern vPortExceptionHandler + .extern pulStackPointerOnFunctionEntry + .global FreeRTOS_IRQ_Handler .global FreeRTOS_SWI_Handler + .global vPortRestoreTaskContext + .global vPortInstallFreeRTOSVectorTable + + + + +.macro portSAVE_CONTEXT + + /* Save the LR and SPSR onto the system mode stack before switching to + system mode to save the remaining system mode registers. */ + SRSDB sp!, #SYS_MODE + CPS #SYS_MODE + PUSH {R0-R12, R14} + + /* Push the critical nesting count. */ + LDR R2, =ulCriticalNesting + LDR R1, [R2] + PUSH {R1} + + /* Does the task have a floating point context that needs saving? If + ulPortTaskHasFPUContext is 0 then no. */ + LDR R2, =ulPortTaskHasFPUContext + LDR R3, [R2] + CMP R3, #0 + + /* Save the floating point context, if any. */ + FMRXNE R1, FPSCR + VPUSHNE {D0-D15} + VPUSHNE {D16-D31} + PUSHNE {R1} + + /* Save ulPortTaskHasFPUContext itself. */ + PUSH {R3} + + /* Save the stack pointer in the TCB. */ + LDR R0, =pxCurrentTCB + LDR R1, [R0] + STR SP, [R1] + + .endm + +; /**********************************************************************/ + +.macro portRESTORE_CONTEXT + + /* Switch to system mode. */ + CPS #SYS_MODE + + /* Set the SP to point to the stack of the task being restored. */ + LDR R0, =pxCurrentTCB + LDR R1, [R0] + LDR SP, [R1] + + /* Is there a floating point context to restore? If the restored + ulPortTaskHasFPUContext is zero then no. */ + LDR R0, =ulPortTaskHasFPUContext + POP {R1} + STR R1, [R0] + CMP R1, #0 + + /* Restore the floating point context, if any. */ + POPNE {R0} + VPOPNE {D16-D31} + VPOPNE {D0-D15} + VMSRNE FPSCR, R0 + + /* Restore the critical section nesting depth. */ + LDR R0, =ulCriticalNesting + POP {R1} + STR R1, [R0] + + /* Ensure the priority mask is correct for the critical nesting depth. */ + LDR R2, =ulICCPMR + CMP R1, #0 + MOVEQ R4, #255 + LDRNE R4, =ulMaxAPIPriorityMask + STR R4, [r2] + + /* Restore all system mode registers other than the SP (which is already + being used). */ + POP {R0-R12, R14} + + /* Return to the task code, loading CPSR on the way. */ + RFEIA sp! + + .endm - .section .vectors -_vector_table: - B _boot - B Undefined - ldr pc, _swi - B PrefetchAbortHandler - B DataAbortHandler - NOP /* Placeholder for address exception vector*/ - LDR PC, _irq - B FIQHandler -_irq: .word FreeRTOS_IRQ_Handler -_swi: .word FreeRTOS_SWI_Handler /****************************************************************************** * SVC handler is used to start the scheduler and yield a task. @@ -94,12 +178,42 @@ _swi: .word FreeRTOS_SWI_Handler FreeRTOS_SWI_Handler: /* Save the context of the current task and select a new task to run. */ -// portSAVE_CONTEXT + /* Save the LR and SPSR onto the system mode stack before switching to + system mode to save the remaining system mode registers. */ + SRSDB sp!, #SYS_MODE + CPS #SYS_MODE + PUSH {R0-R12, R14} + + /* Push the critical nesting count. */ + LDR R2, =ulCriticalNesting + LDR R1, [R2] + PUSH {R1} + + /* Does the task have a floating point context that needs saving? If + ulPortTaskHasFPUContext is 0 then no. */ + LDR R2, =ulPortTaskHasFPUContext + LDR R3, [R2] + CMP R3, #0 + + /* Save the floating point context, if any. */ + FMRXNE R1, FPSCR + VPUSHNE {D0-D15} + VPUSHNE {D16-D31} + PUSHNE {R1} + + /* Save ulPortTaskHasFPUContext itself. */ + PUSH {R3} + + /* Save the stack pointer in the TCB. */ + LDR R0, =pxCurrentTCB + LDR R1, [R0] + STR SP, [R1] + LDR R0, =vTaskSwitchContext BLX R0 vPortRestoreTaskContext: -// portRESTORE_CONTEXT + portRESTORE_CONTEXT FreeRTOS_IRQ_Handler: /* Return to the interrupted instruction. */ @@ -185,7 +299,7 @@ switch_before_exit: POP {LR} MSR SPSR_cxsf, LR POP {LR} -// portSAVE_CONTEXT + portSAVE_CONTEXT /* Call the function that selects the new task to execute. vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD @@ -195,23 +309,19 @@ switch_before_exit: /* Restore the context of, and branch to, the task selected to execute next. */ -// portRESTORE_CONTEXT + portRESTORE_CONTEXT ulICCIARConst: .word ulICCIAR ulICCEOIRConst: .word ulICCEOIR +vPortInstallFreeRTOSVectorTable: + /* Set VBAR to the vector table that contains the FreeRTOS handlers. */ + ldr r0, =_freertos_vector_table + mcr p15, 0, r0, c12, c0, 0 + dsb + isb + bx lr -Undefined: - B . - -PrefetchAbortHandler: - B . - -FIQHandler: - B . - -DataAbortHandler: - B . .end diff --git a/FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.h b/FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.h deleted file mode 100644 index b2d47c82c..000000000 --- a/FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.h +++ /dev/null @@ -1,145 +0,0 @@ -;/* -; FreeRTOS V8.0.0:rc1 - Copyright (C) 2014 Real Time Engineers Ltd. -; All rights reserved -; -; -; *************************************************************************** -; * * -; * FreeRTOS tutorial books are available in pdf and paperback. * -; * Complete, revised, and edited pdf reference manuals are also * -; * available. * -; * * -; * Purchasing FreeRTOS documentation will not only help you, by * -; * ensuring you get running as quickly as possible and with an * -; * in-depth knowledge of how to use FreeRTOS, it will also help * -; * the FreeRTOS project to continue with its mission of providing * -; * professional grade, cross platform, de facto standard solutions * -; * for microcontrollers - completely free of charge! * -; * * -; * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * -; * * -; * Thank you for using FreeRTOS, and thank you for your support! * -; * * -; *************************************************************************** -; -; -; This file is part of the FreeRTOS distribution. -; -; FreeRTOS is free software; you can redistribute it and/or modify it under -; the terms of the GNU General Public License (version 2) as published by the -; Free Software Foundation AND MODIFIED BY the FreeRTOS exception. -; >>>NOTE<<< The modification to the GPL is included to allow you to -; distribute a combined work that includes FreeRTOS without being obliged to -; provide the source code for proprietary components outside of the FreeRTOS -; kernel. FreeRTOS is distributed in the hope that it will be useful, but -; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -; more details. You should have received a copy of the GNU General Public -; License and the FreeRTOS license exception along with FreeRTOS; if not it -; can be viewed here: http://www.freertos.org/a00114.html and also obtained -; by writing to Richard Barry, contact details for whom are available on the -; FreeRTOS WEB site. -; -; 1 tab == 4 spaces! -; -; http://www.FreeRTOS.org - Documentation, latest information, license and -; contact details. -; -; http://www.SafeRTOS.com - A version that is certified for use in safety -; critical systems. -; -; http://www.OpenRTOS.com - Commercial support, development, porting, -; licensing and training services. -;*/ - - EXTERN vTaskSwitchContext - EXTERN ulCriticalNesting - EXTERN pxCurrentTCB - EXTERN ulPortTaskHasFPUContext - EXTERN ulAsmAPIPriorityMask - -portSAVE_CONTEXT macro - - ; Save the LR and SPSR onto the system mode stack before switching to - ; system mode to save the remaining system mode registers - SRSDB sp!, #SYS_MODE - CPS #SYS_MODE - PUSH {R0-R12, R14} - - ; Push the critical nesting count - LDR R2, =ulCriticalNesting - LDR R1, [R2] - PUSH {R1} - - ; Does the task have a floating point context that needs saving? If - ; ulPortTaskHasFPUContext is 0 then no. - LDR R2, =ulPortTaskHasFPUContext - LDR R3, [R2] - CMP R3, #0 - - ; Save the floating point context, if any - FMRXNE R1, FPSCR - VPUSHNE {D0-D15} - VPUSHNE {D16-D31} - PUSHNE {R1} - - ; Save ulPortTaskHasFPUContext itself - PUSH {R3} - - ; Save the stack pointer in the TCB - LDR R0, =pxCurrentTCB - LDR R1, [R0] - STR SP, [R1] - - endm - -; /**********************************************************************/ - -portRESTORE_CONTEXT macro - - ; Switch to system mode - CPS #SYS_MODE - - ; Set the SP to point to the stack of the task being restored. - LDR R0, =pxCurrentTCB - LDR R1, [R0] - LDR SP, [R1] - - ; Is there a floating point context to restore? If the restored - ; ulPortTaskHasFPUContext is zero then no. - LDR R0, =ulPortTaskHasFPUContext - POP {R1} - STR R1, [R0] - CMP R1, #0 - - ; Restore the floating point context, if any - LDMFDNE SP!, {R0} - VPOPNE {D16-D31} - VPOPNE {D0-D15} - VMSRNE FPSCR, R0 - - ; Restore the critical section nesting depth - LDR R0, =ulCriticalNesting - POP {R1} - STR R1, [R0] - - ; Ensure the priority mask is correct for the critical nesting depth - LDR R2, =portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS - CMP R1, #0 - MOVEQ R4, #255 - LDRNE R4, =( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) - STR R4, [r2] - - ; Restore all system mode registers other than the SP (which is already - ; being used) - POP {R0-R12, R14} - - ; Return to the task code, loading CPSR on the way. - RFEIA sp! - - endm - - - - - -- 2.39.5