Contiki 3.x
pic32_timer.c
Go to the documentation of this file.
1 /*
2  * Contiki PIC32 Port project
3  *
4  * Copyright (c) 2012,
5  * Scuola Superiore Sant'Anna (http://www.sssup.it) and
6  * Consorzio Nazionale Interuniversitario per le Telecomunicazioni
7  * (http://www.cnit.it).
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in the
18  * documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the Institute nor the names of its contributors
20  * may be used to endorse or promote products derived from this software
21  * without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36 
37 /**
38  * \addtogroup pic32 PIC32 Contiki Port
39  *
40  * @{
41  */
42 
43 /**
44  * \file pic32_timer.c
45  * \brief TIMER interface for PIC32MX (pic32mx795f512l)
46  * \author Giovanni Pellerano <giovanni.pellerano@evilaliv3.org>
47  * \date 2012-03-26
48  */
49 
50 /*
51  * PIC32MX795F512L - Specific Functions
52  *
53  * All the functions in this part of the file are specific for the
54  * pic32mx795f512l that is characterized by registers' name that differ from
55  * the 3xx and 4xx families of the pic32mx.
56  */
57 
58 #define __TIMER_CODE_TEST__ 0
59 
60 #if __TIMER_CODE_TEST__
61 #define __USE_TIMER__ 1
62 #define __USE_TIMER_1__ 1
63 #define __USE_TIMER_2__ 1
64 #define __USE_TIMER_3__ 1
65 #define __USE_TIMER_4__ 1
66 #define __USE_TIMER_5__ 1
67 #define __USE_TIMER_23__ 1
68 #define __USE_TIMER_45__ 1
69 #endif /* __TIMER_CODE_TEST__ */
70 
71 #ifdef __USE_TIMER__
72 
73 #include <pic32_timer.h>
74 #include <pic32_clock.h>
75 #include <pic32_irq.h>
76 
77 #include <p32xxxx.h>
78 
79 #include <stdint.h>
80 #include <stddef.h>
81 
82 /*---------------------------------------------------------------------------*/
83 #define TIMERN_16(XX, TT, PP) \
84  void \
85  pic32_timer##XX##_enable_irq(void) \
86  { \
87  IFS0CLR = _IFS0_T##XX##IF_MASK; /* Clean Timer IRQ Flag */ \
88  IEC0SET = _IEC0_T##XX##IE_MASK; /* Enable Timer IRQ */ \
89  } \
90  \
91  void \
92  pic32_timer##XX##_disable_irq(void) \
93  { \
94  IEC0CLR = _IEC0_T##XX##IE_MASK; /* Disable Timer IRQ */ \
95  IFS0CLR = _IFS0_T##XX##IF_MASK; /* Clean Timer IRQ Flag */ \
96  } \
97  \
98  uint8_t \
99  pic32_timer##XX##_init(uint32_t frequency) \
100  { \
101  uint32_t prd = pic32_clock_get_peripheral_clock() / frequency; \
102  uint8_t tckps; /* Prescale */ \
103  uint8_t ok = 0; \
104  \
105  if(prd <= UINT16_MAX) { \
106  tckps = TIMER_##TT##_PRESCALE_1; \
107  ok = 1; \
108  } else { \
109  prd = prd / 8; \
110  } \
111  \
112  if(ok == 0) { \
113  if(prd <= UINT16_MAX) { \
114  tckps = TIMER_##TT##_PRESCALE_8; \
115  ok = 1; \
116  } else { \
117  prd = prd / 8; \
118  } \
119  } \
120  \
121  if(ok == 0) { \
122  if(prd <= UINT16_MAX) { \
123  tckps = TIMER_##TT##_PRESCALE_64; \
124  ok = 1; \
125  } else { \
126  prd = prd / 4; \
127  } \
128  } \
129  \
130  if(ok == 0) { \
131  if(prd <= UINT16_MAX) { \
132  tckps = TIMER_##TT##_PRESCALE_256; \
133  } else { \
134  return -TIMER_ERR_BAD_ARGS; \
135  } \
136  } \
137  \
138  pic32_timer##XX##_disable_irq(); \
139  \
140  IPC##XX##CLR = _IPC##XX##_T##XX##IP_MASK | _IPC##XX##_T##XX##IS_MASK; \
141  IPC##XX##SET = (7 << _IPC##XX##_T##XX##IP_POSITION) | (PP << _IPC##XX##_T##XX##IS_POSITION); \
142  T##XX##CON = 0; \
143  T##XX##CONSET = tckps << _T##XX##CON_TCKPS_POSITION; \
144  PR##XX = prd; \
145  TMR##XX = 0; \
146  \
147  return TIMER_NO_ERRORS; \
148  } \
149  \
150  void \
151  pic32_timer##XX##_start(void) \
152  { \
153  T##XX##CONSET = _T##XX##CON_ON_MASK; /* Start Timer */ \
154  } \
155  \
156  void \
157  pic32_timer##XX##_stop(void) \
158  { \
159  T##XX##CONCLR = _T##XX##CON_ON_MASK; /* Stop Timer */ \
160  } \
161  \
162  uint16_t \
163  pic32_timer##XX##_get_val(void) \
164  { \
165  return TMR##XX; \
166  }
167 /*---------------------------------------------------------------------------*/
168 #define TIMERN_32(XX, YY, PP) \
169  \
170  void \
171  pic32_timer##XX##YY##_enable_irq(void) \
172  { \
173  pic32_timer##YY##_enable_irq(); \
174  } \
175  \
176  void \
177  pic32_timer##XX##YY##_disable_irq(void) \
178  { \
179  pic32_timer##YY##_disable_irq(); \
180  } \
181  \
182  uint8_t \
183  pic32_timer##XX##YY##_init(uint32_t frequency) \
184  { \
185  uint32_t prd = pic32_clock_get_peripheral_clock() / frequency; \
186  uint8_t tckps; /* Prescale */ \
187  uint8_t ok = 0; \
188  \
189  if(prd <= UINT16_MAX) { \
190  tckps = TIMER_B_PRESCALE_1; \
191  ok = 1; \
192  } else { \
193  prd = prd / 8; \
194  } \
195  \
196  if(ok == 0) { \
197  if(prd <= UINT16_MAX) { \
198  tckps = TIMER_B_PRESCALE_8; \
199  ok = 1; \
200  } else { \
201  prd = prd / 8; \
202  } \
203  } \
204  \
205  if(ok == 0) { \
206  if(prd <= UINT16_MAX) { \
207  tckps = TIMER_B_PRESCALE_64; \
208  ok = 1; \
209  } else { \
210  prd = prd / 4; \
211  } \
212  } \
213  \
214  if(ok == 0) { \
215  if(prd <= UINT16_MAX) { \
216  tckps = TIMER_B_PRESCALE_256; \
217  } else { \
218  return -TIMER_ERR_BAD_ARGS; \
219  } \
220  } \
221  \
222  pic32_timer##XX##_disable_irq(); \
223  \
224  IPC##YY##CLR = _IPC##YY##_T##YY##IP_MASK | _IPC##YY##_T##YY##IS_MASK; \
225  IPC##YY##SET = (7 << _IPC##YY##_T##YY##IP_POSITION) | (PP << _IPC##YY##_T##YY##IS_POSITION); \
226  T##XX##CON = 0; \
227  T##XX##CONSET = _T##XX##CON_T32_MASK | (tckps << _T##XX##CON_TCKPS_POSITION); \
228  PR##XX = prd; \
229  TMR##XX = 0; \
230  \
231  return TIMER_NO_ERRORS; \
232  } \
233  \
234  void \
235  pic32_timer##XX##YY##_start(void) \
236  { \
237  T##XX##CONSET = _T##XX##CON_ON_MASK; /* Start Timer */ \
238  } \
239  \
240  void \
241  pic32_timer##XX##YY##_stop(void) \
242  { \
243  T##XX##CONCLR = _T##XX##CON_ON_MASK; /* Stop Timer */ \
244  } \
245  \
246  uint32_t \
247  pic32_timer##XX##YY##_get_val(void) \
248  { \
249  return TMR##XX; \
250  }
251 /*---------------------------------------------------------------------------*/
252 
253 #ifdef __USE_TIMER_1__
254 TIMERN_16(1, A, 3)
255 #endif /* __USE_TIMER_1__ */
256 
257 #if defined(__USE_TIMER_2__) || defined(__USE_TIMER_23__)
258 TIMERN_16(2, B, 2)
259 #endif /* __USE_TIMER_2__ */
260 
261 #if defined(__USE_TIMER_3__) || defined(__USE_TIMER_23__)
262 TIMERN_16(3, B, 1)
263 #endif /* __USE_TIMER_3__ */
264 
265 #if defined(__USE_TIMER_4__) || defined(__USE_TIMER_45__)
266 TIMERN_16(4, B, 1)
267 #endif /* __USE_TIMER_4__ */
268 
269 #if defined(__USE_TIMER_5__) || defined(__USE_TIMER_45__)
270 TIMERN_16(5, B, 1)
271 #endif /* __USE_TIMER_5__ */
272 
273 #ifdef __USE_TIMER_23__
274 TIMERN_32(2, 3, 3)
275 #endif /* __USE_TIMER_23__ */
276 
277 #ifdef __USE_TIMER_45__
278 TIMERN_32(4, 5, 2)
279 #endif /* __USE_TIMER_45__ */
280 
281 #endif /* __USE_TIMER__ */
282 
283 /** @} */
INTERRUPT interface for PIC32MX (pic32mx795f512l)
CLOCK interface for PIC32MX (pic32mx795f512l)
TIMER interface for PIC32MX (pic32mx795f512l)