1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /***********************************************************************************************************************
8 * Includes <System Includes> , "Project Includes"
9 **********************************************************************************************************************/
10 #include "bsp_api.h"
11 #include "bsp_delay.h"
12
13 /***********************************************************************************************************************
14 * Macro definitions
15 **********************************************************************************************************************/
16 #define BSP_DELAY_UNIT_CONV_S_TO_NS (1000000000)
17 #define BSP_DELAY_UNIT_CONV_US_TO_NS (1000)
18
19 /***********************************************************************************************************************
20 * Typedef definitions
21 **********************************************************************************************************************/
22
23 /***********************************************************************************************************************
24 * Private function prototypes
25 **********************************************************************************************************************/
26
27 /***********************************************************************************************************************
28 * Exported global variables (to be accessed by other files)
29 **********************************************************************************************************************/
30
31 /***********************************************************************************************************************
32 * Private global variables and functions
33 **********************************************************************************************************************/
34
35 /*******************************************************************************************************************//**
36 * @addtogroup BSP_MCU
37 * @{
38 **********************************************************************************************************************/
39
40 /*******************************************************************************************************************//**
41 * Delay for at least the specified duration in units and return. This function shouldn't be used to
42 * generate an accurate delay time. A running time of the function is depending on the region of memory
43 * where the function is excuted on and a frequency of the CPU clock.
44 *
45 * The funcion calls bsp_prv_software_delay_loop() which loops over the requested delay time.
46 * One loop time through bsp_prv_software_delay_loop() takes roughly 500ns. This value is based on the
47 * actual measured time in the condition that a frequency of the CPU clock is 200MHz and the code is
48 * excuted on DDR3L-1333 DRAM(133MHz).
49 * One loop running time of software_delay_loop() can be modified by redefining BSP_DELAY_LOOP_CYCLES.
50 *
51 * @param[in] delay The number of 'units' to delay.
52 * @param[in] units The 'base' (bsp_delay_units_t) for the units specified. Valid values are:
53 * BSP_DELAY_UNITS_SECONDS, BSP_DELAY_UNITS_MILLISECONDS, BSP_DELAY_UNITS_MICROSECONDS.@n
54 * For example:@n
55 * One run through bsp_prv_software_delay_loop() takes roughly 500ns.
56 * A delay of 100 us therefore requires 100000ns/500ns -> 200 loops.
57 *
58 * The 'theoretical' maximum delay that may be obtained is determined by a full 32 bit loop count and the
59 * system clock rate.
60 * @200MHz: ((0xFFFFFFFF loops * 500ns) = 2147 seconds.
61 *
62 * Note that requests for very large delays will be affected by rounding in the calculations and the
63 * actual delay achieved may be slightly off of a setting time.
64 *
65 * Note also that if the calculations result in a loop_cnt of zero, the bsp_prv_software_delay_loop()
66 * function is not called at all. In this case the requested delay is too small (nanoseconds) to be
67 * carried out by the loop itself, and the overhead associated with executing the code to just get to this
68 * point has certainly satisfied the requested delay.
69 *
70 * @note This function uses SystemCoreClock and therefore requires that the BSP has already initialized the variable
71 * (which it does as part of the SystemInit).
72 * Care should be taken to ensure this remains the case if in the future this function were to be called as part
73 * of the BSP initialization.
74 **********************************************************************************************************************/
75
R_BSP_SoftwareDelay(uint32_t delay,bsp_delay_units_t units)76 void R_BSP_SoftwareDelay (uint32_t delay, bsp_delay_units_t units)
77 {
78 uint32_t iclk_hz;
79 uint32_t cycles_requested;
80 uint32_t us_per_cycle;
81 uint32_t loops_required = 0;
82 uint32_t total_us = (delay * units);
83 uint64_t ns_64bits;
84
85 iclk_hz = SystemCoreClock;
86 us_per_cycle = BSP_DELAY_UNIT_CONV_S_TO_NS / (iclk_hz / BSP_DELAY_UNIT_CONV_US_TO_NS);
87 ns_64bits = (uint64_t) total_us * (uint64_t) BSP_DELAY_UNIT_CONV_US_TO_NS;
88
89 /* Have we overflowed 32 bits? */
90 if (ns_64bits <= UINT32_MAX)
91 {
92 /* No, we will not overflow. */
93 cycles_requested = (((uint32_t) ns_64bits / us_per_cycle) * BSP_DELAY_UNIT_CONV_US_TO_NS);
94 loops_required = cycles_requested / BSP_DELAY_LOOP_CYCLES;
95 }
96 else
97 {
98 /* We did overflow. Try dividing down first. */
99 total_us = (total_us / ((us_per_cycle * BSP_DELAY_LOOP_CYCLES) / BSP_DELAY_UNIT_CONV_US_TO_NS));
100 ns_64bits = (uint64_t) total_us * (uint64_t) BSP_DELAY_UNIT_CONV_US_TO_NS; // Convert to ns.
101
102 /* Have we overflowed 32 bits? */
103 if (ns_64bits <= UINT32_MAX)
104 {
105 /* No, we will not overflow. */
106 loops_required = (uint32_t) ns_64bits;
107 }
108 else
109 {
110 /* We still overflowed, use the max count for cycles */
111 loops_required = UINT32_MAX;
112 }
113 }
114
115 /** Only delay if the supplied parameters constitute a delay. */
116 if (loops_required > (uint32_t) 0)
117 {
118 bsp_prv_software_delay_loop(loops_required);
119 }
120 }
121
122 /** @} (end addtogroup BSP_MCU) */
123
124 /*******************************************************************************************************************//**
125 * This assembly language routine takes roughly 500ns per one loop.
126 * The 'naked' attribute indicates that the specified function does not need prologue/epilogue sequences
127 * generated by the compiler.
128 * @param[in] loop_cnt The number of loops to iterate.
129 **********************************************************************************************************************/
bsp_prv_software_delay_loop(uint32_t loop_cnt)130 BSP_ATTRIBUTE_STACKLESS void bsp_prv_software_delay_loop (__attribute__((unused)) uint32_t loop_cnt)
131 {
132 __asm volatile ("sw_delay_loop: \n"
133
134 #if defined(__ICCARM__) || defined(__ARMCC_VERSION)
135 " subs r0, #1 \n"
136 #elif defined(__GNUC__)
137 " sub r0, r0, #1 \n"
138 #endif
139 " cmp r0, #0 \n"
140
141 " bne.n sw_delay_loop \n"
142
143 " bx lr \n");
144 }
145