forked from epagris/FreeRTOS-Kernel
		
	Test the RTC and BURTC tickless implementations on the Gecko parts, and make correct as appropriate.
Replace some references to the older portTICK_RATE_MS macro with the newer pdMS_TO_TICKS() macro in the standard demo files.
This commit is contained in:
		
							parent
							
								
									556de14a1d
								
							
						
					
					
						commit
						732778a971
					
				@ -103,9 +103,6 @@
 | 
			
		||||
							<tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.archiver.base.1920617400" name="GNU ARM Archiver" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.archiver.base"/>
 | 
			
		||||
						</toolChain>
 | 
			
		||||
					</folderInfo>
 | 
			
		||||
					<fileInfo id="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129.566130702" name="low_power_tick_management_BURTC.c" rcbsApplicability="disable" resourcePath="Source/Low_Power_Demo/low_power_tick_management_BURTC.c" toolsToInvoke="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.base.1299820402.669016646">
 | 
			
		||||
						<tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.base.1299820402.669016646" name="GNU ARM C Compiler" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.base.1299820402"/>
 | 
			
		||||
					</fileInfo>
 | 
			
		||||
					<sourceEntries>
 | 
			
		||||
						<entry excluding="Source/FreeRTOS_Source/portable/GCC/ARM_CM4F|Source/SilLabs_Code/kits/EFM32WG_STK3800|Source/SilLabs_Code/Device/SiliconLabs/EFM32GG/Source|Source/SilLabs_Code/Device/SiliconLabs/EFM32WG|Source/SilLabs_Code/CMSIS/efm32wg|CMSIS/efm32wg|Source/SilLabs_Code/kits/bsp/bsp_dk_3201.c|Source/SilLabs_Code/kits/bsp/bsp_dk_3200.c|Source/SilLabs_Code/kits/bsp/bsp_dk_leds.c|Source/RTT|Source/SilLabs_Code/kits/bsp/bsp_dk_mcuboard.c|Source/SilLabs_Code/kits/bsp/bsp_bcc.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
 | 
			
		||||
					</sourceEntries>
 | 
			
		||||
 | 
			
		||||
