OP-1156 fix path logic to not deviate from correct altitude too much
[librepilot.git] / flight / pios / stm32f10x / pios_delay.c
blob9effa1ec7d6efe0423ab33ef7130e14cb1d4e115
1 /**
2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
4 * @{
5 * @addtogroup PIOS_DELAY Delay Functions
6 * @brief PiOS Delay functionality
7 * @{
9 * @file pios_delay.c
10 * @author Michael Smith Copyright (C) 2011
11 * @brief Delay Functions
12 * - Provides a micro-second granular delay using the CPU
13 * cycle counter.
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
26 * for more details.
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
33 #include <pios.h>
35 #ifdef PIOS_INCLUDE_DELAY
37 /* these should be defined by CMSIS, but they aren't */
38 #define DWT_CTRL (*(volatile uint32_t *)0xe0001000)
39 #define CYCCNTENA (1 << 0)
40 #define DWT_CYCCNT (*(volatile uint32_t *)0xe0001004)
43 /* cycles per microsecond */
44 static uint32_t us_ticks;
46 /**
47 * Initialises the Timer used by PIOS_DELAY functions.
49 * \return always zero (success)
52 int32_t PIOS_DELAY_Init(void)
54 RCC_ClocksTypeDef clocks;
56 /* compute the number of system clocks per microsecond */
57 RCC_GetClocksFreq(&clocks);
58 us_ticks = clocks.SYSCLK_Frequency / 1000000;
59 PIOS_DEBUG_Assert(us_ticks > 1);
61 /* turn on access to the DWT registers */
62 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
64 /* enable the CPU cycle counter */
65 DWT_CTRL |= CYCCNTENA;
67 return 0;
70 /**
71 * Waits for a specific number of uS
73 * Example:<BR>
74 * \code
75 * // Wait for 500 uS
76 * PIOS_DELAY_Wait_uS(500);
77 * \endcode
78 * \param[in] uS delay
79 * \return < 0 on errors
81 int32_t PIOS_DELAY_WaituS(uint32_t uS)
83 uint32_t elapsed = 0;
84 uint32_t last_count = DWT_CYCCNT;
86 for (;;) {
87 uint32_t current_count = DWT_CYCCNT;
88 uint32_t elapsed_uS;
90 /* measure the time elapsed since the last time we checked */
91 elapsed += current_count - last_count;
92 last_count = current_count;
94 /* convert to microseconds */
95 elapsed_uS = elapsed / us_ticks;
96 if (elapsed_uS >= uS) {
97 break;
100 /* reduce the delay by the elapsed time */
101 uS -= elapsed_uS;
103 /* keep fractional microseconds for the next iteration */
104 elapsed %= us_ticks;
107 /* No error */
108 return 0;
112 * Waits for a specific number of mS
114 * Example:<BR>
115 * \code
116 * // Wait for 500 mS
117 * PIOS_DELAY_Wait_mS(500);
118 * \endcode
119 * \param[in] mS delay
120 * \return < 0 on errors
122 int32_t PIOS_DELAY_WaitmS(uint32_t mS)
124 while (mS--) {
125 PIOS_DELAY_WaituS(1000);
128 /* No error */
129 return 0;
133 * @brief Query the Delay timer for the current uS
134 * @return A microsecond value
136 uint32_t PIOS_DELAY_GetuS(void)
138 return DWT_CYCCNT / us_ticks;
142 * @brief Calculate time in microseconds since a previous time
143 * @param[in] t previous time
144 * @return time in us since previous time t.
146 uint32_t PIOS_DELAY_GetuSSince(uint32_t t)
148 return PIOS_DELAY_GetuS() - t;
152 * @brief Get the raw delay timer, useful for timing
153 * @return Unitless value (uint32 wrap around)
155 uint32_t PIOS_DELAY_GetRaw()
157 return DWT_CYCCNT;
161 * @brief Compare to raw times to and convert to us
162 * @return A microsecond value
164 uint32_t PIOS_DELAY_DiffuS(uint32_t raw)
166 uint32_t diff = DWT_CYCCNT - raw;
168 return diff / us_ticks;
171 #endif /* PIOS_INCLUDE_DELAY */
174 * @}
175 * @}