|
@@ -0,0 +1,576 @@
|
|
|
+/*****************************************************************************
|
|
|
+* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved.
|
|
|
+*
|
|
|
+* Unless you and Broadcom execute a separate written software license
|
|
|
+* agreement governing use of this software, this software is licensed to you
|
|
|
+* under the terms of the GNU General Public License version 2, available at
|
|
|
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
|
|
|
+*
|
|
|
+* Notwithstanding the above, under no circumstances may you combine this
|
|
|
+* software in any way with any other Broadcom software provided under a
|
|
|
+* license other than the GPL, without Broadcom's express prior written
|
|
|
+* consent.
|
|
|
+*****************************************************************************/
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @file tmrHw.c
|
|
|
+*
|
|
|
+* @brief Low level Timer driver routines
|
|
|
+*
|
|
|
+* @note
|
|
|
+*
|
|
|
+* These routines provide basic timer functionality only.
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+
|
|
|
+/* ---- Include Files ---------------------------------------------------- */
|
|
|
+
|
|
|
+#include <csp/errno.h>
|
|
|
+#include <csp/stdint.h>
|
|
|
+
|
|
|
+#include <csp/tmrHw.h>
|
|
|
+#include <mach/csp/tmrHw_reg.h>
|
|
|
+
|
|
|
+#define tmrHw_ASSERT(a) if (!(a)) *(char *)0 = 0
|
|
|
+#define tmrHw_MILLISEC_PER_SEC (1000)
|
|
|
+
|
|
|
+#define tmrHw_LOW_1_RESOLUTION_COUNT (tmrHw_LOW_RESOLUTION_CLOCK / tmrHw_MILLISEC_PER_SEC)
|
|
|
+#define tmrHw_LOW_1_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_1_RESOLUTION_COUNT)
|
|
|
+#define tmrHw_LOW_16_RESOLUTION_COUNT (tmrHw_LOW_1_RESOLUTION_COUNT / 16)
|
|
|
+#define tmrHw_LOW_16_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_16_RESOLUTION_COUNT)
|
|
|
+#define tmrHw_LOW_256_RESOLUTION_COUNT (tmrHw_LOW_1_RESOLUTION_COUNT / 256)
|
|
|
+#define tmrHw_LOW_256_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_256_RESOLUTION_COUNT)
|
|
|
+
|
|
|
+#define tmrHw_HIGH_1_RESOLUTION_COUNT (tmrHw_HIGH_RESOLUTION_CLOCK / tmrHw_MILLISEC_PER_SEC)
|
|
|
+#define tmrHw_HIGH_1_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_1_RESOLUTION_COUNT)
|
|
|
+#define tmrHw_HIGH_16_RESOLUTION_COUNT (tmrHw_HIGH_1_RESOLUTION_COUNT / 16)
|
|
|
+#define tmrHw_HIGH_16_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_16_RESOLUTION_COUNT)
|
|
|
+#define tmrHw_HIGH_256_RESOLUTION_COUNT (tmrHw_HIGH_1_RESOLUTION_COUNT / 256)
|
|
|
+#define tmrHw_HIGH_256_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_256_RESOLUTION_COUNT)
|
|
|
+
|
|
|
+static void ResetTimer(tmrHw_ID_t timerId)
|
|
|
+ __attribute__ ((section(".aramtext")));
|
|
|
+static int tmrHw_divide(int num, int denom)
|
|
|
+ __attribute__ ((section(".aramtext")));
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Get timer capability
|
|
|
+*
|
|
|
+* This function returns various capabilities/attributes of a timer
|
|
|
+*
|
|
|
+* @return Capability
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+uint32_t tmrHw_getTimerCapability(tmrHw_ID_t timerId, /* [ IN ] Timer Id */
|
|
|
+ tmrHw_CAPABILITY_e capability /* [ IN ] Timer capability */
|
|
|
+) {
|
|
|
+ switch (capability) {
|
|
|
+ case tmrHw_CAPABILITY_CLOCK:
|
|
|
+ return (timerId <=
|
|
|
+ 1) ? tmrHw_LOW_RESOLUTION_CLOCK :
|
|
|
+ tmrHw_HIGH_RESOLUTION_CLOCK;
|
|
|
+ case tmrHw_CAPABILITY_RESOLUTION:
|
|
|
+ return 32;
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Resets a timer
|
|
|
+*
|
|
|
+* This function initializes timer
|
|
|
+*
|
|
|
+* @return void
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+static void ResetTimer(tmrHw_ID_t timerId /* [ IN ] Timer Id */
|
|
|
+) {
|
|
|
+ /* Reset timer */
|
|
|
+ pTmrHw[timerId].LoadValue = 0;
|
|
|
+ pTmrHw[timerId].CurrentValue = 0xFFFFFFFF;
|
|
|
+ pTmrHw[timerId].Control = 0;
|
|
|
+ pTmrHw[timerId].BackgroundLoad = 0;
|
|
|
+ /* Always configure as a 32 bit timer */
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_32BIT;
|
|
|
+ /* Clear interrupt only if raw status interrupt is set */
|
|
|
+ if (pTmrHw[timerId].RawInterruptStatus) {
|
|
|
+ pTmrHw[timerId].InterruptClear = 0xFFFFFFFF;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Sets counter value for an interval in ms
|
|
|
+*
|
|
|
+* @return On success: Effective counter value set
|
|
|
+* On failure: 0
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+static tmrHw_INTERVAL_t SetTimerPeriod(tmrHw_ID_t timerId, /* [ IN ] Timer Id */
|
|
|
+ tmrHw_INTERVAL_t msec /* [ IN ] Interval in milli-second */
|
|
|
+) {
|
|
|
+ uint32_t scale = 0;
|
|
|
+ uint32_t count = 0;
|
|
|
+
|
|
|
+ if (timerId == 0 || timerId == 1) {
|
|
|
+ if (msec <= tmrHw_LOW_1_MAX_MILLISEC) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1;
|
|
|
+ scale = tmrHw_LOW_1_RESOLUTION_COUNT;
|
|
|
+ } else if (msec <= tmrHw_LOW_16_MAX_MILLISEC) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16;
|
|
|
+ scale = tmrHw_LOW_16_RESOLUTION_COUNT;
|
|
|
+ } else if (msec <= tmrHw_LOW_256_MAX_MILLISEC) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256;
|
|
|
+ scale = tmrHw_LOW_256_RESOLUTION_COUNT;
|
|
|
+ } else {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ count = msec * scale;
|
|
|
+ /* Set counter value */
|
|
|
+ pTmrHw[timerId].LoadValue = count;
|
|
|
+ pTmrHw[timerId].BackgroundLoad = count;
|
|
|
+
|
|
|
+ } else if (timerId == 2 || timerId == 3) {
|
|
|
+ if (msec <= tmrHw_HIGH_1_MAX_MILLISEC) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1;
|
|
|
+ scale = tmrHw_HIGH_1_RESOLUTION_COUNT;
|
|
|
+ } else if (msec <= tmrHw_HIGH_16_MAX_MILLISEC) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16;
|
|
|
+ scale = tmrHw_HIGH_16_RESOLUTION_COUNT;
|
|
|
+ } else if (msec <= tmrHw_HIGH_256_MAX_MILLISEC) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256;
|
|
|
+ scale = tmrHw_HIGH_256_RESOLUTION_COUNT;
|
|
|
+ } else {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ count = msec * scale;
|
|
|
+ /* Set counter value */
|
|
|
+ pTmrHw[timerId].LoadValue = count;
|
|
|
+ pTmrHw[timerId].BackgroundLoad = count;
|
|
|
+ }
|
|
|
+ return count / scale;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Configures a periodic timer in terms of timer interrupt rate
|
|
|
+*
|
|
|
+* This function initializes a periodic timer to generate specific number of
|
|
|
+* timer interrupt per second
|
|
|
+*
|
|
|
+* @return On success: Effective timer frequency
|
|
|
+* On failure: 0
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+tmrHw_RATE_t tmrHw_setPeriodicTimerRate(tmrHw_ID_t timerId, /* [ IN ] Timer Id */
|
|
|
+ tmrHw_RATE_t rate /* [ IN ] Number of timer interrupt per second */
|
|
|
+) {
|
|
|
+ uint32_t resolution = 0;
|
|
|
+ uint32_t count = 0;
|
|
|
+ ResetTimer(timerId);
|
|
|
+
|
|
|
+ /* Set timer mode periodic */
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC;
|
|
|
+ pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT;
|
|
|
+ /* Set timer in highest resolution */
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1;
|
|
|
+
|
|
|
+ if (rate && (timerId == 0 || timerId == 1)) {
|
|
|
+ if (rate > tmrHw_LOW_RESOLUTION_CLOCK) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ resolution = tmrHw_LOW_RESOLUTION_CLOCK;
|
|
|
+ } else if (rate && (timerId == 2 || timerId == 3)) {
|
|
|
+ if (rate > tmrHw_HIGH_RESOLUTION_CLOCK) {
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ resolution = tmrHw_HIGH_RESOLUTION_CLOCK;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ /* Find the counter value */
|
|
|
+ count = resolution / rate;
|
|
|
+ /* Set counter value */
|
|
|
+ pTmrHw[timerId].LoadValue = count;
|
|
|
+ pTmrHw[timerId].BackgroundLoad = count;
|
|
|
+
|
|
|
+ return resolution / count;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Configures a periodic timer to generate timer interrupt after
|
|
|
+* certain time interval
|
|
|
+*
|
|
|
+* This function initializes a periodic timer to generate timer interrupt
|
|
|
+* after every time interval in millisecond
|
|
|
+*
|
|
|
+* @return On success: Effective interval set in milli-second
|
|
|
+* On failure: 0
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+tmrHw_INTERVAL_t tmrHw_setPeriodicTimerInterval(tmrHw_ID_t timerId, /* [ IN ] Timer Id */
|
|
|
+ tmrHw_INTERVAL_t msec /* [ IN ] Interval in milli-second */
|
|
|
+) {
|
|
|
+ ResetTimer(timerId);
|
|
|
+
|
|
|
+ /* Set timer mode periodic */
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC;
|
|
|
+ pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT;
|
|
|
+
|
|
|
+ return SetTimerPeriod(timerId, msec);
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Configures a periodic timer to generate timer interrupt just once
|
|
|
+* after certain time interval
|
|
|
+*
|
|
|
+* This function initializes a periodic timer to generate a single ticks after
|
|
|
+* certain time interval in millisecond
|
|
|
+*
|
|
|
+* @return On success: Effective interval set in milli-second
|
|
|
+* On failure: 0
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+tmrHw_INTERVAL_t tmrHw_setOneshotTimerInterval(tmrHw_ID_t timerId, /* [ IN ] Timer Id */
|
|
|
+ tmrHw_INTERVAL_t msec /* [ IN ] Interval in milli-second */
|
|
|
+) {
|
|
|
+ ResetTimer(timerId);
|
|
|
+
|
|
|
+ /* Set timer mode oneshot */
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC;
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_ONESHOT;
|
|
|
+
|
|
|
+ return SetTimerPeriod(timerId, msec);
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Configures a timer to run as a free running timer
|
|
|
+*
|
|
|
+* This function initializes a timer to run as a free running timer
|
|
|
+*
|
|
|
+* @return Timer resolution (count / sec)
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+tmrHw_RATE_t tmrHw_setFreeRunningTimer(tmrHw_ID_t timerId, /* [ IN ] Timer Id */
|
|
|
+ uint32_t divider /* [ IN ] Dividing the clock frequency */
|
|
|
+) {
|
|
|
+ uint32_t scale = 0;
|
|
|
+
|
|
|
+ ResetTimer(timerId);
|
|
|
+ /* Set timer as free running mode */
|
|
|
+ pTmrHw[timerId].Control &= ~tmrHw_CONTROL_PERIODIC;
|
|
|
+ pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT;
|
|
|
+
|
|
|
+ if (divider >= 64) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256;
|
|
|
+ scale = 256;
|
|
|
+ } else if (divider >= 8) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16;
|
|
|
+ scale = 16;
|
|
|
+ } else {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1;
|
|
|
+ scale = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (timerId == 0 || timerId == 1) {
|
|
|
+ return tmrHw_divide(tmrHw_LOW_RESOLUTION_CLOCK, scale);
|
|
|
+ } else if (timerId == 2 || timerId == 3) {
|
|
|
+ return tmrHw_divide(tmrHw_HIGH_RESOLUTION_CLOCK, scale);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Starts a timer
|
|
|
+*
|
|
|
+* This function starts a preconfigured timer
|
|
|
+*
|
|
|
+* @return -1 - On Failure
|
|
|
+* 0 - On Success
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+int tmrHw_startTimer(tmrHw_ID_t timerId /* [ IN ] Timer id */
|
|
|
+) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_TIMER_ENABLE;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Stops a timer
|
|
|
+*
|
|
|
+* This function stops a running timer
|
|
|
+*
|
|
|
+* @return -1 - On Failure
|
|
|
+* 0 - On Success
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+int tmrHw_stopTimer(tmrHw_ID_t timerId /* [ IN ] Timer id */
|
|
|
+) {
|
|
|
+ pTmrHw[timerId].Control &= ~tmrHw_CONTROL_TIMER_ENABLE;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Gets current timer count
|
|
|
+*
|
|
|
+* This function returns the current timer value
|
|
|
+*
|
|
|
+* @return Current downcounting timer value
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+uint32_t tmrHw_GetCurrentCount(tmrHw_ID_t timerId /* [ IN ] Timer id */
|
|
|
+) {
|
|
|
+ /* return 32 bit timer value */
|
|
|
+ switch (pTmrHw[timerId].Control & tmrHw_CONTROL_MODE_MASK) {
|
|
|
+ case tmrHw_CONTROL_FREE_RUNNING:
|
|
|
+ if (pTmrHw[timerId].CurrentValue) {
|
|
|
+ return tmrHw_MAX_COUNT - pTmrHw[timerId].CurrentValue;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case tmrHw_CONTROL_PERIODIC:
|
|
|
+ case tmrHw_CONTROL_ONESHOT:
|
|
|
+ return pTmrHw[timerId].BackgroundLoad -
|
|
|
+ pTmrHw[timerId].CurrentValue;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Gets timer count rate
|
|
|
+*
|
|
|
+* This function returns the number of counts per second
|
|
|
+*
|
|
|
+* @return Count rate
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+tmrHw_RATE_t tmrHw_getCountRate(tmrHw_ID_t timerId /* [ IN ] Timer id */
|
|
|
+) {
|
|
|
+ uint32_t divider = 0;
|
|
|
+
|
|
|
+ switch (pTmrHw[timerId].Control & tmrHw_CONTROL_PRESCALE_MASK) {
|
|
|
+ case tmrHw_CONTROL_PRESCALE_1:
|
|
|
+ divider = 1;
|
|
|
+ break;
|
|
|
+ case tmrHw_CONTROL_PRESCALE_16:
|
|
|
+ divider = 16;
|
|
|
+ break;
|
|
|
+ case tmrHw_CONTROL_PRESCALE_256:
|
|
|
+ divider = 256;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ tmrHw_ASSERT(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (timerId == 0 || timerId == 1) {
|
|
|
+ return tmrHw_divide(tmrHw_LOW_RESOLUTION_CLOCK, divider);
|
|
|
+ } else {
|
|
|
+ return tmrHw_divide(tmrHw_HIGH_RESOLUTION_CLOCK, divider);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Enables timer interrupt
|
|
|
+*
|
|
|
+* This function enables the timer interrupt
|
|
|
+*
|
|
|
+* @return N/A
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+void tmrHw_enableInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */
|
|
|
+) {
|
|
|
+ pTmrHw[timerId].Control |= tmrHw_CONTROL_INTERRUPT_ENABLE;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Disables timer interrupt
|
|
|
+*
|
|
|
+* This function disable the timer interrupt
|
|
|
+*
|
|
|
+* @return N/A
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+void tmrHw_disableInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */
|
|
|
+) {
|
|
|
+ pTmrHw[timerId].Control &= ~tmrHw_CONTROL_INTERRUPT_ENABLE;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Clears the interrupt
|
|
|
+*
|
|
|
+* This function clears the timer interrupt
|
|
|
+*
|
|
|
+* @return N/A
|
|
|
+*
|
|
|
+* @note
|
|
|
+* Must be called under the context of ISR
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+void tmrHw_clearInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */
|
|
|
+) {
|
|
|
+ pTmrHw[timerId].InterruptClear = 0x1;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Gets the interrupt status
|
|
|
+*
|
|
|
+* This function returns timer interrupt status
|
|
|
+*
|
|
|
+* @return Interrupt status
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+tmrHw_INTERRUPT_STATUS_e tmrHw_getInterruptStatus(tmrHw_ID_t timerId /* [ IN ] Timer id */
|
|
|
+) {
|
|
|
+ if (pTmrHw[timerId].InterruptStatus) {
|
|
|
+ return tmrHw_INTERRUPT_STATUS_SET;
|
|
|
+ } else {
|
|
|
+ return tmrHw_INTERRUPT_STATUS_UNSET;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Indentifies a timer causing interrupt
|
|
|
+*
|
|
|
+* This functions returns a timer causing interrupt
|
|
|
+*
|
|
|
+* @return 0xFFFFFFFF : No timer causing an interrupt
|
|
|
+* ! 0xFFFFFFFF : timer causing an interrupt
|
|
|
+* @note
|
|
|
+* tmrHw_clearIntrrupt() must be called with a valid timer id after calling this function
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+tmrHw_ID_t tmrHw_getInterruptSource(void /* void */
|
|
|
+) {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < tmrHw_TIMER_NUM_COUNT; i++) {
|
|
|
+ if (pTmrHw[i].InterruptStatus) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0xFFFFFFFF;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Displays specific timer registers
|
|
|
+*
|
|
|
+*
|
|
|
+* @return void
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+void tmrHw_printDebugInfo(tmrHw_ID_t timerId, /* [ IN ] Timer id */
|
|
|
+ int (*fpPrint) (const char *, ...) /* [ IN ] Print callback function */
|
|
|
+) {
|
|
|
+ (*fpPrint) ("Displaying register contents \n\n");
|
|
|
+ (*fpPrint) ("Timer %d: Load value 0x%X\n", timerId,
|
|
|
+ pTmrHw[timerId].LoadValue);
|
|
|
+ (*fpPrint) ("Timer %d: Background load value 0x%X\n", timerId,
|
|
|
+ pTmrHw[timerId].BackgroundLoad);
|
|
|
+ (*fpPrint) ("Timer %d: Control 0x%X\n", timerId,
|
|
|
+ pTmrHw[timerId].Control);
|
|
|
+ (*fpPrint) ("Timer %d: Interrupt clear 0x%X\n", timerId,
|
|
|
+ pTmrHw[timerId].InterruptClear);
|
|
|
+ (*fpPrint) ("Timer %d: Interrupt raw interrupt 0x%X\n", timerId,
|
|
|
+ pTmrHw[timerId].RawInterruptStatus);
|
|
|
+ (*fpPrint) ("Timer %d: Interrupt status 0x%X\n", timerId,
|
|
|
+ pTmrHw[timerId].InterruptStatus);
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Use a timer to perform a busy wait delay for a number of usecs.
|
|
|
+*
|
|
|
+* @return N/A
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+void tmrHw_udelay(tmrHw_ID_t timerId, /* [ IN ] Timer id */
|
|
|
+ unsigned long usecs /* [ IN ] usec to delay */
|
|
|
+) {
|
|
|
+ tmrHw_RATE_t usec_tick_rate;
|
|
|
+ tmrHw_COUNT_t start_time;
|
|
|
+ tmrHw_COUNT_t delta_time;
|
|
|
+
|
|
|
+ start_time = tmrHw_GetCurrentCount(timerId);
|
|
|
+ usec_tick_rate = tmrHw_divide(tmrHw_getCountRate(timerId), 1000000);
|
|
|
+ delta_time = usecs * usec_tick_rate;
|
|
|
+
|
|
|
+ /* Busy wait */
|
|
|
+ while (delta_time > (tmrHw_GetCurrentCount(timerId) - start_time))
|
|
|
+ ;
|
|
|
+}
|
|
|
+
|
|
|
+/****************************************************************************/
|
|
|
+/**
|
|
|
+* @brief Local Divide function
|
|
|
+*
|
|
|
+* This function does the divide
|
|
|
+*
|
|
|
+* @return divide value
|
|
|
+*
|
|
|
+*/
|
|
|
+/****************************************************************************/
|
|
|
+static int tmrHw_divide(int num, int denom)
|
|
|
+{
|
|
|
+ int r;
|
|
|
+ int t = 1;
|
|
|
+
|
|
|
+ /* Shift denom and t up to the largest value to optimize algorithm */
|
|
|
+ /* t contains the units of each divide */
|
|
|
+ while ((denom & 0x40000000) == 0) { /* fails if denom=0 */
|
|
|
+ denom = denom << 1;
|
|
|
+ t = t << 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Intialize the result */
|
|
|
+ r = 0;
|
|
|
+
|
|
|
+ do {
|
|
|
+ /* Determine if there exists a positive remainder */
|
|
|
+ if ((num - denom) >= 0) {
|
|
|
+ /* Accumlate t to the result and calculate a new remainder */
|
|
|
+ num = num - denom;
|
|
|
+ r = r + t;
|
|
|
+ }
|
|
|
+ /* Continue to shift denom and shift t down to 0 */
|
|
|
+ denom = denom >> 1;
|
|
|
+ t = t >> 1;
|
|
|
+ } while (t != 0);
|
|
|
+ return r;
|
|
|
+}
|