xref: /btstack/port/renesas-tb-s1ja-cc256x/template/btstack_example/synergy/ssp/src/bsp/mcu/all/bsp_delay.c (revision 3b5c872a8c45689e8cc17891f01530f5aa5e911c)
1 /***********************************************************************************************************************
2  * Copyright [2015-2017] Renesas Electronics Corporation and/or its licensors. All Rights Reserved.
3  *
4  * This file is part of Renesas SynergyTM Software Package (SSP)
5  *
6  * The contents of this file (the "contents") are proprietary and confidential to Renesas Electronics Corporation
7  * and/or its licensors ("Renesas") and subject to statutory and contractual protections.
8  *
9  * This file is subject to a Renesas SSP license agreement. Unless otherwise agreed in an SSP license agreement with
10  * Renesas: 1) you may not use, copy, modify, distribute, display, or perform the contents; 2) you may not use any name
11  * or mark of Renesas for advertising or publicity purposes or in connection with your use of the contents; 3) RENESAS
12  * MAKES NO WARRANTY OR REPRESENTATIONS ABOUT THE SUITABILITY OF THE CONTENTS FOR ANY PURPOSE; THE CONTENTS ARE PROVIDED
13  * "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT; AND 4) RENESAS SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, OR
15  * CONSEQUENTIAL DAMAGES, INCLUDING DAMAGES RESULTING FROM LOSS OF USE, DATA, OR PROJECTS, WHETHER IN AN ACTION OF
16  * CONTRACT OR TORT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE CONTENTS. Third-party contents
17  * included in this file may be subject to different terms.
18  **********************************************************************************************************************/
19 /***********************************************************************************************************************
20 * File Name    : bsp_delay.c
21 * Description  : Implements a software delay function, common to all BSPs.
22 ***********************************************************************************************************************/
23 
24 /***********************************************************************************************************************
25 Includes   <System Includes> , "Project Includes"
26 ***********************************************************************************************************************/
27 #include "bsp_api.h"
28 #include "bsp_delay.h"
29 /***********************************************************************************************************************
30 Macro definitions
31 ***********************************************************************************************************************/
32 #define DELAY_LOOP_CYCLES 4     ///< 4 cycles per loop.
33 
34 #if defined(__ICCARM__)
35 #define BSP_ATTRIBUTE_STACKLESS __stackless
36 #elif defined(__GNUC__)
37 /*LDRA_INSPECTED 293 S */
38 #define BSP_ATTRIBUTE_STACKLESS __attribute__((naked))
39 #endif
40 
41 /***********************************************************************************************************************
42 Typedef definitions
43 ***********************************************************************************************************************/
44 
45 /***********************************************************************************************************************
46 Private function prototypes
47 ***********************************************************************************************************************/
48 
49 /***********************************************************************************************************************
50 Exported global variables (to be accessed by other files)
51 ***********************************************************************************************************************/
52 
53 /***********************************************************************************************************************
54 Private global variables and functions
55 ***********************************************************************************************************************/
56 
57 static void software_delay_loop (uint32_t loop_cnt);
58 
59 /*******************************************************************************************************************//**
60  * @addtogroup BSP_MCU_DELAY
61  * @{
62 ***********************************************************************************************************************/
63 
64 /*******************************************************************************************************************//**
65 * @brief       Delay the specified duration in units and return.
66 * @param[in]   delay  The number of 'units' to delay.
67 * @param[in]   units  The 'base' (bsp_delay_units_t) for the units specified. Valid values are:
68 *              BSP_DELAY_UNITS_SECONDS, BSP_DELAY_UNITS_MILLISECONDS, BSP_DELAY_UNITS_MICROSECONDS.@n
69 *              For example:@n
70 *              At 1 MHz one cycle takes 1 microsecond (.000001 seconds).@n
71 *              At 12 MHz one cycle takes 1/12 microsecond or 83 nanoseconds.@n
72 *              Therefore one run through software_delay_loop() takes:
73 *              ~ (83 * DELAY_LOOP_CYCLES) or 332 ns.
74 *              A delay of 2 us therefore requires 2000ns/332ns or 6 loops.
75 *
76 *              The 'theoretical' maximum delay that may be obtained is determined by a full 32 bit loop count and the system clock rate.
77 *              @240MHz:  ((0xFFFFFFFF loops * 4 cycles /loop) / 240000000) = 71 seconds.
78 *              @32MHz:  ((0xFFFFFFFF loops * 4 cycles /loop) / 32000000) = 536 seconds
79 *
80 *              Note that requests for very large delays will be affected by rounding in the calculations and the actual delay
81 *              achieved may be slightly less. @32 MHz, for example, a request for 532 seconds will be closer to 536 seconds.
82 *
83 *              Note also that if the calculations result in a loop_cnt of zero, the software_delay_loop() function is not called
84 *              at all. In this case the requested delay is too small (nanoseconds) to be carried out by the loop itself, and the
85 *              overhead associated with executing the code to just get to this point has certainly satisfied the requested delay.
86 *
87 *
88 * @note This function calls bsp_cpu_clock_get() which ultimately calls R_CGC_SystemClockFreqGet() and therefore requires
89 *       that the BSP has already initialized the CGC (which it does as part of the Sysinit).
90 *       Care should be taken to ensure this remains the case if in the future this function were to be called as part
91 *       of the BSP initialization.
92 * @retval        None.
93 ***********************************************************************************************************************/
94 
R_BSP_SoftwareDelay(uint32_t delay,bsp_delay_units_t units)95 void R_BSP_SoftwareDelay(uint32_t delay, bsp_delay_units_t units)
96 {
97     uint32_t iclk_hz;
98     uint32_t cycles_requested;
99     uint32_t ns_per_cycle;
100     uint32_t loops_required = 0;
101     uint32_t total_us = (delay * units);  /** Convert the requested time to microseconds. */
102     uint64_t ns_64bits;
103 
104     iclk_hz = bsp_cpu_clock_get();        /** Get the system clock frequency in Hz. */
105 
106     /* Running on the Sub-clock (32768 Hz) there are 30517 ns/cycle. This means one cycle takes 31 us. One execution
107      * loop of the delay_loop takes 6 cycles which at 32768 Hz is 180 us. That does not include the overhead below prior to even getting
108      * to the delay loop. Given this, at this frequency anything less then a delay request of 122 us will not even generate a single
109      * pass through the delay loop.  For this reason small delays (<=~200 us) at this slow clock rate will not be possible and such a request
110      * will generate a minimum delay of ~200 us.*/
111 
112      ns_per_cycle = (1000000000)/iclk_hz;            /** Get the # of nanoseconds/cycle. */
113 
114      /* We want to get the time in total nanoseconds but need to be conscious of overflowing 32 bits. We also do not want to do 64 bit */
115      /* division as that pulls in a division library. */
116      ns_64bits = (uint64_t)total_us * (uint64_t)1000;      // Convert to ns.
117 
118      /* Have we overflowed 32 bits? */
119      if (ns_64bits <= 0xFFFFFFFFUL)
120      {
121          /* No, we will not overflow. */
122          cycles_requested =  ((uint32_t)ns_64bits / ns_per_cycle);
123          loops_required = cycles_requested / DELAY_LOOP_CYCLES;
124      }
125      else
126      {
127          /* We did overflow. Try dividing down first. */
128          total_us = (total_us / (ns_per_cycle * DELAY_LOOP_CYCLES));
129          ns_64bits = (uint64_t)total_us * (uint64_t)1000;      // Convert to ns.
130 
131          /* Have we overflowed 32 bits? */
132           if (ns_64bits <= 0xFFFFFFFFUL)
133           {
134               /* No, we will not overflow. */
135               loops_required =  (uint32_t)ns_64bits;
136           }
137           else
138           {
139               /* We still overflowed, use the max count for cycles */
140               loops_required =  0xFFFFFFFFUL;
141           }
142      }
143 
144      /** Only delay if the supplied parameters constitute a delay. */
145      if (loops_required > (uint32_t)0)
146      {
147          software_delay_loop(loops_required);
148      }
149 }
150 
151 
152 
153 /*******************************************************************************************************************//**
154 * @brief This assembly language routine takes roughly 4 cycles per loop. 2 additional cycles
155 *        occur when the loop exits. The 'naked' attribute  indicates that the specified function does not need
156 *        prologue/epilogue sequences generated by the compiler.
157 * @param[in]     loop_cnt  The number of loops to iterate.
158 * @retval        None.
159 ***********************************************************************************************************************/
software_delay_loop(uint32_t loop_cnt)160 BSP_ATTRIBUTE_STACKLESS static void software_delay_loop (uint32_t loop_cnt)
161 {
162         __asm volatile ("sw_delay_loop:         \n"
163 
164 #if defined(__ICCARM__)
165                         "   subs r0, #1         \n"     ///< 1 cycle
166 #elif defined(__GNUC__)
167                         "   sub r0, r0, #1      \n"     ///< 1 cycle
168 #endif
169 
170                         "   cmp r0, #0          \n"		///< 1 cycle
171 /* CM0 and ARMv8MBL (CM23) have a different instruction set */
172 #if defined(__CORE_CM0PLUS_H_GENERIC) || defined(__CORE_ARMV8MBL_H_GENERIC)
173                         "   bne sw_delay_loop   \n"		///< 2 cycles
174 #else
175                         "   bne.n sw_delay_loop \n"		///< 2 cycles
176 #endif
177                         "   bx lr               \n");	///< 2 cycles
178 
179     /** loop_cnt is used but since it is used in assembly an unused parameter warning can be generated. */
180     SSP_PARAMETER_NOT_USED(loop_cnt);
181 }
182 
183 /** @} (end addtogroup BSP_MCU_COMMON) */
184