/* * Copyright 2021-2023 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #ifndef FSL_MU_H_ #define FSL_MU_H_ #include "fsl_common.h" /*! * @addtogroup mu * @{ */ /****************************************************************************** * Definitions *****************************************************************************/ /*! * @name Driver version * @{ */ /*! @brief MU driver version. */ #define FSL_MU_DRIVER_VERSION (MAKE_VERSION(2, 5, 0)) /*! @} */ #define MU_CORE_INTR(intr) ((uint32_t)(intr) << 0U) #define MU_MISC_INTR(intr) ((uint32_t)(intr) << 8U) #define MU_TX_INTR(intr) ((uint32_t)(intr) << 20U) #define MU_RX_INTR(intr) ((uint32_t)(intr) << 24U) #define MU_GI_INTR(intr) ((uint32_t)(intr) << 28U) #define MU_GET_CORE_INTR(intrs) (((uint32_t)(intrs) >> 0U) & 0xFFUL) #define MU_GET_TX_INTR(intrs) (((uint32_t)(intrs) >> 20U) & 0xFUL) #define MU_GET_RX_INTR(intrs) (((uint32_t)(intrs) >> 24U) & 0xFUL) #define MU_GET_GI_INTR(intrs) (((uint32_t)(intrs) >> 28U) & 0xFUL) #define MU_CORE_FLAG(flag) ((uint32_t)(flag) << 0U) #define MU_STAT_FLAG(flag) ((uint32_t)(flag) << 8U) #define MU_TX_FLAG(flag) ((uint32_t)(flag) << 20U) #define MU_RX_FLAG(flag) ((uint32_t)(flag) << 24U) #define MU_GI_FLAG(flag) ((uint32_t)(flag) << 28U) #define MU_GET_CORE_FLAG(flags) (((uint32_t)(flags) >> 0U) & 0xFFUL) #define MU_GET_STAT_FLAG(flags) (((uint32_t)(flags) >> 8U) & 0xFFUL) #define MU_GET_TX_FLAG(flags) (((uint32_t)(flags) >> 20U) & 0xFUL) #define MU_GET_RX_FLAG(flags) (((uint32_t)(flags) >> 24U) & 0xFUL) #define MU_GET_GI_FLAG(flags) (((uint32_t)(flags) >> 28U) & 0xFUL) /* General Purpose Interrupts count. */ #ifndef FSL_FEATURE_MU_GPI_COUNT #define FSL_FEATURE_MU_GPI_COUNT 4U #endif /*! * @brief MU status flags. */ enum _mu_status_flags { kMU_Tx0EmptyFlag = MU_TX_FLAG(1UL << 0U), /*!< TX0 empty. */ kMU_Tx1EmptyFlag = MU_TX_FLAG(1UL << 1U), /*!< TX1 empty. */ kMU_Tx2EmptyFlag = MU_TX_FLAG(1UL << 2U), /*!< TX2 empty. */ kMU_Tx3EmptyFlag = MU_TX_FLAG(1UL << 3U), /*!< TX3 empty. */ kMU_Rx0FullFlag = MU_RX_FLAG(1UL << 0U), /*!< RX0 full. */ kMU_Rx1FullFlag = MU_RX_FLAG(1UL << 1U), /*!< RX1 full. */ kMU_Rx2FullFlag = MU_RX_FLAG(1UL << 2U), /*!< RX2 full. */ kMU_Rx3FullFlag = MU_RX_FLAG(1UL << 3U), /*!< RX3 full. */ kMU_GenInt0Flag = MU_GI_FLAG(1UL << 0U), /*!< General purpose interrupt 0 pending. */ kMU_GenInt1Flag = MU_GI_FLAG(1UL << 1U), /*!< General purpose interrupt 1 pending. */ kMU_GenInt2Flag = MU_GI_FLAG(1UL << 2U), /*!< General purpose interrupt 2 pending. */ kMU_GenInt3Flag = MU_GI_FLAG(1UL << 3U), /*!< General purpose interrupt 3 pending. */ #if !(defined(FSL_FEATURE_MU_NO_CEP) && (0 != FSL_FEATURE_MU_NO_CEP)) kMU_CoreEventPendingFlag = MU_STAT_FLAG(MU_SR_CEP_MASK), /*!< The other core mode entry event pending. */ #endif kMU_RxFullPendingFlag = MU_STAT_FLAG(MU_SR_RFP_MASK), /*!< Any RX full flag is pending. */ kMU_TxEmptyPendingFlag = MU_STAT_FLAG(MU_SR_TEP_MASK), /*!< Any TX empty flag is pending. */ kMU_GenIntPendingFlag = MU_STAT_FLAG(MU_SR_GIRP_MASK), /*!< Any general interrupt flag is pending. */ kMU_EventPendingFlag = MU_STAT_FLAG(MU_SR_EP_MASK), /*!< MU event pending. */ kMU_FlagsUpdatingFlag = MU_STAT_FLAG(MU_SR_FUP_MASK), /*!< MU flags update is on-going. */ kMU_MuInResetFlag = MU_STAT_FLAG(MU_SR_MURS_MASK), /*!< MU of any side is in reset. */ #if !(defined(FSL_FEATURE_MU_HAS_SR_MURIP) && (FSL_FEATURE_MU_HAS_SR_MURIP == 0)) kMU_MuResetInterruptFlag = MU_STAT_FLAG(MU_SR_MURIP_MASK), /*!< The other side initializes MU reset. */ #endif #if !(defined(FSL_FEATURE_MU_NO_CORE_STATUS) && (0 != FSL_FEATURE_MU_NO_CORE_STATUS)) #if !(defined(FSL_FEATURE_MU_HAS_RUN_INT) && (FSL_FEATURE_MU_HAS_RUN_INT == 0)) kMU_OtherSideEnterRunInterruptFlag = MU_CORE_FLAG(MU_CSSR0_RUN_MASK), /*!< The other side enters run mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_HALT_INT) && (FSL_FEATURE_MU_HAS_HALT_INT == 0)) kMU_OtherSideEnterHaltInterruptFlag = MU_CORE_FLAG(MU_CSSR0_HALT_MASK), /*!< The other side enters halt mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_WAIT_INT) && (FSL_FEATURE_MU_HAS_WAIT_INT == 0)) kMU_OtherSideEnterWaitInterruptFlag = MU_CORE_FLAG(MU_CSSR0_WAIT_MASK), /*!< The other side enters wait mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_STOP_INT) && (FSL_FEATURE_MU_HAS_STOP_INT == 0)) kMU_OtherSideEnterStopInterruptFlag = MU_CORE_FLAG(MU_CSSR0_STOP_MASK), /*!< The other side enters stop mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_PD_INT) && (FSL_FEATURE_MU_HAS_PD_INT == 0)) /*! The other side enters power down mode. */ kMU_OtherSideEnterPowerDownInterruptFlag = MU_CORE_FLAG(MU_CSSR0_PD_MASK), #endif #if !(defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && (FSL_FEATURE_MU_HAS_RESET_ASSERT_INT == 0)) /*! The other core reset assert interrupt. */ kMU_ResetAssertInterruptFlag = MU_CORE_FLAG(MU_CSSR0_RAIP_MASK), #endif #if !(defined(FSL_FEATURE_MU_HAS_SR_HRIP) && (FSL_FEATURE_MU_HAS_SR_HRIP == 0)) /*! Current side has been hardware reset by the other side. */ kMU_HardwareResetInterruptFlag = MU_CORE_FLAG(MU_CSSR0_HRIP_MASK), #endif #endif /* FSL_FEATURE_MU_NO_CORE_STATUS */ }; /*! * @brief MU interrupt source to enable. */ enum _mu_interrupt_enable { kMU_Tx0EmptyInterruptEnable = MU_TX_INTR(1UL << 0U), /*!< TX0 empty. */ kMU_Tx1EmptyInterruptEnable = MU_TX_INTR(1UL << 1U), /*!< TX1 empty. */ kMU_Tx2EmptyInterruptEnable = MU_TX_INTR(1UL << 2U), /*!< TX2 empty. */ kMU_Tx3EmptyInterruptEnable = MU_TX_INTR(1UL << 3U), /*!< TX3 empty. */ kMU_Rx0FullInterruptEnable = MU_RX_INTR(1UL << 0U), /*!< RX0 full. */ kMU_Rx1FullInterruptEnable = MU_RX_INTR(1UL << 1U), /*!< RX1 full. */ kMU_Rx2FullInterruptEnable = MU_RX_INTR(1UL << 2U), /*!< RX2 full. */ kMU_Rx3FullInterruptEnable = MU_RX_INTR(1UL << 3U), /*!< RX3 full. */ kMU_GenInt0InterruptEnable = MU_GI_INTR(1UL << 0U), /*!< General purpose interrupt 0. */ kMU_GenInt1InterruptEnable = MU_GI_INTR(1UL << 1U), /*!< General purpose interrupt 1. */ kMU_GenInt2InterruptEnable = MU_GI_INTR(1UL << 2U), /*!< General purpose interrupt 2. */ kMU_GenInt3InterruptEnable = MU_GI_INTR(1UL << 3U), /*!< General purpose interrupt 3. */ #if !(defined(FSL_FEATURE_MU_NO_CORE_STATUS) && (0 != FSL_FEATURE_MU_NO_CORE_STATUS)) #if !(defined(FSL_FEATURE_MU_HAS_RUN_INT) && (FSL_FEATURE_MU_HAS_RUN_INT == 0)) kMU_OtherSideEnterRunInterruptEnable = MU_CORE_INTR(MU_CIER0_RUNIE_MASK), /*!< The other side enters run mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_HALT_INT) && (FSL_FEATURE_MU_HAS_HALT_INT == 0)) kMU_OtherSideEnterHaltInterruptEnable = MU_CORE_INTR(MU_CIER0_HALTIE_MASK), /*!< The other side enters halt mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_WAIT_INT) && (FSL_FEATURE_MU_HAS_WAIT_INT == 0)) kMU_OtherSideEnterWaitInterruptEnable = MU_CORE_INTR(MU_CIER0_WAITIE_MASK), /*!< The other side enters wait mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_STOP_INT) && (FSL_FEATURE_MU_HAS_STOP_INT == 0)) kMU_OtherSideEnterStopInterruptEnable = MU_CORE_INTR(MU_CIER0_STOPIE_MASK), /*!< The other side enters stop mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_PD_INT) && (FSL_FEATURE_MU_HAS_PD_INT == 0)) /*! The other side enters power down mode. */ kMU_OtherSideEnterPowerDownInterruptEnable = MU_CORE_INTR(MU_CIER0_PDIE_MASK), #endif #if !(defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && (FSL_FEATURE_MU_HAS_RESET_ASSERT_INT == 0)) /*! The other core reset assert interrupt. */ kMU_ResetAssertInterruptEnable = MU_CORE_INTR(MU_CIER0_RAIE_MASK), #endif #if !(defined(FSL_FEATURE_MU_HAS_SR_HRIP) && (FSL_FEATURE_MU_HAS_SR_HRIP == 0)) /*! Current side has been hardware reset by the other side. */ kMU_HardwareResetInterruptEnable = MU_CORE_INTR(MU_CIER0_HRIE_MASK), #endif #endif /* FSL_FEATURE_MU_NO_CORE_STATUS */ #if !(defined(FSL_FEATURE_MU_HAS_SR_MURIP) && (FSL_FEATURE_MU_HAS_SR_MURIP == 0)) kMU_MuResetInterruptEnable = MU_MISC_INTR(MU_CR_MURIE_MASK), /*!< The other side initializes MU reset. */ #endif }; /*! * @brief MU interrupt that could be triggered to the other core. */ enum _mu_interrupt_trigger { kMU_GenInt0InterruptTrigger = MU_GI_INTR(1UL << 0U), /*!< General purpose interrupt 0. */ kMU_GenInt1InterruptTrigger = MU_GI_INTR(1UL << 1U), /*!< General purpose interrupt 1. */ kMU_GenInt2InterruptTrigger = MU_GI_INTR(1UL << 2U), /*!< General purpose interrupt 2. */ kMU_GenInt3InterruptTrigger = MU_GI_INTR(1UL << 3U), /*!< General purpose interrupt 3. */ }; #if !(defined(FSL_FEATURE_MU_NO_CORE_STATUS) && (0 != FSL_FEATURE_MU_NO_CORE_STATUS)) /*! * @brief MU core status flags. */ enum _mu_core_status_flags { #if !(defined(FSL_FEATURE_MU_HAS_RUN_INT) && (FSL_FEATURE_MU_HAS_RUN_INT == 0)) kMU_OtherSideEnterRunFlag = MU_CSSR0_RUN_MASK, /*!< The other side in run mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_HALT_INT) && (FSL_FEATURE_MU_HAS_HALT_INT == 0)) kMU_OtherSideEnterHaltFlag = MU_CSSR0_HALT_MASK, /*!< The other side in halt mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_WAIT_INT) && (FSL_FEATURE_MU_HAS_WAIT_INT == 0)) kMU_OtherSideEnterWaitFlag = MU_CSSR0_WAIT_MASK, /*!< The other side in wait mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_STOP_INT) && (FSL_FEATURE_MU_HAS_STOP_INT == 0)) kMU_OtherSideEnterStopFlag = MU_CSSR0_STOP_MASK, /*!< The other side in stop mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_PD_INT) && (FSL_FEATURE_MU_HAS_PD_INT == 0)) kMU_OtherSideEnterPowerDownFlag = MU_CSSR0_PD_MASK, /*!< The other side in power down mode. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_RESET_ASSERT_INT) && (FSL_FEATURE_MU_HAS_RESET_ASSERT_INT == 0)) kMU_OtherSideEnterResetFlag = MU_CSSR0_RAIP_MASK, /*!< The other core entered reset. */ #endif #if !(defined(FSL_FEATURE_MU_HAS_SR_HRIP) && (FSL_FEATURE_MU_HAS_SR_HRIP == 0)) kMU_HardwareResetFlag = MU_CSSR0_HRIP_MASK, /*!< Current side has been hardware reset by the other side. */ #endif }; #endif /* FSL_FEATURE_MU_NO_CORE_STATUS */ /*! * @brief MU message register index. */ typedef enum _mu_msg_reg_index { kMU_MsgReg0 = 0, /*!< Message register 0. */ kMU_MsgReg1, /*!< Message register 1. */ kMU_MsgReg2, /*!< Message register 2. */ kMU_MsgReg3, /*!< Message register 3. */ } mu_msg_reg_index_t; #if (defined(FSL_FEATURE_MU_HAS_BOOT) && (0 == FSL_FEATURE_MU_HAS_BOOT)) /*! * @brief The other core boot mode. */ typedef enum _mu_core_boot_mode { kMU_CoreBootModeDummy = 0x0U, /*!< MU doesn't support boot mode selection, only for API compatibility. */ } mu_core_boot_mode_t; #endif /*! * @brief MU general purpose interrupts */ typedef enum _mu_general_purpose_interrupt { kMU_GeneralPurposeInterrupt0 = 1UL << 0U, /*!< General purpose interrupt 0 */ kMU_GeneralPurposeInterrupt1 = 1UL << 1U, /*!< General purpose interrupt 1 */ kMU_GeneralPurposeInterrupt2 = 1UL << 2U, /*!< General purpose interrupt 2 */ kMU_GeneralPurposeInterrupt3 = 1UL << 3U, /*!< General purpose interrupt 3 */ #if (FSL_FEATURE_MU_GPI_COUNT > 4U) kMU_GeneralPurposeInterrupt4 = 1UL << 4U, /*!< General purpose interrupt 4 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 5U) kMU_GeneralPurposeInterrupt5 = 1UL << 5U, /*!< General purpose interrupt 5 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 6U) kMU_GeneralPurposeInterrupt6 = 1UL << 6U, /*!< General purpose interrupt 6 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 7U) kMU_GeneralPurposeInterrupt7 = 1UL << 7U, /*!< General purpose interrupt 7 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 8U) kMU_GeneralPurposeInterrupt8 = 1UL << 8U, /*!< General purpose interrupt 8 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 9U) kMU_GeneralPurposeInterrupt9 = 1UL << 9U, /*!< General purpose interrupt 9 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 10U) kMU_GeneralPurposeInterrupt10 = 1UL << 10U, /*!< General purpose interrupt 10 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 11U) kMU_GeneralPurposeInterrupt11 = 1UL << 11U, /*!< General purpose interrupt 11 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 12U) kMU_GeneralPurposeInterrupt12 = 1UL << 12U, /*!< General purpose interrupt 12 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 13U) kMU_GeneralPurposeInterrupt13 = 1UL << 13U, /*!< General purpose interrupt 13 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 14U) kMU_GeneralPurposeInterrupt14 = 1UL << 14U, /*!< General purpose interrupt 14 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 15U) kMU_GeneralPurposeInterrupt15 = 1UL << 15U, /*!< General purpose interrupt 15 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 16U) kMU_GeneralPurposeInterrupt16 = 1UL << 16U, /*!< General purpose interrupt 16 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 17U) kMU_GeneralPurposeInterrupt17 = 1UL << 17U, /*!< General purpose interrupt 17 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 18U) kMU_GeneralPurposeInterrupt18 = 1UL << 18U, /*!< General purpose interrupt 18 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 19U) kMU_GeneralPurposeInterrupt19 = 1UL << 19U, /*!< General purpose interrupt 19 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 20U) kMU_GeneralPurposeInterrupt20 = 1UL << 20U, /*!< General purpose interrupt 20 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 21U) kMU_GeneralPurposeInterrupt21 = 1UL << 21U, /*!< General purpose interrupt 21 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 22U) kMU_GeneralPurposeInterrupt22 = 1UL << 22U, /*!< General purpose interrupt 22 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 23U) kMU_GeneralPurposeInterrupt23 = 1UL << 23U, /*!< General purpose interrupt 23 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 24U) kMU_GeneralPurposeInterrupt24 = 1UL << 24U, /*!< General purpose interrupt 24 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 25U) kMU_GeneralPurposeInterrupt25 = 1UL << 25U, /*!< General purpose interrupt 25 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 26U) kMU_GeneralPurposeInterrupt26 = 1UL << 26U, /*!< General purpose interrupt 26 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 27U) kMU_GeneralPurposeInterrupt27 = 1UL << 27U, /*!< General purpose interrupt 27 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 28U) kMU_GeneralPurposeInterrupt28 = 1UL << 28U, /*!< General purpose interrupt 28 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 29U) kMU_GeneralPurposeInterrupt29 = 1UL << 29U, /*!< General purpose interrupt 29 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 30U) kMU_GeneralPurposeInterrupt30 = 1UL << 30U, /*!< General purpose interrupt 30 */ #endif #if (FSL_FEATURE_MU_GPI_COUNT > 31U) kMU_GeneralPurposeInterrupt31 = 1UL << 31U, /*!< General purpose interrupt 31 */ #endif } mu_general_purpose_interrupt_t; /******************************************************************************* * API ******************************************************************************/ #if defined(__cplusplus) extern "C" { #endif /*! * @name MU instance. * @{ */ /*! * @brief Get the MU instance index. * * @param base MU peripheral base address. * @return MU instance index. */ uint32_t MU_GetInstance(MU_Type *base); /*! @} */ /*! * @name MU initialization. * @{ */ /*! * @brief Initializes the MU module. * * This function enables the MU clock only. * * @param base MU peripheral base address. */ void MU_Init(MU_Type *base); /*! * @brief De-initializes the MU module. * * This function disables the MU clock only. * * @param base MU peripheral base address. */ void MU_Deinit(MU_Type *base); /*! @} */ /*! * @name MU Message * @{ */ /*! * @brief Writes a message to the TX register. * * This function writes a message to the specific TX register. It does not check * whether the TX register is empty or not. The upper layer should make sure the TX * register is empty before calling this function. This function can be used * in ISR for better performance. * * @code * while (!(kMU_Tx0EmptyFlag & MU_GetStatusFlags(base))) { } Wait for TX0 register empty. * MU_SendMsgNonBlocking(base, kMU_MsgReg0, MSG_VAL); Write message to the TX0 register. * @endcode * * @param base MU peripheral base address. * @param regIndex TX register index, see @ref mu_msg_reg_index_t. * @param msg Message to send. */ static inline void MU_SendMsgNonBlocking(MU_Type *base, uint32_t regIndex, uint32_t msg) { assert(regIndex < MU_TR_COUNT); base->TR[regIndex] = msg; } /*! * @brief Blocks to send a message. * * This function waits until the TX register is empty and sends the message. * * @param base MU peripheral base address. * @param regIndex MU message register, see @ref mu_msg_reg_index_t. * @param msg Message to send. */ void MU_SendMsg(MU_Type *base, uint32_t regIndex, uint32_t msg); /*! * @brief Reads a message from the RX register. * * This function reads a message from the specific RX register. It does not check * whether the RX register is full or not. The upper layer should make sure the RX * register is full before calling this function. This function can be used * in ISR for better performance. * * @code * uint32_t msg; * while (!(kMU_Rx0FullFlag & MU_GetStatusFlags(base))) * { * } Wait for the RX0 register full. * * msg = MU_ReceiveMsgNonBlocking(base, kMU_MsgReg0); Read message from RX0 register. * @endcode * * @param base MU peripheral base address. * @param regIndex RX register index, see @ref mu_msg_reg_index_t. * @return The received message. */ static inline uint32_t MU_ReceiveMsgNonBlocking(MU_Type *base, uint32_t regIndex) { assert(regIndex < MU_TR_COUNT); return base->RR[regIndex]; } /*! * @brief Blocks to receive a message. * * This function waits until the RX register is full and receives the message. * * @param base MU peripheral base address. * @param regIndex MU message register, see @ref mu_msg_reg_index_t * @return The received message. */ uint32_t MU_ReceiveMsg(MU_Type *base, uint32_t regIndex); /*! @} */ /*! * @name MU Flags * @{ */ /*! * @brief Sets the 3-bit MU flags reflect on the other MU side. * * This function sets the 3-bit MU flags directly. Every time the 3-bit MU flags are changed, * the status flag \c kMU_FlagsUpdatingFlag asserts indicating the 3-bit MU flags are * updating to the other side. After the 3-bit MU flags are updated, the status flag * \c kMU_FlagsUpdatingFlag is cleared by hardware. During the flags updating period, * the flags cannot be changed. The upper layer should make sure the status flag * \c kMU_FlagsUpdatingFlag is cleared before calling this function. * * @code * while (kMU_FlagsUpdatingFlag & MU_GetStatusFlags(base)) * { * } Wait for previous MU flags updating. * * MU_SetFlagsNonBlocking(base, 0U); Set the mU flags. * @endcode * * @param base MU peripheral base address. * @param flags The 3-bit MU flags to set. */ static inline void MU_SetFlagsNonBlocking(MU_Type *base, uint32_t flags) { base->FCR = flags; } /*! * @brief Blocks setting the 3-bit MU flags reflect on the other MU side. * * This function blocks setting the 3-bit MU flags. Every time the 3-bit MU flags are changed, * the status flag \c kMU_FlagsUpdatingFlag asserts indicating the 3-bit MU flags are * updating to the other side. After the 3-bit MU flags are updated, the status flag * \c kMU_FlagsUpdatingFlag is cleared by hardware. During the flags updating period, * the flags cannot be changed. This function waits for the MU status flag * \c kMU_FlagsUpdatingFlag cleared and sets the 3-bit MU flags. * * @param base MU peripheral base address. * @param flags The 3-bit MU flags to set. */ void MU_SetFlags(MU_Type *base, uint32_t flags); /*! * @brief Gets the current value of the 3-bit MU flags set by the other side. * * This function gets the current 3-bit MU flags on the current side. * * @param base MU peripheral base address. * @return flags Current value of the 3-bit flags. */ static inline uint32_t MU_GetFlags(MU_Type *base) { return base->FSR; } /*! @} */ /*! * @name Status and Interrupt. * @{ */ #if !(defined(FSL_FEATURE_MU_NO_CORE_STATUS) && (0 != FSL_FEATURE_MU_NO_CORE_STATUS)) /*! * @brief Gets the MU core status flags. * * @param base MU peripheral base address. * @return Bit mask of the MU status flags, see @ref _mu_core_status_flags. */ static inline uint32_t MU_GetCoreStatusFlags(MU_Type *base) { return base->CSR0; } #endif /* FSL_FEATURE_MU_NO_CORE_STATUS */ /*! * @brief Gets the MU status flags. * * This function returns the bit mask of the MU status flags. See _mu_status_flags. * * @code * uint32_t flags; * flags = MU_GetStatusFlags(base); Get all status flags. * if (kMU_Tx0EmptyFlag & flags) * { * The TX0 register is empty. Message can be sent. * MU_SendMsgNonBlocking(base, kMU_MsgReg0, MSG0_VAL); * } * if (kMU_Tx1EmptyFlag & flags) * { * The TX1 register is empty. Message can be sent. * MU_SendMsgNonBlocking(base, kMU_MsgReg1, MSG1_VAL); * } * @endcode * * If there are more than 4 general purpose interrupts, use @ref MU_GetGeneralPurposeStatusFlags. * * @param base MU peripheral base address. * @return Bit mask of the MU status flags, see _mu_status_flags. */ uint32_t MU_GetStatusFlags(MU_Type *base); /*! * @brief Clears the specific MU status flags. * * This function clears the specific MU status flags. The flags to clear should * be passed in as bit mask. See _mu_status_flags. * * @code * Clear general interrupt 0 and general interrupt 1 pending flags. * MU_ClearStatusFlags(base, kMU_GenInt0Flag | kMU_GenInt1Flag); * @endcode * * If there are more than 4 general purpose interrupts, use @ref MU_ClearGeneralPurposeStatusFlags. * * @param base MU peripheral base address. * @param flags Bit mask of the MU status flags. See _mu_status_flags. Only the * following flags can be cleared by software, other flags are cleared by hardware: * - #kMU_GenInt0Flag * - #kMU_GenInt1Flag * - #kMU_GenInt2Flag * - #kMU_GenInt3Flag * - #kMU_MuResetInterruptFlag * - #kMU_OtherSideEnterRunInterruptFlag * - #kMU_OtherSideEnterHaltInterruptFlag * - #kMU_OtherSideEnterWaitInterruptFlag * - #kMU_OtherSideEnterStopInterruptFlag * - #kMU_OtherSideEnterPowerDownInterruptFlag * - #kMU_ResetAssertInterruptFlag * - #kMU_HardwareResetInterruptFlag */ static inline void MU_ClearStatusFlags(MU_Type *base, uint32_t flags) { uint32_t tmp; /* General interrupt tmp. */ tmp = MU_GET_GI_FLAG(flags); if (0U != tmp) { base->GSR = tmp; } #if !(defined(FSL_FEATURE_MU_NO_CORE_STATUS) && (0 != FSL_FEATURE_MU_NO_CORE_STATUS)) /* Core interrupt. */ tmp = MU_GET_CORE_FLAG(flags); if (0U != tmp) { base->CSSR0 = tmp; } #endif /* FSL_FEATURE_MU_NO_CORE_STATUS */ #if !(defined(FSL_FEATURE_MU_HAS_SR_MURIP) && (FSL_FEATURE_MU_HAS_SR_MURIP == 0)) /* kMU_MuResetInterruptFlag. */ if (0U != ((uint32_t)kMU_MuResetInterruptFlag & flags)) { base->SR = MU_SR_MURIP_MASK; } #endif } /*! * @brief Enables the specific MU interrupts. * * This function enables the specific MU interrupts. The interrupts to enable * should be passed in as bit mask. See _mu_interrupt_enable. * * @code * Enable general interrupt 0 and TX0 empty interrupt. * MU_EnableInterrupts(base, kMU_GenInt0InterruptEnable | kMU_Tx0EmptyInterruptEnable); * @endcode * * If there are more than 4 general purpose interrupts, use @ref MU_EnableGeneralPurposeInterrupts. * * @param base MU peripheral base address. * @param interrupts Bit mask of the MU interrupts. See _mu_interrupt_enable. */ static inline void MU_EnableInterrupts(MU_Type *base, uint32_t interrupts) { uint32_t tmp; /* TX message interrupts. */ tmp = MU_GET_TX_INTR(interrupts); if (0U != tmp) { base->TCR |= tmp; } /* RX message interrupts. */ tmp = MU_GET_RX_INTR(interrupts); if (0U != tmp) { base->RCR |= tmp; } /* General purpose interrupts. */ tmp = MU_GET_GI_INTR(interrupts); if (0U != tmp) { base->GIER |= tmp; } /* Core interrupts. */ tmp = MU_GET_CORE_INTR(interrupts); if (0U != tmp) { base->CIER0 |= tmp; } #if !(defined(FSL_FEATURE_MU_HAS_SR_MURIP) && (FSL_FEATURE_MU_HAS_SR_MURIP == 0)) if (0U != ((uint32_t)kMU_MuResetInterruptEnable & interrupts)) { base->CR |= MU_CR_MURIE_MASK; } #endif } /*! * @brief Disables the specific MU interrupts. * * This function disables the specific MU interrupts. The interrupts to disable * should be passed in as bit mask. See _mu_interrupt_enable. * * @code * Disable general interrupt 0 and TX0 empty interrupt. * MU_DisableInterrupts(base, kMU_GenInt0InterruptEnable | kMU_Tx0EmptyInterruptEnable); * @endcode * * If there are more than 4 general purpose interrupts, use @ref MU_DisableGeneralPurposeInterrupts. * * @param base MU peripheral base address. * @param interrupts Bit mask of the MU interrupts. See _mu_interrupt_enable. */ static inline void MU_DisableInterrupts(MU_Type *base, uint32_t interrupts) { uint32_t tmp; /* TX message interrupts. */ tmp = MU_GET_TX_INTR(interrupts); if (0U != tmp) { base->TCR &= ~tmp; } /* RX message interrupts. */ tmp = MU_GET_RX_INTR(interrupts); if (0U != tmp) { base->RCR &= ~tmp; } /* General purpose interrupts. */ tmp = MU_GET_GI_INTR(interrupts); if (0U != tmp) { base->GIER &= ~tmp; } /* Core interrupts. */ tmp = MU_GET_CORE_INTR(interrupts); if (0U != tmp) { base->CIER0 &= ~tmp; } #if !(defined(FSL_FEATURE_MU_HAS_SR_MURIP) && (FSL_FEATURE_MU_HAS_SR_MURIP == 0)) if (0U != ((uint32_t)kMU_MuResetInterruptEnable & interrupts)) { base->CR &= ~MU_CR_MURIE_MASK; } #endif } /*! * @brief Triggers interrupts to the other core. * * This function triggers the specific interrupts to the other core. The interrupts * to trigger are passed in as bit mask. See \ref _mu_interrupt_trigger. * The MU should not trigger an interrupt to the other core when the previous interrupt * has not been processed by the other core. This function checks whether the * previous interrupts have been processed. If not, it returns an error. * * @code * if (kStatus_Success != MU_TriggerInterrupts(base, kMU_GenInt0InterruptTrigger | kMU_GenInt2InterruptTrigger)) * { * Previous general purpose interrupt 0 or general purpose interrupt 2 * has not been processed by the other core. * } * @endcode * * If there are more than 4 general purpose interrupts, use @ref MU_TriggerGeneralPurposeInterrupts. * * @param base MU peripheral base address. * @param interrupts Bit mask of the interrupts to trigger. See _mu_interrupt_trigger. * @retval kStatus_Success Interrupts have been triggered successfully. * @retval kStatus_Fail Previous interrupts have not been accepted. */ status_t MU_TriggerInterrupts(MU_Type *base, uint32_t interrupts); #if !(defined(FSL_FEATURE_MU_NO_NMI) && (0 != FSL_FEATURE_MU_NO_NMI)) /*! * @brief Triggers NMI to the other core. * * This function triggers the NMI to the other core. * The MU should not trigger NMI to the other core when the previous interrupt * has not been processed by the other core. This function checks whether the * previous interrupts have been processed. If not, it returns an error. * * @param base MU peripheral base address. * @retval kStatus_Success Interrupts have been triggered successfully. * @retval kStatus_Fail Previous interrupts have not been accepted. */ status_t MU_TriggerNmi(MU_Type *base); /*! * @brief Clear non-maskable interrupt (NMI) sent by the other core. * * This function clears non-maskable interrupt (NMI) sent by the other core. * * @param base MU peripheral base address. */ static inline void MU_ClearNmi(MU_Type *base) { base->CSSR0 = MU_CSSR0_NMIC_MASK; } #endif /* FSL_FEATURE_MU_NO_NMI */ /*! @} */ /*! * @name MU general purpose interrupt * @{ */ /*! * @brief Enables the MU general purpose interrupts. * * This function enables the MU general purpose interrupts. The interrupts * to enable should be passed in as bit mask of @ref mu_general_purpose_interrupt_t. * The function @ref MU_EnableInterrupts only support general interrupt 0~3, * this function supports all general interrupts. * * For example, to enable general purpose interrupt 0 and 3, use like this: * @code MU_EnableGeneralPurposeInterrupts(MU, kMU_GeneralPurposeInterrupt0 | kMU_GeneralPurposeInterrupt3); @endcode * * @param base MU peripheral base address. * @param interrupts Bit mask of the MU general purpose interrupts, * see @ref mu_general_purpose_interrupt_t. */ static inline void MU_EnableGeneralPurposeInterrupts(MU_Type *base, uint32_t interrupts) { base->GIER |= interrupts; } /*! * @brief Disables the MU general purpose interrupts. * * This function disables the MU general purpose interrupts. The interrupts * to disable should be passed in as bit mask of @ref mu_general_purpose_interrupt_t. * The function @ref MU_DisableInterrupts only support general interrupt 0~3, * this function supports all general interrupts. * * For example, to disable general purpose interrupt 0 and 3, use like this: * @code MU_EnableGeneralPurposeInterrupts(MU, kMU_GeneralPurposeInterrupt0 | kMU_GeneralPurposeInterrupt3); @endcode * * @param base MU peripheral base address. * @param interrupts Bit mask of the MU general purpose interrupts. * see @ref mu_general_purpose_interrupt_t. */ static inline void MU_DisableGeneralPurposeInterrupts(MU_Type *base, uint32_t interrupts) { base->GIER &= ~interrupts; } /*! * @brief Gets the MU general purpose interrupt status flags. * * This function returns the bit mask of the MU general purpose interrupt status flags. * @ref MU_GetStatusFlags can only get general purpose interrupt status 0~3, * this function can get all general purpose interrupts status. * * This example shows to check whether general purpose interrupt 0 and 3 happened. * * @code uint32_t flags; flags = MU_GetGeneralPurposeStatusFlags(base); if (kMU_GeneralPurposeInterrupt0 & flags) { } if (kMU_GeneralPurposeInterrupt3 & flags) { } @endcode * * @param base MU peripheral base address. * @return Bit mask of the MU general purpose interrupt status flags. */ static inline uint32_t MU_GetGeneralPurposeStatusFlags(MU_Type *base) { return base->GSR; } /*! * @brief Clear the MU general purpose interrupt status flags. * * This function clears the specific MU general purpose interrupt status flags. The flags to clear should * be passed in as bit mask. mu_general_purpose_interrupt_t_mu_status_flags. * * Example to clear general purpose interrupt 0 and general interrupt 1 pending flags. * @code MU_ClearGeneralPurposeStatusFlags(base, kMU_GeneralPurposeInterrupt0 | kMU_GeneralPurposeInterrupt1); @endcode * * @param base MU peripheral base address. * @param flags Bit mask of the MU general purpose interrupt status flags. * See @ref mu_general_purpose_interrupt_t. */ static inline void MU_ClearGeneralPurposeStatusFlags(MU_Type *base, uint32_t flags) { base->GSR = flags; } /*! * @brief Triggers general purpose interrupts to the other core. * * This function triggers the specific general purpose interrupts to the other core. * The interrupts to trigger are passed in as bit mask. See @ref mu_general_purpose_interrupt_t. * The MU should not trigger an interrupt to the other core when the previous interrupt * has not been processed by the other core. This function checks whether the * previous interrupts have been processed. If not, it returns an error. * * @code status_t status; status = MU_TriggerGeneralPurposeInterrupts(base, kMU_GeneralPurposeInterrupt0 | kMU_GeneralPurposeInterrupt2); if (kStatus_Success != status) { Previous general purpose interrupt 0 or general purpose interrupt 2 has not been processed by the other core. } @endcode * * @param base MU peripheral base address. * @param interrupts Bit mask of the interrupts to trigger. See @ref mu_general_purpose_interrupt_t. * @retval kStatus_Success Interrupts have been triggered successfully. * @retval kStatus_Fail Previous interrupts have not been accepted. */ status_t MU_TriggerGeneralPurposeInterrupts(MU_Type *base, uint32_t interrupts); /*! @} */ /*! * @name MU misc functions * @{ */ #if !(defined(FSL_FEATURE_MU_HAS_BOOT) && (0 == FSL_FEATURE_MU_HAS_BOOT)) /*! * @brief Boots the other core. * * This function boots the other core with a boot configuration. * * @param base MU peripheral base address. * @param mode The other core boot mode. */ void MU_BootOtherCore(MU_Type *base, mu_core_boot_mode_t mode); #endif /* FSL_FEATURE_MU_HAS_BOOT */ #if !(defined(FSL_FEATURE_MU_HAS_RSTH) && (0 == FSL_FEATURE_MU_HAS_RSTH)) /*! * @brief Holds the other core reset. * * This function causes the other core to be held in reset following any reset event. * * @param base MU peripheral base address. */ void MU_HoldOtherCoreReset(MU_Type *base); #endif /* FSL_FEATURE_MU_HAS_RSTH */ /*! * @brief Resets the MU for both A side and B side. * * This function resets the MU for both A side and B side. Before reset, it is * recommended to interrupt processor B, because this function may affect the * ongoing processor B programs. * * @param base MU peripheral base address. */ static inline void MU_ResetBothSides(MU_Type *base) { base->CR |= MU_CR_MUR_MASK; while (0U != (base->SR & MU_SR_MURS_MASK)) { } } #if !(defined(FSL_FEATURE_MU_NO_CLKE) && (0 != FSL_FEATURE_MU_NO_CLKE)) /*! * @brief Enables or disables the clock on the other core. * * This function enables or disables the platform clock on the other core when * that core enters a stop mode. If disabled, the platform clock for the other * core is disabled when it enters stop mode. If enabled, the platform clock * keeps running on the other core in stop mode, until this core also enters * stop mode. * * @param base MU peripheral base address. * @param enable Enable or disable the clock on the other core. */ static inline void MU_SetClockOnOtherCoreEnable(MU_Type *base, bool enable) { if (enable) { base->CCR0 |= MU_CCR0_CLKE_MASK; } else { base->CCR0 &= ~MU_CCR0_CLKE_MASK; } } #endif #if !(defined(FSL_FEATURE_MU_HAS_HR) && (FSL_FEATURE_MU_HAS_HR == 0)) /*! * @brief Hardware reset the other core. * * This function resets the other core, the other core could mask the * hardware reset by calling MU_MaskHardwareReset. The hardware reset * mask feature is only available for some platforms. * This function could be used together with MU_BootOtherCore to control the * other core reset workflow. * * Example 1: Reset the other core, and no hold reset * @code * MU_HardwareResetOtherCore(MU_A, true, false, bootMode); * @endcode * In this example, the core at MU side B will reset with the specified boot mode. * * Example 2: Reset the other core and hold it, then boot the other core later. * @code * Here the other core enters reset, and the reset is hold * MU_HardwareResetOtherCore(MU_A, true, true, modeDontCare); * Current core boot the other core when necessary. * MU_BootOtherCore(MU_A, bootMode); * @endcode * * @note The feature waitReset, holdReset, and bootMode might be not supported * for some platforms. waitReset is only available for platforms that * FSL_FEATURE_MU_NO_CORE_STATUS not defined as 1 and * FSL_FEATURE_MU_HAS_RESET_ASSERT_INT not defined as 0. holdReset is only available * for platforms that FSL_FEATURE_MU_HAS_RSTH not defined as 0. * bootMode is only available for platforms that FSL_FEATURE_MU_HAS_BOOT not * defined as 0. * * @param base MU peripheral base address. * @param waitReset Wait the other core enters reset. Only work when there is CSSR0[RAIP] * - true: Wait until the other core enters reset, if the other * core has masked the hardware reset, then this function will * be blocked. * - false: Don't wait the reset. * @param holdReset Hold the other core reset or not. Only work when there is CCR0[RSTH] * - true: Hold the other core in reset, this function returns * directly when the other core enters reset. * - false: Don't hold the other core in reset, this function * waits until the other core out of reset. * @param bootMode Boot mode of the other core, if @p holdReset is true, this * parameter is useless. */ void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode); #endif /* FSL_FEATURE_MU_HAS_HR */ #if (defined(FSL_FEATURE_MU_HAS_HRM) && FSL_FEATURE_MU_HAS_HRM) /*! * @brief Mask hardware reset by the other core. * * The other core could call MU_HardwareResetOtherCore() to reset current core. * To mask the reset, call this function and pass in true. * * @param base MU peripheral base address. * @param mask Pass true to mask the hardware reset, pass false to unmask it. */ static inline void MU_MaskHardwareReset(MU_Type *base, bool mask) { #if !(defined(FSL_FEATURE_MU_NO_NMI) && (0 != FSL_FEATURE_MU_NO_NMI)) if (mask) { base->CCR0 |= (base->CCR0 & ~(MU_CCR0_HR_MASK | MU_CCR0_NMI_MASK)) | MU_CCR0_HRM_MASK; } else { base->CCR0 |= (base->CCR0 & ~(MU_CCR0_HR_MASK | MU_CCR0_NMI_MASK | MU_CCR0_HRM_MASK)); } #else if (mask) { base->CCR0 |= (base->CCR0 & ~(MU_CCR0_HR_MASK)) | MU_CCR0_HRM_MASK; } else { base->CCR0 |= (base->CCR0 & ~(MU_CCR0_HR_MASK | MU_CCR0_HRM_MASK)); } #endif } #endif /* FSL_FEATURE_MU_HAS_HRM */ /*! @} */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! @} */ #endif /* FSL_MU_H_*/