1 //*****************************************************************************
2 //
3 //! @file am_hal_utils.c
4 //!
5 //! @brief HAL Utility Functions
6 //!
7 //! @addtogroup utils4_4p Utils - HAL Utility Functions
8 //! @ingroup apollo4p_hal
9 //! @{
10 //
11 //*****************************************************************************
12
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_4_4_0-3c5977e664 of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51 #include "am_hal_bootrom_helper.h"
52
53 //*****************************************************************************
54 //
55 //! Mode - the result of a change request.
56 //
57 //*****************************************************************************
58 typedef enum
59 {
60 AM_HAL_BURST_MODE,
61 AM_HAL_NORMAL_MODE,
62 } am_hal_burst_mode_e;
63
64 //*****************************************************************************
65 //
66 //! @brief Return current burst mode state
67 //!
68 //! Implemented as a macro, this function returns the current burst mode state.
69 //! AM_HAL_BURST_MODE
70 //! AM_HAL_NORMAL_MODE
71 //
72 //*****************************************************************************
73 #define am_hal_burst_mode_status() AM_HAL_NORMAL_MODE
74
75 //*****************************************************************************
76 //
77 //! @brief Given an integer number of microseconds, convert to a value representing
78 //! the number of cycles that will provide that amount
79 //! of delay. This macro is designed to take into account some of the call
80 //! overhead and latencies.
81 //! The BOOTROM_CYCLES_US macro assumes:
82 //! - Burst or normal mode operation.
83 //! - If cache is not enabled, use BOOTROM_CYCLES_US_NOCACHE() instead.
84 //!
85 //! @name BootROM_CYCLES
86 //! @{
87 //
88 //*****************************************************************************
89 #define CYCLESPERITER (AM_HAL_CLKGEN_FREQ_MAX_MHZ / 3)
90 #define BOOTROM_CYCLES_US(n) (((n) * CYCLESPERITER) + 0)
91 #define BOOTROM_CYCLES_US_NOCACHE(n) ( (n == 0) ? 0 : (n * CYCLESPERITER) - 5)
92 //! @}
93
94 //*****************************************************************************
95 //
96 // Use the bootrom to implement a spin loop.
97 //
98 //*****************************************************************************
99 void
am_hal_delay_us(uint32_t ui32us)100 am_hal_delay_us(uint32_t ui32us)
101 {
102
103 register uint32_t ui32Iterations = BOOTROM_CYCLES_US(ui32us);
104 register uint32_t ui32CycleCntAdj;
105
106 //
107 // Check for LP (96MHz) vs. HP (192MHz) mode and create the adjustment accordingly.
108 //
109 if (PWRCTRL->MCUPERFREQ_b.MCUPERFSTATUS == AM_HAL_PWRCTRL_MCU_MODE_HIGH_PERFORMANCE)
110 {
111 ui32Iterations <<= 1;
112
113 //
114 // There's an additional shift to account for.
115 //
116 ui32CycleCntAdj = ((13 * 2) + 37) / 3;
117 }
118 else
119 {
120 ui32CycleCntAdj = ((13 * 1) + 32) / 3;
121 }
122
123 //
124 // Allow for the overhead of the burst-mode check and these comparisons
125 // by eliminating an appropriate number of iterations.
126 //
127 if ( ui32Iterations > ui32CycleCntAdj )
128 {
129 ui32Iterations -= ui32CycleCntAdj;
130
131 g_am_hal_bootrom_helper.bootrom_delay_cycles(ui32Iterations);
132 }
133
134 } // am_hal_delay_us()
135
136 //*****************************************************************************
137 //
138 // Delays for a desired amount of cycles while also waiting for a
139 // status to change a value.
140 //
141 //*****************************************************************************
142 uint32_t
am_hal_delay_us_status_change(uint32_t ui32usMaxDelay,uint32_t ui32Address,uint32_t ui32Mask,uint32_t ui32Value)143 am_hal_delay_us_status_change(uint32_t ui32usMaxDelay, uint32_t ui32Address,
144 uint32_t ui32Mask, uint32_t ui32Value)
145 {
146 while ( 1 )
147 {
148 //
149 // Check the status
150 //
151 if ( ( AM_REGVAL(ui32Address) & ui32Mask ) == ui32Value )
152 {
153 return AM_HAL_STATUS_SUCCESS;
154 }
155
156 if (ui32usMaxDelay--)
157 {
158 //
159 // Call the BOOTROM cycle function to delay for about 1 microsecond.
160 //
161 am_hal_delay_us(1);
162 }
163 else
164 {
165 break;
166 }
167 }
168
169 return AM_HAL_STATUS_TIMEOUT;
170
171 } // am_hal_delay_us_status_change()
172
173 //*****************************************************************************
174 //
175 // Delays for a desired amount of cycles while also waiting for a
176 // status to equal OR not-equal to a value.
177 //
178 //*****************************************************************************
179 uint32_t
am_hal_delay_us_status_check(uint32_t ui32usMaxDelay,uint32_t ui32Address,uint32_t ui32Mask,uint32_t ui32Value,bool bIsEqual)180 am_hal_delay_us_status_check(uint32_t ui32usMaxDelay, uint32_t ui32Address,
181 uint32_t ui32Mask, uint32_t ui32Value,
182 bool bIsEqual)
183 {
184 while ( 1 )
185 {
186 //
187 // Check the status
188 //
189 if ( bIsEqual )
190 {
191 if ( ( AM_REGVAL(ui32Address) & ui32Mask ) == ui32Value )
192 {
193 return AM_HAL_STATUS_SUCCESS;
194 }
195 }
196 else
197 {
198 if ( ( AM_REGVAL(ui32Address) & ui32Mask ) != ui32Value )
199 {
200 return AM_HAL_STATUS_SUCCESS;
201 }
202 }
203
204 if ( ui32usMaxDelay-- )
205 {
206 //
207 // Call the BOOTROM cycle function to delay for about 1 microsecond.
208 //
209 am_hal_delay_us(1);
210 }
211 else
212 {
213 break;
214 }
215 }
216
217 return AM_HAL_STATUS_TIMEOUT;
218
219 } // am_hal_delay_us_status_check()
220
221 //*****************************************************************************
222 //
223 // Read a uint32 value from a valid memory or peripheral location.
224 //
225 //*****************************************************************************
226 uint32_t
am_hal_load_ui32(uint32_t * pui32Address)227 am_hal_load_ui32(uint32_t *pui32Address)
228 {
229 return g_am_hal_bootrom_helper.bootrom_util_read_word(pui32Address);
230 } // am_hal_load_ui32()
231
232 //*****************************************************************************
233 //
234 // Use the bootrom to write to a location in SRAM or the system bus.
235 //
236 //*****************************************************************************
237 void
am_hal_store_ui32(uint32_t * pui32Address,uint32_t ui32Data)238 am_hal_store_ui32(uint32_t *pui32Address, uint32_t ui32Data)
239 {
240 g_am_hal_bootrom_helper.bootrom_util_write_word(pui32Address, ui32Data);
241 } // am_hal_store_ui32()
242
243 //*****************************************************************************
244 //
245 // End Doxygen group.
246 //! @}
247 //
248 //*****************************************************************************
249