Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
7d1a435
Added structure for alarm manager
collinc04 Mar 7, 2026
564cc30
more structure
collinc04 Mar 19, 2026
2c08327
rollback if I did something wrong
collinc04 Mar 19, 2026
c5c71d8
Inital alarm contract
nateinaction Mar 20, 2026
56b352a
Merge remote-tracking branch 'origin/rtc-alarm-ngay' into RTC_alarm
collinc04 Mar 20, 2026
d9f1312
does it work? IDK, does it build? yes.
collinc04 Mar 25, 2026
c4e2252
list alarm
collinc04 Mar 25, 2026
8e1a3a5
Merge branch 'main' into RTC_alarm
collinc04 Mar 25, 2026
39b4989
freezes when ALARM_SET is recieved
collinc04 Mar 25, 2026
96a3e94
pushing changes from office hours
nateinaction Mar 25, 2026
ae8708a
Updated code
collinc04 Mar 30, 2026
db8c29d
Mostly works
collinc04 Mar 30, 2026
5621b69
Updated code
collinc04 Mar 31, 2026
eb948d5
updated code
collinc04 Mar 31, 2026
ad4c049
Flexible mask for different boards
collinc04 Apr 1, 2026
f32b685
I know I should have this done but I'm really tired
collinc04 Apr 1, 2026
3da2f8e
input val
collinc04 Apr 1, 2026
e1dc894
Alarm trigger issues
collinc04 Apr 2, 2026
476fb7c
full functionality
collinc04 Apr 2, 2026
3ffe107
Merge branch 'main' into RTC_alarm
collinc04 Apr 2, 2026
461b4ea
Update sdd.md
collinc04 Apr 2, 2026
476492e
tests
collinc04 Apr 2, 2026
797bbb9
fix tests
collinc04 Apr 2, 2026
e528aa2
codespell
collinc04 Apr 2, 2026
a2314ed
Update PROVESFlightControllerReference/test/int/rtc_test.py
collinc04 Apr 6, 2026
446b0e5
AAA
collinc04 Apr 6, 2026
fe50a0c
Merge remote-tracking branch 'refs/remotes/origin/RTC_alarm' into RTC…
collinc04 Apr 6, 2026
4e30e94
Update PROVESFlightControllerReference/Components/Drv/RtcManager/RtcM…
collinc04 Apr 7, 2026
52dce4f
ruff
collinc04 Apr 7, 2026
c62cc89
Merge remote-tracking branch 'refs/remotes/origin/RTC_alarm' into RTC…
collinc04 Apr 7, 2026
29bdf20
post review changes
collinc04 Apr 7, 2026
aa43a0b
oops
collinc04 Apr 7, 2026
33b5221
final final
collinc04 Apr 7, 2026
118f037
Merge branch 'main' into RTC_alarm
collinc04 Apr 7, 2026
0bc11f5
ehh
collinc04 Apr 9, 2026
aacfd35
Refactor
collinc04 Apr 13, 2026
d0599a9
Merge branch 'main' into RTC_alarm
collinc04 Apr 13, 2026
8059be5
Catch RC for callback
collinc04 Apr 13, 2026
1d91a71
Merge remote-tracking branch 'refs/remotes/origin/RTC_alarm' into RTC…
collinc04 Apr 13, 2026
7e2dd65
updated catch
collinc04 Apr 13, 2026
bd18a14
return cap
collinc04 Apr 13, 2026
36e167f
fix redeclaration
hrfarmer Apr 13, 2026
a94fb0b
Merge branch 'main' into RTC_alarm
hrfarmer Apr 13, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,26 @@

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

#include <errno.h>

#include <cstdint>
#include <random>

#include <zephyr/device.h>
#include <zephyr/drivers/rtc.h>
#include <zephyr/kernel.h>
#include <zephyr/syscalls/rtc.h>

namespace Drv {

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

RtcManager ::RtcManager(const char* const compName) : RtcManagerComponentBase(compName), m_rtcHelper() {}
RtcManager ::RtcManager(const char* const compName) : RtcManagerComponentBase(compName), m_rtcHelper() {
// alarm time initialization
memset(&this->m_alarm_time, 0, sizeof(struct rtc_time));
}

RtcManager ::~RtcManager() {}

Expand All @@ -21,8 +34,14 @@ RtcManager ::~RtcManager() {}

void RtcManager ::configure(const struct device* dev) {
this->m_dev = dev;
}

// match to timedata this is constant after being updated here, do not change
int rc = rtc_alarm_get_supported_fields(this->m_dev, 0, &this->m_curr_mask);
if (rc != 0) {
// log failure
this->log_WARNING_HI_AlarmHardwareError(0, rc);
}
}
// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------
Expand Down Expand Up @@ -138,6 +157,160 @@ void RtcManager ::TIME_SET_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, Drv::Time
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
}

