2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
5 * @addtogroup PIOS_DELAY Delay Functions
6 * @brief PiOS Delay functionality
10 * @author Michael Smith Copyright (C) 2011
11 * @brief Delay Functions
12 * - Provides a micro-second granular delay using the CPU
14 * @see The GNU Public License (GPL) Version 3
16 *****************************************************************************/
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 3 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28 * You should have received a copy of the GNU General Public License along
29 * with this program; if not, write to the Free Software Foundation, Inc.,
30 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 #ifdef PIOS_INCLUDE_DELAY
37 /* cycles per microsecond */
38 static uint32_t us_ticks
;
39 static uint32_t raw_hz
;
42 * Initialises the Timer used by PIOS_DELAY functions.
44 * \return always zero (success)
47 int32_t PIOS_DELAY_Init(void)
49 RCC_ClocksTypeDef clocks
;
51 /* compute the number of system clocks per microsecond */
52 RCC_GetClocksFreq(&clocks
);
53 us_ticks
= clocks
.SYSCLK_Frequency
/ 1000000;
54 PIOS_DEBUG_Assert(us_ticks
> 1);
55 raw_hz
= clocks
.SYSCLK_Frequency
;
57 /* turn on access to the DWT registers */
58 CoreDebug
->DEMCR
|= CoreDebug_DEMCR_TRCENA_Msk
;
60 /* enable the CPU cycle counter */
61 DWT_CTRL
|= CYCCNTENA
;
67 * Waits for a specific number of uS
72 * PIOS_DELAY_Wait_uS(500);
75 * \return < 0 on errors
77 int32_t PIOS_DELAY_WaituS(uint32_t uS
)
80 uint32_t last_count
= DWT_CYCCNT
;
83 uint32_t current_count
= PIOS_DELAY_GetRaw();
86 /* measure the time elapsed since the last time we checked */
87 elapsed
+= current_count
- last_count
;
88 last_count
= current_count
;
90 /* convert to microseconds */
91 elapsed_uS
= elapsed
/ us_ticks
;
92 if (elapsed_uS
>= uS
) {
96 /* reduce the delay by the elapsed time */
99 /* keep fractional microseconds for the next iteration */
108 * Waits for a specific number of mS
113 * PIOS_DELAY_Wait_mS(500);
115 * \param[in] mS delay
116 * \return < 0 on errors
118 int32_t PIOS_DELAY_WaitmS(uint32_t mS
)
121 PIOS_DELAY_WaituS(1000);
129 * @brief Query the Delay timer for the current uS
130 * @return A microsecond value
132 uint32_t PIOS_DELAY_GetuS(void)
134 return PIOS_DELAY_GetRaw() / us_ticks
;
138 * @brief Calculate time in microseconds since a previous time
139 * @param[in] t previous time
140 * @return time in us since previous time t.
142 uint32_t PIOS_DELAY_GetuSSince(uint32_t t
)
144 return PIOS_DELAY_GetuS() - t
;
148 * @brief Get the raw delay timer frequency
149 * @return raw delay timer frequency in Hz
151 uint32_t PIOS_DELAY_GetRawHz()
157 * @brief Compare to raw times to and convert to us
158 * @return A microsecond value
160 uint32_t PIOS_DELAY_DiffuS(uint32_t raw
)
162 uint32_t diff
= PIOS_DELAY_GetRaw() - raw
;
164 return diff
/ us_ticks
;
167 #endif /* PIOS_INCLUDE_DELAY */