1 //*****************************************************************************
2 //
3 //! @file am_hal_access.c
4 //!
5 //! @brief This file controls peripheral access in Apollo4.
6 //!
7 //! @addtogroup access_4p Access - Peripheral Access
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
52 //*****************************************************************************
53 //
54 // Global definitions.
55 //
56 //*****************************************************************************
57
58 //
59 //! @brief Access State Struct
60 //
61 typedef struct
62 {
63 const am_hal_access_t *psGlobalAccess;
64 const uint32_t *Allowed;
65 uint32_t *Claimed;
66 }
67 am_hal_access_state_t;
68
69 //*****************************************************************************
70 //
71 //! @name Helper macros for finding the right bit in an access structure.
72 //! @{
73 //
74 //*****************************************************************************
75 #define AM_HAL_ACCESS_ALLOWED(psAccessStruct, ePeriph) \
76 ((bool) (psAccessStruct->Allowed[ePeriph >> 5] & (1 << (ePeriph & 0x1F))))
77
78 #define AM_HAL_ACCESS_CLAIMED(psAccessStruct, ePeriph) \
79 ((bool) (psAccessStruct->Claimed[ePeriph >> 5] & (1 << (ePeriph & 0x1F))))
80
81 #define AM_HAL_ACCESS_SHARED(psAccess, ePeriph) \
82 ((bool) (psAccess->psGlobalAccess->pui32Shared[ePeriph >> 5] & \
83 (1 << (ePeriph & 0x1F))))
84
85 #define AM_HAL_ACCESS_AVAILABLE(psAccess, ePeriph) \
86 (((psAccess->psGlobalAccess->pui32MCUClaimed[ePeriph >> 5] | \
87 psAccess->psGlobalAccess->pui32DSP0Claimed[ePeriph >> 5] | \
88 psAccess->psGlobalAccess->pui32DSP1Claimed[ePeriph >> 5]) \
89 & (1 << (ePeriph & 0x1F))) == 0)
90
91 #define AM_HAL_ACCESS_CLAIM(psAccessStruct, ePeriph) \
92 psAccessStruct->Claimed[ePeriph >> 5] |= (1 << (ePeriph & 0x1F))
93
94 #define AM_HAL_ACCESS_RELEASE(psAccessStruct, ePeriph) \
95 psAccessStruct->Claimed[ePeriph >> 5] &= ~(1 << (ePeriph & 0x1F))
96 //! @}
97
98 //*****************************************************************************
99 //
100 // Static function prototypes.
101 //
102 //*****************************************************************************
103
104 //*****************************************************************************
105 //
106 // Future functions
107 //
108 //*****************************************************************************
109 #define delay_us(...)
110
111 #define get_allowed_structure(psAccess) \
112 psAccess->pui32MCUAllowed
113
114 #define get_claimed_structure(psAccess) \
115 psAccess->pui32MCUClaimed
116
117 //*****************************************************************************
118 //
119 // Future function for managing peripheral access.
120 //
121 //*****************************************************************************
122 uint32_t
get_access_mutex(void)123 get_access_mutex(void)
124 {
125 return 1;
126 }
127
128 //*****************************************************************************
129 //
130 // Future function for managing peripheral access.
131 //
132 //*****************************************************************************
133 static uint32_t
release_access_mutex(void)134 release_access_mutex(void)
135 {
136 return 1;
137 }
138
139 //*****************************************************************************
140 //
141 // Initialize the central access structure.
142 //
143 //*****************************************************************************
144 uint32_t
am_hal_access_initialize(void ** pvHandle)145 am_hal_access_initialize(void **pvHandle)
146 {
147 return AM_HAL_STATUS_SUCCESS;
148 }
149
150 //*****************************************************************************
151 //
152 // Initialize the central access structure.
153 //
154 //*****************************************************************************
155 uint32_t
am_hal_access_deinitialize(void * pvHandle)156 am_hal_access_deinitialize(void *pvHandle)
157 {
158 return AM_HAL_STATUS_SUCCESS;
159 }
160
161 //*****************************************************************************
162 //
163 // Set up the necessary pointers for the acesss structure.
164 //
165 //*****************************************************************************
166 uint32_t
am_hal_access_config(void * pvHandle,am_hal_access_t * psGlobalAccess)167 am_hal_access_config(void *pvHandle, am_hal_access_t *psGlobalAccess)
168 {
169 am_hal_access_state_t *psAccess = pvHandle;
170
171 psAccess->psGlobalAccess = psGlobalAccess;
172 psAccess->Allowed = get_allowed_structure(psGlobalAccess);
173 psAccess->Claimed = get_claimed_structure(psGlobalAccess);
174
175 return AM_HAL_STATUS_SUCCESS;
176 }
177
178 //*****************************************************************************
179 //
180 // Obtain access to a peripheral.
181 //
182 //*****************************************************************************
183 uint32_t
am_hal_access_check(void * pvHandle,am_hal_access_periph_e ePeripheral)184 am_hal_access_check(void *pvHandle,
185 am_hal_access_periph_e ePeripheral)
186 {
187 am_hal_access_state_t *psAccess = pvHandle;
188
189 if (AM_HAL_ACCESS_ALLOWED(psAccess, ePeripheral) &&
190 !AM_HAL_ACCESS_SHARED(psAccess, ePeripheral))
191 {
192 return AM_HAL_STATUS_SUCCESS;
193 }
194 else if (AM_HAL_ACCESS_ALLOWED(psAccess, ePeripheral) &&
195 AM_HAL_ACCESS_CLAIMED(psAccess, ePeripheral))
196 {
197 return AM_HAL_STATUS_SUCCESS;
198 }
199 else
200 {
201 return AM_HAL_STATUS_FAIL;
202 }
203 }
204
205 //*****************************************************************************
206 //
207 // Obtain access to a peripheral.
208 //
209 //*****************************************************************************
210 uint32_t
am_hal_access_get(void * pvHandle,am_hal_access_periph_e ePeripheral,uint32_t ui32TimeoutUS)211 am_hal_access_get(void *pvHandle,
212 am_hal_access_periph_e ePeripheral,
213 uint32_t ui32TimeoutUS)
214 {
215 uint32_t i;
216 bool bPeriphClaimed;
217 am_hal_access_state_t *psAccess = pvHandle;
218
219 if (am_hal_access_check(psAccess, ePeripheral))
220 {
221 //
222 // If we already have access to the peripheral, we don't need to do
223 // anything else.
224 //
225 return AM_HAL_STATUS_SUCCESS;
226 }
227 else if (AM_HAL_ACCESS_ALLOWED(psAccess, ePeripheral))
228 {
229 return AM_HAL_ACCESS_NOT_ALLOWED;
230 }
231 else
232 {
233 //
234 // If we don't have access, we need to try to obtain it. Initialize our
235 // tracking variable, and start a loop to keep track of our timeout
236 // condition.
237 //
238 bPeriphClaimed = false;
239
240 for (i = 0; i < ui32TimeoutUS; i++)
241 {
242 //
243 // Make sure we grab the mutex before accessing the data structure.
244 //
245 if (get_access_mutex())
246 {
247 //
248 // If the peripheral is free, claim it.
249 //
250 if (AM_HAL_ACCESS_AVAILABLE(psAccess, ePeripheral))
251 {
252 AM_HAL_ACCESS_CLAIM(psAccess, ePeripheral);
253 bPeriphClaimed = true;
254 }
255
256 release_access_mutex();
257 }
258
259 //
260 // If we got access, we can exit the loop.
261 //
262 if (bPeriphClaimed)
263 {
264 break;
265 }
266
267 delay_us(1);
268 }
269
270 //
271 // Return a status based on whether we were able to obtain access.
272 //
273 if (bPeriphClaimed)
274 {
275 return AM_HAL_STATUS_SUCCESS;
276 }
277 else
278 {
279 return AM_HAL_STATUS_TIMEOUT;
280 }
281 }
282 }
283
284 //*****************************************************************************
285 //
286 // Release control of a peripheral.
287 //
288 //*****************************************************************************
289 uint32_t
am_hal_access_release(void * pvHandle,am_hal_access_periph_e ePeripheral,uint32_t ui32TimeoutUS)290 am_hal_access_release(void *pvHandle,
291 am_hal_access_periph_e ePeripheral,
292 uint32_t ui32TimeoutUS)
293 {
294 uint32_t i;
295 bool bPeriphFree;
296 am_hal_access_state_t *psAccess = pvHandle;
297
298 //
299 // If we don't have access, we need to try to obtain it. Initialize our
300 // tracking variable, and start a loop to keep track of our timeout
301 // condition.
302 //
303 bPeriphFree = 0;
304
305 for (i = 0; i < ui32TimeoutUS; i++)
306 {
307 //
308 // Make sure we grabe the mutex before accessing the data structure.
309 //
310 if (get_access_mutex())
311 {
312 AM_HAL_ACCESS_RELEASE(psAccess, ePeripheral);
313 release_access_mutex();
314 bPeriphFree = true;
315 }
316
317 //
318 // If we got access, we can exit the loop.
319 //
320 if (bPeriphFree)
321 {
322 break;
323 }
324
325 delay_us(1);
326 }
327
328 //
329 // Return a status based on whether we were able to release the resource.
330 //
331 if (bPeriphFree)
332 {
333 return AM_HAL_STATUS_SUCCESS;
334 }
335 else
336 {
337 return AM_HAL_STATUS_TIMEOUT;
338 }
339 }
340
341 //*****************************************************************************
342 //
343 // End Doxygen group.
344 //! @}
345 //
346 //*****************************************************************************
347