SAMV71 Xplained Ultra Software Package 1.3

tc.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2011, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
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( pTc->TC_CHANNEL[0] )) ) ;
00097     pTcCh = pTc->TC_CHANNEL+dwChannel ;
00098 
00099     /*  Disable TC clock */
00100     pTcCh->TC_CCR = TC_CCR_CLKDIS ;
00101 
00102     /*  Disable interrupts */
00103     pTcCh->TC_IDR = 0xFFFFFFFF ;
00104 
00105     /*  Clear status register */
00106     pTcCh->TC_SR ;
00107 
00108     /*  Set mode */
00109     pTcCh->TC_CMR = dwMode ;
00110 }
00111 
00112 /**
00113  * \brief Reset and Start the TC Channel
00114  *
00115  * Enables the timer clock and performs a software reset to start the counting.
00116  *
00117  * \param pTc  Pointer to a Tc instance.
00118  * \param dwChannel Channel number.
00119  */
00120 extern void TC_Start( Tc *pTc, uint32_t dwChannel )
00121 {
00122     TcChannel* pTcCh ;
00123 
00124     assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
00125 
00126     pTcCh = pTc->TC_CHANNEL+dwChannel ;
00127     pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;
00128 }
00129 
00130 /**
00131  * \brief Stop TC Channel
00132  *
00133  * Disables the timer clock, stopping the counting.
00134  *
00135  * \param pTc     Pointer to a Tc instance.
00136  * \param dwChannel Channel number.
00137  */
00138 extern void TC_Stop(Tc *pTc, uint32_t dwChannel )
00139 {
00140     TcChannel* pTcCh ;
00141 
00142     assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
00143 
00144     pTcCh = pTc->TC_CHANNEL+dwChannel ;
00145     pTcCh->TC_CCR = TC_CCR_CLKDIS ;
00146 }
00147 
00148 /**
00149  * \brief Find best MCK divisor
00150  *
00151  * Finds the best MCK divisor given the timer frequency and MCK. The result
00152  * is guaranteed to satisfy the following equation:
00153  * \code
00154  *   (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
00155  * \endcode
00156  * with DIV being the highest possible value.
00157  *
00158  * \param dwFreq  Desired timer frequency.
00159  * \param dwMCk  Master clock frequency.
00160  * \param dwDiv  Divisor value.
00161  * \param dwTcClks  TCCLKS field value for divisor.
00162  * \param dwBoardMCK  Board clock frequency.
00163  *
00164  * \return 1 if a proper divisor has been found, otherwise 0.
00165  */
00166 extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, 
00167         uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK )
00168 {
00169     const uint32_t adwDivisors[5] = { 2, 8, 32, 128, BOARD_MCK / 32768 } ;
00170 
00171     uint32_t dwIndex = 0 ;
00172     dwBoardMCK = dwBoardMCK;
00173     /*  Satisfy lower bound */
00174     while ( dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536) ) {
00175         dwIndex++ ;
00176 
00177         /*  If no divisor can be found, return 0 */
00178         if ( dwIndex == (sizeof( adwDivisors )/sizeof( adwDivisors[0] )) ) {
00179             return 0 ;
00180         }
00181     }
00182 
00183     /*  Try to maximize DIV while satisfying upper bound */
00184     while ( dwIndex < 4 ) {
00185         if ( dwFreq > (dwMCk / adwDivisors[dwIndex + 1]) ) {
00186             break ;
00187         }
00188         dwIndex++ ;
00189     }
00190 
00191     /*  Store results */
00192     if ( dwDiv ) {
00193         *dwDiv = adwDivisors[dwIndex] ;
00194     }
00195     if ( dwTcClks ) {
00196         *dwTcClks = dwIndex ;
00197     }
00198     return 1 ;
00199 }
00200 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines