![]() |
PDL for FM0+
Version1.0
Peripheral Driverl Library for FM0+
|
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 /******************************************************************************/