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 
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 
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. This macro must be used in conjunction with the HAL_TIMEOUT_DEINIT macro.
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
Definition: gr55xx_delay.h:79
HAL_TIMEOUT_DEINIT
#define HAL_TIMEOUT_DEINIT()
Timeout module deinit. This macro must be used in conjunction with the HAL_TIMEOUT_INIT macro.
Definition: gr55xx_delay.h:137