1 /***********************************************************************************************************************
2 * Copyright [2020-2024] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved.
3 *
4 * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only
5 * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized.
6 * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for
7 * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any
8 * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including
9 * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation.
10 * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND
11 * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY,
12 * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE
13 * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH.
14 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR
15 * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER,
16 * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY
17 * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE
18 * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS.
19 **********************************************************************************************************************/
20
21 /***********************************************************************************************************************
22 * Includes <System Includes> , "Project Includes"
23 **********************************************************************************************************************/
24 #include "bsp_api.h"
25 #include "bsp_delay.h"
26
27 /***********************************************************************************************************************
28 * Macro definitions
29 **********************************************************************************************************************/
30 #define BSP_DELAY_NS_PER_SECOND (1000000000)
31 #define BSP_DELAY_NS_PER_US (1000)
32 #define BSP_DELAY_SIGNIFICANT_DIGITS (10000)
33
34 /***********************************************************************************************************************
35 * Typedef definitions
36 **********************************************************************************************************************/
37
38 /***********************************************************************************************************************
39 * Exported global variables (to be accessed by other files)
40 **********************************************************************************************************************/
41
42 /***********************************************************************************************************************
43 * Private global variables and functions
44 **********************************************************************************************************************/
45
46 /*******************************************************************************************************************//**
47 * @addtogroup BSP_MCU
48 * @{
49 **********************************************************************************************************************/
50
51 /*******************************************************************************************************************//**
52 * Delay for at least the specified duration in units and return.
53 * @param[in] delay The number of 'units' to delay.
54 * @param[in] units The 'base' (bsp_delay_units_t) for the units specified. Valid values are:
55 * BSP_DELAY_UNITS_SECONDS, BSP_DELAY_UNITS_MILLISECONDS, BSP_DELAY_UNITS_MICROSECONDS.@n
56 * For example:@n
57 * At 200 MHz one cycle takes 1/200 microsecond or 5 nanoseconds.@n
58 * At 800 MHz one cycle takes 1/800 microsecond or 1.25 nanoseconds.@n
59 * Therefore one run through bsp_prv_software_delay_loop() takes:
60 * ~ (1.25 * BSP_DELAY_LOOP_CYCLES) or 5 ns.
61 * A delay of 2 us therefore requires 2000ns/5ns or 400 loops.
62 *
63 * The 'theoretical' maximum delay that may be obtained is determined by a full 32 bit loop count and the system clock rate.
64 * @200MHz: ((0xFFFFFFFF loops * 4 cycles /loop) / 200000000) = 85 seconds.
65 * @800MHz: ((0xFFFFFFFF loops * 4 cycles /loop) / 800000000) = 21 seconds.
66 *
67 * Note that requests for very large delays will be affected by rounding in the calculations and the actual delay
68 * achieved may be slightly longer. @200 MHz, for example, a request for 85 seconds will be closer to 86 seconds.
69 *
70 * Note also that if the calculations result in a loop_cnt of zero, the bsp_prv_software_delay_loop() function is not called
71 * at all. In this case the requested delay is too small (nanoseconds) to be carried out by the loop itself, and the
72 * overhead associated with executing the code to just get to this point has certainly satisfied the requested delay.
73 *
74 *
75 * @note R_BSP_SoftwareDelay() obtains the system clock value by reading the SystemCoreClock variable.
76 * Therefore, R_BSP_SoftwareDelay() cannot be used until after the SystemCoreClock has been updated.
77 * The SystemCoreClock is updated by executing SystemCoreClockUpdate() in startup;
78 * users cannot call R_BSP_SoftwareDelay() inside R_BSP_WarmStart(BSP_WARM_START_RESET) and
79 * R_BSP_WarmStart(BSP_WARM_START_POST_CLOCK) since they are invoked before SystemCoreClockUpdate() in startup.
80 *
81 * @note This function will delay for **at least** the specified duration. Due to overhead in calculating the correct number
82 * of loops to delay, very small delay values (generally 1-5 microseconds) may be significantly longer than specified.
83 * Approximate overhead for this function is as follows:
84 * - CR52: 87-94 cycles
85 *
86 * @note If more accurate microsecond timing must be performed in software it is recommended to use
87 * bsp_prv_software_delay_loop() directly. In this case, use BSP_DELAY_LOOP_CYCLES or BSP_DELAY_LOOPS_CALCULATE()
88 * to convert a calculated delay cycle count to a number of software delay loops.
89 *
90 * @note Delays may be longer than expected when compiler optimization is turned off.
91 **********************************************************************************************************************/
92
R_BSP_SoftwareDelay(uint32_t delay,bsp_delay_units_t units)93 void R_BSP_SoftwareDelay (uint32_t delay, bsp_delay_units_t units)
94 {
95 uint32_t cpu_hz;
96 uint32_t cycles_requested;
97 uint32_t ns_per_cycle;
98 uint32_t loops_required = 0;
99 uint32_t total_us = (delay * units); /** Convert the requested time to microseconds. */
100 uint64_t ns_64bits;
101
102 cpu_hz = SystemCoreClock; /** Get the system clock frequency in Hz. */
103
104 /* BSP_DELAY_SIGNIFICANT_DIGITS to keep the decimal point. */
105 ns_per_cycle = BSP_DELAY_NS_PER_SECOND / (cpu_hz / BSP_DELAY_SIGNIFICANT_DIGITS); /** Get the # of nanoseconds/cycle. */
106
107 /* 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 */
108 /* division as that pulls in a division library. */
109 ns_64bits = (uint64_t) total_us * (uint64_t) BSP_DELAY_NS_PER_US; // Convert to ns.
110
111 /* Have we overflowed 32 bits? */
112 if (ns_64bits <= UINT32_MAX)
113 {
114 ns_64bits = ns_64bits * (uint64_t) BSP_DELAY_SIGNIFICANT_DIGITS;
115
116 /* No, we will not overflow.
117 * Multiply the calculation result by BSP_DELAY_SIGNIFICANT_DIGITS to disable the retention of the decimal point.*/
118 cycles_requested = (uint32_t) (ns_64bits / (uint64_t) ns_per_cycle);
119 loops_required = cycles_requested / BSP_DELAY_LOOP_CYCLES;
120 }
121 else
122 {
123 /* We did overflow. Try dividing down first.
124 * Multiply the calculation result by BSP_DELAY_SIGNIFICANT_DIGITS to disable the retention of the decimal point.*/
125 total_us = (total_us / (ns_per_cycle * BSP_DELAY_LOOP_CYCLES)) * BSP_DELAY_SIGNIFICANT_DIGITS;
126 ns_64bits = (uint64_t) total_us * (uint64_t) BSP_DELAY_NS_PER_US; // Convert to ns.
127
128 /* Have we overflowed 32 bits? */
129 if (ns_64bits <= UINT32_MAX)
130 {
131 /* No, we will not overflow. */
132 loops_required = (uint32_t) ns_64bits;
133 }
134 else
135 {
136 /* We still overflowed, use the max count for cycles */
137 loops_required = UINT32_MAX;
138 }
139 }
140
141 /** Only delay if the supplied parameters constitute a delay. */
142 if (loops_required > (uint32_t) 0)
143 {
144 bsp_prv_software_delay_loop(loops_required);
145 }
146 }
147
148 /** @} (end addtogroup BSP_MCU) */
149
150 /*******************************************************************************************************************//**
151 * This assembly language routine takes roughly 4 cycles per loop. 2 additional cycles
152 * occur when the loop exits. The 'naked' attribute indicates that the specified function does not need
153 * prologue/epilogue sequences generated by the compiler.
154 * @param[in] loop_cnt The number of loops to iterate.
155 **********************************************************************************************************************/
bsp_prv_software_delay_loop(uint32_t loop_cnt)156 void bsp_prv_software_delay_loop (uint32_t loop_cnt)
157 {
158 r_bsp_software_delay_loop(loop_cnt);
159 }
160