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