STM32L discovery demo is now demonstrating three low power modes - still needs clean up.

pull/4/head
Richard Barry 11 years ago
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 )
{
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 ul = 0;
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…
Cancel
Save