CIDU Functions

General

__STATIC_FORCEINLINE uint32_t CIDU_GetCoreNum (void)
__STATIC_FORCEINLINE uint32_t CIDU_GetIntNum (void)
CIDU_BASE __CIDU_BASEADDR
CIDU_RECEIVE_INTERRUPT_EN(core_id) (0x1U << core_id)
CIDU_CORE_INT_STATUS_OFS 0x0
CIDU_SEMAPHORE_OFS 0x80
CIDU_ICI_SHADOW_OFS 0x3FFC
CIDU_INT_INDICATOR_OFS 0x4000
CIDU_INT_MASK_OFS 0x8000
CIDU_CORE_NUM_OFS 0xC084
CIDU_INT_NUM_OFS 0xC090
CIDU_CORE_INT_STATUS_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_CORE_INT_STATUS_OFS) + ((n) << 2))
CIDU_SEMAPHORE_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_SEMAPHORE_OFS) + ((n) << 2))
CIDU_ICI_SHADOW_ADDR (unsigned long)((CIDU_BASE) + (CIDU_ICI_SHADOW_OFS))
CIDU_INT_INDICATOR_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_INT_INDICATOR_OFS) + ((n) << 2))
CIDU_INT_MASK_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_INT_MASK_OFS) + ((n) << 2))
CIDU_CORE_NUM_ADDR (unsigned long)((CIDU_BASE) + (CIDU_CORE_NUM_OFS))
CIDU_INT_NUM_ADDR (unsigned long)((CIDU_BASE) + (CIDU_INT_NUM_OFS))
CIDU_ICI_SEND_CORE_ID_POS 16
group CIDU Functions

Functions that manage external interrupts, inter core interrupts and semaphores.

Nuclei provide Cluster Interrupt Distribution Unit (CIDU) for scenarios that a SMP system is designed for real time application or both Linux and real time application, and Nuclei processor core can optionally support CIDU. The CIDU is used to distribute external interrupts to the core’s ECLIC, also it provides Inter Core Interrupt (ICI) and Semaphores Mechanism. Its features are as follows:

  • Support up to 16 Cores in one cluster

  • Support up to 4096 external interrupts sources

  • Support up to 16 Inter Core Interrupts

  • Support 32 Semaphores

Defines

CIDU_BASE __CIDU_BASEADDR
CIDU_RECEIVE_INTERRUPT_EN(core_id) (0x1U << core_id)

Indicates the core can receive corresponding interrupt.

CIDU_CORE_INT_STATUS_OFS 0x0

Core n Inter Core Interrupt status register base offset.

CIDU_SEMAPHORE_OFS 0x80

Semaphore n register base offset.

CIDU_ICI_SHADOW_OFS 0x3FFC

ICI Interrupt source core ID and target core ID register offset.

CIDU_INT_INDICATOR_OFS 0x4000

External interrupt n indicator register base offset.

CIDU_INT_MASK_OFS 0x8000

External interrupt n mask (mask interrupt n to cores or not when interrupt n indicator on)register base offset.

CIDU_CORE_NUM_OFS 0xC084

Static configuration core num register offset.

CIDU_INT_NUM_OFS 0xC090

Static configuration external interrupt number register offset.

CIDU_CORE_INT_STATUS_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_CORE_INT_STATUS_OFS) + ((n) << 2))

Core n Inter Core Interrupt status register address.

CIDU_SEMAPHORE_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_SEMAPHORE_OFS) + ((n) << 2))

Semaphore n register address.

CIDU_ICI_SHADOW_ADDR (unsigned long)((CIDU_BASE) + (CIDU_ICI_SHADOW_OFS))

ICI Interrupt source core ID and target core ID register address.

CIDU_INT_INDICATOR_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_INT_INDICATOR_OFS) + ((n) << 2))

External interrupt n indicator register address.

CIDU_INT_MASK_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_INT_MASK_OFS) + ((n) << 2))

External interrupt n mask (mask interrupt n to cores or not when interrupt n indicator on)register address.

CIDU_CORE_NUM_ADDR (unsigned long)((CIDU_BASE) + (CIDU_CORE_NUM_OFS))

Static configuration core num register address.

CIDU_INT_NUM_ADDR (unsigned long)((CIDU_BASE) + (CIDU_INT_NUM_OFS))

Static configuration external interrupt number register address.

CIDU_ICI_SEND_CORE_ID_POS 16

Functions

__STATIC_FORCEINLINE uint32_t CIDU_GetCoreNum (void)

Get core number in the cluster.

Indicate the static configuration core num in the cluster.

Remark

  • In a Nulcei multi-core system, each core has an identifiable serial number, the serial number starts from 0 and is continuous, also the number is static.

  • CORE_NUM register is read only.

Returns:

core number configured

__STATIC_FORCEINLINE uint32_t CIDU_GetIntNum (void)

Get external interrupt number.

Indicate the static configuration external interrupt number

Remark

  • INT_NUM register is read only.

