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