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

Revision:
0:c3a652eff606
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rtc.c	Tue Apr 21 09:30:11 2015 +0000
@@ -0,0 +1,343 @@
+/*--------------------------------------------------------------------------  */
+/*  RTC controls for STM32                                                    */
+/*  Copyright (c) 2009, Martin Thomas 4/2009, 3BSD-license                    */
+/*  partly based on code from STMircoelectronics, Peter Dannegger, "LaLaDumm" */
+/*--------------------------------------------------------------------------  */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "stm32f10x.h"
+#include "rtc.h"
+
+#define FIRSTYEAR   2000		// start year
+#define FIRSTDAY    6			// 0 = Sunday
+
+static const uint8_t DaysInMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+/*******************************************************************************
+* Function Name  : isDST
+* Description    : checks if given time is in Daylight Saving time-span.
+* Input          : time-struct, must be fully populated including weekday
+* Output         : none
+* Return         : false: no DST ("winter"), true: in DST ("summer")
+*  DST according to German standard
+*  Based on code from Peter Dannegger found in the microcontroller.net forum.
+*******************************************************************************/
+static bool isDST( const RTC_t *t )
+{
+	uint8_t wday, month;		// locals for faster access
+
+	month = t->month;
+
+	if( month < 3 || month > 10 ) {		// month 1, 2, 11, 12
+		return false;					// -> Winter
+	}
+
+	wday  = t->wday;
+
+	if( t->mday - wday >= 25 && (wday || t->hour >= 2) ) { // after last Sunday 2:00
+		if( month == 10 ) {				// October -> Winter
+			return false;
+		}
+	} else {							// before last Sunday 2:00
+		if( month == 3 ) {				// March -> Winter
+			return false;
+		}
+	}
+
+	return true;
+}
+
+/*******************************************************************************
+* Function Name  : adjustDST
+* Description    : adjusts time to DST if needed
+* Input          : non DST time-struct, must be fully populated including weekday
+* Output         : time-stuct gets modified
+* Return         : false: no DST ("winter"), true: in DST ("summer")
+*  DST according to German standard
+*  Based on code from Peter Dannegger found in the microcontroller.net forum.
+*******************************************************************************/
+static bool adjustDST( RTC_t *t )
+{
+	uint8_t hour, day, wday, month;			// locals for faster access
+
+	hour  = t->hour;
+	day   = t->mday;
+	wday  = t->wday;
+	month = t->month;
+
+	if ( isDST(t) ) {
+		t->dst = 1;
+		hour++;								// add one hour
+		if( hour == 24 ){					// next day
+			hour = 0;
+			wday++;							// next weekday
+			if( wday == 7 ) {
+				wday = 0;
+			}
+			if( day == DaysInMonth[month-1] ) {		// next month
+				day = 0;
+				month++;
+			}
+			day++;
+		}
+		t->month = month;
+		t->hour  = hour;
+		t->mday  = day;
+		t->wday  = wday;
+		return true;
+	} else {
+		t->dst = 0;
+		return false;
+	}
+}
+
+/*******************************************************************************
+* Function Name  : counter_to_struct
+* Description    : populates time-struct based on counter-value
+* Input          : - counter-value (unit seconds, 0 -> 1.1.2000 00:00:00),
+*                  - Pointer to time-struct
+* Output         : time-struct gets populated, DST not taken into account here
+* Return         : none
+*  Based on code from Peter Dannegger found in the microcontroller.net forum.
+*******************************************************************************/
+static void counter_to_struct( uint32_t sec, RTC_t *t )
+{
+	uint16_t day;
+	uint8_t year;
+	uint16_t dayofyear;
+	uint8_t leap400;
+	uint8_t month;
+
+	t->sec = sec % 60;
+	sec /= 60;
+	t->min = sec % 60;
+	sec /= 60;
+	t->hour = sec % 24;
+	day = (uint16_t)(sec / 24);
+
+	t->wday = (day + FIRSTDAY) % 7;		// weekday
+
+	year = FIRSTYEAR % 100;				// 0..99
+	leap400 = 4 - ((FIRSTYEAR - 1) / 100 & 3);	// 4, 3, 2, 1
+
+	for(;;) {
+		dayofyear = 365;
+		if( (year & 3) == 0 ) {
+			dayofyear = 366;					// leap year
+			if( year == 0 || year == 100 || year == 200 ) {	// 100 year exception
+				if( --leap400 ) {					// 400 year exception
+					dayofyear = 365;
+				}
+			}
+		}
+		if( day < dayofyear ) {
+			break;
+		}
+		day -= dayofyear;
+		year++;					// 00..136 / 99..235
+	}
+	t->year = year + FIRSTYEAR / 100 * 100;	// + century
+
+	if( dayofyear & 1 && day > 58 ) { 	// no leap year and after 28.2.
+		day++;					// skip 29.2.
+	}
+
+	for( month = 1; day >= DaysInMonth[month-1]; month++ ) {
+		day -= DaysInMonth[month-1];
+	}
+
+	t->month = month;				// 1..12
+	t->mday = day + 1;				// 1..31
+}
+
+/*******************************************************************************
+* Function Name  : struct_to_counter
+* Description    : calculates second-counter from populated time-struct
+* Input          : Pointer to time-struct
+* Output         : none
+* Return         : counter-value (unit seconds, 0 -> 1.1.2000 00:00:00),
+*  Based on code from "LalaDumm" found in the microcontroller.net forum.
+*******************************************************************************/
+static uint32_t struct_to_counter( const RTC_t *t )
+{
+	uint8_t i;
+	uint32_t result = 0;
+	uint16_t idx, year;
+
+	year = t->year;
+
+	/* Calculate days of years before */
+	result = (uint32_t)year * 365;
+	if (t->year >= 1) {
+		result += (year + 3) / 4;
+		result -= (year - 1) / 100;
+		result += (year - 1) / 400;
+	}
+
+	/* Start with 2000 a.d. */
+	result -= 730485UL;
+
+	/* Make month an array index */
+	idx = t->month - 1;
+
+	/* Loop thru each month, adding the days */
+	for (i = 0; i < idx; i++) {
+		result += DaysInMonth[i];
+	}
+
+	/* Leap year? adjust February */
+	if (year%400 == 0 || (year%4 == 0 && year%100 !=0)) {
+		;
+	} else {
+		if (t->month > 1) {
+			result--;
+		}
+	}
+
+	/* Add remaining days */
+	result += t->mday;
+
+	/* Convert to seconds, add all the other stuff */
+	result = (result-1) * 86400L + (uint32_t)t->hour * 3600 +
+		(uint32_t)t->min * 60 + t->sec;
+
+	return result;
+}
+
+/*******************************************************************************
+* Function Name  : rtc_gettime
+* Description    : populates structure from HW-RTC, takes DST into account
+* Input          : None
+* Output         : time-struct gets modified
+* Return         : always true/not used
+*******************************************************************************/
+bool rtc_gettime (RTC_t *rtc)
+{
+	uint32_t t;
+
+	while ( ( t = RTC_GetCounter() ) != RTC_GetCounter() ) { ; }
+	counter_to_struct( t, rtc ); // get non DST time
+	adjustDST( rtc );
+
+	return true;
+}
+
+/*******************************************************************************
+* Function Name  : my_RTC_SetCounter
+* Description    : sets the hardware-counter
+* Input          : new counter-value
+* Output         : None
+* Return         : None
+*******************************************************************************/
+static void my_RTC_SetCounter(uint32_t cnt)
+{
+	/* Wait until last write operation on RTC registers has finished */
+	RTC_WaitForLastTask();
+	/* Change the current time */
+	RTC_SetCounter(cnt);
+	/* Wait until last write operation on RTC registers has finished */
+	RTC_WaitForLastTask();
+}
+
+/*******************************************************************************
+* Function Name  : rtc_settime
+* Description    : sets HW-RTC with values from time-struct, takes DST into
+*                  account, HW-RTC always running in non-DST time
+* Input          : None
+* Output         : None
+* Return         : not used
+*******************************************************************************/
+bool rtc_settime (const RTC_t *rtc)
+{
+	uint32_t cnt;
+	RTC_t ts;
+
+	cnt = struct_to_counter( rtc ); // non-DST counter-value
+	counter_to_struct( cnt, &ts );  // normalize struct (for weekday)
+	if ( isDST( &ts ) ) {
+		cnt -= 60*60; // Subtract one hour
+	}
+	PWR_BackupAccessCmd(ENABLE);
+	my_RTC_SetCounter( cnt );
+	PWR_BackupAccessCmd(DISABLE);
+
+	return true;
+}
+
+/*******************************************************************************
+* Function Name  : rtc_init
+* Description    : initializes HW RTC,
+*                  sets default time-stamp if RTC has not been initialized before
+* Input          : None
+* Output         : None
+* Return         : not used
+*  Based on code from a STM RTC example in the StdPeriph-Library package
+*******************************************************************************/
+int rtc_init(void)
+{
+	volatile uint16_t i;
+
+	/* Enable PWR and BKP clocks */
+	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
+
+	/* LSI clock stabilization time */
+	for(i=0;i<5000;i++) { ; }
+
+	if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) {
+		/* Backup data register value is not correct or not yet programmed (when
+		   the first time the program is executed) */
+
+		/* Allow access to BKP Domain */
+		PWR_BackupAccessCmd(ENABLE);
+
+		/* Reset Backup Domain */
+		BKP_DeInit();
+
+		/* Enable LSE */
+		RCC_LSEConfig(RCC_LSE_ON);
+
+		/* Wait till LSE is ready */
+		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) { ; }
+
+		/* Select LSE as RTC Clock Source */
+		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
+
+		/* Enable RTC Clock */
+		RCC_RTCCLKCmd(ENABLE);
+
+		/* Wait for RTC registers synchronization */
+		RTC_WaitForSynchro();
+
+		/* Wait until last write operation on RTC registers has finished */
+		RTC_WaitForLastTask();
+
+		/* Set RTC prescaler: set RTC period to 1sec */
+		RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
+
+		/* Wait until last write operation on RTC registers has finished */
+		RTC_WaitForLastTask();
+
+		/* Set initial value */
+		RTC_SetCounter( (uint32_t)((11*60+55)*60) ); // here: 1st January 2000 11:55:00
+
+		/* Wait until last write operation on RTC registers has finished */
+		RTC_WaitForLastTask();
+
+		BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
+
+		/* Lock access to BKP Domain */
+		PWR_BackupAccessCmd(DISABLE);
+
+	} else {
+
+		/* Wait for RTC registers synchronization */
+		RTC_WaitForSynchro();
+
+	}
+
+	return 0;
+}
+
+
+