// Alarm manager
void RtcManager ::ALARM_SET_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, Drv::TimeData t) {
// retrieve info about current alarm

uint16_t mask = this->m_curr_mask;
int rc = rtc_alarm_get_time(this->m_dev, 0, &mask, &this->m_alarm_time);

// if alarm is already set, return an EALREADY error
if (rc == 0 && mask != 0) {
this->log_WARNING_HI_AlarmNotSet(t, EALREADY);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}
// populate alarm time
this->m_alarm_time.tm_sec = t.get_Second();
this->m_alarm_time.tm_min = t.get_Minute();
this->m_alarm_time.tm_hour = t.get_Hour();
this->m_alarm_time.tm_mday = t.get_Day();
this->m_alarm_time.tm_mon = t.get_Month() - 1;
this->m_alarm_time.tm_year = t.get_Year() - 1900;

// assure alarm is at a future point in time
struct rtc_time c_time;
struct rtc_time a_time = this->m_alarm_time;
rc = rtc_get_time(this->m_dev, &c_time);
if (rc != 0) {
// indicates hardware error
this->log_WARNING_HI_AlarmHardwareError(0, rc);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}
int c_seconds = timeutil_timegm(rtc_time_to_tm(&c_time));
int a_seconds = timeutil_timegm(rtc_time_to_tm(&a_time));
if (a_seconds <= c_seconds) {
this->log_WARNING_HI_AlarmNotSet(t, EINVAL);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}

// set the alarm
rc = rtc_alarm_set_time(this->m_dev, 0, this->m_curr_mask, &this->m_alarm_time);

// capture the return code for setting the alarm
if (rc != 0) {
// log failure
this->log_WARNING_HI_AlarmHardwareError(0, rc);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}

// callback to trigger upon alarm trigger
rc = rtc_alarm_set_callback(this->m_dev, 0, RtcManager::static_alarm_callback_t, this);

// capture return code for the callback
if (rc != 0) {
// log failure
this->log_WARNING_HI_AlarmHardwareError(0, rc);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}

// log success
this->log_ACTIVITY_HI_AlarmSet(0, t);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
}

void RtcManager::static_alarm_callback_t(const device* dev, uint16_t id, void* user_data) {
// Reconstruct the object pointer from user_data
RtcManager* instance = static_cast<RtcManager*>(user_data);
if (instance != nullptr) {
instance->alarm_callback_t(dev, id);
}
}

void RtcManager ::alarm_callback_t(const struct device* dev, uint16_t id) {
// actual callback
this->log_ACTIVITY_HI_AlarmTriggered(id);
for (int i = 0; i < getNum_alarmTriggered_OutputPorts(); i++) {
if (!this->isConnected_alarmTriggered_OutputPort(i)) {
continue;
}
this->alarmTriggered_out(i);
}
// cancel the alarm, so it won't go off repeatedly.
uint16_t mask = 0;
int rc = rtc_alarm_set_time(this->m_dev, 0, mask, &this->m_alarm_time);
if (rc != 0) {
// log failure
this->log_WARNING_HI_AlarmHardwareError(0, rc);
}
}

void RtcManager ::ALARM_CANCEL_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U16 ID) {
// check if it's present
uint16_t mask = this->m_curr_mask;
int rc = rtc_alarm_get_time(this->m_dev, 0, &mask, &this->m_alarm_time);

if (rc != 0) {
// indicates hardware error
this->log_WARNING_HI_AlarmHardwareError(0, rc);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}

if (mask != 0) {
// set mask to 0 to cancel alarm
mask = 0;
rc = rtc_alarm_set_time(this->m_dev, 0, mask, &this->m_alarm_time);
if (rc != 0) {
// log failure
this->log_WARNING_HI_AlarmHardwareError(0, rc);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
return;
}

this->log_ACTIVITY_HI_AlarmCanceled(ID);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
return;
}

// handle no alarm case
this->log_WARNING_HI_AlarmNotCanceled(ID, 0);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
}

void RtcManager ::ALARM_LIST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
// check if present, if so log its info.
uint16_t mask = this->m_curr_mask;
int rc = rtc_alarm_get_time(this->m_dev, 0, &mask, &this->m_alarm_time);

// if the return code is nonzero, log the error.
if (rc != 0) {
// indicates hardware error
this->log_WARNING_HI_AlarmHardwareError(0, rc);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
}

// check the current mask to see if an alarm is active
if (mask > 0) {
// convert alarm time and log it
Drv::TimeData alarm_time_value(this->m_alarm_time.tm_year + 1900, this->m_alarm_time.tm_mon + 1,
this->m_alarm_time.tm_mday, this->m_alarm_time.tm_hour,
this->m_alarm_time.tm_min, this->m_alarm_time.tm_sec);
log_ACTIVITY_HI_AlarmSet(0, alarm_time_value);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
return;
}

