mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-06-05 20:09:05 -04:00
STM32L discovery demo is now demonstrating three low power modes - still needs clean up.
This commit is contained in:
parent
9001b7b77a
commit
3d00d47239
|
@ -49,7 +49,7 @@
|
|||
</option>
|
||||
<option>
|
||||
<name>RunToEnable</name>
|
||||
<state>1</state>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>RunToName</name>
|
||||
|
@ -1271,7 +1271,7 @@
|
|||
</plugin>
|
||||
<plugin>
|
||||
<file>$TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin</file>
|
||||
<loadFlag>0</loadFlag>
|
||||
<loadFlag>1</loadFlag>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<file>$TOOLKIT_DIR$\plugins\rtos\PowerPac\PowerPacRTOS.ewplugin</file>
|
||||
|
|
|
@ -234,7 +234,7 @@
|
|||
<option>
|
||||
<name>CCAllowList</name>
|
||||
<version>1</version>
|
||||
<state>1111111</state>
|
||||
<state>0000000</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>CCDebugInfo</name>
|
||||
|
@ -328,7 +328,7 @@
|
|||
</option>
|
||||
<option>
|
||||
<name>CCOptLevel</name>
|
||||
<state>3</state>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>CCOptStrategy</name>
|
||||
|
@ -337,7 +337,7 @@
|
|||
</option>
|
||||
<option>
|
||||
<name>CCOptLevelSlave</name>
|
||||
<state>3</state>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>CompilerMisraRules98</name>
|
||||
|
@ -1017,6 +1017,9 @@
|
|||
<file>
|
||||
<name>$PROJ_DIR$\ST_Code\Libraries\STM32L1xx_StdPeriph_Driver\src\stm32l1xx_syscfg.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\ST_Code\Libraries\STM32L1xx_StdPeriph_Driver\src\stm32l1xx_tim.c</name>
|
||||
</file>
|
||||
</group>
|
||||
<group>
|
||||
<name>TouchSensingDriver</name>
|
||||
|
@ -1088,6 +1091,9 @@
|
|||
<file>
|
||||
<name>$PROJ_DIR$\stm32l1xx_it.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\STM32L_low_power_tick_management.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\tsl_user.c</name>
|
||||
</file>
|
||||
|
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
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!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <limits.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* ST library functions. */
|
||||
#include "stm32l1xx.h"
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* SysTick timer.
|
||||
*/
|
||||
#if configCREATE_LOW_POWER_DEMO == 1
|
||||
|
||||
/* The frequency at which TIM2 should 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 )
|
||||
|
||||
#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.
|
||||
*/
|
||||
void TIM2_IRQHandler( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Calculate how many clock increments make up a single tick period. */
|
||||
static const uint32_t ulReloadValueForOneTick = ( ( lpCLOCK_INPUT_FREQUENCY / configTICK_RATE_HZ ) - 1 );
|
||||
|
||||
/* Holds the maximum number of ticks that can be suppressed - which is
|
||||
basically how far into the future an interrupt can be generated. Set during
|
||||
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. */
|
||||
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
|
||||
clears the interrupt, which is specific to the clock being used to generate the
|
||||
tick. */
|
||||
void TIM2_IRQHandler( void )
|
||||
{
|
||||
TIM_ClearITPendingBit( TIM2, TIM_IT_Update );
|
||||
TIM_SetAutoreload( TIM2, ( uint16_t ) ulReloadValueForOneTick );
|
||||
|
||||
/* Protect incrementing the tick with an interrupt safe critical section. */
|
||||
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
|
||||
/* Just completely clear the interrupt mask on exit by passing 0 because
|
||||
it is known that this interrupt will only ever execute with the lowest
|
||||
possible interrupt priority. */
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||
|
||||
/* 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. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
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;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE );
|
||||
TIM_SetCounter( TIM2, 0 );
|
||||
TIM_Cmd( TIM2, ENABLE );
|
||||
|
||||
/* See the comments where xMaximumPossibleSuppressedTicks is declared. */
|
||||
xMaximumPossibleSuppressedTicks = ( ( unsigned long ) USHRT_MAX ) / ulReloadValueForOneTick;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Override the default definition of vPortSuppressTicksAndSleep() that is
|
||||
weakly defined in the FreeRTOS Cortex-M3 port layer with a version that manages
|
||||
the TIM2 interrupt, as the tick is generated from TIM2 compare matches events. */
|
||||
void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulCounterValue, ulCompleteTickPeriods;
|
||||
eSleepModeStatus eSleepAction;
|
||||
portTickType xModifiableIdleTime;
|
||||
const portTickType xRegulatorOffIdleTime = 30;
|
||||
|
||||
/* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */
|
||||
|
||||
/* Make sure the TIM2 reload value does not overflow the counter. */
|
||||
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||
{
|
||||
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
TIM_Cmd( TIM2, DISABLE );
|
||||
|
||||
/* 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" );
|
||||
__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
|
||||
suppressed for the entire xExpectedIdleTime period. */
|
||||
ulTickFlag = pdFALSE;
|
||||
|
||||
/* If a context switch is pending then abandon the low power entry as
|
||||
the context switch might have been pended by an external interrupt that
|
||||
requires processing. */
|
||||
eSleepAction = eTaskConfirmSleepModeStatus();
|
||||
if( eSleepAction == eAbortSleep )
|
||||
{
|
||||
/* Restart tick. */
|
||||
TIM_Cmd( TIM2, ENABLE );
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
above. */
|
||||
__asm volatile ( "cpsie i" );
|
||||
}
|
||||
else if( eSleepAction == eNoTasksWaitingTimeout )
|
||||
{
|
||||
/* 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();
|
||||
PWR_EnterSTOPMode( PWR_Regulator_LowPower, PWR_SLEEPEntry_WFI );
|
||||
configPOST_STOP_PROCESSING();
|
||||
|
||||
/* Restart tick. */
|
||||
TIM_SetCounter( TIM2, 0 );
|
||||
TIM_Cmd( TIM2, ENABLE );
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
above. */
|
||||
__asm volatile ( "cpsie i" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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 );
|
||||
configASSERT( ulCounterValue < ( uint32_t ) USHRT_MAX );
|
||||
configASSERT( ulCounterValue != 0 );
|
||||
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. */
|
||||
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
|
||||
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. */
|
||||
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 )
|
||||
{
|
||||
/* A slightly higher power sleep mode with a faster wake up
|
||||
time. */
|
||||
PWR_EnterSleepMode( PWR_Regulator_ON, PWR_SLEEPEntry_WFI );
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow the application to define some post sleep processing. */
|
||||
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. */
|
||||
TIM_Cmd( TIM2, DISABLE );
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
above. */
|
||||
__asm volatile ( "cpsie i" );
|
||||
__asm volatile ( "dsb" );
|
||||
__asm volatile ( "isb" );
|
||||
|
||||
if( ulTickFlag != pdFALSE )
|
||||
{
|
||||
/* 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 );
|
||||
configASSERT( ulCounterValue <= ( uint32_t ) USHRT_MAX );
|
||||
configASSERT( ulCounterValue != 0 );
|
||||
TIM_SetAutoreload( TIM2, ( uint16_t ) ulCounterValue );
|
||||
TIM_SetCounter( TIM2, 0 );
|
||||
|
||||
/* The tick interrupt handler will already have pended the tick
|
||||
processing in the kernel. 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 sleeping. The
|
||||
actual stepping of the tick appears later in this function. */
|
||||
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something other than the tick interrupt ended the sleep. How
|
||||
many complete tick periods passed while the processor was
|
||||
sleeping? */
|
||||
ulCompleteTickPeriods = ( ( uint32_t ) TIM_GetCounter( TIM2 ) ) / 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 )
|
||||
{
|
||||
/* There is no fraction remaining. */
|
||||
ulCounterValue = ulReloadValueForOneTick;
|
||||
ulCompleteTickPeriods++;
|
||||
}
|
||||
TIM_SetAutoreload( TIM2, ( uint16_t ) ulCounterValue );
|
||||
TIM_SetCounter( TIM2, 0 );
|
||||
}
|
||||
|
||||
/* Restart TIM2 so it runs up to the reload value. The reload value
|
||||
will get set to the value required to generate exactly one tick period
|
||||
the next time the TIM2 interrupt executes. */
|
||||
TIM_Cmd( TIM2, ENABLE );
|
||||
|
||||
/* Wind the tick forward by the number of tick periods that the CPU
|
||||
remained in a low power state. */
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* configCREATE_LOW_POWER_DEMO == 1 */
|
||||
|
|
@ -145,7 +145,7 @@ __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}
|
|||
* @{
|
||||
*/
|
||||
|
||||
static void SetSysClock(void);
|
||||
void SetSysClock(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -281,7 +281,7 @@ void SystemCoreClockUpdate (void)
|
|||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void SetSysClock(void)
|
||||
void SetSysClock(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSIStatus = 0;
|
||||
|
||||
|
|
|
@ -82,14 +82,33 @@
|
|||
#ifdef __ICCARM__
|
||||
#include <stdint.h>
|
||||
extern uint32_t SystemCoreClock;
|
||||
void vMainPostStopProcessing( void );
|
||||
void vAssertCalled( unsigned long ulLine, const char * const pcFileName );
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
||||
#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. */
|
||||
#else
|
||||
#define configCPU_CLOCK_HZ SystemCoreClock
|
||||
#define configSYSTICK_CLOCK_HZ ( SystemCoreClock >> 3UL )
|
||||
#define configUSE_TICKLESS_IDLE 0
|
||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||
#endif /* configCREATE_LOW_POWER_DEMO */
|
||||
|
||||
#define configPRE_STOP_PROCESSING()
|
||||
#define configPOST_STOP_PROCESSING() vMainPostStopProcessing()
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 1
|
||||
#define configCPU_CLOCK_HZ ( SystemCoreClock )
|
||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||
#define configMAX_PRIORITIES ( 5 )
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) )
|
||||
|
@ -119,6 +138,9 @@ to exclude the API function. */
|
|||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
|
||||
/* Standard assert semantics. */
|
||||
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ )
|
||||
|
||||
/* Use the system definition, if there is one */
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||
|
|
|
@ -132,11 +132,13 @@
|
|||
#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 )
|
||||
|
@ -150,9 +152,6 @@ empty. */
|
|||
/* The LED used to indicate that a value has been received on the queue. */
|
||||
#define mainQUEUE_LED ( 0 )
|
||||
|
||||
/* The rate at which the Tx task sends to the queue. */
|
||||
#define mainTX_DELAY ( 500UL / portTICK_RATE_MS )
|
||||
|
||||
/* A block time of zero simply means "don't block". */
|
||||
#define mainDONT_BLOCK ( 0 )
|
||||
|
||||
|
@ -162,7 +161,7 @@ empty. */
|
|||
/* The length of time the LED will remain on for. It is on just long enough
|
||||
to be able to see with the human eye so as not to distort the power readings too
|
||||
much. */
|
||||
#define mainLED_TOGGLE_DELAY ( 20 / portTICK_RATE_MS )
|
||||
#define mainLED_TOGGLE_DELAY ( 10 / portTICK_RATE_MS )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -184,10 +183,16 @@ static void prvSetupHardware( void );
|
|||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static const portTickType xMaxBlockTime = ( 500L / portTICK_RATE_MS ), xMinBlockTime = ( 100L / portTICK_RATE_MS );
|
||||
portTickType xSendBlockTime = ( 100UL / portTICK_RATE_MS );
|
||||
static xSemaphoreHandle xTxSemaphore = NULL;
|
||||
|
||||
int main( void )
|
||||
{
|
||||
prvSetupHardware();
|
||||
|
||||
xTxSemaphore = xSemaphoreCreateBinary();
|
||||
|
||||
/* Create the queue. */
|
||||
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );
|
||||
configASSERT( xQueue );
|
||||
|
@ -216,10 +221,9 @@ const unsigned long ulValueToSend = mainQUEUED_VALUE;
|
|||
|
||||
for( ;; )
|
||||
{
|
||||
/* Place this task into the blocked state until it is time to run again.
|
||||
The kernel will place the MCU into the Retention low power sleep state
|
||||
when the idle task next runs. */
|
||||
vTaskDelay( mainTX_DELAY );
|
||||
/* Place this task into the blocked state until it is time to run
|
||||
again. */
|
||||
xSemaphoreTake( xTxSemaphore, xSendBlockTime );
|
||||
|
||||
/* Send to the queue - causing the queue receive task to flash its LED.
|
||||
It should not be necessary to block on the queue send because the Rx
|
||||
|
@ -253,6 +257,39 @@ unsigned long ulReceivedValue;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void EXTI0_IRQHandler(void)
|
||||
{
|
||||
static const portTickType xIncrement = 200UL / portTICK_RATE_MS;
|
||||
|
||||
if( xSendBlockTime == portMAX_DELAY )
|
||||
{
|
||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
/* Unblock the Tx task again. */
|
||||
xSemaphoreGiveFromISR( xTxSemaphore, &xHigherPriorityTaskWoken );
|
||||
|
||||
/* Start over with the short block time that will not result in the
|
||||
tick being turned off or a low power mode being entered. */
|
||||
xSendBlockTime = xMinBlockTime;
|
||||
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
else
|
||||
{
|
||||
xSendBlockTime += xIncrement;
|
||||
|
||||
if( xSendBlockTime > xMaxBlockTime )
|
||||
{
|
||||
/* Set the send block time to be infinite to force entry into the STOP
|
||||
sleep mode. */
|
||||
xSendBlockTime = portMAX_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
EXTI_ClearITPendingBit( EXTI_Line0 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupHardware( void )
|
||||
{
|
||||
/* GPIO, EXTI and NVIC Init structure declaration */
|
||||
|
@ -266,59 +303,57 @@ void SystemCoreClockUpdate( void );
|
|||
/* Essential on STM32 Cortex-M devices. */
|
||||
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
|
||||
|
||||
/* Enable HSI Clock */
|
||||
RCC_HSICmd(ENABLE);
|
||||
/* Systick is fed from HCLK/8. */
|
||||
SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK_Div8 );
|
||||
|
||||
/*!< Wait till HSI is ready */
|
||||
while( RCC_GetFlagStatus( RCC_FLAG_HSIRDY ) == RESET );
|
||||
/* Enable HSI Clock. */
|
||||
// RCC_HSICmd( ENABLE );
|
||||
|
||||
/*!< Wait till HSI is ready. */
|
||||
// while( RCC_GetFlagStatus( RCC_FLAG_HSIRDY ) == RESET );
|
||||
|
||||
/* Set HSI as sys clock*/
|
||||
RCC_SYSCLKConfig( RCC_SYSCLKSource_HSI );
|
||||
// RCC_SYSCLKConfig( RCC_SYSCLKSource_HSI );
|
||||
|
||||
/* Set MSI clock range to ~4.194MHz*/
|
||||
/* Set MSI clock range to ~4.194MHz. */
|
||||
RCC_MSIRangeConfig( RCC_MSIRange_6 );
|
||||
|
||||
/* Enable the GPIOs clocks */
|
||||
/* Enable the GPIOs clocks. */
|
||||
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC| RCC_AHBPeriph_GPIOD| RCC_AHBPeriph_GPIOE| RCC_AHBPeriph_GPIOH, ENABLE );
|
||||
|
||||
/* Enable comparator, PWR mngt clocks */
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_COMP | RCC_APB1Periph_PWR,ENABLE );
|
||||
/* Enable comparator clocks. */
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_COMP, ENABLE );
|
||||
|
||||
/* Enable ADC & SYSCFG clocks */
|
||||
/* Enable SYSCFG clocks. */
|
||||
RCC_APB2PeriphClockCmd( RCC_APB2Periph_SYSCFG , ENABLE );
|
||||
|
||||
/* Allow access to the RTC */
|
||||
PWR_RTCAccessCmd( ENABLE );
|
||||
// PWR_RTCAccessCmd( ENABLE );
|
||||
|
||||
/* Reset RTC Backup Domain */
|
||||
RCC_RTCResetCmd( ENABLE );
|
||||
RCC_RTCResetCmd( DISABLE );
|
||||
// RCC_RTCResetCmd( ENABLE );
|
||||
// RCC_RTCResetCmd( DISABLE );
|
||||
|
||||
/* LSE Enable */
|
||||
RCC_LSEConfig( RCC_LSE_ON );
|
||||
// RCC_LSEConfig( RCC_LSE_ON );
|
||||
//RCC_LSICmd( ENABLE ); //_RB_
|
||||
|
||||
/* Wait until LSE is ready */
|
||||
while( RCC_GetFlagStatus( RCC_FLAG_LSERDY ) == RESET );
|
||||
|
||||
/* RTC Clock Source Selection */
|
||||
RCC_RTCCLKConfig( RCC_RTCCLKSource_LSE );
|
||||
|
||||
/* Enable the RTC */
|
||||
RCC_RTCCLKCmd( ENABLE );
|
||||
// while( RCC_GetFlagStatus( RCC_FLAG_LSERDY ) == RESET );
|
||||
|
||||
/* Disable HSE */
|
||||
RCC_HSEConfig( RCC_HSE_OFF );
|
||||
// RCC_HSEConfig( RCC_HSE_OFF );
|
||||
|
||||
if( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) != RESET )
|
||||
{
|
||||
/* Stay in infinite loop if HSE is not disabled*/
|
||||
while( 1 );
|
||||
}
|
||||
// if( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) != RESET )
|
||||
// {
|
||||
/* Stay in infinite loop if HSE is not disabled. */
|
||||
// while( 1 );
|
||||
// }
|
||||
|
||||
/* Set internal voltage regulator to 1.8V */
|
||||
PWR_VoltageScalingConfig( PWR_VoltageScaling_Range1 );
|
||||
/* Set internal voltage regulator to 1.5V. */
|
||||
PWR_VoltageScalingConfig( PWR_VoltageScaling_Range2 );
|
||||
|
||||
/* Wait Until the Voltage Regulator is ready */
|
||||
/* Wait Until the Voltage Regulator is ready. */
|
||||
while( PWR_GetFlagStatus( PWR_FLAG_VOS ) != RESET );
|
||||
|
||||
/* Configure User Button pin as input */
|
||||
|
@ -329,7 +364,7 @@ void SystemCoreClockUpdate( void );
|
|||
GPIO_Init( USERBUTTON_GPIO_PORT, &GPIO_InitStructure );
|
||||
|
||||
/* Select User Button pin as input source for EXTI Line */
|
||||
SYSCFG_EXTILineConfig( EXTI_PortSourceGPIOA,EXTI_PinSource0 );
|
||||
SYSCFG_EXTILineConfig( EXTI_PortSourceGPIOA, EXTI_PinSource0 );
|
||||
|
||||
/* Configure EXT1 Line 0 in interrupt mode trigged on Rising edge */
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line0 ; /* PA0 for User button AND IDD_WakeUP */
|
||||
|
@ -413,16 +448,36 @@ void vApplicationTickHook( void )
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vAssertCalled( void )
|
||||
void vMainPostStopProcessing( void )
|
||||
{
|
||||
volatile unsigned long ul = 0;
|
||||
extern void SetSysClock( void );
|
||||
|
||||
SetSysClock();
|
||||
/* Unblock the Tx task again. */
|
||||
// xSemaphoreGiveFromISR( xTxSemaphore, NULL );
|
||||
|
||||
/* Start over with the short block time that will not result in the
|
||||
tick being turned off or a low power mode being entered. */
|
||||
// xSendBlockTime = xMinBlockTime;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vAssertCalled( unsigned long ulLine, const char * const pcFileName )
|
||||
{
|
||||
volatile unsigned long ulSetToNonZeroInDebuggerToContinue = 0;
|
||||
|
||||
/* Parameters are not used. */
|
||||
( void ) ulLine;
|
||||
( void ) pcFileName;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Set ul to a non-zero value using the debugger to step out of this
|
||||
function. */
|
||||
while( ul == 0 )
|
||||
while( ulSetToNonZeroInDebuggerToContinue == 0 )
|
||||
{
|
||||
/* Use the debugger to set ulSetToNonZeroInDebuggerToContinue to a
|
||||
non zero value to step out of this function to the point that raised
|
||||
this assert(). */
|
||||
__asm volatile( "NOP" );
|
||||
__asm volatile( "NOP" );
|
||||
}
|
||||
}
|
||||
|
@ -430,6 +485,35 @@ volatile unsigned long ul = 0;
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
|
||||
/**
|
||||
* @brief Reports the name of the source file and the source line number
|
||||
* where the assert_param error has occurred.
|
||||
* @param file: pointer to the source file name
|
||||
* @param line: assert_param error line source number
|
||||
* @retval None
|
||||
*/
|
||||
void assert_failed(uint8_t* file, uint32_t line)
|
||||
{
|
||||
/* User can add his own implementation to report the file name and line number,
|
||||
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
/* Infinite loop */
|
||||
while (1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
******************************************************************************
|
||||
|
@ -962,6 +1046,273 @@ void vApplicationStackOverflowHook( void )
|
|||
}
|
||||
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
||||
/* Ensure the interrupt is clear before exiting. The RTC uses EXTI line 20
|
||||
to bring the CPU out of sleep. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void _vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulWakeupValue, ulCompleteTickPeriods;
|
||||
eSleepModeStatus eSleepAction;
|
||||
portTickType xModifiableIdleTime;
|
||||
|
||||
/* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */
|
||||
|
||||
/* Make sure the wakeup timer reload value does not overflow the counter. */
|
||||
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||
{
|
||||
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||
}
|
||||
|
||||
/* Calculate the reload value required to wait xExpectedIdleTime tick
|
||||
periods. */
|
||||
ulWakeupValue = ( ( ulWakeupValueForOneTick + 1UL ) * xExpectedIdleTime ) - 1UL;
|
||||
if( ulWakeupValue > ulStoppedTimerCompensation )
|
||||
{
|
||||
/* Compensate for the fact that the RTC is going to be stopped
|
||||
momentarily. */
|
||||
ulWakeupValue -= ulStoppedTimerCompensation;
|
||||
}
|
||||
|
||||
/* Stop the RTC momentarily. The time the RTC 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. */
|
||||
prvDisableWakeupTimer();
|
||||
|
||||
/* 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" );
|
||||
|
||||
/* 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
|
||||
suppressed for the entire xExpectedIdleTime period. */
|
||||
ulTickFlag = pdFALSE;
|
||||
|
||||
/* If a context switch is pending then abandon the low power entry as
|
||||
the context switch might have been pended by an external interrupt that
|
||||
requires processing. */
|
||||
eSleepAction = eTaskConfirmSleepModeStatus();
|
||||
if( eSleepAction == eAbortSleep )
|
||||
{
|
||||
/* Restart tick. */
|
||||
prvEnableWakeupTimer();
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
above. */
|
||||
__asm volatile ( "cpsie i" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Adjust the alarm value to take into account that the current time
|
||||
slice is already partially complete. */
|
||||
// ulWakeupValue -= ( RTC->WUTR & RTC_WUTR_WUT ); /* Current value. */
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
/* Set the Wakeup Timer value */
|
||||
RTC->WUTR = ulWakeupValue;
|
||||
|
||||
/* Enable the Wakeup Timer */
|
||||
RTC->CR |= (uint32_t)RTC_CR_WUTE;
|
||||
|
||||
/* Enable the write protection for RTC registers. */
|
||||
RTC->WPR = 0xFF;
|
||||
|
||||
/* Allow the application to define some pre-sleep processing. */
|
||||
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
|
||||
instruction. */
|
||||
if( xModifiableIdleTime > 0 )
|
||||
{
|
||||
/* Sleep until something happens. */
|
||||
__asm volatile ( "wfi" );
|
||||
__asm volatile ( "dsb" );
|
||||
}
|
||||
|
||||
/* Allow the application to define some post sleep processing. */
|
||||
configPOST_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
|
||||
/* Stop RTC. Again, the time the clock 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. */
|
||||
prvDisableWakeupTimer();
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
above. */
|
||||
__asm volatile ( "cpsie i" );
|
||||
|
||||
if( ulTickFlag != pdFALSE )
|
||||
{
|
||||
/* 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 alarm value with whatever remains of this tick period. */
|
||||
ulWakeupValue = ulWakeupValueForOneTick;//_RB_ - ( RTC->WUTR & RTC_WUTR_WUT ); /* Current value. */
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
/* Set the Wakeup Timer value */
|
||||
RTC->WUTR = ulWakeupValue;
|
||||
|
||||
/* Enable the write protection for RTC registers. */
|
||||
RTC->WPR = 0xFF;
|
||||
|
||||
/* The tick interrupt handler will already have pended the tick
|
||||
processing in the kernel. 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 sleeping. The
|
||||
actual stepping of the tick appears later in this function. */
|
||||
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something other than the tick interrupt ended the sleep. How
|
||||
many complete tick periods passed while the processor was
|
||||
sleeping? */
|
||||
ulCompleteTickPeriods = ( RTC->WUTR & RTC_WUTR_WUT ) / ulWakeupValueForOneTick;
|
||||
|
||||
/* The alarm value is set to whatever fraction of a single tick
|
||||
period remains. */
|
||||
ulWakeupValue = ( RTC->WUTR & RTC_WUTR_WUT ) - ( ulCompleteTickPeriods * ulWakeupValueForOneTick );
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
/* Set the Wakeup Timer value */
|
||||
RTC->WUTR = ulWakeupValue;
|
||||
|
||||
/* Enable the write protection for RTC registers. */
|
||||
RTC->WPR = 0xFF;
|
||||
}
|
||||
|
||||
/* Restart the RTC so it runs down from the wakeup value. The wakeup
|
||||
value will get set to the value required to generate exactly one tick
|
||||
period the next time the wakeup interrupt executes. */
|
||||
prvEnableWakeupTimer();
|
||||
|
||||
/* Wind the tick forward by the number of tick periods that the CPU
|
||||
remained in a low power state. */
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// RTC_ClearITPendingBit( RTC_IT_WUT );
|
||||
// EXTI_ClearITPendingBit( EXTI_Line20 );
|
||||
|
||||
|
||||
|
||||
#ifdef USE_RTC
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
EXTI_InitTypeDef EXTI_InitStructure;
|
||||
|
||||
/* Enable access to the RTC registers. */
|
||||
PWR_RTCAccessCmd( ENABLE );
|
||||
RCC_RTCResetCmd( ENABLE );
|
||||
RCC_RTCResetCmd( DISABLE );
|
||||
|
||||
/* LSE Enable */
|
||||
RCC_LSEConfig( RCC_LSE_ON );
|
||||
|
||||
/* Wait until LSE is ready. */
|
||||
while( RCC_GetFlagStatus( RCC_FLAG_LSERDY ) == RESET );
|
||||
|
||||
/* Enable the PWR clock. */
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR, ENABLE );
|
||||
|
||||
/* LSE used as RTC clock source. */
|
||||
RCC_RTCCLKConfig( RCC_RTCCLKSource_LSE ); /* 32.768KHz external */
|
||||
|
||||
/* Enable the RTC clock and wait for sync. */
|
||||
RCC_RTCCLKCmd( ENABLE );
|
||||
RTC_WaitForSynchro();
|
||||
|
||||
/* Watchdog timer user EXTI line 20 to wake from sleep. */
|
||||
EXTI_ClearITPendingBit( EXTI_Line20 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line20;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
/* Enable the RTC Wakeup Interrupt. */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_LOWEST_INTERRUPT_PRIORITY;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init( &NVIC_InitStructure );
|
||||
|
||||
/* Drive the wakeup clock from LSE/2 (32768/2) */
|
||||
RTC_WakeUpClockConfig( RTC_WakeUpClock_RTCCLK_Div2 );
|
||||
|
||||
/* Set count and reload values. */
|
||||
RTC_SetWakeUpCounter( ulReloadValueForOneTick );
|
||||
|
||||
/* Enable the RTC Wakeup Interrupt. */
|
||||
RTC_ITConfig( RTC_IT_WUT, ENABLE );
|
||||
|
||||
/* Enable Wakeup Counter. */
|
||||
RTC_WakeUpCmd( ENABLE );
|
||||
#endif
|
||||
|
||||
|
||||
static void prvDisableWakeupTimer( void )
|
||||
{
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
/* Disable the Wakeup Timer */
|
||||
RTC->CR &= (uint32_t)~RTC_CR_WUTE;
|
||||
|
||||
/* Wait till RTC WUTWF flag is set. */
|
||||
/* _RB_ Timeout needed. */
|
||||
do
|
||||
{
|
||||
} while( ( RTC->ISR & RTC_ISR_WUTWF ) == 0x00 );
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
RTC->WPR = 0xFF;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvEnableWakeupTimer( void )
|
||||
{
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
/* Enable the Wakeup Timer */
|
||||
RTC->CR |= (uint32_t)RTC_CR_WUTE;
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
RTC->WPR = 0xFF;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -116,10 +116,6 @@ void DebugMon_Handler(void)
|
|||
while (1);
|
||||
}
|
||||
|
||||
void EXTI0_IRQHandler(void)
|
||||
{
|
||||
EXTI_ClearITPendingBit(EXTI_Line0);
|
||||
}
|
||||
|
||||
|
||||
void RTC_WKUP_IRQHandler (void)
|
||||
|
|
Loading…
Reference in a new issue