1 /*
2 * Copyright (c) 2019 - 2025, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <nrfx.h>
35
36 #if NRFX_CHECK(NRFX_IPC_ENABLED)
37
38 #include <nrfx_ipc.h>
39
40 #define NRFX_LOG_MODULE IPC
41 #include <nrfx_log.h>
42
43 // Control block - driver instance local data.
44 typedef struct
45 {
46 nrfx_ipc_handler_t handler;
47 nrfx_drv_state_t state;
48 void * p_context;
49 } ipc_control_block_t;
50
51 static ipc_control_block_t m_cb;
52
nrfx_ipc_init(uint8_t irq_priority,nrfx_ipc_handler_t handler,void * p_context)53 nrfx_err_t nrfx_ipc_init(uint8_t irq_priority, nrfx_ipc_handler_t handler, void * p_context)
54 {
55 NRFX_ASSERT(handler);
56 if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
57 {
58 return NRFX_ERROR_ALREADY;
59 }
60
61 NRFX_IRQ_PRIORITY_SET(IPC_IRQn, irq_priority);
62 NRFX_IRQ_ENABLE(IPC_IRQn);
63
64 m_cb.state = NRFX_DRV_STATE_INITIALIZED;
65 m_cb.handler = handler;
66 m_cb.p_context = p_context;
67
68 NRFX_LOG_INFO("Initialized.");
69 return NRFX_SUCCESS;
70 }
71
nrfx_ipc_config_load(const nrfx_ipc_config_t * p_config)72 void nrfx_ipc_config_load(const nrfx_ipc_config_t * p_config)
73 {
74 NRFX_ASSERT(p_config);
75 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
76
77 uint8_t i;
78 for (i = 0; i < IPC_CONF_NUM; ++i)
79 {
80 nrf_ipc_send_config_set(NRF_IPC, i, p_config->send_task_config[i]);
81 }
82
83 for (i = 0; i < IPC_CONF_NUM; ++i)
84 {
85 nrf_ipc_receive_config_set(NRF_IPC, i, p_config->receive_event_config[i]);
86 }
87
88 nrf_ipc_int_enable(NRF_IPC, p_config->receive_events_enabled);
89
90 NRFX_LOG_INFO("Configuartion loaded.");
91 }
92
nrfx_ipc_uninit(void)93 void nrfx_ipc_uninit(void)
94 {
95 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
96
97 uint8_t i;
98 for (i = 0; i < IPC_CONF_NUM; ++i)
99 {
100 nrf_ipc_send_config_set(NRF_IPC, i, 0);
101 }
102
103 for (i = 0; i < IPC_CONF_NUM; ++i)
104 {
105 nrf_ipc_receive_config_set(NRF_IPC, i, 0);
106 }
107
108 NRFX_IRQ_DISABLE(IPC_IRQn);
109 nrf_ipc_int_disable(NRF_IPC, 0xFFFFFFFF);
110
111 m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
112 NRFX_LOG_INFO("Uninitialized.");
113 }
114
nrfx_ipc_init_check(void)115 bool nrfx_ipc_init_check(void)
116 {
117 return (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
118 }
119
nrfx_ipc_receive_event_enable(uint8_t event_index)120 void nrfx_ipc_receive_event_enable(uint8_t event_index)
121 {
122 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
123 nrf_ipc_int_enable(NRF_IPC, (1UL << event_index));
124
125 NRFX_LOG_INFO("Event %u enabled.", event_index);
126 }
127
nrfx_ipc_receive_event_disable(uint8_t event_index)128 void nrfx_ipc_receive_event_disable(uint8_t event_index)
129 {
130 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
131 nrf_ipc_int_disable(NRF_IPC, (1UL << event_index));
132
133 NRFX_LOG_INFO("Event %u disabled.", event_index);
134 }
135
nrfx_ipc_receive_event_group_enable(uint32_t event_bitmask)136 void nrfx_ipc_receive_event_group_enable(uint32_t event_bitmask)
137 {
138 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
139 nrf_ipc_int_enable(NRF_IPC, event_bitmask);
140
141 NRFX_LOG_INFO("Events masked with %x enabled.", event_bitmask);
142 }
143
nrfx_ipc_receive_event_group_disable(uint32_t event_bitmask)144 void nrfx_ipc_receive_event_group_disable(uint32_t event_bitmask)
145 {
146 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
147 nrf_ipc_int_disable(NRF_IPC, event_bitmask);
148
149 NRFX_LOG_INFO("Events masked with %x disabled.", event_bitmask);
150 }
151
nrfx_ipc_receive_event_channel_assign(uint8_t event_index,uint8_t channel_index)152 void nrfx_ipc_receive_event_channel_assign(uint8_t event_index, uint8_t channel_index)
153 {
154 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
155 NRFX_ASSERT(channel_index < IPC_CH_NUM);
156
157 uint32_t channel_bitmask = (1UL << channel_index);
158 channel_bitmask |= nrf_ipc_receive_config_get(NRF_IPC, event_index);
159 nrf_ipc_receive_config_set(NRF_IPC, event_index, channel_bitmask);
160
161 NRFX_LOG_INFO("Event %u assigned to IPC channel %u.", event_index, channel_index);
162 }
163
nrfx_ipc_send_task_channel_assign(uint8_t send_index,uint8_t channel_index)164 void nrfx_ipc_send_task_channel_assign(uint8_t send_index, uint8_t channel_index)
165 {
166 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
167 NRFX_ASSERT(channel_index < IPC_CH_NUM);
168
169 uint32_t channel_bitmask = (1UL << channel_index);
170 channel_bitmask |= nrf_ipc_send_config_get(NRF_IPC, send_index);
171 nrf_ipc_send_config_set(NRF_IPC, send_index, channel_bitmask);
172
173 NRFX_LOG_INFO("Signal %u assigned to IPC channel %u.", send_index, channel_index);
174 }
175
nrfx_ipc_irq_handler(void)176 void nrfx_ipc_irq_handler(void)
177 {
178 // Get the information about events that fire this interrupt
179 uint32_t events_map = nrf_ipc_int_pending_get(NRF_IPC);
180 // Clear these events
181 uint32_t bitmask = events_map;
182
183 while (bitmask)
184 {
185 uint8_t event_idx = (uint8_t)NRF_CTZ(bitmask);
186 bitmask &= ~(1UL << event_idx);
187 nrf_ipc_event_clear(NRF_IPC, nrf_ipc_receive_event_get(event_idx));
188 if (m_cb.handler)
189 {
190 m_cb.handler(event_idx, m_cb.p_context);
191 }
192 }
193 }
194
195 #endif // NRFX_CHECK(NRFX_IPC_ENABLED)
196