/***************************************************************************//** * \file cy_ipc_drv.h * \version 1.60 * * Provides an API declaration of the IPC driver. * ******************************************************************************** * \copyright * Copyright 2016-2020 Cypress Semiconductor Corporation * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ #ifndef CY_IPC_DRV_H #define CY_IPC_DRV_H /** * \addtogroup group_ipc * \{ * The inter-processor communication (IPC) driver provides a safe and reliable * method to transfer data between CPUs. Hardware locking ensures that only one * device can acquire and transfer data at a time so no data is lost or * overwritten by asynchronous processes or CPUs. * * Include either cy_ipc_pipe.h, cy_ipc_sema.h or cy_ipc_bt.h. Alternatively include cy_pdl.h * to get access to all functions and declarations in the PDL. * * There are three parts to the API: * - Driver-level (DRV) API - used internally by Semaphore, Pipe and Bluetooth levels * - Pipe-level (PIPE) API - establishes a communication channel between * processors * - Semaphore-level (SEMA) API - enables users to set and clear flags to * synchronize operations. * - Bluetooth Subsystem (BTSS) API - establishes communication channel * between MCU and the BTSS * * Firmware does not need to use the DRV API. It can implement IPC functionality * entirely with the PIPE, SEMA and BTSS APIs. * * \section group_ipc_background Background * * IPC is implemented in hardware as a collection of individual communication * channels, each with a set of 32-bit registers. The IPC design implements a set * of interrupts that enable each processor to notify the other that data is * available, or has been processed. There is also a locking mechanism that * allows only one CPU to gain access at a time. * * The Driver-level API manages each channel's registers to implement IPC * functionality. For information on the IPC registers, see the IPC chapter of * the Technical Reference Manual (TRM). * * At the hardware level, communication is a five-step process. * -# The sending processor acquires a channel * -# It puts data into the channel * -# The sender generates a notify event (interrupt) * -# The receiving processor identifies the sender and retrieves the data * -# The receiving processor generates a release event (interrupt) * * \image html ipc_driver.png * * These transactions are handled transparently by the DRV-level API. Use the * PIPE, SEMA and BTSS layers of the API to implement communication in your application. * The data transferred is limited to a single 32-bit value incase of PIPE and SEMA and two * 32 bit value incse of BTIPC. As implemented by * the PIPE API, that value is a pointer to a data structure of arbitrary size * and complexity. * BTSS uses both 32 bit registers for communication of short messages. If the payload * is greater than 7 bytes, then it copies the data to the shared memory between MCU * and the BT SS. * * \section group_ipc_overview Overview * * The Pipe is the key element in the PDL design. A pipe is typically a * full-duplex communication channel between CPU cores. A pipe allows a single * conduit to transfer messages or data to and from multiple processes or CPUs. * * A pipe has two endpoints, one on each core. Each endpoint contains a dedicated * IPC channel and an interrupt. IPC channels 0-7(8 for the CYB064XX devices) * and IPC interrupts 0-7 are reserved for system use. * * The pipe also contains the number of clients it supports, and for each client * a callback function. So the pipe can service a number of clients, each with a * separate callback function, on either endpoint. The number of clients a pipe * supports is the sum of each endpoint's clients. * * This design enables any number of processes on the sending core to put * arbitrary data into a single pipe. The first element of that data is the * client ID of the client that should handle the data. * * An interrupt notifies the receiving core that data is available. The receiving * core parses the data to identify the client, and then dispatches the event to * the appropriate client via the client callback function. An interrupt notifies * the sending core that the receiver is finished. In this way a single pipe can * manage arbitrary data transfers between cores with data flowing in either * direction. * * \image html ipc_ints.png * * The application can use semaphores to control access to shared resources, as * required by the application's logic. * * The PDL provides specific files that set up default IPC functionality. * They are system_psoc6.h, system_psoc6_cm0plus.c and system_psoc6_cm4.c. You * can modify these files based on the requirements of your design. * If you use PSoC Creator as a development environment, it will not overwrite * your changes when you generate the application or build your code. * * BTSS provides dedicated communication channels for communication between * MCU and the BT SS. APIs provided handle exchange of HCI and HPC packets * using 4 dedicated IPC channels. Two dedicated Up Link (UL) channels, one for HCI * and another for HPC from MCU to BT SS and two dedicated Down Link (DL) channels, * one for HCI and another for HPC from BT SS to MCU are used. * * \section group_ipc_pipe_layer PIPE layer * * A pipe is a communication channel between two endpoints. PSoC 6 devices support * 16 IPC channels, and 16 IPC interrupts, each numbered 0-15. IPC Channels 0-7 * and IPC interrupts 0-7 are reserved for system use. Channels 8-15 and * interrupts 8-15 are available for application use. * * A full duplex pipe uses two IPC channels, one per endpoint. Each endpoint * specifies all the information required to process a message (either sent or * received). Each endpoint is configured to use an IPC channel, and an IPC * interrupt. Common practice is to use the interrupt with the same number as * the IPC channel. However, IPC Interrupts are not directly associated with the * IPC channels, so any channel can use any interrupt. Any IPC channel can * trigger 0, 1 or all the IPC interrupts at once, depending on the Notify or * Release masks used. * * It is also possible to set up a one-directional pipe, using a single IPC * channel. In this design one processor is always the sender, and the other is * always the receiver. However, there are still two endpoints. * * A pipe supports an arbitrary number of clients with an array of callback * functions, one per client. The client ID is the index number into the array * for the client. After a pipe is configured and initialized, the application * calls Cy_IPC_Pipe_RegisterCallback() once per client to register each client's * callback function. Multiple clients can use the same callback function. The * endpoints in a pipe share the callback array. * * Use Cy_IPC_Pipe_SendMessage() to send data. You specify both the "to" and * "from" endpoints, and a callback function to be used when the data transfer is * complete. The data is a 32-bit void pointer. The data pointed to is arbitrary, * and can be an array, a structure, or a location in memory. The only limitation * is that the first element of the data must be a 32-bit unsigned word containing * a client ID number. The ID number is the index into the callback array. * * When a message is sent, the receiving endpoint's interrupt handler is called. * The ISR can perform any task required by the design. However, as part of its * function it calls \ref Cy_IPC_Pipe_ExecCallback. This function retrieves the * client ID from the data and calls the associated callback function. * The user-supplied callback function handles the data in whatever way is * appropriate based on the application logic. * * After the callback function is returned by the receiver, it invokes the release * callback function defined by the sender of the message. * * \section group_ipc_sema_layer SEMA Layer * * A semaphore is a flag the application uses to control access to a shared * resource. The SEMA-level API uses an IPC channel to implement * semaphores. Startup code sets up a default semaphore system. The * default system creates an array of 128 semaphores (four 32-bit values). * Semaphores 0-15 are reserved for system use. See * Configuration Considerations - SEMA. * * Functions are available to initialize the semaphore system, to set or * clear a semaphore, or to get the semaphore's current status. Application * logic uses SEMA functions to relate a particular semaphore to a particular * shared resource, and set, clear, or check the flag when accessing the * shared resource. * * \section group_ipc_bt_layer BTSS layer * * A Bluetooth Sub-system (BTSS) layer is a communication channel between the MCU and the BT * Sub-system. It uses 4 IPC channels and 2 interrupts. 2 UL channels ( one for HCI and HPC each) * and 2 DL channels (one for HCI and HPC each). IPC interrupt 0 is used to interrupt the * BT SS and IPC interrupt 1 is used to interrupt the MCU. * IPC channels 0 is used for HCI UL, channel 1 is used from HCI DL, * IPC channels 2 is used for HPC UL,and channel 3 is used from HPC DL. * The IPC interrupt gets triggered for both Notify and Release channel. * Bluetooth stack interface layer registers a callback function for notification * when BT SS sends an HCI packet. It also provides APIs to read the * HCI packets from the BT SS. On the UL path, it supports APIs to send HCI packet * from MCU to BT SS. * * The communication is made more efficient by elimilnating the need for buffers * by packing them into the DATA0 and DATA1 IPC channel registers when payload * length is less than or equal to 7 bytes . In case the where the payload length * is greater than 7bytes, it would use the shared memory to send/recevive the packet. * * This layer support control message communication between the MCU and the BT SS * using the HPC channels. The HPC channel is used for power manamgement, * IO configuration, access for TRNG, etc. APIs are provided to send HPC packets to the * BT SS. It also supports APIs to register the callback function to get notification on receiving * the HPC packets from the BT SS. Multiple modules running on the MCU can register * callback functions. Maximum number of HPC callbacks supported is decided by * the MAX_BT_IPC_HPC_CB macro. All the shared buffer management mechanism * is built into this layer. * * \section group_ipc_configuration_cypipe Configuration Considerations - CYPIPE * * There are none. The startup files set up the required CYPIPE for system * use. Do not modify the CYPIPE. It uses IPC channels 5 and 6 to implement full * duplex communication between cores. See System Interrupt (SysInt) for background. * * To create your own pipe (<b>USRPIPE</b>) you should edit startup files * and take 4 steps: * -# Define a pipe callbacks processing interrupt handler * (similar to <b>Cy_SysIpcPipeIsrCm0</b> or <b>Cy_SysIpcPipeIsrCm4</b>) * -# Define a callbacks array (similar to <b>systemIpcPipeSysCbArray</b>) * -# Define your pipe configuration with a cy_stc_ipc_pipe_config_t type structure * (similar to <b>systemIpcPipeConfigCm0</b> and <b>systemIpcPipeConfigCm4</b>) * -# Call Cy_IPC_Pipe_Init() from each core to initialize your pipe (similar * to call in the <b>SystemInit</b>) * * \section group_ipc_configuration_sema Configuration Considerations - SEMA * * Startup code calls Cy_IPC_Sema_Init() with default values to set up semaphore * functionality. By default the semaphore system uses IPC channel 4, and * creates 128 semaphores. Do <b>not</b> change the IPC channel. * You can change the number of semaphores. * * To change the number of semaphores, modify this line of code in system_psoc6.h. * * \code * #define CY_IPC_SEMA_COUNT (uint32_t)(128u) * \endcode * * Startup also declares array ipcSemaArray to hold the semaphore * flags based on the size defined for this symbol. Use increments of 32. You * must have at least 32 semaphores. Semaphores 0-15 are reserved for * system use. Your application can use semaphores greater than 15. * * \section group_ipc_configuration_btss Configuration Considerations - BTSS * * Application code calls Cy_BTIPC_Init() with configuration parameters to set up BTSS IPC * functionality. By default the BT IPC uses IPC channel 0,1,2 and 3. * Do <b>not</b> change the IPC channel. * * To change the number of callbacks supported, modify this line of code in cy_ipc_bt.h. * * \code * #define MAX_BT_IPC_HPC_CB 5 * \endcode * * To change the count of maximum number of buffers shared by BT SS, * modify this line of code in cy_ipc_bt.h. * * \code * #define MAX_BUF_COUNT 10 * \endcode * * \section group_ipc_more_information More Information * * If the default startup file is not used, or SystemInit() is not called in your * project, call the following three functions prior to executing any flash or * EmEEPROM write or erase operation: * -# Cy_IPC_Sema_Init() * -# Cy_IPC_Pipe_Config() * -# Cy_IPC_Pipe_Init() * -# Cy_Flash_Init() * * See the technical reference manual(TRM) for more information on the IPC. * * \section group_ipc_changelog Changelog * * <table class="doxtable"> * <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr> * <tr> * <td >1.60</td> * <td>Added new APIs to use DATA0 and DATA1 for short messages.</td> * <td>Enhancement based on usability/efficiency.</td> * </tr> * <tr> * <td rowspan="2">1.50</td> * <td>Updated attribute usage for the linker section placement.</td> * <td>Enhancement based on usability feedback.</td> * </tr> * <tr> * <td>Fixed MISRA 2012 violations.</td> * <td>MISRA 2012 compliance.</td> * </tr> * <tr> * <td>1.40.2</td> * <td>Updated information about IPC resources reserved for the system usage * in \ref group_ipc_pipe_layer section. * </td> * <td>Documentation enhancement.</td> * </tr> * <tr> * <td>1.40.1</td> * <td>Minor documentation updates.</td> * <td>Documentation enhancement.</td> * </tr> * <tr> * <td rowspan="1">1.40</td> * <td>Moved cy_semaData structure to the RAM section called ".cy_sharedmem".</td> * <td>Support Secure Boot devices.</td> * </tr> * <tr> * <td rowspan="3">1.30</td> * <td>Flattened the organization of the driver source code into the single source directory and the single include directory.</td> * <td>Driver library directory-structure simplification.</td> * </tr> * <tr> * <td>Moved the Cy_IPC_SystemSemaInit(), Cy_IPC_SystemPipeInit() functions implementation from IPC to Startup, removed cy_ipc_config.c and cy_ipc_config.h files.</td> * <td>Changed IPC driver configuration method from compile time to run time.</td> * </tr> * <tr> * <td>Added register access layer. Use register access macros instead * of direct register access using dereferenced pointers.</td> * <td>Makes register access device-independent, so that the PDL does * not need to be recompiled for each supported part number.</td> * </tr> * <tr> * <td>1.20</td> * <td>Added \ref Cy_IPC_Pipe_ExecuteCallback function. * Updated documentation about user pipe initialization. * </td> * <td>Interface improvement, documentation update</td> * </tr> * <tr> * <td>1.10.1</td> * <td>Updated description of the \ref Cy_IPC_Pipe_Init, * \ref Cy_IPC_Pipe_EndpointInit, \ref Cy_IPC_Sema_Set functions. * Added / updated code snippets. * </td> * <td>Documentation update and clarification</td> * </tr> * <tr> * <td>1.10</td> * <td>Added support for more IPC structures</td> * <td>New device support</td> * </tr> * <tr> * <td>1.0</td> * <td>Initial version</td> * <td></td> * </tr> * </table> * * \defgroup group_ipc_drv IPC driver layer (IPC_DRV) * \{ * The functions of this layer are used in the higher IPC levels * (Semaphores and Pipes). * Users are not expected to call any of these IPC functions directly (cy_ipc_drv.h). * Instead include either of cy_ipc_sema.h or cy_ipc_pipe.h. * Alternatively include cy_pdl.h to get access to all functions and declarations in the PDL. * * \defgroup group_ipc_macros Macros * Macro definitions are used in the driver * * \defgroup group_ipc_functions Functions * Functions are used in the driver * * \defgroup group_ipc_data_structures Data Structures * Data structures are used in the driver * * \defgroup group_ipc_enums Enumerated Types * Enumerations are used in the driver * \} * * \defgroup group_ipc_sema IPC semaphores layer (IPC_SEMA) * \defgroup group_ipc_pipe IPC pipes layer (IPC_PIPE) * \defgroup group_ipc_bt IPC bluetooth sub-system layer (IPC_BTSS) * */ /******************************************************************************/ /* Include files */ /******************************************************************************/ #include "cy_device.h" #if defined (CY_IP_M4CPUSS) || defined (CY_IP_MXIPC) #include "cy_syslib.h" #include <stddef.h> /** * \addtogroup group_ipc_macros * \{ */ /** Driver major version */ #define CY_IPC_DRV_VERSION_MAJOR 1 /** Driver minor version */ #define CY_IPC_DRV_VERSION_MINOR 60 /** Defines a value to indicate that no notification events are needed */ #define CY_IPC_NO_NOTIFICATION (uint32_t)(0x00000000UL) /* Error Code constants */ #define CY_IPC_ID CY_PDL_DRV_ID(0x22u) /**< Software PDL driver ID for IPC */ /** Return prefix for IPC driver function status codes */ #define CY_IPC_ID_INFO (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_INFO ) /** Return prefix for IPC driver function warning return values */ #define CY_IPC_ID_WARNING (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_WARNING) /** Return prefix for IPC driver function error return values */ #define CY_IPC_ID_ERROR (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_ERROR) /** Converts the IPC interrupt channel number to interrupt vector */ #define CY_IPC_INTR_NUM_TO_VECT(x) ((int32_t) cy_device->cpussIpc0Irq + (x)) /** \} group_ipc_macros */ /* end of definition in device.h */ /** \cond INTERNAL */ #if (CY_CPU_CORTEX_M0P) #define CY_IPC_CHAN_SYSCALL CY_IPC_CHAN_SYSCALL_CM0 #else #define CY_IPC_CHAN_SYSCALL CY_IPC_CHAN_SYSCALL_CM4 #endif /* (CY_CPU_CORTEX_M0P) */ /** \endcond */ /** * \addtogroup group_ipc_enums * \{ */ /** * This is a list of ENUMs used for function return status. */ typedef enum { /** Function was successfully executed */ CY_IPC_DRV_SUCCESS = (0x00u), /** Function was not executed due to an error. Typical conditions for the error explained in the function description */ CY_IPC_DRV_ERROR = ( CY_IPC_ID_ERROR + 1UL), } cy_en_ipcdrv_status_t; /** \} group_ipc_enums */ #ifdef __cplusplus extern "C" { #endif /** \cond INTERNAL */ __STATIC_INLINE void Cy_IPC_Drv_WriteDataValue (IPC_STRUCT_Type* base, uint32_t dataValue); __STATIC_INLINE uint32_t Cy_IPC_Drv_ReadDataValue (IPC_STRUCT_Type const * base); __STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractAcquireMask (uint32_t intMask); __STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractReleaseMask (uint32_t intMask); /** \endcond */ /** * \addtogroup group_ipc_functions * \{ */ __STATIC_INLINE IPC_STRUCT_Type* Cy_IPC_Drv_GetIpcBaseAddress (uint32_t ipcIndex); __STATIC_INLINE IPC_INTR_STRUCT_Type* Cy_IPC_Drv_GetIntrBaseAddr (uint32_t ipcIntrIndex); __STATIC_INLINE void Cy_IPC_Drv_AcquireNotify (IPC_STRUCT_Type * base, uint32_t notifyEventIntr); __STATIC_INLINE void Cy_IPC_Drv_ReleaseNotify (IPC_STRUCT_Type * base, uint32_t notifyEventIntr); __STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_LockAcquire (IPC_STRUCT_Type const * base); cy_en_ipcdrv_status_t Cy_IPC_Drv_LockRelease (IPC_STRUCT_Type * base, uint32_t releaseEventIntr); __STATIC_INLINE bool Cy_IPC_Drv_IsLockAcquired (IPC_STRUCT_Type const * base); __STATIC_INLINE uint32_t Cy_IPC_Drv_GetLockStatus (IPC_STRUCT_Type const * base); cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgWord (IPC_STRUCT_Type * base, uint32_t notifyEventIntr, uint32_t message); cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgWord (IPC_STRUCT_Type const * base, uint32_t * message); #if (CY_IP_M4CPUSS_VERSION > 1) || defined (CY_IP_M33SYSCPUSS_VERSION) || defined (CY_DOXYGEN) cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgDWord (IPC_STRUCT_Type * base, uint32_t notifyEventIntr, uint32_t* message); cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgDWord (IPC_STRUCT_Type const * base, uint32_t* message); #endif __STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgPtr (IPC_STRUCT_Type* base, uint32_t notifyEventIntr, void const * msgPtr); __STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgPtr (IPC_STRUCT_Type const * base, void ** msgPtr); __STATIC_INLINE void Cy_IPC_Drv_SetInterruptMask (IPC_INTR_STRUCT_Type * base, uint32_t ipcReleaseMask, uint32_t ipcAcquireMask); __STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptMask (IPC_INTR_STRUCT_Type const * base); __STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatusMasked (IPC_INTR_STRUCT_Type const * base); __STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatus (IPC_INTR_STRUCT_Type const * base); __STATIC_INLINE void Cy_IPC_Drv_SetInterrupt (IPC_INTR_STRUCT_Type * base, uint32_t ipcReleaseMask, uint32_t ipcAcquireMask); __STATIC_INLINE void Cy_IPC_Drv_ClearInterrupt (IPC_INTR_STRUCT_Type * base, uint32_t ipcReleaseMask, uint32_t ipcAcquireMask); /******************************************************************************* * Function Name: Cy_IPC_Drv_GetIpcBaseAddress ****************************************************************************//** * * This function takes an IPC channel index as a parameter and returns the base * address the IPC registers corresponding to the IPC channel. * * \note The user is responsible for ensuring that ipcIndex does not exceed the * limits. * * \param ipcIndex * Represents the number of IPC structure. This is converted to the base address of * the IPC channel registers. * * \return * Returns a pointer to the base of the IPC registers. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_SendMsgWord * *******************************************************************************/ __STATIC_INLINE IPC_STRUCT_Type* Cy_IPC_Drv_GetIpcBaseAddress (uint32_t ipcIndex) { CY_ASSERT_L1(CY_IPC_CHANNELS > ipcIndex); return ( (IPC_STRUCT_Type*) CY_IPC_STRUCT_PTR(ipcIndex)); } /******************************************************************************* * Function Name: Cy_IPC_Drv_GetIntrBaseAddr ****************************************************************************//** * * This function takes an IPC interrupt structure index and returns the base * address of the IPC interrupt registers corresponding to the IPC Interrupt. * * \note The user is responsible for ensuring that ipcIntrIndex does not exceed the * limits. * * \param ipcIntrIndex * Represents the number of IPC interrupt structure. This is converted to the * base address of the IPC interrupt registers. * * \return * Returns a pointer to the base of the IPC interrupt registers. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_GetInterruptStatus * *******************************************************************************/ __STATIC_INLINE IPC_INTR_STRUCT_Type* Cy_IPC_Drv_GetIntrBaseAddr (uint32_t ipcIntrIndex) { CY_ASSERT_L1(CY_IPC_INTERRUPTS > ipcIntrIndex); return ( (IPC_INTR_STRUCT_Type*) CY_IPC_INTR_STRUCT_PTR(ipcIntrIndex)); } /******************************************************************************* * Function Name: Cy_IPC_Drv_SetInterruptMask ****************************************************************************//** * * This function is used to set the interrupt mask for an IPC Interrupt. * The mask sets release or acquire notification events for all IPC channels. * * \param base * This is a handle to the IPC interrupt. This handle can be calculated from the * IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. * * \param ipcReleaseMask * An encoded list of all IPC channels that can trigger the interrupt on a * release event. * * \param ipcAcquireMask * An encoded list of all IPC channels that can trigger the interrupt on a * notify event. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_GetInterruptStatusMasked * *******************************************************************************/ __STATIC_INLINE void Cy_IPC_Drv_SetInterruptMask (IPC_INTR_STRUCT_Type* base, uint32_t ipcReleaseMask, uint32_t ipcAcquireMask) { CY_ASSERT_L1(0UL == (ipcAcquireMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); CY_ASSERT_L1(0UL == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk))); REG_IPC_INTR_STRUCT_INTR_MASK(base) = _VAL2FLD( IPC_INTR_STRUCT_INTR_MASK_NOTIFY, ipcAcquireMask) | _VAL2FLD( IPC_INTR_STRUCT_INTR_MASK_RELEASE, ipcReleaseMask); } /******************************************************************************* * Function Name: Cy_IPC_Drv_GetInterruptMask ****************************************************************************//** * * This function is used to read the interrupt mask. * * \param base * This is a handle to the IPC interrupt. This handle can be calculated from * the IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. * * \return * The return value is encoded as follows * <table> * <tr><th>Interrupt sources <th>Value * <tr><td>Ipc_PORTX_RELEASE <td>Xth bit set * <tr><td>Ipc_PORTX_NOTIFY <td>X+16th bit set * </table> * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_GetInterruptStatusMasked * *******************************************************************************/ __STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptMask(IPC_INTR_STRUCT_Type const * base) { return REG_IPC_INTR_STRUCT_INTR_MASK(base); } /******************************************************************************* * Function Name: Cy_IPC_Drv_GetInterruptStatusMasked ****************************************************************************//** * * This function is used to read the active unmasked interrupt. This function * can be used in the interrupt service routine to find which source triggered * the interrupt. * * \param base * This is a handle to the IPC interrupt. This handle can be calculated from the * IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. * * \return * The return value is encoded as follows * <table> * <tr><th>Interrupt sources <th>Value * <tr><td>Ipc_PORTX_RELEASE <td>Xth bit set * <tr><td>Ipc_PORTX_NOTIFY <td>X+16th bit set * </table> * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_GetInterruptStatusMasked * *******************************************************************************/ __STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatusMasked (IPC_INTR_STRUCT_Type const * base) { return REG_IPC_INTR_STRUCT_INTR_MASKED(base); } /******************************************************************************* * Function Name: Cy_IPC_Drv_GetInterruptStatus ****************************************************************************//** * * This function is used to read the pending interrupts. Note that this read is * an unmasked read of the interrupt status. Interrupt sources read as active by * this function would generate interrupts only if they were not masked. * * \param base * This is a handle to the IPC interrupt. This handle can be calculated from the * IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. * * \return * The return value is encoded as follows * <table> * <tr><th>Interrupt sources <th>Value * <tr><td>Ipc_PORTX_RELEASE <td>Xth bit set * <tr><td>Ipc_PORTX_NOTIFY <td>X+16th bit set * </table> * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_GetInterruptStatus * *******************************************************************************/ __STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatus(IPC_INTR_STRUCT_Type const * base) { return REG_IPC_INTR_STRUCT_INTR(base); } /******************************************************************************* * Function Name: Cy_IPC_Drv_SetInterrupt ****************************************************************************//** * * This function is used to set the interrupt source. This function can be used * to activate interrupts through software. * \note That interrupt sources set using this interrupt would generate interrupts * only if they are not masked. * * \param base * This is a handle to the IPC interrupt. This handle can be calculated from the * IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. * * \param ipcReleaseMask * An encoded list of all IPC channels that can trigger the interrupt on a * release event. * * \param ipcAcquireMask * An encoded list of all IPC channels that can trigger the interrupt on a * notify event. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_SetInterrupt * *******************************************************************************/ __STATIC_INLINE void Cy_IPC_Drv_SetInterrupt(IPC_INTR_STRUCT_Type* base, uint32_t ipcReleaseMask, uint32_t ipcAcquireMask) { CY_ASSERT_L1(0UL == (ipcAcquireMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); CY_ASSERT_L1(0UL == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk))); REG_IPC_INTR_STRUCT_INTR_SET(base) = _VAL2FLD( IPC_INTR_STRUCT_INTR_NOTIFY, ipcAcquireMask ) | _VAL2FLD( IPC_INTR_STRUCT_INTR_RELEASE, ipcReleaseMask ); } /******************************************************************************* * Function Name: Cy_IPC_Drv_ClearInterrupt ****************************************************************************//** * * This function is used to clear the interrupt source. Use this function to clear * a pending interrupt source in the interrupt status. * * \param base * This is a handle to the IPC interrupt. This handle can be calculated from the * IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr. * * \param ipcReleaseMask * An encoded list of all IPC channels that can trigger the interrupt on a * release event. * * \param ipcAcquireMask * An encoded list of all IPC channels that can trigger the interrupt on a * notify event. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_GetInterruptStatusMasked * *******************************************************************************/ __STATIC_INLINE void Cy_IPC_Drv_ClearInterrupt(IPC_INTR_STRUCT_Type* base, uint32_t ipcReleaseMask, uint32_t ipcAcquireMask) { CY_ASSERT_L1(0UL == (ipcAcquireMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); CY_ASSERT_L1(0UL == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk))); REG_IPC_INTR_STRUCT_INTR(base) = _VAL2FLD(IPC_INTR_STRUCT_INTR_NOTIFY, ipcAcquireMask) | _VAL2FLD(IPC_INTR_STRUCT_INTR_RELEASE, ipcReleaseMask); (void)REG_IPC_INTR_STRUCT_INTR(base); /* Read the register to flush the cache */ } /** \} group_ipc_functions */ /** \} group_ipc */ /******************************************************************************* * Function Name: Cy_IPC_Drv_AcquireNotify ****************************************************************************//** * * The function generates a acquire notification event by IPC interrupt structure. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \param notifyEventIntr * Bit encoded list of IPC interrupt structures that are triggered * by a notification. Bit number correspond to number of the IPC interrupt * structure. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_LockAcquire * *******************************************************************************/ __STATIC_INLINE void Cy_IPC_Drv_AcquireNotify (IPC_STRUCT_Type* base, uint32_t notifyEventIntr) { CY_ASSERT_L1(0UL == (notifyEventIntr & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk))); REG_IPC_STRUCT_NOTIFY(base) = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, notifyEventIntr); } /******************************************************************************* * Function Name: Cy_IPC_Drv_ReleaseNotify ****************************************************************************//** * * The function generates a release notification event by IPC interrupt structure. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \param notifyEventIntr * Bit encoded list of IPC interrupt lines that are triggered by a notification. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_ReadMsgWord * *******************************************************************************/ __STATIC_INLINE void Cy_IPC_Drv_ReleaseNotify (IPC_STRUCT_Type* base, uint32_t notifyEventIntr) { CY_ASSERT_L1(0UL == (notifyEventIntr & ~(uint32_t)(IPC_INTR_STRUCT_INTR_RELEASE_Msk))); REG_IPC_STRUCT_RELEASE(base) = _VAL2FLD(IPC_INTR_STRUCT_INTR_RELEASE, notifyEventIntr); } /******************************************************************************* * Function Name: Cy_IPC_Drv_WriteDataValue ****************************************************************************//** * * The function writes a value to the DATA register of the IPC channel. * * This function is internal and should not be called directly by user * software. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \param dataValue * Value to be written. * *******************************************************************************/ __STATIC_INLINE void Cy_IPC_Drv_WriteDataValue (IPC_STRUCT_Type* base, uint32_t dataValue) { REG_IPC_STRUCT_DATA(base) = dataValue; } #if (CY_IP_M4CPUSS_VERSION > 1) || defined (CY_IP_M33SYSCPUSS_VERSION) || defined (CY_DOXYGEN) /******************************************************************************* * Function Name: Cy_IPC_Drv_WriteDDataValue ****************************************************************************//** * * The function writes two 32 bit values to the DATA registers of the IPC channel. * * This function is internal and should not be called directly by user * software. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \param dataValue * Value to be written. * *******************************************************************************/ __STATIC_INLINE void Cy_IPC_Drv_WriteDDataValue (IPC_STRUCT_Type* base, uint32_t *pDataValue) { REG_IPC_STRUCT_DATA(base) = *pDataValue++; REG_IPC_STRUCT_DATA1(base) = *pDataValue; } #endif /******************************************************************************* * Function Name: Cy_IPC_Drv_ReadDataValue ****************************************************************************//** * * The function reads a value from the DATA register of the IPC channel. * * This function is internal and should not be called directly by user * software. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \return * Value from DATA register. * *******************************************************************************/ __STATIC_INLINE uint32_t Cy_IPC_Drv_ReadDataValue (IPC_STRUCT_Type const * base) { return REG_IPC_STRUCT_DATA(base); } #if (CY_IP_M4CPUSS_VERSION > 1) || defined (CY_IP_M33SYSCPUSS_VERSION) || defined (CY_DOXYGEN) /******************************************************************************* * Function Name: Cy_IPC_Drv_ReadDDataValue ****************************************************************************//** * * The function reads two 32bit values from the DATA registers of the IPC channel. * * This function is internal and should not be called directly by user * software. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \return * Value from DATA register. * *******************************************************************************/ __STATIC_INLINE void Cy_IPC_Drv_ReadDDataValue (IPC_STRUCT_Type const * base, uint32_t *pDataValue) { *pDataValue++ = REG_IPC_STRUCT_DATA(base); *pDataValue = REG_IPC_STRUCT_DATA1(base); } #endif /******************************************************************************* * Function Name: Cy_IPC_Drv_IsLockAcquired ****************************************************************************//** * * The function is used to test the status of an IPC channel. The function * tells the reader if the IPC channel was in the locked or released state. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \return * Status for the function: * true: The IPC channel is in the Locked state. * false: The IPC channel is in the Released state. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_LockAcquire * *******************************************************************************/ __STATIC_INLINE bool Cy_IPC_Drv_IsLockAcquired (IPC_STRUCT_Type const * base) { return ( 0u != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, REG_IPC_STRUCT_LOCK_STATUS(base)) ); } /******************************************************************************* * Function Name: Cy_IPC_Drv_GetLockStatus ****************************************************************************//** * * The function is used to get the status of an IPC channel. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \return * Value from LOCK_STATUS register. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_GetLockStatus * *******************************************************************************/ __STATIC_INLINE uint32_t Cy_IPC_Drv_GetLockStatus (IPC_STRUCT_Type const * base) { return REG_IPC_STRUCT_LOCK_STATUS(base); } /******************************************************************************* * Function Name: Cy_IPC_Drv_ExtractAcquireMask ****************************************************************************//** * * The function extracts an Acquire mask part from full interrupt mask value. * * This function is internal and should not be called directly by user * software. * * \param intMask * Interrupt mask value to be processed. * * \return * Acquire mask value. * *******************************************************************************/ __STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractAcquireMask (uint32_t intMask) { return _FLD2VAL(IPC_INTR_STRUCT_INTR_MASK_NOTIFY, intMask); } /******************************************************************************* * Function Name: Cy_IPC_Drv_ExtractReleaseMask ****************************************************************************//** * * The function extracts a Release mask part from full interrupt mask value. * * This function is internal and should not be called directly by user * software. * * \param intMask * Interrupt mask value to be processed. * * \return * Release mask value. * *******************************************************************************/ __STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractReleaseMask (uint32_t intMask) { return _FLD2VAL(IPC_INTR_STRUCT_INTR_MASK_RELEASE, intMask); } /******************************************************************************* * Function Name: Cy_IPC_Drv_SendMsgPtr ****************************************************************************//** * * This function is used to send a message pointer through an IPC channel. * The message structure may hold a generic pointer that may contain the address * of any user data type or structure. This parameter could be a pointer to a 32-bit * integer, an array, or even a data structure defined in the user code. This * function acts as a transfer engine for sending the pointer. Any memory * management of the pointer allocation and deallocation is up to the application * code. * The function also has an associated notification field that will let the * message notify one or multiple interrupts. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \param notifyEventIntr * Bit encoded list of IPC interrupt lines that are triggered during the release * action. * * \param msgPtr * The message pointer that is being sent over the IPC channel. * * \return Status of the operation: * \retval CY_IPC_DRV_SUCCESS: The send operation was successful. * \retval CY_IPC_DRV_ERROR: The IPC channel is unavailable because * it is already locked. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_SendMsgPtr * *******************************************************************************/ __STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgPtr(IPC_STRUCT_Type* base, uint32_t notifyEventIntr, void const * msgPtr) { CY_ASSERT_L1(NULL != msgPtr); return Cy_IPC_Drv_SendMsgWord(base, notifyEventIntr, (uint32_t)msgPtr); } /******************************************************************************* * Function Name: Cy_IPC_Drv_ReadMsgPtr ****************************************************************************//** * * This function is used to read a 32-bit pointer message through an IPC channel. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress. * * \param msgPtr * Pointer variable to hold the data pointer that is being read from the IPC * channel. * * * \return Status of the operation * \retval CY_IPC_DRV_SUCCESS: The function executed successfully and the IPC * was acquired. * \retval CY_IPC_DRV_ERROR: The function encountered an error because the IPC * channel was already in a released state meaning the data * in it is invalid. * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_ReadMsgPtr * *******************************************************************************/ __STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgPtr (IPC_STRUCT_Type const * base, void ** msgPtr) { CY_ASSERT_L1(NULL != msgPtr); return Cy_IPC_Drv_ReadMsgWord(base, (uint32_t *)msgPtr); } /******************************************************************************* * Function Name: Cy_IPC_Drv_LockAcquire ****************************************************************************//** * * This function is used to acquire the IPC channel. * * \param base * This parameter is a handle that represents the base address of the registers * of the IPC channel. * The parameter is generally returned from a call to the \ref * Cy_IPC_Drv_GetIpcBaseAddress * * \return Status of the operation * \retval CY_IPC_DRV_SUCCESS: The IPC was successfully acquired * \retval CY_IPC_DRV_ERROR: The IPC was not acquired because it was already acquired * by another master * * \funcusage * \snippet ipc/snippet/main.c snippet_Cy_IPC_Drv_LockAcquire * *******************************************************************************/ __STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_LockAcquire (IPC_STRUCT_Type const * base) { return ( 0UL != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, REG_IPC_STRUCT_ACQUIRE(base))) ? CY_IPC_DRV_SUCCESS : CY_IPC_DRV_ERROR; } #ifdef __cplusplus } #endif #endif /* CY_IP_M4CPUSS */ #endif /* !defined (CY_IPC_DRV_H) */ /* [] END OF FILE */