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 136 static void swi_mark_allocated(nrfx_swi_t swi) 137 { 138 m_swi_allocated_mask |= (1u << swi); 139 } 140 141 static void swi_mark_unallocated(nrfx_swi_t swi) 142 { 143 m_swi_allocated_mask &= ~(1u << swi); 144 } 145 146 static bool swi_is_allocated(nrfx_swi_t swi) 147 { 148 return (m_swi_allocated_mask & (1u << swi)); 149 } 150 151 static bool swi_is_available(nrfx_swi_t swi) 152 { 153 return NRFX_SWI_IS_AVAILABLE(swi); 154 } 155 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 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 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 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 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 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 249 bool nrfx_swi_is_allocated(nrfx_swi_t swi) 250 { 251 return swi_is_allocated(swi); 252 } 253 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 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 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 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 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 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) 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) 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) 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) 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) 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) 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) 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