Returns:

interrupt number configured

External Interrupt Distribution Functions

__STATIC_FORCEINLINE void CIDU_BroadcastExtInterrupt (uint32_t int_id, uint32_t to_cores)
__STATIC_FORCEINLINE uint32_t CIDU_GetBroadcastModeStatus (uint32_t int_id)
__STATIC_FORCEINLINE long CIDU_SetFirstClaimMode (uint32_t int_id, uint32_t core_id)
__STATIC_FORCEINLINE void CIDU_ResetFirstClaimMode (uint32_t int_id)
__STATIC_FORCEINLINE uint32_t CIDU_GetClaimStatus (uint32_t int_id)
group External Interrupt Distribution Functions

Functions that distribute external interrupts to cores.

Functions

__STATIC_FORCEINLINE void CIDU_BroadcastExtInterrupt (uint32_t int_id, uint32_t to_cores)

Broadcast external interrupt to cores.

This function broadcasts external interrupt which id is int_id to some/all target cores

Remark

  • External IRQn ID(int_id) is from the hard-wired persperctive, which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>

  • By default on reset, only core 0 can receive interrupt which id is int_id

Parameters:
  • int_id[in] external interrupt id

  • to_cores[in] target cores which can receive interrupt, use bitwise inclusive or of CIDU_RECEIVE_INTERRUPT_EN(core_id)

__STATIC_FORCEINLINE uint32_t CIDU_GetBroadcastModeStatus (uint32_t int_id)

get broadcast mode status

Just query the INTn_INDICATOR register value

Remark

  • External IRQn ID(int_id) is from the hard-wired persperctive, which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>

  • By default on reset, only core 0 can receive interrupt which id is int_id

Parameters:

int_id[in] external interrupt id

Returns:

INTn_INDICATOR register value

__STATIC_FORCEINLINE long CIDU_SetFirstClaimMode (uint32_t int_id, uint32_t core_id)

Let the first coming core to first claim the interrupt.

In external interrupt broadcast mode, make the first coming core to claim this interrupt and then can handle it.

Remark

  • External IRQn ID(int_id) is from the hard-wired persperctive, which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>.

  • If it fails to claim the interrupt, it should quit the interrupt n’s handler of all cores

  • When a core claims the interrupt successfully and has handled it, it must call CIDU_ResetFirstClaimMode to reset the claim.

See also

  • CIDU_BroadcastExtInterrupt

  • CIDU_ResetFirstClaimMode

Parameters:
  • int_id[in] external interrupt id

  • core_id[in] core id that receive the interrupt

Returns:

-1 if it fails to claim the interrupt, else it can continue to handle the interrupt

__STATIC_FORCEINLINE void CIDU_ResetFirstClaimMode (uint32_t int_id)

Reset the claim mode mask.

Reset the claim mode mask by Writing the reset value (all 1) to it

Remark

  • External IRQn ID(int_id) is from the hard-wired persperctive, which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>

  • When a core claims the interrupt successfully and handle it, it must call CIDU_ResetFirstClaimMode to reset the claim

See also

  • CIDU_SetFirstClaimMode

Parameters:

int_id[in] external interrupt id

__STATIC_FORCEINLINE uint32_t CIDU_GetClaimStatus (uint32_t int_id)

Get the claim mask status.

Get the claim mode staus, each bit[n] indicates whether core n has claimed interrupt successfully, 1 means yes, 0 means no.

Remark

  • External IRQn ID(int_id) is from the hard-wired persperctive, which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>

See also

  • CIDU_ResetFirstClaimMode

  • CIDU_SetFirstClaimMode

Parameters:

int_id[in] external interrupt id

Returns:

claim mode register INTn_MASK value

Inter Core Interrupt Functions

__STATIC_FORCEINLINE void CIDU_TriggerInterCoreInt (uint32_t send_core_id, uint32_t recv_core_id)
__STATIC_FORCEINLINE uint32_t CIDU_QueryCoreIntSenderMask (uint32_t recv_core_id)
__STATIC_FORCEINLINE void CIDU_ClearInterCoreIntReq (uint32_t send_core_id, uint32_t recv_core_id)
group Inter Core Interrupt Functions

Functions that implement Inter Core Interrupt mechanism.

Inter Core Interrupt (ICI) means that one core can send interrupt to another core in a multi-core cluster. CIDU ICI belongs to Internal Interrupt.

  • CIDU ICI Interrupt ID is fixed to 16.

Functions

__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.

When called by core send_core_id, CIDU will trigger ICI to core recv_core_id automatically. and core recv_core_id could query CIDU_GetCoreIntSenderId to know the sender.

Remark

  • The core recv_core_id need to call CIDU_ClearInterCoreIntReq to clear the corresponding bit/bits of its own COREn_INT_STATUS.

  • It supports that multiple cores call CIDU_TriggerInterCoreInt simultaneously.

See also

  • CIDU_GetCoreIntSenderId

  • CIDU_ClearInterCoreIntReq

