1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - RTC - libraries
3   File:     swclock.c
4 
5   Copyright 2003-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date: 2008-01-11#$
14   $Rev: 9449 $
15   $Author: tokunaga_eiji $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nitro/os.h>
19 #include <nitro/rtc.h>
20 #include <nitro/spi/ARM9/pm.h>
21 
22 /*---------------------------------------------------------------------------*
23     Static Variable Definitions
24  *---------------------------------------------------------------------------*/
25 static u16       rtcSWClockInitialized;       // Tick initialized verify flag
26 static OSTick    rtcSWClockBootTicks;         // Boot-time tick-converted RTC value
27 static RTCResult rtcLastResultOfSyncSWClock;  // RTCResult at final synchronization
28 static PMSleepCallbackInfo rtcSWClockSleepCbInfo; // Callback information when recovering from sleep
29 
30 /*---------------------------------------------------------------------------*
31     Internal Function Definitions
32  *---------------------------------------------------------------------------*/
33 
34 static void RtcGetDateTimeExFromSWClock(RTCDate * date, RTCTimeEx *time);
35 static void RtcSleepCallbackForSyncSWClock(void* args);
36 
37 /*---------------------------------------------------------------------------*
38   Name:         RTC_InitSWClock
39 
40   Description:  Initializes the software clock. Synchronizes the software clock value with the current RTC value, and adds a function to the sleep recovery callbacks that resynchronizes the RTC value and software clock.
41 
42 
43                 It is necessary to call this function before calling the RTC_GetDateTimeExFromSWClock or RTC_SyncSWClock functions.
44 
45 
46   Arguments:    None.
47 
48   Returns:      RTCResult - Returns the device operation processing result.
49  *---------------------------------------------------------------------------*/
RTC_InitSWClock(void)50 RTCResult RTC_InitSWClock(void)
51 {
52     SDK_ASSERT(OS_IsTickAvailable());
53 
54     // If already initialized, do nothing and return RTC_RESULT_SUCCESS
55     if(rtcSWClockInitialized)
56     {
57         return RTC_RESULT_SUCCESS;
58     }
59 
60     // Synchronize the software clock value with the current RTC.
61     (void) RTC_SyncSWClock();
62 
63     // Register sleep recovery callbacks.
64     PM_SetSleepCallbackInfo(&rtcSWClockSleepCbInfo, RtcSleepCallbackForSyncSWClock, NULL);
65     PM_AppendPostSleepCallback(&rtcSWClockSleepCbInfo);
66 
67     rtcSWClockInitialized = TRUE;
68 
69     return rtcLastResultOfSyncSWClock;
70 }
71 
72 /*---------------------------------------------------------------------------*
73   Name:         RTC_GetSWClockTicks
74 
75   Description:  Totals the current tick value and the boot-time tick-converted RTC value, and returns the length of time between January 1 2000 00:00:00 and the current time as a tick conversion value.
76 
77 
78   Arguments:    None.
79 
80   Returns:      OSTick: Tick conversion time from January 1 2000 00:00:00 to the current time
81                          If the most recent synchronization failed, this is 0.
82  *---------------------------------------------------------------------------*/
RTC_GetSWClockTick(void)83 OSTick RTC_GetSWClockTick(void)
84 {
85     if(rtcLastResultOfSyncSWClock == RTC_RESULT_SUCCESS)
86     {
87         return OS_GetTick() + rtcSWClockBootTicks;
88     }
89     else
90     {
91         return 0;
92     }
93 }
94 
95 /*---------------------------------------------------------------------------*
96   Name:         RTC_GetLastSyncSWClockResult
97 
98   Description:  Returns the result of the RTC_GetDateTime called during the most recent software clock synchronization.
99 
100 
101   Arguments:    None.
102 
103   Returns:      RTCResult: Result of the RTC_GetDateTime called at synchronization
104  *---------------------------------------------------------------------------*/
RTC_GetLastSyncSWClockResult(void)105 RTCResult RTC_GetLastSyncSWClockResult(void)
106 {
107     return rtcLastResultOfSyncSWClock;
108 }
109 
110 
111 /*---------------------------------------------------------------------------*
112   Name:         RTC_GetDateTimeExFromSWClock
113 
114   Description:  Reads date and time data up to the millisecond from the software clock (which uses CPU ticks)..
115 
116 
117   Arguments:    date: Specifies the buffer for storing date data.
118                 time: Specifies the buffer for storing time data.
119 
120   Returns:      RTCResult: Returns the RTCResult that was saved during the most recent synchronization
121  *---------------------------------------------------------------------------*/
RTC_GetDateTimeExFromSWClock(RTCDate * date,RTCTimeEx * time)122 RTCResult RTC_GetDateTimeExFromSWClock(RTCDate *date, RTCTimeEx *time)
123 {
124     SDK_NULL_ASSERT(date);
125     SDK_NULL_ASSERT(time);
126 
127     RtcGetDateTimeExFromSWClock(date, time);
128 
129     return rtcLastResultOfSyncSWClock;
130 }
131 
132 /*---------------------------------------------------------------------------*
133   Name:         RTC_SyncSWClock
134 
135   Description:  Synchronizes the software clock (which uses CPU ticks) to the RTC.
136                 The result of the RTC_GetDateTime called when synchronizing is saved and returned as the return value of RTC_GetDateTimeExFromSWClock.
137 
138 
139   Arguments:    None.
140 
141   Returns:      RTCResult: Returns the device operation processing result.
142  *---------------------------------------------------------------------------*/
RTC_SyncSWClock(void)143 RTCResult RTC_SyncSWClock(void)
144 {
145     RTCDate currentDate;
146     RTCTime currentTime;
147 
148     // Save the result of the RTC_GetDateTime.
149     rtcLastResultOfSyncSWClock = RTC_GetDateTime(&currentDate, &currentTime);
150     // Convert the current RTC to ticks, take the difference compared to the current CPU tick, and save the boot-time tick-converted RTC value.
151     rtcSWClockBootTicks = OS_SecondsToTicks(RTC_ConvertDateTimeToSecond(&currentDate, &currentTime)) - OS_GetTick();
152 
153     return rtcLastResultOfSyncSWClock;
154 }
155 
156 /*---------------------------------------------------------------------------*
157   Name:         RtcGetDateTimeExFromSWClock
158 
159   Description:  Calculates date and time data from the tick difference saved when the current ticks and software clock were synchronized to RTC.
160 
161 
162   Arguments:    date: Buffer for storing RTCDate
163                 time: Buffer for storing RTCTimeEx
164 
165   Returns:      None.
166  *---------------------------------------------------------------------------*/
RtcGetDateTimeExFromSWClock(RTCDate * date,RTCTimeEx * time)167 static void RtcGetDateTimeExFromSWClock(RTCDate * date, RTCTimeEx *time)
168 {
169     OSTick currentTicks;
170     s64 currentSWClockSeconds;
171 
172     currentTicks = RTC_GetSWClockTick();
173     currentSWClockSeconds = (s64) OS_TicksToSeconds(currentTicks);
174 
175     // Convert the current time in seconds (not including milliseconds) into RTCDate and RTCTime.
176     RTC_ConvertSecondToDateTime(date, (RTCTime*)time, currentSWClockSeconds);
177 
178     // Add milliseconds separately
179     time->millisecond = (u32) (OS_TicksToMilliSeconds(currentTicks) % 1000);
180 }
181 
182 /*---------------------------------------------------------------------------*
183   Name:         RtcSleepCallbackForSyncSWClock
184 
185   Description:  Sleep callback registered when RTC_InitSWClock is called.
186                 Synchronizes the software clock to the RTC when recovering from sleep.
187 
188   Arguments:    args: Unused argument
189 
190   Returns:      None.
191  *---------------------------------------------------------------------------*/
192 #define RTC_SWCLOCK_SYNC_RETRY_INTERVAL   1   // Units are milliseconds
RtcSleepCallbackForSyncSWClock(void * args)193 static void RtcSleepCallbackForSyncSWClock(void* args)
194 {
195 #pragma unused(args)
196     for (;;)
197     {
198         (void) RTC_SyncSWClock();
199 
200         // If the RTC is being processed by another thread or by the ARM7, or if the PXI FIFO is FULL, wait RTC_SWCLOCK_SYNC_RETRY_INTERVAL milliseconds and retry.
201         //
202         if(rtcLastResultOfSyncSWClock != RTC_RESULT_BUSY &&
203            rtcLastResultOfSyncSWClock != RTC_RESULT_SEND_ERROR)
204         {
205             break;
206         }
207 
208         OS_TWarning("RTC_SyncSWClock() failed at sleep callback. Retry... \n");
209         OS_Sleep(RTC_SWCLOCK_SYNC_RETRY_INTERVAL);
210     }
211 }
212 
213 /*---------------------------------------------------------------------------*
214   End of file
215  *---------------------------------------------------------------------------*/
216