source: rtems/bsps/arm/atsam/start/power-rtc.c @ 522cde4

5
Last change on this file since 522cde4 was 522cde4, checked in by Sebastian Huber <sebastian.huber@…>, on 06/18/19 at 09:31:48

atsam: Enable fast startup via RTC alarm

  • Property mode set to 100644
File size: 2.6 KB
Line 
1/*
2 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <bsp.h>
16#include <bsp/power.h>
17#include <bsp/irq.h>
18
19#include <libchip/chip.h>
20
21#define ATSAM_ENABLE_ALARM_INTERRUPT RTC_IER_ALREN
22
23static void set_rtc_alarm_interrupt(uint32_t interval)
24{
25        Rtc *rtc = RTC;
26        uint8_t hour;
27        uint8_t minute;
28        uint8_t second;
29        uint32_t time;
30
31        /* Clear current status register */
32        RTC_ClearSCCR(rtc, 0x3F);
33
34        RTC_GetTime(rtc, &hour, &minute, &second);
35
36        time = UINT32_C(3600) * hour + UINT32_C(60) * minute + second;
37        time = (time + interval) % (UINT32_C(24) * 3600);
38
39        second = (uint8_t) (time % 60);
40        minute = (uint8_t) ((time / 60) % 60);
41        hour = (uint8_t) (time / 3600);
42
43        if (interval < 60) {
44                RTC_SetTimeAlarm(rtc, NULL, NULL, &second);
45        } else if (interval < 3600) {
46                RTC_SetTimeAlarm(rtc, NULL, &minute, &second);
47        } else {
48                RTC_SetTimeAlarm(rtc, &hour, &minute, &second);
49        }
50
51        RTC_EnableIt(rtc, ATSAM_ENABLE_ALARM_INTERRUPT);
52}
53
54static void rtc_interrupt_handler(void *arg)
55{
56        atsam_power_data_rtc_driver *rtc_data;
57
58        rtc_data = (atsam_power_data_rtc_driver *)arg;
59        set_rtc_alarm_interrupt(rtc_data->interval);
60}
61
62static void rtc_alarm_handler(void *arg)
63{
64        Rtc *rtc = RTC;
65        rtems_status_code sc;
66
67        /* Clear current status register */
68        RTC_ClearSCCR(rtc, 0x3F);
69
70        /* Switch off all RTC interrupts */
71        RTC_DisableIt(rtc, 0x1F);
72
73        /* Install RTC interrupt handler */
74        sc = rtems_interrupt_handler_install(RTC_IRQn,
75            "RTC",
76            RTEMS_INTERRUPT_UNIQUE,
77            rtc_interrupt_handler,
78            arg
79        );
80        assert(sc == RTEMS_SUCCESSFUL);
81}
82
83static void set_time(void)
84{
85        rtems_time_of_day tod;
86        rtems_status_code sc;
87
88        atsam_rtc_get_time(&tod);
89        sc = rtems_clock_set(&tod);
90        assert(sc == RTEMS_SUCCESSFUL);
91}
92
93void atsam_power_handler_rtc_driver(
94    const atsam_power_control *control,
95    atsam_power_state state
96)
97{
98        atsam_power_data_rtc_driver *rtc_data;
99        rtems_interrupt_level level;
100        Rtc *rtc = RTC;
101
102        rtc_data = (atsam_power_data_rtc_driver *)control->data.arg;
103
104        switch (state) {
105                case ATSAM_POWER_ON:
106                        RTC_DisableIt(rtc, ATSAM_ENABLE_ALARM_INTERRUPT);
107                        set_time();
108                        break;
109                case ATSAM_POWER_OFF:
110                        set_rtc_alarm_interrupt(rtc_data->interval);
111                        break;
112                case ATSAM_POWER_INIT:
113                        /* Enable fast startup via RTC alarm */
114                        rtems_interrupt_disable(level);
115                        PMC->PMC_FSMR |= PMC_FSMR_RTCAL;
116                        rtems_interrupt_enable(level);
117
118                        rtc_alarm_handler(rtc_data);
119                        break;
120                default:
121                        break;
122        }
123}
Note: See TracBrowser for help on using the repository browser.