Bootload from SD card to sector 0, and jump to sector 24 where new firmware resides

Dependencies:   FatFS mbed

Fork of Panel-Controller-Bootloader by Emma

Committer:
bonchenko
Date:
Tue Apr 21 09:30:11 2015 +0000
Revision:
0:c3a652eff606
Able to remove flash content, write new firmware from sd card, and jump to that new firmware. But its still not running completely

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bonchenko 0:c3a652eff606 1 /*-------------------------------------------------------------------------- */
bonchenko 0:c3a652eff606 2 /* RTC controls for STM32 */
bonchenko 0:c3a652eff606 3 /* Copyright (c) 2009, Martin Thomas 4/2009, 3BSD-license */
bonchenko 0:c3a652eff606 4 /* partly based on code from STMircoelectronics, Peter Dannegger, "LaLaDumm" */
bonchenko 0:c3a652eff606 5 /*-------------------------------------------------------------------------- */
bonchenko 0:c3a652eff606 6
bonchenko 0:c3a652eff606 7 #include <stdint.h>
bonchenko 0:c3a652eff606 8 #include <stdbool.h>
bonchenko 0:c3a652eff606 9 #include "stm32f10x.h"
bonchenko 0:c3a652eff606 10 #include "rtc.h"
bonchenko 0:c3a652eff606 11
bonchenko 0:c3a652eff606 12 #define FIRSTYEAR 2000 // start year
bonchenko 0:c3a652eff606 13 #define FIRSTDAY 6 // 0 = Sunday
bonchenko 0:c3a652eff606 14
bonchenko 0:c3a652eff606 15 static const uint8_t DaysInMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
bonchenko 0:c3a652eff606 16
bonchenko 0:c3a652eff606 17 /*******************************************************************************
bonchenko 0:c3a652eff606 18 * Function Name : isDST
bonchenko 0:c3a652eff606 19 * Description : checks if given time is in Daylight Saving time-span.
bonchenko 0:c3a652eff606 20 * Input : time-struct, must be fully populated including weekday
bonchenko 0:c3a652eff606 21 * Output : none
bonchenko 0:c3a652eff606 22 * Return : false: no DST ("winter"), true: in DST ("summer")
bonchenko 0:c3a652eff606 23 * DST according to German standard
bonchenko 0:c3a652eff606 24 * Based on code from Peter Dannegger found in the microcontroller.net forum.
bonchenko 0:c3a652eff606 25 *******************************************************************************/
bonchenko 0:c3a652eff606 26 static bool isDST( const RTC_t *t )
bonchenko 0:c3a652eff606 27 {
bonchenko 0:c3a652eff606 28 uint8_t wday, month; // locals for faster access
bonchenko 0:c3a652eff606 29
bonchenko 0:c3a652eff606 30 month = t->month;
bonchenko 0:c3a652eff606 31
bonchenko 0:c3a652eff606 32 if( month < 3 || month > 10 ) { // month 1, 2, 11, 12
bonchenko 0:c3a652eff606 33 return false; // -> Winter
bonchenko 0:c3a652eff606 34 }
bonchenko 0:c3a652eff606 35
bonchenko 0:c3a652eff606 36 wday = t->wday;
bonchenko 0:c3a652eff606 37
bonchenko 0:c3a652eff606 38 if( t->mday - wday >= 25 && (wday || t->hour >= 2) ) { // after last Sunday 2:00
bonchenko 0:c3a652eff606 39 if( month == 10 ) { // October -> Winter
bonchenko 0:c3a652eff606 40 return false;
bonchenko 0:c3a652eff606 41 }
bonchenko 0:c3a652eff606 42 } else { // before last Sunday 2:00
bonchenko 0:c3a652eff606 43 if( month == 3 ) { // March -> Winter
bonchenko 0:c3a652eff606 44 return false;
bonchenko 0:c3a652eff606 45 }
bonchenko 0:c3a652eff606 46 }
bonchenko 0:c3a652eff606 47
bonchenko 0:c3a652eff606 48 return true;
bonchenko 0:c3a652eff606 49 }
bonchenko 0:c3a652eff606 50
bonchenko 0:c3a652eff606 51 /*******************************************************************************
bonchenko 0:c3a652eff606 52 * Function Name : adjustDST
bonchenko 0:c3a652eff606 53 * Description : adjusts time to DST if needed
bonchenko 0:c3a652eff606 54 * Input : non DST time-struct, must be fully populated including weekday
bonchenko 0:c3a652eff606 55 * Output : time-stuct gets modified
bonchenko 0:c3a652eff606 56 * Return : false: no DST ("winter"), true: in DST ("summer")
bonchenko 0:c3a652eff606 57 * DST according to German standard
bonchenko 0:c3a652eff606 58 * Based on code from Peter Dannegger found in the microcontroller.net forum.
bonchenko 0:c3a652eff606 59 *******************************************************************************/
bonchenko 0:c3a652eff606 60 static bool adjustDST( RTC_t *t )
bonchenko 0:c3a652eff606 61 {
bonchenko 0:c3a652eff606 62 uint8_t hour, day, wday, month; // locals for faster access
bonchenko 0:c3a652eff606 63
bonchenko 0:c3a652eff606 64 hour = t->hour;
bonchenko 0:c3a652eff606 65 day = t->mday;
bonchenko 0:c3a652eff606 66 wday = t->wday;
bonchenko 0:c3a652eff606 67 month = t->month;
bonchenko 0:c3a652eff606 68
bonchenko 0:c3a652eff606 69 if ( isDST(t) ) {
bonchenko 0:c3a652eff606 70 t->dst = 1;
bonchenko 0:c3a652eff606 71 hour++; // add one hour
bonchenko 0:c3a652eff606 72 if( hour == 24 ){ // next day
bonchenko 0:c3a652eff606 73 hour = 0;
bonchenko 0:c3a652eff606 74 wday++; // next weekday
bonchenko 0:c3a652eff606 75 if( wday == 7 ) {
bonchenko 0:c3a652eff606 76 wday = 0;
bonchenko 0:c3a652eff606 77 }
bonchenko 0:c3a652eff606 78 if( day == DaysInMonth[month-1] ) { // next month
bonchenko 0:c3a652eff606 79 day = 0;
bonchenko 0:c3a652eff606 80 month++;
bonchenko 0:c3a652eff606 81 }
bonchenko 0:c3a652eff606 82 day++;
bonchenko 0:c3a652eff606 83 }
bonchenko 0:c3a652eff606 84 t->month = month;
bonchenko 0:c3a652eff606 85 t->hour = hour;
bonchenko 0:c3a652eff606 86 t->mday = day;
bonchenko 0:c3a652eff606 87 t->wday = wday;
bonchenko 0:c3a652eff606 88 return true;
bonchenko 0:c3a652eff606 89 } else {
bonchenko 0:c3a652eff606 90 t->dst = 0;
bonchenko 0:c3a652eff606 91 return false;
bonchenko 0:c3a652eff606 92 }
bonchenko 0:c3a652eff606 93 }
bonchenko 0:c3a652eff606 94
bonchenko 0:c3a652eff606 95 /*******************************************************************************
bonchenko 0:c3a652eff606 96 * Function Name : counter_to_struct
bonchenko 0:c3a652eff606 97 * Description : populates time-struct based on counter-value
bonchenko 0:c3a652eff606 98 * Input : - counter-value (unit seconds, 0 -> 1.1.2000 00:00:00),
bonchenko 0:c3a652eff606 99 * - Pointer to time-struct
bonchenko 0:c3a652eff606 100 * Output : time-struct gets populated, DST not taken into account here
bonchenko 0:c3a652eff606 101 * Return : none
bonchenko 0:c3a652eff606 102 * Based on code from Peter Dannegger found in the microcontroller.net forum.
bonchenko 0:c3a652eff606 103 *******************************************************************************/
bonchenko 0:c3a652eff606 104 static void counter_to_struct( uint32_t sec, RTC_t *t )
bonchenko 0:c3a652eff606 105 {
bonchenko 0:c3a652eff606 106 uint16_t day;
bonchenko 0:c3a652eff606 107 uint8_t year;
bonchenko 0:c3a652eff606 108 uint16_t dayofyear;
bonchenko 0:c3a652eff606 109 uint8_t leap400;
bonchenko 0:c3a652eff606 110 uint8_t month;
bonchenko 0:c3a652eff606 111
bonchenko 0:c3a652eff606 112 t->sec = sec % 60;
bonchenko 0:c3a652eff606 113 sec /= 60;
bonchenko 0:c3a652eff606 114 t->min = sec % 60;
bonchenko 0:c3a652eff606 115 sec /= 60;
bonchenko 0:c3a652eff606 116 t->hour = sec % 24;
bonchenko 0:c3a652eff606 117 day = (uint16_t)(sec / 24);
bonchenko 0:c3a652eff606 118
bonchenko 0:c3a652eff606 119 t->wday = (day + FIRSTDAY) % 7; // weekday
bonchenko 0:c3a652eff606 120
bonchenko 0:c3a652eff606 121 year = FIRSTYEAR % 100; // 0..99
bonchenko 0:c3a652eff606 122 leap400 = 4 - ((FIRSTYEAR - 1) / 100 & 3); // 4, 3, 2, 1
bonchenko 0:c3a652eff606 123
bonchenko 0:c3a652eff606 124 for(;;) {
bonchenko 0:c3a652eff606 125 dayofyear = 365;
bonchenko 0:c3a652eff606 126 if( (year & 3) == 0 ) {
bonchenko 0:c3a652eff606 127 dayofyear = 366; // leap year
bonchenko 0:c3a652eff606 128 if( year == 0 || year == 100 || year == 200 ) { // 100 year exception
bonchenko 0:c3a652eff606 129 if( --leap400 ) { // 400 year exception
bonchenko 0:c3a652eff606 130 dayofyear = 365;
bonchenko 0:c3a652eff606 131 }
bonchenko 0:c3a652eff606 132 }
bonchenko 0:c3a652eff606 133 }
bonchenko 0:c3a652eff606 134 if( day < dayofyear ) {
bonchenko 0:c3a652eff606 135 break;
bonchenko 0:c3a652eff606 136 }
bonchenko 0:c3a652eff606 137 day -= dayofyear;
bonchenko 0:c3a652eff606 138 year++; // 00..136 / 99..235
bonchenko 0:c3a652eff606 139 }
bonchenko 0:c3a652eff606 140 t->year = year + FIRSTYEAR / 100 * 100; // + century
bonchenko 0:c3a652eff606 141
bonchenko 0:c3a652eff606 142 if( dayofyear & 1 && day > 58 ) { // no leap year and after 28.2.
bonchenko 0:c3a652eff606 143 day++; // skip 29.2.
bonchenko 0:c3a652eff606 144 }
bonchenko 0:c3a652eff606 145
bonchenko 0:c3a652eff606 146 for( month = 1; day >= DaysInMonth[month-1]; month++ ) {
bonchenko 0:c3a652eff606 147 day -= DaysInMonth[month-1];
bonchenko 0:c3a652eff606 148 }
bonchenko 0:c3a652eff606 149
bonchenko 0:c3a652eff606 150 t->month = month; // 1..12
bonchenko 0:c3a652eff606 151 t->mday = day + 1; // 1..31
bonchenko 0:c3a652eff606 152 }
bonchenko 0:c3a652eff606 153
bonchenko 0:c3a652eff606 154 /*******************************************************************************
bonchenko 0:c3a652eff606 155 * Function Name : struct_to_counter
bonchenko 0:c3a652eff606 156 * Description : calculates second-counter from populated time-struct
bonchenko 0:c3a652eff606 157 * Input : Pointer to time-struct
bonchenko 0:c3a652eff606 158 * Output : none
bonchenko 0:c3a652eff606 159 * Return : counter-value (unit seconds, 0 -> 1.1.2000 00:00:00),
bonchenko 0:c3a652eff606 160 * Based on code from "LalaDumm" found in the microcontroller.net forum.
bonchenko 0:c3a652eff606 161 *******************************************************************************/
bonchenko 0:c3a652eff606 162 static uint32_t struct_to_counter( const RTC_t *t )
bonchenko 0:c3a652eff606 163 {
bonchenko 0:c3a652eff606 164 uint8_t i;
bonchenko 0:c3a652eff606 165 uint32_t result = 0;
bonchenko 0:c3a652eff606 166 uint16_t idx, year;
bonchenko 0:c3a652eff606 167
bonchenko 0:c3a652eff606 168 year = t->year;
bonchenko 0:c3a652eff606 169
bonchenko 0:c3a652eff606 170 /* Calculate days of years before */
bonchenko 0:c3a652eff606 171 result = (uint32_t)year * 365;
bonchenko 0:c3a652eff606 172 if (t->year >= 1) {
bonchenko 0:c3a652eff606 173 result += (year + 3) / 4;
bonchenko 0:c3a652eff606 174 result -= (year - 1) / 100;
bonchenko 0:c3a652eff606 175 result += (year - 1) / 400;
bonchenko 0:c3a652eff606 176 }
bonchenko 0:c3a652eff606 177
bonchenko 0:c3a652eff606 178 /* Start with 2000 a.d. */
bonchenko 0:c3a652eff606 179 result -= 730485UL;
bonchenko 0:c3a652eff606 180
bonchenko 0:c3a652eff606 181 /* Make month an array index */
bonchenko 0:c3a652eff606 182 idx = t->month - 1;
bonchenko 0:c3a652eff606 183
bonchenko 0:c3a652eff606 184 /* Loop thru each month, adding the days */
bonchenko 0:c3a652eff606 185 for (i = 0; i < idx; i++) {
bonchenko 0:c3a652eff606 186 result += DaysInMonth[i];
bonchenko 0:c3a652eff606 187 }
bonchenko 0:c3a652eff606 188
bonchenko 0:c3a652eff606 189 /* Leap year? adjust February */
bonchenko 0:c3a652eff606 190 if (year%400 == 0 || (year%4 == 0 && year%100 !=0)) {
bonchenko 0:c3a652eff606 191 ;
bonchenko 0:c3a652eff606 192 } else {
bonchenko 0:c3a652eff606 193 if (t->month > 1) {
bonchenko 0:c3a652eff606 194 result--;
bonchenko 0:c3a652eff606 195 }
bonchenko 0:c3a652eff606 196 }
bonchenko 0:c3a652eff606 197
bonchenko 0:c3a652eff606 198 /* Add remaining days */
bonchenko 0:c3a652eff606 199 result += t->mday;
bonchenko 0:c3a652eff606 200
bonchenko 0:c3a652eff606 201 /* Convert to seconds, add all the other stuff */
bonchenko 0:c3a652eff606 202 result = (result-1) * 86400L + (uint32_t)t->hour * 3600 +
bonchenko 0:c3a652eff606 203 (uint32_t)t->min * 60 + t->sec;
bonchenko 0:c3a652eff606 204
bonchenko 0:c3a652eff606 205 return result;
bonchenko 0:c3a652eff606 206 }
bonchenko 0:c3a652eff606 207
bonchenko 0:c3a652eff606 208 /*******************************************************************************
bonchenko 0:c3a652eff606 209 * Function Name : rtc_gettime
bonchenko 0:c3a652eff606 210 * Description : populates structure from HW-RTC, takes DST into account
bonchenko 0:c3a652eff606 211 * Input : None
bonchenko 0:c3a652eff606 212 * Output : time-struct gets modified
bonchenko 0:c3a652eff606 213 * Return : always true/not used
bonchenko 0:c3a652eff606 214 *******************************************************************************/
bonchenko 0:c3a652eff606 215 bool rtc_gettime (RTC_t *rtc)
bonchenko 0:c3a652eff606 216 {
bonchenko 0:c3a652eff606 217 uint32_t t;
bonchenko 0:c3a652eff606 218
bonchenko 0:c3a652eff606 219 while ( ( t = RTC_GetCounter() ) != RTC_GetCounter() ) { ; }
bonchenko 0:c3a652eff606 220 counter_to_struct( t, rtc ); // get non DST time
bonchenko 0:c3a652eff606 221 adjustDST( rtc );
bonchenko 0:c3a652eff606 222
bonchenko 0:c3a652eff606 223 return true;
bonchenko 0:c3a652eff606 224 }
bonchenko 0:c3a652eff606 225
bonchenko 0:c3a652eff606 226 /*******************************************************************************
bonchenko 0:c3a652eff606 227 * Function Name : my_RTC_SetCounter
bonchenko 0:c3a652eff606 228 * Description : sets the hardware-counter
bonchenko 0:c3a652eff606 229 * Input : new counter-value
bonchenko 0:c3a652eff606 230 * Output : None
bonchenko 0:c3a652eff606 231 * Return : None
bonchenko 0:c3a652eff606 232 *******************************************************************************/
bonchenko 0:c3a652eff606 233 static void my_RTC_SetCounter(uint32_t cnt)
bonchenko 0:c3a652eff606 234 {
bonchenko 0:c3a652eff606 235 /* Wait until last write operation on RTC registers has finished */
bonchenko 0:c3a652eff606 236 RTC_WaitForLastTask();
bonchenko 0:c3a652eff606 237 /* Change the current time */
bonchenko 0:c3a652eff606 238 RTC_SetCounter(cnt);
bonchenko 0:c3a652eff606 239 /* Wait until last write operation on RTC registers has finished */
bonchenko 0:c3a652eff606 240 RTC_WaitForLastTask();
bonchenko 0:c3a652eff606 241 }
bonchenko 0:c3a652eff606 242
bonchenko 0:c3a652eff606 243 /*******************************************************************************
bonchenko 0:c3a652eff606 244 * Function Name : rtc_settime
bonchenko 0:c3a652eff606 245 * Description : sets HW-RTC with values from time-struct, takes DST into
bonchenko 0:c3a652eff606 246 * account, HW-RTC always running in non-DST time
bonchenko 0:c3a652eff606 247 * Input : None
bonchenko 0:c3a652eff606 248 * Output : None
bonchenko 0:c3a652eff606 249 * Return : not used
bonchenko 0:c3a652eff606 250 *******************************************************************************/
bonchenko 0:c3a652eff606 251 bool rtc_settime (const RTC_t *rtc)
bonchenko 0:c3a652eff606 252 {
bonchenko 0:c3a652eff606 253 uint32_t cnt;
bonchenko 0:c3a652eff606 254 RTC_t ts;
bonchenko 0:c3a652eff606 255
bonchenko 0:c3a652eff606 256 cnt = struct_to_counter( rtc ); // non-DST counter-value
bonchenko 0:c3a652eff606 257 counter_to_struct( cnt, &ts ); // normalize struct (for weekday)
bonchenko 0:c3a652eff606 258 if ( isDST( &ts ) ) {
bonchenko 0:c3a652eff606 259 cnt -= 60*60; // Subtract one hour
bonchenko 0:c3a652eff606 260 }
bonchenko 0:c3a652eff606 261 PWR_BackupAccessCmd(ENABLE);
bonchenko 0:c3a652eff606 262 my_RTC_SetCounter( cnt );
bonchenko 0:c3a652eff606 263 PWR_BackupAccessCmd(DISABLE);
bonchenko 0:c3a652eff606 264
bonchenko 0:c3a652eff606 265 return true;
bonchenko 0:c3a652eff606 266 }
bonchenko 0:c3a652eff606 267
bonchenko 0:c3a652eff606 268 /*******************************************************************************
bonchenko 0:c3a652eff606 269 * Function Name : rtc_init
bonchenko 0:c3a652eff606 270 * Description : initializes HW RTC,
bonchenko 0:c3a652eff606 271 * sets default time-stamp if RTC has not been initialized before
bonchenko 0:c3a652eff606 272 * Input : None
bonchenko 0:c3a652eff606 273 * Output : None
bonchenko 0:c3a652eff606 274 * Return : not used
bonchenko 0:c3a652eff606 275 * Based on code from a STM RTC example in the StdPeriph-Library package
bonchenko 0:c3a652eff606 276 *******************************************************************************/
bonchenko 0:c3a652eff606 277 int rtc_init(void)
bonchenko 0:c3a652eff606 278 {
bonchenko 0:c3a652eff606 279 volatile uint16_t i;
bonchenko 0:c3a652eff606 280
bonchenko 0:c3a652eff606 281 /* Enable PWR and BKP clocks */
bonchenko 0:c3a652eff606 282 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
bonchenko 0:c3a652eff606 283
bonchenko 0:c3a652eff606 284 /* LSI clock stabilization time */
bonchenko 0:c3a652eff606 285 for(i=0;i<5000;i++) { ; }
bonchenko 0:c3a652eff606 286
bonchenko 0:c3a652eff606 287 if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) {
bonchenko 0:c3a652eff606 288 /* Backup data register value is not correct or not yet programmed (when
bonchenko 0:c3a652eff606 289 the first time the program is executed) */
bonchenko 0:c3a652eff606 290
bonchenko 0:c3a652eff606 291 /* Allow access to BKP Domain */
bonchenko 0:c3a652eff606 292 PWR_BackupAccessCmd(ENABLE);
bonchenko 0:c3a652eff606 293
bonchenko 0:c3a652eff606 294 /* Reset Backup Domain */
bonchenko 0:c3a652eff606 295 BKP_DeInit();
bonchenko 0:c3a652eff606 296
bonchenko 0:c3a652eff606 297 /* Enable LSE */
bonchenko 0:c3a652eff606 298 RCC_LSEConfig(RCC_LSE_ON);
bonchenko 0:c3a652eff606 299
bonchenko 0:c3a652eff606 300 /* Wait till LSE is ready */
bonchenko 0:c3a652eff606 301 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) { ; }
bonchenko 0:c3a652eff606 302
bonchenko 0:c3a652eff606 303 /* Select LSE as RTC Clock Source */
bonchenko 0:c3a652eff606 304 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
bonchenko 0:c3a652eff606 305
bonchenko 0:c3a652eff606 306 /* Enable RTC Clock */
bonchenko 0:c3a652eff606 307 RCC_RTCCLKCmd(ENABLE);
bonchenko 0:c3a652eff606 308
bonchenko 0:c3a652eff606 309 /* Wait for RTC registers synchronization */
bonchenko 0:c3a652eff606 310 RTC_WaitForSynchro();
bonchenko 0:c3a652eff606 311
bonchenko 0:c3a652eff606 312 /* Wait until last write operation on RTC registers has finished */
bonchenko 0:c3a652eff606 313 RTC_WaitForLastTask();
bonchenko 0:c3a652eff606 314
bonchenko 0:c3a652eff606 315 /* Set RTC prescaler: set RTC period to 1sec */
bonchenko 0:c3a652eff606 316 RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
bonchenko 0:c3a652eff606 317
bonchenko 0:c3a652eff606 318 /* Wait until last write operation on RTC registers has finished */
bonchenko 0:c3a652eff606 319 RTC_WaitForLastTask();
bonchenko 0:c3a652eff606 320
bonchenko 0:c3a652eff606 321 /* Set initial value */
bonchenko 0:c3a652eff606 322 RTC_SetCounter( (uint32_t)((11*60+55)*60) ); // here: 1st January 2000 11:55:00
bonchenko 0:c3a652eff606 323
bonchenko 0:c3a652eff606 324 /* Wait until last write operation on RTC registers has finished */
bonchenko 0:c3a652eff606 325 RTC_WaitForLastTask();
bonchenko 0:c3a652eff606 326
bonchenko 0:c3a652eff606 327 BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
bonchenko 0:c3a652eff606 328
bonchenko 0:c3a652eff606 329 /* Lock access to BKP Domain */
bonchenko 0:c3a652eff606 330 PWR_BackupAccessCmd(DISABLE);
bonchenko 0:c3a652eff606 331
bonchenko 0:c3a652eff606 332 } else {
bonchenko 0:c3a652eff606 333
bonchenko 0:c3a652eff606 334 /* Wait for RTC registers synchronization */
bonchenko 0:c3a652eff606 335 RTC_WaitForSynchro();
bonchenko 0:c3a652eff606 336
bonchenko 0:c3a652eff606 337 }
bonchenko 0:c3a652eff606 338
bonchenko 0:c3a652eff606 339 return 0;
bonchenko 0:c3a652eff606 340 }
bonchenko 0:c3a652eff606 341
bonchenko 0:c3a652eff606 342
bonchenko 0:c3a652eff606 343