• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /** \addtogroup hal */
3 /** @{*/
4 /* mbed Microcontroller Library
5  * Copyright (c) 2006-2015 ARM Limited
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 #ifndef MBED_US_TICKER_API_H
21 #define MBED_US_TICKER_API_H
22 
23 #include <stdint.h>
24 #include "ticker_api.h"
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 /**
31  * \defgroup hal_us_ticker Microsecond Ticker
32  * Low level interface to the microsecond ticker of a target
33  *
34  * # Defined behavior
35  * * Has a reported frequency between 250KHz and 8MHz for counters which are less than 32 bits wide - Verified by test ::us_ticker_info_test
36  * * Has a reported frequency up to 100MHz for counters which are 32 bits wide - Verified by test ::us_ticker_info_test
37  * * Has a counter that is at least 16 bits wide - Verified by test ::us_ticker_info_test
38  * * All behavior defined by the @ref hal_ticker_shared "ticker specification"
39  *
40  * # Undefined behavior
41  * * See the @ref hal_ticker_shared "ticker specification"
42  *
43  * @see hal_us_ticker_tests
44  *
45  * # Compile-time optimization macros
46  *
47  * To permit compile-time optimization, particularly of wait_us, the following macros should
48  * be defined by a target's device.h:
49  *
50  * US_TICKER_PERIOD_NUM, US_TICKER_PERIOD_DEN: These denote the ratio (numerator, denominator)
51  * of the ticker period to a microsecond. For example, an 8MHz ticker would have NUM = 1, DEN = 8;
52  * a 1MHz ticker would have NUM = 1, DEN = 1; a 250kHz ticker would have NUM = 4, DEN = 1.
53  * Both numerator and denominator must be 16 bits or less.
54  *
55  * US_TICKER_MASK: The value mask for the ticker - eg 0x07FFFFFF for a 27-bit ticker.
56  *
57  * If any are defined, all 3 must be defined, and the macros are checked for consistency with
58  * us_ticker_get_info by test ::us_ticker_info_test.
59 
60  * @{
61  */
62 
63 /**
64  * \defgroup hal_us_ticker_tests Microsecond Ticker tests
65  * Tests to validate the proper implementation of the microsecond ticker
66  *
67  * To run the microsecond ticker hal tests use the command:
68  *
69  *     mbed test -t <toolchain> -m <target> -n tests-mbed_hal-common_ticker*,tests-mbed_hal-us_ticker*
70  *
71  * @see hal_ticker_tests
72  *
73  */
74 
75 /**
76  * \defgroup hal_ticker_shared Ticker Hal
77  * Low level interface to the ticker of a target
78  *
79  * # Defined behavior
80  * * The function ticker_init is safe to call repeatedly - Verified by test ::ticker_init_test
81  * * The function ticker_init allows the ticker to keep counting and disables the ticker interrupt - Verified by test ::ticker_init_test
82  * * Ticker frequency is non-zero and counter is at least 8 bits - Verified by ::ticker_info_test
83  * * The ticker rolls over at (1 << bits) and continues counting starting from 0 - Verified by ::ticker_overflow_test
84  * * The ticker counts at the specified frequency +- 10% - Verified by ::ticker_frequency_test
85  * * The ticker increments by 1 each tick - Verified by ::ticker_increment_test
86  * * The ticker interrupt fires only when the ticker times increments to or past the value set by ticker_set_interrupt.
87  * Verified by ::ticker_interrupt_test and ::ticker_past_test
88  * * It is safe to call ticker_set_interrupt repeatedly before the handler is called - Verified by ::ticker_repeat_reschedule_test
89  * * The function ticker_fire_interrupt causes ticker_irq_handler to be called immediately from interrupt context -
90  * Verified by ::ticker_fire_now_test
91  * * The ticker operations ticker_read, ticker_clear_interrupt, ticker_set_interrupt and ticker_fire_interrupt
92  * take less than 20us to complete - Verified by ::ticker_speed_test
93  * * The ticker operations ticker_init and ticker_read are atomic.
94  *
95  * # Undefined behavior
96  * * Calling any function other than ticker_init before the initialization of the ticker
97  * * Whether ticker_irq_handler is called a second time if the time wraps and matches the value set by ticker_set_interrupt again
98  * * Calling ticker_set_interrupt with a value that has more than the supported number of bits
99  * * Calling any function other than us_ticker_init after calling us_ticker_free
100  *
101  * # Potential bugs
102  * * Drift due to reschedule - Verified by ::ticker_repeat_reschedule_test
103  * * Incorrect overflow handling of timers - Verified by ::ticker_overflow_test
104  * * Interrupting at a time of 0 - Verified by ::ticker_overflow_test
105  * * Interrupt triggered more than once - Verified by ::ticker_interrupt_test
106  *
107  * @ingroup hal_us_ticker
108  * @ingroup hal_lp_ticker
109  */
110 
111 /**
112  * \defgroup hal_ticker_tests Ticker Tests
113  * Tests to validate the proper implementation of a ticker
114  *
115  * To run the ticker hal tests use the command:
116  *
117  *     mbed test -t <toolchain> -m <target> -n tests-mbed_hal-common_ticker*
118  *
119  * @ingroup hal_us_ticker
120  * @ingroup hal_lp_ticker
121  */
122 
123 
124 typedef void (*ticker_irq_handler_type)(const ticker_data_t *const);
125 
126 /** Set ticker IRQ handler
127  *
128  * @param ticker_irq_handler IRQ handler to be connected
129  *
130  * @return previous ticker IRQ handler
131  *
132  * @note by default IRQ handler is set to ::ticker_irq_handler
133  * @note this function is primarily for testing purposes and it's not required part of HAL implementation
134  *
135  */
136 ticker_irq_handler_type set_us_ticker_irq_handler(ticker_irq_handler_type ticker_irq_handler);
137 
138 /** Get ticker's data
139  *
140  * @return The microsecond ticker data
141  */
142 const ticker_data_t *get_us_ticker_data(void);
143 
144 
145 /** The wrapper for ticker_irq_handler, to pass us ticker's data
146  *
147  */
148 void us_ticker_irq_handler(void);
149 
150 /* HAL us ticker */
151 
152 /** Initialize the ticker
153  *
154  * Initialize or re-initialize the ticker. This resets all the
155  * clocking and prescaler registers, along with disabling
156  * the compare interrupt.
157  *
158  * @note Initialization properties tested by ::ticker_init_test
159  *
160  * Pseudo Code:
161  * @code
162  * void us_ticker_init()
163  * {
164  *     // Enable clock gate so processor can read TIMER registers
165  *     POWER_CTRL |= POWER_CTRL_TIMER_Msk;
166  *
167  *     // Disable the timer and ensure it is powered down
168  *     TIMER_CTRL &= ~(TIMER_CTRL_ENABLE_Msk | TIMER_CTRL_COMPARE_ENABLE_Msk);
169  *
170  *     // Configure divisors
171  *     uint32_t prescale = SystemCoreClock / 1000000;
172  *     TIMER_PRESCALE = prescale - 1;
173  *     TIMER_CTRL |= TIMER_CTRL_ENABLE_Msk;
174  *
175  *     // Install the interrupt handler
176  *     NVIC_SetVector(TIMER_IRQn, (uint32_t)us_ticker_irq_handler);
177  *     NVIC_EnableIRQ(TIMER_IRQn);
178  * }
179  * @endcode
180  */
181 void us_ticker_init(void);
182 
183 /** Deinitialize the us ticker
184  *
185  * Powerdown the us ticker in preparation for sleep, powerdown, or reset.
186  *
187  * After this function is called, no other ticker functions should be called
188  * except us_ticker_init(), calling any function other than init is undefined.
189  *
190  * @note This function stops the ticker from counting.
191  *
192  * Pseudo Code:
193  * @code
194  * uint32_t us_ticker_free()
195  * {
196  *     // Disable timer
197  *     TIMER_CTRL &= ~TIMER_CTRL_ENABLE_Msk;
198  *
199  *     // Disable the compare interrupt
200  *     TIMER_CTRL &= ~TIMER_CTRL_COMPARE_ENABLE_Msk;
201  *
202  *     // Disable timer interrupt
203  *     NVIC_DisableIRQ(TIMER_IRQn);
204  *
205  *     // Disable clock gate so processor cannot read TIMER registers
206  *     POWER_CTRL &= ~POWER_CTRL_TIMER_Msk;
207  * }
208  * @endcode
209  *
210  */
211 void us_ticker_free(void);
212 
213 /** Read the current counter
214  *
215  * Read the current counter value without performing frequency conversions.
216  * If no rollover has occurred, the seconds passed since us_ticker_init()
217  * was called can be found by dividing the ticks returned by this function
218  * by the frequency returned by ::us_ticker_get_info.
219  *
220  * @return The current timer's counter value in ticks
221  *
222  * Pseudo Code:
223  * @code
224  * uint32_t us_ticker_read()
225  * {
226  *     return TIMER_COUNT;
227  * }
228  * @endcode
229  */
230 uint32_t (us_ticker_read)(void);
231 
232 /** Set interrupt for specified timestamp
233  *
234  * @param timestamp The time in ticks to be set
235  *
236  * @note no special handling needs to be done for times in the past
237  * as the common timer code will detect this and call
238  * us_ticker_fire_interrupt() if this is the case
239  *
240  * @note calling this function with timestamp of more than the supported
241  * number of bits returned by ::us_ticker_get_info results in undefined
242  * behavior.
243  *
244  * Pseudo Code:
245  * @code
246  * void us_ticker_set_interrupt(timestamp_t timestamp)
247  * {
248  *     TIMER_COMPARE = timestamp;
249  *     TIMER_CTRL |= TIMER_CTRL_COMPARE_ENABLE_Msk;
250  * }
251  * @endcode
252  */
253 void us_ticker_set_interrupt(timestamp_t timestamp);
254 
255 /** Disable us ticker interrupt
256  *
257  * Pseudo Code:
258  * @code
259  * void us_ticker_disable_interrupt(void)
260  * {
261  *     // Disable the compare interrupt
262  *     TIMER_CTRL &= ~TIMER_CTRL_COMPARE_ENABLE_Msk;
263  * }
264  * @endcode
265  */
266 void us_ticker_disable_interrupt(void);
267 
268 /** Clear us ticker interrupt
269  *
270  * Pseudo Code:
271  * @code
272  * void us_ticker_clear_interrupt(void)
273  * {
274  *     // Write to the ICR (interrupt clear register) of the TIMER
275  *     TIMER_ICR = TIMER_ICR_COMPARE_Msk;
276  * }
277  * @endcode
278  */
279 void us_ticker_clear_interrupt(void);
280 
281 /** Set pending interrupt that should be fired right away.
282  *
283  * The ticker should be initialized prior calling this function.
284  *
285  * Pseudo Code:
286  * @code
287  * void us_ticker_fire_interrupt(void)
288  * {
289  *     NVIC_SetPendingIRQ(TIMER_IRQn);
290  * }
291  * @endcode
292  */
293 void us_ticker_fire_interrupt(void);
294 
295 /** Get frequency and counter bits of this ticker.
296  *
297  * Pseudo Code:
298  * @code
299  * const ticker_info_t* us_ticker_get_info()
300  * {
301  *     static const ticker_info_t info = {
302  *         1000000,    // 1 MHz
303  *         32          // 32 bit counter
304  *     };
305  *     return &info;
306  * }
307  * @endcode
308  */
309 const ticker_info_t *us_ticker_get_info(void);
310 
311 /**@}*/
312 
313 #ifdef __cplusplus
314 }
315 #endif
316 
317 #endif
318 
319 /** @}*/
320