forked from epagris/FreeRTOS-Kernel
		
	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_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
 | 
			
		||||
from inline assembler easier. */
 | 
			
		||||
const unsigned long ulKernelPriority = configKERNEL_INTERRUPT_PRIORITY;
 | 
			
		||||
@ -112,6 +121,11 @@ void SysTick_Handler( void );
 | 
			
		||||
extern void vPortEnableVFP( 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
 | 
			
		||||
port_asm.asm assembly file. */
 | 
			
		||||
const unsigned long ulMaxSyscallInterruptPriorityConst = configMAX_SYSCALL_INTERRUPT_PRIORITY;
 | 
			
		||||
@ -134,7 +148,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
 | 
			
		||||
	pxTopOfStack--;
 | 
			
		||||
	*pxTopOfStack = ( portSTACK_TYPE ) pxCode;	/* PC */
 | 
			
		||||
	pxTopOfStack--;
 | 
			
		||||
	*pxTopOfStack = 0;	/* LR */
 | 
			
		||||
	*pxTopOfStack = ( portSTACK_TYPE ) portTASK_RETURN_ADDRESS;	/* LR */
 | 
			
		||||
 | 
			
		||||
	/* Save code space by skipping register initialisation. */
 | 
			
		||||
	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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -51,21 +51,26 @@
 | 
			
		||||
;    licensing and training services.
 | 
			
		||||
;*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	.extern pxCurrentTCB
 | 
			
		||||
	.extern vTaskSwitchContext
 | 
			
		||||
	.extern ulMaxSyscallInterruptPriorityConst
 | 
			
		||||
 | 
			
		||||
	.global PendSV_Handler
 | 
			
		||||
	.global _vector_14
 | 
			
		||||
	.global _lc_ref__vector_pp_14
 | 
			
		||||
	.global SVC_Handler
 | 
			
		||||
	.global vPortStartFirstTask
 | 
			
		||||
	.global vPortEnableVFP
 | 
			
		||||
	.global ulPortSetInterruptMask
 | 
			
		||||
	.global vPortClearInterruptMask
 | 
			
		||||
	
 | 
			
		||||
;-----------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
	.section .text
 | 
			
		||||
	.thumb
 | 
			
		||||
	.align 4
 | 
			
		||||
PendSV_Handler: .type func
 | 
			
		||||
_vector_14: .type func
 | 
			
		||||
 | 
			
		||||
	mrs r0, psp
 | 
			
		||||
 | 
			
		||||
	;Get the location of the current TCB.
 | 
			
		||||
@ -106,7 +111,60 @@ PendSV_Handler: .type func
 | 
			
		||||
	msr psp, r0
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
;-----------------------------------------------------------
 | 
			
		||||
@ -163,6 +221,31 @@ vPortEnableVFP .type func
 | 
			
		||||
	.size	vPortEnableVFP, $-vPortEnableVFP
 | 
			
		||||
	.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
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
@ -131,10 +131,10 @@ extern void vPortYield( void );
 | 
			
		||||
 */
 | 
			
		||||
#define portCLEAR_INTERRUPT_MASK() __set_BASEPRI( 0 )
 | 
			
		||||
 | 
			
		||||
/* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see
 | 
			
		||||
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
 | 
			
		||||
#define portSET_INTERRUPT_MASK_FROM_ISR()		0;portSET_INTERRUPT_MASK()
 | 
			
		||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	portCLEAR_INTERRUPT_MASK();(void)x
 | 
			
		||||
extern unsigned long ulPortSetInterruptMask( void );
 | 
			
		||||
extern void vPortClearInterruptMask( unsigned long ulNewMask );
 | 
			
		||||
#define portSET_INTERRUPT_MASK_FROM_ISR()		ulPortSetInterruptMask()
 | 
			
		||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	vPortClearInterruptMask( x )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void vPortEnterCritical( void );
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user