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(¤tDate, ¤tTime);
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(¤tDate, ¤tTime)) - 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