summaryrefslogtreecommitdiff
path: root/bsp/hpmicro/libraries/hpm_sdk/drivers/src/hpm_rtc_drv.c
blob: d5ba53257651f20ff810bd49c4bbe5017d1e5dfa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
 * Copyright (c) 2021-2023 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include "hpm_common.h"
#include "hpm_rtc_drv.h"


hpm_stat_t rtc_config_time(RTC_Type *base, time_t time)
{
    base->SECOND = (uint32_t)time;
    return status_success;
}

time_t rtc_get_time(RTC_Type *base)
{
    time_t time = (time_t)base->SECOND;
    return time;
}

struct timeval rtc_get_timeval(RTC_Type *base)
{
    struct timeval tm;

    base->SUB_SNAP = 0; /* Lock shadow registers first */

    /* Convert sub-second ticks into micro-second */
    uint32_t sub_sec = (uint32_t)((base->SUB_SNAP >> 17) * 1.0 * 1000000 / 32768);

    tm.tv_sec   = base->SEC_SNAP;
    tm.tv_usec  = sub_sec;

    return tm;
}

hpm_stat_t rtc_config_alarm(RTC_Type *base, rtc_alarm_config_t *config)
{
    hpm_stat_t status = status_invalid_argument;
    do {
        if ((config == NULL) || (config->index > 1U) || (config->type > RTC_ALARM_TYPE_ABSOLUTE_TIME_ONE_SHOT)) {
            break;
        }
        uint32_t alarm_inc = 0;
        uint32_t alarm;
        if (config->type == RTC_ALARM_TYPE_ONE_SHOT) {
            uint32_t current_sec = base->SECOND;
            alarm = current_sec + config->period;
            if (alarm < current_sec) {
                break;
            }
        } else if (config->type == RTC_ALARM_TYPE_PERIODIC) {
            uint32_t current_sec = base->SECOND;
            alarm_inc = config->period;
            alarm = current_sec + config->period;
            if (alarm < current_sec) {
                break;
            }
        } else {
            alarm = config->period;
        }

        if (config->index == 0U) {
            base->ALARM0 = alarm;
            base->ALARM0_INC = alarm_inc;
        } else {
            base->ALARM1 = alarm;
            base->ALARM1_INC = alarm_inc;
        }

        status = status_success;
    } while (false);

    return status;
}