Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
1dad937
Use custom board definition
nateinaction Sep 7, 2025
7fd3d7b
Remove commented config
nateinaction Sep 8, 2025
bbf35a3
Moving prj.conf sensors to board definition
nateinaction Sep 12, 2025
57e4183
Add d board
nateinaction Sep 12, 2025
e98a434
Try referencing c definitions in d board
nateinaction Sep 12, 2025
a75b69f
Making a common v5 board definition
nateinaction Sep 13, 2025
649e44f
Fix readme
nateinaction Sep 13, 2025
4aef1be
checkpoint rtc working
nateinaction Sep 17, 2025
d1613b0
Pushing what I have
nateinaction Sep 17, 2025
651eb05
poke
nateinaction Sep 17, 2025
08d1fbb
replaced chronotime with zepyhry time
ineskhou Sep 17, 2025
1ea3703
use direct power for rtc backup
nateinaction Sep 17, 2025
a674b21
This builds and runs but Fprime still does not know the time
nateinaction Sep 17, 2025
a1e5c4a
super working rtc component
nateinaction Sep 18, 2025
09e097b
Set fprime-zephyr submodule to latest main
nateinaction Sep 18, 2025
b7b442e
Split rtc manager/driver, confirmed working
nateinaction Sep 18, 2025
6d89365
Working on sdds
nateinaction Sep 18, 2025
8cb2b34
Update the RV3028 sdd
nateinaction Sep 18, 2025
3de364a
Update SDDs
nateinaction Sep 18, 2025
a5fd7b5
Merge branch 'main' of github.com:Open-Source-Space-Foundation/proves…
nateinaction Sep 18, 2025
f35a255
Merge branch 'main' of github.com:Open-Source-Space-Foundation/proves…
nateinaction Sep 18, 2025
60fb355
Merge branch 'main' of github.com:Open-Source-Space-Foundation/proves…
nateinaction Sep 18, 2025
72671c7
Revert submodule change
nateinaction Sep 18, 2025
e11fb04
Rename driver to `Rv3028Manager`
SamuelGomezG Sep 22, 2025
85cb11a
Rename references from Rv3028Driver to Rv3028Manager
SamuelGomezG Sep 22, 2025
f2c18bd
Remove assertion in constructor
SamuelGomezG Sep 22, 2025
7c40dd5
Change logging to use `Fw::Logger`
SamuelGomezG Sep 22, 2025
fab0b47
Most feedback covered
nateinaction Sep 23, 2025
2f447e8
appease linter
ineskhou Sep 26, 2025
6eff68e
Merge branch 'rtc' of github.com:Open-Source-Space-Foundation/proves-…
nateinaction Sep 27, 2025
f659d5b
Add integration tests
nateinaction Sep 28, 2025
aab21fb
Add typehinting
nateinaction Sep 28, 2025
ff77b96
Comment fix
nateinaction Sep 28, 2025
582ae5c
Test for previous time output when setting time
nateinaction Sep 28, 2025
6866735
Stop using EventData.get_dict()
nateinaction Sep 28, 2025
b7c3ddb
Now with microseconds!
nateinaction Sep 29, 2025
a454a07
Fix FPrime microsecond range expectation
nateinaction Sep 29, 2025
4b42cc4
Simplify RTC Manager
nateinaction Sep 29, 2025
d57ed57
Add command failure test
nateinaction Sep 30, 2025
ae3099e
Remove commented code
nateinaction Sep 30, 2025
fe5b6e8
Stop overwriting getTime
nateinaction Sep 30, 2025
7287ead
Use fprime getTime() to get the time
nateinaction Sep 30, 2025
ad4780f
Send command failure response if dev not ready
nateinaction Sep 30, 2025
690abd6
Merge branch 'main' of github.com:Open-Source-Space-Foundation/proves…
nateinaction Oct 2, 2025
16bea0b
Add input validation
nateinaction Oct 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion FprimeZephyrReference/Components/Drv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Include project-wide components here
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Helpers/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Lis2mdlManager/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Lsm6dsoManager/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/RtcManager")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/")
36 changes: 36 additions & 0 deletions FprimeZephyrReference/Components/Drv/RtcManager/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
####
# F Prime CMakeLists.txt:
#
# SOURCES: list of source files (to be compiled)
# AUTOCODER_INPUTS: list of files to be passed to the autocoders
# DEPENDS: list of libraries that this module depends on
#
# More information in the F´ CMake API documentation:
# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/
#
####

# Module names are derived from the path from the nearest project/library/framework
# root when not specifically overridden by the developer. i.e. The module defined by
# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`.

register_fprime_library(
AUTOCODER_INPUTS
"${CMAKE_CURRENT_LIST_DIR}/RtcManager.fpp"
SOURCES
"${CMAKE_CURRENT_LIST_DIR}/RtcManager.cpp"
# DEPENDS
# MyPackage_MyOtherModule
)

