Carry on working on the Cortex-A/GCC port layer - still a work in progress.

pull/1/head
Richard Barry 11 years ago
parent 33351b02c9
commit 3e430b3801

@ -110,6 +110,10 @@
#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 #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 /* A critical section is exited when the critical section nesting count reaches
this value. */ this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
@ -126,7 +130,8 @@ context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* 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 portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINTERRUPT_ENABLE_BIT ( 0x80UL ) #define portINTERRUPT_ENABLE_BIT ( 0x80UL )
#define portTHUMB_MODE_ADDRESS ( 0x01UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL )
@ -146,12 +151,20 @@ mode. */
#define portCLEAR_INTERRUPT_MASK() \ #define portCLEAR_INTERRUPT_MASK() \
{ \ { \
__asm volatile ( "cpsid i" ); \ __asm volatile ( "cpsid i" ); \
__asm volatile ( "dsb" ); \
__asm volatile ( "isb" ); \
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
__asm( "DSB \n" \ __asm( "DSB \n" \
"ISB \n" ); \ "ISB \n" ); \
__asm volatile( "cpsie i" ); \ __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 ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
__attribute__(( used )) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_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; 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 /* Only continue if the CPU is not in User mode. The CPU must be in a
Privileged mode for the scheduler to start. */ Privileged mode for the scheduler to start. */
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) ); __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE ); configASSERT( ulAPSR != portAPSR_USER_MODE );
#if configINSTALL_FREERTOS_VECTOR_TABLE == 1
{
vPortInstallFreeRTOSVectorTable();
}
#endif
if( ulAPSR != portAPSR_USER_MODE ) if( ulAPSR != portAPSR_USER_MODE )
{ {
/* Only continue if the binary point value is set to its lowest possible /* 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. */ /* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT(); configSETUP_TICK_INTERRUPT();
__asm volatile( "cpsie i" ); // __asm volatile( "cpsie i" );
vPortRestoreTaskContext(); vPortRestoreTaskContext();
} }
} }
@ -340,10 +397,14 @@ void FreeRTOS_Tick_Handler( void )
handler runs at the lowest priority, so interrupts cannot already be masked, 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. */ so there is no need to save and restore the current mask value. */
__asm volatile( "cpsid i" ); __asm volatile( "cpsid i" );
__asm volatile ( "dsb" );
__asm volatile ( "isb" );
portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm( "dsb \n" __asm( "dsb \n"
"isb \n" "isb \n"
"cpsie i "); "cpsie i \n"
"dsb \n"
"isb" );
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
@ -383,6 +444,8 @@ uint32_t ulPortSetInterruptMask( void )
uint32_t ulReturn; uint32_t ulReturn;
__asm volatile ( "cpsid i" ); __asm volatile ( "cpsid i" );
__asm volatile ( "dsb" );
__asm volatile ( "isb" );
if( portICCPMR_PRIORITY_MASK_REGISTER == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) if( portICCPMR_PRIORITY_MASK_REGISTER == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{ {
/* Interrupts were already masked. */ /* Interrupts were already masked. */
@ -396,6 +459,8 @@ uint32_t ulReturn;
"isb \n" ); "isb \n" );
} }
__asm volatile ( "cpsie i" ); __asm volatile ( "cpsie i" );
__asm volatile ( "dsb" );
__asm volatile ( "isb" );
return ulReturn; return ulReturn;
} }
@ -441,13 +506,3 @@ uint32_t ulReturn;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortRestoreTaskContext( void )
{
}
void vPortRestoreContext( void )
{
}
/*-----------------------------------------------------------*/

@ -53,40 +53,124 @@
*/ */
.org 0
.text .text
.set SYS_MODE, 0x1f .set SYS_MODE, 0x1f
.set SVC_MODE, 0x13 .set SVC_MODE, 0x13
.set IRQ_MODE, 0x12 .set IRQ_MODE, 0x12
.extern _boot
.extern vTaskSwitchContext
.extern ulICCIAR .extern ulICCIAR
.extern ulICCEOIR .extern ulICCEOIR
.extern ulMaxAPIPriorityMask
.extern ulICCPMR
.extern _freertos_vector_table
.global _vector_table .global FreeRTOS_vector_table
.global FIQInterrupt .global FIQInterrupt
.global Undefined .global Undefined
.global PrefetchAbortHandler .global PrefetchAbortHandler
.global DataAbortInterrupt .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_IRQ_Handler
.global FreeRTOS_SWI_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. * SVC handler is used to start the scheduler and yield a task.
@ -94,12 +178,42 @@ _swi: .word FreeRTOS_SWI_Handler
FreeRTOS_SWI_Handler: FreeRTOS_SWI_Handler:
/* Save the context of the current task and select a new task to run. */ /* 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 LDR R0, =vTaskSwitchContext
BLX R0 BLX R0
vPortRestoreTaskContext: vPortRestoreTaskContext:
// portRESTORE_CONTEXT portRESTORE_CONTEXT
FreeRTOS_IRQ_Handler: FreeRTOS_IRQ_Handler:
/* Return to the interrupted instruction. */ /* Return to the interrupted instruction. */
@ -185,7 +299,7 @@ switch_before_exit:
POP {LR} POP {LR}
MSR SPSR_cxsf, LR MSR SPSR_cxsf, LR
POP {LR} POP {LR}
// portSAVE_CONTEXT portSAVE_CONTEXT
/* Call the function that selects the new task to execute. /* Call the function that selects the new task to execute.
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD 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 /* Restore the context of, and branch to, the task selected to execute
next. */ next. */
// portRESTORE_CONTEXT portRESTORE_CONTEXT
ulICCIARConst: .word ulICCIAR ulICCIARConst: .word ulICCIAR
ulICCEOIRConst: .word ulICCEOIR 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 .end

@ -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
Loading…
Cancel
Save