TIMER: TIMER.c Source File

TIMER

TIMER.c
00001 
00060 /***********************************************************************************************************************
00061  * HEADER FILES
00062  **********************************************************************************************************************/
00063 #include "timer.h"
00064 
00065 /***********************************************************************************************************************
00066  * MACROS
00067  **********************************************************************************************************************/
00068 #define TIMER_CMP_100_DUTY             ((uint16_t)0) /* Compare value for 100% duty cycle */
00069 #define TIMER_RESOLUTION_SEC_TO_MICRO  (100000000U)  /* Convert the resolution from sec to usec, by dividing with the \
00070                                                       scale factor */
00071 #define TIMER_PRESCALER_MAX            (15U)      /* Maximum prescaler values allowed */
00072 #define TIMER_PERIOD_16BIT_MAX         (0xFFFFU)  /* Maximum period value */
00073 #define TIMER_PERIOD_MIN               (0x1U)     /* Minimum period value */
00074 #define TIMER_CLK_SCALE_FACTOR         (32U)      /* Scale factor used during calculation of the "TIMER_CLK_CONST_SCALED" */
00075 
00076 /***********************************************************************************************************************
00077  * LOCAL DATA
00078  **********************************************************************************************************************/
00079 
00080 /***********************************************************************************************************************
00081  * LOCAL ROUTINES
00082  **********************************************************************************************************************/
00083 #ifdef TIMER_CCU4_USED
00084 TIMER_STATUS_t TIMER_CCU4_lInit(TIMER_t* const handle_ptr);
00085 void TIMER_CCU4_lShadowTransfer(TIMER_t* const handle_ptr);
00086 #endif
00087 
00088 #ifdef TIMER_CCU8_USED
00089 TIMER_STATUS_t TIMER_CCU8_lInit(TIMER_t* const handle_ptr);
00090 void TIMER_CCU8_lShadowTransfer(TIMER_t* const handle_ptr);
00091 #endif
00092 
00093  /**********************************************************************************************************************
00094  * API IMPLEMENTATION
00095  **********************************************************************************************************************/
00096  /* Returns the version of the TIMER APP.
00097  */
00098 DAVE_APP_VERSION_t TIMER_GetAppVersion(void)
00099 {
00100   DAVE_APP_VERSION_t version;
00101 
00102   version.major = TIMER_MAJOR_VERSION;
00103   version.minor = TIMER_MINOR_VERSION;
00104   version.patch = TIMER_PATCH_VERSION;
00105 
00106   return version;
00107 }
00108 
00109 /*
00110  * This function initializes a TIMER APP based on user configuration.
00111  *
00112  */
00113 TIMER_STATUS_t TIMER_Init(TIMER_t* const handle_ptr)
00114 {
00115   TIMER_STATUS_t status;
00116 
00117   XMC_ASSERT("TIMER_Init:handle_ptr NULL" , (handle_ptr != NULL));
00118 
00119   status = TIMER_STATUS_SUCCESS;
00120   /* Check for APP instance is initialized or not */
00121   if (false == handle_ptr->initialized)
00122   {
00123 #ifdef TIMER_CCU4_USED
00124     if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00125     {
00126       /* Configure CCU4 timer for the required time tick settings */
00127       status = TIMER_CCU4_lInit(handle_ptr);
00128     }
00129 #endif
00130 
00131 #ifdef TIMER_CCU8_USED
00132     if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00133     {
00134       /* Configure CCU8 timer for the required time tick settings */
00135       status = TIMER_CCU8_lInit(handle_ptr);
00136     }
00137 #endif
00138   }
00139 
00140   return (status);
00141 }
00142 
00143 /*
00144  * This function starts the timer to generate the events for the specified time_interval value
00145  */
00146 TIMER_STATUS_t TIMER_Start(TIMER_t  *const handle_ptr)
00147 {
00148   TIMER_STATUS_t status;
00149 
00150   XMC_ASSERT("TIMER_Start:handle_ptr NULL" , (handle_ptr != NULL));
00151 
00152   /* Check for APP instance is initialized or not */
00153   if (true == handle_ptr->initialized)
00154   {
00155 #ifdef TIMER_CCU4_USED
00156     if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00157     {
00158       /* Start the timer manually */
00159       XMC_CCU4_SLICE_StartTimer(handle_ptr->ccu4_slice_ptr);
00160     }
00161 #endif
00162 
00163 #ifdef TIMER_CCU8_USED
00164     if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00165        {
00166       /* Start the timer manually */
00167       XMC_CCU8_SLICE_StartTimer(handle_ptr->ccu8_slice_ptr);
00168        }
00169 #endif
00170     status = TIMER_STATUS_SUCCESS;
00171   }
00172   else
00173   {
00174     status = TIMER_STATUS_FAILURE;
00175   }
00176 
00177   return (status);
00178 }
00179 
00180 /*
00181  * This function stops and clears the timer
00182  */
00183 TIMER_STATUS_t TIMER_Stop(TIMER_t  *const handle_ptr)
00184 {
00185   TIMER_STATUS_t status;
00186 
00187   XMC_ASSERT("TIMER_Stop:handle_ptr NULL" , (handle_ptr != NULL));
00188 
00189   /* Check whether timer is initialized and in running state */
00190   if ((TIMER_GetTimerStatus(handle_ptr)) && (true == handle_ptr->initialized))
00191   {
00192 #ifdef TIMER_CCU4_USED
00193     if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00194     {
00195       /* Stops the timer */
00196       XMC_CCU4_SLICE_StopTimer(handle_ptr->ccu4_slice_ptr);
00197     }
00198 #endif
00199 
00200 #ifdef TIMER_CCU8_USED
00201     if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00202        {
00203       /* Stops the timer */
00204       XMC_CCU8_SLICE_StopTimer(handle_ptr->ccu8_slice_ptr);
00205        }
00206 #endif
00207     status = TIMER_STATUS_SUCCESS;
00208   }
00209   else
00210   {
00211     status = TIMER_STATUS_FAILURE;
00212   }
00213 
00214   return (status);
00215 }
00216 
00217 /*
00218  * This function returns the status of the timer
00219  */
00220 bool TIMER_GetTimerStatus(TIMER_t  *const handle_ptr)
00221 {
00222   bool status;
00223 
00224   XMC_ASSERT("TIMER_GetTimerStatus:handle_ptr NULL" , (handle_ptr != NULL));
00225 
00226   status = false;
00227 
00228 #ifdef TIMER_CCU4_USED
00229   if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00230   {
00231     /* Returns the current status of the timer */
00232     status = XMC_CCU4_SLICE_IsTimerRunning(handle_ptr->ccu4_slice_ptr);
00233   }
00234 #endif
00235 
00236 #ifdef TIMER_CCU8_USED
00237   if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00238   {
00239     /* Returns the current status of the timer */
00240     status = XMC_CCU8_SLICE_IsTimerRunning(handle_ptr->ccu8_slice_ptr);
00241   }
00242 #endif
00243 
00244   return (status);
00245 }
00246 
00247 /*
00248  * This function changes the PWM period which in turn changes the time tick interval value by checking that
00249  * the given time tick value is within supported range.
00250  */
00251 TIMER_STATUS_t TIMER_SetTimeInterval(TIMER_t  *const handle_ptr, uint32_t time_interval)
00252 {
00253   TIMER_STATUS_t status;
00254   uint32_t lfrequency;
00255   uint32_t lprescaler;
00256 
00257   XMC_ASSERT("TIMER_SetTimeInterval:handle_ptr NULL" , (handle_ptr != NULL));
00258 
00259   status = TIMER_STATUS_FAILURE;
00260 
00261   if (false == TIMER_GetTimerStatus(handle_ptr))
00262   {
00263     /* check for time_interval range */
00264     if ((time_interval >= handle_ptr->timer_min_value_us) && (time_interval <= handle_ptr->timer_max_value_us))
00265     {
00266       /* Initialize the prescaler */
00267       lprescaler = 0U;
00268       while (time_interval > (handle_ptr->timer_max_value_us >> (TIMER_PRESCALER_MAX - lprescaler)))
00269       {
00270         lprescaler++;
00271       }
00272 #ifdef TIMER_CCU4_USED
00273       if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00274       {
00275         lfrequency = handle_ptr->global_ccu4_handler->module_frequency;
00276         handle_ptr->ccu4_slice_config_ptr->prescaler_initval = lprescaler;
00277         /* Calculate the period register for the required time_interval value */
00278         handle_ptr->period_value = (uint16_t)((((uint64_t)time_interval * lfrequency) >> \
00279                                                handle_ptr->ccu4_slice_config_ptr->prescaler_initval) / \
00280                                               TIMER_RESOLUTION_SEC_TO_MICRO);
00281         /* Actual timer period values is Period_reg_val+1U */
00282         if (handle_ptr->period_value > TIMER_PERIOD_MIN)
00283         {
00284           (handle_ptr->period_value)--;
00285         }
00286         /* Update the prescaler */
00287         XMC_CCU4_SLICE_SetPrescaler(handle_ptr->ccu4_slice_ptr, handle_ptr->ccu4_slice_config_ptr->prescaler_initval);
00288         /* update period, compare and prescaler values */
00289         TIMER_CCU4_lShadowTransfer(handle_ptr);
00290         /* Update the status */
00291         status = TIMER_STATUS_SUCCESS;
00292       }
00293 #endif
00294 
00295 #ifdef TIMER_CCU8_USED
00296       if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00297       {
00298         handle_ptr->ccu8_slice_config_ptr->prescaler_initval = lprescaler;
00299         lfrequency = handle_ptr->global_ccu8_handler->module_frequency;
00300         /* Calculate the period register for the required time_interval value */
00301         handle_ptr->period_value = (uint16_t)((((uint64_t)time_interval * lfrequency) >> \
00302                                                handle_ptr->ccu8_slice_config_ptr->prescaler_initval) / \
00303                                               TIMER_RESOLUTION_SEC_TO_MICRO);
00304         /* Actual timer period values is Period_reg_val+1U */
00305         if (handle_ptr->period_value > TIMER_PERIOD_MIN)
00306         {
00307           (handle_ptr->period_value)--;
00308         }
00309         /* Update the prescaler */
00310         XMC_CCU8_SLICE_SetPrescaler(handle_ptr->ccu8_slice_ptr, handle_ptr->ccu8_slice_config_ptr->prescaler_initval);
00311         /* update period, compare and prescaler values */
00312         TIMER_CCU8_lShadowTransfer(handle_ptr);
00313         /* Update the status */
00314         status = TIMER_STATUS_SUCCESS;
00315       }
00316 #endif
00317     }
00318   }
00319   return (status);
00320 }
00321 
00322 /*
00323  * This function reads the timer event(period match interrupt) status of the given timer
00324  */
00325 bool TIMER_GetInterruptStatus(TIMER_t * const handle_ptr)
00326 {
00327   bool status;
00328   XMC_ASSERT("TIMER_GetInterruptStatus:handle_ptr NULL" , (handle_ptr != NULL));
00329   status = false;
00330 #ifdef TIMER_CCU4_USED
00331   if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00332   {
00333     /* Reads the interrupt status */
00334     status = XMC_CCU4_SLICE_GetEvent(handle_ptr->ccu4_slice_ptr, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
00335   }
00336 #endif
00337 
00338 #ifdef TIMER_CCU8_USED
00339   if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00340   {
00341     /* Reads the interrupt status */
00342     status = XMC_CCU8_SLICE_GetEvent(handle_ptr->ccu8_slice_ptr, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH);
00343   }
00344 #endif
00345   return (status);
00346 }
00347 
00348 /*
00349  * This function clears the period match interrupt status of the given timer.
00350  */
00351 void TIMER_ClearEvent(TIMER_t *const handle_ptr)
00352 {
00353   XMC_ASSERT("TIME_CCU_AcknowledgeInterrupt:handle_ptr NULL" , (handle_ptr != NULL));
00354 
00355 #ifdef TIMER_CCU4_USED
00356   if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00357   {
00358     /* clears the timer event(period match interrupt) */
00359     XMC_CCU4_SLICE_ClearEvent(handle_ptr->ccu4_slice_ptr, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
00360   }
00361 #endif
00362 
00363 #ifdef TIMER_CCU8_USED
00364   if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00365   {
00366     /* clears the timer event(period match interrupt) */
00367     XMC_CCU8_SLICE_ClearEvent(handle_ptr->ccu8_slice_ptr, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH);
00368   }
00369 #endif
00370 }
00371 
00372 /*
00373  * This function returns the current time value
00374  */
00375 uint32_t TIMER_GetTime(TIMER_t *const handle_ptr)
00376 {
00377   uint32_t ltimer_val;
00378   uint32_t lprescaler;
00379   uint32_t ltime_val;
00380 
00381   XMC_ASSERT("TIMER_GetTimerStatus:handle_ptr NULL" , (handle_ptr != NULL));
00382   ltime_val = 0U;
00383 
00384 #ifdef TIMER_CCU4_USED
00385   if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00386   {
00387     /* Added one to according to the edge aligned mode */
00388     ltimer_val = (uint32_t)XMC_CCU4_SLICE_GetTimerValue(handle_ptr->ccu4_slice_ptr) + 1U;
00389     lprescaler = handle_ptr->ccu4_slice_config_ptr->prescaler_initval;
00390 
00391     /* calculate the time value in micro seconds and scaled with 100 */
00392     ltime_val = (uint32_t)((uint64_t)((uint64_t)ltimer_val * (uint64_t)TIMER_CLK_CONST_SCALED) >> \
00393                            (TIMER_CLK_SCALE_FACTOR - lprescaler));
00394   }
00395 #endif
00396 
00397 #ifdef TIMER_CCU8_USED
00398   if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00399   {
00400     /* Added one to according to the edge aligned mode */
00401     ltimer_val = (uint32_t)XMC_CCU8_SLICE_GetTimerValue(handle_ptr->ccu8_slice_ptr) + 1U;
00402     lprescaler = handle_ptr->ccu8_slice_config_ptr->prescaler_initval;
00403 
00404     /* calculate the time value in micro seconds and scaled with 100 */
00405     ltime_val = (uint32_t)((uint64_t)((uint64_t)ltimer_val * (uint64_t)TIMER_CLK_CONST_SCALED) >> \
00406                            (TIMER_CLK_SCALE_FACTOR - lprescaler));
00407   }
00408 #endif
00409 
00410   return ltime_val;
00411 }
00412 
00413 /*
00414  * Clear the timer
00415  */
00416 TIMER_STATUS_t TIMER_Clear(TIMER_t *const handle_ptr)
00417 {
00418   TIMER_STATUS_t status;
00419 
00420   XMC_ASSERT("TIMER_Clear:handle_ptr NULL" , (handle_ptr != NULL));
00421 
00422   /* Check for APP instance is initialized or not */
00423   if (true == handle_ptr->initialized)
00424   {
00425 #ifdef TIMER_CCU4_USED
00426     if (TIMER_MODULE_CCU4 == handle_ptr->timer_module)
00427     {
00428       /* Clear the timer register */
00429       XMC_CCU4_SLICE_ClearTimer(handle_ptr->ccu4_slice_ptr);
00430     }
00431 #endif
00432 
00433 #ifdef TIMER_CCU8_USED
00434     if (TIMER_MODULE_CCU8 == handle_ptr->timer_module)
00435     {
00436       /* Clear the timer register */
00437       XMC_CCU8_SLICE_ClearTimer(handle_ptr->ccu8_slice_ptr);
00438     }
00439 #endif
00440     status = TIMER_STATUS_SUCCESS;
00441   }
00442   else
00443   {
00444     status = TIMER_STATUS_FAILURE;
00445   }
00446 
00447   return (status);
00448 }
00449 
00450 /******************************************** PRIVATE FUNCTION DEFINITIONS ********************************************/
00451 #ifdef TIMER_CCU4_USED
00452 /*
00453  * This function configures timer ccu4 timer with required time tick value
00454  */
00455 TIMER_STATUS_t TIMER_CCU4_lInit(TIMER_t* const handle_ptr)
00456 {
00457   TIMER_STATUS_t status;
00458   /* Initialize the global registers */
00459   status = (TIMER_STATUS_t)GLOBAL_CCU4_Init(handle_ptr->global_ccu4_handler);
00460 
00461   /* Enable the clock for selected timer */
00462   XMC_CCU4_EnableClock(handle_ptr->global_ccu4_handler->module_ptr, handle_ptr->ccu4_slice_number);
00463   /* Configure the timer with required settings */
00464   XMC_CCU4_SLICE_CompareInit(handle_ptr->ccu4_slice_ptr, handle_ptr->ccu4_slice_config_ptr);
00465   /* programs the timer period and compare register according to time interval value and do the shadow transfer */
00466   TIMER_CCU4_lShadowTransfer(handle_ptr);
00467 
00468 #ifdef  TIMER_INTERRUPT
00469   if (true == handle_ptr->period_match_enable)
00470   {
00471     /* Binds a period match event to an NVIC node  */
00472     XMC_CCU4_SLICE_SetInterruptNode(handle_ptr->ccu4_slice_ptr, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH,
00473                                     handle_ptr->ccu4_period_match_node);
00474     /* Enables a timer(period match) event  */
00475     XMC_CCU4_SLICE_EnableEvent(handle_ptr->ccu4_slice_ptr, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
00476   }
00477 #endif
00478   /* Clears the timer register */
00479   XMC_CCU4_SLICE_ClearTimer(handle_ptr->ccu4_slice_ptr);
00480 
00481   /* update the initialization flag as true for particular instance*/
00482   handle_ptr->initialized = true;
00483 
00484   /* Check whether the start of the timer is enabled during initialization or not */
00485   if (handle_ptr->start_control == true)
00486   {
00487     /* Start the timer */
00488     XMC_CCU4_SLICE_StartTimer(handle_ptr->ccu4_slice_ptr);
00489   }
00490 
00491   return (status);
00492 }
00493 
00494 /*
00495  * This function configures timer period and compare values and triggers the shadow transfer operation
00496  */
00497 void TIMER_CCU4_lShadowTransfer(TIMER_t* const handle_ptr)
00498 {
00499   /* programs the timer period register according to time interval value */
00500   XMC_CCU4_SLICE_SetTimerPeriodMatch(handle_ptr->ccu4_slice_ptr, handle_ptr->period_value);
00501   /* programs the timer compare register for 50% duty cycle */
00502   XMC_CCU4_SLICE_SetTimerCompareMatch(handle_ptr->ccu4_slice_ptr, TIMER_CMP_100_DUTY);
00503   /* Transfers value from shadow timer registers to actual timer registers */
00504   XMC_CCU4_EnableShadowTransfer(handle_ptr->global_ccu4_handler->module_ptr, handle_ptr->shadow_mask);
00505 }
00506 #endif
00507 
00508 #ifdef TIMER_CCU8_USED
00509 /*
00510  * This function configures timer ccu8 timer with required time tick value
00511  */
00512 TIMER_STATUS_t TIMER_CCU8_lInit(TIMER_t* const handle_ptr)
00513 {
00514   TIMER_STATUS_t status;
00515   /* Initialize the global registers */
00516   status = (TIMER_STATUS_t)GLOBAL_CCU8_Init(handle_ptr->global_ccu8_handler);
00517 
00518   /* Enable the clock for selected timer */
00519   XMC_CCU8_EnableClock(handle_ptr->global_ccu8_handler->module_ptr, handle_ptr->ccu8_slice_number);
00520   /* Configure the timer with required settings */
00521   XMC_CCU8_SLICE_CompareInit(handle_ptr->ccu8_slice_ptr, handle_ptr->ccu8_slice_config_ptr);
00522   /* programs the timer period and compare register according to time interval value and do the shadow transfer */
00523   TIMER_CCU8_lShadowTransfer(handle_ptr);
00524 
00525 #ifdef  TIMER_INTERRUPT
00526   if (true == handle_ptr->period_match_enable)
00527   {
00528     /* Binds a period match event to an NVIC node  */
00529     XMC_CCU8_SLICE_SetInterruptNode(handle_ptr->ccu8_slice_ptr, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH,
00530                                     handle_ptr->ccu8_period_match_node);
00531     /* Enables a timer(period match) event  */
00532     XMC_CCU8_SLICE_EnableEvent(handle_ptr->ccu8_slice_ptr, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH);
00533   }
00534 #endif
00535   /* Clears the timer register */
00536   XMC_CCU8_SLICE_ClearTimer(handle_ptr->ccu8_slice_ptr);
00537 
00538   /* update the initialization flag as true for particular instance*/
00539   handle_ptr->initialized = true;
00540 
00541   /* Check whether the start of the timer is enabled during initialization or not */
00542   if (handle_ptr->start_control == true)
00543   {
00544     /* Start the timer */
00545     XMC_CCU8_SLICE_StartTimer(handle_ptr->ccu8_slice_ptr);
00546   }
00547 
00548   return (status);
00549 }
00550 
00551 /*
00552  * This function configures timer period and compare values and triggers the shadow transfer operation
00553  */
00554 void TIMER_CCU8_lShadowTransfer(TIMER_t* const handle_ptr)
00555 {
00556   /* programs the timer period register according to time interval value */
00557   XMC_CCU8_SLICE_SetTimerPeriodMatch(handle_ptr->ccu8_slice_ptr, handle_ptr->period_value);
00558   /* programs the timer compare register for 50% duty cycle in compare channel 1*/
00559   XMC_CCU8_SLICE_SetTimerCompareMatch(handle_ptr->ccu8_slice_ptr,
00560                                       XMC_CCU8_SLICE_COMPARE_CHANNEL_1,
00561                                       TIMER_CMP_100_DUTY);
00562   /* Transfers value from shadow timer registers to actual timer registers */
00563   XMC_CCU8_EnableShadowTransfer(handle_ptr->global_ccu8_handler->module_ptr, handle_ptr->shadow_mask);
00564 }
00565 #endif