1 /*
2 * Copyright (c) 2015 - 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_SWI_ENABLED)
35
36 #include <nrfx_swi.h>
37
38 #define NRFX_LOG_MODULE SWI
39 #include <nrfx_log.h>
40
41
42 // NRFX_SWI_RESERVED_MASK - SWIs reserved for use by external modules.
43 #if NRFX_CHECK(NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
44 #define NRFX_SWI_RESERVED_MASK ((NRFX_SWI_USED) | \
45 (1u << NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE))
46 #else
47 #define NRFX_SWI_RESERVED_MASK (NRFX_SWI_USED)
48 #endif
49
50 // NRFX_SWI_DISABLED_MASK - SWIs excluded from use in <nrfx_config.h>.
51 #if NRFX_CHECK(NRFX_SWI0_DISABLED)
52 #define NRFX_SWI0_DISABLED_MASK (1u << 0)
53 #else
54 #define NRFX_SWI0_DISABLED_MASK 0u
55 #endif
56 #if NRFX_CHECK(NRFX_SWI1_DISABLED)
57 #define NRFX_SWI1_DISABLED_MASK (1u << 1)
58 #else
59 #define NRFX_SWI1_DISABLED_MASK 0u
60 #endif
61 #if NRFX_CHECK(NRFX_SWI2_DISABLED)
62 #define NRFX_SWI2_DISABLED_MASK (1u << 2)
63 #else
64 #define NRFX_SWI2_DISABLED_MASK 0u
65 #endif
66 #if NRFX_CHECK(NRFX_SWI3_DISABLED)
67 #define NRFX_SWI3_DISABLED_MASK (1u << 3)
68 #else
69 #define NRFX_SWI3_DISABLED_MASK 0u
70 #endif
71 #if NRFX_CHECK(NRFX_SWI4_DISABLED)
72 #define NRFX_SWI4_DISABLED_MASK (1u << 4)
73 #else
74 #define NRFX_SWI4_DISABLED_MASK 0u
75 #endif
76 #if NRFX_CHECK(NRFX_SWI5_DISABLED)
77 #define NRFX_SWI5_DISABLED_MASK (1u << 5)
78 #else
79 #define NRFX_SWI5_DISABLED_MASK 0u
80 #endif
81 #define NRFX_SWI_DISABLED_MASK (NRFX_SWI0_DISABLED_MASK | \
82 NRFX_SWI1_DISABLED_MASK | \
83 NRFX_SWI2_DISABLED_MASK | \
84 NRFX_SWI3_DISABLED_MASK | \
85 NRFX_SWI4_DISABLED_MASK | \
86 NRFX_SWI5_DISABLED_MASK)
87
88 #if (NRFX_SWI_RESERVED_MASK & NRFX_SWI_DISABLED_MASK)
89 #error "A reserved SWI configured to be disabled. Check <nrfx_config.h> and NRFX_SWI_USED."
90 #endif
91
92 // NRFX_SWI_AVAILABLE_MASK - SWIs available for this module, i.e. present
93 // in the hardware and neither reserved by external modules nor disabled
94 // in <nrfx_config.h>.
95 #define NRFX_SWI_PRESENT_MASK ((1u << (SWI_COUNT)) - 1u)
96 #define NRFX_SWI_AVAILABLE_MASK (NRFX_SWI_PRESENT_MASK & \
97 ~(NRFX_SWI_RESERVED_MASK | \
98 NRFX_SWI_DISABLED_MASK))
99
100 #if (NRFX_SWI_AVAILABLE_MASK == 0)
101 #error "No available SWI instances. Check <nrfx_config.h> and NRFX_SWI_USED."
102 #endif
103
104 #define NRFX_SWI_IS_AVAILABLE(idx) ((NRFX_SWI_AVAILABLE_MASK >> (idx)) & 1u)
105
106 #define NRFX_SWI_FIRST (NRFX_SWI_IS_AVAILABLE(0) ? 0u : \
107 (NRFX_SWI_IS_AVAILABLE(1) ? 1u : \
108 (NRFX_SWI_IS_AVAILABLE(2) ? 2u : \
109 (NRFX_SWI_IS_AVAILABLE(3) ? 3u : \
110 (NRFX_SWI_IS_AVAILABLE(4) ? 4u : \
111 5u)))))
112 #define NRFX_SWI_LAST (NRFX_SWI_IS_AVAILABLE(5) ? 5u : \
113 (NRFX_SWI_IS_AVAILABLE(4) ? 4u : \
114 (NRFX_SWI_IS_AVAILABLE(3) ? 3u : \
115 (NRFX_SWI_IS_AVAILABLE(2) ? 2u : \
116 (NRFX_SWI_IS_AVAILABLE(1) ? 1u : \
117 0u)))))
118
119 // NRFX_SWI_EGU_COUNT - number of EGU instances to be used by this module
120 // (note - if EGU is not present, EGU_COUNT is not defined).
121 #if NRFX_CHECK(NRFX_EGU_ENABLED)
122 #define NRFX_SWI_EGU_COUNT EGU_COUNT
123 #else
124 #define NRFX_SWI_EGU_COUNT 0
125 #endif
126
127 // These flags are needed only for SWIs that have no corresponding EGU unit
128 // (in EGU such flags are available in hardware).
129 #if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
130 static nrfx_swi_flags_t m_swi_flags[SWI_COUNT - NRFX_SWI_EGU_COUNT];
131 #endif
132 static nrfx_swi_handler_t m_swi_handlers[SWI_COUNT];
133 static uint8_t m_swi_allocated_mask;
134
135
swi_mark_allocated(nrfx_swi_t swi)136 static void swi_mark_allocated(nrfx_swi_t swi)
137 {
138 m_swi_allocated_mask |= (1u << swi);
139 }
140
swi_mark_unallocated(nrfx_swi_t swi)141 static void swi_mark_unallocated(nrfx_swi_t swi)
142 {
143 m_swi_allocated_mask &= ~(1u << swi);
144 }
145
swi_is_allocated(nrfx_swi_t swi)146 static bool swi_is_allocated(nrfx_swi_t swi)
147 {
148 return (m_swi_allocated_mask & (1u << swi));
149 }
150
swi_is_available(nrfx_swi_t swi)151 static bool swi_is_available(nrfx_swi_t swi)
152 {
153 return NRFX_SWI_IS_AVAILABLE(swi);
154 }
155
swi_irq_number_get(nrfx_swi_t swi)156 static IRQn_Type swi_irq_number_get(nrfx_swi_t swi)
157 {
158 #if defined(SWI_PRESENT)
159 return (IRQn_Type)((uint32_t)SWI0_IRQn + (uint32_t)swi);
160 #else
161 return (IRQn_Type)((uint32_t)EGU0_IRQn + (uint32_t)swi);
162 #endif
163 }
164
swi_int_enable(nrfx_swi_t swi)165 static void swi_int_enable(nrfx_swi_t swi)
166 {
167 #if NRFX_SWI_EGU_COUNT
168 if (swi < NRFX_SWI_EGU_COUNT)
169 {
170 NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
171 NRFX_ASSERT(p_egu != NULL);
172 nrf_egu_int_enable(p_egu, NRF_EGU_INT_ALL);
173
174 if (m_swi_handlers[swi] == NULL)
175 {
176 return;
177 }
178 }
179 #endif
180
181 NRFX_IRQ_ENABLE(swi_irq_number_get(swi));
182 }
183
swi_int_disable(nrfx_swi_t swi)184 static void swi_int_disable(nrfx_swi_t swi)
185 {
186 NRFX_IRQ_DISABLE(swi_irq_number_get(swi));
187
188 #if NRFX_SWI_EGU_COUNT
189 if (swi < NRFX_SWI_EGU_COUNT)
190 {
191 nrf_egu_int_disable(nrfx_swi_egu_instance_get(swi), NRF_EGU_INT_ALL);
192 }
193 #endif
194 }
195
swi_handler_setup(nrfx_swi_t swi,nrfx_swi_handler_t event_handler,uint32_t irq_priority)196 static void swi_handler_setup(nrfx_swi_t swi,
197 nrfx_swi_handler_t event_handler,
198 uint32_t irq_priority)
199 {
200 m_swi_handlers[swi] = event_handler;
201 NRFX_IRQ_PRIORITY_SET(swi_irq_number_get(swi), irq_priority);
202 swi_int_enable(swi);
203 }
204
swi_deallocate(nrfx_swi_t swi)205 static void swi_deallocate(nrfx_swi_t swi)
206 {
207 swi_int_disable(swi);
208 m_swi_handlers[swi] = NULL;
209 swi_mark_unallocated(swi);
210 }
211
nrfx_swi_alloc(nrfx_swi_t * p_swi,nrfx_swi_handler_t event_handler,uint32_t irq_priority)212 nrfx_err_t nrfx_swi_alloc(nrfx_swi_t * p_swi,
213 nrfx_swi_handler_t event_handler,
214 uint32_t irq_priority)
215 {
216 NRFX_ASSERT(p_swi != NULL);
217
218 nrfx_err_t err_code;
219
220 for (nrfx_swi_t swi = NRFX_SWI_FIRST; swi <= NRFX_SWI_LAST; ++swi)
221 {
222 if (swi_is_available(swi))
223 {
224 bool allocated = false;
225 NRFX_CRITICAL_SECTION_ENTER();
226 if (!swi_is_allocated(swi))
227 {
228 swi_mark_allocated(swi);
229 allocated = true;
230 }
231 NRFX_CRITICAL_SECTION_EXIT();
232
233 if (allocated)
234 {
235 swi_handler_setup(swi, event_handler, irq_priority);
236
237 *p_swi = swi;
238 NRFX_LOG_INFO("SWI channel allocated: %d.", (*p_swi));
239 return NRFX_SUCCESS;
240 }
241 }
242 }
243
244 err_code = NRFX_ERROR_NO_MEM;
245 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
246 return err_code;
247 }
248
nrfx_swi_is_allocated(nrfx_swi_t swi)249 bool nrfx_swi_is_allocated(nrfx_swi_t swi)
250 {
251 return swi_is_allocated(swi);
252 }
253
nrfx_swi_int_disable(nrfx_swi_t swi)254 void nrfx_swi_int_disable(nrfx_swi_t swi)
255 {
256 NRFX_ASSERT(swi_is_allocated(swi));
257 swi_int_disable(swi);
258 }
259
nrfx_swi_int_enable(nrfx_swi_t swi)260 void nrfx_swi_int_enable(nrfx_swi_t swi)
261 {
262 NRFX_ASSERT(swi_is_allocated(swi));
263 swi_int_enable(swi);
264 }
265
nrfx_swi_free(nrfx_swi_t * p_swi)266 void nrfx_swi_free(nrfx_swi_t * p_swi)
267 {
268 NRFX_ASSERT(p_swi != NULL);
269 nrfx_swi_t swi = *p_swi;
270
271 NRFX_ASSERT(swi_is_allocated(swi));
272 swi_deallocate(swi);
273
274 *p_swi = NRFX_SWI_UNALLOCATED;
275 }
276
nrfx_swi_all_free(void)277 void nrfx_swi_all_free(void)
278 {
279 for (nrfx_swi_t swi = NRFX_SWI_FIRST; swi <= NRFX_SWI_LAST; ++swi)
280 {
281 if (swi_is_allocated(swi))
282 {
283 swi_deallocate(swi);
284 }
285 }
286 }
287
nrfx_swi_trigger(nrfx_swi_t swi,uint8_t flag_number)288 void nrfx_swi_trigger(nrfx_swi_t swi, uint8_t flag_number)
289 {
290 NRFX_ASSERT(swi_is_allocated(swi));
291
292 #if NRFX_SWI_EGU_COUNT
293
294 NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
295 #if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
296 if (p_egu == NULL)
297 {
298 m_swi_flags[swi - NRFX_SWI_EGU_COUNT] |= (1 << flag_number);
299 NRFX_IRQ_PENDING_SET(swi_irq_number_get(swi));
300 }
301 else
302 #endif // (NRFX_SWI_EGU_COUNT < SWI_COUNT)
303 {
304 nrf_egu_task_trigger(p_egu,
305 nrf_egu_task_trigger_get(p_egu, flag_number));
306 }
307
308 #else // -> #if !NRFX_SWI_EGU_COUNT
309
310 m_swi_flags[swi - NRFX_SWI_EGU_COUNT] |= (1 << flag_number);
311 NRFX_IRQ_PENDING_SET(swi_irq_number_get(swi));
312
313 #endif
314 }
315
316 #if NRFX_SWI_EGU_COUNT
egu_irq_handler(nrfx_swi_t swi,uint8_t egu_channel_count)317 static void egu_irq_handler(nrfx_swi_t swi, uint8_t egu_channel_count)
318 {
319 #if (NRFX_SWI_FIRST > 0)
320 NRFX_ASSERT(swi >= NRFX_SWI_FIRST);
321 #endif
322 NRFX_ASSERT(swi <= NRFX_SWI_LAST);
323 nrfx_swi_handler_t handler = m_swi_handlers[swi];
324 NRFX_ASSERT(handler != NULL);
325
326 NRF_EGU_Type * p_egu = nrfx_swi_egu_instance_get(swi);
327 NRFX_ASSERT(p_egu != NULL);
328
329 nrfx_swi_flags_t flags = 0;
330 for (uint8_t i = 0; i < egu_channel_count; ++i)
331 {
332 nrf_egu_event_t egu_event = nrf_egu_event_triggered_get(p_egu, i);
333 if (nrf_egu_event_check(p_egu, egu_event))
334 {
335 flags |= (1u << i);
336 nrf_egu_event_clear(p_egu, egu_event);
337 }
338 }
339
340 handler(swi, flags);
341 }
342 #endif // NRFX_SWI_EGU_COUNT
343
344 #if (NRFX_SWI_EGU_COUNT < SWI_COUNT)
swi_irq_handler(nrfx_swi_t swi)345 static void swi_irq_handler(nrfx_swi_t swi)
346 {
347 #if (NRFX_SWI_FIRST > 0)
348 NRFX_ASSERT(swi >= NRFX_SWI_FIRST);
349 #endif
350 NRFX_ASSERT(swi <= NRFX_SWI_LAST);
351 nrfx_swi_handler_t handler = m_swi_handlers[swi];
352 NRFX_ASSERT(handler != NULL);
353
354 nrfx_swi_flags_t flags = m_swi_flags[swi - NRFX_SWI_EGU_COUNT];
355 m_swi_flags[swi - NRFX_SWI_EGU_COUNT] &= ~flags;
356
357 handler(swi, flags);
358 }
359 #endif // (NRFX_SWI_EGU_COUNT < SWI_COUNT)
360
361
362 #if NRFX_SWI_IS_AVAILABLE(0)
nrfx_swi_0_irq_handler(void)363 void nrfx_swi_0_irq_handler(void)
364 {
365 #if (NRFX_SWI_EGU_COUNT > 0)
366 egu_irq_handler(0, EGU0_CH_NUM);
367 #else
368 swi_irq_handler(0);
369 #endif
370 }
371 #endif // NRFX_SWI_IS_AVAILABLE(0)
372
373 #if NRFX_SWI_IS_AVAILABLE(1)
nrfx_swi_1_irq_handler(void)374 void nrfx_swi_1_irq_handler(void)
375 {
376 #if (NRFX_SWI_EGU_COUNT > 1)
377 egu_irq_handler(1, EGU1_CH_NUM);
378 #else
379 swi_irq_handler(1);
380 #endif
381 }
382 #endif // NRFX_SWI_IS_AVAILABLE(1)
383
384 #if NRFX_SWI_IS_AVAILABLE(2)
nrfx_swi_2_irq_handler(void)385 void nrfx_swi_2_irq_handler(void)
386 {
387 #if (NRFX_SWI_EGU_COUNT > 2)
388 egu_irq_handler(2, EGU2_CH_NUM);
389 #else
390 swi_irq_handler(2);
391 #endif
392 }
393 #endif // NRFX_SWI_IS_AVAILABLE(2)
394
395 #if NRFX_SWI_IS_AVAILABLE(3)
nrfx_swi_3_irq_handler(void)396 void nrfx_swi_3_irq_handler(void)
397 {
398 #if (NRFX_SWI_EGU_COUNT > 3)
399 egu_irq_handler(3, EGU3_CH_NUM);
400 #else
401 swi_irq_handler(3);
402 #endif
403 }
404 #endif // NRFX_SWI_IS_AVAILABLE(3)
405
406 #if NRFX_SWI_IS_AVAILABLE(4)
nrfx_swi_4_irq_handler(void)407 void nrfx_swi_4_irq_handler(void)
408 {
409 #if (NRFX_SWI_EGU_COUNT > 4)
410 egu_irq_handler(4, EGU4_CH_NUM);
411 #else
412 swi_irq_handler(4);
413 #endif
414 }
415 #endif // NRFX_SWI_IS_AVAILABLE(4)
416
417 #if NRFX_SWI_IS_AVAILABLE(5)
nrfx_swi_5_irq_handler(void)418 void nrfx_swi_5_irq_handler(void)
419 {
420 #if (NRFX_SWI_EGU_COUNT > 5)
421 egu_irq_handler(5, EGU5_CH_NUM);
422 #else
423 swi_irq_handler(5);
424 #endif
425 }
426 #endif // NRFX_SWI_IS_AVAILABLE(5)
427
428 #endif // NRFX_CHECK(NRFX_SWI_ENABLED)
429