mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			STM32F4 - Add low power timer
							parent
							
								
									58c12f19b2
								
							
						
					
					
						commit
						21b11a26ec
					
				| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 *******************************************************************************
 | 
			
		||||
 * Copyright (c) 2016, STMicroelectronics
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
 *    this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
			
		||||
 *    this list of conditions and the following disclaimer in the documentation
 | 
			
		||||
 *    and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. Neither the name of STMicroelectronics nor the names of its contributors
 | 
			
		||||
 *    may be used to endorse or promote products derived from this software
 | 
			
		||||
 *    without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
			
		||||
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
			
		||||
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *******************************************************************************
 | 
			
		||||
 */
 | 
			
		||||
#include "device.h"
 | 
			
		||||
 | 
			
		||||
#if DEVICE_LOWPOWERTIMER
 | 
			
		||||
 | 
			
		||||
#include "ticker_api.h"
 | 
			
		||||
#include "lp_ticker_api.h"
 | 
			
		||||
#include "rtc_api.h"
 | 
			
		||||
#include "rtc_api_hal.h"
 | 
			
		||||
 | 
			
		||||
static uint8_t lp_ticker_inited = 0;
 | 
			
		||||
 | 
			
		||||
void lp_ticker_init(void)
 | 
			
		||||
{
 | 
			
		||||
    if (lp_ticker_inited) return;
 | 
			
		||||
    lp_ticker_inited = 1;
 | 
			
		||||
    
 | 
			
		||||
    rtc_init();
 | 
			
		||||
    rtc_set_irq_handler((uint32_t) lp_ticker_irq_handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t lp_ticker_read(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t usecs;
 | 
			
		||||
    time_t time;
 | 
			
		||||
 | 
			
		||||
    lp_ticker_init();
 | 
			
		||||
    
 | 
			
		||||
    do {
 | 
			
		||||
      time = rtc_read();
 | 
			
		||||
      usecs = rtc_read_subseconds();
 | 
			
		||||
    } while (time != rtc_read());
 | 
			
		||||
    
 | 
			
		||||
    return (time * 1000000) + usecs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t delta;
 | 
			
		||||
 | 
			
		||||
    delta = timestamp - lp_ticker_read();
 | 
			
		||||
    rtc_set_wake_up_timer(delta);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lp_ticker_disable_interrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    rtc_deactivate_wake_up_timer();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lp_ticker_clear_interrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 *******************************************************************************
 | 
			
		||||
 * Copyright (c) 2014, STMicroelectronics
 | 
			
		||||
 * Copyright (c) 2016, STMicroelectronics
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +28,7 @@
 | 
			
		|||
 *******************************************************************************
 | 
			
		||||
 */
 | 
			
		||||
#include "rtc_api.h"
 | 
			
		||||
#include "rtc_api_hal.h"
 | 
			
		||||
 | 
			
		||||
#if DEVICE_RTC
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,12 +40,31 @@ static int rtc_inited = 0;
 | 
			
		|||
 | 
			
		||||
static RTC_HandleTypeDef RtcHandle;
 | 
			
		||||
 | 
			
		||||
#if DEVICE_RTC_LSI
 | 
			
		||||
    #define RTC_CLOCK LSI_VALUE
 | 
			
		||||
#else
 | 
			
		||||
    #define RTC_CLOCK LSE_VALUE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DEVICE_LOWPOWERTIMER
 | 
			
		||||
    #define RTC_ASYNCH_PREDIV ((RTC_CLOCK - 1) / 0x8000)
 | 
			
		||||
    #define RTC_SYNCH_PREDIV  (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1)
 | 
			
		||||
#else
 | 
			
		||||
    #define RTC_ASYNCH_PREDIV (0x007F)
 | 
			
		||||
    #define RTC_SYNCH_PREDIV  (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1)    
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DEVICE_LOWPOWERTIMER
 | 
			
		||||
    static void (*irq_handler)(void);
 | 
			
		||||
    static void RTC_IRQHandler();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void rtc_init(void)
 | 
			
		||||
{
 | 
			
		||||
    RCC_OscInitTypeDef RCC_OscInitStruct;
 | 
			
		||||
    uint32_t rtc_freq = 0;
 | 
			
		||||
 | 
			
		||||
#if DEVICE_RTC_LSI
 | 
			
		||||
    if (rtc_inited) return;
 | 
			
		||||
    rtc_inited = 1;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -59,9 +79,7 @@ void rtc_init(void)
 | 
			
		|||
        // Connect LSE to RTC
 | 
			
		||||
        __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE);
 | 
			
		||||
        __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
 | 
			
		||||
        rtc_freq = LSE_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    } else {
 | 
			
		||||
      error("RTC error: LSE clock initialization failed.");
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -86,16 +104,14 @@ void rtc_init(void)
 | 
			
		|||
	// Connect LSI to RTC
 | 
			
		||||
	__HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI);
 | 
			
		||||
	__HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI);
 | 
			
		||||
	// [TODO] This value is LSI typical value. To be measured precisely using a timer input capture
 | 
			
		||||
	rtc_freq = LSI_VALUE;
 | 
			
		||||
#endif    
 | 
			
		||||
 | 
			
		||||
    // Enable RTC
 | 
			
		||||
    __HAL_RCC_RTC_ENABLE();
 | 
			
		||||
 | 
			
		||||
    RtcHandle.Init.HourFormat     = RTC_HOURFORMAT_24;
 | 
			
		||||
    RtcHandle.Init.AsynchPrediv   = 127;
 | 
			
		||||
    RtcHandle.Init.SynchPrediv    = (rtc_freq / 128) - 1;
 | 
			
		||||
    RtcHandle.Init.AsynchPrediv   = RTC_ASYNCH_PREDIV;
 | 
			
		||||
    RtcHandle.Init.SynchPrediv    = RTC_SYNCH_PREDIV;
 | 
			
		||||
    RtcHandle.Init.OutPut         = RTC_OUTPUT_DISABLE;
 | 
			
		||||
    RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
 | 
			
		||||
    RtcHandle.Init.OutPutType     = RTC_OUTPUT_TYPE_OPENDRAIN;
 | 
			
		||||
| 
						 | 
				
			
			@ -103,6 +119,20 @@ void rtc_init(void)
 | 
			
		|||
    if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
 | 
			
		||||
        error("RTC error: RTC initialization failed.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if DEVICE_LOWPOWERTIMER
 | 
			
		||||
#if DEVICE_RTC_LSI
 | 
			
		||||
    rtc_write(0);
 | 
			
		||||
#else
 | 
			
		||||
    if (!rtc_isenabled()) {
 | 
			
		||||
        rtc_write(0);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    NVIC_ClearPendingIRQ(RTC_WKUP_IRQn);
 | 
			
		||||
    NVIC_DisableIRQ(RTC_WKUP_IRQn);
 | 
			
		||||
    NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
 | 
			
		||||
    NVIC_EnableIRQ(RTC_WKUP_IRQn);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_free(void)
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +159,7 @@ void rtc_free(void)
 | 
			
		|||
    RCC_OscInitStruct.LSIState       = RCC_LSI_OFF;
 | 
			
		||||
    RCC_OscInitStruct.LSEState       = RCC_LSE_OFF;
 | 
			
		||||
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
 | 
			
		||||
 | 
			
		||||
#if DEVICE_RTC_LSI
 | 
			
		||||
    rtc_inited = 0;
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -218,4 +249,50 @@ void rtc_write(time_t t)
 | 
			
		|||
    HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if DEVICE_LOWPOWERTIMER
 | 
			
		||||
 | 
			
		||||
static void RTC_IRQHandler()
 | 
			
		||||
{
 | 
			
		||||
    HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
 | 
			
		||||
{
 | 
			
		||||
    if (irq_handler) {
 | 
			
		||||
        // Fire the user callback
 | 
			
		||||
        irq_handler();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_set_irq_handler(uint32_t handler)
 | 
			
		||||
{
 | 
			
		||||
    irq_handler = (void (*)(void))handler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t rtc_read_subseconds(void)
 | 
			
		||||
{
 | 
			
		||||
    return 1000000.f * ((double)(RTC_SYNCH_PREDIV - RTC->SSR) / (RTC_SYNCH_PREDIV + 1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_set_wake_up_timer(uint32_t delta)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t wake_up_counter = delta / (2000000 / RTC_CLOCK);
 | 
			
		||||
  
 | 
			
		||||
    if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, wake_up_counter,
 | 
			
		||||
                                    RTC_WAKEUPCLOCK_RTCCLK_DIV2) != HAL_OK) {
 | 
			
		||||
        error("Set wake up timer failed\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_deactivate_wake_up_timer(void)
 | 
			
		||||
{
 | 
			
		||||
    HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_synchronize(void)
 | 
			
		||||
{
 | 
			
		||||
    HAL_RTC_WaitForSynchro(&RtcHandle);
 | 
			
		||||
}
 | 
			
		||||
#endif // DEVICE_LOWPOWERTIMER
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,79 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
* Copyright (c) 2016, STMicroelectronics
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*
 | 
			
		||||
* 1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
*    this list of conditions and the following disclaimer.
 | 
			
		||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
			
		||||
*    this list of conditions and the following disclaimer in the documentation
 | 
			
		||||
*    and/or other materials provided with the distribution.
 | 
			
		||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
 | 
			
		||||
*    may be used to endorse or promote products derived from this software
 | 
			
		||||
*    without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
			
		||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
			
		||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef MBED_RTC_API_HAL_H
 | 
			
		||||
#define MBED_RTC_API_HAL_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "rtc_api.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
/*
 | 
			
		||||
 * Extend rtc_api.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** Set the given function as handler of wakeup timer event.
 | 
			
		||||
 *
 | 
			
		||||
 * @param handler    The function to set as handler
 | 
			
		||||
 */
 | 
			
		||||
void rtc_set_irq_handler(uint32_t handler);
 | 
			
		||||
 | 
			
		||||
/** Read the subsecond register.
 | 
			
		||||
 *
 | 
			
		||||
 * @return The remaining time as microseconds (0-999999)
 | 
			
		||||
 */
 | 
			
		||||
uint32_t rtc_read_subseconds(void);
 | 
			
		||||
 | 
			
		||||
/** Program a wake up timer event in delta microseconds.
 | 
			
		||||
 *
 | 
			
		||||
 * @param delta    The time to wait
 | 
			
		||||
 */
 | 
			
		||||
void rtc_set_wake_up_timer(uint32_t delta);
 | 
			
		||||
 | 
			
		||||
/** Disable the wake up timer event.
 | 
			
		||||
 *
 | 
			
		||||
 * The wake up timer use auto reload, you have to deactivate it manually.
 | 
			
		||||
 */
 | 
			
		||||
void rtc_deactivate_wake_up_timer(void);
 | 
			
		||||
 | 
			
		||||
/** Synchronise the RTC shadow registers.
 | 
			
		||||
 *
 | 
			
		||||
 * Must be called after a deepsleep.
 | 
			
		||||
 */
 | 
			
		||||
void rtc_synchronize(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +28,8 @@
 | 
			
		|||
 *******************************************************************************
 | 
			
		||||
 */
 | 
			
		||||
#include "sleep_api.h"
 | 
			
		||||
#include "rtc_api_hal.h"
 | 
			
		||||
 | 
			
		||||
#if DEVICE_SLEEP
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +51,10 @@ void deepsleep(void)
 | 
			
		|||
 | 
			
		||||
    // After wake-up from STOP reconfigure the PLL
 | 
			
		||||
    SetSysClock();
 | 
			
		||||
    
 | 
			
		||||
#if DEVICE_LOWPOWERTIMER
 | 
			
		||||
    rtc_synchronize();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue