123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- /*****************************************************************************
- * 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;
- }
|