SAMV71 Xplained Ultra Software Package 1.5

tc.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /** \addtogroup tc_module
00031  * The TC driver provides the Interface to configure the Timer Counter (TC).
00032  *
00033  *  \section Usage
00034  * <ul>
00035  *  <li> Optionally, use TC_FindMckDivisor() to let the program find the best
00036  *     TCCLKS field value automatically.</li>
00037  *  <li> Configure a Timer Counter in the desired mode using TC_Configure().</li>
00038  *  <li> Start or stop the timer clock using TC_Start() and TC_Stop().</li>
00039  *
00040  * </ul>
00041  * For more accurate information, please look at the TC section of the Datasheet.
00042  *
00043  * Related files :\n
00044  * \ref tc.c\n
00045  * \ref tc.h.\n
00046 */
00047 
00048 /**
00049 *  \file
00050 *
00051 *  \section Purpose
00052 *
00053 *  Interface for configuring and using Timer Counter (TC) peripherals.
00054 *
00055 *  \section Usage
00056 *  -# Optionally, use TC_FindMckDivisor() to let the program find the best
00057 *     TCCLKS field value automatically.
00058 *  -# Configure a Timer Counter in the desired mode using TC_Configure().
00059 *  -# Start or stop the timer clock using TC_Start() and TC_Stop().
00060 */
00061 
00062 /**
00063  * \file
00064  *
00065  * Implementation of Timer Counter (TC).
00066  *
00067  */
00068 
00069 /*------------------------------------------------------------------------------
00070  *         Headers
00071  *-----------------------------------------------------------------------------*/
00072 
00073 #include "board.h"
00074 
00075 #include <assert.h>
00076 
00077 /*------------------------------------------------------------------------------
00078  *         Global functions
00079  *----------------------------------------------------------------------------*/
00080 
00081 /**
00082  * \brief Configures a Timer Counter Channel
00083  *
00084  * Configures a Timer Counter to operate in the given mode. Timer is stopped
00085  * after configuration and must be restarted with TC_Start(). All the
00086  * interrupts of the timer are also disabled.
00087  *
00088  * \param pTc  Pointer to a Tc instance.
00089  * \param channel Channel number.
00090  * \param mode  Operating mode (TC_CMR value).
00091  */
00092 extern void TC_Configure(Tc *pTc, uint32_t dwChannel, uint32_t dwMode)
00093 {
00094     TcChannel *pTcCh;
00095 
00096     assert(dwChannel < (sizeof(pTc->TC_CHANNEL) / sizeof(
00097                              pTc->TC_CHANNEL[0])));
00098     pTcCh = pTc->TC_CHANNEL + dwChannel;
00099 
00100     /*  Disable TC clock */
00101     pTcCh->TC_CCR = TC_CCR_CLKDIS;
00102 
00103     /*  Disable interrupts */
00104     pTcCh->TC_IDR = 0xFFFFFFFF;
00105 
00106     /*  Clear status register */
00107     pTcCh->TC_SR;
00108 
00109     /*  Set mode */
00110     pTcCh->TC_CMR = dwMode;
00111 }
00112 
00113 /**
00114  * \brief Reset and Start the TC Channel
00115  *
00116  * Enables the timer clock and performs a software reset to start the counting.
00117  *
00118  * \param pTc  Pointer to a Tc instance.
00119  * \param dwChannel Channel number.
00120  */
00121 extern void TC_Start(Tc *pTc, uint32_t dwChannel)
00122 {
00123     TcChannel *pTcCh;
00124 
00125     assert(dwChannel < (sizeof(pTc->TC_CHANNEL) / sizeof(
00126                              pTc->TC_CHANNEL[0])));
00127 
00128     pTcCh = pTc->TC_CHANNEL + dwChannel;
00129     pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
00130 }
00131 
00132 /**
00133  * \brief Stop TC Channel
00134  *
00135  * Disables the timer clock, stopping the counting.
00136  *
00137  * \param pTc     Pointer to a Tc instance.
00138  * \param dwChannel Channel number.
00139  */
00140 extern void TC_Stop(Tc *pTc, uint32_t dwChannel)
00141 {
00142     TcChannel *pTcCh;
00143 
00144     assert(dwChannel < (sizeof(pTc->TC_CHANNEL) / sizeof(
00145                              pTc->TC_CHANNEL[0])));
00146 
00147     pTcCh = pTc->TC_CHANNEL + dwChannel;
00148     pTcCh->TC_CCR = TC_CCR_CLKDIS;
00149 }
00150 
00151 /**
00152  * \brief Find best MCK divisor
00153  *
00154  * Finds the best MCK divisor given the timer frequency and MCK. The result
00155  * is guaranteed to satisfy the following equation:
00156  * \code
00157  *   (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
00158  * \endcode
00159  * with DIV being the highest possible value.
00160  *
00161  * \param dwFreq  Desired timer frequency.
00162  * \param dwMCk  Master clock frequency.
00163  * \param dwDiv  Divisor value.
00164  * \param dwTcClks  TCCLKS field value for divisor.
00165  * \param dwBoardMCK  Board clock frequency.
00166  *
00167  * \return 1 if a proper divisor has been found, otherwise 0.
00168  */
00169 extern uint32_t TC_FindMckDivisor(uint32_t dwFreq, uint32_t dwMCk,
00170                                    uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK)
00171 {
00172     /*
00173     TCCLKS:
00174         0 - PCK6: default source - Slow Clock; update according to actual case
00175         4 - SLCK: (slow clock) is either "Embedded 32kHz RC Oscillator" or
00176                   "32768Hz Crystal Oscillator"
00177     */
00178     const uint32_t adwDivisors[5] = { BOARD_MCK / 32768, 8, 32, 128, BOARD_MCK / 32768 };
00179 
00180     uint32_t dwIndex = 0;
00181     dwBoardMCK = dwBoardMCK;
00182 
00183     /*  Satisfy lower bound */
00184     while (dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536)) {
00185         dwIndex++;
00186 
00187         /*  If no divisor can be found, return 0 */
00188         if (dwIndex == (sizeof(adwDivisors) / sizeof(adwDivisors[0])))
00189             return 0;
00190     }
00191 
00192     /*  Try to maximize DIV while satisfying upper bound */
00193     while (dwIndex < 4) {
00194         if (dwFreq > (dwMCk / adwDivisors[dwIndex + 1]))
00195             break;
00196 
00197         dwIndex++;
00198     }
00199 
00200     /*  Store results */
00201     if (dwDiv)
00202         *dwDiv = adwDivisors[dwIndex];
00203 
00204     if (dwTcClks)
00205         *dwTcClks = dwIndex;
00206 
00207     return 1;
00208 }
00209 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines