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