]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained/libchip_samv7/source/tc.c
Update version number ready for V8.2.1 release.
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained / libchip_samv7 / source / tc.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2011, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /**\r
31  * \file\r
32  *\r
33  * Implementation of Timer Counter (TC).\r
34  *\r
35  */\r
36 \r
37 /*------------------------------------------------------------------------------\r
38  *         Headers\r
39  *------------------------------------------------------------------------------*/\r
40 \r
41 #include "chip.h"\r
42 \r
43 #include <assert.h>\r
44 \r
45 /*------------------------------------------------------------------------------\r
46  *         Global functions\r
47  *------------------------------------------------------------------------------*/\r
48 \r
49 /**\r
50  * \brief Configures a Timer Counter Channel\r
51  *\r
52  * Configures a Timer Counter to operate in the given mode. Timer is stopped\r
53  * after configuration and must be restarted with TC_Start(). All the\r
54  * interrupts of the timer are also disabled.\r
55  *\r
56  * \param pTc  Pointer to a Tc instance.\r
57  * \param channel Channel number.\r
58  * \param mode  Operating mode (TC_CMR value).\r
59  */\r
60 extern void TC_Configure( Tc *pTc, uint32_t dwChannel, uint32_t dwMode )\r
61 {\r
62     TcChannel* pTcCh ;\r
63 \r
64     assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;\r
65     pTcCh = pTc->TC_CHANNEL+dwChannel ;\r
66 \r
67     /*  Disable TC clock */\r
68     pTcCh->TC_CCR = TC_CCR_CLKDIS ;\r
69 \r
70     /*  Disable interrupts */\r
71     pTcCh->TC_IDR = 0xFFFFFFFF ;\r
72 \r
73     /*  Clear status register */\r
74     pTcCh->TC_SR ;\r
75 \r
76     /*  Set mode */\r
77     pTcCh->TC_CMR = dwMode ;\r
78 }\r
79 \r
80 /**\r
81  * \brief Reset and Start the TC Channel\r
82  *\r
83  * Enables the timer clock and performs a software reset to start the counting.\r
84  *\r
85  * \param pTc  Pointer to a Tc instance.\r
86  * \param dwChannel Channel number.\r
87  */\r
88 extern void TC_Start( Tc *pTc, uint32_t dwChannel )\r
89 {\r
90     TcChannel* pTcCh ;\r
91 \r
92     assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;\r
93 \r
94     pTcCh = pTc->TC_CHANNEL+dwChannel ;\r
95     pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;\r
96 }\r
97 \r
98 /**\r
99  * \brief Stop TC Channel\r
100  *\r
101  * Disables the timer clock, stopping the counting.\r
102  *\r
103  * \param pTc     Pointer to a Tc instance.\r
104  * \param dwChannel Channel number.\r
105  */\r
106 extern void TC_Stop(Tc *pTc, uint32_t dwChannel )\r
107 {\r
108     TcChannel* pTcCh ;\r
109 \r
110     assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;\r
111 \r
112     pTcCh = pTc->TC_CHANNEL+dwChannel ;\r
113     pTcCh->TC_CCR = TC_CCR_CLKDIS ;\r
114 }\r
115 \r
116 /**\r
117  * \brief Find best MCK divisor\r
118  *\r
119  * Finds the best MCK divisor given the timer frequency and MCK. The result\r
120  * is guaranteed to satisfy the following equation:\r
121  * \code\r
122  *   (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)\r
123  * \endcode\r
124  * with DIV being the highest possible value.\r
125  *\r
126  * \param dwFreq  Desired timer frequency.\r
127  * \param dwMCk  Master clock frequency.\r
128  * \param dwDiv  Divisor value.\r
129  * \param dwTcClks  TCCLKS field value for divisor.\r
130  * \param dwBoardMCK  Board clock frequency.\r
131  *\r
132  * \return 1 if a proper divisor has been found, otherwise 0.\r
133  */\r
134 extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK )\r
135 {\r
136     const uint32_t adwDivisors[5] = { 2, 8, 32, 128, dwBoardMCK / 32768 } ;\r
137 \r
138     uint32_t dwIndex = 0 ;\r
139 \r
140     /*  Satisfy lower bound */\r
141     while ( dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536) )\r
142     {\r
143         dwIndex++ ;\r
144 \r
145         /*  If no divisor can be found, return 0 */\r
146         if ( dwIndex == (sizeof( adwDivisors )/sizeof( adwDivisors[0] ))  )\r
147         {\r
148             return 0 ;\r
149         }\r
150     }\r
151 \r
152     /*  Try to maximize DIV while satisfying upper bound */\r
153     while ( dwIndex < 4 )\r
154     {\r
155 \r
156         if ( dwFreq > (dwMCk / adwDivisors[dwIndex + 1]) )\r
157         {\r
158             break ;\r
159         }\r
160         dwIndex++ ;\r
161     }\r
162 \r
163     /*  Store results */\r
164     if ( dwDiv )\r
165     {\r
166         *dwDiv = adwDivisors[dwIndex] ;\r
167     }\r
168     if ( dwTcClks )\r
169     {\r
170         *dwTcClks = dwIndex ;\r
171     }\r
172 \r
173     return 1 ;\r
174 }\r
175 \r