1 /***************************************************************************//**
2 * \file cy_ipc_sema.c
3 * \version 1.91
4 *
5 *  Description:
6 *   IPC Semaphore Driver - This source file contains the source code for the
7 *   semaphore level APIs for the IPC interface.
8 *
9 ********************************************************************************
10 * Copyright 2016-2020 Cypress Semiconductor Corporation
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 *     http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25 
26 #include "cy_device.h"
27 
28 #if defined (CY_IP_M4CPUSS) || defined (CY_IP_M7CPUSS) || (defined (CY_IP_MXIPC) && (CY_IPC_INSTANCES > 1U))
29 
30 #include "cy_ipc_drv.h"
31 #include "cy_ipc_sema.h"
32 #include "cy_syslib.h"
33 #include <string.h> /* The memset() definition */
34 
35 /* Defines a mask to Check if semaphore count is a multiple of 32 */
36 #define CY_IPC_SEMA_PER_WORD_MASK    (CY_IPC_SEMA_PER_WORD - 1UL)
37 
38 /* Pointer to IPC structure used for semaphores */
39 static IPC_STRUCT_Type* cy_semaIpcStruct;
40 
41 
42 /*******************************************************************************
43 * Function Name: Cy_IPC_Sema_Init
44 ****************************************************************************//**
45 *
46 * This function initializes the semaphores subsystem. The user must create an
47 * array of unsigned 32-bit words to hold the semaphore bits. The number
48 * of semaphores will be the size of the array * 32. The total semaphores count
49 * will always be a multiple of 32.
50 *
51 * \note In a multi-CPU system this init function should be called with all
52 * initialized parameters on one CPU only to provide a pointer to SRAM that can
53 * be shared between all the CPUs in the system that will use semaphores.
54 * On other CPUs user must specify the IPC semaphores channel and pass 0 / NULL
55 * to count and memPtr parameters correspondingly.
56 *
57 * CM7 cores in CAT1C devices support Data Cache. Data Cache line is 32 bytes.
58 * User needs to make sure that the memPtr pointer passed to the Cy_IPC_Sema_Init
59 * function points to 32 byte aligned array of words that contain the semaphore data.
60 * User can use CY_ALIGN(32) macro for 32 byte alignment.
61 *
62 * \param ipcChannel
63 * The IPC channel number used for semaphores
64 *
65 * \param count
66 *  The maximum number of semaphores to be supported (multiple of 32).
67 *
68 * \param memPtr
69 *  This points to the array of (count/32) words that contain the semaphore data.
70 *
71 * \return Status of the operation
72 *    \retval CY_IPC_SEMA_SUCCESS: Successfully initialized
73 *    \retval CY_IPC_SEMA_BAD_PARAM:     Memory pointer is NULL and count is not zero,
74 *                             or count not multiple of 32
75 *    \retval CY_IPC_SEMA_ERROR_LOCKED:  Could not acquire semaphores IPC channel
76 *
77 * \funcusage
78 * \snippet ipc/snippet/main.c snippet_Cy_IPC_Sema_Init
79 *
80 *******************************************************************************/
Cy_IPC_Sema_Init(uint32_t ipcChannel,uint32_t count,uint32_t memPtr[])81 cy_en_ipcsema_status_t Cy_IPC_Sema_Init(uint32_t ipcChannel,
82                                         uint32_t count, uint32_t memPtr[])
83 {
84     /* Structure containing semaphores control data */
85     CY_SECTION_SHAREDMEM
86 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
87     static cy_stc_ipc_sema_t       cy_semaData CY_ALIGN(__SCB_DCACHE_LINE_SIZE);
88 #else
89     static cy_stc_ipc_sema_t       cy_semaData;
90 #endif
91     cy_en_ipcsema_status_t retStatus = CY_IPC_SEMA_BAD_PARAM;
92 
93     if( (NULL == memPtr) && (0u == count))
94     {
95         cy_semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipcChannel);
96 
97         retStatus = CY_IPC_SEMA_SUCCESS;
98     }
99 
100     /* Check for non Null pointers and count value */
101     else if ((NULL != memPtr) && (0u != count))
102     {
103         cy_semaData.maxSema  = count;
104         cy_semaData.arrayPtr = memPtr;
105 
106         retStatus = Cy_IPC_Sema_InitExt(ipcChannel, &cy_semaData);
107     }
108 
109     else
110     {
111         retStatus = CY_IPC_SEMA_BAD_PARAM;
112     }
113 
114     return(retStatus);
115 }
116 
117 
118 /*******************************************************************************
119 * Function Name: Cy_IPC_Sema_InitExt
120 ****************************************************************************//**
121 * This function initializes the semaphores subsystem. The user must create an
122 * array of unsigned 32-bit words to hold the semaphore bits. The number
123 * of semaphores will be the size of the array * 32. The total semaphores count
124 * will always be a multiple of 32.
125 *
126 * \note In a multi-CPU system this init function should be called with all
127 * initialized parameters on one CPU only to provide a pointer to SRAM that can
128 * be shared between all the CPUs in the system that will use semaphores.
129 * On other CPUs user must specify the IPC semaphores channel and pass 0 / NULL
130 * to count and memPtr parameters correspondingly.
131 *
132 * \param ipcChannel
133 * The IPC channel number used for semaphores
134 *
135 * \param ipcSema
136 *  This is configuration structure of the IPC semaphore.
137 *  See \ref cy_stc_ipc_sema_t.
138 *
139 * \return Status of the operation
140 *    \retval CY_IPC_SEMA_SUCCESS: Successfully initialized
141 *    \retval CY_IPC_SEMA_BAD_PARAM:     Memory pointer is NULL and count is not zero,
142 *                             or count not multiple of 32
143 *    \retval CY_IPC_SEMA_ERROR_LOCKED:  Could not acquire semaphores IPC channel
144 *
145 *******************************************************************************/
Cy_IPC_Sema_InitExt(uint32_t ipcChannel,cy_stc_ipc_sema_t * ipcSema)146 cy_en_ipcsema_status_t Cy_IPC_Sema_InitExt(uint32_t ipcChannel, cy_stc_ipc_sema_t *ipcSema)
147 {
148     cy_en_ipcsema_status_t retStatus = CY_IPC_SEMA_BAD_PARAM;
149 
150     if (ipcChannel >= CY_IPC_CHANNELS)
151     {
152         retStatus = CY_IPC_SEMA_BAD_PARAM;
153     }
154     else
155     {
156         if(NULL != ipcSema)
157         {
158 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
159             SCB_CleanDCache_by_Addr((uint32_t*)&ipcSema->maxSema, (int32_t)sizeof(ipcSema->maxSema));
160 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
161             /* Check if semaphore count is a multiple of 32 */
162             if( 0UL == (ipcSema->maxSema & CY_IPC_SEMA_PER_WORD_MASK))
163             {
164                 cy_semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipcChannel);
165 
166                 /* Initialize all semaphores to released */
167                 for (uint32_t index=0; index<(uint32_t)(ipcSema->maxSema / CY_IPC_SEMA_PER_WORD); index++)
168                 {
169                     ipcSema->arrayPtr[index] = 0UL;
170                 }
171 
172 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
173                 SCB_CleanDCache_by_Addr((uint32_t*)ipcSema->arrayPtr, (int32_t)sizeof(*ipcSema->arrayPtr));
174 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
175 
176                 /* Make sure semaphores start out released.  */
177                 /* Ignore the return value since it is OK if it was already released. */
178                 (void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION);
179 
180                  /* Set the IPC Data with the pointer to the array. */
181                 if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_SendMsgPtr (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION, ipcSema))
182                 {
183                     if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION))
184                     {
185                         retStatus = CY_IPC_SEMA_SUCCESS;
186                     }
187                     else
188                     {
189                         /* IPC channel not released, still semaphored */
190                         retStatus = CY_IPC_SEMA_ERROR_LOCKED;
191                     }
192                 }
193                 else
194                 {
195                     /* Could not acquire semaphore channel */
196                     retStatus = CY_IPC_SEMA_ERROR_LOCKED;
197                 }
198             }
199             else
200             {
201                 retStatus = CY_IPC_SEMA_BAD_PARAM;
202             }
203         }
204         else
205         {
206             retStatus = CY_IPC_SEMA_BAD_PARAM;
207         }
208     }
209 
210     return(retStatus);
211 }
212 
213 
214 /*******************************************************************************
215 * Function Name: Cy_IPC_Sema_Set
216 ****************************************************************************//**
217 *
218 * This function tries to acquire a semaphore. If the
219 * semaphore is not available, this function returns immediately with
220 * CY_IPC_SEMA_LOCKED.
221 *
222 * It first acquires the IPC channel that is used for all the semaphores, sets
223 * the semaphore if it is cleared, then releases the IPC channel used for the
224 * semaphore.
225 *
226 * \param semaNumber
227 *  The semaphore number to acquire.
228 * \note CAT1D has two shared memories. One is a secure memory area which is accessible from
229 *  secure domains only. Another memory area which is accessible from both secure and non-secure
230 *  domains. To use secure area for semaphore, user has to use \ref CY_IPC_SEMA_SEC macro to create
231 *  a secure semaphore.
232 *
233 * \param preemptable
234 *  When this parameter is enabled the function can be preempted by another
235 *  task or other forms of context switching in an RTOS environment.
236 *
237 * \note
238 *  If <b>preemptable</b> is enabled (true), the user must ensure that there are
239 *  no deadlocks in the system, which can be caused by an interrupt that occurs
240 *  after the IPC channel is locked. Unless the user is ready to handle IPC
241 *  channel locks correctly at the application level, set <b>preemptable</b> to
242 *  false.
243 *
244 * \return Status of the operation
245 *    \retval CY_IPC_SEMA_SUCCESS:      The semaphore was set successfully
246 *    \retval CY_IPC_SEMA_LOCKED:       The semaphore channel is busy or locked
247 *                              by another process
248 *    \retval CY_IPC_SEMA_NOT_ACQUIRED: Semaphore was already set
249 *    \retval CY_IPC_SEMA_OUT_OF_RANGE: The semaphore number is not valid
250 *
251 * \funcusage
252 * \snippet ipc/snippet/main.c snippet_Cy_IPC_Sema_Set
253 *
254 *******************************************************************************/
Cy_IPC_Sema_Set(uint32_t semaNumber,bool preemptable)255 cy_en_ipcsema_status_t Cy_IPC_Sema_Set(uint32_t semaNumber, bool preemptable)
256 {
257     uint32_t semaIndex;
258     uint32_t semaMask;
259     uint32_t interruptState = 0UL;
260 
261     cy_stc_ipc_sema_t      *semaStruct;
262     cy_en_ipcsema_status_t  retStatus = CY_IPC_SEMA_LOCKED;
263     uint32_t *ptrArray;
264     uint32_t semaNum;
265 
266     /** check cy_semaIpcStruct != NULL */
267     if (cy_semaIpcStruct == NULL)
268     {
269         return CY_IPC_SEMA_NOT_ACQUIRED;
270     }
271 
272 
273     /* Get pointer to structure */
274     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
275         semaNum = CY_IPC_SEMA_GET_NUM(semaNumber);
276         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
277     #else
278         semaNum = semaNumber;
279         semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
280     #endif
281 
282 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
283     SCB_InvalidateDCache_by_Addr((uint32_t*)&semaStruct->maxSema, (int32_t)sizeof(semaStruct->maxSema));
284 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
285 
286     if (semaNum < semaStruct->maxSema)
287     {
288         semaIndex = semaNum / CY_IPC_SEMA_PER_WORD;
289         semaMask = (uint32_t)(1UL << (semaNum - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
290     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
291         ptrArray = CY_IPC_SEMA_IS_SEC(semaNumber) ? semaStruct->arrayPtr_sec : (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
292     #else
293         ptrArray = semaStruct->arrayPtr;
294     #endif
295         if (!preemptable)
296         {
297             interruptState = Cy_SysLib_EnterCriticalSection();
298         }
299 
300         /* Check to make sure the IPC channel is released
301            If so, check if specific channel can be locked. */
302         if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire (cy_semaIpcStruct))
303         {
304 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
305             SCB_InvalidateDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
306 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
307 
308             if((ptrArray[semaIndex] & semaMask) == 0UL)
309             {
310                 ptrArray[semaIndex] |= semaMask;
311 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
312                 SCB_CleanDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
313 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
314                 retStatus = CY_IPC_SEMA_SUCCESS;
315             }
316             else
317             {
318                 retStatus = CY_IPC_SEMA_NOT_ACQUIRED;
319             }
320 
321             /* Release, but do not trigger a release event */
322             (void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION);
323         }
324 
325         if (!preemptable)
326         {
327             Cy_SysLib_ExitCriticalSection(interruptState);
328         }
329     }
330     else
331     {
332         retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
333     }
334 
335     return(retStatus);
336 }
337 
338 
339 /*******************************************************************************
340 * Function Name: Cy_IPC_Sema_Clear
341 ****************************************************************************//**
342 *
343 * This functions tries to releases a semaphore.
344 *
345 * It first acquires the IPC channel that is used for all the semaphores, clears
346 * the semaphore if it is set, then releases the IPC channel used for the
347 * semaphores.
348 *
349 * \param semaNumber
350 *  The index of the semaphore to release.
351 * \note CAT1D has two shared memories. One is a secure memory area which is accessible from
352 *  secure domains only. Another memory area which is accessible from both secure and non-secure
353 *  domains. To use secure area for semaphore, user has to use \ref CY_IPC_SEMA_SEC macro to create
354 *  a secure semaphore.
355 *
356 * \param preemptable
357 *  When this parameter is enabled the function can be preempted by another
358 *  task or other forms of context switching in an RTOS environment.
359 *
360 * \note
361 *  If <b>preemptable</b> is enabled (true), the user must ensure that there are
362 *  no deadlocks in the system, which can be caused by an interrupt that occurs
363 *  after the IPC channel is locked. Unless the user is ready to handle IPC
364 *  channel locks correctly at the application level, set <b>preemptable</b> to
365 *  false.
366 *
367 * \return Status of the operation
368 *    \retval CY_IPC_SEMA_SUCCESS:         The semaphore was cleared successfully
369 *    \retval CY_IPC_SEMA_NOT_ACQUIRED:    The semaphore was already cleared
370 *    \retval CY_IPC_SEMA_LOCKED:          The semaphore channel was semaphored or busy
371 *    \retval CY_IPC_SEMA_OUT_OF_RANGE:    The semaphore number is not valid
372 *
373 * \funcusage
374 * \snippet ipc/snippet/main.c snippet_Cy_IPC_Sema_Clear
375 *
376 *******************************************************************************/
Cy_IPC_Sema_Clear(uint32_t semaNumber,bool preemptable)377 cy_en_ipcsema_status_t Cy_IPC_Sema_Clear(uint32_t semaNumber, bool preemptable)
378 {
379     uint32_t semaIndex;
380     uint32_t semaMask;
381     uint32_t interruptState = 0UL;
382 
383     cy_stc_ipc_sema_t      *semaStruct;
384     cy_en_ipcsema_status_t  retStatus = CY_IPC_SEMA_LOCKED;
385     uint32_t *ptrArray;
386     uint32_t semaNum;
387 
388     /** check cy_semaIpcStruct != NULL */
389     if (cy_semaIpcStruct == NULL)
390     {
391         return CY_IPC_SEMA_NOT_ACQUIRED;
392     }
393 
394 
395     /* Get pointer to structure */
396     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
397         semaNum = CY_IPC_SEMA_GET_NUM(semaNumber);
398         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
399     #else
400         semaNum = semaNumber;
401         semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
402     #endif
403 
404 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
405      SCB_InvalidateDCache_by_Addr((uint32_t*)&semaStruct->maxSema, (int32_t)sizeof(semaStruct->maxSema));
406 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
407 
408     if (semaNum < semaStruct->maxSema)
409     {
410         semaIndex = semaNum / CY_IPC_SEMA_PER_WORD;
411         semaMask = (uint32_t)(1UL << (semaNum - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
412     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
413         ptrArray = CY_IPC_SEMA_IS_SEC(semaNumber) ? semaStruct->arrayPtr_sec : (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
414     #else
415         ptrArray = semaStruct->arrayPtr;
416     #endif
417 
418         if (!preemptable)
419         {
420             interruptState = Cy_SysLib_EnterCriticalSection();
421         }
422 
423         /* Check to make sure the IPC channel is released
424            If so, check if specific channel can be locked. */
425         if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire (cy_semaIpcStruct))
426         {
427 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
428             SCB_InvalidateDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
429 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
430             if((ptrArray[semaIndex] & semaMask) != 0UL)
431             {
432                 ptrArray[semaIndex] &= ~semaMask;
433 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
434                 SCB_CleanDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
435 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
436                 retStatus = CY_IPC_SEMA_SUCCESS;
437             }
438             else
439             {
440                 retStatus = CY_IPC_SEMA_NOT_ACQUIRED;
441             }
442 
443             /* Release, but do not trigger a release event */
444             (void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION);
445         }
446 
447         if (!preemptable)
448         {
449             Cy_SysLib_ExitCriticalSection(interruptState);
450         }
451     }
452     else
453     {
454         retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
455     }
456     return(retStatus);
457 }
458 
459 
460 /*******************************************************************************
461 * Function Name: Cy_IPC_Sema_Status
462 ****************************************************************************//**
463 *
464 * This function returns the status of the semaphore.
465 *
466 * \param semaNumber
467 *  The index of the semaphore to return status.
468 * \note CAT1D has two shared memories. One is a secure memory area which is accessible from
469 *  secure domains only. Another memory area which is accessible from both secure and non-secure
470 *  domains. To use secure area for semaphore, user has to use \ref CY_IPC_SEMA_SEC macro to create
471 *  a secure semaphore.
472 *
473 * \return Status of the operation
474 *     \retval CY_IPC_SEMA_STATUS_LOCKED:    The semaphore is in the set state.
475 *     \retval CY_IPC_SEMA_STATUS_UNLOCKED:  The semaphore is in the cleared state.
476 *     \retval CY_IPC_SEMA_OUT_OF_RANGE:     The semaphore number is not valid
477 *
478 * \funcusage
479 * \snippet ipc/snippet/main.c snippet_Cy_IPC_Sema_Status
480 *
481 *******************************************************************************/
Cy_IPC_Sema_Status(uint32_t semaNumber)482 cy_en_ipcsema_status_t Cy_IPC_Sema_Status(uint32_t semaNumber)
483 {
484     cy_en_ipcsema_status_t   retStatus;
485     uint32_t semaIndex;
486     uint32_t semaMask;
487     cy_stc_ipc_sema_t      *semaStruct;
488     uint32_t *ptrArray;
489     uint32_t semaNum;
490 
491     /** check cy_semaIpcStruct != NULL */
492     if (cy_semaIpcStruct == NULL)
493     {
494         return CY_IPC_SEMA_NOT_ACQUIRED;
495     }
496 
497 
498     /* Get pointer to structure */
499     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
500         semaNum = CY_IPC_SEMA_GET_NUM(semaNumber);
501         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
502     #else
503         semaNum = semaNumber;
504         semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
505     #endif
506 
507 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
508     SCB_InvalidateDCache_by_Addr((uint32_t*)&semaStruct->maxSema, (int32_t)sizeof(semaStruct->maxSema));
509 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
510 
511     if (semaNum < semaStruct->maxSema)
512     {
513         /* Get the index into the semaphore array and calculate the mask */
514         semaIndex = semaNum / CY_IPC_SEMA_PER_WORD;
515         semaMask = (uint32_t)(1UL << (semaNum - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
516     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
517         ptrArray = CY_IPC_SEMA_IS_SEC(semaNumber) ? semaStruct->arrayPtr_sec : (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
518     #else
519         ptrArray = semaStruct->arrayPtr;
520     #endif
521 
522 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
523         SCB_InvalidateDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
524 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
525 
526         if((ptrArray[semaIndex] & semaMask) != 0UL)
527         {
528             retStatus =  CY_IPC_SEMA_STATUS_LOCKED;
529         }
530         else
531         {
532             retStatus =  CY_IPC_SEMA_STATUS_UNLOCKED;
533         }
534     }
535     else
536     {
537         retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
538     }
539     return(retStatus);
540 }
541 
542 
543 /*******************************************************************************
544 * Function Name: Cy_IPC_Sema_GetMaxSems
545 ****************************************************************************//**
546 *
547 * This function returns the number of semaphores in the semaphores subsystem.
548 *
549 * \return
550 *     Returns the semaphores quantity.
551 *
552 * \funcusage
553 * \snippet ipc/snippet/main.c snippet_Cy_IPC_Sema_GetMaxSems
554 *
555 *******************************************************************************/
Cy_IPC_Sema_GetMaxSems(void)556 uint32_t Cy_IPC_Sema_GetMaxSems(void)
557 {
558     cy_stc_ipc_sema_t      *semaStruct;
559 
560     /* Get pointer to structure */
561     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
562         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
563     #else
564         semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
565     #endif
566 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
567      SCB_InvalidateDCache_by_Addr((uint32_t*)&semaStruct->maxSema, (int32_t)sizeof(semaStruct->maxSema));
568 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
569     return (semaStruct->maxSema);
570 }
571 
572 #endif
573 
574 /* [] END OF FILE */
575