]> git.sur5r.net Git - freertos/blob
4534553f63afe8084033ca1625563c4e7676223e
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2015 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xttcps.c
36 * @addtogroup ttcps_v3_0
37 * @{
38 *
39 * This file contains the implementation of the XTtcPs driver. This driver
40 * controls the operation of one timer counter in the Triple Timer Counter (TTC)
41 * module in the Ps block. Refer to xttcps.h for more detailed description
42 * of the driver.
43 *
44 * <pre>
45 * MODIFICATION HISTORY:
46 *
47 * Ver   Who    Date     Changes
48 * ----- ------ -------- -------------------------------------------------
49 * 1.00a drg/jz 01/21/10 First release
50 * 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
51 * 3.01  pkp        01/30/16 Modified XTtcPs_CfgInitialize to add XTtcps_Stop
52 *                                               to stop the timer before configuring
53 *
54 * </pre>
55 *
56 ******************************************************************************/
57
58 /***************************** Include Files *********************************/
59
60 #include "xttcps.h"
61
62 /************************** Constant Definitions *****************************/
63
64 /**************************** Type Definitions *******************************/
65
66 /***************** Macros (Inline Functions) Definitions *********************/
67
68 /************************** Function Prototypes ******************************/
69
70 /************************** Variable Definitions *****************************/
71
72
73 /*****************************************************************************/
74 /**
75 *
76 * Initializes a specific XTtcPs instance such that the driver is ready to use.
77 * This function initializes a single timer counter in the triple timer counter
78 * function block.
79 *
80 * The state of the device after initialization is:
81 *  - Overflow Mode
82 *  - Internal (pclk) selected
83 *  - Counter disabled
84 *  - All Interrupts disabled
85 *  - Output waveforms disabled
86 *
87 * @param        InstancePtr is a pointer to the XTtcPs instance.
88 * @param        ConfigPtr is a reference to a structure containing information
89 *               about a specific TTC device.
90 * @param        EffectiveAddr is the device base address in the virtual memory
91 *               address space. The caller is responsible for keeping the address
92 *               mapping from EffectiveAddr to the device physical base address
93 *               unchanged once this function is invoked. Unexpected errors may
94 *               occur if the address mapping changes after this function is
95 *               called. If address translation is not used, then use
96 *               ConfigPtr->BaseAddress for this parameter, passing the physical
97 *               address instead.
98 *
99 * @return
100 *
101 *               - XST_SUCCESS if the initialization is successful.
102 *               - XST_DEVICE_IS_STARTED if the device is started. It must be
103 *                 stopped to re-initialize.
104 *
105 * @note         Device has to be stopped first to call this function to
106 *               initialize it.
107 *
108 ******************************************************************************/
109 s32 XTtcPs_CfgInitialize(XTtcPs *InstancePtr, XTtcPs_Config *ConfigPtr,
110                               u32 EffectiveAddr)
111 {
112         s32 Status;
113         u32 IsStartResult;
114         /*
115          * Assert to validate input arguments.
116          */
117         Xil_AssertNonvoid(InstancePtr != NULL);
118         Xil_AssertNonvoid(ConfigPtr != NULL);
119
120         /*
121          * Set some default values
122          */
123         InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
124         InstancePtr->Config.BaseAddress = EffectiveAddr;
125         InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
126
127         IsStartResult = XTtcPs_IsStarted(InstancePtr);
128         /*
129          * If the timer counter has already started, return an error
130          * Device should be stopped first.
131          */
132         if(IsStartResult == (u32)TRUE) {
133                 Status = XST_DEVICE_IS_STARTED;
134         } else {
135
136                 /*
137                  * stop the timer before configuring
138                  */
139                 XTtcPs_Stop(InstancePtr);
140                 /*
141                  * Reset the count control register to it's default value.
142                  */
143                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
144                                   XTTCPS_CNT_CNTRL_OFFSET,
145                                   XTTCPS_CNT_CNTRL_RESET_VALUE);
146
147                 /*
148                  * Reset the rest of the registers to the default values.
149                  */
150                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
151                                   XTTCPS_CLK_CNTRL_OFFSET, 0x00U);
152                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
153                                   XTTCPS_INTERVAL_VAL_OFFSET, 0x00U);
154                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
155                                   XTTCPS_MATCH_1_OFFSET, 0x00U);
156                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
157                                   XTTCPS_MATCH_2_OFFSET, 0x00U);
158                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
159                                   XTTCPS_MATCH_2_OFFSET, 0x00U);
160                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
161                                   XTTCPS_IER_OFFSET, 0x00U);
162                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
163                                   XTTCPS_ISR_OFFSET, XTTCPS_IXR_ALL_MASK);
164
165                 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
166
167                 /*
168                  * Reset the counter value
169                  */
170                 XTtcPs_ResetCounterValue(InstancePtr);
171                 Status = XST_SUCCESS;
172         }
173         return Status;
174 }
175
176 /*****************************************************************************/
177 /**
178 *
179 * This function is used to set the match registers. There are three match
180 * registers.
181 *
182 * The match 0 register is special. If the waveform output mode is enabled, the
183 * waveform will change polarity when the count matches the value in the match 0
184 * register. The polarity of the waveform output can also be set using the
185 * XTtcPs_SetOptions() function.
186 *
187 * @param        InstancePtr is a pointer to the XTtcPs instance.
188 * @param        MatchIndex is the index to the match register to be set.
189 *               Valid values are 0, 1, or 2.
190 * @param        Value is the 16-bit value to be set in the match register.
191 *
192 * @return       None
193 *
194 * @note         None
195 *
196 ****************************************************************************/
197 void XTtcPs_SetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex, u16 Value)
198 {
199         /*
200          * Assert to validate input arguments.
201          */
202         Xil_AssertVoid(InstancePtr != NULL);
203         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
204         Xil_AssertVoid(MatchIndex < (u8)XTTCPS_NUM_MATCH_REG);
205
206         /*
207          * Write the value to the correct match register with MatchIndex
208          */
209         XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
210                           XTtcPs_Match_N_Offset(MatchIndex), Value);
211 }
212
213 /*****************************************************************************/
214 /**
215 *
216 * This function is used to get the value of the match registers. There are
217 * three match registers.
218 *
219 * @param        InstancePtr is a pointer to the XTtcPs instance.
220 * @param        MatchIndex is the index to the match register to be set.
221 *               Valid values are 0, 1, or 2.
222 *
223 * @return       None
224 *
225 * @note         None
226 *
227 ****************************************************************************/
228 u16 XTtcPs_GetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex)
229 {
230         u32 MatchReg;
231
232         /*
233          * Assert to validate input arguments.
234          */
235         Xil_AssertNonvoid(InstancePtr != NULL);
236         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
237         Xil_AssertNonvoid(MatchIndex < XTTCPS_NUM_MATCH_REG);
238
239         MatchReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
240                             XTtcPs_Match_N_Offset(MatchIndex));
241
242         return (u16) MatchReg;
243 }
244
245 /*****************************************************************************/
246 /**
247 *
248 * This function sets the prescaler enable bit and if needed sets the prescaler
249 * bits in the control register.
250 *
251 * @param        InstancePtr is a pointer to the XTtcPs instance.
252 * @param        PrescalerValue is a number from 0-16 that sets the prescaler
253 *               to use.
254 *               If the parameter is 0 - 15, use a prescaler on the clock of
255 *               2^(PrescalerValue+1), or 2-65536.
256 *               If the parameter is XTTCPS_CLK_CNTRL_PS_DISABLE, do not use a
257 *               prescaler.
258 *
259 * @return       None
260 *
261 * @note         None
262 *
263 ****************************************************************************/
264 void XTtcPs_SetPrescaler(XTtcPs *InstancePtr, u8 PrescalerValue)
265 {
266         u32 ClockReg;
267
268         /*
269          * Assert to validate input arguments.
270          */
271         Xil_AssertVoid(InstancePtr != NULL);
272         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
273         Xil_AssertVoid(PrescalerValue <= XTTCPS_CLK_CNTRL_PS_DISABLE);
274
275         /*
276          * Read the clock control register
277          */
278         ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
279                            XTTCPS_CLK_CNTRL_OFFSET);
280
281         /*
282          * Clear all of the prescaler control bits in the register
283          */
284         ClockReg &=
285                 ~(XTTCPS_CLK_CNTRL_PS_VAL_MASK | XTTCPS_CLK_CNTRL_PS_EN_MASK);
286
287         if (PrescalerValue < XTTCPS_CLK_CNTRL_PS_DISABLE) {
288                 /*
289                  * Set the prescaler value and enable prescaler
290                  */
291                 ClockReg |= (u32)(((u32)PrescalerValue << (u32)XTTCPS_CLK_CNTRL_PS_VAL_SHIFT) &
292                         (u32)XTTCPS_CLK_CNTRL_PS_VAL_MASK);
293                 ClockReg |= (u32)XTTCPS_CLK_CNTRL_PS_EN_MASK;
294         }
295
296         /*
297          * Write the register with the new values.
298          */
299         XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
300                           XTTCPS_CLK_CNTRL_OFFSET, ClockReg);
301 }
302
303 /*****************************************************************************/
304 /**
305 *
306 * This function gets the input clock prescaler
307 *
308 * @param        InstancePtr is a pointer to the XTtcPs instance.
309 *
310 * <pre>
311 * @return       The value(n) from which the prescalar value is calculated
312 *               as 2^(n+1). Some example values are given below :
313 *
314 *       Value           Prescaler
315 *       0               2
316 *       1               4
317 *       N               2^(n+1)
318 *       15              65536
319 *       16              1
320 * </pre>
321 *
322 * @note         None.
323 *
324 ****************************************************************************/
325 u8 XTtcPs_GetPrescaler(XTtcPs *InstancePtr)
326 {
327         u8 Status;
328         u32 ClockReg;
329
330         /*
331          * Assert to validate input arguments.
332          */
333         Xil_AssertNonvoid(InstancePtr != NULL);
334         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
335
336         /*
337          * Read the clock control register
338          */
339         ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
340                                     XTTCPS_CLK_CNTRL_OFFSET);
341
342         if (0 == (ClockReg & XTTCPS_CLK_CNTRL_PS_EN_MASK)) {
343                 /*
344                  * Prescaler is disabled. Return the correct flag value
345                  */
346                 Status = (u8)XTTCPS_CLK_CNTRL_PS_DISABLE;
347         }
348         else {
349
350                 Status = (u8)((ClockReg & (u32)XTTCPS_CLK_CNTRL_PS_VAL_MASK) >>
351                         (u32)XTTCPS_CLK_CNTRL_PS_VAL_SHIFT);
352         }
353         return Status;
354 }
355
356 /*****************************************************************************/
357 /**
358 *
359 * This function calculates the interval value as well as the prescaler value
360 * for a given frequency.
361 *
362 * @param        InstancePtr is a pointer to the XTtcPs instance.
363 * @param        Freq is the requested output frequency for the device.
364 * @param        Interval is the interval value for the given frequency,
365 *               it is the output value for this function.
366 * @param        Prescaler is the prescaler value for the given frequency,
367 *               it is the output value for this function.
368 *
369 * @return       None.
370 *
371 * @note
372 *  Upon successful calculation for the given frequency, Interval and Prescaler
373 *  carry the settings for the timer counter; Upon unsuccessful calculation,
374 *  Interval and Prescaler are set to 0xFF(FF) for their maximum values to
375 *  signal the caller of failure. Therefore, caller needs to check the return
376 *  interval or prescaler values for whether the function has succeeded.
377 *
378 ****************************************************************************/
379 void XTtcPs_CalcIntervalFromFreq(XTtcPs *InstancePtr, u32 Freq,
380         u16 *Interval, u8 *Prescaler)
381 {
382         u8 TmpPrescaler;
383         u32 TempValue;
384         u32 InputClock;
385
386         InputClock = InstancePtr->Config.InputClockHz;
387         /*
388          * Find the smallest prescaler that will work for a given frequency. The
389          * smaller the prescaler, the larger the count and the more accurate the
390          *  PWM setting.
391          */
392         TempValue = InputClock/ Freq;
393
394         if (TempValue < 4U) {
395                 /*
396                  * The frequency is too high, it is too close to the input
397                  * clock value. Use maximum values to signal caller.
398                  */
399                 *Interval = 0xFFFFU;
400                 *Prescaler = 0xFFU;
401                 return;
402         }
403
404         /*
405          * First, do we need a prescaler or not?
406          */
407         if (((u32)65536U) > TempValue) {
408                 /*
409                  * We do not need a prescaler, so set the values appropriately
410                  */
411                 *Interval = (u16)TempValue;
412                 *Prescaler = XTTCPS_CLK_CNTRL_PS_DISABLE;
413                 return;
414         }
415
416
417         for (TmpPrescaler = 0U; TmpPrescaler < XTTCPS_CLK_CNTRL_PS_DISABLE;
418              TmpPrescaler++) {
419                 TempValue =     InputClock/ (Freq * (1U << (TmpPrescaler + 1U)));
420
421                 /*
422                  * The first value less than 2^16 is the best bet
423                  */
424                 if (((u32)65536U) > TempValue) {
425                         /*
426                          * Set the values appropriately
427                          */
428                         *Interval = (u16)TempValue;
429                         *Prescaler = TmpPrescaler;
430                         return;
431                 }
432         }
433
434         /* Can not find interval values that work for the given frequency.
435          * Return maximum values to signal caller.
436          */
437         *Interval = 0XFFFFU;
438         *Prescaler = 0XFFU;
439         return;
440 }
441 /** @} */