1 /***************************************************************************//**
2 * \file cy_ipc_sema.c
3 * \version 1.130
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)
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     #elif defined(__SAUREGION_PRESENT) && (__SAUREGION_PRESENT==1)
278         semaNum = semaNumber;
279         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
280     #else
281         semaNum = semaNumber;
282         semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
283     #endif
284 
285 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
286     SCB_InvalidateDCache_by_Addr((uint32_t*)&semaStruct->maxSema, (int32_t)sizeof(semaStruct->maxSema));
287 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
288 
289     if (semaNum < semaStruct->maxSema)
290     {
291         semaIndex = semaNum / CY_IPC_SEMA_PER_WORD;
292         semaMask = (uint32_t)(1UL << (semaNum - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
293     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
294         ptrArray = CY_IPC_SEMA_IS_SEC(semaNumber) ? semaStruct->arrayPtr_sec : (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
295     #elif defined(__SAUREGION_PRESENT) && (__SAUREGION_PRESENT==1)
296         ptrArray = (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
297     #else
298         ptrArray = semaStruct->arrayPtr;
299     #endif
300         if (!preemptable)
301         {
302             interruptState = Cy_SysLib_EnterCriticalSection();
303         }
304 
305         /* Check to make sure the IPC channel is released
306            If so, check if specific channel can be locked. */
307         if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire (cy_semaIpcStruct))
308         {
309 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
310             SCB_InvalidateDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
311 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
312 
313             if((ptrArray[semaIndex] & semaMask) == 0UL)
314             {
315                 ptrArray[semaIndex] |= semaMask;
316 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
317                 SCB_CleanDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
318 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
319                 retStatus = CY_IPC_SEMA_SUCCESS;
320             }
321             else
322             {
323                 retStatus = CY_IPC_SEMA_NOT_ACQUIRED;
324             }
325 
326             /* Release, but do not trigger a release event */
327             (void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION);
328         }
329 
330         if (!preemptable)
331         {
332             Cy_SysLib_ExitCriticalSection(interruptState);
333         }
334     }
335     else
336     {
337         retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
338     }
339 
340     return(retStatus);
341 }
342 
343 
344 /*******************************************************************************
345 * Function Name: Cy_IPC_Sema_Clear
346 ****************************************************************************//**
347 *
348 * This functions tries to releases a semaphore.
349 *
350 * It first acquires the IPC channel that is used for all the semaphores, clears
351 * the semaphore if it is set, then releases the IPC channel used for the
352 * semaphores.
353 *
354 * \param semaNumber
355 *  The index of the semaphore to release.
356 * \note CAT1D has two shared memories. One is a secure memory area which is accessible from
357 *  secure domains only. Another memory area which is accessible from both secure and non-secure
358 *  domains. To use secure area for semaphore, user has to use \ref CY_IPC_SEMA_SEC macro to create
359 *  a secure semaphore.
360 *
361 * \param preemptable
362 *  When this parameter is enabled the function can be preempted by another
363 *  task or other forms of context switching in an RTOS environment.
364 *
365 * \note
366 *  If <b>preemptable</b> is enabled (true), the user must ensure that there are
367 *  no deadlocks in the system, which can be caused by an interrupt that occurs
368 *  after the IPC channel is locked. Unless the user is ready to handle IPC
369 *  channel locks correctly at the application level, set <b>preemptable</b> to
370 *  false.
371 *
372 * \return Status of the operation
373 *    \retval CY_IPC_SEMA_SUCCESS:         The semaphore was cleared successfully
374 *    \retval CY_IPC_SEMA_NOT_ACQUIRED:    The semaphore was already cleared
375 *    \retval CY_IPC_SEMA_LOCKED:          The semaphore channel was semaphored or busy
376 *    \retval CY_IPC_SEMA_OUT_OF_RANGE:    The semaphore number is not valid
377 *
378 * \funcusage
379 * \snippet ipc/snippet/main.c snippet_Cy_IPC_Sema_Clear
380 *
381 *******************************************************************************/
Cy_IPC_Sema_Clear(uint32_t semaNumber,bool preemptable)382 cy_en_ipcsema_status_t Cy_IPC_Sema_Clear(uint32_t semaNumber, bool preemptable)
383 {
384     uint32_t semaIndex;
385     uint32_t semaMask;
386     uint32_t interruptState = 0UL;
387 
388     cy_stc_ipc_sema_t      *semaStruct;
389     cy_en_ipcsema_status_t  retStatus = CY_IPC_SEMA_LOCKED;
390     uint32_t *ptrArray;
391     uint32_t semaNum;
392 
393     /** check cy_semaIpcStruct != NULL */
394     if (cy_semaIpcStruct == NULL)
395     {
396         return CY_IPC_SEMA_NOT_ACQUIRED;
397     }
398 
399 
400     /* Get pointer to structure */
401     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
402         semaNum = CY_IPC_SEMA_GET_NUM(semaNumber);
403         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
404     #elif defined(__SAUREGION_PRESENT) && (__SAUREGION_PRESENT==1)
405         semaNum = semaNumber;
406         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
407     #else
408         semaNum = semaNumber;
409         semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
410     #endif
411 
412 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
413      SCB_InvalidateDCache_by_Addr((uint32_t*)&semaStruct->maxSema, (int32_t)sizeof(semaStruct->maxSema));
414 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
415 
416     if (semaNum < semaStruct->maxSema)
417     {
418         semaIndex = semaNum / CY_IPC_SEMA_PER_WORD;
419         semaMask = (uint32_t)(1UL << (semaNum - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
420     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
421         ptrArray = CY_IPC_SEMA_IS_SEC(semaNumber) ? semaStruct->arrayPtr_sec : (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
422     #elif defined(__SAUREGION_PRESENT) && (__SAUREGION_PRESENT==1)
423         ptrArray = (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
424     #else
425         ptrArray = semaStruct->arrayPtr;
426     #endif
427 
428         if (!preemptable)
429         {
430             interruptState = Cy_SysLib_EnterCriticalSection();
431         }
432 
433         /* Check to make sure the IPC channel is released
434            If so, check if specific channel can be locked. */
435         if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire (cy_semaIpcStruct))
436         {
437 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
438             SCB_InvalidateDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
439 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
440             if((ptrArray[semaIndex] & semaMask) != 0UL)
441             {
442                 ptrArray[semaIndex] &= ~semaMask;
443 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
444                 SCB_CleanDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
445 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
446                 retStatus = CY_IPC_SEMA_SUCCESS;
447             }
448             else
449             {
450                 retStatus = CY_IPC_SEMA_NOT_ACQUIRED;
451             }
452 
453             /* Release, but do not trigger a release event */
454             (void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION);
455         }
456 
457         if (!preemptable)
458         {
459             Cy_SysLib_ExitCriticalSection(interruptState);
460         }
461     }
462     else
463     {
464         retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
465     }
466     return(retStatus);
467 }
468 
469 
470 /*******************************************************************************
471 * Function Name: Cy_IPC_Sema_Status
472 ****************************************************************************//**
473 *
474 * This function returns the status of the semaphore.
475 *
476 * \param semaNumber
477 *  The index of the semaphore to return status.
478 * \note CAT1D has two shared memories. One is a secure memory area which is accessible from
479 *  secure domains only. Another memory area which is accessible from both secure and non-secure
480 *  domains. To use secure area for semaphore, user has to use \ref CY_IPC_SEMA_SEC macro to create
481 *  a secure semaphore.
482 *
483 * \return Status of the operation
484 *     \retval CY_IPC_SEMA_STATUS_LOCKED:    The semaphore is in the set state.
485 *     \retval CY_IPC_SEMA_STATUS_UNLOCKED:  The semaphore is in the cleared state.
486 *     \retval CY_IPC_SEMA_OUT_OF_RANGE:     The semaphore number is not valid
487 *
488 * \funcusage
489 * \snippet ipc/snippet/main.c snippet_Cy_IPC_Sema_Status
490 *
491 *******************************************************************************/
Cy_IPC_Sema_Status(uint32_t semaNumber)492 cy_en_ipcsema_status_t Cy_IPC_Sema_Status(uint32_t semaNumber)
493 {
494     cy_en_ipcsema_status_t   retStatus;
495     uint32_t semaIndex;
496     uint32_t semaMask;
497     cy_stc_ipc_sema_t      *semaStruct;
498     uint32_t *ptrArray;
499     uint32_t semaNum;
500 
501     /** check cy_semaIpcStruct != NULL */
502     if (cy_semaIpcStruct == NULL)
503     {
504         return CY_IPC_SEMA_NOT_ACQUIRED;
505     }
506 
507 
508     /* Get pointer to structure */
509     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
510         semaNum = CY_IPC_SEMA_GET_NUM(semaNumber);
511         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
512     #elif defined(__SAUREGION_PRESENT) && (__SAUREGION_PRESENT==1)
513         semaNum = semaNumber;
514         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
515     #else
516         semaNum = semaNumber;
517         semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
518     #endif
519 
520 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
521     SCB_InvalidateDCache_by_Addr((uint32_t*)&semaStruct->maxSema, (int32_t)sizeof(semaStruct->maxSema));
522 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
523 
524     if (semaNum < semaStruct->maxSema)
525     {
526         /* Get the index into the semaphore array and calculate the mask */
527         semaIndex = semaNum / CY_IPC_SEMA_PER_WORD;
528         semaMask = (uint32_t)(1UL << (semaNum - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
529     #if defined(CY_IPC_SECURE_SEMA_DEVICE)
530         ptrArray = CY_IPC_SEMA_IS_SEC(semaNumber) ? semaStruct->arrayPtr_sec : (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
531     #elif defined(__SAUREGION_PRESENT) && (__SAUREGION_PRESENT==1)
532         ptrArray = (uint32_t*)GET_ALIAS_ADDRESS(semaStruct->arrayPtr);
533     #else
534         ptrArray = semaStruct->arrayPtr;
535     #endif
536 
537 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
538         SCB_InvalidateDCache_by_Addr((uint32_t*)ptrArray, (int32_t)sizeof(*ptrArray));
539 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
540 
541         if((ptrArray[semaIndex] & semaMask) != 0UL)
542         {
543             retStatus =  CY_IPC_SEMA_STATUS_LOCKED;
544         }
545         else
546         {
547             retStatus =  CY_IPC_SEMA_STATUS_UNLOCKED;
548         }
549     }
550     else
551     {
552         retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
553     }
554     return(retStatus);
555 }
556 
557 
558 /*******************************************************************************
559 * Function Name: Cy_IPC_Sema_GetMaxSems
560 ****************************************************************************//**
561 *
562 * This function returns the number of semaphores in the semaphores subsystem.
563 *
564 * \return
565 *     Returns the semaphores quantity.
566 *
567 * \funcusage
568 * \snippet ipc/snippet/main.c snippet_Cy_IPC_Sema_GetMaxSems
569 *
570 *******************************************************************************/
Cy_IPC_Sema_GetMaxSems(void)571 uint32_t Cy_IPC_Sema_GetMaxSems(void)
572 {
573     cy_stc_ipc_sema_t      *semaStruct;
574 
575     /* Get pointer to structure */
576     #if defined(__SAUREGION_PRESENT) && (__SAUREGION_PRESENT==1)
577         semaStruct = (cy_stc_ipc_sema_t *)(GET_ALIAS_ADDRESS(Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct)));
578     #else
579         semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
580     #endif
581 #if (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)
582      SCB_InvalidateDCache_by_Addr((uint32_t*)&semaStruct->maxSema, (int32_t)sizeof(semaStruct->maxSema));
583 #endif /* (CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE) */
584     return (semaStruct->maxSema);
585 }
586 
587 #endif
588 
589 /* [] END OF FILE */
590