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 64 __STATIC_INLINE bool channel_is_allocated(uint8_t channel) 65 { 66 return ((m_allocated_channels & DPPI_BIT_SET(channel)) != 0); 67 } 68 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 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 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 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 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 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 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 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 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 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 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 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 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