xref: /nrf52832-nimble/nordic/nrfx/drivers/src/nrfx_dppi.c (revision 150812a83cab50279bd772ef6db1bfaf255f2c5b)
1 /*
2  * Copyright (c) 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_DPPI_ENABLED)
35 
36 #include <nrfx_dppi.h>
37 
38 #define NRFX_LOG_MODULE DPPI
39 #include <nrfx_log.h>
40 
41 #if !defined(NRFX_DPPI_CHANNELS_USED)
42 // Default mask of DPPI channels reserved for other modules.
43 #define NRFX_DPPI_CHANNELS_USED 0x00000000uL
44 #endif
45 
46 #if !defined(NRFX_DPPI_GROUPS_USED)
47 // Default mask of DPPI groups reserved for other modules.
48 #define NRFX_DPPI_GROUPS_USED 0x00000000uL
49 #endif
50 
51 #define DPPI_AVAILABLE_CHANNELS_MASK \
52     (((1UL << DPPI_CH_NUM) - 1) & (~NRFX_DPPI_CHANNELS_USED))
53 
54 #define DPPI_AVAILABLE_GROUPS_MASK   \
55     (((1UL << DPPI_GROUP_NUM) - 1)   & (~NRFX_DPPI_GROUPS_USED))
56 
57 /** @brief Set bit at given position. */
58 #define DPPI_BIT_SET(pos) (1uL << (pos))
59 
60 static uint32_t m_allocated_channels;
61 
62 static uint8_t  m_allocated_groups;
63 
channel_is_allocated(uint8_t channel)64 __STATIC_INLINE bool channel_is_allocated(uint8_t channel)
65 {
66     return ((m_allocated_channels & DPPI_BIT_SET(channel)) != 0);
67 }
68 
group_is_allocated(nrf_dppi_channel_group_t group)69 __STATIC_INLINE bool group_is_allocated(nrf_dppi_channel_group_t group)
70 {
71     return ((m_allocated_groups & DPPI_BIT_SET(group)) != 0);
72 }
73 
nrfx_dppi_free(void)74 void nrfx_dppi_free(void)
75 {
76     uint32_t mask = m_allocated_groups;
77     nrf_dppi_channel_group_t group = NRF_DPPI_CHANNEL_GROUP0;
78 
79     // Disable all channels
80     nrf_dppi_channels_disable(NRF_DPPIC, m_allocated_channels);
81 
82     // Clear all groups configurations
83     while (mask)
84     {
85         if (mask & DPPI_BIT_SET(group))
86         {
87             nrf_dppi_group_clear(NRF_DPPIC, group);
88             mask &= ~DPPI_BIT_SET(group);
89         }
90         group++;
91     }
92 
93     // Clear all allocated channels.
94     m_allocated_channels = 0;
95 
96     // Clear all allocated groups.
97     m_allocated_groups = 0;
98 }
99 
nrfx_dppi_channel_alloc(uint8_t * p_channel)100 nrfx_err_t nrfx_dppi_channel_alloc(uint8_t * p_channel)
101 {
102     nrfx_err_t err_code;
103 
104     // Get mask of available DPPI channels
105     uint32_t remaining_channels = DPPI_AVAILABLE_CHANNELS_MASK & ~(m_allocated_channels);
106     uint8_t channel = 0;
107 
108     if (!remaining_channels)
109     {
110         err_code = NRFX_ERROR_NO_MEM;
111         NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
112         return err_code;
113     }
114 
115     // Find first free channel
116     while (!(remaining_channels & DPPI_BIT_SET(channel)))
117     {
118         channel++;
119     }
120 
121     m_allocated_channels |= DPPI_BIT_SET(channel);
122     *p_channel = channel;
123 
124     err_code = NRFX_SUCCESS;
125     NRFX_LOG_INFO("Allocated channel: %d.", channel);
126     return err_code;
127 }
128 
nrfx_dppi_channel_free(uint8_t channel)129 nrfx_err_t nrfx_dppi_channel_free(uint8_t channel)
130 {
131     nrfx_err_t err_code = NRFX_SUCCESS;
132 
133     if (!channel_is_allocated(channel))
134     {
135         err_code = NRFX_ERROR_INVALID_PARAM;
136     }
137     else
138     {
139         // First disable this channel
140         nrf_dppi_channels_disable(NRF_DPPIC, DPPI_BIT_SET(channel));
141         // Clear channel allocated indication.
142         m_allocated_channels &= ~DPPI_BIT_SET(channel);
143     }
144     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
145     return err_code;
146 }
147 
nrfx_dppi_channel_enable(uint8_t channel)148 nrfx_err_t nrfx_dppi_channel_enable(uint8_t channel)
149 {
150     nrfx_err_t err_code = NRFX_SUCCESS;
151 
152     if (!channel_is_allocated(channel))
153     {
154         err_code = NRFX_ERROR_INVALID_PARAM;
155     }
156     else
157     {
158         nrf_dppi_channels_enable(NRF_DPPIC, DPPI_BIT_SET(channel));
159     }
160     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
161     return err_code;
162 }
163 
nrfx_dppi_channel_disable(uint8_t channel)164 nrfx_err_t nrfx_dppi_channel_disable(uint8_t channel)
165 {
166     nrfx_err_t err_code = NRFX_SUCCESS;
167 
168     if (!channel_is_allocated(channel))
169     {
170         err_code = NRFX_ERROR_INVALID_PARAM;
171     }
172     else
173     {
174         nrf_dppi_channels_disable(NRF_DPPIC, DPPI_BIT_SET(channel));
175         err_code = NRFX_SUCCESS;
176     }
177     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
178     return err_code;
179 }
180 
nrfx_dppi_group_alloc(nrf_dppi_channel_group_t * p_group)181 nrfx_err_t nrfx_dppi_group_alloc(nrf_dppi_channel_group_t * p_group)
182 {
183     nrfx_err_t err_code;
184 
185     // Get mask of available DPPI groups
186     uint32_t remaining_groups = DPPI_AVAILABLE_GROUPS_MASK & ~(m_allocated_groups);
187     nrf_dppi_channel_group_t group = NRF_DPPI_CHANNEL_GROUP0;
188 
189     if (!remaining_groups)
190     {
191         err_code = NRFX_ERROR_NO_MEM;
192         NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
193         return err_code;
194     }
195 
196     // Find first free group
197     while (!(remaining_groups & DPPI_BIT_SET(group)))
198     {
199         group++;
200     }
201 
202     m_allocated_groups |= DPPI_BIT_SET(group);
203     *p_group = group;
204 
205     err_code = NRFX_SUCCESS;
206     NRFX_LOG_INFO("Allocated channel: %d.", group);
207     return err_code;
208 }
209 
nrfx_dppi_group_free(nrf_dppi_channel_group_t group)210 nrfx_err_t nrfx_dppi_group_free(nrf_dppi_channel_group_t group)
211 {
212     nrfx_err_t err_code = NRFX_SUCCESS;
213 
214     if (!group_is_allocated(group))
215     {
216         err_code = NRFX_ERROR_INVALID_PARAM;
217     }
218     else
219     {
220         nrf_dppi_group_disable(NRF_DPPIC, group);
221         // Set bit value to zero at position corresponding to the group number.
222         m_allocated_groups &= ~DPPI_BIT_SET(group);
223     }
224     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
225     return err_code;
226 }
227 
nrfx_dppi_channel_include_in_group(uint8_t channel,nrf_dppi_channel_group_t group)228 nrfx_err_t nrfx_dppi_channel_include_in_group(uint8_t                  channel,
229                                               nrf_dppi_channel_group_t group)
230 {
231     nrfx_err_t err_code = NRFX_SUCCESS;
232 
233     if (!group_is_allocated(group) || !channel_is_allocated(channel))
234     {
235         err_code = NRFX_ERROR_INVALID_PARAM;
236     }
237     else
238     {
239         nrf_dppi_channels_include_in_group(NRF_DPPIC, DPPI_BIT_SET(channel), group);
240     }
241     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
242     return err_code;
243 }
244 
nrfx_dppi_channel_remove_from_group(uint8_t channel,nrf_dppi_channel_group_t group)245 nrfx_err_t nrfx_dppi_channel_remove_from_group(uint8_t                  channel,
246                                                nrf_dppi_channel_group_t group)
247 {
248     nrfx_err_t err_code = NRFX_SUCCESS;
249 
250     if (!group_is_allocated(group) || !channel_is_allocated(channel))
251     {
252         err_code = NRFX_ERROR_INVALID_PARAM;
253     }
254     else
255     {
256         nrf_dppi_channels_remove_from_group(NRF_DPPIC, DPPI_BIT_SET(channel), group);
257     }
258     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
259     return err_code;
260 }
261 
nrfx_dppi_group_clear(nrf_dppi_channel_group_t group)262 nrfx_err_t nrfx_dppi_group_clear(nrf_dppi_channel_group_t group)
263 {
264     nrfx_err_t err_code = NRFX_SUCCESS;
265 
266     if (!group_is_allocated(group))
267     {
268         err_code = NRFX_ERROR_INVALID_PARAM;
269     }
270     else
271     {
272         nrf_dppi_channels_remove_from_group(NRF_DPPIC, DPPI_AVAILABLE_CHANNELS_MASK, group);
273     }
274     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
275     return err_code;
276 }
277 
nrfx_dppi_group_enable(nrf_dppi_channel_group_t group)278 nrfx_err_t nrfx_dppi_group_enable(nrf_dppi_channel_group_t group)
279 {
280     nrfx_err_t err_code = NRFX_SUCCESS;
281 
282     if (!group_is_allocated(group))
283     {
284         err_code = NRFX_ERROR_INVALID_PARAM;
285     }
286     else
287     {
288         nrf_dppi_group_enable(NRF_DPPIC, group);
289     }
290     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
291     return err_code;
292 }
293 
nrfx_dppi_group_disable(nrf_dppi_channel_group_t group)294 nrfx_err_t nrfx_dppi_group_disable(nrf_dppi_channel_group_t group)
295 {
296     nrfx_err_t err_code = NRFX_SUCCESS;
297 
298     if (!group_is_allocated(group))
299     {
300         err_code = NRFX_ERROR_INVALID_PARAM;
301     }
302     else
303     {
304         nrf_dppi_group_disable(NRF_DPPIC, group);
305     }
306     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
307     return err_code;
308 }
309 
310 #endif // NRFX_CHECK(NRFX_DPPI_ENABLED)
311