NMSIS-Core  Version 1.4.0
NMSIS-Core support for Nuclei processor-based devices
core_feature_cidu.h
1 /*
2  * Copyright (c) 2019 Nuclei Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #ifndef __CORE_FEATURE_CIDU_H__
19 #define __CORE_FEATURE_CIDU_H__
24 /*
25  * CIDU Feature Configuration Macro:
26  * 1. __CIDU_PRESENT: Define whether Cluster Interrupt Distribution Unit is present or not.
27  * * 0: Not present
28  * * 1: Present
29  * 2. __CIDU_BASEADDR: Define the base address of the CIDU.
30  */
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #include "core_feature_base.h"
36 
37 #if defined(__CIDU_PRESENT) && (__CIDU_PRESENT == 1)
38 
39 /* ########################## CIDU functions #################################### */
59 #ifndef __CIDU_BASEADDR
60 /* Base address of CIDU(__CIDU_BASEADDR) should be defined in <Device.h> */
61 #error "__CIDU_BASEADDR is not defined, please check!"
62 #endif
63 
64 #define CIDU_BASE __CIDU_BASEADDR
65 #define CIDU_RECEIVE_INTERRUPT_EN(core_id) (0x1UL << core_id)
67 #define CIDU_CORE_INT_STATUS_OFS 0x0
68 #define CIDU_SEMAPHORE_OFS 0x80
69 #define CIDU_ICI_SHADOW_OFS 0x3FFC
70 #define CIDU_INT_INDICATOR_OFS 0x4000
71 #define CIDU_INT_MASK_OFS 0x8000
72 #define CIDU_CORE_NUM_OFS 0xC084
73 #define CIDU_INT_NUM_OFS 0xC090
75 #define CIDU_CORE_INT_STATUS_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_CORE_INT_STATUS_OFS) + ((n) << 2))
76 #define CIDU_SEMAPHORE_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_SEMAPHORE_OFS) + ((n) << 2))
77 #define CIDU_ICI_SHADOW_ADDR (unsigned long)((CIDU_BASE) + (CIDU_ICI_SHADOW_OFS))
78 #define CIDU_INT_INDICATOR_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_INT_INDICATOR_OFS) + ((n) << 2))
79 #define CIDU_INT_MASK_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_INT_MASK_OFS) + ((n) << 2))
80 #define CIDU_CORE_NUM_ADDR (unsigned long)((CIDU_BASE) + (CIDU_CORE_NUM_OFS))
81 #define CIDU_INT_NUM_ADDR (unsigned long)((CIDU_BASE) + (CIDU_INT_NUM_OFS))
84 /* SEND_CORE_ID position in ICI_SHADOW_REG register */
85 #define CIDU_ICI_SEND_CORE_ID_POS 16
86 
98 {
99  uint32_t val;
100  uint32_t* addr = (uint32_t*)CIDU_CORE_NUM_ADDR;
101 
102  val = __LW(addr);
103  return val;
104 }
105 
115 {
116  uint32_t val;
117  uint32_t* addr = (uint32_t*)CIDU_INT_NUM_ADDR;
118 
119  val = __LW(addr);
120  return val;
121 } /* End of Doxygen Group NMSIS_Core_CIDU */
123 
143 __STATIC_FORCEINLINE void CIDU_BroadcastExtInterrupt(uint32_t int_id, uint32_t to_cores)
144 {
145  uint32_t* addr = (uint32_t*)CIDU_INT_INDICATOR_ADDR(int_id);
146 
147  __SW(addr, (uint32_t)to_cores);
148 }
149 
162 {
163  uint32_t val = 0;
164  uint32_t* addr = (uint32_t*)CIDU_INT_INDICATOR_ADDR(int_id);
165 
166  val = __LW(addr);
167  return val;
168 }
169 
186 __STATIC_FORCEINLINE long CIDU_SetFirstClaimMode(uint32_t int_id, uint32_t core_id)
187 {
188  uint32_t val = 0;
189  uint32_t* addr = (uint32_t*)CIDU_INT_MASK_ADDR(int_id);
190  uint32_t mask = 1UL << core_id;
191 
192  __SW(addr, mask);
193  val = __LW(addr);
194  if (mask == val) {
195  return 0;
196  }
197  return -1;
198 }
199 
213 {
214  uint32_t val = 0;
215  uint32_t* addr = (uint32_t*)CIDU_INT_MASK_ADDR(int_id);
216 
217  /* clear by writing all 1 */
218  __SW(addr, 0xFFFFFFFF);
219 }
220 
235 __STATIC_FORCEINLINE uint32_t CIDU_GetClaimStatus(uint32_t int_id)
236 {
237  uint32_t val = 0;
238  uint32_t* addr = (uint32_t*)CIDU_INT_MASK_ADDR(int_id);
239 
240  val = __LW(addr);
241  return val;
242 } /* End of Doxygen Group NMSIS_Core_Distribute_Interrupt */
244 
271 __STATIC_FORCEINLINE void CIDU_TriggerInterCoreInt(uint32_t send_core_id, uint32_t recv_core_id)
272 {
273  uint32_t val = 0;
274  uint32_t* addr = (uint32_t*)CIDU_ICI_SHADOW_ADDR;
275 
276  val = (uint32_t)(send_core_id << CIDU_ICI_SEND_CORE_ID_POS) | (uint32_t)(recv_core_id);
277  __SW(addr, (uint32_t)val);
278 }
279 
290 __STATIC_FORCEINLINE uint32_t CIDU_QueryCoreIntSenderMask(uint32_t recv_core_id)
291 {
292  uint32_t val = 0;
293  uint32_t* addr = (uint32_t*)CIDU_CORE_INT_STATUS_ADDR(recv_core_id);
294 
295  val = __LW(addr);
296  return val;
297 }
298 
309 __STATIC_FORCEINLINE void CIDU_ClearInterCoreIntReq(uint32_t send_core_id, uint32_t recv_core_id)
310 {
311  uint32_t val = 0;
312  uint32_t* addr = (uint32_t*)CIDU_CORE_INT_STATUS_ADDR(recv_core_id);
313 
314  val = (uint32_t)(1UL << send_core_id);
315  __SW(addr, val);
316 } /* End of Doxygen Group NMSIS_Core_ICI */
318 
340 {
341  uint32_t val;
342  uint32_t* addr = (uint32_t*)CIDU_SEMAPHORE_ADDR(semph_n);
343 
344  val = __LW(addr);
345  return val;
346 }
347 
362 __STATIC_FORCEINLINE long CIDU_CheckSemaphoreAcquired(uint32_t semph_n, uint32_t core_id)
363 {
364  uint32_t val;
365  val = CIDU_GetSemaphoreStatus(semph_n);
366  if (core_id != val) {
367  return -1;
368  }
369  return 0;
370 }
371 
386 __STATIC_FORCEINLINE long CIDU_AcquireSemaphore(uint32_t semph_n, uint32_t core_id)
387 {
388  long semaphore_status = -1;
389  uint32_t* addr = (uint32_t*)CIDU_SEMAPHORE_ADDR(semph_n);
390 
391  __SW(addr, core_id);
392  semaphore_status = CIDU_CheckSemaphoreAcquired(semph_n, core_id);
393  return semaphore_status;
394 }
395 
408 __STATIC_FORCEINLINE void CIDU_AcquireSemaphore_Block(uint32_t semph_n, uint32_t core_id)
409 {
410  int32_t semaphore_status = -1;
411 
412  while(0 != semaphore_status) {
413  semaphore_status = CIDU_AcquireSemaphore(semph_n, core_id);
414  }
415 }
416 
428 {
429  uint32_t* addr = (uint32_t*)CIDU_SEMAPHORE_ADDR(semph_n);
430 
431  /* Release by writing all 1 */
432  __SW(addr, 0xFFFFFFFF);
433 } /* End of Doxygen Group NMSIS_Core_Semaphore */
435  /* End of Doxygen Group NMSIS_Core_CIDU_Functions */
437 #endif /* defined(__CIDU_PRESENT) && (__CIDU_PRESENT == 1) */
438 
439 #ifdef __cplusplus
440 }
441 #endif
442 #endif /* __CORE_FEATURE_CIDU_H__ */
#define CIDU_ICI_SEND_CORE_ID_POS
#define CIDU_CORE_INT_STATUS_ADDR(n)
Core n Inter Core Interrupt status register address.
__STATIC_FORCEINLINE uint32_t CIDU_GetCoreNum(void)
Get core number in the cluster.
#define CIDU_INT_NUM_ADDR
Static configuration external interrupt number register address.
#define CIDU_INT_INDICATOR_ADDR(n)
External interrupt n indicator register address.
__STATIC_FORCEINLINE uint32_t CIDU_GetIntNum(void)
Get external interrupt number.
#define CIDU_CORE_NUM_ADDR
Static configuration core num register address.
#define CIDU_ICI_SHADOW_ADDR
ICI Interrupt source core ID and target core ID register address.
#define CIDU_INT_MASK_ADDR(n)
External interrupt n mask (mask interrupt n to cores or not when interrupt n indicator on)register ad...
#define CIDU_SEMAPHORE_ADDR(n)
Semaphore n register address.
__STATIC_FORCEINLINE void __SW(volatile void *addr, uint32_t val)
Write 32bit value to address (32 bit)
__STATIC_FORCEINLINE uint32_t __LW(volatile void *addr)
Load 32bit value from address (32 bit)
#define __STATIC_FORCEINLINE
Define a static function that should be always inlined by the compiler.
Definition: nmsis_gcc.h:70
__STATIC_FORCEINLINE uint32_t CIDU_GetBroadcastModeStatus(uint32_t int_id)
get broadcast mode status
__STATIC_FORCEINLINE uint32_t CIDU_GetClaimStatus(uint32_t int_id)
Get the claim mask status.
__STATIC_FORCEINLINE long CIDU_SetFirstClaimMode(uint32_t int_id, uint32_t core_id)
Let the first coming core to first claim the interrupt.
__STATIC_FORCEINLINE void CIDU_ResetFirstClaimMode(uint32_t int_id)
Reset the claim mode mask.
__STATIC_FORCEINLINE void CIDU_BroadcastExtInterrupt(uint32_t int_id, uint32_t to_cores)
Broadcast external interrupt to cores.
__STATIC_FORCEINLINE void CIDU_TriggerInterCoreInt(uint32_t send_core_id, uint32_t recv_core_id)
Trigger interrupt to another core in a multi-core cluster.
__STATIC_FORCEINLINE void CIDU_ClearInterCoreIntReq(uint32_t send_core_id, uint32_t recv_core_id)
Clear the corresponding bit/bits of ICI request triggered by sender core.
__STATIC_FORCEINLINE uint32_t CIDU_QueryCoreIntSenderMask(uint32_t recv_core_id)
Core recv_core_id queries out who sends inter core interrupt to itself.
__STATIC_FORCEINLINE uint32_t CIDU_GetSemaphoreStatus(uint32_t semph_n)
Get SEMAPHOREn's value.
__STATIC_FORCEINLINE long CIDU_AcquireSemaphore(uint32_t semph_n, uint32_t core_id)
Acquire the SEMAPHOREn.
__STATIC_FORCEINLINE void CIDU_ReleaseSemaphore(uint32_t semph_n)
Release the SEMAPHOREn.
__STATIC_FORCEINLINE long CIDU_CheckSemaphoreAcquired(uint32_t semph_n, uint32_t core_id)
check SEMAPHOREn's acquired status
__STATIC_FORCEINLINE void CIDU_AcquireSemaphore_Block(uint32_t semph_n, uint32_t core_id)
Keep acquiring the SEMAPHOREn until it has acquired this semaphore successfully.