mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-21 22:11:57 -04:00
Add workaround to XMC4000 silicon bug to Tasking Cortex-M4F port layer.
This commit is contained in:
parent
c1353bb12d
commit
94607d83f9
|
@ -88,6 +88,15 @@
|
||||||
#define portINITIAL_XPSR ( 0x01000000 )
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
|
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
|
||||||
|
|
||||||
|
/* Let the user override the pre-loading of the initial LR with the address of
|
||||||
|
prvTaskExitError() in case is messes up unwinding of the stack in the
|
||||||
|
debugger. */
|
||||||
|
#ifdef configTASK_RETURN_ADDRESS
|
||||||
|
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||||
|
#else
|
||||||
|
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The priority used by the kernel is assigned to a variable to make access
|
/* The priority used by the kernel is assigned to a variable to make access
|
||||||
from inline assembler easier. */
|
from inline assembler easier. */
|
||||||
const unsigned long ulKernelPriority = configKERNEL_INTERRUPT_PRIORITY;
|
const unsigned long ulKernelPriority = configKERNEL_INTERRUPT_PRIORITY;
|
||||||
|
@ -112,6 +121,11 @@ void SysTick_Handler( void );
|
||||||
extern void vPortEnableVFP( void );
|
extern void vPortEnableVFP( void );
|
||||||
extern void vPortStartFirstTask( void );
|
extern void vPortStartFirstTask( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
/* This exists purely to allow the const to be used from within the
|
/* This exists purely to allow the const to be used from within the
|
||||||
port_asm.asm assembly file. */
|
port_asm.asm assembly file. */
|
||||||
const unsigned long ulMaxSyscallInterruptPriorityConst = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
const unsigned long ulMaxSyscallInterruptPriorityConst = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
@ -134,7 +148,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
|
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = 0; /* LR */
|
*pxTopOfStack = ( portSTACK_TYPE ) portTASK_RETURN_ADDRESS; /* LR */
|
||||||
|
|
||||||
/* Save code space by skipping register initialisation. */
|
/* Save code space by skipping register initialisation. */
|
||||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
@ -151,6 +165,20 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
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( ulCriticalNesting == ~0UL );
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See header file for description.
|
* See header file for description.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -51,21 +51,26 @@
|
||||||
; licensing and training services.
|
; licensing and training services.
|
||||||
;*/
|
;*/
|
||||||
|
|
||||||
|
|
||||||
.extern pxCurrentTCB
|
.extern pxCurrentTCB
|
||||||
.extern vTaskSwitchContext
|
.extern vTaskSwitchContext
|
||||||
.extern ulMaxSyscallInterruptPriorityConst
|
.extern ulMaxSyscallInterruptPriorityConst
|
||||||
|
|
||||||
.global PendSV_Handler
|
.global _vector_14
|
||||||
|
.global _lc_ref__vector_pp_14
|
||||||
.global SVC_Handler
|
.global SVC_Handler
|
||||||
.global vPortStartFirstTask
|
.global vPortStartFirstTask
|
||||||
.global vPortEnableVFP
|
.global vPortEnableVFP
|
||||||
|
.global ulPortSetInterruptMask
|
||||||
|
.global vPortClearInterruptMask
|
||||||
|
|
||||||
;-----------------------------------------------------------
|
;-----------------------------------------------------------
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
.thumb
|
.thumb
|
||||||
.align 4
|
.align 4
|
||||||
PendSV_Handler: .type func
|
_vector_14: .type func
|
||||||
|
|
||||||
mrs r0, psp
|
mrs r0, psp
|
||||||
|
|
||||||
;Get the location of the current TCB.
|
;Get the location of the current TCB.
|
||||||
|
@ -106,7 +111,60 @@ PendSV_Handler: .type func
|
||||||
msr psp, r0
|
msr psp, r0
|
||||||
bx r14
|
bx r14
|
||||||
|
|
||||||
.size PendSV_Handler, $-PendSV_Handler
|
.size _vector_14, $-_vector_14
|
||||||
|
.endsec
|
||||||
|
|
||||||
|
;-----------------------------------------------------------
|
||||||
|
|
||||||
|
; This function is an XMC4000 silicon errata workaround. It will get used when
|
||||||
|
; the SILICON_BUG_PMC_CM_001 linker macro is defined.
|
||||||
|
.section .text
|
||||||
|
.thumb
|
||||||
|
.align 4
|
||||||
|
_lc_ref__vector_pp_14: .type func
|
||||||
|
|
||||||
|
mrs r0, psp
|
||||||
|
|
||||||
|
;Get the location of the current TCB.
|
||||||
|
ldr.w r3, =pxCurrentTCB
|
||||||
|
ldr r2, [r3]
|
||||||
|
|
||||||
|
;Is the task using the FPU context? If so, push high vfp registers.
|
||||||
|
tst r14, #0x10
|
||||||
|
it eq
|
||||||
|
vstmdbeq r0!, {s16-s31}
|
||||||
|
|
||||||
|
;Save the core registers.
|
||||||
|
stmdb r0!, {r4-r11, r14}
|
||||||
|
|
||||||
|
;Save the new top of stack into the first member of the TCB.
|
||||||
|
str r0, [r2]
|
||||||
|
|
||||||
|
stmdb sp!, {r3, r14}
|
||||||
|
ldr.w r0, =ulMaxSyscallInterruptPriorityConst
|
||||||
|
msr basepri, r0
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
ldmia sp!, {r3, r14}
|
||||||
|
|
||||||
|
;The first item in pxCurrentTCB is the task top of stack.
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
|
||||||
|
;Pop the core registers.
|
||||||
|
ldmia r0!, {r4-r11, r14}
|
||||||
|
|
||||||
|
;Is the task using the FPU context? If so, pop the high vfp registers too.
|
||||||
|
tst r14, #0x10
|
||||||
|
it eq
|
||||||
|
vldmiaeq r0!, {s16-s31}
|
||||||
|
|
||||||
|
msr psp, r0
|
||||||
|
push { lr }
|
||||||
|
pop { pc } ; XMC4000 specific errata workaround. Do not used "bx lr" here.
|
||||||
|
|
||||||
|
.size _lc_ref__vector_pp_14, $-_lc_ref__vector_pp_14
|
||||||
.endsec
|
.endsec
|
||||||
|
|
||||||
;-----------------------------------------------------------
|
;-----------------------------------------------------------
|
||||||
|
@ -163,6 +221,31 @@ vPortEnableVFP .type func
|
||||||
.size vPortEnableVFP, $-vPortEnableVFP
|
.size vPortEnableVFP, $-vPortEnableVFP
|
||||||
.endsec
|
.endsec
|
||||||
|
|
||||||
|
;-----------------------------------------------------------
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.thumb
|
||||||
|
.align 4
|
||||||
|
ulPortSetInterruptMask:
|
||||||
|
mrs r0, basepri
|
||||||
|
ldr.w r1, =ulMaxSyscallInterruptPriorityConst
|
||||||
|
msr basepri, r1
|
||||||
|
bx r14
|
||||||
|
.size ulPortSetInterruptMask, $-ulPortSetInterruptMask
|
||||||
|
.endsec
|
||||||
|
|
||||||
|
;-----------------------------------------------------------
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.thumb
|
||||||
|
.align 4
|
||||||
|
vPortClearInterruptMask:
|
||||||
|
msr basepri, r0
|
||||||
|
bx r14
|
||||||
|
.size vPortClearInterruptMask, $-vPortClearInterruptMask
|
||||||
|
.endsec
|
||||||
|
|
||||||
|
;-----------------------------------------------------------
|
||||||
|
|
||||||
.end
|
.end
|
||||||
|
|
||||||
|
|
|
@ -131,10 +131,10 @@ extern void vPortYield( void );
|
||||||
*/
|
*/
|
||||||
#define portCLEAR_INTERRUPT_MASK() __set_BASEPRI( 0 )
|
#define portCLEAR_INTERRUPT_MASK() __set_BASEPRI( 0 )
|
||||||
|
|
||||||
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see
|
extern unsigned long ulPortSetInterruptMask( void );
|
||||||
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
|
extern void vPortClearInterruptMask( unsigned long ulNewMask );
|
||||||
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
|
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x )
|
||||||
|
|
||||||
|
|
||||||
extern void vPortEnterCritical( void );
|
extern void vPortEnterCritical( void );
|
||||||
|
|
Loading…
Reference in a new issue