1 /*
2 * Copyright (c) 2017 - 2020, 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_PRS_ENABLED)
35 #include "nrfx_prs.h"
36
37 #define NRFX_LOG_MODULE PRS
38 #include <nrfx_log.h>
39
40 #define LOG_FUNCTION_EXIT(level, ret_code) \
41 NRFX_LOG_##level("Function: %s, error code: %s.", \
42 __func__, \
43 NRFX_LOG_ERROR_STRING_GET(ret_code))
44
45
46 typedef struct {
47 nrfx_irq_handler_t handler;
48 bool acquired;
49 } prs_box_t;
50
51 #define PRS_BOX_DEFINE(n) \
52 static prs_box_t m_prs_box_##n = { .handler = NULL, .acquired = false }; \
53 void nrfx_prs_box_##n##_irq_handler(void) \
54 { \
55 NRFX_ASSERT(m_prs_box_##n.handler); \
56 m_prs_box_##n.handler(); \
57 }
58
59 #if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
60 PRS_BOX_DEFINE(0)
61 #endif
62 #if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
63 PRS_BOX_DEFINE(1)
64 #endif
65 #if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
66 PRS_BOX_DEFINE(2)
67 #endif
68 #if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
69 PRS_BOX_DEFINE(3)
70 #endif
71 #if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
72 PRS_BOX_DEFINE(4)
73 #endif
74
75
prs_box_get(void const * p_base_addr)76 static prs_box_t * prs_box_get(void const * p_base_addr)
77 {
78 #if !defined(IS_PRS_BOX)
79 #define IS_PRS_BOX(n, p_base_addr) ((p_base_addr) == NRFX_PRS_BOX_##n##_ADDR)
80 #endif
81
82 #if defined(NRFX_PRS_BOX_0_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_0_ENABLED)
83 if (IS_PRS_BOX(0, p_base_addr)) { return &m_prs_box_0; }
84 else
85 #endif
86 #if defined(NRFX_PRS_BOX_1_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_1_ENABLED)
87 if (IS_PRS_BOX(1, p_base_addr)) { return &m_prs_box_1; }
88 else
89 #endif
90 #if defined(NRFX_PRS_BOX_2_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_2_ENABLED)
91 if (IS_PRS_BOX(2, p_base_addr)) { return &m_prs_box_2; }
92 else
93 #endif
94 #if defined(NRFX_PRS_BOX_3_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_3_ENABLED)
95 if (IS_PRS_BOX(3, p_base_addr)) { return &m_prs_box_3; }
96 else
97 #endif
98 #if defined(NRFX_PRS_BOX_4_ADDR) && NRFX_CHECK(NRFX_PRS_BOX_4_ENABLED)
99 if (IS_PRS_BOX(4, p_base_addr)) { return &m_prs_box_4; }
100 else
101 #endif
102 {
103 return NULL;
104 }
105 }
106
nrfx_prs_acquire(void const * p_base_addr,nrfx_irq_handler_t irq_handler)107 nrfx_err_t nrfx_prs_acquire(void const * p_base_addr,
108 nrfx_irq_handler_t irq_handler)
109 {
110 NRFX_ASSERT(p_base_addr);
111
112 nrfx_err_t ret_code;
113
114 prs_box_t * p_box = prs_box_get(p_base_addr);
115 if (p_box != NULL)
116 {
117 bool busy = false;
118
119 NRFX_CRITICAL_SECTION_ENTER();
120 if (p_box->acquired)
121 {
122 busy = true;
123 }
124 else
125 {
126 p_box->handler = irq_handler;
127 p_box->acquired = true;
128 }
129 NRFX_CRITICAL_SECTION_EXIT();
130
131 if (busy)
132 {
133 ret_code = NRFX_ERROR_BUSY;
134 LOG_FUNCTION_EXIT(WARNING, ret_code);
135 return ret_code;
136 }
137 }
138
139 ret_code = NRFX_SUCCESS;
140 LOG_FUNCTION_EXIT(INFO, ret_code);
141 return ret_code;
142 }
143
nrfx_prs_release(void const * p_base_addr)144 void nrfx_prs_release(void const * p_base_addr)
145 {
146 NRFX_ASSERT(p_base_addr);
147
148 prs_box_t * p_box = prs_box_get(p_base_addr);
149 if (p_box != NULL)
150 {
151 p_box->handler = NULL;
152 p_box->acquired = false;
153 }
154 }
155
156
157 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
158