nrf_drv_common.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include <stddef.h>
  13. #include "nrf_drv_common.h"
  14. #include "nrf_assert.h"
  15. #include "app_util_platform.h"
  16. #ifdef SOFTDEVICE_PRESENT
  17. #include "nrf_soc.h"
  18. #endif
  19. #if PERIPHERAL_RESOURCE_SHARING_ENABLED
  20. typedef struct {
  21. nrf_drv_irq_handler_t handler;
  22. bool acquired;
  23. } shared_resource_t;
  24. // SPIM0, SPIS0, SPI0, TWIM0, TWIS0, TWI0
  25. #if (SPI0_ENABLED || SPIS0_ENABLED || TWI0_ENABLED || TWIS0_ENABLED)
  26. #define SERIAL_BOX_0_IN_USE
  27. // [this checking may need a different form in unit tests, hence macro]
  28. #ifndef IS_SERIAL_BOX_0
  29. #define IS_SERIAL_BOX_0(p_per_base) (p_per_base == NRF_SPI0)
  30. #endif
  31. static shared_resource_t m_serial_box_0 = { .acquired = false };
  32. void SPI0_TWI0_IRQHandler(void)
  33. {
  34. ASSERT(m_serial_box_0.handler);
  35. m_serial_box_0.handler();
  36. }
  37. #endif // (SPI0_ENABLED || SPIS0_ENABLED || TWI0_ENABLED || TWIS0_ENABLED)
  38. // SPIM1, SPIS1, SPI1, TWIM1, TWIS1, TWI1
  39. #if (SPI1_ENABLED || SPIS1_ENABLED || TWI1_ENABLED || TWIS1_ENABLED)
  40. #define SERIAL_BOX_1_IN_USE
  41. // [this checking may need a different form in unit tests, hence macro]
  42. #ifndef IS_SERIAL_BOX_1
  43. #define IS_SERIAL_BOX_1(p_per_base) (p_per_base == NRF_SPI1)
  44. #endif
  45. static shared_resource_t m_serial_box_1 = { .acquired = false };
  46. void SPI1_TWI1_IRQHandler(void)
  47. {
  48. ASSERT(m_serial_box_1.handler);
  49. m_serial_box_1.handler();
  50. }
  51. #endif // (SPI1_ENABLED || SPIS1_ENABLED || TWI1_ENABLED || TWIS1_ENABLED)
  52. // SPIM2, SPIS2, SPI2
  53. #if (SPI2_ENABLED || SPIS2_ENABLED)
  54. #define SERIAL_BOX_2_IN_USE
  55. // [this checking may need a different form in unit tests, hence macro]
  56. #ifndef IS_SERIAL_BOX_2
  57. #define IS_SERIAL_BOX_2(p_per_base) (p_per_base == NRF_SPI2)
  58. #endif
  59. static shared_resource_t m_serial_box_2 = { .acquired = false };
  60. void SPIM2_SPIS2_SPI2_IRQHandler(void)
  61. {
  62. ASSERT(m_serial_box_2.handler);
  63. m_serial_box_2.handler();
  64. }
  65. #endif // (SPI2_ENABLED || SPIS2_ENABLED)
  66. // COMP, LPCOMP
  67. #if (COMP_ENABLED || LPCOMP_ENABLED)
  68. #define COMP_LPCOMP_IN_USE
  69. #ifndef IS_COMP_LPCOMP
  70. #define IS_COMP_LPCOMP(p_per_base) ((p_per_base) == NRF_LPCOMP)
  71. #endif
  72. static shared_resource_t m_comp_lpcomp = { .acquired = false };
  73. void LPCOMP_IRQHandler(void)
  74. {
  75. ASSERT(m_comp_lpcomp.handler);
  76. m_comp_lpcomp.handler();
  77. }
  78. #endif // (COMP_ENABLED || LPCOMP_ENABLED)
  79. #if defined(SERIAL_BOX_0_IN_USE) || \
  80. defined(SERIAL_BOX_1_IN_USE) || \
  81. defined(SERIAL_BOX_2_IN_USE) || \
  82. defined(COMP_LPCOMP_IN_USE)
  83. static ret_code_t acquire_shared_resource(shared_resource_t * p_resource,
  84. nrf_drv_irq_handler_t handler)
  85. {
  86. bool busy = false;
  87. CRITICAL_REGION_ENTER();
  88. if (p_resource->acquired)
  89. {
  90. busy = true;
  91. }
  92. else
  93. {
  94. p_resource->acquired = true;
  95. }
  96. CRITICAL_REGION_EXIT();
  97. if (busy)
  98. {
  99. return NRF_ERROR_BUSY;
  100. }
  101. p_resource->handler = handler;
  102. return NRF_SUCCESS;
  103. }
  104. #endif
  105. ret_code_t nrf_drv_common_per_res_acquire(void const * p_per_base,
  106. nrf_drv_irq_handler_t handler)
  107. {
  108. #ifdef SERIAL_BOX_0_IN_USE
  109. if (IS_SERIAL_BOX_0(p_per_base))
  110. {
  111. return acquire_shared_resource(&m_serial_box_0, handler);
  112. }
  113. #endif
  114. #ifdef SERIAL_BOX_1_IN_USE
  115. if (IS_SERIAL_BOX_1(p_per_base))
  116. {
  117. return acquire_shared_resource(&m_serial_box_1, handler);
  118. }
  119. #endif
  120. #ifdef SERIAL_BOX_2_IN_USE
  121. if (IS_SERIAL_BOX_2(p_per_base))
  122. {
  123. return acquire_shared_resource(&m_serial_box_2, handler);
  124. }
  125. #endif
  126. #ifdef COMP_LPCOMP_IN_USE
  127. if (IS_COMP_LPCOMP(p_per_base))
  128. {
  129. return acquire_shared_resource(&m_comp_lpcomp, handler);
  130. }
  131. #endif
  132. return NRF_ERROR_INVALID_PARAM;
  133. }
  134. void nrf_drv_common_per_res_release(void const * p_per_base)
  135. {
  136. #ifdef SERIAL_BOX_0_IN_USE
  137. if (IS_SERIAL_BOX_0(p_per_base))
  138. {
  139. m_serial_box_0.acquired = false;
  140. }
  141. else
  142. #endif
  143. #ifdef SERIAL_BOX_1_IN_USE
  144. if (IS_SERIAL_BOX_1(p_per_base))
  145. {
  146. m_serial_box_1.acquired = false;
  147. }
  148. else
  149. #endif
  150. #ifdef SERIAL_BOX_2_IN_USE
  151. if (IS_SERIAL_BOX_2(p_per_base))
  152. {
  153. m_serial_box_2.acquired = false;
  154. }
  155. else
  156. #endif
  157. #ifdef COMP_LPCOMP_IN_USE
  158. if (IS_COMP_LPCOMP(p_per_base))
  159. {
  160. m_comp_lpcomp.acquired = false;
  161. }
  162. else
  163. #endif
  164. {}
  165. }
  166. #endif // PERIPHERAL_RESOURCE_SHARING_ENABLED
  167. void nrf_drv_common_irq_enable(IRQn_Type IRQn, uint8_t priority)
  168. {
  169. #ifdef SOFTDEVICE_PRESENT
  170. ASSERT((priority == APP_IRQ_PRIORITY_LOW) || (priority == APP_IRQ_PRIORITY_HIGH));
  171. #endif
  172. NVIC_SetPriority(IRQn, priority);
  173. NVIC_ClearPendingIRQ(IRQn);
  174. NVIC_EnableIRQ(IRQn);
  175. }