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 
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 
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.