xref: /nrf52832-nimble/nordic/nrfx/drivers/src/nrfx_swi.c (revision 150812a83cab50279bd772ef6db1bfaf255f2c5b)
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