Skip to content

Commit

Permalink
Add RTC to firmware
Browse files Browse the repository at this point in the history
  • Loading branch information
Kampi committed Aug 7, 2024
2 parents 3d1fe61 + 8384fc9 commit 5a70a18
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
low-power-enable;
};
};

};

&uicr {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
bias-pull-up;
};
};

};

&uicr {
Expand Down
4 changes: 2 additions & 2 deletions app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.conf
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ CONFIG_NVS=y

CONFIG_DEBUG_COREDUMP_BACKEND_OTHER=y

#CONFIG_RTC=y
#CONFIG_RTC_UPDATE=y
CONFIG_RTC=y
CONFIG_RTC_UPDATE=y

CONFIG_MISC_ENABLE_SYSTEM_RESET=n # Implemented in nPM, hence not needed in FW

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
bias-pull-up;
};
};

};

&uicr {
Expand Down Expand Up @@ -198,7 +197,7 @@
reg = <0x51>;
status = "okay";
clkout = <0>;
int-gpios = <&gpio1 13 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
int-gpios = <&gpio1 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
};

bmi270: bmi270@68 {
Expand Down
48 changes: 32 additions & 16 deletions app/patches/rv8263_rtc.patch
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ new file mode 100644
index 0000000000..bb82ed7d9b
--- /dev/null
+++ b/drivers/rtc/rtc_rv8263.c
@@ -0,0 +1,771 @@
@@ -0,0 +1,787 @@
+/* Copyright (c) 2024 Daniel Kampert
+ * Author: Daniel Kampert <DanielKampert@kampis-Elektroecke.de>
+ */
Expand Down Expand Up @@ -275,6 +275,25 @@ index 0000000000..bb82ed7d9b
+}
+
+#if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
+static int rv8263c8_disable_alarm(const struct device *dev)
+{
+ int err;
+ const struct rv8263c8_config *config = dev->config;
+ uint8_t buf[] = {RV8263C8_REGISTER_SECONDS_ALARM, RV8263C8_BM_ALARM_DISABLE,
+ RV8263C8_BM_ALARM_DISABLE, RV8263C8_BM_ALARM_DISABLE,
+ RV8263C8_BM_ALARM_DISABLE, RV8263C8_BM_ALARM_DISABLE};
+
+ /* We start with the seconds alarm to disable the alarm and continue for all other alarm */
+ /* registers. */
+ err = i2c_write_dt(&config->i2c_bus, buf, 6);
+ if (err) {
+ return err;
+ }
+
+ return i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2,
+ RV8263C8_BM_ALARM_INT_ENABLE, RV8263C8_BM_ALARM_INT_DISABLE);
+}
+
+static void rv8263c8_gpio_callback_handler(const struct device *p_port, struct gpio_callback *p_cb,
+ gpio_port_pins_t pins)
+{
Expand Down Expand Up @@ -404,10 +423,10 @@ index 0000000000..bb82ed7d9b
+ return err;
+ }
+
+ /* Return an error when the oscillator is stopped. */
+ if (regs[0] & RV8263_BM_OS) {
+ return -ECANCELED;
+ }
+ /* Clear the oscillator stop flag and return an error when the oscillator is stopped. */
+ if (regs[0] & RV8263_BM_OS) {
+ return -ENODATA;
+ }
+
+ timeptr->tm_sec = bcd2bin(regs[0] & SECONDS_BITS);
+ timeptr->tm_min = bcd2bin(regs[1] & MINUTES_BITS);
Expand Down Expand Up @@ -566,9 +585,7 @@ index 0000000000..bb82ed7d9b
+
+ /* Disable the alarm when mask is zero. */
+ if (mask == 0) {
+ return i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2,
+ RV8263C8_BM_ALARM_INT_ENABLE,
+ RV8263C8_BM_ALARM_INT_DISABLE);
+ return rv8263c8_disable_alarm(dev);
+ }
+
+ if (!rtc_utils_validate_rtc_time(timeptr, mask)) {
Expand Down Expand Up @@ -671,27 +688,28 @@ index 0000000000..bb82ed7d9b
+ return err;
+ }
+
+ if (value[0] <= MAX_SEC) {
+ /* Check if the highest bit is not set. If so the alarm is enabled. */
+ if ((value[0] & RV8263C8_BM_ALARM_DISABLE) == 0) {
+ timeptr->tm_sec = bcd2bin(value[0]) & SECONDS_BITS;
+ (*p_mask) |= RTC_ALARM_TIME_MASK_SECOND;
+ }
+
+ if (value[1] <= MAX_MIN) {
+ if ((value[1] & RV8263C8_BM_ALARM_DISABLE) == 0) {
+ timeptr->tm_min = bcd2bin(value[1]) & MINUTES_BITS;
+ (*p_mask) |= RTC_ALARM_TIME_MASK_MINUTE;
+ }
+
+ if (value[2] <= MAX_HOUR) {
+ if ((value[2] & RV8263C8_BM_ALARM_DISABLE) == 0) {
+ timeptr->tm_hour = bcd2bin(value[2]) & HOURS_BITS;
+ (*p_mask) |= RTC_ALARM_TIME_MASK_HOUR;
+ }
+
+ if (value[3] <= MAX_MDAY) {
+ if ((value[3] & RV8263C8_BM_ALARM_DISABLE) == 0) {
+ timeptr->tm_mday = bcd2bin(value[3]) & DATE_BITS;
+ (*p_mask) |= RTC_ALARM_TIME_MASK_MONTHDAY;
+ }
+
+ if (value[4] <= MAX_WDAY) {
+ if ((value[4] & RV8263C8_BM_ALARM_DISABLE) == 0) {
+ timeptr->tm_wday = bcd2bin(value[4]) & WEEKDAY_BITS;
+ (*p_mask) |= RTC_ALARM_TIME_MASK_WEEKDAY;
+ }
Expand Down Expand Up @@ -727,9 +745,7 @@ index 0000000000..bb82ed7d9b
+ if ((callback == NULL) && (user_data == NULL)) {
+ LOG_DBG("Disable alarm function");
+
+ err = i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2,
+ RV8263C8_BM_ALARM_INT_ENABLE,
+ RV8263C8_BM_ALARM_INT_DISABLE);
+ err = rv8263c8_disable_alarm(dev);
+ } else {
+ LOG_DBG("Enable alarm function");
+
Expand Down
56 changes: 38 additions & 18 deletions app/src/events/zsw_periodic_event.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/zbus/zbus.h>
#include <zephyr/logging/log.h>

#if CONFIG_RTC
#include <zephyr/drivers/rtc.h>
Expand All @@ -21,6 +22,8 @@ ZBUS_CHAN_DECLARE(periodic_event_1s_chan);
ZBUS_CHAN_DECLARE(periodic_event_10s_chan);
ZBUS_CHAN_DECLARE(periodic_event_100ms_chan);

LOG_MODULE_REGISTER(zsw_periodic_event, LOG_LEVEL_INF);

int zsw_periodic_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs)
{
struct k_work_delayable *work = NULL;
Expand Down Expand Up @@ -76,28 +79,43 @@ static void handle_slow_timeout(struct k_work *item)
zbus_chan_pub(&periodic_event_10s_chan, &evt, K_MSEC(250));
}

//#if CONFIG_RTC
//void handle_mid_timeout(const struct device *dev, void *user_data)
//{
// struct periodic_event evt = {
// };
//
// zbus_chan_pub(&periodic_event_1s_chan, &evt, K_MSEC(250));
//}
//#else
#if CONFIG_RTC
static void test(const struct device *dev, void *user_data)
{
struct periodic_event evt = {
};

LOG_ERR("RTC update");
}

static void handle_mid_timeout(struct k_work *item)
{
struct periodic_event evt = {
};
struct k_work_delayable *work = NULL;

zbus_chan_claim(&periodic_event_1s_chan, K_FOREVER);
work = (struct k_work_delayable *)zbus_chan_user_data(&periodic_event_1s_chan);
k_work_reschedule(work, K_MSEC(PERIODIC_MID_INTERVAL_MS));
zbus_chan_finish(&periodic_event_1s_chan);

zbus_chan_pub(&periodic_event_1s_chan, &evt, K_MSEC(250));
}
//#endif
#else
static void handle_mid_timeout(struct k_work *item)
{
struct periodic_event evt = {
};
struct k_work_delayable *work = NULL;

zbus_chan_claim(&periodic_event_1s_chan, K_FOREVER);
work = (struct k_work_delayable *)zbus_chan_user_data(&periodic_event_1s_chan);
k_work_reschedule(work, K_MSEC(PERIODIC_MID_INTERVAL_MS));
zbus_chan_finish(&periodic_event_1s_chan);

zbus_chan_pub(&periodic_event_1s_chan, &evt, K_MSEC(250));
}
#endif

static void handle_fast_timeout(struct k_work *item)
{
Expand All @@ -119,16 +137,18 @@ static int zsw_timer_init(void)
work = (struct k_work_delayable *)zbus_chan_user_data(&periodic_event_10s_chan);
k_work_init_delayable(work, handle_slow_timeout);

//#if CONFIG_RTC
// if (!device_is_ready(rtc)) {
// return -EBUSY;
// }
//
// rtc_update_set_callback(rtc, handle_mid_timeout, NULL);
//#else
#if CONFIG_RTC
if (!device_is_ready(rtc)) {
return -EBUSY;
}

work = (struct k_work_delayable *)zbus_chan_user_data(&periodic_event_1s_chan);
k_work_init_delayable(work, handle_mid_timeout);
//#endif
rtc_update_set_callback(rtc, test, NULL);
#else
work = (struct k_work_delayable *)zbus_chan_user_data(&periodic_event_1s_chan);
k_work_init_delayable(work, handle_mid_timeout);
#endif

work = (struct k_work_delayable *)zbus_chan_user_data(&periodic_event_100ms_chan);
k_work_init_delayable(work, handle_fast_timeout);
Expand Down
10 changes: 5 additions & 5 deletions app/src/filesystem/zsw_filesystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ static int lsdir(const char *path)
}

if (entry.type == FS_DIR_ENTRY_DIR) {
LOG_PRINTK("[DIR ] %s\n", entry.name);
LOG_DBG("[DIR ] %s\n", entry.name);
} else {
LOG_PRINTK("[FILE] %s (size = %zu)\n",
entry.name, entry.size);
LOG_DBG("[FILE] %s (size = %zu)\n",
entry.name, entry.size);
}
}

Expand All @@ -78,7 +78,7 @@ int zsw_filesystem_ls(void)

rc = fs_statvfs(mountpoint->mnt_point, &sbuf);
if (rc < 0) {
LOG_PRINTK("FAIL: statvfs: %d\n", rc);
LOG_ERR("FAIL: statvfs: %d\n", rc);
return -1;
}

Expand All @@ -90,7 +90,7 @@ int zsw_filesystem_ls(void)

rc = lsdir(mountpoint->mnt_point);
if (rc < 0) {
LOG_PRINTK("FAIL: lsdir %s: %d\n", mountpoint->mnt_point, rc);
LOG_ERR("FAIL: lsdir %s: %d\n", mountpoint->mnt_point, rc);
return -1;
}

Expand Down
36 changes: 31 additions & 5 deletions app/src/zsw_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ ZBUS_LISTENER_DEFINE(zsw_clock_lis, zbus_periodic_slow_callback);
LOG_MODULE_REGISTER(zsw_clock, LOG_LEVEL_INF);

#ifndef CONFIG_RTC

static time_t zsw_clock_get_time_unix(void)
{
struct timeval tv;
Expand All @@ -64,7 +63,7 @@ static void zbus_periodic_slow_callback(const struct zbus_channel *chan)
}
#endif

void zsw_clock_set_time(zsw_timeval_t *ztm)
int zsw_clock_set_time(zsw_timeval_t *ztm)
{
// Substract one from the month because we want to count from December instead of January
ztm->tm.tm_mon -= 1;
Expand All @@ -73,7 +72,9 @@ void zsw_clock_set_time(zsw_timeval_t *ztm)
ztm->tm.tm_year -= 1900;

#if CONFIG_RTC
rtc_set_time(rtc, &ztm->tm);
if (rtc_set_time(rtc, &ztm->tm) != 0) {
return -EBUSY;
}
#else
struct timespec tspec;

Expand All @@ -87,14 +88,22 @@ void zsw_clock_set_time(zsw_timeval_t *ztm)
tzset();
}
#endif

return 0;
}

void zsw_clock_get_time(zsw_timeval_t *ztm)
int zsw_clock_get_time(zsw_timeval_t *ztm)
{
// Set the buffer to 0 to avoid issues with invalid values.
memset(ztm, 0, sizeof(struct rtc_time));

#if CONFIG_RTC
struct rtc_time tm;

rtc_get_time(rtc, &tm);
if (rtc_get_time(rtc, &tm) != 0) {
return -ENODATA;
}

memcpy(ztm, &tm, sizeof(struct rtc_time));
#else
struct tm *tm;
Expand All @@ -110,15 +119,32 @@ void zsw_clock_get_time(zsw_timeval_t *ztm)

// Add 1900 to the year because we want to count from 1900
ztm->tm.tm_year += 1900;

return 0;
}

static int zsw_clock_init(void)
{
#if CONFIG_RTC
struct rtc_time tm;

if (!device_is_ready(rtc)) {
LOG_ERR("Device not ready!");
return -EBUSY;
}

// Check if the oscillator stop flag is set and set a default time to reset it
if (rtc_get_time(rtc, &tm) != 0) {
tm.tm_hour = 0;
tm.tm_min = 1;
tm.tm_sec = 0;
tm.tm_wday = 6;
tm.tm_mday = 1;
tm.tm_mon = 1;
tm.tm_year = 2000;

return rtc_set_time(rtc, &tm);
}
#else
struct timespec tspec;

Expand Down
6 changes: 4 additions & 2 deletions app/src/zsw_clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ typedef struct {
/** @brief
* NOTE: This function needs the time as seconds
* @param ztm
* @return 0 when successful
*/
void zsw_clock_set_time(zsw_timeval_t *ztm);
int zsw_clock_set_time(zsw_timeval_t *ztm);

/** @brief
* @param ztm
* @return 0 when successful
*/
void zsw_clock_get_time(zsw_timeval_t *ztm);
int zsw_clock_get_time(zsw_timeval_t *ztm);

0 comments on commit 5a70a18

Please sign in to comment.