Initial commit
This commit is contained in:
		
							
								
								
									
										765
									
								
								ide-touchgfx-gen/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										765
									
								
								ide-touchgfx-gen/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,765 @@ | ||||
| /* | ||||
|  * FreeRTOS Kernel V10.2.1 | ||||
|  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * http://www.FreeRTOS.org | ||||
|  * http://aws.amazon.com/freertos | ||||
|  * | ||||
|  * 1 tab == 4 spaces! | ||||
|  */ | ||||
|  | ||||
| /*----------------------------------------------------------- | ||||
|  * Implementation of functions defined in portable.h for the ARM CM4F port. | ||||
|  *----------------------------------------------------------*/ | ||||
|  | ||||
| /* Scheduler includes. */ | ||||
| #include "FreeRTOS.h" | ||||
| #include "task.h" | ||||
|  | ||||
| #ifndef __VFP_FP__ | ||||
| 	#error This port can only be used when the project options are configured to enable hardware floating point support. | ||||
| #endif | ||||
|  | ||||
| #ifndef configSYSTICK_CLOCK_HZ | ||||
| 	#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ | ||||
| 	/* Ensure the SysTick is clocked at the same frequency as the core. */ | ||||
| 	#define portNVIC_SYSTICK_CLK_BIT	( 1UL << 2UL ) | ||||
| #else | ||||
| 	/* The way the SysTick is clocked is not modified in case it is not the same | ||||
| 	as the core. */ | ||||
| 	#define portNVIC_SYSTICK_CLK_BIT	( 0 ) | ||||
| #endif | ||||
|  | ||||
| /* Constants required to manipulate the core.  Registers first... */ | ||||
| #define portNVIC_SYSTICK_CTRL_REG			( * ( ( volatile uint32_t * ) 0xe000e010 ) ) | ||||
| #define portNVIC_SYSTICK_LOAD_REG			( * ( ( volatile uint32_t * ) 0xe000e014 ) ) | ||||
| #define portNVIC_SYSTICK_CURRENT_VALUE_REG	( * ( ( volatile uint32_t * ) 0xe000e018 ) ) | ||||
| #define portNVIC_SYSPRI2_REG				( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) | ||||
| /* ...then bits in the registers. */ | ||||
| #define portNVIC_SYSTICK_INT_BIT			( 1UL << 1UL ) | ||||
| #define portNVIC_SYSTICK_ENABLE_BIT			( 1UL << 0UL ) | ||||
| #define portNVIC_SYSTICK_COUNT_FLAG_BIT		( 1UL << 16UL ) | ||||
| #define portNVIC_PENDSVCLEAR_BIT 			( 1UL << 27UL ) | ||||
| #define portNVIC_PEND_SYSTICK_CLEAR_BIT		( 1UL << 25UL ) | ||||
|  | ||||
| #define portNVIC_PENDSV_PRI					( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) | ||||
| #define portNVIC_SYSTICK_PRI				( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) | ||||
|  | ||||
| /* Constants required to check the validity of an interrupt priority. */ | ||||
| #define portFIRST_USER_INTERRUPT_NUMBER		( 16 ) | ||||
| #define portNVIC_IP_REGISTERS_OFFSET_16 	( 0xE000E3F0 ) | ||||
| #define portAIRCR_REG						( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) | ||||
| #define portMAX_8_BIT_VALUE					( ( uint8_t ) 0xff ) | ||||
| #define portTOP_BIT_OF_BYTE					( ( uint8_t ) 0x80 ) | ||||
| #define portMAX_PRIGROUP_BITS				( ( uint8_t ) 7 ) | ||||
| #define portPRIORITY_GROUP_MASK				( 0x07UL << 8UL ) | ||||
| #define portPRIGROUP_SHIFT					( 8UL ) | ||||
|  | ||||
| /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ | ||||
| #define portVECTACTIVE_MASK					( 0xFFUL ) | ||||
|  | ||||
| /* Constants required to manipulate the VFP. */ | ||||
| #define portFPCCR							( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ | ||||
| #define portASPEN_AND_LSPEN_BITS			( 0x3UL << 30UL ) | ||||
|  | ||||
| /* Constants required to set up the initial stack. */ | ||||
| #define portINITIAL_XPSR					( 0x01000000 ) | ||||
| #define portINITIAL_EXC_RETURN				( 0xfffffffd ) | ||||
|  | ||||
| /* The systick is a 24-bit counter. */ | ||||
| #define portMAX_24_BIT_NUMBER				( 0xffffffUL ) | ||||
|  | ||||
| /* For strict compliance with the Cortex-M spec the task start address should | ||||
| have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ | ||||
| #define portSTART_ADDRESS_MASK		( ( StackType_t ) 0xfffffffeUL ) | ||||
|  | ||||
| /* A fiddle factor to estimate the number of SysTick counts that would have | ||||
| occurred while the SysTick counter is stopped during tickless idle | ||||
| calculations. */ | ||||
| #define portMISSED_COUNTS_FACTOR			( 45UL ) | ||||
|  | ||||
| /* Let the user override the pre-loading of the initial LR with the address of | ||||
| prvTaskExitError() in case it 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 | ||||
|  | ||||
| /* | ||||
|  * Setup the timer to generate the tick interrupts.  The implementation in this | ||||
|  * file is weak to allow application writers to change the timer used to | ||||
|  * generate the tick interrupt. | ||||
|  */ | ||||
| void vPortSetupTimerInterrupt( void ); | ||||
|  | ||||
| /* | ||||
|  * Exception handlers. | ||||
|  */ | ||||
| void xPortPendSVHandler( void ) __attribute__ (( naked )); | ||||
| void xPortSysTickHandler( void ); | ||||
| void vPortSVCHandler( void ) __attribute__ (( naked )); | ||||
|  | ||||
| /* | ||||
|  * Start first task is a separate function so it can be tested in isolation. | ||||
|  */ | ||||
| static void prvPortStartFirstTask( void ) __attribute__ (( naked )); | ||||
|  | ||||
| /* | ||||
|  * Function to enable the VFP. | ||||
|  */ | ||||
| static void vPortEnableVFP( void ) __attribute__ (( naked )); | ||||
|  | ||||
| /* | ||||
|  * Used to catch tasks that attempt to return from their implementing function. | ||||
|  */ | ||||
| static void prvTaskExitError( void ); | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* Each task maintains its own interrupt status in the critical nesting | ||||
| variable. */ | ||||
| static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; | ||||
|  | ||||
| /* | ||||
|  * The number of SysTick increments that make up one tick period. | ||||
|  */ | ||||
| #if( configUSE_TICKLESS_IDLE == 1 ) | ||||
| 	static uint32_t ulTimerCountsForOneTick = 0; | ||||
| #endif /* configUSE_TICKLESS_IDLE */ | ||||
|  | ||||
| /* | ||||
|  * The maximum number of tick periods that can be suppressed is limited by the | ||||
|  * 24 bit resolution of the SysTick timer. | ||||
|  */ | ||||
| #if( configUSE_TICKLESS_IDLE == 1 ) | ||||
| 	static uint32_t xMaximumPossibleSuppressedTicks = 0; | ||||
| #endif /* configUSE_TICKLESS_IDLE */ | ||||
|  | ||||
| /* | ||||
|  * Compensate for the CPU cycles that pass while the SysTick is stopped (low | ||||
|  * power functionality only. | ||||
|  */ | ||||
| #if( configUSE_TICKLESS_IDLE == 1 ) | ||||
| 	static uint32_t ulStoppedTimerCompensation = 0; | ||||
| #endif /* configUSE_TICKLESS_IDLE */ | ||||
|  | ||||
| /* | ||||
|  * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure | ||||
|  * FreeRTOS API functions are not called from interrupts that have been assigned | ||||
|  * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. | ||||
|  */ | ||||
| #if( configASSERT_DEFINED == 1 ) | ||||
| 	 static uint8_t ucMaxSysCallPriority = 0; | ||||
| 	 static uint32_t ulMaxPRIGROUPValue = 0; | ||||
| 	 static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; | ||||
| #endif /* configASSERT_DEFINED */ | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* | ||||
|  * See header file for description. | ||||
|  */ | ||||
| StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) | ||||
| { | ||||
| 	/* Simulate the stack frame as it would be created by a context switch | ||||
| 	interrupt. */ | ||||
|  | ||||
| 	/* Offset added to account for the way the MCU uses the stack on entry/exit | ||||
| 	of interrupts, and to ensure alignment. */ | ||||
| 	pxTopOfStack--; | ||||
|  | ||||
| 	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */ | ||||
| 	pxTopOfStack--; | ||||
| 	*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK;	/* PC */ | ||||
| 	pxTopOfStack--; | ||||
| 	*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS;	/* LR */ | ||||
|  | ||||
| 	/* Save code space by skipping register initialisation. */ | ||||
| 	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */ | ||||
| 	*pxTopOfStack = ( StackType_t ) pvParameters;	/* R0 */ | ||||
|  | ||||
| 	/* A save method is being used that requires each task to maintain its | ||||
| 	own exec return value. */ | ||||
| 	pxTopOfStack--; | ||||
| 	*pxTopOfStack = portINITIAL_EXC_RETURN; | ||||
|  | ||||
| 	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */ | ||||
|  | ||||
| 	return pxTopOfStack; | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| static void prvTaskExitError( void ) | ||||
| { | ||||
| volatile uint32_t ulDummy = 0; | ||||
|  | ||||
| 	/* 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( uxCriticalNesting == ~0UL ); | ||||
| 	portDISABLE_INTERRUPTS(); | ||||
| 	while( ulDummy == 0 ) | ||||
| 	{ | ||||
| 		/* This file calls prvTaskExitError() after the scheduler has been | ||||
| 		started to remove a compiler warning about the function being defined | ||||
| 		but never called.  ulDummy is used purely to quieten other warnings | ||||
| 		about code appearing after this function is called - making ulDummy | ||||
| 		volatile makes the compiler think the function could return and | ||||
| 		therefore not output an 'unreachable code' warning for code that appears | ||||
| 		after it. */ | ||||
| 	} | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void vPortSVCHandler( void ) | ||||
| { | ||||
| 	__asm volatile ( | ||||
| 					"	ldr	r3, pxCurrentTCBConst2		\n" /* Restore the context. */ | ||||
| 					"	ldr r1, [r3]					\n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ | ||||
| 					"	ldr r0, [r1]					\n" /* The first item in pxCurrentTCB is the task top of stack. */ | ||||
| 					"	ldmia r0!, {r4-r11, r14}		\n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ | ||||
| 					"	msr psp, r0						\n" /* Restore the task stack pointer. */ | ||||
| 					"	isb								\n" | ||||
| 					"	mov r0, #0 						\n" | ||||
| 					"	msr	basepri, r0					\n" | ||||
| 					"	bx r14							\n" | ||||
| 					"									\n" | ||||
| 					"	.align 4						\n" | ||||
| 					"pxCurrentTCBConst2: .word pxCurrentTCB				\n" | ||||
| 				); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| static void prvPortStartFirstTask( void ) | ||||
| { | ||||
| 	/* Start the first task.  This also clears the bit that indicates the FPU is | ||||
| 	in use in case the FPU was used before the scheduler was started - which | ||||
| 	would otherwise result in the unnecessary leaving of space in the SVC stack | ||||
| 	for lazy saving of FPU registers. */ | ||||
| 	__asm volatile( | ||||
| 					" ldr r0, =0xE000ED08 	\n" /* Use the NVIC offset register to locate the stack. */ | ||||
| 					" ldr r0, [r0] 			\n" | ||||
| 					" ldr r0, [r0] 			\n" | ||||
| 					" msr msp, r0			\n" /* Set the msp back to the start of the stack. */ | ||||
| 					" mov r0, #0			\n" /* Clear the bit that indicates the FPU is in use, see comment above. */ | ||||
| 					" msr control, r0		\n" | ||||
| 					" cpsie i				\n" /* Globally enable interrupts. */ | ||||
| 					" cpsie f				\n" | ||||
| 					" dsb					\n" | ||||
| 					" isb					\n" | ||||
| 					" svc 0					\n" /* System call to start first task. */ | ||||
| 					" nop					\n" | ||||
| 				); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* | ||||
|  * See header file for description. | ||||
|  */ | ||||
| BaseType_t xPortStartScheduler( void ) | ||||
| { | ||||
| 	/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. | ||||
| 	See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ | ||||
| 	configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); | ||||
|  | ||||
| 	#if( configASSERT_DEFINED == 1 ) | ||||
| 	{ | ||||
| 		volatile uint32_t ulOriginalPriority; | ||||
| 		volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); | ||||
| 		volatile uint8_t ucMaxPriorityValue; | ||||
|  | ||||
| 		/* Determine the maximum priority from which ISR safe FreeRTOS API | ||||
| 		functions can be called.  ISR safe functions are those that end in | ||||
| 		"FromISR".  FreeRTOS maintains separate thread and ISR API functions to | ||||
| 		ensure interrupt entry is as fast and simple as possible. | ||||
|  | ||||
| 		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; | ||||
|  | ||||
| 		/* Use the same mask on the maximum system call priority. */ | ||||
| 		ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; | ||||
|  | ||||
| 		/* Calculate the maximum acceptable priority group value for the number | ||||
| 		of bits read back. */ | ||||
| 		ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; | ||||
| 		while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) | ||||
| 		{ | ||||
| 			ulMaxPRIGROUPValue--; | ||||
| 			ucMaxPriorityValue <<= ( uint8_t ) 0x01; | ||||
| 		} | ||||
|  | ||||
| 		#ifdef __NVIC_PRIO_BITS | ||||
| 		{ | ||||
| 			/* Check the CMSIS configuration that defines the number of | ||||
| 			priority bits matches the number of priority bits actually queried | ||||
| 			from the hardware. */ | ||||
| 			configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); | ||||
| 		} | ||||
| 		#endif | ||||
|  | ||||
| 		#ifdef configPRIO_BITS | ||||
| 		{ | ||||
| 			/* Check the FreeRTOS configuration that defines the number of | ||||
| 			priority bits matches the number of priority bits actually queried | ||||
| 			from the hardware. */ | ||||
| 			configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); | ||||
| 		} | ||||
| 		#endif | ||||
|  | ||||
| 		/* Shift the priority group value back to its position within the AIRCR | ||||
| 		register. */ | ||||
| 		ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; | ||||
| 		ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; | ||||
|  | ||||
| 		/* Restore the clobbered interrupt priority register to its original | ||||
| 		value. */ | ||||
| 		*pucFirstUserPriorityRegister = ulOriginalPriority; | ||||
| 	} | ||||
| 	#endif /* conifgASSERT_DEFINED */ | ||||
|  | ||||
| 	/* Make PendSV and SysTick the lowest priority interrupts. */ | ||||
| 	portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; | ||||
| 	portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; | ||||
|  | ||||
| 	/* Start the timer that generates the tick ISR.  Interrupts are disabled | ||||
| 	here already. */ | ||||
| 	vPortSetupTimerInterrupt(); | ||||
|  | ||||
| 	/* Initialise the critical nesting count ready for the first task. */ | ||||
| 	uxCriticalNesting = 0; | ||||
|  | ||||
| 	/* Ensure the VFP is enabled - it should be anyway. */ | ||||
| 	vPortEnableVFP(); | ||||
|  | ||||
| 	/* Lazy save always. */ | ||||
| 	*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; | ||||
|  | ||||
| 	/* Start the first task. */ | ||||
| 	prvPortStartFirstTask(); | ||||
|  | ||||
| 	/* Should never get here as the tasks will now be executing!  Call the task | ||||
| 	exit error function to prevent compiler warnings about a static function | ||||
| 	not being called in the case that the application writer overrides this | ||||
| 	functionality by defining configTASK_RETURN_ADDRESS.  Call | ||||
| 	vTaskSwitchContext() so link time optimisation does not remove the | ||||
| 	symbol. */ | ||||
| 	vTaskSwitchContext(); | ||||
| 	prvTaskExitError(); | ||||
|  | ||||
| 	/* Should not get here! */ | ||||
| 	return 0; | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void vPortEndScheduler( void ) | ||||
| { | ||||
| 	/* Not implemented in ports where there is nothing to return to. | ||||
| 	Artificially force an assert. */ | ||||
| 	configASSERT( uxCriticalNesting == 1000UL ); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void vPortEnterCritical( void ) | ||||
| { | ||||
| 	portDISABLE_INTERRUPTS(); | ||||
| 	uxCriticalNesting++; | ||||
|  | ||||
| 	/* This is not the interrupt safe version of the enter critical function so | ||||
| 	assert() if it is being called from an interrupt context.  Only API | ||||
| 	functions that end in "FromISR" can be used in an interrupt.  Only assert if | ||||
| 	the critical nesting count is 1 to protect against recursive calls if the | ||||
| 	assert function also uses a critical section. */ | ||||
| 	if( uxCriticalNesting == 1 ) | ||||
| 	{ | ||||
| 		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); | ||||
| 	} | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void vPortExitCritical( void ) | ||||
| { | ||||
| 	configASSERT( uxCriticalNesting ); | ||||
| 	uxCriticalNesting--; | ||||
| 	if( uxCriticalNesting == 0 ) | ||||
| 	{ | ||||
| 		portENABLE_INTERRUPTS(); | ||||
| 	} | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void xPortPendSVHandler( void ) | ||||
| { | ||||
| 	/* This is a naked function. */ | ||||
|  | ||||
| 	__asm volatile | ||||
| 	( | ||||
| 	"	mrs r0, psp							\n" | ||||
| 	"	isb									\n" | ||||
| 	"										\n" | ||||
| 	"	ldr	r3, pxCurrentTCBConst			\n" /* Get the location of the current TCB. */ | ||||
| 	"	ldr	r2, [r3]						\n" | ||||
| 	"										\n" | ||||
| 	"	tst r14, #0x10						\n" /* Is the task using the FPU context?  If so, push high vfp registers. */ | ||||
| 	"	it eq								\n" | ||||
| 	"	vstmdbeq r0!, {s16-s31}				\n" | ||||
| 	"										\n" | ||||
| 	"	stmdb r0!, {r4-r11, r14}			\n" /* Save the core registers. */ | ||||
| 	"	str r0, [r2]						\n" /* Save the new top of stack into the first member of the TCB. */ | ||||
| 	"										\n" | ||||
| 	"	stmdb sp!, {r0, r3}					\n" | ||||
| 	"	mov r0, %0 							\n" | ||||
| 	"	cpsid i								\n" /* Errata workaround. */ | ||||
| 	"	msr basepri, r0						\n" | ||||
| 	"	dsb									\n" | ||||
| 	"	isb									\n" | ||||
| 	"	cpsie i								\n" /* Errata workaround. */ | ||||
| 	"	bl vTaskSwitchContext				\n" | ||||
| 	"	mov r0, #0							\n" | ||||
| 	"	msr basepri, r0						\n" | ||||
| 	"	ldmia sp!, {r0, r3}					\n" | ||||
| 	"										\n" | ||||
| 	"	ldr r1, [r3]						\n" /* The first item in pxCurrentTCB is the task top of stack. */ | ||||
| 	"	ldr r0, [r1]						\n" | ||||
| 	"										\n" | ||||
| 	"	ldmia r0!, {r4-r11, r14}			\n" /* Pop the core registers. */ | ||||
| 	"										\n" | ||||
| 	"	tst r14, #0x10						\n" /* Is the task using the FPU context?  If so, pop the high vfp registers too. */ | ||||
| 	"	it eq								\n" | ||||
| 	"	vldmiaeq r0!, {s16-s31}				\n" | ||||
| 	"										\n" | ||||
| 	"	msr psp, r0							\n" | ||||
| 	"	isb									\n" | ||||
| 	"										\n" | ||||
| 	#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ | ||||
| 		#if WORKAROUND_PMU_CM001 == 1 | ||||
| 	"			push { r14 }				\n" | ||||
| 	"			pop { pc }					\n" | ||||
| 		#endif | ||||
| 	#endif | ||||
| 	"										\n" | ||||
| 	"	bx r14								\n" | ||||
| 	"										\n" | ||||
| 	"	.align 4							\n" | ||||
| 	"pxCurrentTCBConst: .word pxCurrentTCB	\n" | ||||
| 	::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) | ||||
| 	); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void xPortSysTickHandler( void ) | ||||
| { | ||||
| 	/* The SysTick runs at the lowest interrupt priority, so when this interrupt | ||||
| 	executes all interrupts must be unmasked.  There is therefore no need to | ||||
| 	save and then restore the interrupt mask value as its value is already | ||||
| 	known. */ | ||||
| 	portDISABLE_INTERRUPTS(); | ||||
| 	{ | ||||
| 		/* Increment the RTOS tick. */ | ||||
| 		if( xTaskIncrementTick() != pdFALSE ) | ||||
| 		{ | ||||
| 			/* A context switch is required.  Context switching is performed in | ||||
| 			the PendSV interrupt.  Pend the PendSV interrupt. */ | ||||
| 			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; | ||||
| 		} | ||||
| 	} | ||||
| 	portENABLE_INTERRUPTS(); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| #if( configUSE_TICKLESS_IDLE == 1 ) | ||||
|  | ||||
| 	__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) | ||||
| 	{ | ||||
| 	uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; | ||||
| 	TickType_t xModifiableIdleTime; | ||||
|  | ||||
| 		/* Make sure the SysTick reload value does not overflow the counter. */ | ||||
| 		if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) | ||||
| 		{ | ||||
| 			xExpectedIdleTime = xMaximumPossibleSuppressedTicks; | ||||
| 		} | ||||
|  | ||||
| 		/* Stop the SysTick momentarily.  The time the SysTick is stopped for | ||||
| 		is accounted for as best it can be, but using the tickless mode will | ||||
| 		inevitably result in some tiny drift of the time maintained by the | ||||
| 		kernel with respect to calendar time. */ | ||||
| 		portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; | ||||
|  | ||||
| 		/* Calculate the reload value required to wait xExpectedIdleTime | ||||
| 		tick periods.  -1 is used because this code will execute part way | ||||
| 		through one of the tick periods. */ | ||||
| 		ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); | ||||
| 		if( ulReloadValue > ulStoppedTimerCompensation ) | ||||
| 		{ | ||||
| 			ulReloadValue -= ulStoppedTimerCompensation; | ||||
| 		} | ||||
|  | ||||
| 		/* Enter a critical section but don't use the taskENTER_CRITICAL() | ||||
| 		method as that will mask interrupts that should exit sleep mode. */ | ||||
| 		__asm volatile( "cpsid i" ::: "memory" ); | ||||
| 		__asm volatile( "dsb" ); | ||||
| 		__asm volatile( "isb" ); | ||||
|  | ||||
| 		/* If a context switch is pending or a task is waiting for the scheduler | ||||
| 		to be unsuspended then abandon the low power entry. */ | ||||
| 		if( eTaskConfirmSleepModeStatus() == eAbortSleep ) | ||||
| 		{ | ||||
| 			/* Restart from whatever is left in the count register to complete | ||||
| 			this tick period. */ | ||||
| 			portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; | ||||
|  | ||||
| 			/* Restart SysTick. */ | ||||
| 			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; | ||||
|  | ||||
| 			/* Reset the reload register to the value required for normal tick | ||||
| 			periods. */ | ||||
| 			portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; | ||||
|  | ||||
| 			/* Re-enable interrupts - see comments above the cpsid instruction() | ||||
| 			above. */ | ||||
| 			__asm volatile( "cpsie i" ::: "memory" ); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* Set the new reload value. */ | ||||
| 			portNVIC_SYSTICK_LOAD_REG = ulReloadValue; | ||||
|  | ||||
| 			/* Clear the SysTick count flag and set the count value back to | ||||
| 			zero. */ | ||||
| 			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; | ||||
|  | ||||
| 			/* Restart SysTick. */ | ||||
| 			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; | ||||
|  | ||||
| 			/* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can | ||||
| 			set its parameter to 0 to indicate that its implementation contains | ||||
| 			its own wait for interrupt or wait for event instruction, and so wfi | ||||
| 			should not be executed again.  However, the original expected idle | ||||
| 			time variable must remain unmodified, so a copy is taken. */ | ||||
| 			xModifiableIdleTime = xExpectedIdleTime; | ||||
| 			configPRE_SLEEP_PROCESSING( &xModifiableIdleTime ); | ||||
| 			if( xModifiableIdleTime > 0 ) | ||||
| 			{ | ||||
| 				__asm volatile( "dsb" ::: "memory" ); | ||||
| 				__asm volatile( "wfi" ); | ||||
| 				__asm volatile( "isb" ); | ||||
| 			} | ||||
| 			configPOST_SLEEP_PROCESSING( &xExpectedIdleTime ); | ||||
|  | ||||
| 			/* Re-enable interrupts to allow the interrupt that brought the MCU | ||||
| 			out of sleep mode to execute immediately.  see comments above | ||||
| 			__disable_interrupt() call above. */ | ||||
| 			__asm volatile( "cpsie i" ::: "memory" ); | ||||
| 			__asm volatile( "dsb" ); | ||||
| 			__asm volatile( "isb" ); | ||||
|  | ||||
| 			/* Disable interrupts again because the clock is about to be stopped | ||||
| 			and interrupts that execute while the clock is stopped will increase | ||||
| 			any slippage between the time maintained by the RTOS and calendar | ||||
| 			time. */ | ||||
| 			__asm volatile( "cpsid i" ::: "memory" ); | ||||
| 			__asm volatile( "dsb" ); | ||||
| 			__asm volatile( "isb" ); | ||||
|  | ||||
| 			/* Disable the SysTick clock without reading the | ||||
| 			portNVIC_SYSTICK_CTRL_REG register to ensure the | ||||
| 			portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.  Again, | ||||
| 			the time the SysTick is stopped for is accounted for as best it can | ||||
| 			be, but using the tickless mode will inevitably result in some tiny | ||||
| 			drift of the time maintained by the kernel with respect to calendar | ||||
| 			time*/ | ||||
| 			portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); | ||||
|  | ||||
| 			/* Determine if the SysTick clock has already counted to zero and | ||||
| 			been set back to the current reload value (the reload back being | ||||
| 			correct for the entire expected idle time) or if the SysTick is yet | ||||
| 			to count to zero (in which case an interrupt other than the SysTick | ||||
| 			must have brought the system out of sleep mode). */ | ||||
| 			if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) | ||||
| 			{ | ||||
| 				uint32_t ulCalculatedLoadValue; | ||||
|  | ||||
| 				/* The tick interrupt is already pending, and the SysTick count | ||||
| 				reloaded with ulReloadValue.  Reset the | ||||
| 				portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick | ||||
| 				period. */ | ||||
| 				ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); | ||||
|  | ||||
| 				/* Don't allow a tiny value, or values that have somehow | ||||
| 				underflowed because the post sleep hook did something | ||||
| 				that took too long. */ | ||||
| 				if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) | ||||
| 				{ | ||||
| 					ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); | ||||
| 				} | ||||
|  | ||||
| 				portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; | ||||
|  | ||||
| 				/* As the pending tick will be processed as soon as this | ||||
| 				function exits, the tick value maintained by the tick is stepped | ||||
| 				forward by one less than the time spent waiting. */ | ||||
| 				ulCompleteTickPeriods = xExpectedIdleTime - 1UL; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* Something other than the tick interrupt ended the sleep. | ||||
| 				Work out how long the sleep lasted rounded to complete tick | ||||
| 				periods (not the ulReload value which accounted for part | ||||
| 				ticks). */ | ||||
| 				ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; | ||||
|  | ||||
| 				/* How many complete tick periods passed while the processor | ||||
| 				was waiting? */ | ||||
| 				ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; | ||||
|  | ||||
| 				/* The reload value is set to whatever fraction of a single tick | ||||
| 				period remains. */ | ||||
| 				portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; | ||||
| 			} | ||||
|  | ||||
| 			/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG | ||||
| 			again, then set portNVIC_SYSTICK_LOAD_REG back to its standard | ||||
| 			value. */ | ||||
| 			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; | ||||
| 			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; | ||||
| 			vTaskStepTick( ulCompleteTickPeriods ); | ||||
| 			portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; | ||||
|  | ||||
| 			/* Exit with interrpts enabled. */ | ||||
| 			__asm volatile( "cpsie i" ::: "memory" ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| #endif /* #if configUSE_TICKLESS_IDLE */ | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* | ||||
|  * Setup the systick timer to generate the tick interrupts at the required | ||||
|  * frequency. | ||||
|  */ | ||||
| __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) | ||||
| { | ||||
| 	/* Calculate the constants required to configure the tick interrupt. */ | ||||
| 	#if( configUSE_TICKLESS_IDLE == 1 ) | ||||
| 	{ | ||||
| 		ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); | ||||
| 		xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; | ||||
| 		ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); | ||||
| 	} | ||||
| 	#endif /* configUSE_TICKLESS_IDLE */ | ||||
|  | ||||
| 	/* Stop and clear the SysTick. */ | ||||
| 	portNVIC_SYSTICK_CTRL_REG = 0UL; | ||||
| 	portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; | ||||
|  | ||||
| 	/* Configure SysTick to interrupt at the requested rate. */ | ||||
| 	portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; | ||||
| 	portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* This is a naked function. */ | ||||
| static void vPortEnableVFP( void ) | ||||
| { | ||||
| 	__asm volatile | ||||
| 	( | ||||
| 		"	ldr.w r0, =0xE000ED88		\n" /* The FPU enable bits are in the CPACR. */ | ||||
| 		"	ldr r1, [r0]				\n" | ||||
| 		"								\n" | ||||
| 		"	orr r1, r1, #( 0xf << 20 )	\n" /* Enable CP10 and CP11 coprocessors, then save back. */ | ||||
| 		"	str r1, [r0]				\n" | ||||
| 		"	bx r14						" | ||||
| 	); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| #if( configASSERT_DEFINED == 1 ) | ||||
|  | ||||
| 	void vPortValidateInterruptPriority( void ) | ||||
| 	{ | ||||
| 	uint32_t ulCurrentInterrupt; | ||||
| 	uint8_t ucCurrentPriority; | ||||
|  | ||||
| 		/* Obtain the number of the currently executing interrupt. */ | ||||
| 		__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" ); | ||||
|  | ||||
| 		/* Is the interrupt number a user defined interrupt? */ | ||||
| 		if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) | ||||
| 		{ | ||||
| 			/* Look up the interrupt's priority. */ | ||||
| 			ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; | ||||
|  | ||||
| 			/* The following assertion will fail if a service routine (ISR) for | ||||
| 			an interrupt that has been assigned a priority above | ||||
| 			configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API | ||||
| 			function.  ISR safe FreeRTOS API functions must *only* be called | ||||
| 			from interrupts that have been assigned a priority at or below | ||||
| 			configMAX_SYSCALL_INTERRUPT_PRIORITY. | ||||
|  | ||||
| 			Numerically low interrupt priority numbers represent logically high | ||||
| 			interrupt priorities, therefore the priority of the interrupt must | ||||
| 			be set to a value equal to or numerically *higher* than | ||||
| 			configMAX_SYSCALL_INTERRUPT_PRIORITY. | ||||
|  | ||||
| 			Interrupts that	use the FreeRTOS API must not be left at their | ||||
| 			default priority of	zero as that is the highest possible priority, | ||||
| 			which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, | ||||
| 			and	therefore also guaranteed to be invalid. | ||||
|  | ||||
| 			FreeRTOS maintains separate thread and ISR API functions to ensure | ||||
| 			interrupt entry is as fast and simple as possible. | ||||
|  | ||||
| 			The following links provide detailed information: | ||||
| 			http://www.freertos.org/RTOS-Cortex-M3-M4.html | ||||
| 			http://www.freertos.org/FAQHelp.html */ | ||||
| 			configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); | ||||
| 		} | ||||
|  | ||||
| 		/* Priority grouping:  The interrupt controller (NVIC) allows the bits | ||||
| 		that define each interrupt's priority to be split between bits that | ||||
| 		define the interrupt's pre-emption priority bits and bits that define | ||||
| 		the interrupt's sub-priority.  For simplicity all bits must be defined | ||||
| 		to be pre-emption priority bits.  The following assertion will fail if | ||||
| 		this is not the case (if some bits represent a sub-priority). | ||||
|  | ||||
| 		If the application only uses CMSIS libraries for interrupt | ||||
| 		configuration then the correct setting can be achieved on all Cortex-M | ||||
| 		devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the | ||||
| 		scheduler.  Note however that some vendor specific peripheral libraries | ||||
| 		assume a non-zero priority group setting, in which cases using a value | ||||
| 		of zero will result in unpredictable behaviour. */ | ||||
| 		configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); | ||||
| 	} | ||||
|  | ||||
| #endif /* configASSERT_DEFINED */ | ||||
|  | ||||
|  | ||||
							
								
								
									
										247
									
								
								ide-touchgfx-gen/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/portmacro.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								ide-touchgfx-gen/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/portmacro.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| /* | ||||
|  * FreeRTOS Kernel V10.2.1 | ||||
|  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * http://www.FreeRTOS.org | ||||
|  * http://aws.amazon.com/freertos | ||||
|  * | ||||
|  * 1 tab == 4 spaces! | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef PORTMACRO_H | ||||
| #define PORTMACRO_H | ||||
|  | ||||
| #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	uint32_t | ||||
| #define portBASE_TYPE	long | ||||
|  | ||||
| typedef portSTACK_TYPE StackType_t; | ||||
| typedef long BaseType_t; | ||||
| typedef unsigned long UBaseType_t; | ||||
|  | ||||
| #if( configUSE_16_BIT_TICKS == 1 ) | ||||
| 	typedef uint16_t TickType_t; | ||||
| 	#define portMAX_DELAY ( TickType_t ) 0xffff | ||||
| #else | ||||
| 	typedef uint32_t TickType_t; | ||||
| 	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL | ||||
|  | ||||
| 	/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do | ||||
| 	not need to be guarded with a critical section. */ | ||||
| 	#define portTICK_TYPE_IS_ATOMIC 1 | ||||
| #endif | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* Architecture specifics. */ | ||||
| #define portSTACK_GROWTH			( -1 ) | ||||
| #define portTICK_PERIOD_MS			( ( TickType_t ) 1000 / configTICK_RATE_HZ ) | ||||
| #define portBYTE_ALIGNMENT			8 | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* Scheduler utilities. */ | ||||
| #define portYIELD() 															\ | ||||
| {																				\ | ||||
| 	/* Set a PendSV to request a context switch. */								\ | ||||
| 	portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;								\ | ||||
| 																				\ | ||||
| 	/* Barriers are normally not required but do ensure the code is completely	\ | ||||
| 	within the specified behaviour for the architecture. */						\ | ||||
| 	__asm volatile( "dsb" ::: "memory" );										\ | ||||
| 	__asm volatile( "isb" );													\ | ||||
| } | ||||
|  | ||||
| #define portNVIC_INT_CTRL_REG		( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) | ||||
| #define portNVIC_PENDSVSET_BIT		( 1UL << 28UL ) | ||||
| #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD() | ||||
| #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* Critical section management. */ | ||||
| extern void vPortEnterCritical( void ); | ||||
| extern void vPortExitCritical( void ); | ||||
| #define portSET_INTERRUPT_MASK_FROM_ISR()		ulPortRaiseBASEPRI() | ||||
| #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	vPortSetBASEPRI(x) | ||||
| #define portDISABLE_INTERRUPTS()				vPortRaiseBASEPRI() | ||||
| #define portENABLE_INTERRUPTS()					vPortSetBASEPRI(0) | ||||
| #define portENTER_CRITICAL()					vPortEnterCritical() | ||||
| #define portEXIT_CRITICAL()						vPortExitCritical() | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* Task function macros as described on the FreeRTOS.org WEB site.  These are | ||||
| not necessary for to use this port.  They are defined so the common demo files | ||||
| (which build with all the ports) will build. */ | ||||
| #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) | ||||
| #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* Tickless idle/low power functionality. */ | ||||
| #ifndef portSUPPRESS_TICKS_AND_SLEEP | ||||
| 	extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); | ||||
| 	#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) | ||||
| #endif | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* Architecture specific optimisations. */ | ||||
| #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION | ||||
| 	#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 | ||||
| #endif | ||||
|  | ||||
| #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 | ||||
|  | ||||
| 	/* Generic helper function. */ | ||||
| 	__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) | ||||
| 	{ | ||||
| 	uint8_t ucReturn; | ||||
|  | ||||
| 		__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); | ||||
| 		return ucReturn; | ||||
| 	} | ||||
|  | ||||
| 	/* Check the configuration. */ | ||||
| 	#if( configMAX_PRIORITIES > 32 ) | ||||
| 		#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. | ||||
| 	#endif | ||||
|  | ||||
| 	/* Store/clear the ready priorities in a bit map. */ | ||||
| 	#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) | ||||
| 	#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) | ||||
|  | ||||
| 	/*-----------------------------------------------------------*/ | ||||
|  | ||||
| 	#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) | ||||
|  | ||||
| #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| #ifdef configASSERT | ||||
| 	void vPortValidateInterruptPriority( void ); | ||||
| 	#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() 	vPortValidateInterruptPriority() | ||||
| #endif | ||||
|  | ||||
| /* portNOP() is not required by this port. */ | ||||
| #define portNOP() | ||||
|  | ||||
| #define portINLINE	__inline | ||||
|  | ||||
| #ifndef portFORCE_INLINE | ||||
| 	#define portFORCE_INLINE inline __attribute__(( always_inline)) | ||||
| #endif | ||||
|  | ||||
| portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) | ||||
| { | ||||
| uint32_t ulCurrentInterrupt; | ||||
| BaseType_t xReturn; | ||||
|  | ||||
| 	/* Obtain the number of the currently executing interrupt. */ | ||||
| 	__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" ); | ||||
|  | ||||
| 	if( ulCurrentInterrupt == 0 ) | ||||
| 	{ | ||||
| 		xReturn = pdFALSE; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		xReturn = pdTRUE; | ||||
| 	} | ||||
|  | ||||
| 	return xReturn; | ||||
| } | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| portFORCE_INLINE static void vPortRaiseBASEPRI( void ) | ||||
| { | ||||
| uint32_t ulNewBASEPRI; | ||||
|  | ||||
| 	__asm volatile | ||||
| 	( | ||||
| 		"	mov %0, %1												\n"	\ | ||||
| 		"	cpsid i													\n" \ | ||||
| 		"	msr basepri, %0											\n" \ | ||||
| 		"	isb														\n" \ | ||||
| 		"	dsb														\n" \ | ||||
| 		"	cpsie i													\n" \ | ||||
| 		:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" | ||||
| 	); | ||||
| } | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) | ||||
| { | ||||
| uint32_t ulOriginalBASEPRI, ulNewBASEPRI; | ||||
|  | ||||
| 	__asm volatile | ||||
| 	( | ||||
| 		"	mrs %0, basepri											\n" \ | ||||
| 		"	mov %1, %2												\n"	\ | ||||
| 		"	cpsid i													\n" \ | ||||
| 		"	msr basepri, %1											\n" \ | ||||
| 		"	isb														\n" \ | ||||
| 		"	dsb														\n" \ | ||||
| 		"	cpsie i													\n" \ | ||||
| 		:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" | ||||
| 	); | ||||
|  | ||||
| 	/* This return will not be reached but is necessary to prevent compiler | ||||
| 	warnings. */ | ||||
| 	return ulOriginalBASEPRI; | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) | ||||
| { | ||||
| 	__asm volatile | ||||
| 	( | ||||
| 		"	msr basepri, %0	" :: "r" ( ulNewMaskValue ) : "memory" | ||||
| 	); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* PORTMACRO_H */ | ||||
|  | ||||
							
								
								
									
										436
									
								
								ide-touchgfx-gen/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										436
									
								
								ide-touchgfx-gen/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,436 @@ | ||||
| /* | ||||
|  * FreeRTOS Kernel V10.2.1 | ||||
|  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
|  * this software and associated documentation files (the "Software"), to deal in | ||||
|  * the Software without restriction, including without limitation the rights to | ||||
|  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||
|  * the Software, and to permit persons to whom the Software is furnished to do so, | ||||
|  * subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||||
|  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * http://www.FreeRTOS.org | ||||
|  * http://aws.amazon.com/freertos | ||||
|  * | ||||
|  * 1 tab == 4 spaces! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * A sample implementation of pvPortMalloc() and vPortFree() that combines | ||||
|  * (coalescences) adjacent memory blocks as they are freed, and in so doing | ||||
|  * limits memory fragmentation. | ||||
|  * | ||||
|  * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the | ||||
|  * memory management pages of http://www.FreeRTOS.org for more information. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
|  | ||||
| /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining | ||||
| all the API functions to use the MPU wrappers.  That should only be done when | ||||
| task.h is included from an application file. */ | ||||
| #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE | ||||
|  | ||||
| #include "FreeRTOS.h" | ||||
| #include "task.h" | ||||
|  | ||||
| #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE | ||||
|  | ||||
| #if( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) | ||||
| 	#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 | ||||
| #endif | ||||
|  | ||||
| /* Block sizes must not get too small. */ | ||||
| #define heapMINIMUM_BLOCK_SIZE	( ( size_t ) ( xHeapStructSize << 1 ) ) | ||||
|  | ||||
| /* Assumes 8bit bytes! */ | ||||
| #define heapBITS_PER_BYTE		( ( size_t ) 8 ) | ||||
|  | ||||
| /* Allocate the memory for the heap. */ | ||||
| #if( configAPPLICATION_ALLOCATED_HEAP == 1 ) | ||||
| 	/* The application writer has already defined the array used for the RTOS | ||||
| 	heap - probably so it can be placed in a special segment or address. */ | ||||
| 	extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; | ||||
| #else | ||||
| 	static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; | ||||
| #endif /* configAPPLICATION_ALLOCATED_HEAP */ | ||||
|  | ||||
| /* Define the linked list structure.  This is used to link free blocks in order | ||||
| of their memory address. */ | ||||
| typedef struct A_BLOCK_LINK | ||||
| { | ||||
| 	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<< The next free block in the list. */ | ||||
| 	size_t xBlockSize;						/*<< The size of the free block. */ | ||||
| } BlockLink_t; | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* | ||||
|  * Inserts a block of memory that is being freed into the correct position in | ||||
|  * the list of free memory blocks.  The block being freed will be merged with | ||||
|  * the block in front it and/or the block behind it if the memory blocks are | ||||
|  * adjacent to each other. | ||||
|  */ | ||||
| static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); | ||||
|  | ||||
| /* | ||||
|  * Called automatically to setup the required heap structures the first time | ||||
|  * pvPortMalloc() is called. | ||||
|  */ | ||||
| static void prvHeapInit( void ); | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| /* The size of the structure placed at the beginning of each allocated memory | ||||
| block must by correctly byte aligned. */ | ||||
| static const size_t xHeapStructSize	= ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); | ||||
|  | ||||
| /* Create a couple of list links to mark the start and end of the list. */ | ||||
| static BlockLink_t xStart, *pxEnd = NULL; | ||||
|  | ||||
| /* Keeps track of the number of free bytes remaining, but says nothing about | ||||
| fragmentation. */ | ||||
| static size_t xFreeBytesRemaining = 0U; | ||||
| static size_t xMinimumEverFreeBytesRemaining = 0U; | ||||
|  | ||||
| /* Gets set to the top bit of an size_t type.  When this bit in the xBlockSize | ||||
| member of an BlockLink_t structure is set then the block belongs to the | ||||
| application.  When the bit is free the block is still part of the free heap | ||||
| space. */ | ||||
| static size_t xBlockAllocatedBit = 0; | ||||
|  | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void *pvPortMalloc( size_t xWantedSize ) | ||||
| { | ||||
| BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; | ||||
| void *pvReturn = NULL; | ||||
|  | ||||
| 	vTaskSuspendAll(); | ||||
| 	{ | ||||
| 		/* If this is the first call to malloc then the heap will require | ||||
| 		initialisation to setup the list of free blocks. */ | ||||
| 		if( pxEnd == NULL ) | ||||
| 		{ | ||||
| 			prvHeapInit(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			mtCOVERAGE_TEST_MARKER(); | ||||
| 		} | ||||
|  | ||||
| 		/* Check the requested block size is not so large that the top bit is | ||||
| 		set.  The top bit of the block size member of the BlockLink_t structure | ||||
| 		is used to determine who owns the block - the application or the | ||||
| 		kernel, so it must be free. */ | ||||
| 		if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) | ||||
| 		{ | ||||
| 			/* The wanted size is increased so it can contain a BlockLink_t | ||||
| 			structure in addition to the requested amount of bytes. */ | ||||
| 			if( xWantedSize > 0 ) | ||||
| 			{ | ||||
| 				xWantedSize += xHeapStructSize; | ||||
|  | ||||
| 				/* Ensure that blocks are always aligned to the required number | ||||
| 				of bytes. */ | ||||
| 				if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) | ||||
| 				{ | ||||
| 					/* Byte alignment required. */ | ||||
| 					xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); | ||||
| 					configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					mtCOVERAGE_TEST_MARKER(); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				mtCOVERAGE_TEST_MARKER(); | ||||
| 			} | ||||
|  | ||||
| 			if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) | ||||
| 			{ | ||||
| 				/* Traverse the list from the start	(lowest address) block until | ||||
| 				one	of adequate size is found. */ | ||||
| 				pxPreviousBlock = &xStart; | ||||
| 				pxBlock = xStart.pxNextFreeBlock; | ||||
| 				while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) | ||||
| 				{ | ||||
| 					pxPreviousBlock = pxBlock; | ||||
| 					pxBlock = pxBlock->pxNextFreeBlock; | ||||
| 				} | ||||
|  | ||||
| 				/* If the end marker was reached then a block of adequate size | ||||
| 				was	not found. */ | ||||
| 				if( pxBlock != pxEnd ) | ||||
| 				{ | ||||
| 					/* Return the memory space pointed to - jumping over the | ||||
| 					BlockLink_t structure at its start. */ | ||||
| 					pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize ); | ||||
|  | ||||
| 					/* This block is being returned for use so must be taken out | ||||
| 					of the list of free blocks. */ | ||||
| 					pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; | ||||
|  | ||||
| 					/* If the block is larger than required it can be split into | ||||
| 					two. */ | ||||
| 					if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) | ||||
| 					{ | ||||
| 						/* This block is to be split into two.  Create a new | ||||
| 						block following the number of bytes requested. The void | ||||
| 						cast is used to prevent byte alignment warnings from the | ||||
| 						compiler. */ | ||||
| 						pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); | ||||
| 						configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); | ||||
|  | ||||
| 						/* Calculate the sizes of two blocks split from the | ||||
| 						single block. */ | ||||
| 						pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; | ||||
| 						pxBlock->xBlockSize = xWantedSize; | ||||
|  | ||||
| 						/* Insert the new block into the list of free blocks. */ | ||||
| 						prvInsertBlockIntoFreeList( pxNewBlockLink ); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						mtCOVERAGE_TEST_MARKER(); | ||||
| 					} | ||||
|  | ||||
| 					xFreeBytesRemaining -= pxBlock->xBlockSize; | ||||
|  | ||||
| 					if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) | ||||
| 					{ | ||||
| 						xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						mtCOVERAGE_TEST_MARKER(); | ||||
| 					} | ||||
|  | ||||
| 					/* The block is being returned - it is allocated and owned | ||||
| 					by the application and has no "next" block. */ | ||||
| 					pxBlock->xBlockSize |= xBlockAllocatedBit; | ||||
| 					pxBlock->pxNextFreeBlock = NULL; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					mtCOVERAGE_TEST_MARKER(); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				mtCOVERAGE_TEST_MARKER(); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			mtCOVERAGE_TEST_MARKER(); | ||||
| 		} | ||||
|  | ||||
| 		traceMALLOC( pvReturn, xWantedSize ); | ||||
| 	} | ||||
| 	( void ) xTaskResumeAll(); | ||||
|  | ||||
| 	#if( configUSE_MALLOC_FAILED_HOOK == 1 ) | ||||
| 	{ | ||||
| 		if( pvReturn == NULL ) | ||||
| 		{ | ||||
| 			extern void vApplicationMallocFailedHook( void ); | ||||
| 			vApplicationMallocFailedHook(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			mtCOVERAGE_TEST_MARKER(); | ||||
| 		} | ||||
| 	} | ||||
| 	#endif | ||||
|  | ||||
| 	configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 ); | ||||
| 	return pvReturn; | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void vPortFree( void *pv ) | ||||
| { | ||||
| uint8_t *puc = ( uint8_t * ) pv; | ||||
| BlockLink_t *pxLink; | ||||
|  | ||||
| 	if( pv != NULL ) | ||||
| 	{ | ||||
| 		/* The memory being freed will have an BlockLink_t structure immediately | ||||
| 		before it. */ | ||||
| 		puc -= xHeapStructSize; | ||||
|  | ||||
| 		/* This casting is to keep the compiler from issuing warnings. */ | ||||
| 		pxLink = ( void * ) puc; | ||||
|  | ||||
| 		/* Check the block is actually allocated. */ | ||||
| 		configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); | ||||
| 		configASSERT( pxLink->pxNextFreeBlock == NULL ); | ||||
|  | ||||
| 		if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) | ||||
| 		{ | ||||
| 			if( pxLink->pxNextFreeBlock == NULL ) | ||||
| 			{ | ||||
| 				/* The block is being returned to the heap - it is no longer | ||||
| 				allocated. */ | ||||
| 				pxLink->xBlockSize &= ~xBlockAllocatedBit; | ||||
|  | ||||
| 				vTaskSuspendAll(); | ||||
| 				{ | ||||
| 					/* Add this block to the list of free blocks. */ | ||||
| 					xFreeBytesRemaining += pxLink->xBlockSize; | ||||
| 					traceFREE( pv, pxLink->xBlockSize ); | ||||
| 					prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); | ||||
| 				} | ||||
| 				( void ) xTaskResumeAll(); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				mtCOVERAGE_TEST_MARKER(); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			mtCOVERAGE_TEST_MARKER(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| size_t xPortGetFreeHeapSize( void ) | ||||
| { | ||||
| 	return xFreeBytesRemaining; | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| size_t xPortGetMinimumEverFreeHeapSize( void ) | ||||
| { | ||||
| 	return xMinimumEverFreeBytesRemaining; | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| void vPortInitialiseBlocks( void ) | ||||
| { | ||||
| 	/* This just exists to keep the linker quiet. */ | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| static void prvHeapInit( void ) | ||||
| { | ||||
| BlockLink_t *pxFirstFreeBlock; | ||||
| uint8_t *pucAlignedHeap; | ||||
| size_t uxAddress; | ||||
| size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; | ||||
|  | ||||
| 	/* Ensure the heap starts on a correctly aligned boundary. */ | ||||
| 	uxAddress = ( size_t ) ucHeap; | ||||
|  | ||||
| 	if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) | ||||
| 	{ | ||||
| 		uxAddress += ( portBYTE_ALIGNMENT - 1 ); | ||||
| 		uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); | ||||
| 		xTotalHeapSize -= uxAddress - ( size_t ) ucHeap; | ||||
| 	} | ||||
|  | ||||
| 	pucAlignedHeap = ( uint8_t * ) uxAddress; | ||||
|  | ||||
| 	/* xStart is used to hold a pointer to the first item in the list of free | ||||
| 	blocks.  The void cast is used to prevent compiler warnings. */ | ||||
| 	xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; | ||||
| 	xStart.xBlockSize = ( size_t ) 0; | ||||
|  | ||||
| 	/* pxEnd is used to mark the end of the list of free blocks and is inserted | ||||
| 	at the end of the heap space. */ | ||||
| 	uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize; | ||||
| 	uxAddress -= xHeapStructSize; | ||||
| 	uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); | ||||
| 	pxEnd = ( void * ) uxAddress; | ||||
| 	pxEnd->xBlockSize = 0; | ||||
| 	pxEnd->pxNextFreeBlock = NULL; | ||||
|  | ||||
| 	/* To start with there is a single free block that is sized to take up the | ||||
| 	entire heap space, minus the space taken by pxEnd. */ | ||||
| 	pxFirstFreeBlock = ( void * ) pucAlignedHeap; | ||||
| 	pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock; | ||||
| 	pxFirstFreeBlock->pxNextFreeBlock = pxEnd; | ||||
|  | ||||
| 	/* Only one block exists - and it covers the entire usable heap space. */ | ||||
| 	xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; | ||||
| 	xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; | ||||
|  | ||||
| 	/* Work out the position of the top bit in a size_t variable. */ | ||||
| 	xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); | ||||
| } | ||||
| /*-----------------------------------------------------------*/ | ||||
|  | ||||
| static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) | ||||
| { | ||||
| BlockLink_t *pxIterator; | ||||
| uint8_t *puc; | ||||
|  | ||||
| 	/* Iterate through the list until a block is found that has a higher address | ||||
| 	than the block being inserted. */ | ||||
| 	for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) | ||||
| 	{ | ||||
| 		/* Nothing to do here, just iterate to the right position. */ | ||||
| 	} | ||||
|  | ||||
| 	/* Do the block being inserted, and the block it is being inserted after | ||||
| 	make a contiguous block of memory? */ | ||||
| 	puc = ( uint8_t * ) pxIterator; | ||||
| 	if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) | ||||
| 	{ | ||||
| 		pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; | ||||
| 		pxBlockToInsert = pxIterator; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		mtCOVERAGE_TEST_MARKER(); | ||||
| 	} | ||||
|  | ||||
| 	/* Do the block being inserted, and the block it is being inserted before | ||||
| 	make a contiguous block of memory? */ | ||||
| 	puc = ( uint8_t * ) pxBlockToInsert; | ||||
| 	if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) | ||||
| 	{ | ||||
| 		if( pxIterator->pxNextFreeBlock != pxEnd ) | ||||
| 		{ | ||||
| 			/* Form one big block from the two blocks. */ | ||||
| 			pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; | ||||
| 			pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			pxBlockToInsert->pxNextFreeBlock = pxEnd; | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; | ||||
| 	} | ||||
|  | ||||
| 	/* If the block being inserted plugged a gab, so was merged with the block | ||||
| 	before and the block after, then it's pxNextFreeBlock pointer will have | ||||
| 	already been set, and should not be set here as that would make it point | ||||
| 	to itself. */ | ||||
| 	if( pxIterator != pxBlockToInsert ) | ||||
| 	{ | ||||
| 		pxIterator->pxNextFreeBlock = pxBlockToInsert; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		mtCOVERAGE_TEST_MARKER(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user