Parameters:
  • send_core_id[in] the core id which want to send the inter core interrupt

  • recv_core_id[in] the core id which will receive the inter core interrupt

__STATIC_FORCEINLINE uint32_t CIDU_QueryCoreIntSenderMask (uint32_t recv_core_id)

Core recv_core_id queries out who sends inter core interrupt to itself.

In the ISR of ICI, receive core can query if bit[n] of this return value is 1, core n sends the current ICI, if bit[m] is 1, then core m also sends, etc.

Remark

  • If the ICI ISR has finished the job, should call CIDU_ClearInterCoreIntReq to clear the IRQ

Parameters:

recv_core_id[in] the core id which receives the inter core interrupt

Returns:

Value that shows sender core’s ID n whose bitn is 1

__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.

Core recv_core_id write 1 to clear the bit send_core_id of the core recv_core_id’s COREn_INT_STATUS.

Remark

  • If the ICI ISR has finished the job of send_core_id_n’s ICI, then clear bit send_core_id_n; if it has finished send_core_id_n and send_core_id_m’s, then should clear both the bits, etc.

Parameters:
  • send_core_id[in] the core id which wants to send the inter core interrupt

  • recv_core_id[in] the core id which will receive the inter core interrupt

Semaphore Functions

__STATIC_FORCEINLINE uint32_t CIDU_GetSemaphoreStatus (uint32_t semph_n)
__STATIC_FORCEINLINE long CIDU_CheckSemaphoreAcquired (uint32_t semph_n, uint32_t core_id)
__STATIC_FORCEINLINE long CIDU_AcquireSemaphore (uint32_t semph_n, uint32_t core_id)
__STATIC_FORCEINLINE void CIDU_AcquireSemaphore_Block (uint32_t semph_n, uint32_t core_id)
__STATIC_FORCEINLINE void CIDU_ReleaseSemaphore (uint32_t semph_n)
group Semaphore Functions

Functions that configure and use semaphores

Semaphore is very useful for multi-core cluster without SMP enable.

  • All Cores in the cluster agree on using SEMAPHORE_n register to protect a critical resource (an UART device for example).

  • If Core n wants to access the critical resource, it should try to own the SEMPAPHORE_n register, or else it can’t access the critical resource.

  • When the Core n owns the register SEMPAPHORE_n and finishes the job related the critical resource, then it should release the register by writing all 1 to it.

Functions

__STATIC_FORCEINLINE uint32_t CIDU_GetSemaphoreStatus (uint32_t semph_n)

Get SEMAPHOREn’s value.

Just query the semaphore n’s value

Parameters:

semph_n[in] the semaphore id used to protect a critical resource

Returns:

register SEMAPHOREn_STATUS value

__STATIC_FORCEINLINE long CIDU_CheckSemaphoreAcquired (uint32_t semph_n, uint32_t core_id)

check SEMAPHOREn’s acquired status

Query that whether SEMAPHOREn has been acquired by one core successfully.

Remark

  • When the core n owns the register SEMPAPHORE_n and finishes the job related the critical resource, it should call CIDU_ReleaseSemaphore to release it.

See also

  • CIDU_GetSemaphoreStatus

  • CIDU_ReleaseSemaphore

Parameters:
  • semph_n[in] the semaphore id used to protect a critical resource

  • core_id[in] the core id that wants to access the critical resource

Returns:

0 if core_id has acquired this semaphore successfully, or else -1 if failed

__STATIC_FORCEINLINE long CIDU_AcquireSemaphore (uint32_t semph_n, uint32_t core_id)

Acquire the SEMAPHOREn.

Acuqire the SEMAPHOREn, and check the acquired status

Remark

  • When the core n owns the register SEMPAPHORE_n and finishes the job related the critical resource, it should call CIDU_ReleaseSemaphore to release it.

See also

  • CIDU_CheckSemaphoreAcquired

  • CIDU_ReleaseSemaphore

Parameters:
  • semph_n[in] the semaphore id used to protect a critical resource

  • core_id[in] the core id that wants to access the critical resource

Returns:

0 if core_id has acquired this semaphore successfully, or else -1 if failed

__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.

Query that whether SEMAPHOREn has been owned by one core successfully, if not, keep trying.

Remark

  • Core n will block here acquiring, so take care that core should release the semaphore when related job done.

See also

  • CIDU_AcquireSemaphore

  • CIDU_ReleaseSemaphore

Parameters:
  • semph_n[in] the semaphore id used to protect a critical resource

  • core_id[in] the core id that wants to access the critical resource

__STATIC_FORCEINLINE void CIDU_ReleaseSemaphore (uint32_t semph_n)

Release the SEMAPHOREn.

Release the SEMAPHOREn by writing all 1 to SEMAPHOREn register.

Remark

  • When the core finishes the job related to the critical resource, it should release the corresponding semaphore.

See also

  • CIDU_AcquireSemaphore_Block

Parameters:

semph_n[in] the semaphore id used to protect a critical resource