PDL for FM0+  Version1.0
Peripheral Driverl Library for FM0+
C:/pdl_v10/library/driver/rtc/rtc.c
Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2013 Spansion LLC. All Rights Reserved. 
00003 *
00004 * This software is owned and published by: 
00005 * Spansion LLC, 915 DeGuigne Dr. Sunnyvale, CA  94088-3453 ("Spansion").
00006 *
00007 * BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND 
00008 * BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
00009 *
00010 * This software contains source code for use with Spansion 
00011 * components. This software is licensed by Spansion to be adapted only 
00012 * for use in systems utilizing Spansion components. Spansion shall not be 
00013 * responsible for misuse or illegal use of this software for devices not 
00014 * supported herein.  Spansion is providing this software "AS IS" and will 
00015 * not be responsible for issues arising from incorrect user implementation 
00016 * of the software.  
00017 *
00018 * SPANSION MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
00019 * REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS), 
00020 * ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING, 
00021 * WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED 
00022 * WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED 
00023 * WARRANTY OF NONINFRINGEMENT.  
00024 * SPANSION SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT, 
00025 * NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT 
00026 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, 
00027 * LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR 
00028 * INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT, 
00029 * INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA, 
00030 * SAVINGS OR PROFITS, 
00031 * EVEN IF SPANSION HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
00032 * YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
00033 * INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED 
00034 * FROM, THE SOFTWARE.  
00035 *
00036 * This software may be replicated in part or whole for the licensed use, 
00037 * with the restriction that this Disclaimer and Copyright notice must be 
00038 * included with each copy of this software, whether used in part or whole, 
00039 * at all times.  
00040 */
00041 /******************************************************************************/
00054 /******************************************************************************/
00055 /* Include files                                                              */
00056 /******************************************************************************/
00057 #include "rtc.h"
00058 
00059 #if (defined(PDL_PERIPHERAL_RTC_ACTIVE))
00060 
00066 
00067 /******************************************************************************/
00068 /* Local pre-processor symbols/macros ('#define')                             */
00069 /******************************************************************************/
00070 /* Timeout count */
00071 #define RTC_TIMEOUT              (SystemCoreClock/10)
00072 /* Error code for mktime */
00073 #define RTC_ERR                 (-1)
00074 /* convert DEC to BCD */
00075 #define DecToBcd(x)           ((((x)/10)<<4) + ((x)%10))
00076 /* convert BCD to DEC */
00077 #define BcdToDec(x)           ((((x)>>4)*10) + ((x)&0x0F))
00078 
00079 /******************************************************************************/
00080 /* Global variable definitions (declared in header file with 'extern')        */
00081 /******************************************************************************/
00082 
00083 /******************************************************************************/
00084 /* Local type definitions ('typedef')                                         */
00085 /******************************************************************************/
00086 
00087 /******************************************************************************/
00088 /* Local function prototypes ('static')                                       */
00089 /******************************************************************************/
00090 static void RtcToTm( stc_rtc_time_t* pstcRtcTime,
00091                             struct tm*      pstcTime);
00092 static void RtcDisableNvic(void);
00093 static void RtcRestoreNvic(void);
00094 
00095 #if (PDL_INTERRUPT_ENABLE_RTC == PDL_ON)
00096 static void RtcInitIrq(void);
00097 static void RtcDeInitIrq(void);
00098 #endif
00099 
00100 /******************************************************************************/
00101 /* Local variable definitions ('static')                                      */
00102 /******************************************************************************/
00103 #if (PDL_INTERRUPT_ENABLE_RTC == PDL_ON)
00104 static stc_rtc_intern_data_t stcRtcInternData;
00105 #endif
00106 static uint32_t u32NvicData;
00107 
00108 /******************************************************************************/
00109 /* Function implementation - global ('extern') and local ('static')           */
00110 /******************************************************************************/
00111 
00116 static void RtcDisableNvic(void)
00117 {
00118     u32NvicData = NVIC->ISER[(uint32_t)((int32_t)OSC_PLL_WC_RTC_IRQn) >> 5];
00119     NVIC->ICER[((uint32_t)(OSC_PLL_WC_RTC_IRQn) >> 5)] = (1 << ((uint32_t)(OSC_PLL_WC_RTC_IRQn) & 0x1F));
00120 }
00121 
00126 static void RtcRestoreNvic(void)
00127 {
00128     NVIC->ISER[(uint32_t)((int32_t)OSC_PLL_WC_RTC_IRQn) >> 5] = u32NvicData;
00129 }
00130 
00131 
00140 static void RtcToTm( stc_rtc_time_t* pstcRtcTime,
00141                             struct tm*      pstcTime)
00142 {
00143     pstcTime->tm_year  = (int)(pstcRtcTime->u16Year - 1900);
00144     pstcTime->tm_mon   = (int)(pstcRtcTime->u8Month - 1);
00145     pstcTime->tm_mday  = (int)(pstcRtcTime->u8Day);
00146     pstcTime->tm_sec   = (int)(pstcRtcTime->u8Second);
00147     pstcTime->tm_min   = (int)(pstcRtcTime->u8Minute);
00148     pstcTime->tm_hour  = (int)(pstcRtcTime->u8Hour);
00149     pstcTime->tm_isdst = 0;
00150 } /* RtcToTm */
00151 
00152 #if (PDL_INTERRUPT_ENABLE_RTC == PDL_ON)
00153 
00159 static void RtcInitIrq(void)
00160 {
00161     NVIC_ClearPendingIRQ(OSC_PLL_WC_RTC_IRQn);
00162     NVIC_EnableIRQ(OSC_PLL_WC_RTC_IRQn);
00163     NVIC_SetPriority(OSC_PLL_WC_RTC_IRQn, PDL_IRQ_LEVEL_CLK_WC_RTC);
00164 
00165 } /* RtcInitIrq */
00166 
00173 static void RtcDeInitIrq(void)
00174 {
00175     NVIC_ClearPendingIRQ(OSC_PLL_WC_RTC_IRQn);
00176     NVIC_DisableIRQ(OSC_PLL_WC_RTC_IRQn);
00177     NVIC_SetPriority(OSC_PLL_WC_RTC_IRQn, PDL_DEFAULT_INTERRUPT_LEVEL);
00178 } /* RtcDeInitIrq */
00179 
00184 void Rtc_IrqHandler(void)
00185 {
00186     stc_rtc_wtcr1_field_t stcWtcr1;
00187     stc_rtc_time_t stcTime;
00188     boolean_t bAlarmMatch = TRUE;
00189 
00190     stcWtcr1 = FM0P_RTC->WTCR1_f;
00191 
00192     /* Timer writing error Interrupt? */
00193     if (TRUE == stcWtcr1.INTERI)
00194     {
00195         /* Clear INTERI Flag */
00196         stcWtcr1.INTERI = FALSE;
00197 
00198         if (NULL != stcRtcInternData.pfnTimeWrtErrCallback)
00199         {
00200             /* Callback */
00201             stcRtcInternData.pfnTimeWrtErrCallback();
00202         }
00203     }
00204 
00205     /* Alarm Completion? */
00206     if (TRUE == stcWtcr1.INTALI)
00207     {
00208         /* Clear INTALI Flag */
00209         stcWtcr1.INTALI = FALSE;
00210         
00211         Rtc_ReadDateTime(&stcTime);
00212         
00213         if(FM0P_RTC->WTCR1_f.MIEN)
00214         {
00215             if(FM0P_RTC->ALMIR != DecToBcd(stcTime.u8Minute)) bAlarmMatch = FALSE;
00216         }
00217         if(FM0P_RTC->WTCR1_f.HEN)
00218         {
00219             if(FM0P_RTC->ALHR != DecToBcd(stcTime.u8Hour)) bAlarmMatch = FALSE;
00220         }
00221         if(FM0P_RTC->WTCR1_f.DEN)
00222         {
00223             if(FM0P_RTC->ALDR != DecToBcd(stcTime.u8Day)) bAlarmMatch = FALSE;
00224         }
00225         if(FM0P_RTC->WTCR1_f.MOEN)
00226         {
00227             if(FM0P_RTC->ALMOR != DecToBcd(stcTime.u8Month)) bAlarmMatch = FALSE;
00228         }
00229         if(FM0P_RTC->WTCR1_f.YEN)
00230         {
00231             if(FM0P_RTC->ALYR != DecToBcd(stcTime.u16Year - 2000)) bAlarmMatch = FALSE;
00232         }
00233 
00234         if(bAlarmMatch == TRUE)
00235         {
00236             if (NULL != stcRtcInternData.pfnAlarmCallback)
00237             {
00238                 /* Callback */
00239                 stcRtcInternData.pfnAlarmCallback();
00240             }
00241         }
00242     }
00243 
00244     /* Timer Interrupt? */
00245     if (TRUE == stcWtcr1.INTTMI)
00246     {
00247         /* Clear INTTMI Flag */
00248         stcWtcr1.INTTMI = FALSE;
00249 
00250         if (NULL != stcRtcInternData.pfnTimerCallback)
00251         {
00252             /* Callback */
00253             stcRtcInternData.pfnTimerCallback();
00254         }
00255     }
00256 
00257     /* 0.5-Second Interrupt? */
00258     if (TRUE == stcWtcr1.INTSSI)
00259     {
00260         /* Clear INTSSI Flag */
00261         stcWtcr1.INTSSI = FALSE;
00262 
00263         if (NULL != stcRtcInternData.pfnHalfSecondCallback)
00264         {
00265             /* Callback */
00266             stcRtcInternData.pfnHalfSecondCallback();
00267         }
00268     }
00269 
00270     /* One Second Interrupt? */
00271     if (TRUE == stcWtcr1.INTSI)
00272     {
00273         /* Clear INTSI Flag */
00274         stcWtcr1.INTSI = FALSE;
00275 
00276         if (NULL != stcRtcInternData.pfnOneSecondCallback)
00277         {
00278             /* Callback */
00279             stcRtcInternData.pfnOneSecondCallback();
00280         }
00281     }
00282 
00283     /* One Minute Interrupt? */
00284     if (TRUE == stcWtcr1.INTMI)
00285     {
00286         /* Clear INTMI Flag */
00287         stcWtcr1.INTMI = FALSE;
00288 
00289         if (NULL != stcRtcInternData.pfnOneMinuteCallback)
00290         {
00291             /* Callback */
00292             stcRtcInternData.pfnOneMinuteCallback();
00293         }
00294     }
00295 
00296     /* One Hour Interrupt? */
00297     if (TRUE == stcWtcr1.INTHI)
00298     {
00299         /* Clear INTHI Flag */
00300         stcWtcr1.INTHI = FALSE;
00301 
00302         if (NULL != stcRtcInternData.pfnOneHourCallback)
00303         {
00304             /* Callback */
00305             stcRtcInternData.pfnOneHourCallback();
00306         }
00307     }
00308 
00309     FM0P_RTC->WTCR1_f = stcWtcr1;
00310 } /* RtcIrqHandler */
00311 
00325 en_result_t Rtc_EnableInt(stc_rtc_int_sel_t* pstcIntSel, stc_rtc_int_cb_t* pstcIntCb)
00326 {
00327     stc_rtc_wtcr1_field_t stcWtcr1 ;
00328 
00329     stcWtcr1 = FM0P_RTC->WTCR1_f;
00330     /* Check for valid pointer */
00331     if ((NULL == pstcIntSel) || (NULL == pstcIntCb))
00332     {
00333         return ErrorInvalidParameter;
00334     }
00335     /* Enable timer rewrite error interrupt */
00336     if (TRUE == pstcIntSel->TimeRewriteErrorInt)
00337     {
00338         stcWtcr1.INTERIE = TRUE;
00339         stcRtcInternData.pfnTimeWrtErrCallback = pstcIntCb->pfnTimeWrtErrCallback;
00340     }
00341 
00342     /* Enable alarm coincidence interrupt */
00343     if (TRUE == pstcIntSel->AlarmInt)
00344     {
00345         stcWtcr1.INTALIE = TRUE;
00346         stcRtcInternData.pfnAlarmCallback = pstcIntCb->pfnAlarmCallback;
00347     }
00348 
00349     /* Enable timer underflow detection interrupt */
00350     if (TRUE == pstcIntSel->TimerInt)
00351     {
00352         stcWtcr1.INTTMIE = TRUE;
00353         stcRtcInternData.pfnTimerCallback = pstcIntCb->pfnTimerCallback;
00354     }
00355 
00356     /* Enable every hour interrupt */
00357     if (TRUE == pstcIntSel->OneHourInt)
00358     {
00359         stcWtcr1.INTHIE = TRUE;
00360         stcRtcInternData.pfnOneHourCallback = pstcIntCb->pfnOneHourCallback;
00361     }
00362 
00363     /* Enable every minute interrupt */
00364     if (TRUE == pstcIntSel->OneMinuteInt)
00365     {
00366         stcWtcr1.INTMIE = TRUE;
00367         stcRtcInternData.pfnOneMinuteCallback = pstcIntCb->pfnOneMinuteCallback;
00368     }
00369 
00370     /* Enable every second interrupt */
00371     if (TRUE == pstcIntSel->OneSecondInt)
00372     {
00373         stcWtcr1.INTSIE = TRUE;
00374         stcRtcInternData.pfnOneSecondCallback = pstcIntCb->pfnOneSecondCallback;
00375     }
00376 
00377     /* Enable every 0.5 second interrupt */
00378     if (TRUE == pstcIntSel->HalfSecondInt)
00379     {
00380         stcWtcr1.INTSSIE = TRUE;
00381         stcRtcInternData.pfnHalfSecondCallback = pstcIntCb->pfnHalfSecondCallback;
00382     }
00383 
00384     FM0P_RTC->WTCR1_f = stcWtcr1;  /* Update WTCR13 */
00385 
00386     RtcInitIrq();
00387 
00388     return (Ok);
00389 } /* Rtc_EnableDisableInterrupts */
00390 
00401 en_result_t Rtc_DisableInt(stc_rtc_int_sel_t* pstcIntSel)
00402 {
00403     stc_rtc_wtcr1_field_t stcWtcr1 ; 
00404     stcWtcr1 = FM0P_RTC->WTCR1_f;
00405     
00406     /* Check for valid pointer */
00407     if (NULL == pstcIntSel)
00408     {
00409         return ErrorInvalidParameter;
00410     }
00411 
00412     /* Enable timer rewrite error interrupt */
00413     if (TRUE == pstcIntSel->TimeRewriteErrorInt)
00414     {
00415         stcWtcr1.INTERIE = FALSE;
00416     }
00417 
00418     /* Enable alarm coincidence interrupt */
00419     if (TRUE == pstcIntSel->AlarmInt)
00420     {
00421         stcWtcr1.INTALIE = FALSE;
00422     }
00423 
00424     /* Enable timer underflow detection interrupt */
00425     if (TRUE == pstcIntSel->TimerInt)
00426     {
00427         stcWtcr1.INTTMIE = FALSE;
00428     }
00429 
00430     /* Enable every hour interrupt */
00431     if (TRUE == pstcIntSel->OneHourInt)
00432     {
00433         stcWtcr1.INTHIE = FALSE;
00434     }
00435 
00436     /* Enable every minute interrupt */
00437     if (TRUE == pstcIntSel->OneMinuteInt)
00438     {
00439         stcWtcr1.INTMIE = FALSE;;
00440     }
00441 
00442     /* Enable every second interrupt */
00443     if (TRUE == pstcIntSel->OneSecondInt)
00444     {
00445         stcWtcr1.INTSIE = FALSE;
00446     }
00447 
00448     /* Enable every 0.5 second interrupt */
00449     if (TRUE == pstcIntSel->HalfSecondInt)
00450     {
00451         stcWtcr1.INTSSIE = FALSE;
00452     }
00453 
00454     FM0P_RTC->WTCR1_f = stcWtcr1;  /* Update WTCR13 */
00455 
00456     if((FM0P_RTC->WTCR1 & 0xFF000000u) != 0u)
00457     {
00458         return Ok;
00459     }
00460     
00461     if(FM0P_WC->WCCR_f.WCIE != 0)
00462     {
00463         return Ok;
00464     }
00465         
00466     /* Only when RTC and WC interrupt are all disabled, disable IRQ */    
00467     RtcDeInitIrq();    
00468 
00469     return Ok;
00470 } /* Rtc_DisableInt */
00471 
00472 #endif
00473 
00488 en_result_t Rtc_Init(stc_rtc_config_t*       pstcConfig)
00489 {
00490     uint32_t u32Timeout = RTC_TIMEOUT;
00491     
00492     if(pstcConfig == NULL)
00493     {
00494         return ErrorInvalidParameter;
00495     }
00496     
00497     /* For initialization: Force all bits of WTCR1 and WTCR2 (inclusive ST bit) */
00498     /*   to '0'  */
00499     FM0P_RTC->WTCR1 = 0;
00500     FM0P_RTC->WTCR2 = 0;
00501 
00502     /* Select source clock for RTC */
00503     switch (pstcConfig->enClkSel)
00504     {
00505         case RtcUseSubClk:
00506             /* Select sub clock as source clock */
00507             FM0P_RTC->WTCLKS_f.WTCLKS = 0u;
00508             /* Wait until sub clock stable */
00509             while(1)
00510             {
00511                 if(FM0P_RTC->WTCLKM_f.WTCLKM == 0x02u)
00512                 {
00513                     break;
00514                 }
00515                 else
00516                 {
00517                     u32Timeout--;
00518                     if(u32Timeout == 0)
00519                     {
00520                         return ErrorTimeout;
00521                     }
00522                 }
00523             }
00524             
00525             FM0P_RTC->WTBR = (__CLKSO/4) - 1; /* set 0.5s as sub-second interval */
00526             break;
00527         case RtcuseMainClk:
00528             /* Select main clock as source clock */
00529             FM0P_RTC->WTCLKS_f.WTCLKS = 1u;
00530             /* Wait until main clock stable */
00531             while(1)
00532             {
00533                 if(FM0P_RTC->WTCLKM_f.WTCLKM == 0x03u)
00534                 {
00535                     break;
00536                 }
00537                 else
00538                 {
00539                     u32Timeout--;
00540                     if(u32Timeout == 0)
00541                     {
00542                         return ErrorTimeout;
00543                     }
00544                 }
00545             }
00546             FM0P_RTC->WTBR = (__CLKMO/4) - 1; /* set 0.5s as sub-second interval */
00547             break;  
00548         default:
00549             return ErrorInvalidParameter;
00550     }
00551        
00552     if(pstcConfig->bEnSuboutDivider == TRUE)
00553     {
00554         /* Disable divider */
00555         FM0P_RTC->WTDIVEN_f.WTDIVEN = 0;
00556         
00557         /* Set Divider ratio */
00558         switch (pstcConfig->enDividerRatio)
00559         {
00560             case RtcDivRatio1:
00561             case RtcDivRatio2:
00562             case RtcDivRatio4:
00563             case RtcDivRatio8:
00564             case RtcDivRatio16:
00565             case RtcDivRatio32:
00566             case RtcDivRatio64:
00567             case RtcDivRatio128:
00568             case RtcDivRatio256:
00569             case RtcDivRatio512:
00570             case RtcDivRatio1024:
00571             case RtcDivRatio2048:
00572             case RtcDivRatio4096:
00573             case RtcDivRatio8192:
00574             case RtcDivRatio16384:
00575             case RtcDivRatio32768:
00576                 FM0P_RTC->WTDIV = pstcConfig->enDividerRatio;
00577                 break;
00578             default:
00579                 return  ErrorInvalidParameter;
00580         }
00581         
00582         /*  Enable divider */
00583         u32Timeout = RTC_TIMEOUT;
00584         FM0P_RTC->WTDIVEN_f.WTDIVEN = 1;
00585         while(TRUE != FM0P_RTC->WTDIVEN_f.WTDIVRDY)
00586         {
00587             u32Timeout--;
00588             if(u32Timeout == 0)
00589             {
00590                 return ErrorInvalidParameter;
00591             }
00592         }
00593     }
00594     
00595     /* Initial frequency correction module */
00596     if(pstcConfig->bInitFreqCorr == TRUE)
00597     {
00598         if(pstcConfig->stcFreqCorrConfig.u16FreqCorrValue > RTC_MAX_FREQ_CORR_VALUE)
00599         {
00600             return ErrorInvalidParameter;
00601         }
00602         FM0P_RTC->WTCAL = pstcConfig->stcFreqCorrConfig.u16FreqCorrValue;
00603         
00604         if(pstcConfig->stcFreqCorrConfig.u16FreqCorrCycle > RTC_MAX_FREQ_CORR_CYCLE_SET_VALUE)
00605         {
00606             return ErrorInvalidParameter;
00607         }
00608         FM0P_RTC->WTCALPRD = pstcConfig->stcFreqCorrConfig.u16FreqCorrCycle;
00609     }
00610     
00611     /* Configure RTCCO output */
00612     if (pstcConfig->enRtccoSel == RtccoOutput2Hz) 
00613     {
00614         FM0P_RTC->WTCOSEL_f.WTCOSEL = 0; 
00615     }
00616     else
00617     {
00618         FM0P_RTC->WTCOSEL_f.WTCOSEL = 1; 
00619     }
00620       
00621     /* Initialize time and date */
00622     if(pstcConfig->bInitTimeDate == TRUE)
00623     {
00624         FM0P_RTC->WTSR  = DecToBcd(pstcConfig->stcTimeDate.u8Second);
00625         FM0P_RTC->WTMIR = DecToBcd(pstcConfig->stcTimeDate.u8Minute);
00626         FM0P_RTC->WTHR  = DecToBcd(pstcConfig->stcTimeDate.u8Hour);
00627         FM0P_RTC->WTDR  = DecToBcd(pstcConfig->stcTimeDate.u8Day);
00628         FM0P_RTC->WTMOR = DecToBcd(pstcConfig->stcTimeDate.u8Month);
00629         FM0P_RTC->WTYR  = DecToBcd(pstcConfig->stcTimeDate.u16Year - 2000);
00630         FM0P_RTC->WTDW  = DecToBcd(pstcConfig->stcTimeDate.u8DayOfWeek);
00631     }
00632     
00633     /* Initialize Alarm */
00634     if(pstcConfig->bInitAlarm == TRUE)
00635     {
00636         FM0P_RTC->ALMIR = DecToBcd(pstcConfig->stcAlarm.u8Minute);
00637         FM0P_RTC->ALHR  = DecToBcd(pstcConfig->stcAlarm.u8Hour);
00638         FM0P_RTC->ALDR  = DecToBcd(pstcConfig->stcAlarm.u8Day);
00639         FM0P_RTC->ALMOR = DecToBcd(pstcConfig->stcAlarm.u8Month);
00640         FM0P_RTC->ALYR  = DecToBcd(pstcConfig->stcAlarm.u16Year - 2000);
00641     }
00642     
00643     if(pstcConfig->bInitTimer == TRUE)
00644     {
00645         switch (pstcConfig->stcTimer.enMode)
00646         {
00647             case RtcTimerOneshot:
00648                 FM0P_RTC->WTCR2_f.TMEN = 0u;
00649                 break;
00650             case RtcTimerPeriod:
00651                 FM0P_RTC->WTCR2_f.TMEN = 1u;
00652                 break;
00653             default:
00654                 return ErrorInvalidParameter;
00655         }
00656         
00657         if(pstcConfig->stcTimer.u32TimerCycle > RTC_MAX_TIMER_SET_VALUE)
00658         {
00659             return ErrorInvalidParameter;
00660         }
00661         
00662         FM0P_RTC->WTTR = (pstcConfig->stcTimer.u32TimerCycle*2) - 1;
00663         
00664     }
00665 
00666     return (Ok);
00667 } /* Rtc_Init */
00668 
00678 en_result_t Rtc_DeInit(void)
00679 {
00680     /* Set all registers of RTC instance to '0' */
00681     FM0P_RTC->WTCAL    = 0;
00682     FM0P_RTC->WTCALEN  = 0;
00683     FM0P_RTC->WTDIV    = 0;
00684     FM0P_RTC->WTDIVEN  = 0;
00685     FM0P_RTC->WTCALPRD = 0;
00686     FM0P_RTC->WTCOSEL  = 0;
00687     FM0P_RTC->WTSR     = 0;
00688     FM0P_RTC->WTMIR    = 0;
00689     FM0P_RTC->WTHR     = 0;
00690     FM0P_RTC->WTDR     = 0;
00691     FM0P_RTC->WTDW     = 0;
00692     FM0P_RTC->WTMOR    = 0;
00693     FM0P_RTC->WTYR     = 0;
00694     FM0P_RTC->ALMIR    = 0;
00695     FM0P_RTC->ALHR     = 0;
00696     FM0P_RTC->ALDR     = 0;
00697     FM0P_RTC->ALMOR    = 0;
00698     FM0P_RTC->ALYR     = 0;
00699         
00700     return (Ok);
00701 } /* Rtc_DeInit */
00702 
00703 
00726 en_result_t Rtc_EnableFunc(en_rtc_func_t enFunc)
00727 {
00728     switch (enFunc)
00729     {
00730         case RtcCount:
00731             FM0P_RTC->WTCR1_f.ST = 1u;
00732             break;
00733         case RtcTimer:
00734             FM0P_RTC->WTCR2_f.TMST = 1u;
00735             break;
00736         case RtcFreqCorr:
00737             FM0P_RTC->WTCALEN_f.WTCALEN = 1u;
00738             break;
00739         case RtcAlarmYearEn:
00740             FM0P_RTC->WTCR1_f.YEN = 1u;
00741             break;
00742         case RtcAlarmMonthEn:
00743             FM0P_RTC->WTCR1_f.MOEN = 1u;
00744             break;
00745         case RtcAlarmDayEn:
00746             FM0P_RTC->WTCR1_f.DEN = 1u;
00747             break;
00748         case RtcAlarmHourEn:
00749             FM0P_RTC->WTCR1_f.HEN = 1u;
00750             break;
00751         case RtcAlarmMinEn:
00752             FM0P_RTC->WTCR1_f.MIEN = 1u;
00753             break;
00754         default:
00755             return ErrorInvalidParameter;
00756     }
00757     
00758     return Ok;
00759 }
00760        
00783 en_result_t Rtc_DisableFunc(en_rtc_func_t enFunc)
00784 {
00785     switch (enFunc)
00786     {
00787         case RtcCount:
00788             FM0P_RTC->WTCR1_f.ST = 0u;
00789             break;
00790         case RtcTimer:
00791             FM0P_RTC->WTCR2_f.TMST = 0u;
00792             break;
00793         case RtcFreqCorr:
00794             FM0P_RTC->WTCALEN_f.WTCALEN = 0u;
00795             break;
00796         case RtcAlarmYearEn:
00797             FM0P_RTC->WTCR1_f.YEN = 0u;
00798             break;
00799         case RtcAlarmMonthEn:
00800             FM0P_RTC->WTCR1_f.MOEN = 0u;
00801             break;
00802         case RtcAlarmDayEn:
00803             FM0P_RTC->WTCR1_f.DEN = 0u;
00804             break;
00805         case RtcAlarmHourEn:
00806             FM0P_RTC->WTCR1_f.HEN = 0u;
00807             break;
00808         case RtcAlarmMinEn:
00809             FM0P_RTC->WTCR1_f.MIEN = 0u;
00810             break;
00811         default:
00812             return ErrorInvalidParameter;
00813     }
00814     
00815     return Ok;
00816 }
00817 
00855 boolean_t Rtc_GetStatus(en_rtc_status_t enStatus)
00856 {
00857     boolean_t bRet = FALSE;
00858       
00859     switch(enStatus)
00860     {
00861         case RtcRewriteError:
00862             (FM0P_RTC->WTCR1_f.INTERI == 1) ? (bRet = TRUE) : (bRet = FALSE);
00863             break;
00864         case RtcAlarmElementMatch:
00865             (FM0P_RTC->WTCR1_f.INTALI == 1) ? (bRet = TRUE) : (bRet = FALSE);
00866             break;
00867         case RtcTimerUnderFlow:
00868             (FM0P_RTC->WTCR1_f.INTTMI == 1) ? (bRet = TRUE) : (bRet = FALSE);
00869             break;
00870         case RtcOneHourFlag:
00871             (FM0P_RTC->WTCR1_f.INTHI == 1) ? (bRet = TRUE) : (bRet = FALSE);
00872             break;
00873         case RtcOneMiniteFlag:
00874             (FM0P_RTC->WTCR1_f.INTMI == 1) ? (bRet = TRUE) : (bRet = FALSE);
00875             break;
00876         case RtcOneSecondFlag:
00877             (FM0P_RTC->WTCR1_f.INTSI == 1) ? (bRet = TRUE) : (bRet = FALSE);
00878             break;
00879         case RtcHalfSecondFlag:
00880             (FM0P_RTC->WTCR1_f.INTSSI == 1) ? (bRet = TRUE) : (bRet = FALSE);
00881             break;
00882         case RtcRunStatus:
00883             (FM0P_RTC->WTCR1_f.RUN == 1) ? (bRet = TRUE) : (bRet = FALSE);
00884             break;
00885         case RtcTimerStatus:
00886             (FM0P_RTC->WTCR2_f.TMRUN == 1) ? (bRet = TRUE) : (bRet = FALSE);
00887             break;
00888         default:
00889             break;  
00890     }
00891     
00892     return bRet;
00893 }
00894 
00918 en_result_t Rtc_ClrStatus(en_rtc_status_t enStatus)
00919 {      
00920     switch(enStatus)
00921     {
00922         case RtcRewriteError:
00923             FM0P_RTC->WTCR1_f.INTERI = 0;
00924             break;
00925         case RtcAlarmElementMatch:
00926             FM0P_RTC->WTCR1_f.INTALI = 0;
00927             break;
00928         case RtcTimerUnderFlow:
00929             FM0P_RTC->WTCR1_f.INTTMI = 0;
00930             break;
00931         case RtcOneHourFlag:
00932             FM0P_RTC->WTCR1_f.INTHI = 0;
00933             break;
00934         case RtcOneMiniteFlag:
00935             FM0P_RTC->WTCR1_f.INTMI = 0;
00936             break;
00937         case RtcOneSecondFlag:
00938             FM0P_RTC->WTCR1_f.INTSI = 0;
00939             break;
00940         case RtcHalfSecondFlag:
00941             FM0P_RTC->WTCR1_f.INTSSI = 0;
00942             break;
00943         case RtcRunStatus:
00944         case RtcTimerStatus:  
00945             break;
00946         default:
00947             return ErrorInvalidParameter;  
00948     }
00949     
00950     return Ok;
00951 }
00952         
00957 void Rtc_Reset(void)
00958 {
00959     FM0P_RTC->WTCR1_f.SRST = 1;
00960 }
00961         
00978 en_result_t Rtc_SetDateTime(stc_rtc_time_t* pstcTimeDate, boolean_t bContinue)
00979 {
00980     uint32_t u32TimeOut;
00981   
00982      /* Don't set time and date with this function before RTC starts */
00983     if(FM0P_RTC->WTCR1_f.RUN == 1)
00984     {
00985         return ErrorInvalidMode;
00986     }
00987     
00988     if(pstcTimeDate == NULL)
00989     {
00990         return ErrorInvalidParameter;  
00991     }
00992 
00993     if(FM0P_RTC->WTCR1_f.BUSY == 1)
00994     {
00995         /*  Wait until rewrite idle */
00996         u32TimeOut = RTC_TIMEOUT;
00997         while(1)
00998         {
00999             if(bContinue == TRUE)
01000             {
01001                 if((FM0P_RTC->WTCR1_f.BUSY == 0) && (FM0P_RTC->WTCR1_f.SCST == 0))
01002                 {
01003                     break;
01004                 }
01005             }
01006             else
01007             {
01008                 if((FM0P_RTC->WTCR1_f.BUSY == 0) && (FM0P_RTC->WTCR1_f.SCRST == 0))
01009                 {
01010                     break;
01011                 }
01012             }
01013             u32TimeOut--;
01014             if(u32TimeOut == 0)
01015             {
01016                 return ErrorTimeout;
01017             }
01018         }       
01019     }
01020              
01021     RtcDisableNvic();
01022                     
01023     if(bContinue == TRUE)
01024     {
01025         /* Stop 1 second output */
01026         FM0P_RTC->WTCR1_f.SCST = 1;
01027     }
01028     else
01029     {
01030         /* Reset 1 second counter */
01031         FM0P_RTC->WTCR1_f.SCRST = 1;
01032     }
01033     
01034     /* Set time and date */
01035     FM0P_RTC->WTSR  = DecToBcd(pstcTimeDate->u8Second);
01036     FM0P_RTC->WTMIR = DecToBcd(pstcTimeDate->u8Minute);
01037     FM0P_RTC->WTHR  = DecToBcd(pstcTimeDate->u8Hour);
01038     FM0P_RTC->WTDR  = DecToBcd(pstcTimeDate->u8Day);
01039     FM0P_RTC->WTMOR = DecToBcd(pstcTimeDate->u8Month);
01040     FM0P_RTC->WTYR  = DecToBcd(pstcTimeDate->u16Year - 2000);
01041     FM0P_RTC->WTDW  = DecToBcd(pstcTimeDate->u8DayOfWeek);
01042     
01043     if(bContinue == TRUE)
01044     {
01045         /* Refresh the time and date */
01046         FM0P_RTC->WTCR1_f.SCST = 0;
01047     }
01048     else
01049     {
01050         /* Refresh the time and date  */
01051         FM0P_RTC->WTCR1_f.SCRST = 0;
01052     }
01053     
01054     RtcRestoreNvic();    
01055     
01056     /* Wait until the transfer from time and date registers to counters end */
01057     u32TimeOut = RTC_TIMEOUT;
01058     while(1)
01059     {
01060         if(bContinue == TRUE)
01061         {
01062             if((FM0P_RTC->WTCR1_f.BUSY == 0) && (FM0P_RTC->WTCR1_f.SCST == 0))
01063             {
01064                 break;
01065             }
01066         }
01067         else
01068         {
01069             if((FM0P_RTC->WTCR1_f.BUSY == 0) && (FM0P_RTC->WTCR1_f.SCRST == 0))
01070             {
01071                 break;
01072             }
01073         }
01074         u32TimeOut--;
01075         if(u32TimeOut == 0)
01076         {
01077             return ErrorTimeout;
01078         }
01079     }    
01080                  
01081     return Ok;            
01082 }
01083                 
01096 en_result_t Rtc_ReadDateTime(stc_rtc_time_t* pstcTimeDate)
01097 {
01098     uint32_t u32TimeOut;
01099     uint8_t  u8DayOfWeek, u8BcdSec, u8BcdMin, u8BcdHour, u8Day, u8Month, u16Year = 0;
01100   
01101     if(pstcTimeDate == NULL)
01102     {
01103         return ErrorInvalidParameter;
01104     }
01105     
01106     RtcDisableNvic();
01107     
01108     if(FM0P_RTC->WTCR2_f.CREAD == 1) /* read is in process? */
01109     {
01110         ;  /* Already been read */
01111     }
01112     else
01113     {
01114         /* Start read */
01115         FM0P_RTC->WTCR2_f.CREAD = 1;
01116 
01117     }
01118     
01119     /* Wait until read finish */
01120     u32TimeOut = RTC_TIMEOUT;
01121     while(1)
01122     {
01123         if(FM0P_RTC->WTCR2_f.CREAD == 0)
01124         {
01125             break;
01126         }
01127         u32TimeOut --;
01128         if(u32TimeOut == 0)
01129         {
01130             RtcRestoreNvic(); 
01131             return ErrorTimeout;
01132         }
01133         
01134     }
01135     
01136     /* Read time and date */    
01137     u8BcdSec  = FM0P_RTC->WTSR;
01138     u8BcdMin  = FM0P_RTC->WTMIR;
01139     u8BcdHour = FM0P_RTC->WTHR;
01140     u8Day     = FM0P_RTC->WTDR;
01141     u8Month   = FM0P_RTC->WTMOR;
01142     u16Year    = FM0P_RTC->WTYR;
01143     u8DayOfWeek = FM0P_RTC->WTDW;
01144     
01145     pstcTimeDate->u8Second = BcdToDec(u8BcdSec);
01146     pstcTimeDate->u8Minute = BcdToDec(u8BcdMin);
01147     pstcTimeDate->u8Hour   = BcdToDec(u8BcdHour);
01148     pstcTimeDate->u8Day    = BcdToDec(u8Day);
01149     pstcTimeDate->u8Month  = BcdToDec(u8Month);
01150     pstcTimeDate->u16Year  = BcdToDec(u16Year) + 2000;
01151     pstcTimeDate->u8DayOfWeek = BcdToDec(u8DayOfWeek);
01152     
01153     RtcRestoreNvic(); 
01154     
01155     return Ok;
01156 }
01157 
01168 en_result_t Rtc_SetAlarmDateTime(stc_rtc_alarm_t* pstcAlarm)
01169 {
01170     if(pstcAlarm == NULL)
01171     {
01172         return ErrorInvalidParameter;
01173     }
01174   
01175     FM0P_RTC->ALMIR = DecToBcd(pstcAlarm->u8Minute);
01176     FM0P_RTC->ALHR  = DecToBcd(pstcAlarm->u8Hour);
01177     FM0P_RTC->ALDR  = DecToBcd(pstcAlarm->u8Day);
01178     FM0P_RTC->ALMOR = DecToBcd(pstcAlarm->u8Month);
01179     FM0P_RTC->ALYR  = DecToBcd(pstcAlarm->u16Year - 2000);
01180     
01181     return Ok;
01182 }
01183                 
01194 en_result_t Rtc_GetAlarmDateTime(stc_rtc_alarm_t* pstcAlarm)
01195 {
01196     uint8_t  u8BcdMin, u8BcdHour, u8Day, u8Month, u8Year;
01197     if(pstcAlarm == NULL)
01198     {
01199         return ErrorInvalidParameter;
01200     }
01201     
01202     u8BcdMin  = FM0P_RTC->ALMIR;
01203     u8BcdHour = FM0P_RTC->ALHR;
01204     u8Day     = FM0P_RTC->ALDR;
01205     u8Month   = FM0P_RTC->ALMOR;
01206     u8Year    = FM0P_RTC->ALYR;
01207     
01208     pstcAlarm->u8Minute = BcdToDec(u8BcdMin);
01209     pstcAlarm->u8Hour   = BcdToDec(u8BcdHour);
01210     pstcAlarm->u8Day    = BcdToDec(u8Day);
01211     pstcAlarm->u8Month  = BcdToDec(u8Month);
01212     pstcAlarm->u16Year   = BcdToDec(u8Year) + 2000;
01213     
01214     return Ok;
01215 }
01216                 
01230 en_result_t Rtc_SetDayOfWeek(stc_rtc_time_t* pstcRtcTime)
01231 {
01232     en_result_t enResult;
01233     struct tm stcTime;
01234 
01235     enResult = ErrorInvalidParameter;
01236 
01237     /* Check for NULL pointer */
01238     if (NULL != pstcRtcTime)
01239     {
01240         enResult = Ok;
01241         /* Convert RTC time structure to time.h tm structure */
01242         RtcToTm(pstcRtcTime, &stcTime);
01243 
01244         /* Calculated raw time (UNIX time) is error */
01245         if ((time_t)RTC_ERR == mktime(&stcTime))
01246         {
01247             enResult = ErrorInvalidParameter;
01248         }
01249 
01250         if (Ok == enResult)
01251         {
01252             /* Set calculated the day of week */
01253             pstcRtcTime->u8DayOfWeek = (uint8_t)(stcTime.tm_wday);
01254         }
01255     }
01256 
01257     return (enResult);
01258 } /* Rtc_SetDayOfWeek */
01259                 
01272 en_result_t Rtc_SetTimerCycle(uint32_t u32TimerCycle)
01273 {
01274     if(u32TimerCycle > RTC_MAX_TIMER_SET_VALUE)
01275     {
01276         return ErrorInvalidParameter;
01277     }
01278   
01279     FM0P_RTC->WTTR = (u32TimerCycle*2) - 1;
01280     
01281     return Ok;
01282 }
01283        
01294 en_result_t Rtc_SetFreqCorrValue(uint16_t u16Value)
01295 {
01296     if(u16Value > RTC_MAX_FREQ_CORR_VALUE)
01297     {
01298         return ErrorInvalidParameter;
01299     }
01300   
01301     FM0P_RTC->WTCAL = u16Value;
01302     
01303     return Ok;
01304 }
01305 
01307 
01308 #endif /* #if (defined(PDL_PERIPHERAL_RTC_ACTIVE)) */
01309 /******************************************************************************/
01310 /* EOF (not truncated)                                                        */
01311 /******************************************************************************/