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