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