Tidy up STM32L low power demo and add 'comprehensive demo' option.
This commit is contained in:
parent
5638fe28a2
commit
751103d848
@ -49,7 +49,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>RunToEnable</name>
|
||||
<state>0</state>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>RunToName</name>
|
||||
|
@ -39,20 +39,20 @@
|
||||
<option>
|
||||
<name>Input variant</name>
|
||||
<version>3</version>
|
||||
<state>1</state>
|
||||
<state>7</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>Input description</name>
|
||||
<state>Full formatting.</state>
|
||||
<state>No specifier n, no float nor long long, no scan set, no assignment suppressing, without multibyte support.</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>Output variant</name>
|
||||
<version>2</version>
|
||||
<state>1</state>
|
||||
<state>7</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>Output description</name>
|
||||
<state>Full formatting.</state>
|
||||
<state>No specifier a, A, no specifier n, no float nor long long, no flags.</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GOutputBinary</name>
|
||||
@ -70,16 +70,16 @@
|
||||
<option>
|
||||
<name>GRuntimeLibSelect</name>
|
||||
<version>0</version>
|
||||
<state>2</state>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GRuntimeLibSelectSlave</name>
|
||||
<version>0</version>
|
||||
<state>2</state>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>RTDescription</name>
|
||||
<state>Use the full configuration of the C/C++ runtime library. Full locale interface, C locale, file descriptor support, multibytes in printf and scanf, and hex floats in strtod.</state>
|
||||
<state>Use the normal configuration of the C/C++ runtime library. No locale interface, C locale, no file descriptor support, no multibytes in printf and scanf, and no hex floats in strtod.</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OGProductVersion</name>
|
||||
@ -103,7 +103,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GenLowLevelInterface</name>
|
||||
<state>1</state>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GEndianModeBE</name>
|
||||
@ -133,7 +133,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>RTConfigPath2</name>
|
||||
<state>$TOOLKIT_DIR$\INC\c\DLib_Config_Full.h</state>
|
||||
<state>$TOOLKIT_DIR$\INC\c\DLib_Config_Normal.h</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GFPUCoreSlave</name>
|
||||
@ -309,6 +309,7 @@
|
||||
<state>$PROJ_DIR$\ST_Code\libraries\CMSIS\Device\ST\STM32L1xx\Include</state>
|
||||
<state>$PROJ_DIR$\..\..\Source\include</state>
|
||||
<state>$PROJ_DIR$\..\..\Source\portable\IAR\ARM_CM3</state>
|
||||
<state>$PROJ_DIR$\..\Common\include</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>CCStdIncCheck</name>
|
||||
@ -645,7 +646,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkOutputFile</name>
|
||||
<state>STM32L-Discovery.out</state>
|
||||
<state>RTOSDemo.out</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkDebugInfoEnable</name>
|
||||
@ -1064,6 +1065,33 @@
|
||||
</file>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<name>Standard Demo Tasks</name>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\Common\Minimal\BlockQ.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\Common\Minimal\blocktim.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\Common\Minimal\countsem.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\Common\Minimal\dynamic.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\Common\Minimal\GenQTest.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\Common\Minimal\PollQ.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\Common\Minimal\recmutex.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\Common\Minimal\semtest.c</name>
|
||||
</file>
|
||||
</group>
|
||||
<group>
|
||||
<name>System</name>
|
||||
<file>
|
||||
@ -1088,6 +1116,12 @@
|
||||
<file>
|
||||
<name>$PROJ_DIR$\main.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\main_full.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\main_low_power.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\stm32l1xx_it.c</name>
|
||||
</file>
|
||||
|
@ -75,8 +75,8 @@
|
||||
|
||||
/*
|
||||
* When configCREATE_LOW_POWER_DEMO is set to 1 then the tick interrupt
|
||||
* is generated by the wakeup interrupt of the real time clock (RTC). The RTC
|
||||
* configuration and handling functions are defined in this file.
|
||||
* is generated by the TIM2 peripheral. The TIM2 configuration and handling
|
||||
* functions are defined in this file.
|
||||
*
|
||||
* When configCREATE_LOW_POWER_DEMO is set to 0 the tick interrupt is
|
||||
* generated by the standard FreeRTOS Cortex-M port layer, which uses the
|
||||
@ -84,23 +84,17 @@
|
||||
*/
|
||||
#if configCREATE_LOW_POWER_DEMO == 1
|
||||
|
||||
/* The frequency at which TIM2 should run. */
|
||||
/* The frequency at which TIM2 will run. */
|
||||
#define lpCLOCK_INPUT_FREQUENCY ( 1000UL )
|
||||
|
||||
/* Constants required to pend a PendSV interrupt from the tick ISR if the
|
||||
preemptive scheduler is being used. These are just standard bits and registers
|
||||
within the Cortex-M core itself. */
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
|
||||
/* STM32 register used to ensure the TIM2 clock stops when the MCU is in debug
|
||||
mode. */
|
||||
#define DBGMCU_APB1_FZ ( * ( ( volatile unsigned long * ) 0xE0042008 ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The tick interrupt is generated by the TIM2 timer. The default interrupt
|
||||
* handler cannot be used (even with the TIM2 being handled from the tick hook
|
||||
* function) because the default tick interrupt accesses the SysTick registers
|
||||
* when configUSE_TICKLESS_IDLE set to 1. TIM2_IRQHandler() is the default name
|
||||
* for the TIM2 interrupt handler.
|
||||
* The tick interrupt is generated by the TIM2 timer.
|
||||
*/
|
||||
void TIM2_IRQHandler( void );
|
||||
|
||||
@ -115,15 +109,9 @@ initialisation. */
|
||||
static portTickType xMaximumPossibleSuppressedTicks = 0;
|
||||
|
||||
/* Flag set from the tick interrupt to allow the sleep processing to know if
|
||||
sleep mode was exited because of an RTC interrupt or a different interrupt. */
|
||||
sleep mode was exited because of an tick interrupt or a different interrupt. */
|
||||
static volatile uint32_t ulTickFlag = pdFALSE;
|
||||
|
||||
/* The RTC counter is stopped temporarily each time it is re-programmed. The
|
||||
following variable offsets the RTC counter alarm value by the number of RTC
|
||||
counts that would typically be missed while the counter was stopped to
|
||||
compensate for the lost time. _RB_ Value needs calculating correctly. */
|
||||
static uint32_t ulStoppedTimerCompensation = 1;//_RB_ / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The tick interrupt handler. This is always the same other than the part that
|
||||
@ -131,10 +119,13 @@ clears the interrupt, which is specific to the clock being used to generate the
|
||||
tick. */
|
||||
void TIM2_IRQHandler( void )
|
||||
{
|
||||
/* Clear the interrupt. */
|
||||
TIM_ClearITPendingBit( TIM2, TIM_IT_Update );
|
||||
TIM_SetAutoreload( TIM2, ( uint16_t ) ulReloadValueForOneTick );
|
||||
|
||||
/* Protect incrementing the tick with an interrupt safe critical section. */
|
||||
/* The next block of code is from the standard FreeRTOS tick interrupt
|
||||
handler. The standard handler is not called directly in case future
|
||||
versions contain changes that make it no longer suitable for calling
|
||||
here. */
|
||||
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
@ -148,39 +139,42 @@ void TIM2_IRQHandler( void )
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||
|
||||
/* In case this is the first tick since the MCU left a low power mode the
|
||||
reload value is reset to its default. */
|
||||
TIM2->ARR = ( uint16_t ) ulReloadValueForOneTick;
|
||||
|
||||
/* The CPU woke because of a tick. */
|
||||
ulTickFlag = pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Override the default definition of vPortSetupTimerInterrupt() that is weakly
|
||||
defined in the FreeRTOS Cortex-M3 port layer with a version that configures the
|
||||
wakeup timer of the RTC to generate the tick interrupt. */
|
||||
defined in the FreeRTOS Cortex-M3 port layer with a version that configures TIM2
|
||||
to generate the tick interrupt. */
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
|
||||
/* Enable the TIM2 clock, which is used to generate long tickless periods
|
||||
when the tickless period is finite. */
|
||||
/* Enable the TIM2 clock. */
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
|
||||
|
||||
/* Ensure clock stops in debug mode. */
|
||||
DBGMCU_APB1_FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP;
|
||||
|
||||
/* Scale the clock so very long tickless periods can be acheived. The
|
||||
SysTick is not used as even when its frequency is divided by 8 the maximum
|
||||
tickless period with a system clock of 16MHz is only 8.3 seconds. Using
|
||||
a prescaled clock on the 16-bit TIM2 allows a tickless period of nearly
|
||||
66 seconds, albeit at low resolution. */
|
||||
/* Scale the clock so longer tickless periods can be achieved. The SysTick
|
||||
is not used as even when its frequency is divided by 8 the maximum tickless
|
||||
period with a system clock of 16MHz is only 8.3 seconds. Using a prescaled
|
||||
clock on the 16-bit TIM2 allows a tickless period of nearly 66 seconds,
|
||||
albeit at low resolution. */
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = ( uint16_t ) ( SystemCoreClock / lpCLOCK_INPUT_FREQUENCY );
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseStructure.TIM_Period = ( uint16_t ) ( lpCLOCK_INPUT_FREQUENCY / configTICK_RATE_HZ );
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseInit( TIM2, &TIM_TimeBaseStructure );
|
||||
|
||||
/* Enable the TIM2 interrupt - used for the tick interrupt when the tickless
|
||||
period is finite. */
|
||||
/* Enable the TIM2 interrupt. This must execute at the lowest interrupt
|
||||
priority. */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_LOWEST_INTERRUPT_PRIORITY; /* Must be set to lowest priority. */
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
@ -216,17 +210,11 @@ const portTickType xRegulatorOffIdleTime = 30;
|
||||
/* Calculate the reload value required to wait xExpectedIdleTime tick
|
||||
periods. */
|
||||
ulCounterValue = ulReloadValueForOneTick * xExpectedIdleTime;
|
||||
if( ulCounterValue > ulStoppedTimerCompensation )
|
||||
{
|
||||
/* Compensate for the fact that TIM2 is going to be stopped
|
||||
momentarily. */
|
||||
ulCounterValue -= ulStoppedTimerCompensation;
|
||||
}
|
||||
|
||||
/* Stop TIM2 momentarily. The time TIM2 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. */
|
||||
/* Stop TIM2 momentarily. The time TIM2 is stopped for is not accounted for
|
||||
in this implementation (as it is in the generic implementation) because the
|
||||
clock is so slow it is unlikely to be stopped for a complete count period
|
||||
anyway. */
|
||||
TIM_Cmd( TIM2, DISABLE );
|
||||
|
||||
/* Enter a critical section but don't use the taskENTER_CRITICAL() method as
|
||||
@ -255,13 +243,25 @@ const portTickType xRegulatorOffIdleTime = 30;
|
||||
}
|
||||
else if( eSleepAction == eNoTasksWaitingTimeout )
|
||||
{
|
||||
/* A user definable macro that allows application code to be inserted
|
||||
here. Such application code can be used to minimise power consumption
|
||||
further by turning off IO, peripheral clocks, the Flash, etc. */
|
||||
configPRE_STOP_PROCESSING();
|
||||
|
||||
/* There are no running state tasks and no tasks that are blocked with a
|
||||
time out. Assuming the application does not care if the tick time slips
|
||||
with respect to calendar time then enter a deep sleep that can only be
|
||||
woken by (in this demo case) the user button being pushed on the
|
||||
STM32L discovery board. */
|
||||
configPRE_STOP_PROCESSING();
|
||||
STM32L discovery board. If the application does require the tick time
|
||||
to keep better track of the calender time then the RTC peripheral can be
|
||||
used to make rough adjustments. */
|
||||
PWR_EnterSTOPMode( PWR_Regulator_LowPower, PWR_SLEEPEntry_WFI );
|
||||
|
||||
/* A user definable macro that allows application code to be inserted
|
||||
here. Such application code can be used to reverse any actions taken
|
||||
by the configPRE_STOP_PROCESSING(). In this demo
|
||||
configPOST_STOP_PROCESSING() is used to re-initialise the clocks that
|
||||
were turned off when STOP mode was entered. */
|
||||
configPOST_STOP_PROCESSING();
|
||||
|
||||
/* Restart tick. */
|
||||
@ -274,36 +274,48 @@ const portTickType xRegulatorOffIdleTime = 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Trap underflow before the next calculation. */
|
||||
configASSERT( ulCounterValue >= TIM_GetCounter( TIM2 ) );
|
||||
|
||||
/* Adjust the TIM2 value to take into account that the current time
|
||||
slice is already partially complete. */
|
||||
configASSERT( ulCounterValue >= TIM_GetCounter( TIM2 ) );
|
||||
ulCounterValue -= ( uint32_t ) TIM_GetCounter( TIM2 );
|
||||
|
||||
/* Trap overflow/underflow before the calculated value is written to
|
||||
TIM2. */
|
||||
configASSERT( ulCounterValue < ( uint32_t ) USHRT_MAX );
|
||||
configASSERT( ulCounterValue != 0 );
|
||||
|
||||
/* Update to use the calculated overflow value. */
|
||||
TIM_SetAutoreload( TIM2, ( uint16_t ) ulCounterValue );
|
||||
TIM_SetCounter( TIM2, 0 );
|
||||
|
||||
/* Restart the TIM2. */
|
||||
TIM_Cmd( TIM2, ENABLE );
|
||||
|
||||
/* Allow the application to define some pre-sleep processing. */
|
||||
/* Allow the application to define some pre-sleep processing. This is
|
||||
the standard configPRE_SLEEP_PROCESSING() macro as described on the
|
||||
FreeRTOS.org website. */
|
||||
xModifiableIdleTime = xExpectedIdleTime;
|
||||
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
|
||||
/* xExpectedIdleTime being set to 0 by configPRE_SLEEP_PROCESSING()
|
||||
means the application defined code has already executed the WAIT
|
||||
means the application defined code has already executed the wait/sleep
|
||||
instruction. */
|
||||
if( xModifiableIdleTime > 0 )
|
||||
{
|
||||
/* The sleep mode used is dependent on the expected idle time
|
||||
as the deeper the sleep the longer the wake up time. */
|
||||
as the deeper the sleep the longer the wake up time. See the
|
||||
comments at the top of main_low_power.c. Note xRegulatorOffIdleTime
|
||||
is set purely for convenience of demonstration and is not intended
|
||||
to be an optimised value. */
|
||||
if( xModifiableIdleTime > xRegulatorOffIdleTime )
|
||||
{
|
||||
/* A slightly lower power sleep mode with a longer wake up
|
||||
time. */
|
||||
PWR_EnterSleepMode( PWR_Regulator_LowPower, PWR_SLEEPEntry_WFI );
|
||||
}
|
||||
else if( pdTRUE )
|
||||
else
|
||||
{
|
||||
/* A slightly higher power sleep mode with a faster wake up
|
||||
time. */
|
||||
@ -311,13 +323,14 @@ const portTickType xRegulatorOffIdleTime = 30;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow the application to define some post sleep processing. */
|
||||
/* Allow the application to define some post sleep processing. This is
|
||||
the standard configPOST_SLEEP_PROCESSING() macro, as described on the
|
||||
FreeRTOS.org website. */
|
||||
configPOST_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
|
||||
/* Stop TIM2. 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. */
|
||||
/* Stop TIM2. Again, the time the clock is stopped for in not accounted
|
||||
for here (as it would normally be) because the clock is so slow it is
|
||||
unlikely it will be stopped for a complete count period anyway. */
|
||||
TIM_Cmd( TIM2, DISABLE );
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
@ -328,14 +341,20 @@ const portTickType xRegulatorOffIdleTime = 30;
|
||||
|
||||
if( ulTickFlag != pdFALSE )
|
||||
{
|
||||
/* Trap overflows before the next calculation. */
|
||||
configASSERT( ulReloadValueForOneTick >= ( uint32_t ) TIM_GetCounter( TIM2 ) );
|
||||
|
||||
/* The tick interrupt has already executed, although because this
|
||||
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. */
|
||||
configASSERT( ulReloadValueForOneTick >= ( uint32_t ) TIM_GetCounter( TIM2 ) );
|
||||
ulCounterValue = ulReloadValueForOneTick - ( uint32_t ) TIM_GetCounter( TIM2 );
|
||||
|
||||
/* Trap under/overflows before the calculated value is used. */
|
||||
configASSERT( ulCounterValue <= ( uint32_t ) USHRT_MAX );
|
||||
configASSERT( ulCounterValue != 0 );
|
||||
|
||||
/* Use the calculated reload value. */
|
||||
TIM_SetAutoreload( TIM2, ( uint16_t ) ulCounterValue );
|
||||
TIM_SetCounter( TIM2, 0 );
|
||||
|
||||
@ -353,9 +372,11 @@ const portTickType xRegulatorOffIdleTime = 30;
|
||||
sleeping? */
|
||||
ulCompleteTickPeriods = ( ( uint32_t ) TIM_GetCounter( TIM2 ) ) / ulReloadValueForOneTick;
|
||||
|
||||
/* Check for over/under flows before the following calculation. */
|
||||
configASSERT( ( ( uint32_t ) TIM_GetCounter( TIM2 ) ) >= ( ulCompleteTickPeriods * ulReloadValueForOneTick ) );
|
||||
|
||||
/* The reload value is set to whatever fraction of a single tick
|
||||
period remains. */
|
||||
configASSERT( ( ( uint32_t ) TIM_GetCounter( TIM2 ) ) >= ( ulCompleteTickPeriods * ulReloadValueForOneTick ) );
|
||||
ulCounterValue = ( ( uint32_t ) TIM_GetCounter( TIM2 ) ) - ( ulCompleteTickPeriods * ulReloadValueForOneTick );
|
||||
configASSERT( ulCounterValue <= ( uint32_t ) USHRT_MAX );
|
||||
if( ulCounterValue == 0 )
|
||||
@ -379,7 +400,5 @@ const portTickType xRegulatorOffIdleTime = 30;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* configCREATE_LOW_POWER_DEMO == 1 */
|
||||
|
||||
|
@ -78,7 +78,8 @@
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Ensure stdint is only used by the compiler, and not the assembler. */
|
||||
/* Ensure stdint and C code is only used by the compiler, and not the
|
||||
assembler. */
|
||||
#ifdef __ICCARM__
|
||||
#include <stdint.h>
|
||||
extern uint32_t SystemCoreClock;
|
||||
@ -88,30 +89,42 @@
|
||||
|
||||
/* Set configCREATE_LOW_POWER_DEMO to one to run the simple blinky low power
|
||||
demo, or 0 to run the more comprehensive test and demo application. */
|
||||
#define configCREATE_LOW_POWER_DEMO 1
|
||||
#define configCREATE_LOW_POWER_DEMO 0
|
||||
|
||||
/* A few settings are dependent on the configCREATE_LOW_POWER_DEMO setting. */
|
||||
#if configCREATE_LOW_POWER_DEMO == 1
|
||||
#define configCPU_CLOCK_HZ SystemCoreClock
|
||||
#define configUSE_TICKLESS_IDLE 1
|
||||
#define configTICK_RATE_HZ ( 100 )
|
||||
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP ( 20 + 1 ) /* ( ( 200 / portTICK_RATE_MS ) + 1 ) written out pre-processed to enable #error statements to check its value. */
|
||||
#define configUSE_TIMERS 0
|
||||
#else
|
||||
#define configCPU_CLOCK_HZ SystemCoreClock
|
||||
#define configSYSTICK_CLOCK_HZ ( SystemCoreClock >> 3UL )
|
||||
#define configUSE_TICKLESS_IDLE 0
|
||||
#define configSYSTICK_CLOCK_HZ ( SystemCoreClock >> 3UL ) /* Systick clock is one eighth the system clock. */
|
||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||
#define configUSE_TIMERS 1
|
||||
#endif /* configCREATE_LOW_POWER_DEMO */
|
||||
|
||||
/* Demo specific macros that allow the application writer to insert code to be
|
||||
executed immediately before the MCU's STOP low power mode is entered and exited
|
||||
respectively. These macros are in addition to the standard
|
||||
configPRE_SLEEP_PROCESSING() and configPOST_SLEEP_PROCESSING() macros, which are
|
||||
called pre and post the low power SLEEP mode being entered and exited. These
|
||||
macros can be used to turn turn off and on IO, clocks, the Flash etc. to obtain
|
||||
the lowest power possible while the tick is off. See the comments at the top of
|
||||
main_low_power.c and in STM32L_low_power_tick_management.c. */
|
||||
#define configPRE_STOP_PROCESSING()
|
||||
#define configPOST_STOP_PROCESSING() vMainPostStopProcessing()
|
||||
|
||||
/* The configUSE_TICKLESS_IDLE setting is dependent on the users setting of
|
||||
configCREATE_LOW_POWER_DEMO at the top of this file. */
|
||||
#define configUSE_TICKLESS_IDLE configCREATE_LOW_POWER_DEMO
|
||||
|
||||
#define configCPU_CLOCK_HZ SystemCoreClock
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 1
|
||||
#define configMAX_PRIORITIES ( 5 )
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 14 * 1024 ) )
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
@ -119,9 +132,15 @@ demo, or 0 to run the more comprehensive test and demo application. */
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configQUEUE_REGISTRY_SIZE 5
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||
#define configUSE_RECURSIVE_MUTEXES 0
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_MALLOC_FAILED_HOOK 1
|
||||
#define configUSE_APPLICATION_TASK_TAG 0
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
|
||||
/* Software timer related definitions. */
|
||||
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||
#define configTIMER_QUEUE_LENGTH 10
|
||||
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||
|
||||
/* Co-routine definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
|
File diff suppressed because it is too large
Load Diff
263
FreeRTOS/Demo/CORTEX_STM32L152_Discovery_IAR/main_full.c
Normal file
263
FreeRTOS/Demo/CORTEX_STM32L152_Discovery_IAR/main_full.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that has become a de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly and support the FreeRTOS *
|
||||
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* Thank you! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
|
||||
>>! NOTE: The modification to the GPL is included to allow you to distribute
|
||||
>>! a combined work that includes FreeRTOS without being obliged to provide
|
||||
>>! the source code for proprietary components outside of the FreeRTOS
|
||||
>>! kernel.
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available from the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
* not run, what could be wrong?" *
|
||||
* *
|
||||
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||
license and Real Time Engineers Ltd. contact details.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* NOTE 1: This project provides two demo applications. A low power tickless
|
||||
* project, and a more comprehensive test and demo application. The
|
||||
* configCREATE_LOW_POWER_DEMO setting in FreeRTOSConfig.h is used to
|
||||
* select between the two. See the notes on using
|
||||
* configCREATE_LOW_POWER_DEMO in FreeRTOSConfig.h. This file implements
|
||||
* the comprehensive test and demo version.
|
||||
*
|
||||
* NOTE 2: This file only contains the source code that is specific to the
|
||||
* full demo. Generic functions, such FreeRTOS hook functions, and functions
|
||||
* required to configure the hardware, are defined in main.c.
|
||||
******************************************************************************
|
||||
*
|
||||
* main_full() creates all the demo application tasks and a software timer, then
|
||||
* starts the scheduler. The web documentation provides more details of the
|
||||
* standard demo application tasks, which provide no particular functionality,
|
||||
* but do provide a good example of how to use the FreeRTOS API.
|
||||
*
|
||||
* In addition to the standard demo tasks, the following tasks and tests are
|
||||
* defined and/or created within this file:
|
||||
*
|
||||
* "Check" timer - The check software timer period is initially set to three
|
||||
* seconds. The callback function associated with the check software timer
|
||||
* checks that all the standard demo tasks are not only still executing, but
|
||||
* are executing without reporting any errors. If the check software timer
|
||||
* discovers that a task has either stalled, or reported an error, then it
|
||||
* changes its own execution period from the initial three seconds, to just
|
||||
* 200ms. The check software timer callback function also toggles an LED each
|
||||
* time it is called. This provides a visual indication of the system status:
|
||||
* If the LED toggles every three seconds, then no issues have been discovered.
|
||||
* If the LED toggles every 200ms, then an issue has been discovered with at
|
||||
* least one task.
|
||||
*
|
||||
* See the documentation page for this demo on the FreeRTOS.org web site for
|
||||
* full information, including hardware setup requirements.
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* Standard demo application includes. */
|
||||
#include "PollQ.h"
|
||||
#include "semtest.h"
|
||||
#include "dynamic.h"
|
||||
#include "BlockQ.h"
|
||||
#include "blocktim.h"
|
||||
#include "countsem.h"
|
||||
#include "GenQTest.h"
|
||||
#include "recmutex.h"
|
||||
|
||||
/* ST library functions. */
|
||||
#include "stm32l1xx.h"
|
||||
#include "discover_board.h"
|
||||
#include "discover_functions.h"
|
||||
#include "stm32l_discovery_lcd.h"
|
||||
|
||||
/* Priorities for the demo application tasks. */
|
||||
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2UL )
|
||||
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1UL )
|
||||
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2UL )
|
||||
|
||||
/* A block time of zero simply means "don't block". */
|
||||
#define mainDONT_BLOCK ( 0UL )
|
||||
|
||||
/* The period after which the check timer will expire providing no errors
|
||||
have been reported by any of the standard demo tasks. ms are converted to the
|
||||
equivalent in ticks using the portTICK_RATE_MS constant. */
|
||||
#define mainCHECK_TIMER_PERIOD_MS ( 3000UL / portTICK_RATE_MS )
|
||||
|
||||
/* The period at which the check timer will expire, in ms, if an error has been
|
||||
reported in one of the standard demo tasks. ms are converted to the equivalent
|
||||
in ticks using the portTICK_RATE_MS constant. */
|
||||
#define mainERROR_CHECK_TIMER_PERIOD_MS ( 200UL / portTICK_RATE_MS )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The check timer callback function, as described at the top of this file.
|
||||
*/
|
||||
static void prvCheckTimerCallback( xTimerHandle xTimer );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void main_full( void )
|
||||
{
|
||||
xTimerHandle xCheckTimer = NULL;
|
||||
|
||||
/* Start all the other standard demo/test tasks. They have not particular
|
||||
functionality, but do demonstrate how to use the FreeRTOS API and test the
|
||||
kernel port. */
|
||||
vStartDynamicPriorityTasks();
|
||||
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
|
||||
vCreateBlockTimeTasks();
|
||||
vStartCountingSemaphoreTasks();
|
||||
vStartGenericQueueTasks( tskIDLE_PRIORITY );
|
||||
vStartRecursiveMutexTasks();
|
||||
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
|
||||
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
|
||||
|
||||
/* Create the software timer that performs the 'check' functionality,
|
||||
as described at the top of this file. */
|
||||
xCheckTimer = xTimerCreate( ( const signed char * ) "CheckTimer",/* A text name, purely to help debugging. */
|
||||
( mainCHECK_TIMER_PERIOD_MS ), /* The timer period, in this case 3000ms (3s). */
|
||||
pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */
|
||||
( void * ) 0, /* The ID is not used, so can be set to anything. */
|
||||
prvCheckTimerCallback /* The callback function that inspects the status of all the other tasks. */
|
||||
);
|
||||
|
||||
if( xCheckTimer != NULL )
|
||||
{
|
||||
xTimerStart( xCheckTimer, mainDONT_BLOCK );
|
||||
}
|
||||
|
||||
/* Start the scheduler. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
/* If all is well, the scheduler will now be running, and the following line
|
||||
will never be reached. If the following line does execute, then there was
|
||||
insufficient FreeRTOS heap memory available for the idle and/or timer tasks
|
||||
to be created. See the memory management section on the FreeRTOS web site
|
||||
for more details. */
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckTimerCallback( xTimerHandle xTimer )
|
||||
{
|
||||
static long lChangedTimerPeriodAlready = pdFALSE;
|
||||
unsigned long ulErrorFound = pdFALSE;
|
||||
|
||||
/* Check all the demo tasks to ensure they are all still running, and that
|
||||
none have detected an error. */
|
||||
|
||||
if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
ulErrorFound = pdTRUE;
|
||||
}
|
||||
|
||||
if( xAreBlockingQueuesStillRunning() != pdTRUE )
|
||||
{
|
||||
ulErrorFound = pdTRUE;
|
||||
}
|
||||
|
||||
if ( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
ulErrorFound = pdTRUE;
|
||||
}
|
||||
|
||||
if ( xAreGenericQueueTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
ulErrorFound = pdTRUE;
|
||||
}
|
||||
|
||||
if ( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
ulErrorFound = pdTRUE;
|
||||
}
|
||||
|
||||
if( xArePollingQueuesStillRunning() != pdTRUE )
|
||||
{
|
||||
ulErrorFound = pdTRUE;
|
||||
}
|
||||
|
||||
if( xAreSemaphoreTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
ulErrorFound = pdTRUE;
|
||||
}
|
||||
|
||||
/* Toggle the check LED to give an indication of the system status. If
|
||||
the LED toggles every mainCHECK_TIMER_PERIOD_MS milliseconds then
|
||||
everything is ok. A faster toggle indicates an error. */
|
||||
GPIO_TOGGLE( LD_GPIO_PORT, LD_GREEN_GPIO_PIN );
|
||||
|
||||
/* Have any errors been latch in ulErrorFound? If so, shorten the
|
||||
period of the check timer to mainERROR_CHECK_TIMER_PERIOD_MS milliseconds.
|
||||
This will result in an increase in the rate at which mainCHECK_LED
|
||||
toggles. */
|
||||
if( ulErrorFound != pdFALSE )
|
||||
{
|
||||
if( lChangedTimerPeriodAlready == pdFALSE )
|
||||
{
|
||||
lChangedTimerPeriodAlready = pdTRUE;
|
||||
|
||||
/* This call to xTimerChangePeriod() uses a zero block time.
|
||||
Functions called from inside of a timer callback function must
|
||||
*never* attempt to block. */
|
||||
xTimerChangePeriod( xTimer, ( mainERROR_CHECK_TIMER_PERIOD_MS ), mainDONT_BLOCK );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
337
FreeRTOS/Demo/CORTEX_STM32L152_Discovery_IAR/main_low_power.c
Normal file
337
FreeRTOS/Demo/CORTEX_STM32L152_Discovery_IAR/main_low_power.c
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that has become a de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly and support the FreeRTOS *
|
||||
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* Thank you! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
|
||||
>>! NOTE: The modification to the GPL is included to allow you to distribute
|
||||
>>! a combined work that includes FreeRTOS without being obliged to provide
|
||||
>>! the source code for proprietary components outside of the FreeRTOS
|
||||
>>! kernel.
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available from the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
* not run, what could be wrong?" *
|
||||
* *
|
||||
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||
license and Real Time Engineers Ltd. contact details.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* ****************************************************************************
|
||||
* When configCREATE_LOW_POWER_DEMO is set to 1 in FreeRTOSConfig.h main() will
|
||||
* call main_low_power(), which is defined in this file. main_low_power()
|
||||
* demonstrates FreeRTOS tick suppression being used to allow the MCU to be
|
||||
* placed into the Sleep, Low Power Sleep and Stop low power modes. When
|
||||
* configCREATE_LOW_POWER_DEMO is set to 0 main will instead call main_full(),
|
||||
* which is a more comprehensive RTOS demonstration.
|
||||
* ****************************************************************************
|
||||
*
|
||||
* This application demonstrates the FreeRTOS tickless idle mode (tick
|
||||
* suppression) being used to allow the STM32L to enter various low power modes
|
||||
* during extended idle periods. See
|
||||
* http://www.freertos.org/low-power-tickless-rtos.html for information on
|
||||
* tickless operation.
|
||||
*
|
||||
* Deeper low power modes have longer wake up periods that lighter low power
|
||||
* modes, and power is also used simply entering and especially exiting the low
|
||||
* power modes. How the low power modes are used therefore requires careful
|
||||
* consideration to ensure power consumption is truly minimised and that the
|
||||
* embedded device meets its real time requirements. This demo is configured to
|
||||
* select between four different modes depending on the anticipated idle period.
|
||||
* Note the time thresholds used to decide which low power mode to enter are
|
||||
* purely for convenience of demonstration and are not intended to represent
|
||||
* optimal values for any particular application.
|
||||
*
|
||||
* The STM32L specific part of the tickless operation is implemented in
|
||||
* STM32L_low_power_tick_management.c.
|
||||
*
|
||||
* The demo is configured to execute on the STM32L Discovery board.
|
||||
*
|
||||
* Functionality:
|
||||
*
|
||||
* + Two tasks are created, an Rx task and a Tx task. A queue is created to
|
||||
* pass a message from the Tx task to the Rx task.
|
||||
*
|
||||
* + The Rx task blocks on a queue to wait for data, blipping an LED each time
|
||||
* data is received (turning it on and then off again) before returning to
|
||||
* block on the queue once more.
|
||||
*
|
||||
* + The Tx task repeatedly blocks on an attempt to obtain a semaphore, and
|
||||
* unblocks if either the semaphore is received or its block time expires.
|
||||
* After leaving the blocked state the Tx task uses the queue to send a
|
||||
* value to the Rx task, which in turn causes the Rx task to exit the
|
||||
* Blocked state and blip the LED. The rate at which the LED is seen to blip
|
||||
* is therefore dependent on the block time.
|
||||
*
|
||||
* + The Tx task's block time is changed by the interrupt service routine that
|
||||
* executes when the USER button is pressed. The low power mode entered
|
||||
* depends on the block time (as described in the Observed Behaviour section
|
||||
* below). Four block times are used: short, medium, long and infinite.
|
||||
*
|
||||
* Observed behaviour:
|
||||
*
|
||||
* 1) The block time used by the Tx task is initialised to its 'short' value,
|
||||
* so when the Tx task blocks on the semaphore it times-out quickly, resulting
|
||||
* in the LED toggling rapidly. The timeout period is less than the value of
|
||||
* configEXPECTED_IDLE_TIME_BEFORE_SLEEP (set in FreeRTOSConfig.h), so the
|
||||
* initial state does not suppress the tick interrupt or enter a low power mode.
|
||||
*
|
||||
* 2) When the button is pressed the block time used by the Tx task is increased
|
||||
* to its 'medium' value. The longer block time results in a slowing of the
|
||||
* rate at which the LED toggles. The time the Tx task spends in the blocked
|
||||
* state is now greater than configEXPECTED_IDLE_TIME_BEFORE_SLEEP, so the tick
|
||||
* is suppressed. The MCU is placed into the 'Sleep' low power state while the
|
||||
* tick is suppressed.
|
||||
*
|
||||
* 3) When the button is pressed again the block time used by the Tx task is
|
||||
* increased to its 'long' value, so the rate at which the LED is observed to
|
||||
* blip gets even slow. When the 'long' block time is used the MCU is placed
|
||||
* into its 'Low Power Sleep' low power state.
|
||||
*
|
||||
* 4) The next time the button is pressed the block time used by the Tx task is
|
||||
* set to infinite, so the Tx task does not time out when it attempts to obtain
|
||||
* the semaphore, and therefore the LED stops blipping completely. Both tasks
|
||||
* are not blocked indefinitely and the MCU is placed into its 'Stop' low power
|
||||
* state.
|
||||
*
|
||||
* 5) Pressing the button one final time results in the semaphore being 'given'
|
||||
* to unblock the Tx task, the CPU clocks being returned to their pre-stop
|
||||
* state, and the block time being reset to its 'short' time. The system is
|
||||
* then back to its initial condition with the LED blipping rapidly.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* ST library functions. */
|
||||
#include "stm32l1xx.h"
|
||||
#include "discover_board.h"
|
||||
#include "discover_functions.h"
|
||||
#include "stm32l_discovery_lcd.h"
|
||||
|
||||
/* Priorities at which the Rx and Tx tasks are created. */
|
||||
#define configQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||
#define configQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||
|
||||
/* The number of items the queue can hold. This is 1 as the Rx task will
|
||||
remove items as they are added so the Tx task should always find the queue
|
||||
empty. */
|
||||
#define mainQUEUE_LENGTH ( 1 )
|
||||
|
||||
/* A block time of zero simply means "don't block". */
|
||||
#define mainDONT_BLOCK ( 0 )
|
||||
|
||||
/* The value that is sent from the Tx task to the Rx task on the queue. */
|
||||
#define mainQUEUED_VALUE ( 100UL )
|
||||
|
||||
/* The length of time the LED will remain on for. */
|
||||
#define mainLED_TOGGLE_DELAY ( 10 / portTICK_RATE_MS )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The Rx and Tx tasks as described at the top of this file.
|
||||
*/
|
||||
static void prvQueueReceiveTask( void *pvParameters );
|
||||
static void prvQueueSendTask( void *pvParameters );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The queue used to pass data from the Tx task to the Rx task. */
|
||||
static xQueueHandle xQueue = NULL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Holds the block time used by the Tx task. */
|
||||
portTickType xSendBlockTime = ( 100UL / portTICK_RATE_MS );
|
||||
|
||||
/* The lower an upper limits of the block time. An infinite block time is used
|
||||
if xSendBlockTime is incremented past xMaxBlockTime. */
|
||||
static const portTickType xMaxBlockTime = ( 500L / portTICK_RATE_MS ), xMinBlockTime = ( 100L / portTICK_RATE_MS );
|
||||
|
||||
/* The semaphore on which the Tx task blocks. */
|
||||
static xSemaphoreHandle xTxSemaphore = NULL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See the comments at the top of the file. */
|
||||
void main_low_power( void )
|
||||
{
|
||||
/* Create the semaphore as described at the top of this file. */
|
||||
xTxSemaphore = xSemaphoreCreateBinary();
|
||||
configASSERT( xTxSemaphore );
|
||||
|
||||
/* Create the queue as described at the top of this file. */
|
||||
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );
|
||||
configASSERT( xQueue );
|
||||
|
||||
/* Start the two tasks as described at the top of this file. */
|
||||
xTaskCreate( prvQueueReceiveTask, ( const signed char * const ) "Rx", configMINIMAL_STACK_SIZE, NULL, configQUEUE_RECEIVE_TASK_PRIORITY, NULL );
|
||||
xTaskCreate( prvQueueSendTask, ( const signed char * const ) "TX", configMINIMAL_STACK_SIZE, NULL, configQUEUE_SEND_TASK_PRIORITY, NULL );
|
||||
|
||||
/* Start the scheduler running running. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
/* If all is well the next line of code will not be reached as the
|
||||
scheduler will be running. If the next line is reached then it is likely
|
||||
there was insufficient FreeRTOS heap available for the idle task and/or
|
||||
timer task to be created. See http://www.freertos.org/a00111.html. */
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvQueueSendTask( void *pvParameters )
|
||||
{
|
||||
const unsigned long ulValueToSend = mainQUEUED_VALUE;
|
||||
|
||||
/* Remove compiler warning about unused parameter. */
|
||||
( void ) pvParameters;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Enter the Blocked state to wait for the semaphore. The task will
|
||||
leave the Blocked state if either the semaphore is received or
|
||||
xSendBlockTime ticks pass without the semaphore being received. */
|
||||
xSemaphoreTake( xTxSemaphore, xSendBlockTime );
|
||||
|
||||
/* Send to the queue - causing the Tx task to flash its LED. */
|
||||
xQueueSend( xQueue, &ulValueToSend, mainDONT_BLOCK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvQueueReceiveTask( void *pvParameters )
|
||||
{
|
||||
unsigned long ulReceivedValue;
|
||||
|
||||
/* Remove compiler warning about unused parameter. */
|
||||
( void ) pvParameters;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Wait until something arrives in the queue. */
|
||||
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
|
||||
|
||||
/* To get here something must have arrived, but is it the expected
|
||||
value? If it is, turn the LED on for a short while. */
|
||||
if( ulReceivedValue == mainQUEUED_VALUE )
|
||||
{
|
||||
/* LED on... */
|
||||
GPIO_HIGH( LD_GPIO_PORT, LD_GREEN_GPIO_PIN );
|
||||
|
||||
/* ... short delay ... */
|
||||
vTaskDelay( mainLED_TOGGLE_DELAY );
|
||||
|
||||
/* ... LED off again. */
|
||||
GPIO_LOW( LD_GPIO_PORT, LD_GREEN_GPIO_PIN );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Handles interrupts generated by pressing the USER button. */
|
||||
void EXTI0_IRQHandler(void)
|
||||
{
|
||||
static const portTickType xIncrement = 200UL / portTICK_RATE_MS;
|
||||
|
||||
/* If xSendBlockTime is already portMAX_DELAY then the Tx task was blocked
|
||||
indefinitely, and this interrupt is bringing the MCU out of STOP low power
|
||||
mode. */
|
||||
if( xSendBlockTime == portMAX_DELAY )
|
||||
{
|
||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
/* Unblock the Tx task. */
|
||||
xSemaphoreGiveFromISR( xTxSemaphore, &xHigherPriorityTaskWoken );
|
||||
|
||||
/* Start over with the 'short' block time as described at the top of
|
||||
this file. */
|
||||
xSendBlockTime = xMinBlockTime;
|
||||
|
||||
/* Request a yield if calling xSemaphoreGiveFromISR() caused a task to
|
||||
leave the Blocked state (which it will have done) and the task that left
|
||||
the Blocked state has a priority higher than the currently running task
|
||||
(which it will have). */
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increase the block time used by the Tx task, as described at the top
|
||||
of this file. */
|
||||
xSendBlockTime += xIncrement;
|
||||
|
||||
/* If the block time has gone over the configured maximum then set it to
|
||||
an infinite block time to allow the MCU to go into its STOP low power
|
||||
mode. */
|
||||
if( xSendBlockTime > xMaxBlockTime )
|
||||
{
|
||||
xSendBlockTime = portMAX_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
EXTI_ClearITPendingBit( EXTI_Line0 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The configPOST_STOP_PROCESSING() macro is called when the MCU leaves its
|
||||
STOP low power mode. The macro is set in FreeRTOSConfig.h to call
|
||||
vMainPostStopProcessing(). */
|
||||
void vMainPostStopProcessing( void )
|
||||
{
|
||||
extern void SetSysClock( void );
|
||||
|
||||
/* The STOP low power mode has been exited. Reconfigure the system clocks
|
||||
ready for normally running again. */
|
||||
SetSysClock();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
@ -10,7 +10,7 @@ define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
|
||||
define symbol __ICFEDIT_region_RAM_end__ = 0x20003FFF;
|
||||
/*-Sizes-*/
|
||||
define symbol __ICFEDIT_size_cstack__ = 0x400;
|
||||
define symbol __ICFEDIT_size_heap__ = 0x200;
|
||||
define symbol __ICFEDIT_size_heap__ = 0x0;
|
||||
/**** End of ICF editor section. ###ICF###*/
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user