@ -99,7 +99,7 @@ extern "C" {
 | 
			
		||||
 *  See the comments at the top of main.c, main_full.c and main_low_power.c for
 | 
			
		||||
 *  more information.
 | 
			
		||||
 */
 | 
			
		||||
#define configCREATE_LOW_POWER_DEMO	2
 | 
			
		||||
#define configCREATE_LOW_POWER_DEMO	1
 | 
			
		||||
 | 
			
		||||
/* Some configuration is dependent on the demo being built. */
 | 
			
		||||
#if( configCREATE_LOW_POWER_DEMO == 0 )
 | 
			
		||||
@ -142,7 +142,7 @@ extern "C" {
 | 
			
		||||
	#define configUSE_MALLOC_FAILED_HOOK	( 0 )
 | 
			
		||||
	#define configUSE_IDLE_HOOK				( 0 )
 | 
			
		||||
 | 
			
		||||
	#define configENERGY_MODE				( sleepEM4 )
 | 
			
		||||
	#define configENERGY_MODE				( sleepEM3 )
 | 
			
		||||
 | 
			
		||||
#elif( configCREATE_LOW_POWER_DEMO == 2 )
 | 
			
		||||
 | 
			
		||||
@ -198,9 +198,31 @@ extern "C" {
 | 
			
		||||
#define configTIMER_QUEUE_LENGTH				( 10 )
 | 
			
		||||
#define configTIMER_TASK_STACK_DEPTH			( configMINIMAL_STACK_SIZE )
 | 
			
		||||
 | 
			
		||||
/* Interrupt nesting behaviour configuration. */
 | 
			
		||||
#define configKERNEL_INTERRUPT_PRIORITY			( 255 )
 | 
			
		||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY	( 191 ) /* equivalent to 0xa0, or priority 5. */
 | 
			
		||||
/* Cortex-M specific definitions. */
 | 
			
		||||
#ifdef __NVIC_PRIO_BITS
 | 
			
		||||
	/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
 | 
			
		||||
	#define configPRIO_BITS		       __NVIC_PRIO_BITS
 | 
			
		||||
#else
 | 
			
		||||
	#define configPRIO_BITS		       3	/* 7 priority levels */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The lowest interrupt priority that can be used in a call to a "set priority"
 | 
			
		||||
function. */
 | 
			
		||||
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			0x07
 | 
			
		||||
 | 
			
		||||
/* The highest interrupt priority that can be used by any interrupt service
 | 
			
		||||
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
 | 
			
		||||
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
 | 
			
		||||
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
 | 
			
		||||
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	0x05
 | 
			
		||||
 | 
			
		||||
/* Interrupt priorities used by the kernel port layer itself.  These are generic
 | 
			
		||||
to all Cortex-M ports, and do not rely on any particular library functions. */
 | 
			
		||||
#define configKERNEL_INTERRUPT_PRIORITY		 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
 | 
			
		||||
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
 | 
			
		||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
 | 
			
		||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY	 ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Optional functions - most linkers will remove unused functions anyway. */
 | 
			
		||||
#define INCLUDE_vTaskPrioritySet				( 1 )
 | 
			
		||||
 | 
			
		||||
@ -150,7 +150,7 @@ BURTC_Init_TypeDef xBURTCInitStruct = BURTC_INIT_DEFAULT;
 | 
			
		||||
	BURTC_Init( &xBURTCInitStruct );
 | 
			
		||||
 | 
			
		||||
	/* The tick interrupt must be set to the lowest priority possible. */
 | 
			
		||||
	NVIC_SetPriority( BURTC_IRQn, configKERNEL_INTERRUPT_PRIORITY );
 | 
			
		||||
	NVIC_SetPriority( BURTC_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY );
 | 
			
		||||
	NVIC_ClearPendingIRQ( BURTC_IRQn );
 | 
			
		||||
	NVIC_EnableIRQ( BURTC_IRQn );
 | 
			
		||||
	BURTC_CompareSet( 0, ulReloadValueForOneTick );
 | 
			
		||||
@ -162,7 +162,7 @@ BURTC_Init_TypeDef xBURTCInitStruct = BURTC_INIT_DEFAULT;
 | 
			
		||||
 | 
			
		||||
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
 | 
			
		||||
{
 | 
			
		||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCurrentCount;
 | 
			
		||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCountBeforeSleep, ulCountAfterSleep;
 | 
			
		||||
eSleepModeStatus eSleepAction;
 | 
			
		||||
TickType_t xModifiableIdleTime;
 | 
			
		||||
 | 
			
		||||
@ -189,12 +189,20 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
	result in some tiny drift of the time maintained by the kernel with respect
 | 
			
		||||
	to calendar time.  The count is latched before stopping the timer as
 | 
			
		||||
	stopping the timer appears to clear the count. */
 | 
			
		||||
	ulCurrentCount = BURTC_CounterGet();
 | 
			
		||||
	ulCountBeforeSleep = BURTC_CounterGet();
 | 
			
		||||
	BURTC_Enable( false );
 | 
			
		||||
 | 
			
		||||
	/* If this function is re-entered before one complete tick period then the
 | 
			
		||||
	reload value might be to take into account a partial tick, but just reading
 | 
			
		||||
	the count assumes it is counting up to a full ticks worth - so add in the
 | 
			
		||||
	different if any. */
 | 
			
		||||
	ulCountBeforeSleep += ( ulReloadValueForOneTick - BURTC_CompareGet( 0 ) );
 | 
			
		||||
 | 
			
		||||
	/* Enter a critical section but don't use the taskENTER_CRITICAL() method as
 | 
			
		||||
	that will mask interrupts that should exit sleep mode. */
 | 
			
		||||
	INT_Disable();
 | 
			
		||||
	__asm volatile( "dsb" );
 | 
			
		||||
	__asm volatile( "isb" );
 | 
			
		||||
 | 
			
		||||
	/* The tick flag is set to false before sleeping.  If it is true when sleep
 | 
			
		||||
	mode is exited then sleep mode was probably exited because the tick was
 | 
			
		||||
@ -209,7 +217,7 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
	{
 | 
			
		||||
		/* Restart tick and count up to whatever was left of the current time
 | 
			
		||||
		slice. */
 | 
			
		||||
		BURTC_CompareSet( 0, ulReloadValueForOneTick - ulCurrentCount );
 | 
			
		||||
		BURTC_CompareSet( 0, ( ulReloadValueForOneTick - ulCountBeforeSleep ) + ulStoppedTimerCompensation );
 | 
			
		||||
		BURTC_Enable( true );
 | 
			
		||||
 | 
			
		||||
		/* Re-enable interrupts - see comments above the cpsid instruction()
 | 
			
		||||
@ -220,7 +228,7 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
	{
 | 
			
		||||
		/* Adjust the reload value to take into account that the current time
 | 
			
		||||
		slice is already partially complete. */
 | 
			
		||||
		ulReloadValue -= ulCurrentCount;
 | 
			
		||||
		ulReloadValue -= ulCountBeforeSleep;
 | 
			
		||||
		BURTC_CompareSet( 0, ulReloadValue );
 | 
			
		||||
 | 
			
		||||
		/* Restart the BURTC. */
 | 
			
		||||
@ -248,12 +256,14 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
		result in some tiny drift of the time maintained by the	kernel with
 | 
			
		||||
		respect to calendar time.  The count value is latched before stopping
 | 
			
		||||
		the timer as stopping the timer appears to clear the count. */
 | 
			
		||||
		ulCurrentCount = BURTC_CounterGet();
 | 
			
		||||
		ulCountAfterSleep = BURTC_CounterGet();
 | 
			
		||||
		BURTC_Enable( false );
 | 
			
		||||
 | 
			
		||||
		/* Re-enable interrupts - see comments above the cpsid instruction()
 | 
			
		||||
		above. */
 | 
			
		||||
		INT_Enable();
 | 
			
		||||
		__asm volatile( "dsb" );
 | 
			
		||||
		__asm volatile( "isb" );
 | 
			
		||||
 | 
			
		||||
		if( ulTickFlag != pdFALSE )
 | 
			
		||||
		{
 | 
			
		||||
@ -261,7 +271,7 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
			function is called with the scheduler suspended the actual tick
 | 
			
		||||
			processing will not occur until after this function has exited.
 | 
			
		||||
			Reset the reload value with whatever remains of this tick period. */
 | 
			
		||||
			ulReloadValue = ulReloadValueForOneTick - ulCurrentCount;
 | 
			
		||||
			ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;
 | 
			
		||||
			BURTC_CompareSet( 0, ulReloadValue );
 | 
			
		||||
 | 
			
		||||
			/* The tick interrupt handler will already have pended the tick
 | 
			
		||||
@ -275,12 +285,17 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
		{
 | 
			
		||||
			/* Something other than the tick interrupt ended the sleep.  How
 | 
			
		||||
			many complete tick periods passed while the processor was
 | 
			
		||||
			sleeping? */
 | 
			
		||||
			ulCompleteTickPeriods = ulCurrentCount / ulReloadValueForOneTick;
 | 
			
		||||
			sleeping?  Add back in the adjustment that was made to the reload
 | 
			
		||||
			value to account for the fact that a time slice was part way through
 | 
			
		||||
			when this function was called. */
 | 
			
		||||
			ulCountAfterSleep += ulCountBeforeSleep;
 | 
			
		||||
			ulCompleteTickPeriods = ulCountAfterSleep / ulReloadValueForOneTick;
 | 
			
		||||
 | 
			
		||||
			/* The reload value is set to whatever fraction of a single tick
 | 
			
		||||
			period remains. */
 | 
			
		||||
			ulReloadValue = ulCurrentCount - ( ulCompleteTickPeriods * ulReloadValueForOneTick );
 | 
			
		||||
			ulCountAfterSleep -= ( ulCompleteTickPeriods * ulReloadValueForOneTick );
 | 
			
		||||
			ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;
 | 
			
		||||
 | 
			
		||||
			if( ulReloadValue == 0 )
 | 
			
		||||
			{
 | 
			
		||||
				/* There is no fraction remaining. */
 | 
			
		||||
@ -305,12 +320,13 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
 | 
			
		||||
void BURTC_IRQHandler( void )
 | 
			
		||||
{
 | 
			
		||||
	if( ulTickFlag == pdFALSE )
 | 
			
		||||
	ulTickFlag = pdTRUE;
 | 
			
		||||
 | 
			
		||||
	if( RTC_CompareGet( 0 ) != ulReloadValueForOneTick )
 | 
			
		||||
	{
 | 
			
		||||
		/* Set BURTC interrupt to one RTOS tick period. */
 | 
			
		||||
		/* Set RTC interrupt to one RTOS tick period. */
 | 
			
		||||
		BURTC_Enable( false );
 | 
			
		||||
		BURTC_CompareSet( 0, ulReloadValueForOneTick );
 | 
			
		||||
		ulTickFlag = pdTRUE;
 | 
			
		||||
		BURTC_Enable( true );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -74,10 +74,13 @@
 | 
			
		||||
/* SiLabs library includes. */
 | 
			
		||||
#include "em_cmu.h"
 | 
			
		||||
#include "em_rtc.h"
 | 
			
		||||
#include "em_burtc.h"
 | 
			
		||||
#include "em_rmu.h"
 | 
			
		||||
#include "em_int.h"
 | 
			
		||||
#include "sleep.h"
 | 
			
		||||
 | 
			
		||||
#define lpINCLUDE_TEST_TIMER	1
 | 
			
		||||
 | 
			
		||||
/* SEE THE COMMENTS ABOVE THE DEFINITION OF configCREATE_LOW_POWER_DEMO IN
 | 
			
		||||
FreeRTOSConfig.h
 | 
			
		||||
This file contains functions that will override the default implementations
 | 
			
		||||
@ -103,6 +106,14 @@ void vPortSetupTimerInterrupt( void );
 | 
			
		||||
 */
 | 
			
		||||
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
 | 
			
		||||
 | 
			
		||||
/* If lpINCLUDE_TEST_TIMER is defined then the BURTC is used to generate
 | 
			
		||||
interrupts that will wake the processor prior to the expected idle time
 | 
			
		||||
completing.  The timer interval can be altered to test different
 | 
			
		||||
scenarios. */
 | 
			
		||||
#if( lpINCLUDE_TEST_TIMER == 1 )
 | 
			
		||||
	static void prvSetupTestTimer( void );
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Calculate how many clock increments make up a single tick period. */
 | 
			
		||||
@ -155,19 +166,27 @@ const uint32_t ulMAX24BitValue = 0xffffffUL;
 | 
			
		||||
	RTC_IntDisable( RTC_IFC_COMP0 );
 | 
			
		||||
 | 
			
		||||
	/* The tick interrupt must be set to the lowest priority possible. */
 | 
			
		||||
	NVIC_SetPriority( RTC_IRQn, configKERNEL_INTERRUPT_PRIORITY );
 | 
			
		||||
	NVIC_SetPriority( RTC_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY );
 | 
			
		||||
	NVIC_ClearPendingIRQ( RTC_IRQn );
 | 
			
		||||
	NVIC_EnableIRQ( RTC_IRQn );
 | 
			
		||||
	RTC_CompareSet( 0, ulReloadValueForOneTick );
 | 
			
		||||
	RTC_IntClear( RTC_IFC_COMP0 );
 | 
			
		||||
	RTC_IntEnable( RTC_IF_COMP0 );
 | 
			
		||||
	RTC_Enable( true );
 | 
			
		||||
 | 
			
		||||
	/* If lpINCLUDE_TEST_TIMER is defined then the BURTC is used to generate
 | 
			
		||||
	interrupts that will wake the processor prior to the expected idle time
 | 
			
		||||
	completing.  The timer interval can be altered to test different
 | 
			
		||||
	scenarios. */
 | 
			
		||||
	#if( lpINCLUDE_TEST_TIMER == 1 )
 | 
			
		||||
		prvSetupTestTimer();
 | 
			
		||||
	#endif
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
 | 
			
		||||
{
 | 
			
		||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCurrentCount;
 | 
			
		||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCountBeforeSleep, ulCountAfterSleep;
 | 
			
		||||
eSleepModeStatus eSleepAction;
 | 
			
		||||
TickType_t xModifiableIdleTime;
 | 
			
		||||
 | 
			
		||||
@ -194,9 +213,15 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
	in some tiny drift of the time maintained by the kernel with respect to
 | 
			
		||||
	calendar time.  The count is latched before stopping the timer as stopping
 | 
			
		||||
	the timer appears to clear the count. */
 | 
			
		||||
	ulCurrentCount = RTC_CounterGet();
 | 
			
		||||
	ulCountBeforeSleep = RTC_CounterGet();
 | 
			
		||||
	RTC_Enable( false );
 | 
			
		||||
 | 
			
		||||
	/* If this function is re-entered before one complete tick period then the
 | 
			
		||||
	reload value might be to take into account a partial tick, but just reading
 | 
			
		||||
	the count assumes it is counting up to a full ticks worth - so add in the
 | 
			
		||||
	different if any. */
 | 
			
		||||
	ulCountBeforeSleep += ( ulReloadValueForOneTick - RTC_CompareGet( 0 ) );
 | 
			
		||||
 | 
			
		||||
	/* Enter a critical section but don't use the taskENTER_CRITICAL() method as
 | 
			
		||||
	that will mask interrupts that should exit sleep mode. */
 | 
			
		||||
	INT_Disable();
 | 
			
		||||
@ -216,7 +241,7 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
	{
 | 
			
		||||
		/* Restart tick and count up to whatever was left of the current time
 | 
			
		||||
		slice. */
 | 
			
		||||
		RTC_CompareSet( 0, ulReloadValueForOneTick - ulCurrentCount );
 | 
			
		||||
		RTC_CompareSet( 0, ( ulReloadValueForOneTick - ulCountBeforeSleep ) + ulStoppedTimerCompensation );
 | 
			
		||||
		RTC_Enable( true );
 | 
			
		||||
 | 
			
		||||
		/* Re-enable interrupts - see comments above the cpsid instruction()
 | 
			
		||||
@ -227,7 +252,7 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
	{
 | 
			
		||||
		/* Adjust the reload value to take into account that the current time
 | 
			
		||||
		slice is already partially complete. */
 | 
			
		||||
		ulReloadValue -= ulCurrentCount;
 | 
			
		||||
		ulReloadValue -= ulCountBeforeSleep;
 | 
			
		||||
		RTC_CompareSet( 0, ulReloadValue );
 | 
			
		||||
 | 
			
		||||
		/* Restart the RTC. */
 | 
			
		||||
@ -255,7 +280,7 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
		result in some tiny drift of the time maintained by the	kernel with
 | 
			
		||||
		respect to calendar time.  The count value is latched before stopping
 | 
			
		||||
		the timer as stopping the timer appears to clear the count. */
 | 
			
		||||
		ulCurrentCount = RTC_CounterGet();
 | 
			
		||||
		ulCountAfterSleep = RTC_CounterGet();
 | 
			
		||||
		RTC_Enable( false );
 | 
			
		||||
 | 
			
		||||
		/* Re-enable interrupts - see comments above the cpsid instruction()
 | 
			
		||||
@ -270,7 +295,7 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
			function is called with the scheduler suspended the actual tick
 | 
			
		||||
			processing will not occur until after this function has exited.
 | 
			
		||||
			Reset the reload value with whatever remains of this tick period. */
 | 
			
		||||
			ulReloadValue = ulReloadValueForOneTick - ulCurrentCount;
 | 
			
		||||
			ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;
 | 
			
		||||
			RTC_CompareSet( 0, ulReloadValue );
 | 
			
		||||
 | 
			
		||||
			/* The tick interrupt handler will already have pended the tick
 | 
			
		||||
@ -284,12 +309,17 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
		{
 | 
			
		||||
			/* Something other than the tick interrupt ended the sleep.  How
 | 
			
		||||
			many complete tick periods passed while the processor was
 | 
			
		||||
			sleeping? */
 | 
			
		||||
			ulCompleteTickPeriods = ulCurrentCount / ulReloadValueForOneTick;
 | 
			
		||||
			sleeping?  Add back in the adjustment that was made to the reload
 | 
			
		||||
			value to account for the fact that a time slice was part way through
 | 
			
		||||
			when this function was called. */
 | 
			
		||||
			ulCountAfterSleep += ulCountBeforeSleep;
 | 
			
		||||
			ulCompleteTickPeriods = ulCountAfterSleep / ulReloadValueForOneTick;
 | 
			
		||||
 | 
			
		||||
			/* The reload value is set to whatever fraction of a single tick
 | 
			
		||||
			period remains. */
 | 
			
		||||
			ulReloadValue = ulCurrentCount - ( ulCompleteTickPeriods * ulReloadValueForOneTick );
 | 
			
		||||
			ulCountAfterSleep -= ( ulCompleteTickPeriods * ulReloadValueForOneTick );
 | 
			
		||||
			ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;
 | 
			
		||||
 | 
			
		||||
			if( ulReloadValue == 0 )
 | 
			
		||||
			{
 | 
			
		||||
				/* There is no fraction remaining. */
 | 
			
		||||
@ -314,12 +344,13 @@ TickType_t xModifiableIdleTime;
 | 
			
		||||
 | 
			
		||||
void RTC_IRQHandler( void )
 | 
			
		||||
{
 | 
			
		||||
	if( ulTickFlag == pdFALSE )
 | 
			
		||||
	ulTickFlag = pdTRUE;
 | 
			
		||||
 | 
			
		||||
	if( RTC_CompareGet( 0 ) != ulReloadValueForOneTick )
 | 
			
		||||
	{
 | 
			
		||||
		/* Set RTC interrupt to one RTOS tick period. */
 | 
			
		||||
		RTC_Enable( false );
 | 
			
		||||
		RTC_CompareSet( 0, ulReloadValueForOneTick );
 | 
			
		||||
		ulTickFlag = pdTRUE;
 | 
			
		||||
		RTC_Enable( true );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -336,6 +367,64 @@ void RTC_IRQHandler( void )
 | 
			
		||||
	}
 | 
			
		||||
	portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#endif /* ( configCREATE_LOW_POWER_DEMO == 1 ) */
 | 
			
		||||
#if( lpINCLUDE_TEST_TIMER == 1 )
 | 
			
		||||
 | 
			
		||||
	/* If lpINCLUDE_TEST_TIMER is defined then the BURTC is used to generate
 | 
			
		||||
	interrupts that will wake the processor prior to the expected idle time
 | 
			
		||||
	completing.  The timer interval can be altered to test different
 | 
			
		||||
	scenarios. */
 | 
			
		||||
	static void prvSetupTestTimer( void )
 | 
			
		||||
	{
 | 
			
		||||
	BURTC_Init_TypeDef xBURTCInitStruct = BURTC_INIT_DEFAULT;
 | 
			
		||||
	const uint32_t ulBURTClockHz = 2000UL, ulInterruptFrequency = 1000UL;
 | 
			
		||||
	const uint32_t ulReload = ( ulBURTClockHz / ulInterruptFrequency );
 | 
			
		||||
 | 
			
		||||
		/* Ensure LE modules are accessible. */
 | 
			
		||||
		CMU_ClockEnable( cmuClock_CORELE, true );
 | 
			
		||||
 | 
			
		||||
		/* Enable access to BURTC registers. */
 | 
			
		||||
		RMU_ResetControl( rmuResetBU, false );
 | 
			
		||||
 | 
			
		||||
		/* Generate periodic interrupts from BURTC. */
 | 
			
		||||
		xBURTCInitStruct.mode   = burtcModeEM3;		/* Operational in EM3. */
 | 
			
		||||
		xBURTCInitStruct.clkSel = burtcClkSelULFRCO;/* ULFRCO clock. */
 | 
			
		||||
		xBURTCInitStruct.clkDiv = burtcClkDiv_1;	/* 2kHz ULFRCO clock. */
 | 
			
		||||
		xBURTCInitStruct.compare0Top = true;		/* Wrap on COMP0. */
 | 
			
		||||
		BURTC_IntDisable( BURTC_IF_COMP0 );
 | 
			
		||||
		BURTC_Init( &xBURTCInitStruct );
 | 
			
		||||
 | 
			
		||||
		NVIC_SetPriority( BURTC_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY );
 | 
			
		||||
		NVIC_ClearPendingIRQ( BURTC_IRQn );
 | 
			
		||||
		NVIC_EnableIRQ( BURTC_IRQn );
 | 
			
		||||
		BURTC_CompareSet( 0, ulReload );
 | 
			
		||||
		BURTC_IntClear( BURTC_IF_COMP0 );
 | 
			
		||||
		BURTC_IntEnable( BURTC_IF_COMP0 );
 | 
			
		||||
		BURTC_CounterReset();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if( lpINCLUDE_TEST_TIMER == 1 )
 | 
			
		||||
 | 
			
		||||
	/* If lpINCLUDE_TEST_TIMER is defined then the BURTC is used to generate
 | 
			
		||||
	interrupts that will wake the processor prior to the expected idle time
 | 
			
		||||
	completing.  The timer interval can be altered to test different
 | 
			
		||||
	scenarios. */
 | 
			
		||||
	volatile uint32_t ulTestTimerCounts = 0;
 | 
			
		||||
 | 
			
		||||
	void BURTC_IRQHandler( void )
 | 
			
		||||
	{
 | 
			
		||||
		/* Nothing to do here - just testing the code in the scenario where a
 | 
			
		||||
		tickless idle period is ended prior to the expected maximum idle time
 | 
			
		||||
		expiring. */
 | 
			
		||||
		BURTC_IntClear( _RTC_IFC_MASK );
 | 
			
		||||
		ulTestTimerCounts++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#endif /* ( configCREATE_LOW_POWER_DEMO == 2 ) */
 | 
			
		||||
 | 
			
		||||
@ -84,10 +84,22 @@
 | 
			
		||||
 * main_low_power() creates one queue, and two tasks.  It then starts the
 | 
			
		||||
 * scheduler.
 | 
			
		||||
 *
 | 
			
		||||
 * TBD
 | 
			
		||||
 * The Queue Send Task:
 | 
			
		||||
 * The queue send task is implemented by the prvQueueSendTask() function in
 | 
			
		||||
 * this file.  It sends the value 100 to the queue every second.
 | 
			
		||||
 *
 | 
			
		||||
 * The Queue Receive Task:
 | 
			
		||||
 * The queue receive task is implemented by the prvQueueReceiveTask() function
 | 
			
		||||
 * in this file.  prvQueueReceiveTask() blocks on the queue, blipping (quickly
 | 
			
		||||
 * turn on then off again) the LED each time it received the value 100 from the
 | 
			
		||||
 * queue send task.  The queue send task writes to the queue every second, so
 | 
			
		||||
 * the LED will blip once a second.
 | 
			
		||||
 *
 | 
			
		||||
 * The RTOS tick is turned off when the queue send task and queue receive task
 | 
			
		||||
 * are both in the Blocked state.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#warning Description of demo in comments above is not correct.
 | 
			
		||||
 | 
			
		||||
/* Kernel includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
 | 
			
		||||
@ -87,8 +87,6 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#warning Check the tick suppression routine in the case where the system unblocks before an entire tick period has expired.
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
@ -114,7 +112,7 @@ static void prvSetupHardware( void );
 | 
			
		||||
 * main_low_power() is used when configCREATE_LOW_POWER_DEMO is set to 1.
 | 
			
		||||
 * main_full() is used when configCREATE_LOW_POWER_DEMO is set to 0.
 | 
			
		||||
 */
 | 
			
		||||
#if( configCREATE_LOW_POWER_DEMO == 1 )
 | 
			
		||||
#if( configCREATE_LOW_POWER_DEMO != 0 )
 | 
			
		||||
	extern void main_low_power( void );
 | 
			
		||||
#else
 | 
			
		||||
	extern void main_full( void );
 | 
			
		||||
 | 
			
		||||
@ -136,7 +136,7 @@ xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2;
 | 
			
		||||
xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4;
 | 
			
		||||
xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6;
 | 
			
		||||
const UBaseType_t uxQueueSize1 = 1, uxQueueSize5 = 5;
 | 
			
		||||
const TickType_t xBlockTime = ( TickType_t ) 1000 / portTICK_PERIOD_MS;
 | 
			
		||||
const TickType_t xBlockTime = pdMS_TO_TICKS( ( TickType_t ) 1000 );
 | 
			
		||||
const TickType_t xDontBlock = ( TickType_t ) 0;
 | 
			
		||||
 | 
			
		||||
	/* Create the first two tasks as described at the top of the file. */
 | 
			
		||||
 | 
			
		||||
@ -122,7 +122,7 @@ that synchronise with the xEventGroupSync() function. */
 | 
			
		||||
#define ebDONT_BLOCK	( 0 )
 | 
			
		||||
 | 
			
		||||
/* A 5ms delay. */
 | 
			
		||||
#define ebSHORT_DELAY	( 5 / portTICK_PERIOD_MS )
 | 
			
		||||
#define ebSHORT_DELAY	pdMS_TO_TICKS( ( TickType_t ) 5 )
 | 
			
		||||
 | 
			
		||||
/* Used in the selective bits test which checks no, one or both tasks blocked on
 | 
			
		||||
event bits in a group are unblocked as appropriate as different bits get set. */
 | 
			
		||||
 | 
			
		||||
@ -109,7 +109,7 @@ Changes from V2.0.0
 | 
			
		||||
 | 
			
		||||
#define pollqSTACK_SIZE			configMINIMAL_STACK_SIZE
 | 
			
		||||
#define pollqQUEUE_SIZE			( 10 )
 | 
			
		||||
#define pollqPRODUCER_DELAY		( ( TickType_t ) 200 / portTICK_PERIOD_MS )
 | 
			
		||||
#define pollqPRODUCER_DELAY		( pdMS_TO_TICKS( ( TickType_t ) 200 ) )
 | 
			
		||||
#define pollqCONSUMER_DELAY		( pollqPRODUCER_DELAY - ( TickType_t ) ( 20 / portTICK_PERIOD_MS ) )
 | 
			
		||||
#define pollqNO_DELAY			( ( TickType_t ) 0 )
 | 
			
		||||
#define pollqVALUES_TO_PRODUCE	( ( BaseType_t ) 3 )
 | 
			
		||||
@ -135,10 +135,10 @@ static QueueHandle_t xPolledQueue;
 | 
			
		||||
	xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( UBaseType_t ) sizeof( uint16_t ) );
 | 
			
		||||
 | 
			
		||||
	/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
 | 
			
		||||
	in use.  The queue registry is provided as a means for kernel aware 
 | 
			
		||||
	in use.  The queue registry is provided as a means for kernel aware
 | 
			
		||||
	debuggers to locate queues and has no purpose if a kernel aware debugger
 | 
			
		||||
	is not being used.  The call to vQueueAddToRegistry() will be removed
 | 
			
		||||
	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is 
 | 
			
		||||
	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
 | 
			
		||||
	defined to be less than 1. */
 | 
			
		||||
	vQueueAddToRegistry( xPolledQueue, "Poll_Test_Queue" );
 | 
			
		||||
 | 
			
		||||
@ -154,7 +154,7 @@ uint16_t usValue = ( uint16_t ) 0;
 | 
			
		||||
BaseType_t xError = pdFALSE, xLoop;
 | 
			
		||||
 | 
			
		||||
	for( ;; )
 | 
			
		||||
	{		
 | 
			
		||||
	{
 | 
			
		||||
		for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ )
 | 
			
		||||
		{
 | 
			
		||||
			/* Send an incrementing number on the queue without blocking. */
 | 
			
		||||
@ -193,7 +193,7 @@ uint16_t usData, usExpectedValue = ( uint16_t ) 0;
 | 
			
		||||
BaseType_t xError = pdFALSE;
 | 
			
		||||
 | 
			
		||||
	for( ;; )
 | 
			
		||||
	{		
 | 
			
		||||
	{
 | 
			
		||||
		/* Loop until the queue is empty. */
 | 
			
		||||
		while( uxQueueMessagesWaiting( *( ( QueueHandle_t * ) pvParameters ) ) )
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
@ -122,7 +122,7 @@ queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */
 | 
			
		||||
/* A delay inserted when the Tx task changes its priority to be above the idle
 | 
			
		||||
task priority to ensure the idle priority tasks get some CPU time before the
 | 
			
		||||
next iteration of the queue set Tx task. */
 | 
			
		||||
#define queuesetTX_LOOP_DELAY	( 200 / portTICK_PERIOD_MS )
 | 
			
		||||
#define queuesetTX_LOOP_DELAY	pdMS_TO_TICKS( ( TickType_t ) 200 )
 | 
			
		||||
 | 
			
		||||
/* The allowable maximum deviation between a received value and the expected
 | 
			
		||||
received value.  A deviation will occur when data is received from a queue
 | 
			
		||||
@ -420,7 +420,7 @@ TickType_t xBlockTime;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Wait for a message to arrive on one of the queues in the set. */
 | 
			
		||||
		xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY );		
 | 
			
		||||
		xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY );
 | 
			
		||||
 | 
			
		||||
		if( xActivatedQueue == NULL )
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
@ -115,7 +115,7 @@ task can tell if any of the suicidal tasks have failed to die.
 | 
			
		||||
static volatile UBaseType_t uxTasksRunningAtStart = 0;
 | 
			
		||||
 | 
			
		||||
/* When a task deletes itself, it stack and TCB are cleaned up by the Idle task.
 | 
			
		||||
Under heavy load the idle task might not get much processing time, so it would 
 | 
			
		||||
Under heavy load the idle task might not get much processing time, so it would
 | 
			
		||||
be legitimate for several tasks to remain undeleted for a short period.  There
 | 
			
		||||
may also be a few other unexpected tasks if, for example, the tasks that test
 | 
			
		||||
static allocation are also being used. */
 | 
			
		||||
@ -141,15 +141,15 @@ UBaseType_t *puxPriority;
 | 
			
		||||
	/* Record the number of tasks that are running now so we know if any of the
 | 
			
		||||
	suicidal tasks have failed to be killed. */
 | 
			
		||||
	uxTasksRunningAtStart = ( UBaseType_t ) uxTaskGetNumberOfTasks();
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	/* FreeRTOS.org versions before V3.0 started the idle-task as the very
 | 
			
		||||
	first task. The idle task was then already included in uxTasksRunningAtStart.
 | 
			
		||||
	From FreeRTOS V3.0 on, the idle task is started when the scheduler is
 | 
			
		||||
	started. Therefore the idle task is not yet accounted for. We correct
 | 
			
		||||
	this by increasing uxTasksRunningAtStart by 1. */
 | 
			
		||||
	uxTasksRunningAtStart++;
 | 
			
		||||
	
 | 
			
		||||
	/* From FreeRTOS version 7.0.0 can optionally create a timer service task.  
 | 
			
		||||
 | 
			
		||||
	/* From FreeRTOS version 7.0.0 can optionally create a timer service task.
 | 
			
		||||
	If this is done, then uxTasksRunningAtStart needs incrementing again as that
 | 
			
		||||
	too is created when the scheduler is started. */
 | 
			
		||||
	#if configUSE_TIMERS == 1
 | 
			
		||||
@ -159,12 +159,12 @@ UBaseType_t *puxPriority;
 | 
			
		||||
	#endif
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
					
 | 
			
		||||
 | 
			
		||||
static portTASK_FUNCTION( vSuicidalTask, pvParameters )
 | 
			
		||||
{
 | 
			
		||||
volatile long l1, l2;
 | 
			
		||||
TaskHandle_t xTaskToKill;
 | 
			
		||||
const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS;
 | 
			
		||||
const TickType_t xDelay = pdMS_TO_TICKS( ( TickType_t ) 200 );
 | 
			
		||||
 | 
			
		||||
	if( pvParameters != NULL )
 | 
			
		||||
	{
 | 
			
		||||
@ -203,7 +203,7 @@ const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS;
 | 
			
		||||
 | 
			
		||||
static portTASK_FUNCTION( vCreateTasks, pvParameters )
 | 
			
		||||
{
 | 
			
		||||
const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS;
 | 
			
		||||
const TickType_t xDelay = pdMS_TO_TICKS( ( TickType_t ) 1000 );
 | 
			
		||||
UBaseType_t uxPriority;
 | 
			
		||||
 | 
			
		||||
	uxPriority = *( UBaseType_t * ) pvParameters;
 | 
			
		||||
@ -240,7 +240,7 @@ static UBaseType_t uxTasksRunningNow;
 | 
			
		||||
	{
 | 
			
		||||
		usLastCreationCount = usCreationCount;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	uxTasksRunningNow = ( UBaseType_t ) uxTaskGetNumberOfTasks();
 | 
			
		||||
 | 
			
		||||
	if( uxTasksRunningNow < uxTasksRunningAtStart )
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user