Bootload from SD card to sector 0, and jump to sector 24 where new firmware resides
Fork of Panel-Controller-Bootloader by
rtc.c
00001 /*-------------------------------------------------------------------------- */ 00002 /* RTC controls for STM32 */ 00003 /* Copyright (c) 2009, Martin Thomas 4/2009, 3BSD-license */ 00004 /* partly based on code from STMircoelectronics, Peter Dannegger, "LaLaDumm" */ 00005 /*-------------------------------------------------------------------------- */ 00006 00007 #include <stdint.h> 00008 #include <stdbool.h> 00009 #include "stm32f10x.h" 00010 #include "rtc.h" 00011 00012 #define FIRSTYEAR 2000 // start year 00013 #define FIRSTDAY 6 // 0 = Sunday 00014 00015 static const uint8_t DaysInMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 00016 00017 /******************************************************************************* 00018 * Function Name : isDST 00019 * Description : checks if given time is in Daylight Saving time-span. 00020 * Input : time-struct, must be fully populated including weekday 00021 * Output : none 00022 * Return : false: no DST ("winter"), true: in DST ("summer") 00023 * DST according to German standard 00024 * Based on code from Peter Dannegger found in the microcontroller.net forum. 00025 *******************************************************************************/ 00026 static bool isDST( const RTC_t *t ) 00027 { 00028 uint8_t wday, month; // locals for faster access 00029 00030 month = t->month; 00031 00032 if( month < 3 || month > 10 ) { // month 1, 2, 11, 12 00033 return false; // -> Winter 00034 } 00035 00036 wday = t->wday; 00037 00038 if( t->mday - wday >= 25 && (wday || t->hour >= 2) ) { // after last Sunday 2:00 00039 if( month == 10 ) { // October -> Winter 00040 return false; 00041 } 00042 } else { // before last Sunday 2:00 00043 if( month == 3 ) { // March -> Winter 00044 return false; 00045 } 00046 } 00047 00048 return true; 00049 } 00050 00051 /******************************************************************************* 00052 * Function Name : adjustDST 00053 * Description : adjusts time to DST if needed 00054 * Input : non DST time-struct, must be fully populated including weekday 00055 * Output : time-stuct gets modified 00056 * Return : false: no DST ("winter"), true: in DST ("summer") 00057 * DST according to German standard 00058 * Based on code from Peter Dannegger found in the microcontroller.net forum. 00059 *******************************************************************************/ 00060 static bool adjustDST( RTC_t *t ) 00061 { 00062 uint8_t hour, day, wday, month; // locals for faster access 00063 00064 hour = t->hour; 00065 day = t->mday; 00066 wday = t->wday; 00067 month = t->month; 00068 00069 if ( isDST(t) ) { 00070 t->dst = 1; 00071 hour++; // add one hour 00072 if( hour == 24 ){ // next day 00073 hour = 0; 00074 wday++; // next weekday 00075 if( wday == 7 ) { 00076 wday = 0; 00077 } 00078 if( day == DaysInMonth[month-1] ) { // next month 00079 day = 0; 00080 month++; 00081 } 00082 day++; 00083 } 00084 t->month = month; 00085 t->hour = hour; 00086 t->mday = day; 00087 t->wday = wday; 00088 return true; 00089 } else { 00090 t->dst = 0; 00091 return false; 00092 } 00093 } 00094 00095 /******************************************************************************* 00096 * Function Name : counter_to_struct 00097 * Description : populates time-struct based on counter-value 00098 * Input : - counter-value (unit seconds, 0 -> 1.1.2000 00:00:00), 00099 * - Pointer to time-struct 00100 * Output : time-struct gets populated, DST not taken into account here 00101 * Return : none 00102 * Based on code from Peter Dannegger found in the microcontroller.net forum. 00103 *******************************************************************************/ 00104 static void counter_to_struct( uint32_t sec, RTC_t *t ) 00105 { 00106 uint16_t day; 00107 uint8_t year; 00108 uint16_t dayofyear; 00109 uint8_t leap400; 00110 uint8_t month; 00111 00112 t->sec = sec % 60; 00113 sec /= 60; 00114 t->min = sec % 60; 00115 sec /= 60; 00116 t->hour = sec % 24; 00117 day = (uint16_t)(sec / 24); 00118 00119 t->wday = (day + FIRSTDAY) % 7; // weekday 00120 00121 year = FIRSTYEAR % 100; // 0..99 00122 leap400 = 4 - ((FIRSTYEAR - 1) / 100 & 3); // 4, 3, 2, 1 00123 00124 for(;;) { 00125 dayofyear = 365; 00126 if( (year & 3) == 0 ) { 00127 dayofyear = 366; // leap year 00128 if( year == 0 || year == 100 || year == 200 ) { // 100 year exception 00129 if( --leap400 ) { // 400 year exception 00130 dayofyear = 365; 00131 } 00132 } 00133 } 00134 if( day < dayofyear ) { 00135 break; 00136 } 00137 day -= dayofyear; 00138 year++; // 00..136 / 99..235 00139 } 00140 t->year = year + FIRSTYEAR / 100 * 100; // + century 00141 00142 if( dayofyear & 1 && day > 58 ) { // no leap year and after 28.2. 00143 day++; // skip 29.2. 00144 } 00145 00146 for( month = 1; day >= DaysInMonth[month-1]; month++ ) { 00147 day -= DaysInMonth[month-1]; 00148 } 00149 00150 t->month = month; // 1..12 00151 t->mday = day + 1; // 1..31 00152 } 00153 00154 /******************************************************************************* 00155 * Function Name : struct_to_counter 00156 * Description : calculates second-counter from populated time-struct 00157 * Input : Pointer to time-struct 00158 * Output : none 00159 * Return : counter-value (unit seconds, 0 -> 1.1.2000 00:00:00), 00160 * Based on code from "LalaDumm" found in the microcontroller.net forum. 00161 *******************************************************************************/ 00162 static uint32_t struct_to_counter( const RTC_t *t ) 00163 { 00164 uint8_t i; 00165 uint32_t result = 0; 00166 uint16_t idx, year; 00167 00168 year = t->year; 00169 00170 /* Calculate days of years before */ 00171 result = (uint32_t)year * 365; 00172 if (t->year >= 1) { 00173 result += (year + 3) / 4; 00174 result -= (year - 1) / 100; 00175 result += (year - 1) / 400; 00176 } 00177 00178 /* Start with 2000 a.d. */ 00179 result -= 730485UL; 00180 00181 /* Make month an array index */ 00182 idx = t->month - 1; 00183 00184 /* Loop thru each month, adding the days */ 00185 for (i = 0; i < idx; i++) { 00186 result += DaysInMonth[i]; 00187 } 00188 00189 /* Leap year? adjust February */ 00190 if (year%400 == 0 || (year%4 == 0 && year%100 !=0)) { 00191 ; 00192 } else { 00193 if (t->month > 1) { 00194 result--; 00195 } 00196 } 00197 00198 /* Add remaining days */ 00199 result += t->mday; 00200 00201 /* Convert to seconds, add all the other stuff */ 00202 result = (result-1) * 86400L + (uint32_t)t->hour * 3600 + 00203 (uint32_t)t->min * 60 + t->sec; 00204 00205 return result; 00206 } 00207 00208 /******************************************************************************* 00209 * Function Name : rtc_gettime 00210 * Description : populates structure from HW-RTC, takes DST into account 00211 * Input : None 00212 * Output : time-struct gets modified 00213 * Return : always true/not used 00214 *******************************************************************************/ 00215 bool rtc_gettime (RTC_t *rtc) 00216 { 00217 uint32_t t; 00218 00219 while ( ( t = RTC_GetCounter() ) != RTC_GetCounter() ) { ; } 00220 counter_to_struct( t, rtc ); // get non DST time 00221 adjustDST( rtc ); 00222 00223 return true; 00224 } 00225 00226 /******************************************************************************* 00227 * Function Name : my_RTC_SetCounter 00228 * Description : sets the hardware-counter 00229 * Input : new counter-value 00230 * Output : None 00231 * Return : None 00232 *******************************************************************************/ 00233 static void my_RTC_SetCounter(uint32_t cnt) 00234 { 00235 /* Wait until last write operation on RTC registers has finished */ 00236 RTC_WaitForLastTask(); 00237 /* Change the current time */ 00238 RTC_SetCounter(cnt); 00239 /* Wait until last write operation on RTC registers has finished */ 00240 RTC_WaitForLastTask(); 00241 } 00242 00243 /******************************************************************************* 00244 * Function Name : rtc_settime 00245 * Description : sets HW-RTC with values from time-struct, takes DST into 00246 * account, HW-RTC always running in non-DST time 00247 * Input : None 00248 * Output : None 00249 * Return : not used 00250 *******************************************************************************/ 00251 bool rtc_settime (const RTC_t *rtc) 00252 { 00253 uint32_t cnt; 00254 RTC_t ts; 00255 00256 cnt = struct_to_counter( rtc ); // non-DST counter-value 00257 counter_to_struct( cnt, &ts ); // normalize struct (for weekday) 00258 if ( isDST( &ts ) ) { 00259 cnt -= 60*60; // Subtract one hour 00260 } 00261 PWR_BackupAccessCmd(ENABLE); 00262 my_RTC_SetCounter( cnt ); 00263 PWR_BackupAccessCmd(DISABLE); 00264 00265 return true; 00266 } 00267 00268 /******************************************************************************* 00269 * Function Name : rtc_init 00270 * Description : initializes HW RTC, 00271 * sets default time-stamp if RTC has not been initialized before 00272 * Input : None 00273 * Output : None 00274 * Return : not used 00275 * Based on code from a STM RTC example in the StdPeriph-Library package 00276 *******************************************************************************/ 00277 int rtc_init(void) 00278 { 00279 volatile uint16_t i; 00280 00281 /* Enable PWR and BKP clocks */ 00282 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); 00283 00284 /* LSI clock stabilization time */ 00285 for(i=0;i<5000;i++) { ; } 00286 00287 if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) { 00288 /* Backup data register value is not correct or not yet programmed (when 00289 the first time the program is executed) */ 00290 00291 /* Allow access to BKP Domain */ 00292 PWR_BackupAccessCmd(ENABLE); 00293 00294 /* Reset Backup Domain */ 00295 BKP_DeInit(); 00296 00297 /* Enable LSE */ 00298 RCC_LSEConfig(RCC_LSE_ON); 00299 00300 /* Wait till LSE is ready */ 00301 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) { ; } 00302 00303 /* Select LSE as RTC Clock Source */ 00304 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); 00305 00306 /* Enable RTC Clock */ 00307 RCC_RTCCLKCmd(ENABLE); 00308 00309 /* Wait for RTC registers synchronization */ 00310 RTC_WaitForSynchro(); 00311 00312 /* Wait until last write operation on RTC registers has finished */ 00313 RTC_WaitForLastTask(); 00314 00315 /* Set RTC prescaler: set RTC period to 1sec */ 00316 RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */ 00317 00318 /* Wait until last write operation on RTC registers has finished */ 00319 RTC_WaitForLastTask(); 00320 00321 /* Set initial value */ 00322 RTC_SetCounter( (uint32_t)((11*60+55)*60) ); // here: 1st January 2000 11:55:00 00323 00324 /* Wait until last write operation on RTC registers has finished */ 00325 RTC_WaitForLastTask(); 00326 00327 BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); 00328 00329 /* Lock access to BKP Domain */ 00330 PWR_BackupAccessCmd(DISABLE); 00331 00332 } else { 00333 00334 /* Wait for RTC registers synchronization */ 00335 RTC_WaitForSynchro(); 00336 00337 } 00338 00339 return 0; 00340 } 00341 00342 00343
Generated on Fri Jul 15 2022 02:02:47 by 1.7.2