### Unit Tests ###
# register_fprime_ut(
# AUTOCODER_INPUTS
# "${CMAKE_CURRENT_LIST_DIR}/RtcManager.fpp"
# SOURCES
# "${CMAKE_CURRENT_LIST_DIR}/test/ut/RtcManagerTestMain.cpp"
# "${CMAKE_CURRENT_LIST_DIR}/test/ut/RtcManagerTester.cpp"
# DEPENDS
# STest # For rules-based testing
# UT_AUTO_HELPERS
# )
156 changes: 156 additions & 0 deletions FprimeZephyrReference/Components/Drv/RtcManager/RtcManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// ======================================================================
// \title RtcManager.cpp
// \brief cpp file for RtcManager component implementation class
// ======================================================================

#include "FprimeZephyrReference/Components/Drv/RtcManager/RtcManager.hpp"

namespace Drv {

// ----------------------------------------------------------------------
// Component construction and destruction
// ----------------------------------------------------------------------

RtcManager ::RtcManager(const char* const compName) : RtcManagerComponentBase(compName) {
// Initialize device
this->dev = device_get_binding("RV3028");
}

RtcManager ::~RtcManager() {}

// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------

void RtcManager ::timeGetPort_handler(FwIndexType portNum, Fw::Time& time) {
// Check device readiness
if (!device_is_ready(this->dev)) {
// Use logger instead of events since this fn is in a critical path for FPrime
// to get time. Events require time, if this method fails an event will fail.
Fw::Logger::log("RTC not ready");
return;
}

// Get time from RTC
struct rtc_time time_rtc = {};
rtc_get_time(this->dev, &time_rtc);

// Convert to generic tm struct
struct tm* time_tm = rtc_time_to_tm(&time_rtc);

// Convert to time_t (seconds since epoch)
errno = 0;
time_t seconds = timeutil_timegm(time_tm);
if (errno == ERANGE) {
Fw::Logger::log("RTC returned invalid time");
return;
}

// Get microseconds from system clock cycles
// Note: RV3028 does not provide sub-second precision, so this is
// just an approximation based on system cycles.
// FPrime expects microseconds in the range [0, 999999]
uint32_t useconds = k_cyc_to_us_near32(k_cycle_get_32()) % 1000000;

// Set FPrime time object
time.set(TimeBase::TB_WORKSTATION_TIME, 0, static_cast<U32>(seconds), static_cast<U32>(useconds));
}

// ----------------------------------------------------------------------
// Handler implementations for commands
// ----------------------------------------------------------------------

void RtcManager ::TIME_SET_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, Drv::TimeData t) {
// Check device readiness
if (!device_is_ready(this->dev)) {
// Emit device not ready event
this->log_WARNING_HI_DeviceNotReady();

// Send command response
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}
this->log_WARNING_HI_DeviceNotReady_ThrottleClear();

// Validate time data
if (!this->timeDataIsValid(t)) {
// Emit time not set event
this->log_WARNING_HI_TimeNotSet();

// Send command response
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
return;
}

// Store current time for logging
Fw::Time time_before_set = this->getTime();

// Populate rtc_time structure from TimeData
const struct rtc_time time_rtc = {
.tm_sec = static_cast<int>(t.get_Second()),
.tm_min = static_cast<int>(t.get_Minute()),
.tm_hour = static_cast<int>(t.get_Hour()),
.tm_mday = static_cast<int>(t.get_Day()),
.tm_mon = static_cast<int>(t.get_Month() - 1), // month [0-11]
.tm_year = static_cast<int>(t.get_Year() - 1900), // year since 1900
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0,
};

// Set time on RTC
const int status = rtc_set_time(this->dev, &time_rtc);

if (status != 0) {
// Emit time not set event
this->log_WARNING_HI_TimeNotSet();

// Send command response
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}

// Emit time set event, include previous time for reference
this->log_ACTIVITY_HI_TimeSet(time_before_set.getSeconds(), time_before_set.getUSeconds());

// Send command response
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
}

bool RtcManager ::timeDataIsValid(Drv::TimeData t) {
bool valid = true;

if (t.get_Year() < 1900) {
this->log_WARNING_HI_YearValidationFailed(t.get_Year());
valid = false;
}

if (t.get_Month() < 1 || t.get_Month() > 12) {
this->log_WARNING_HI_MonthValidationFailed(t.get_Month());
valid = false;
}

if (t.get_Day() < 1 || t.get_Day() > 31) {
this->log_WARNING_HI_DayValidationFailed(t.get_Day());
valid = false;
}

if (t.get_Hour() > 23) {
this->log_WARNING_HI_HourValidationFailed(t.get_Hour());
valid = false;
}

if (t.get_Minute() > 59) {
this->log_WARNING_HI_MinuteValidationFailed(t.get_Minute());
valid = false;
}

if (t.get_Second() > 59) {
this->log_WARNING_HI_SecondValidationFailed(t.get_Second());
valid = false;
}

return valid;
}

} // namespace Drv
96 changes: 96 additions & 0 deletions FprimeZephyrReference/Components/Drv/RtcManager/RtcManager.fpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Type definition
module Drv {
struct TimeData {
Year: U32 @< Year value.
Month: U32 @< Month value.
Day: U32 @< Day value.
Hour: U32 @< Hour value.
Minute: U32 @< Minute value.
Second: U32 @< Second value.
}
}

