/****************************************************************************** * Filename: timer.c * Revised: 2015-11-16 19:41:47 +0100 (Mon, 16 Nov 2015) * Revision: 45094 * * Description: Driver for the General Purpose Timer * * Copyright (c) 2015, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2) Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3) Neither the name of the ORGANIZATION nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ #include //***************************************************************************** // // Handle support for DriverLib in ROM: // This section will undo prototype renaming made in the header file // //***************************************************************************** #if !defined(DOXYGEN) #undef TimerConfigure #define TimerConfigure NOROM_TimerConfigure #undef TimerLevelControl #define TimerLevelControl NOROM_TimerLevelControl #undef TimerStallControl #define TimerStallControl NOROM_TimerStallControl #undef TimerWaitOnTriggerControl #define TimerWaitOnTriggerControl NOROM_TimerWaitOnTriggerControl #undef TimerIntRegister #define TimerIntRegister NOROM_TimerIntRegister #undef TimerIntUnregister #define TimerIntUnregister NOROM_TimerIntUnregister #undef TimerMatchUpdateMode #define TimerMatchUpdateMode NOROM_TimerMatchUpdateMode #undef TimerIntervalLoadMode #define TimerIntervalLoadMode NOROM_TimerIntervalLoadMode #endif //***************************************************************************** // //! \brief Gets the timer interrupt number. //! //! Given a timer base address, this function returns the corresponding //! interrupt number. //! //! \param ui32Base is the base address of the timer module. //! //! \return Returns a timer interrupt number, or -1 if \c ui32Base is invalid. // //***************************************************************************** static uint32_t TimerIntNumberGet(uint32_t ui32Base) { uint32_t ui32Int; // // Loop through the table that maps timer base addresses to interrupt // numbers. // switch(ui32Base) { case GPT0_BASE : ui32Int = INT_GPT0A; break; case GPT1_BASE : ui32Int = INT_GPT1A; break; case GPT2_BASE : ui32Int = INT_GPT2A; break; case GPT3_BASE : ui32Int = INT_GPT3A; break; default : ui32Int = 0x0; } // // Return the interrupt number or (-1) if not base address is not matched. // return (ui32Int); } //***************************************************************************** // //! Configures the timer(s) // //***************************************************************************** void TimerConfigure(uint32_t ui32Base, uint32_t ui32Config) { // // Check the arguments. // ASSERT(TimerBaseValid(ui32Base)); ASSERT((ui32Config == TIMER_CFG_ONE_SHOT) || (ui32Config == TIMER_CFG_ONE_SHOT_UP) || (ui32Config == TIMER_CFG_PERIODIC) || (ui32Config == TIMER_CFG_PERIODIC_UP) || ((ui32Config & 0xFF000000) == TIMER_CFG_SPLIT_PAIR)); ASSERT(((ui32Config & 0xFF000000) != TIMER_CFG_SPLIT_PAIR) || ((((ui32Config & 0x000000FF) == TIMER_CFG_A_ONE_SHOT) || ((ui32Config & 0x000000FF) == TIMER_CFG_A_ONE_SHOT_UP) || ((ui32Config & 0x000000FF) == TIMER_CFG_A_PERIODIC) || ((ui32Config & 0x000000FF) == TIMER_CFG_A_PERIODIC_UP) || ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_COUNT) || ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_COUNT_UP) || ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_TIME) || ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_TIME_UP) || ((ui32Config & 0x000000FF) == TIMER_CFG_A_PWM)) && (((ui32Config & 0x0000FF00) == TIMER_CFG_B_ONE_SHOT) || ((ui32Config & 0x0000FF00) == TIMER_CFG_B_ONE_SHOT_UP) || ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PERIODIC) || ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PERIODIC_UP) || ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_COUNT) || ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_COUNT_UP) || ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_TIME) || ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_TIME_UP) || ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PWM)))); // // Disable the timers. // HWREG(ui32Base + GPT_O_CTL) &= ~(GPT_CTL_TAEN | GPT_CTL_TBEN); // // Set the global timer configuration. // HWREG(ui32Base + GPT_O_CFG) = ui32Config >> 24; // // Set the configuration of the A and B timers. Note that the B timer // configuration is ignored by the hardware in 32-bit modes. // HWREG(ui32Base + GPT_O_TAMR) = (ui32Config & 0xFF) | GPT_TAMR_TAPWMIE; HWREG(ui32Base + GPT_O_TBMR) = ((ui32Config >> 8) & 0xFF) | GPT_TBMR_TBPWMIE; } //***************************************************************************** // //! Controls the output level // //***************************************************************************** void TimerLevelControl(uint32_t ui32Base, uint32_t ui32Timer, bool bInvert) { // // Check the arguments. // ASSERT(TimerBaseValid(ui32Base)); ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH)); // // Set the output levels as requested. // ui32Timer &= GPT_CTL_TAPWML | GPT_CTL_TBPWML; HWREG(ui32Base + GPT_O_CTL) = (bInvert ? (HWREG(ui32Base + GPT_O_CTL) | ui32Timer) : (HWREG(ui32Base + GPT_O_CTL) & ~(ui32Timer))); } //***************************************************************************** // //! Controls the stall handling // //***************************************************************************** void TimerStallControl(uint32_t ui32Base, uint32_t ui32Timer, bool bStall) { // // Check the arguments. // ASSERT(TimerBaseValid(ui32Base)); ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH)); // // Set the stall mode. // ui32Timer &= GPT_CTL_TASTALL | GPT_CTL_TBSTALL; HWREG(ui32Base + GPT_O_CTL) = (bStall ? (HWREG(ui32Base + GPT_O_CTL) | ui32Timer) : (HWREG(ui32Base + GPT_O_CTL) & ~(ui32Timer))); } //***************************************************************************** // //! Controls the wait on trigger handling // //***************************************************************************** void TimerWaitOnTriggerControl(uint32_t ui32Base, uint32_t ui32Timer, bool bWait) { // // Check the arguments. // ASSERT(TimerBaseValid(ui32Base)); ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH)); // // Set the wait on trigger mode for timer A. // if(ui32Timer & TIMER_A) { if(bWait) { HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAWOT; } else { HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAWOT); } } // // Set the wait on trigger mode for timer B. // if(ui32Timer & TIMER_B) { if(bWait) { HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBWOT; } else { HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBWOT); } } } //***************************************************************************** // //! Registers an interrupt handler for the timer interrupt // //***************************************************************************** void TimerIntRegister(uint32_t ui32Base, uint32_t ui32Timer, void (*pfnHandler)(void)) { uint32_t ui32Int; // // Check the arguments. // ASSERT(TimerBaseValid(ui32Base)); ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH)); // // Get the interrupt number for this timer module. // ui32Int = TimerIntNumberGet(ui32Base); // // Register an interrupt handler for timer A if requested. // if(ui32Timer & TIMER_A) { // // Register the interrupt handler. // IntRegister(ui32Int, pfnHandler); // // Enable the interrupt. // IntEnable(ui32Int); } // // Register an interrupt handler for timer B if requested. // if(ui32Timer & TIMER_B) { // // Register the interrupt handler. // IntRegister(ui32Int + 1, pfnHandler); // // Enable the interrupt. // IntEnable(ui32Int + 1); } } //***************************************************************************** // //! Unregisters an interrupt handler for the timer interrupt // //***************************************************************************** void TimerIntUnregister(uint32_t ui32Base, uint32_t ui32Timer) { uint32_t ui32Int; // // Check the arguments. // ASSERT(TimerBaseValid(ui32Base)); ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH)); // // Get the interrupt number for this timer module. // ui32Int = TimerIntNumberGet(ui32Base); // // Unregister the interrupt handler for timer A if requested. // if(ui32Timer & TIMER_A) { // // Disable the interrupt. // IntDisable(ui32Int); // // Unregister the interrupt handler. // IntUnregister(ui32Int); } // // Unregister the interrupt handler for timer B if requested. // if(ui32Timer & TIMER_B) { // // Disable the interrupt. // IntDisable(ui32Int + 1); // // Unregister the interrupt handler. // IntUnregister(ui32Int + 1); } } //***************************************************************************** // // Sets the Match Register Update mode // //***************************************************************************** void TimerMatchUpdateMode(uint32_t ui32Base, uint32_t ui32Timer, uint32_t ui32Mode) { // Check the arguments ASSERT(TimerBaseValid(ui32Base)); ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH)); ASSERT((ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE) || (ui32Mode == TIMER_MATCHUPDATE_TIMEOUT)); // Set mode for timer A if(ui32Timer & TIMER_A) { if(ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE) { HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAMRSU); } else { HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAMRSU; } } // Set mode for timer B if(ui32Timer & TIMER_B) { if(ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE) { HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBMRSU); } else { HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBMRSU; } } } //***************************************************************************** // // Sets the Interval Load mode // //***************************************************************************** void TimerIntervalLoadMode(uint32_t ui32Base, uint32_t ui32Timer, uint32_t ui32Mode) { // Check the arguments ASSERT(TimerBaseValid(ui32Base)); ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH)); ASSERT((ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE) || (ui32Mode == TIMER_INTERVALLOAD_TIMEOUT)); // Set mode for timer A if(ui32Timer & TIMER_A) { if(ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE) { HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAILD); } else { HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAILD; } } // Set mode for timer B if(ui32Timer & TIMER_B) { if(ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE) { HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBILD); } else { HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBILD; } } }