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 *
104 ****************************************************************************************
105 */
106 void hal_dwt_enable(void);
107
108 /**
109 ****************************************************************************************
110 * @brief Disable the DWT.
111 *
112 ****************************************************************************************
113 */
114 void hal_dwt_disable(void);
115 /** @} */
116
117 /** @addtogroup HAL_DELAY_DEFINES Defines
118 * @{
119 */
120 /**
121 * @brief Timeout module init. This macro must be used in
122 * conjunction with the @ref HAL_TIMEOUT_DEINIT macro
123 */
124 #define HAL_TIMEOUT_INIT() hal_dwt_enable()
125
126 /**
127 * @brief Timeout module deinit. This macro must be used in
128 * conjunction with the @ref HAL_TIMEOUT_INIT macro
129 */
130 #define HAL_TIMEOUT_DEINIT() hal_dwt_disable()
131 /** @} */
132
133 /** @addtogroup HAL_DELAY_FUNCTIONS Functions
134 * @{
135 */
136 /**
137 ****************************************************************************************
138 * @brief Function for delaying execution for number of us.
139 * @note GR55xxx is based on ARM Cortex-M4, and this fuction is based on Data Watchpoint and Trace (DWT) unit so delay is precise.
140 * @param number_of_us: The maximum delay time is about 67 seconds in 64M system clock.
141 * The faster the system clock, the shorter the maximum delay time.
142 ****************************************************************************************
143 */
144 __STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
145 {
146 const uint8_t clocks[] = {64, 48, 16, 24, 16, 32};
147 uint32_t cycles = number_of_us * (clocks[AON->PWR_RET01 & AON_PWR_REG01_SYS_CLK_SEL]);
148
149 if (number_of_us == 0)
150 {
151 return;
152 }
153
154 HAL_TIMEOUT_INIT();
155
156 // Get start value of the cycle counter.
157 uint32_t cyccnt_initial = DWT->CYCCNT;
158
159 // Wait time end
160 while ((DWT->CYCCNT - cyccnt_initial) < cycles)
161 {}
162
163 HAL_TIMEOUT_DEINIT();
164 }
165 /** @} */
166 #endif
167
168 #ifndef DELAY_US_DWT
169
170 #if defined ( __CC_ARM )
171
172 #pragma push
173 #pragma O2
174 /** @addtogroup HAL_DELAY_FUNCTIONS Functions
175 * @{
176 */
177 /**
178 ****************************************************************************************
179 * @brief Function for delaying execution for number of us.
180 * @note GR55xxx is based on ARM Cortex-M4, and this fuction is based on Data Watchpoint and Trace (DWT) unit so delay is precise.
181 * @param number_of_us: The maximum delay time is about 67 seconds in 64M system clock.
182 * The faster the system clock, the shorter the maximum delay time.
183 ****************************************************************************************
184 */
185 __STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
186 {
187 uint32_t pc = (unsigned int)__current_pc();
188 uint8_t clocks[] = {64, 48, 16, 24, 16, 32};
189
190 if (number_of_us == 0)
191 {
192 return;
193 }
194
195 static const uint16_t delay_ramcode[] = {
196 0x3809, // SUBS r0, #9
197 0xd8fd, // BHI .-2
198 0x4770 // BX LR
199 };
200 // Set LSB to 1 to execute code in Thumb mode.
201 const delay_func_t delay_ram_cycles = (delay_func_t)((((uint32_t)delay_ramcode) | 1));
202
203 static const uint16_t delay_flashcode[] = {
204 0x3803, // SUBS r0, #3
205 0xd8fd, // BHI .-2
206 0x4770 // BX LR
207 };
208 // Set LSB to 1 to execute code in Thumb mode.
209 const delay_func_t delay_flash_cycles = (delay_func_t)((((uint32_t)delay_flashcode) | 1));
210
211 static const uint16_t delay_aliascode[] = {
212 0x3803, // SUBS r0, #3
213 0xd8fd, // BHI .-2
214 0x4770 // BX LR
215 };
216 // Set LSB to 1 to execute code in Thumb mode.
217 const delay_func_t delay_alias_cycles = (delay_func_t)((((uint32_t)delay_aliascode) | 1));
218
219 uint32_t cycles = number_of_us * (clocks[AON->PWR_RET01 & AON_PWR_REG01_SYS_CLK_SEL]);
220
221 if(pc & GR55XX_RAM_ADDRESS)
222 delay_ram_cycles(cycles);
223 else if(pc & GR55XX_FLASH_ADDRESS)
224 delay_flash_cycles(cycles);
225 else if(pc & GR55XX_ALIAS_ADDRESS)
226 delay_alias_cycles(cycles);
227 else
228 {
229 cycles = cycles / 4;
230 __asm
231 {
232 loop:
233 NOP
234 SUBS cycles, #1
235 BNE loop
236 }
237 }
238 }
239 #pragma pop
240
241 #elif defined ( _WIN32 ) || defined ( __unix ) || defined ( __APPLE__ )
242
243 #ifndef CUSTOM_DELAY_US
244 /**
245 ****************************************************************************************
246 * @brief Function for delaying execution for number of us.
247 * @param number_of_us: The maximum delay time is about 67 seconds in 64M system clock.
248 * The faster the system clock, the shorter the maximum delay time.
249 ****************************************************************************************
250 */
251 __STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
252 {
253 }
254 #endif
255
256 #elif defined ( __GNUC__ ) || ( __ICCARM__ )
257 /**
258 ****************************************************************************************
259 * @brief Function for delaying execution for number of us.
260 * @param number_of_us: The maximum delay time is about 67 seconds in 64M system clock.
261 * The faster the system clock, the shorter the maximum delay time.
262 ****************************************************************************************
263 */
264 __STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
265 {
266 uint8_t clocks[] = {64, 48, 16, 24, 16, 32};
267
268 if (number_of_us)
269 {
270 uint32_t cycles;
271 cycles = number_of_us*(clocks[AON->PWR_RET01 & AON_PWR_REG01_SYS_CLK_SEL])/6;
272 __asm__ volatile ("1:\n"
273 "NOP\n"
274 "NOP\n"
275 "NOP\n"
276 "SUBS %[cycles], %[cycles], #1\n"
277 "BNE.N 1b\n"
278 : [cycles] "=r" (cycles)
279 : "[cycles]" "r" (cycles)
280 );
281 }
282 }
283 /** @} */
284 #endif
285
286 #endif
287
288 /** @addtogroup HAL_DELAY_FUNCTIONS Functions
289 * @{
290 */
291 /**
292 * @brief Function for delaying execution for number of milliseconds.
293 *
294 * @note GR55xx is based on ARM Cortex-M4, and this fuction is based on Data Watchpoint and Trace (DWT) unit so delay is precise.
295 *
296 * @note Function internally calls @ref delay_us so the maximum delay is the
297 * same as in case of @ref delay_us.
298 *
299 * @param number_of_ms: The maximum delay time is about 67 seconds in 64M system clock.
300 * The faster the system clock, the shorter the maximum delay time.
301 *
302 */
303 __STATIC_FORCEINLINE void delay_ms(uint32_t number_of_ms)
304 {
305 delay_us(1000 * number_of_ms);
306 return;
307 }
308 /** @} */
309
310 #ifdef __cplusplus
311 }
312 #endif
313
314 #endif /* __GR55xx_DELAY_H__ */
315 /** @} */
316 /** @} */
317 /** @} */
318
hal_dwt_disable
void hal_dwt_disable(void)
Disable the DWT.
HAL_TIMEOUT_INIT
#define HAL_TIMEOUT_INIT()
Timeout module init.
Definition: gr55xx_delay.h:124
delay_ms
__STATIC_FORCEINLINE void delay_ms(uint32_t number_of_ms)
Function for delaying execution for number of milliseconds.
Definition: gr55xx_delay.h:303
delay_us
__STATIC_FORCEINLINE void delay_us(uint32_t number_of_us)
Function for delaying execution for number of us.
Definition: gr55xx_delay.h:144
__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:130
hal_dwt_enable
void hal_dwt_enable(void)
Enable the DWT.