# Port definition
module Drv {
port TimeSet(t: TimeData)
port TimeGet -> U32
}

module Drv {
@ Manages the real time clock
passive component RtcManager {
import Svc.Time

@ TIME_SET command to set the time on the RTC
sync command TIME_SET(
t: Drv.TimeData @< Set the time
) opcode 0

##############################################################################
#### Uncomment the following examples to start customizing your component ####
##############################################################################

@ DeviceNotReady event indicates that the RTC is not ready
event DeviceNotReady() severity warning high id 0 format "RTC not ready" throttle 5

@ TimeSet event indicates that the time was set successfully
event TimeSet(
seconds: U32 @< Seconds since epoch
useconds: U32 @< Microseconds
) severity activity high id 3 format "Time set on RTC, previous time: {}.{}"

@ TimeNotSet event indicates that the time was not set successfully
event TimeNotSet() severity warning high id 4 format "Time not set on RTC"

@ YearValidationFailed event indicates that the provided year is invalid
event YearValidationFailed(
year: U32 @< The invalid year
) severity warning high id 5 format "Provided year is invalid should be >= 1900: {}"

@ MonthValidationFailed event indicates that the provided month is invalid
event MonthValidationFailed(
month: U32 @< The invalid month
) severity warning high id 6 format "Provided month is invalid should be in [1, 12]: {}"

@ DayValidationFailed event indicates that the provided day is invalid
event DayValidationFailed(
day: U32 @< The invalid day
) severity warning high id 7 format "Provided day is invalid should be in [1, 31]: {}"

@ HourValidationFailed event indicates that the provided hour is invalid
event HourValidationFailed(
hour: U32 @< The invalid hour
) severity warning high id 8 format "Provided hour is invalid should be in [0, 23]: {}"

@ MinuteValidationFailed event indicates that the provided minute is invalid
event MinuteValidationFailed(
minute: U32 @< The invalid minute
) severity warning high id 9 format "Provided minute is invalid should be in [0, 59]: {}"

@ SecondValidationFailed event indicates that the provided second is invalid
event SecondValidationFailed(
second: U32 @< The invalid second
) severity warning high id 10 format "Provided second is invalid should be in [0, 59]: {}"

###############################################################################
# Standard AC Ports: Required for Channels, Events, Commands, and Parameters #
###############################################################################
@ Port for requesting the current time
time get port timeCaller

@ Port for sending command registrations
command reg port cmdRegOut

@ Port for receiving commands
command recv port cmdIn

@ Port for sending command responses
command resp port cmdResponseOut

@ Port for sending textual representation of events
text event port logTextOut

@ Port for sending events to downlink
event port logOut
}
}
77 changes: 77 additions & 0 deletions FprimeZephyrReference/Components/Drv/RtcManager/RtcManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// ======================================================================
// \title RtcManager.hpp
// \brief hpp file for RtcManager component implementation class
// ======================================================================

#ifndef Components_RtcManager_HPP
#define Components_RtcManager_HPP

#include "FprimeZephyrReference/Components/Drv/RtcManager/RtcManagerComponentAc.hpp"

#include <cerrno>
#include <string>
#include <vector>

#include <Fw/Logger/Logger.hpp>

#include <zephyr/device.h>
#include <zephyr/drivers/rtc.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/timeutil.h>

namespace Drv {

class RtcManager final : public RtcManagerComponentBase {
public:
// ----------------------------------------------------------------------
// Component construction and destruction
// ----------------------------------------------------------------------

//! Construct RtcManager object
RtcManager(const char* const compName //!< The component name
);

//! Destroy RtcManager object
~RtcManager();

private:
// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------

//! Handler implementation for timeGetPort
//!
//! Port to retrieve time
void timeGetPort_handler(FwIndexType portNum, //!< The port number
Fw::Time& time //!< Reference to Time object
) override;

private:
// ----------------------------------------------------------------------
// Handler implementations for commands
// ----------------------------------------------------------------------

//! Handler implementation for command TIME_SET
//!
//! TIME_SET command to set the time on the RTC
void TIME_SET_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
Drv::TimeData t //!< Set the time
) override;

private:
// ----------------------------------------------------------------------
// Private helper methods
// ----------------------------------------------------------------------

//! Validate time data
bool timeDataIsValid(Drv::TimeData t);

//! device stores the initialized Zephyr RTC device
const struct device* dev;
};

} // namespace Drv

#endif
Loading