1 /***************************************************************************//**
2 * \file cyhal_ipc_impl.h
3 *
4 * \brief
5 * CAT1 specific implementation for IPC API.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 *     http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26 
27 #pragma once
28 
29 #if (CYHAL_DRIVER_AVAILABLE_IPC)
30 
31 #if defined(__cplusplus)
32 extern "C" {
33 #endif /* __cplusplus */
34 
35 /**
36  * \addtogroup group_hal_impl_ipc IPC
37  * \ingroup group_hal_impl
38  * \{
39  * Implementation specific interface for using the IPC driver.
40  *
41  */
42 
43 /**
44 * \cond INTERNAL
45 */
46 
47 #if defined(COMPONENT_CAT1A)
48     /* On CAT1A devices CY_IPC_CHANNELS is not available at compile time,
49        except for TVIIBE devices. */
50     #if defined (CPUSS_IPC_IPC_NR) && (CPUSS_IPC_IPC_NR > 0)
51         #define _CYHAL_IPC_DRV_CHANNELS     (CPUSS_IPC_IPC_NR)
52     #else
53         #define _CYHAL_IPC_DRV_CHANNELS     (16u)
54     #endif
55 #elif defined(COMPONENT_CAT1D)
56     /* Last channel is used by semaphores */
57     #define _CYHAL_IPC_DRV_CHANNELS     (CY_IPC_IP1_CH - 1)
58 #else
59     #define _CYHAL_IPC_DRV_CHANNELS     (CPUSS_IPC_IPC_NR)
60 #endif
61 
62 /** Definition of _CYHAL_IPC_CHAN_USER which stands for first user-available IPC channel index */
63 #if defined(CY_IPC_CHAN_USER)
64 #if defined(COMPONENT_CAT1D)
65     #define _CYHAL_IPC_CHAN_USER        (CY_IPC_CHAN_USER - IPC0_IPC_NR)
66 #else
67     #define _CYHAL_IPC_CHAN_USER        (CY_IPC_CHAN_USER)
68 #endif
69 #else
70     #if defined(COMPONENT_CAT1A)
71         #define _CYHAL_IPC_CHAN_USER    (CY_IPC_CHAN_DDFT + 1)
72     #elif defined(COMPONENT_CAT1B)
73         #define _CYHAL_IPC_CHAN_USER    (0u)
74     #else
75         #error "Unhandled device"
76     #endif /* defined(COMPONENT_CAT1A) or defined(COMPONENT_CAT1B) or other */
77 #endif /* !defined(CY_IPC_CHAN_USER) */
78 
79 /** Number of available for IPC HAL user channels */
80 #define CYHAL_IPC_USR_CHANNELS                 ((_CYHAL_IPC_DRV_CHANNELS) - _CYHAL_IPC_CHAN_USER)
81 
82 #if (CYHAL_IPC_USR_CHANNELS > 0)
83     /** User IPC channel 0 */
84     #define CYHAL_IPC_CHAN_0    (_CYHAL_IPC_CHAN_USER)
85 #endif /* CYHAL_IPC_USR_CHANNELS > 0 */
86 #if (CYHAL_IPC_USR_CHANNELS > 1)
87     /** User IPC channel 1 */
88     #define CYHAL_IPC_CHAN_1    (_CYHAL_IPC_CHAN_USER + 1)
89 #endif /* CYHAL_IPC_USR_CHANNELS > 1 */
90 #if (CYHAL_IPC_USR_CHANNELS > 2)
91     /** User IPC channel 2 */
92     #define CYHAL_IPC_CHAN_2    (_CYHAL_IPC_CHAN_USER + 2)
93 #endif /* CYHAL_IPC_USR_CHANNELS > 2 */
94 #if (CYHAL_IPC_USR_CHANNELS > 3)
95     /** User IPC channel 3 */
96     #define CYHAL_IPC_CHAN_3    (_CYHAL_IPC_CHAN_USER + 3)
97 #endif /* CYHAL_IPC_USR_CHANNELS > 3 */
98 #if (CYHAL_IPC_USR_CHANNELS > 4)
99     /** User IPC channel 4 */
100     #define CYHAL_IPC_CHAN_4    (_CYHAL_IPC_CHAN_USER + 4)
101 #endif /* CYHAL_IPC_USR_CHANNELS > 4 */
102 #if (CYHAL_IPC_USR_CHANNELS > 5)
103     /** User IPC channel 5 */
104     #define CYHAL_IPC_CHAN_5    (_CYHAL_IPC_CHAN_USER + 5)
105 #endif /* CYHAL_IPC_USR_CHANNELS > 5 */
106 #if (CYHAL_IPC_USR_CHANNELS > 6)
107     /** User IPC channel 6 */
108     #define CYHAL_IPC_CHAN_6    (_CYHAL_IPC_CHAN_USER + 6)
109 #endif /* CYHAL_IPC_USR_CHANNELS > 6 */
110 #if (CYHAL_IPC_USR_CHANNELS > 7)
111     /** User IPC channel 7 */
112     #define CYHAL_IPC_CHAN_7    (_CYHAL_IPC_CHAN_USER + 7)
113 #endif /* CYHAL_IPC_USR_CHANNELS > 7 */
114 #if (CYHAL_IPC_USR_CHANNELS > 8)
115     /** User IPC channel 8 */
116     #define CYHAL_IPC_CHAN_8    (_CYHAL_IPC_CHAN_USER + 8)
117 #endif /* CYHAL_IPC_USR_CHANNELS > 8 */
118 #if (CYHAL_IPC_USR_CHANNELS > 9)
119     /** User IPC channel 9 */
120     #define CYHAL_IPC_CHAN_9    (_CYHAL_IPC_CHAN_USER + 9)
121 #endif /* CYHAL_IPC_USR_CHANNELS > 9 */
122 #if (CYHAL_IPC_USR_CHANNELS > 10)
123     /** User IPC channel 10 */
124     #define CYHAL_IPC_CHAN_10    (_CYHAL_IPC_CHAN_USER + 10)
125 #endif /* CYHAL_IPC_USR_CHANNELS > 10 */
126 #if (CYHAL_IPC_USR_CHANNELS > 11)
127     /** User IPC channel 11 */
128     #define CYHAL_IPC_CHAN_11    (_CYHAL_IPC_CHAN_USER + 11)
129 #endif /* CYHAL_IPC_USR_CHANNELS > 11 */
130 #if (CYHAL_IPC_USR_CHANNELS > 12)
131     /** User IPC channel 12 */
132     #define CYHAL_IPC_CHAN_12    (_CYHAL_IPC_CHAN_USER + 12)
133 #endif /* CYHAL_IPC_USR_CHANNELS > 12 */
134 #if (CYHAL_IPC_USR_CHANNELS > 13)
135     /** User IPC channel 13 */
136     #define CYHAL_IPC_CHAN_13    (_CYHAL_IPC_CHAN_USER + 13)
137 #endif /* CYHAL_IPC_USR_CHANNELS > 13 */
138 #if (CYHAL_IPC_USR_CHANNELS > 14)
139     /** User IPC channel 14 */
140     #define CYHAL_IPC_CHAN_14    (_CYHAL_IPC_CHAN_USER + 14)
141 #endif /* CYHAL_IPC_USR_CHANNELS > 14 */
142 #if (CYHAL_IPC_USR_CHANNELS > 15)
143     /** User IPC channel 15 */
144     #define CYHAL_IPC_CHAN_15    (_CYHAL_IPC_CHAN_USER + 15)
145 #endif /* CYHAL_IPC_USR_CHANNELS > 15 */
146 #if (CYHAL_IPC_USR_CHANNELS > 16)
147     #error "Unhandled number of free IPC channels"
148 #endif /* CYHAL_IPC_USR_CHANNELS > 16 */
149 
150 /** Definition of _CYHAL_IPC_INTR_USER which stands for first user-available IPC interrupt structure index */
151 #if defined(CY_IPC_INTR_USER)
152 #if defined(COMPONENT_CAT1D)
153 #define _CYHAL_IPC_INTR_USER            (CY_IPC_INTR_USER - IPC0_IPC_IRQ_NR)
154 #else
155 #define _CYHAL_IPC_INTR_USER            (CY_IPC_INTR_USER)
156 #endif
157 #elif defined(CY_IPC_INTR_SPARE)
158 #define _CYHAL_IPC_INTR_USER            (CY_IPC_INTR_SPARE)
159 #else
160 #define _CYHAL_IPC_INTR_USER            (CYHAL_IPC_CHAN_0)
161 #endif
162 
163 #define _CYHAL_IPC_CHAN_IDX_CORRECT(channel)    (((channel) >= CYHAL_IPC_CHAN_0) && ((channel) < (CYHAL_IPC_CHAN_0 + CYHAL_IPC_USR_CHANNELS)))
164 
165 #ifdef CPUSS_IPC_IPC_IRQ_NR
166 #define _CYHAL_IPC_RELEASE_INTR_BITS            (CPUSS_IPC_IPC_IRQ_NR)
167 #else
168 #define _CYHAL_IPC_RELEASE_INTR_BITS            (16u)
169 #endif
170 
171 #ifdef CY_IPC_CHAN_SEMA
172 #define _CYHAL_IPC_PDL_SEMA_CHAN                (CY_IPC_CHAN_SEMA)
173 #elif defined(COMPONENT_CAT1D)
174 /* Last available channel is used for semaphores */
175 #define _CYHAL_IPC_PDL_SEMA_CHAN                (CY_IPC_IP1_CH - 1)
176 #endif /* ifdef CY_IPC_CHAN_SEMA or other */
177 
178 /** \endcond */
179 
180 /** Number of semaphores, that can be used */
181 #ifdef CY_IPC_SEMA_COUNT
182 #define CYHAL_IPC_SEMA_COUNT               (CY_IPC_SEMA_COUNT)
183 #else
184 #define CYHAL_IPC_SEMA_COUNT               (128u)
185 #endif /* ifdef CY_IPC_SEMA_COUNT or other */
186 
187 /** The round up of cacheline size MACRO */
188 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
189 #define L1_DCACHE_LINE_BYTES_MASK         (uint32_t)(__SCB_DCACHE_LINE_SIZE - 1)
190 #define L1_DCACHE_ROUND_UP_BYTES(a)       (((uint32_t)(a) + L1_DCACHE_LINE_BYTES_MASK) & ~(L1_DCACHE_LINE_BYTES_MASK))
191 #define L1_DCACHE_LINE_WORDS_MASK         (uint32_t)((__SCB_DCACHE_LINE_SIZE >> 2) - 1)
192 #define L1_DCACHE_ROUND_UP_WORDS(a)       (((uint32_t)(a) + L1_DCACHE_LINE_WORDS_MASK) & ~(L1_DCACHE_LINE_WORDS_MASK))
193 #endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
194 
195 /** Macro for Queue pool shared memory allocation. Can be used only in function scope. Please use CY_SECTION_SHAREDMEM
196  * instead if allocation in global scope is needed.
197  * Params:
198  * queue_pool - void pointer to point to the shared memory
199  * NUM_ITEMS - number of items, that are expected to fit into the queue
200  * ITEMSIZE - size of one queue item (in bytes)
201  */
202 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
203 #define CYHAL_IPC_QUEUE_POOL_ALLOC(queue_pool, NUM_ITEMS, ITEMSIZE) \
204     do { \
205         CY_SECTION_SHAREDMEM static uint8_t _cyhal_ipc_queue_pool[L1_DCACHE_ROUND_UP_BYTES(ITEMSIZE * NUM_ITEMS)] CY_ALIGN(__SCB_DCACHE_LINE_SIZE); \
206         queue_pool = (void*)&_cyhal_ipc_queue_pool; \
207     } while (0)
208 #else
209 #define CYHAL_IPC_QUEUE_POOL_ALLOC(queue_pool, NUM_ITEMS, ITEMSIZE) \
210     do { \
211         CY_SECTION_SHAREDMEM static uint8_t _cyhal_ipc_queue_pool[ITEMSIZE * NUM_ITEMS]; \
212         queue_pool = (void*)&_cyhal_ipc_queue_pool; \
213     } while (0)
214 #endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
215 
216 /** Macro for Queue handle shared memory allocation. Can be used only in function scope. Please use CY_SECTION_SHAREDMEM
217  * instead if allocation in global scope is needed.
218  * Params:
219  * queue_handle - pointer to cyhal_ipc_queue_t data type, which will point to the shared memory
220  */
221 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
222 #define CYHAL_IPC_QUEUE_HANDLE_ALLOC(queue_handle) \
223     do { \
224         CY_SECTION_SHAREDMEM static cyhal_ipc_queue_t _cyhal_ipc_queue_handle CY_ALIGN(__SCB_DCACHE_LINE_SIZE); \
225         queue_handle = &_cyhal_ipc_queue_handle; \
226     } while (0)
227 #else
228 #define CYHAL_IPC_QUEUE_HANDLE_ALLOC(queue_handle) \
229     do { \
230         CY_SECTION_SHAREDMEM static cyhal_ipc_queue_t _cyhal_ipc_queue_handle; \
231         queue_handle = &_cyhal_ipc_queue_handle; \
232     } while (0)
233 #endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
234 
235 /** Polling interval, that will be used in blocking cyhal_ipc_* functions.
236  * It is recommended to use value either below 1000 (e.g. 750) or multiple of 1000 (e.g. 1000, 2000, 3000, etc.)
237  */
238 #ifndef CYHAL_IPC_POLLING_INTERVAL_uS
239 #define CYHAL_IPC_POLLING_INTERVAL_uS   (1000u)
240 #endif /* #ifndef CYHAL_IPC_POLLING_INTERVAL_uS */
241 
242 /** This macro defines what device's core will initialize IPC PDL semaphores in scope of cyhal_ipc_semaphore_init call.
243  * Please refer to implementation specific documentation for details.
244  */
245 #ifndef CYHAL_IPC_INIT_CORE
246 #if defined(CY_DEVICE_TVIIBE)
247 #define CYHAL_IPC_INIT_CORE CORE_NAME_CM4_0
248 #elif defined(COMPONENT_CAT1C)
249 #define CYHAL_IPC_INIT_CORE CORE_NAME_CM7_0
250 #elif defined(COMPONENT_CAT1D)
251 #define CYHAL_IPC_INIT_CORE CORE_NAME_CM55
252 #endif /* defined(COMPONENT_CAT1C) or defined(COMPONENT_CAT1D) */
253 #endif /* not defined (CYHAL_IPC_INIT_CORE) */
254 
255 /** Number of RTOS semaphores, that will be allocated and used by driver in RTOS environment
256  * (CY_RTOS_AWARE or COMPONENT_RTOS_AWARE should be defined). Usage of RTOS semaphores in IPC semaphores implementation
257  * helps to utilize waiting for semaphores times in RTOS environment more effectively. To achieve most effectiveness,
258  * it is recommended to define CYHAL_IPC_RTOS_SEMA_NUM value to be greater-equal to the number of IPC semaphores, that
259  * are planned to be used. Only semaphores with `semaphore_num`, that is less than _CYHAL_IPC_RELEASE_INTR_BITS can
260  * benefit from this feature.
261  * Value of this define can be 0. In this case, IPC HAL semaphores will not use RTOS semaphores.*/
262 #ifndef CYHAL_IPC_RTOS_SEMA_NUM
263 #define CYHAL_IPC_RTOS_SEMA_NUM         (4u)
264 #endif /* #ifndef CYHAL_IPC_RTOS_SEMA_NUM */
265 
266 #if (CYHAL_IPC_RTOS_SEMA_NUM > _CYHAL_IPC_RELEASE_INTR_BITS)
267 #error "Cannot handle selected amount of RTOS semaphores. Please fix CYHAL_IPC_RTOS_SEMA_NUM value"
268 #endif /* CYHAL_IPC_RTOS_SEMA_NUM > _CYHAL_IPC_RELEASE_INTR_BITS */
269 
270 /** \} group_hal_impl_ipc */
271 
272 #if defined(__cplusplus)
273 }
274 #endif /* __cplusplus */
275 
276 #endif /* CYHAL_DRIVER_AVAILABLE_IPC */
277