// no alarm is present, log accordingly.
Drv::TimeData alarm_none;
this->log_WARNING_HI_AlarmNotSet(alarm_none, 0);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,37 @@ module Drv {
module Drv {
port TimeSet(t: TimeData)
port TimeGet -> U32
port AlarmSet(t: Fw.TimeValue) -> U32
port AlarmCancel(ID: U16) -> U32
port AlarmTriggered()
}

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

### COMMANDS ###

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

@ ALARM_SET command to set an alarm on the RTC
sync command ALARM_SET(
t: Drv.TimeData @< Time to set the alarm for
)

@ ALARM_CANCEL command to cancel any set alarms on the RTC
sync command ALARM_CANCEL(
ID: U16 @< ID of the alarm to cancel
)

@ ALARM_LIST command to list all set alarms on the RTC
sync command ALARM_LIST()

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

@ DeviceNotReady event indicates that the RTC is not ready
event DeviceNotReady() severity warning high id 0 format "RTC not ready" throttle 1
Expand Down Expand Up @@ -72,13 +88,49 @@ module Drv {
second: U32 @< The invalid second
) severity warning high id 10 format "Provided second is invalid should be in [0, 59]: {}"

###############################################################################
# Port for canceling sequences on time change #
###############################################################################
@ AlarmSet event indicates that the alarm was set successfully
event AlarmSet(
ID: U16 @< ID of the set alarm
t: Drv.TimeData @< Time for the set alarm
) severity activity high id 11 format "Alarm set on RTC with ID {}, time: {}"

@ AlarmNotSet event indicates that the alarm was not set successfully
event AlarmNotSet(
t: Drv.TimeData @< Time for the alarm that was not set
rc: U32 @< Return code from the RTC driver
) severity warning high id 12 format "Alarm not set on RTC for time: {}, return code: {}"

@ AlarmTriggered event indicates that an alarm was triggered
event AlarmTriggered(
ID: U16 @< ID of the triggered alarm
) severity activity high id 13 format "Alarm with ID {} triggered"

@ AlarmCanceled event indicates that an alarm was canceled successfully
event AlarmCanceled(
ID: U16 @< ID of the canceled alarm
) severity activity high id 14 format "Alarm with ID {} canceled"

@ AlarmNotCanceled event indicates that an alarm was not canceled successfully
event AlarmNotCanceled(
ID: U16 @< ID of the alarm that was not canceled
rc: U32 @< Return code from the RTC driver
) severity warning high id 15 format "Alarm with ID {} not canceled, return code: {}"

@ AlarmHardwareError event indicates hardware issues with the RTC
event AlarmHardwareError(
ID: U16 @< ID of the alarm that had a hardware error
rc: U32 @< Return code from the RTC driver
) severity warning high id 16 format "Alarm with ID {} had a hardware error, return code: {}"

### PORTS ###

@ Port for canceling running sequences when RTC time is set
@ Connected to seqCancelIn ports of Command, Payload, and SafeMode sequencers
output port cancelSequences: [3] Svc.CmdSeqCancel

@ Port to indicate an alarm was triggered
output port alarmTriggered: [1] Drv.AlarmTriggered

###############################################################################
# Standard AC Ports: Required for Channels, Events, Commands, and Parameters #
###############################################################################
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,40 @@ class RtcManager final : public RtcManagerComponentBase {
Drv::TimeData t //!< Set the time
) override;

//! Handler implementation for command ALARM_SET
//!
//! ALARM_SET command to set an alarm on the RTC
void ALARM_SET_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
Drv::TimeData t //!< Time to set the alarm for
) override;

//! Handler implementation for command ALARM_CANCEL
//!
//! ALARM_CANCEL command to cancel any set alarms on the RTC
void ALARM_CANCEL_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
U16 ID //!< ID of the alarm to cancel
) override;

//! Handler implementation for command ALARM_LIST
//!
//! ALARM_LIST command to list all set alarms on the RTC
void ALARM_LIST_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq //!< The command sequence number
) override;

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

// Alarm callback kicker method. Must be static but cannot reference this in a static context
static void static_alarm_callback_t(const struct device* dev, uint16_t id, void* user_data);
Comment thread
collinc04 marked this conversation as resolved.

// Actual alarm callback, for triggering events
void alarm_callback_t(const struct device* dev, uint16_t id);
Comment thread
collinc04 marked this conversation as resolved.

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

Expand All @@ -83,6 +112,11 @@ class RtcManager final : public RtcManagerComponentBase {
std::atomic<bool> m_console_throttled; //!< Counter for console throttle
const struct device* m_dev; //!< The initialized Zephyr RTC device
RtcHelper m_rtcHelper; //!< Helper for RTC operations

// rtc alarm members

U16 m_curr_mask; //!< The mask of the alarm present on hardware
struct rtc_time m_alarm_time; //!< Current alarm's time settings
};

} // namespace Drv
Expand Down
Loading
Loading