Skip to content

Commit

Permalink
[stm32] Add RTC peripheral
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Dec 28, 2024
1 parent 2a2e8c9 commit 45c3732
Show file tree
Hide file tree
Showing 7 changed files with 486 additions and 5 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,31 @@ Please [discover modm's peripheral drivers for your specific device][discover].
<td align="center">✕</td>
<td align="center">✕</td>
</tr><tr>
<td align="left">RTC</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">○</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">✕</td>
<td align="center">✕</td>
<td align="center">✕</td>
</tr><tr>
<td align="left">SPI</td>
<td align="center">✅</td>
<td align="center">✅</td>
Expand Down
7 changes: 6 additions & 1 deletion src/modm/platform/clock/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ def build(env):
nper = "DSI"
if "Eth" in all_peripherals and per == "ETHMAC":
per = "Eth"
if "Rtc" in all_peripherals and per == "RTCAPB":
per = "RTC"
nper = "RTCAPB"
# Fix USBOTG OTG
if target.family == "u5" and per == "OTG":
per = "Usbotgfs"
Expand All @@ -200,7 +203,9 @@ def build(env):
if per.capitalize() not in all_peripherals:
continue
if "EN" in mode:
rcc_enable[per.capitalize()] = (nper, mode["EN"])
kw = per.capitalize()
if kw not in rcc_enable:
rcc_enable[kw] = (nper, mode["EN"])
if "RST" in mode:
rcc_reset[per.capitalize()] = (nper, mode["RST"])

Expand Down
12 changes: 8 additions & 4 deletions src/modm/platform/core/stm32/startup_platform.c.in
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,17 @@ __modm_initialize_platform(void)
// Enable Data Tighly Coupled Memory (DTCM) and backup SRAM (BKPSRAM)
RCC->AHB1ENR |= RCC_AHB1ENR_DTCMRAMEN | RCC_AHB1ENR_BKPSRAMEN;
%% elif target.family in ["g0", "g4", "l4", "l5"]
%% if target.family in ["l4", "g4"]
%% if target.family in ["l4", "g4"]
RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;
%% elif target.family != "g0"
#ifdef PWR_CR2_IOSV
%% elif target.family in ["g0"]
RCC->APBENR1 |= RCC_APBENR1_PWREN;
%% else
#ifdef RCC_APB1ENR1_PWREN
RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;
#endif
%% endif
%% endif
// Enable access to RTC and Backup registers
PWR->CR1 |= PWR_CR1_DBP;

#ifdef PWR_CR2_IOSV
// Enable VDDIO2
Expand Down
33 changes: 33 additions & 0 deletions src/modm/platform/rtc/stm32/module.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2023, Rasmus Kleist Hørlyck Sørensen
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------

def init(module):
module.name = ":platform:rtc"
module.description = "Real Time Clock (RTC)"

def prepare(module, options):
device = options[":target"]
if not device.has_driver("rtc:stm32*") or device.identifier.family in ["f1", "f2"]:
return False

module.depends(
":cmsis:device",
":platform:rcc",
":architecture:register",
":math:calendar",
)

return True

def build(env):
env.outbasepath = "modm/src/modm/platform/rtc"
env.copy(".")
25 changes: 25 additions & 0 deletions src/modm/platform/rtc/stm32/rtc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2024, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include "rtc.hpp"
#include <sys/time.h>

/*
extern "C" int
_gettimeofday(struct timeval *tp, void *)
{
const auto milliseconds = Rtc::read();
Rtc::update_cache();
tp->tv_sec = cache_time_seconds;
tp->tv_usec = milliseconds * 1000ul;
return 0;
}
*/
153 changes: 153 additions & 0 deletions src/modm/platform/rtc/stm32/rtc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* Copyright (c) 2023, Rasmus Kleist Hørlyck Sørensen
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_STM32_RTC_HPP
#define MODM_STM32_RTC_HPP

#include <chrono>
#include <ctime>

#include <modm/architecture.hpp>
#include <modm/math/calendar/date_time.hpp>

namespace modm::platform
{

/**
* Real Time Clock (RTC) control for STM32 devices
*
* @author Niklas Hauser
* @author Rasmus Kleist Hørlyck Sørensen
* @ingroup modm_platform_rtc
*/
class Rtc : public modm::PeripheralDriver
{
public:
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<Rtc, duration>;
static constexpr bool is_steady = true;

static time_point
now() noexcept;

static std::time_t
to_time_t(const time_point& t) noexcept
{
return std::time_t(duration_cast<std::chrono::seconds>(t.time_since_epoch()).count());
}

static time_point
from_time_t(std::time_t t) noexcept
{
using from_t = std::chrono::time_point<Rtc, std::chrono::seconds>;
return time_point_cast<duration>(from_t(std::chrono::seconds(t)));
}

public:
// Optimized version that returns seconds since epoch
static std::time_t
time_t();

static modm::DateTime
dateTime();

static void
setDateTime(const modm::DateTime &dt);

public:
static void
enable();

static void
disable();

template< class SystemClock >
static bool
initialize();

/**
* Synchronized to a remote clock with a high degree of precision
*
* @tparam Rep
* an arithmetic type representing the number of ticks
* @tparam Period
* a std::ratio representing the tick period (i.e. the number of second's fractions per tick)
*
* @param delay The amount of time to delay (or advance) the
* @param waitCycle Number of cycles to wait for the INITF bit to be set. (default = 2048)
*
* @return True on success
*/
// template< typename Rep, typename Period >
// static bool
// synchronize(std::chrono::duration<Rep, Period> delay, uint32_t waitCycles = 2048);

protected:
/// Unlock RTC register write protection
static void
unlock();

/// Lock RTC register write protection
static void
lock();

static uint16_t
read();

static void
update_cache();

struct Data
{
union
{
struct
{
uint8_t second;
uint8_t minute;
uint8_t hour;
} modm_packed;
uint32_t time32;
};
union
{
struct
{
uint8_t weekday;
uint8_t day;
uint8_t month;
uint8_t year;
} modm_packed;
uint32_t date32;
};
};

static inline Data data{};

static inline uint64_t cache_time_milliseconds{};
static inline uint32_t cache_time_seconds{};
static inline uint32_t cache_date_seconds{};
static inline uint32_t cache_time{};
static inline uint32_t cache_date{};

static inline uint32_t (*t2ms)(uint32_t) = [](uint32_t) { return 0ul; };
static inline uint32_t (*ms2t)(uint32_t) = [](uint32_t) { return 0ul; };

static constexpr uint16_t epoch{1970};
};

} // namespace modm::platform

#include "rtc_impl.hpp"

#endif // MODM_STM32_RTC_HPP
Loading

0 comments on commit 45c3732

Please sign in to comment.