Merge pull request #1796 from BartSX/lptickerF0

[STM32F0xx] LowPowerTicker implementation
pull/1966/merge
Martin Kojtal 2016-06-17 09:51:09 +01:00 committed by GitHub
commit abf9850559
4 changed files with 274 additions and 4 deletions

View File

@ -569,7 +569,7 @@
"inherits": ["Target"],
"progen": {"target": "nucleo-f030r8"},
"detect_code": ["0725"],
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"default_build": "small"
},
"NUCLEO_F031K6": {
@ -605,7 +605,7 @@
"inherits": ["Target"],
"progen": {"target": "nucleo-f070rb"},
"detect_code": ["0755"],
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"default_build": "small"
},
"NUCLEO_F072RB": {
@ -617,7 +617,7 @@
"inherits": ["Target"],
"progen": {"target": "nucleo-f072rb"},
"detect_code": ["0730"],
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"default_build": "small"
},
"NUCLEO_F091RC": {
@ -629,7 +629,7 @@
"inherits": ["Target"],
"progen": {"target": "nucleo-f091rc"},
"detect_code": ["0750"],
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"default_build": "small"
},
"NUCLEO_F103RB": {

View File

@ -0,0 +1,94 @@
/* 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;
static uint8_t lp_ticker_reconf_presc = 0;
void lp_ticker_init() {
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() {
uint32_t sub_secs, milis;
time_t time;
lp_ticker_init();
time = rtc_read();
sub_secs = rtc_read_subseconds();
milis = 1000 - (sub_secs * 1000 / rtc_ticker_get_synch_presc());
return (time * 1000000) + (milis * 1000);
}
void lp_ticker_set_interrupt(timestamp_t timestamp) {
uint32_t sub_secs, delta, milis;
time_t secs;
struct tm *timeinfo;
// Reconfigure RTC prescalers whenever the timestamp is below 30ms
if (!lp_ticker_reconf_presc && timestamp < 30000) {
rtc_reconfigure_prescalers();
lp_ticker_reconf_presc = 1;
}
milis = (timestamp % 1000000) / 1000;
secs = rtc_read();
delta = ((timestamp / 1000000) - secs);
secs += delta;
sub_secs = (rtc_ticker_get_synch_presc() * (1000 - milis)) / 1000;
timeinfo = localtime(&secs);
rtc_set_alarm(timeinfo, sub_secs);
}
void lp_ticker_disable_interrupt() {
lp_ticker_reconf_presc = 0;
rtc_ticker_disable_irq();
}
void lp_ticker_clear_interrupt() {
}
#endif

View File

@ -28,6 +28,9 @@
*******************************************************************************
*/
#include "rtc_api.h"
#include "rtc_api_hal.h"
#include "stm32f0xx.h"
#include "stm32f0xx_hal_rtc_ex.h"
#if DEVICE_RTC
@ -39,6 +42,57 @@ static int rtc_inited = 0;
static RTC_HandleTypeDef RtcHandle;
#if DEVICE_LOWPOWERTIMER
static uint32_t m_synch_prediv = RTC_SYNCH_PREDIV;
static uint32_t m_asynch_prediv = RTC_ASYNCH_PREDIV;
static void (*irq_handler)(void);
static void rtc_configure_time_and_date()
{
RTC_TimeTypeDef mTime;
RTC_DateTypeDef mDate;
mDate.WeekDay = 1;
mDate.Month = 1;
mDate.Date = 1;
mDate.Year = 1970;
if (HAL_RTC_SetDate(&RtcHandle, &mDate, RTC_FORMAT_BIN) != HAL_OK) {
error("Date set failed\n");
}
mTime.Hours = 0;
mTime.Minutes = 0;
mTime.Seconds = 0;
mTime.TimeFormat = RTC_HOURFORMAT12_AM;
mTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
mTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&RtcHandle, &mTime, RTC_FORMAT_BIN) != HAL_OK) {
error("Time set failed\n");
}
}
void RTC_IRQHandler()
{
HAL_RTC_AlarmIRQHandler(&RtcHandle);
}
void HAL_RTC_AlarmAEventCallback(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;
}
#endif
void rtc_init(void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
uint32_t rtc_freq = 0;
@ -92,8 +146,14 @@ void rtc_init(void) {
__HAL_RCC_RTC_ENABLE();
RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
#if !DEVICE_LOWPOWERTIMER
RtcHandle.Init.AsynchPrediv = 127;
RtcHandle.Init.SynchPrediv = (rtc_freq / 128) - 1;
#else
RtcHandle.Init.AsynchPrediv = m_asynch_prediv;
RtcHandle.Init.SynchPrediv = m_synch_prediv;
#endif
RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
@ -101,6 +161,12 @@ void rtc_init(void) {
if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
error("RTC error: RTC initialization failed.");
}
#if DEVICE_LOWPOWERTIMER
rtc_configure_time_and_date();
NVIC_SetVector(RTC_IRQn, (uint32_t)&RTC_IRQHandler);
HAL_NVIC_EnableIRQ(RTC_IRQn);
#endif
}
void rtc_free(void) {
@ -177,7 +243,12 @@ time_t rtc_read(void) {
timeinfo.tm_wday = dateStruct.WeekDay;
timeinfo.tm_mon = dateStruct.Month - 1;
timeinfo.tm_mday = dateStruct.Date;
#if DEVICE_LOWPOWERTIMER
//We need to add 52 to get the 1970 year
timeinfo.tm_year = dateStruct.Year + 52;
#else
timeinfo.tm_year = dateStruct.Year + 100;
#endif
timeinfo.tm_hour = timeStruct.Hours;
timeinfo.tm_min = timeStruct.Minutes;
timeinfo.tm_sec = timeStruct.Seconds;
@ -215,4 +286,48 @@ void rtc_write(time_t t) {
HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
}
#if DEVICE_LOWPOWERTIMER
void rtc_set_alarm(struct tm *ti, uint32_t subsecs)
{
RTC_AlarmTypeDef mAlarm;
mAlarm.AlarmTime.Hours = ti->tm_hour;
mAlarm.AlarmTime.Minutes = ti->tm_min;
mAlarm.AlarmTime.Seconds = ti->tm_sec;
mAlarm.AlarmTime.SubSeconds = subsecs;
mAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
mAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
mAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
mAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
mAlarm.AlarmDateWeekDay = 1;
mAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&RtcHandle, &mAlarm, RTC_FORMAT_BIN) != HAL_OK) {
error("Set Alarm failed\n");
}
}
void rtc_reconfigure_prescalers()
{
m_synch_prediv = 0x3FF;
m_asynch_prediv = 0x1F;
rtc_init();
}
uint32_t rtc_ticker_get_synch_presc()
{
return m_synch_prediv;
}
uint32_t rtc_read_subseconds()
{
return RTC->SSR;
}
void rtc_ticker_disable_irq()
{
HAL_RTC_DeactivateAlarm(&RtcHandle, RTC_ALARM_A);
}
#endif // DEVICE_LOWPOWERTIMER
#endif

View File

@ -0,0 +1,61 @@
/* 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
*/
// Prescaler values for LSE clock
#define RTC_ASYNCH_PREDIV 0x7F
#define RTC_SYNCH_PREDIV 0x00FF
void rtc_set_irq_handler(uint32_t handler);
void rtc_ticker_disable_irq();
uint32_t rtc_ticker_get_synch_presc();
void rtc_set_alarm(struct tm *ti, uint32_t subsecs);
uint32_t rtc_read_subseconds();
void rtc_reconfigure_prescalers();
#ifdef __cplusplus
}
#endif
#endif