大理水控初始版本
diff --git a/sys_hw/rtc.c b/sys_hw/rtc.c
new file mode 100644
index 0000000..61f263c
--- /dev/null
+++ b/sys_hw/rtc.c
@@ -0,0 +1,165 @@
+#include "rtc.h"
+#include "time.h"
+#include "data_tools.h"
+#include "string.h"
+#include "timer.h"
+
+uint32_t CrystalStartErrFlag;
+
+static uint8_t rtc_wait_flag(uint32_t* reg, uint32_t mask, uint32_t flag, uint32_t timeout)
+{
+    uint32_t t = timeout/100;
+    
+    while(((*reg)&mask) != flag)
+    {
+        delay_ms(100);
+        t --;
+        if(t == 0)
+            return 1;
+    }
+    
+    return 0;
+}
+
+uint32_t rtc_get_counter(void)
+{
+    return (uint32_t)((RTC->CNTH << 16) | RTC->CNTL);
+}
+
+static uint8_t rtc_set_counter(uint32_t cnt)
+{
+    PWR->CR	 |= PWR_CR_DBP;         	// ʹÄÜ·ÃÎÊRTC, BDC ¼Ä´æÆ÷
+	RTC->CRL |=RTC_CRL_CNF;    		    // ÉèÖÃRTCÅäÖñê¼Ç,ÔÊÐíÅäÖÃ			
+	RTC->CNTH = (cnt>>16)&0xffff;
+	RTC->CNTL = cnt&0xffff ;
+	RTC->CRL  &= ~RTC_CRL_CNF; 			// ÉèÖÃRTCÅäÖñê¼Ç,²»ÔÊÐíÅäÖà 
+    if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RTOFF, RTC_FLAG_RTOFF, 4000ul))  //µÈ´ýÅäÖÃÍê³É 
+    {
+        PWR->CR   &= ~PWR_CR_DBP;      	// ²»ÔÊÐíÅäÖÃRTC¡¢BDC¼Ä´æÆ÷  
+        return 1;
+    }
+	PWR->CR   &= ~PWR_CR_DBP;      	// ²»ÔÊÐíÅäÖÃRTC¡¢BDC¼Ä´æÆ÷  
+    return 0;    
+}
+
+void rtc_init(void)
+{
+    CrystalStartErrFlag = 0;
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); 
+
+    //RTCÊ×´ÎÉϵç»òʱÖÓ¶ªÊ§
+    if(BKP_ReadBackupRegister(BKP_DR1) != 0x5A5A)
+    {
+        RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);       
+        PWR_BackupAccessCmd(ENABLE);
+        BKP_DeInit();
+        RCC_LSEConfig(RCC_LSE_ON);
+
+        //²ÎÕÕstm32f10x datasheet£¬LES startup time
+        //tsu(lse) = 3S (Typ)
+        //´Ë´¦µÈ´ýLSEÆðÕñÑÓʱԼ4S
+        if(rtc_wait_flag((uint32_t*)&RCC->BDCR, 0x02, 0x02, 4000ul))
+            CrystalStartErrFlag = 1;
+        
+        if(!CrystalStartErrFlag)
+        {
+            RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
+            RCC_RTCCLKCmd(ENABLE);
+			/* Clear RSF flag */
+			RTC->CRL &= (u16)~RTC_FLAG_RSF;            
+			/* Loop until RSF flag is set */
+            if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RSF, RTC_FLAG_RSF, 4000ul))
+                CrystalStartErrFlag = 1;
+            
+			//rtc wait for last task
+            if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RTOFF, RTC_FLAG_RTOFF, 4000ul))
+                CrystalStartErrFlag = 1;
+            
+            RTC_SetPrescaler(32767);
+			//rtc wait for last task
+            if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RTOFF, RTC_FLAG_RTOFF, 4000ul))
+                CrystalStartErrFlag = 1;  
+    
+            BKP_WriteBackupRegister(BKP_DR1, 0x5A5A);
+        } 
+        PWR_BackupAccessCmd(DISABLE); 
+        RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, DISABLE); 
+    }
+    else
+    {
+		/* Clear RSF flag */
+		RTC->CRL &= (u16)~RTC_FLAG_RSF;
+		/* Loop until RSF flag is set */
+        if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RSF, RTC_FLAG_RSF, 4000ul))
+            CrystalStartErrFlag = 1; 
+        else
+        {
+            //0x386D4380ul 2000Äê1ÔÂ1ÈÕÃëÊý
+            if(rtc_get_counter()<0x386D4380ul)
+            {
+                rtc_set_counter(0x386D4380ul);
+            }
+            
+//            rtc_get_time(&SystemTime);
+        }
+    }
+}
+
+uint32_t rtc_mk_time(_SystemTime* t)
+{
+    struct tm temp_time; 
+    _SystemTime temp_time_hex; 
+
+    memcpy(&temp_time_hex, t, sizeof(_SystemTime));
+    bcd2hex(&temp_time_hex, sizeof(temp_time_hex));
+    temp_time.tm_year = temp_time_hex.year+100;   //´Ó1900Ä꿪ʼ   
+    temp_time.tm_mon  = temp_time_hex.month-1;  
+    temp_time.tm_mday = temp_time_hex.day;    
+    temp_time.tm_wday = temp_time_hex.week;   
+    temp_time.tm_hour = temp_time_hex.hour;   
+    temp_time.tm_min  = temp_time_hex.minute; 
+    temp_time.tm_sec  = temp_time_hex.second; 
+    
+    return mktime(&temp_time);
+}
+
+uint8_t rtc_set_time(_SystemTime* t)
+{
+    uint8_t ret = 0;
+    time_t seconds = rtc_mk_time(t);
+    
+    ret = rtc_set_counter(seconds);
+    
+    return ret;
+}
+
+uint8_t rtc_get_time(_SystemTime* t)
+{
+    struct tm* temp_time;
+    _SystemTime temp_time_bcd;
+    time_t seconds = rtc_get_counter();
+    
+    temp_time = localtime(&seconds);
+    if(temp_time->tm_year<100)
+        temp_time_bcd.year = 0;
+    else
+        temp_time_bcd.year   = temp_time->tm_year - 100;
+    
+    temp_time_bcd.month  = temp_time->tm_mon+1;
+    temp_time_bcd.day    = temp_time->tm_mday;
+    temp_time_bcd.week   = temp_time->tm_wday;
+    temp_time_bcd.hour   = temp_time->tm_hour;
+    temp_time_bcd.minute = temp_time->tm_min;
+    temp_time_bcd.second = temp_time->tm_sec;
+    hex2bcd(&temp_time_bcd, sizeof(temp_time_bcd));
+    memcpy(t, &temp_time_bcd, sizeof(temp_time_bcd));
+    return 0;
+}
+
+uint32_t rtc_time_diff(void* t1, void* t2)
+{
+    uint32_t t1_sec = rtc_mk_time((_SystemTime*)t1);    
+    uint32_t t2_sec = rtc_mk_time((_SystemTime*)t2);
+    
+    return (t1_sec-t2_sec);
+}