1 /*
2 * Copyright (c) 2018, 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_DPPI_ENABLED)
35
36 #include <nrfx_dppi.h>
37
38 #define NRFX_LOG_MODULE DPPI
39 #include <nrfx_log.h>
40
41 #if !defined(NRFX_DPPI_CHANNELS_USED)
42 // Default mask of DPPI channels reserved for other modules.
43 #define NRFX_DPPI_CHANNELS_USED 0x00000000uL
44 #endif
45
46 #if !defined(NRFX_DPPI_GROUPS_USED)
47 // Default mask of DPPI groups reserved for other modules.
48 #define NRFX_DPPI_GROUPS_USED 0x00000000uL
49 #endif
50
51 #define DPPI_AVAILABLE_CHANNELS_MASK \
52 (((1UL << DPPI_CH_NUM) - 1) & (~NRFX_DPPI_CHANNELS_USED))
53
54 #define DPPI_AVAILABLE_GROUPS_MASK \
55 (((1UL << DPPI_GROUP_NUM) - 1) & (~NRFX_DPPI_GROUPS_USED))
56
57 /** @brief Set bit at given position. */
58 #define DPPI_BIT_SET(pos) (1uL << (pos))
59
60 static uint32_t m_allocated_channels;
61
62 static uint8_t m_allocated_groups;
63
channel_is_allocated(uint8_t channel)64 __STATIC_INLINE bool channel_is_allocated(uint8_t channel)
65 {
66 return ((m_allocated_channels & DPPI_BIT_SET(channel)) != 0);
67 }
68
group_is_allocated(nrf_dppi_channel_group_t group)69 __STATIC_INLINE bool group_is_allocated(nrf_dppi_channel_group_t group)
70 {
71 return ((m_allocated_groups & DPPI_BIT_SET(group)) != 0);
72 }
73
nrfx_dppi_free(void)74 void nrfx_dppi_free(void)
75 {
76 uint32_t mask = m_allocated_groups;
77 nrf_dppi_channel_group_t group = NRF_DPPI_CHANNEL_GROUP0;
78
79 // Disable all channels
80 nrf_dppi_channels_disable(NRF_DPPIC, m_allocated_channels);
81
82 // Clear all groups configurations
83 while (mask)
84 {
85 if (mask & DPPI_BIT_SET(group))
86 {
87 nrf_dppi_group_clear(NRF_DPPIC, group);
88 mask &= ~DPPI_BIT_SET(group);
89 }
90 group++;
91 }
92
93 // Clear all allocated channels.
94 m_allocated_channels = 0;
95
96 // Clear all allocated groups.
97 m_allocated_groups = 0;
98 }
99
nrfx_dppi_channel_alloc(uint8_t * p_channel)100 nrfx_err_t nrfx_dppi_channel_alloc(uint8_t * p_channel)
101 {
102 nrfx_err_t err_code;
103
104 // Get mask of available DPPI channels
105 uint32_t remaining_channels = DPPI_AVAILABLE_CHANNELS_MASK & ~(m_allocated_channels);
106 uint8_t channel = 0;
107
108 if (!remaining_channels)
109 {
110 err_code = NRFX_ERROR_NO_MEM;
111 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
112 return err_code;
113 }
114
115 // Find first free channel
116 while (!(remaining_channels & DPPI_BIT_SET(channel)))
117 {
118 channel++;
119 }
120
121 m_allocated_channels |= DPPI_BIT_SET(channel);
122 *p_channel = channel;
123
124 err_code = NRFX_SUCCESS;
125 NRFX_LOG_INFO("Allocated channel: %d.", channel);
126 return err_code;
127 }
128
nrfx_dppi_channel_free(uint8_t channel)129 nrfx_err_t nrfx_dppi_channel_free(uint8_t channel)
130 {
131 nrfx_err_t err_code = NRFX_SUCCESS;
132
133 if (!channel_is_allocated(channel))
134 {
135 err_code = NRFX_ERROR_INVALID_PARAM;
136 }
137 else
138 {
139 // First disable this channel
140 nrf_dppi_channels_disable(NRF_DPPIC, DPPI_BIT_SET(channel));
141 // Clear channel allocated indication.
142 m_allocated_channels &= ~DPPI_BIT_SET(channel);
143 }
144 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
145 return err_code;
146 }
147
nrfx_dppi_channel_enable(uint8_t channel)148 nrfx_err_t nrfx_dppi_channel_enable(uint8_t channel)
149 {
150 nrfx_err_t err_code = NRFX_SUCCESS;
151
152 if (!channel_is_allocated(channel))
153 {
154 err_code = NRFX_ERROR_INVALID_PARAM;
155 }
156 else
157 {
158 nrf_dppi_channels_enable(NRF_DPPIC, DPPI_BIT_SET(channel));
159 }
160 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
161 return err_code;
162 }
163
nrfx_dppi_channel_disable(uint8_t channel)164 nrfx_err_t nrfx_dppi_channel_disable(uint8_t channel)
165 {
166 nrfx_err_t err_code = NRFX_SUCCESS;
167
168 if (!channel_is_allocated(channel))
169 {
170 err_code = NRFX_ERROR_INVALID_PARAM;
171 }
172 else
173 {
174 nrf_dppi_channels_disable(NRF_DPPIC, DPPI_BIT_SET(channel));
175 err_code = NRFX_SUCCESS;
176 }
177 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
178 return err_code;
179 }
180
nrfx_dppi_group_alloc(nrf_dppi_channel_group_t * p_group)181 nrfx_err_t nrfx_dppi_group_alloc(nrf_dppi_channel_group_t * p_group)
182 {
183 nrfx_err_t err_code;
184
185 // Get mask of available DPPI groups
186 uint32_t remaining_groups = DPPI_AVAILABLE_GROUPS_MASK & ~(m_allocated_groups);
187 nrf_dppi_channel_group_t group = NRF_DPPI_CHANNEL_GROUP0;
188
189 if (!remaining_groups)
190 {
191 err_code = NRFX_ERROR_NO_MEM;
192 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
193 return err_code;
194 }
195
196 // Find first free group
197 while (!(remaining_groups & DPPI_BIT_SET(group)))
198 {
199 group++;
200 }
201
202 m_allocated_groups |= DPPI_BIT_SET(group);
203 *p_group = group;
204
205 err_code = NRFX_SUCCESS;
206 NRFX_LOG_INFO("Allocated channel: %d.", group);
207 return err_code;
208 }
209
nrfx_dppi_group_free(nrf_dppi_channel_group_t group)210 nrfx_err_t nrfx_dppi_group_free(nrf_dppi_channel_group_t group)
211 {
212 nrfx_err_t err_code = NRFX_SUCCESS;
213
214 if (!group_is_allocated(group))
215 {
216 err_code = NRFX_ERROR_INVALID_PARAM;
217 }
218 else
219 {
220 nrf_dppi_group_disable(NRF_DPPIC, group);
221 // Set bit value to zero at position corresponding to the group number.
222 m_allocated_groups &= ~DPPI_BIT_SET(group);
223 }
224 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
225 return err_code;
226 }
227
nrfx_dppi_channel_include_in_group(uint8_t channel,nrf_dppi_channel_group_t group)228 nrfx_err_t nrfx_dppi_channel_include_in_group(uint8_t channel,
229 nrf_dppi_channel_group_t group)
230 {
231 nrfx_err_t err_code = NRFX_SUCCESS;
232
233 if (!group_is_allocated(group) || !channel_is_allocated(channel))
234 {
235 err_code = NRFX_ERROR_INVALID_PARAM;
236 }
237 else
238 {
239 nrf_dppi_channels_include_in_group(NRF_DPPIC, DPPI_BIT_SET(channel), group);
240 }
241 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
242 return err_code;
243 }
244
nrfx_dppi_channel_remove_from_group(uint8_t channel,nrf_dppi_channel_group_t group)245 nrfx_err_t nrfx_dppi_channel_remove_from_group(uint8_t channel,
246 nrf_dppi_channel_group_t group)
247 {
248 nrfx_err_t err_code = NRFX_SUCCESS;
249
250 if (!group_is_allocated(group) || !channel_is_allocated(channel))
251 {
252 err_code = NRFX_ERROR_INVALID_PARAM;
253 }
254 else
255 {
256 nrf_dppi_channels_remove_from_group(NRF_DPPIC, DPPI_BIT_SET(channel), group);
257 }
258 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
259 return err_code;
260 }
261
nrfx_dppi_group_clear(nrf_dppi_channel_group_t group)262 nrfx_err_t nrfx_dppi_group_clear(nrf_dppi_channel_group_t group)
263 {
264 nrfx_err_t err_code = NRFX_SUCCESS;
265
266 if (!group_is_allocated(group))
267 {
268 err_code = NRFX_ERROR_INVALID_PARAM;
269 }
270 else
271 {
272 nrf_dppi_channels_remove_from_group(NRF_DPPIC, DPPI_AVAILABLE_CHANNELS_MASK, group);
273 }
274 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
275 return err_code;
276 }
277
nrfx_dppi_group_enable(nrf_dppi_channel_group_t group)278 nrfx_err_t nrfx_dppi_group_enable(nrf_dppi_channel_group_t group)
279 {
280 nrfx_err_t err_code = NRFX_SUCCESS;
281
282 if (!group_is_allocated(group))
283 {
284 err_code = NRFX_ERROR_INVALID_PARAM;
285 }
286 else
287 {
288 nrf_dppi_group_enable(NRF_DPPIC, group);
289 }
290 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
291 return err_code;
292 }
293
nrfx_dppi_group_disable(nrf_dppi_channel_group_t group)294 nrfx_err_t nrfx_dppi_group_disable(nrf_dppi_channel_group_t group)
295 {
296 nrfx_err_t err_code = NRFX_SUCCESS;
297
298 if (!group_is_allocated(group))
299 {
300 err_code = NRFX_ERROR_INVALID_PARAM;
301 }
302 else
303 {
304 nrf_dppi_group_disable(NRF_DPPIC, group);
305 }
306 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
307 return err_code;
308 }
309
310 #endif // NRFX_CHECK(NRFX_DPPI_ENABLED)
311