gr55xx_delay.h
Go to the documentation of this file.
1 /**
2 ****************************************************************************************
3 *
4 * @file gr55xx_delay.h
5 * @author BLE Driver Team
6 * @brief PERIPHERAL API DELAY DRIVER
7 *
8 ****************************************************************************************
9 * @attention
10 #####Copyright (c) 2019 GOODIX
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions are met:
15 * Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20 * Neither the name of GOODIX nor the names of its contributors may be used
21 to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35 ****************************************************************************************
36 */
37
38 #ifndef __GR55xx_DELAY_H__
39 #define __GR55xx_DELAY_H__
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 #include "gr55xx.h"
46
47 /** @addtogroup PERIPHERAL Peripheral Driver
48 * @{
49 */
50
51 /** @addtogroup HAL_DRIVER HAL Driver
52 * @{
53 */
54
55 /** @defgroup HAL_DELAY DELAY
56 * @brief Delay HAL module driver.
57 * @{
58 */
59 /** @addtogroup HAL_DELAY_DEFINES Defines
60 * @{
61 */
62 #define DELAY_US_DWT /**< dealy us dwt define */
63
64 #if defined ( __CC_ARM )
65
66 #ifndef __STATIC_FORCEINLINE
67 #define __STATIC_FORCEINLINE static __forceinline /**< Static inline define */
68 #endif
69
70 #elif defined ( __GNUC__ )
71
72 #ifndef __STATIC_FORCEINLINE
73 #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline /**< Static inline define */
74 #endif
75
76 #else
77
78 #ifndef __STATIC_FORCEINLINE
79 #define __STATIC_FORCEINLINE __STATIC_INLINE /**< Static inline define */
80 #endif
81
82 #endif
83 /** @} */
84
85 #ifndef DELAY_US_DWT
86 /** @addtogroup HAL_DELAY_TYPEDEFS Typedefs
87 * @{
88 */
89 /**
90 * @brief Pointer to a function for delaying execution
91 */
92 typedef void (* delay_func_t)(uint32_t);
93 /** @} */
94 #endif
95
96 #ifdef DELAY_US_DWT
97 /** @addtogroup HAL_DELAY_FUNCTIONS Functions
98 * @{
99 */
100 /**
101 ****************************************************************************************
102 * @brief Enable the DWT.
103 * @param _demcr_initial: demcr initial.
104 * @param _dwt_ctrl_initial: dwt ctrl initial.
105 ****************************************************************************************
106 */
107 void hal_dwt_enable(uint32_t _demcr_initial, uint32_t _dwt_ctrl_initial);
108
109 /**
110 ****************************************************************************************
111 * @brief Disable the DWT.
112 * @param _demcr_initial: demcr initial.
113 * @param _dwt_ctrl_initial: dwt ctrl initial.
114 ****************************************************************************************
115 */
116 void hal_dwt_disable(uint32_t _demcr_initial, uint32_t _dwt_ctrl_initial);
117 /** @} */
118
119 /** @addtogroup HAL_DELAY_DEFINES Defines
120 * @{
121 */
122 /**
123 * @brief Timeout module init. This macro must be used in
124 * conjunction with the @ref HAL_TIMEOUT_DEINIT macro
125 */
126 #define HAL_TIMEOUT_INIT() \
127 uint32_t _demcr_initial = CoreDebug->DEMCR; \
128 uint32_t _dwt_ctrl_initial = DWT->CTRL; \
129 do { \
130 hal_dwt_enable(_demcr_initial, _dwt_ctrl_initial); \
131 } while (0)
132
133 /**
134 * @brief Timeout module deinit. This macro must be used in
135 * conjunction with the @ref HAL_TIMEOUT_INIT macro
136 */
137 #define HAL_TIMEOUT_DEINIT() \
138 do { \
139 hal_dwt_disable(_demcr_initial, _dwt_ctrl_initial); \
140 } while(0)
141 /** @} */
142
143 /** @addtogroup HAL_DELAY_FUNCTIONS Functions
144 * @{
145 */
146 /**
147 ****************************************************************************************
148 * @brief Function for delaying execution for number of us.
149 * @note GR55xxx is based on ARM Cortex-M4, and this fuction is based on Data Watchpoint and Trace (DWT) unit so delay is precise.
150 * @param number_of_us: The maximum delay time is about 67 seconds in 64M system clock.
151 * The faster the system clock, the shorter the maximum delay time.
152 ****************************************************************************************
153 */
154 __STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
155 {
156 const uint8_t clocks[] = {64, 48, 16, 24, 16, 32};
157 uint32_t cycles = number_of_us * (clocks[AON->PWR_RET01 & AON_PWR_REG01_SYS_CLK_SEL]);
158
159 if (number_of_us == 0)
160 {
161 return;
162 }
163
164 HAL_TIMEOUT_INIT();
165
166 // Get start value of the cycle counter.
167 uint32_t cyccnt_initial = DWT->CYCCNT;
168
169 // Wait time end
170 while ((DWT->CYCCNT - cyccnt_initial) < cycles)
171 {}
172
173 HAL_TIMEOUT_DEINIT();
174 }
175 /** @} */
176 #endif
177
178 #ifndef DELAY_US_DWT
179
180 #if defined ( __CC_ARM )
181
182 #pragma push
183 #pragma O2
184 /** @addtogroup HAL_DELAY_FUNCTIONS Functions
185 * @{
186 */
187 /**
188 ****************************************************************************************
189 * @brief Function for delaying execution for number of us.
190 * @note GR55xxx is based on ARM Cortex-M4, and this fuction is based on Data Watchpoint and Trace (DWT) unit so delay is precise.
191 * @param number_of_us: The maximum delay time is about 67 seconds in 64M system clock.
192 * The faster the system clock, the shorter the maximum delay time.
193 ****************************************************************************************
194 */
195 __STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
196 {
197 uint32_t pc = (unsigned int)__current_pc();
198 uint8_t clocks[] = {64, 48, 16, 24, 16, 32};
199
200 if (number_of_us == 0)
201 {
202 return;
203 }
204
205 static const uint16_t delay_ramcode[] = {
206 0x3809, // SUBS r0, #9
207 0xd8fd, // BHI .-2
208 0x4770 // BX LR
209 };
210 // Set LSB to 1 to execute code in Thumb mode.
211 const delay_func_t delay_ram_cycles = (delay_func_t)((((uint32_t)delay_ramcode) | 1));
212
213 static const uint16_t delay_flashcode[] = {
214 0x3803, // SUBS r0, #3
215 0xd8fd, // BHI .-2
216 0x4770 // BX LR
217 };
218 // Set LSB to 1 to execute code in Thumb mode.
219 const delay_func_t delay_flash_cycles = (delay_func_t)((((uint32_t)delay_flashcode) | 1));
220
221 static const uint16_t delay_aliascode[] = {
222 0x3803, // SUBS r0, #3
223 0xd8fd, // BHI .-2
224 0x4770 // BX LR
225 };
226 // Set LSB to 1 to execute code in Thumb mode.
227 const delay_func_t delay_alias_cycles = (delay_func_t)((((uint32_t)delay_aliascode) | 1));
228
229 uint32_t cycles = number_of_us * (clocks[AON->PWR_RET01 & AON_PWR_REG01_SYS_CLK_SEL]);
230
231 if(pc & GR55XX_RAM_ADDRESS)
232 delay_ram_cycles(cycles);
233 else if(pc & GR55XX_FLASH_ADDRESS)
234 delay_flash_cycles(cycles);
235 else if(pc & GR55XX_ALIAS_ADDRESS)
236 delay_alias_cycles(cycles);
237 else
238 {
239 cycles = cycles / 4;
240 __asm
241 {
242 loop:
243 NOP
244 SUBS cycles, #1
245 BNE loop
246 }
247 }
248 }
249 #pragma pop
250
251 #elif defined ( _WIN32 ) || defined ( __unix ) || defined ( __APPLE__ )
252
253 #ifndef CUSTOM_DELAY_US
254 /**
255 ****************************************************************************************
256 * @brief Function for delaying execution for number of us.
257 * @param number_of_us: The maximum delay time is about 67 seconds in 64M system clock.
258 * The faster the system clock, the shorter the maximum delay time.
259 ****************************************************************************************
260 */
261 __STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
262 {
263 }
264 #endif
265
266 #elif defined ( __GNUC__ ) || ( __ICCARM__ )
267 /**
268 ****************************************************************************************
269 * @brief Function for delaying execution for number of us.
270 * @param number_of_us: The maximum delay time is about 67 seconds in 64M system clock.
271 * The faster the system clock, the shorter the maximum delay time.
272 ****************************************************************************************
273 */
274 __STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
275 {
276 uint8_t clocks[] = {64, 48, 16, 24, 16, 32};
277
278 if (number_of_us)
279 {
280 uint32_t cycles;
281 cycles = number_of_us*(clocks[AON->PWR_RET01 & AON_PWR_REG01_SYS_CLK_SEL])/6;
282 __asm__ volatile ("1:\n"
283 "NOP\n"
284 "NOP\n"
285 "NOP\n"
286 "SUBS %[cycles], %[cycles], #1\n"
287 "BNE.N 1b\n"
288 : [cycles] "=r" (cycles)
289 : "[cycles]" "r" (cycles)
290 );
291 }
292 }
293 /** @} */
294 #endif
295
296 #endif
297
298 /** @addtogroup HAL_DELAY_FUNCTIONS Functions
299 * @{
300 */
301 /**
302 * @brief Function for delaying execution for number of milliseconds.
303 *
304 * @note GR55xx is based on ARM Cortex-M4, and this fuction is based on Data Watchpoint and Trace (DWT) unit so delay is precise.
305 *
306 * @note Function internally calls @ref delay_us so the maximum delay is the
307 * same as in case of @ref delay_us.
308 *
309 * @param number_of_ms: The maximum delay time is about 67 seconds in 64M system clock.
310 * The faster the system clock, the shorter the maximum delay time.
311 *
312 */
313 __STATIC_FORCEINLINE void delay_ms(uint32_t number_of_ms)
314 {
315 delay_us(1000 * number_of_ms);
316 return;
317 }
318 /** @} */
319
320 #ifdef __cplusplus
321 }
322 #endif
323
324 #endif /* __GR55xx_DELAY_H__ */
325 /** @} */
326 /** @} */
327 /** @} */
328
hal_dwt_disable
void hal_dwt_disable(uint32_t _demcr_initial, uint32_t _dwt_ctrl_initial)
Disable the DWT.
HAL_TIMEOUT_INIT
#define HAL_TIMEOUT_INIT()
Timeout module init.
Definition: gr55xx_delay.h:126
delay_ms
__STATIC_FORCEINLINE void delay_ms(uint32_t number_of_ms)
Function for delaying execution for number of milliseconds.
Definition: gr55xx_delay.h:313
delay_us
__STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
Function for delaying execution for number of us.
Definition: gr55xx_delay.h:154
hal_dwt_enable
void hal_dwt_enable(uint32_t _demcr_initial, uint32_t _dwt_ctrl_initial)
Enable the DWT.
__STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE
Static inline define.
Definition: gr55xx_delay.h:79
HAL_TIMEOUT_DEINIT
#define HAL_TIMEOUT_DEINIT()
Timeout module deinit.
Definition: gr55xx_delay.h:137