aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_error.h95
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c123
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.h166
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_sdm.h56
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c48
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_soc.h80
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/radio_config/radio_config.c188
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/radio_config/radio_config.h58
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/config/sdio_config.h55
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/sdio.c244
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/sdio.h105
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/spi_master/spi_5W_master.c629
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/spi_master/spi_5W_master.h206
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/config/twi_master_config.h55
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_hw_master.c331
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_master.h137
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_sw_master.c519
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd.c2333
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd.h943
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd_errata.h193
20 files changed, 6564 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_error.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_error.h
new file mode 100644
index 0000000..c673beb
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_error.h
@@ -0,0 +1,95 @@
+/**
+ * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/* Header guard */
+
+#ifndef SOFTDEVICE_PRESENT
+
+/**
+ @defgroup nrf_error Global Error Codes
+ @{
+
+ @brief Global Error definitions
+*/
+
+#ifndef NRF_ERROR_H__
+#define NRF_ERROR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions
+ * @{ */
+#define NRF_ERROR_BASE_NUM (0x0) ///< Global error base
+#define NRF_ERROR_SDM_BASE_NUM (0x1000) ///< SDM error base
+#define NRF_ERROR_SOC_BASE_NUM (0x2000) ///< SoC error base
+#define NRF_ERROR_STK_BASE_NUM (0x3000) ///< STK error base
+/** @} */
+
+#define NRF_SUCCESS (NRF_ERROR_BASE_NUM + 0) ///< Successful command
+#define NRF_ERROR_SVC_HANDLER_MISSING (NRF_ERROR_BASE_NUM + 1) ///< SVC handler is missing
+#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED (NRF_ERROR_BASE_NUM + 2) ///< SoftDevice has not been enabled
+#define NRF_ERROR_INTERNAL (NRF_ERROR_BASE_NUM + 3) ///< Internal Error
+#define NRF_ERROR_NO_MEM (NRF_ERROR_BASE_NUM + 4) ///< No Memory for operation
+#define NRF_ERROR_NOT_FOUND (NRF_ERROR_BASE_NUM + 5) ///< Not found
+#define NRF_ERROR_NOT_SUPPORTED (NRF_ERROR_BASE_NUM + 6) ///< Not supported
+#define NRF_ERROR_INVALID_PARAM (NRF_ERROR_BASE_NUM + 7) ///< Invalid Parameter
+#define NRF_ERROR_INVALID_STATE (NRF_ERROR_BASE_NUM + 8) ///< Invalid state, operation disallowed in this state
+#define NRF_ERROR_INVALID_LENGTH (NRF_ERROR_BASE_NUM + 9) ///< Invalid Length
+#define NRF_ERROR_INVALID_FLAGS (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags
+#define NRF_ERROR_INVALID_DATA (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data
+#define NRF_ERROR_DATA_SIZE (NRF_ERROR_BASE_NUM + 12) ///< Data size exceeds limit
+#define NRF_ERROR_TIMEOUT (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out
+#define NRF_ERROR_NULL (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer
+#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation
+#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address
+#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_ERROR_H__
+
+/**
+ @}
+*/
+
+#endif // SOFTDEVICE_PRESENT
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c
new file mode 100644
index 0000000..8fa8b2b
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c
@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <stdlib.h>
+#include "nrf_soc.h"
+#include "nrf_error.h"
+
+static uint8_t m_in_critical_region = 0;
+
+uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn)
+{
+ NVIC_EnableIRQ(IRQn);
+ return NRF_SUCCESS;
+}
+
+uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn)
+{
+ NVIC_DisableIRQ(IRQn);
+ return NRF_SUCCESS;
+}
+
+uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq)
+{
+ if (p_pending_irq != NULL)
+ {
+ *p_pending_irq = NVIC_GetPendingIRQ(IRQn);
+ return NRF_SUCCESS;
+ }
+ return NRF_ERROR_NULL;
+}
+
+uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn)
+{
+ NVIC_SetPendingIRQ(IRQn);
+ return NRF_SUCCESS;
+}
+
+uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ NVIC_ClearPendingIRQ(IRQn);
+ return NRF_SUCCESS;
+}
+
+uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ NVIC_SetPriority(IRQn, priority);
+ return NRF_SUCCESS;
+}
+
+uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority)
+{
+ if (p_priority != NULL)
+ {
+ *p_priority = NVIC_GetPriority(IRQn);
+ return NRF_SUCCESS;
+ }
+
+ return NRF_ERROR_NULL;
+}
+
+uint32_t sd_nvic_SystemReset(void)
+{
+ NVIC_SystemReset();
+ return NRF_SUCCESS;
+}
+
+uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region)
+{
+ __disable_irq();
+
+ *p_is_nested_critical_region = (m_in_critical_region != 0);
+ m_in_critical_region++;
+
+ return NRF_SUCCESS;
+}
+
+uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region)
+{
+ m_in_critical_region--;
+
+ if (is_nested_critical_region == 0)
+ {
+ m_in_critical_region = 0;
+ __enable_irq();
+ }
+ return NRF_SUCCESS;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.h
new file mode 100644
index 0000000..58dd027
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.h
@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NRF_NVIC_H__
+#define NRF_NVIC_H__
+
+#include <stdint.h>
+#include "nrf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Enable External Interrupt.
+ * @note Corresponds to NVIC_EnableIRQ in CMSIS.
+ *
+ * @pre{IRQn is valid and not reserved by the stack}
+ *
+ * @param[in] IRQn See the NVIC_EnableIRQ documentation in CMSIS.
+ *
+ * @retval ::NRF_SUCCESS The interrupt was enabled.
+ */
+uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn);
+
+/**@brief Disable External Interrupt.
+ * @note Corresponds to NVIC_DisableIRQ in CMSIS.
+ *
+ * @pre{IRQn is valid and not reserved by the stack}
+ *
+ * @param[in] IRQn See the NVIC_DisableIRQ documentation in CMSIS
+ *
+ * @retval ::NRF_SUCCESS The interrupt was disabled.
+ */
+uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn);
+
+/**@brief Get Pending Interrupt.
+ * @note Corresponds to NVIC_GetPendingIRQ in CMSIS.
+ *
+ * @pre{IRQn is valid and not reserved by the stack}
+ *
+ * @param[in] IRQn See the NVIC_GetPendingIRQ documentation in CMSIS.
+ * @param[out] p_pending_irq Return value from NVIC_GetPendingIRQ.
+ *
+ * @retval ::NRF_SUCCESS The interrupt is available for the application.
+ */
+uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq);
+
+/**@brief Set Pending Interrupt.
+ * @note Corresponds to NVIC_SetPendingIRQ in CMSIS.
+ *
+ * @pre{IRQn is valid and not reserved by the stack}
+ *
+ * @param[in] IRQn See the NVIC_SetPendingIRQ documentation in CMSIS.
+ *
+ * @retval ::NRF_SUCCESS The interrupt is set pending.
+ */
+uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn);
+
+/**@brief Clear Pending Interrupt.
+ * @note Corresponds to NVIC_ClearPendingIRQ in CMSIS.
+ *
+ * @pre{IRQn is valid and not reserved by the stack}
+ *
+ * @param[in] IRQn See the NVIC_ClearPendingIRQ documentation in CMSIS.
+ *
+ * @retval ::NRF_SUCCESS The interrupt pending flag is cleared.
+ */
+uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn);
+
+/**@brief Set Interrupt Priority.
+ * @note Corresponds to NVIC_SetPriority in CMSIS.
+ *
+ * @pre{IRQn is valid and not reserved by the stack}
+ * @pre{priority is valid and not reserved by the stack}
+ *
+ * @param[in] IRQn See the NVIC_SetPriority documentation in CMSIS.
+ * @param[in] priority A valid IRQ priority for use by the application.
+ *
+ * @retval ::NRF_SUCCESS The interrupt and priority level is available for the application.
+ */
+uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority);
+
+/**@brief Get Interrupt Priority.
+ * @note Corresponds to NVIC_GetPriority in CMSIS.
+ *
+ * @pre{IRQn is valid and not reserved by the stack}
+ *
+ * @param[in] IRQn See the NVIC_GetPriority documentation in CMSIS.
+ * @param[out] p_priority Return value from NVIC_GetPriority.
+ *
+ * @retval ::NRF_SUCCESS The interrupt priority is returned in p_priority.
+ */
+uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority);
+
+/**@brief System Reset.
+ * @note Corresponds to NVIC_SystemReset in CMSIS.
+ *
+ * @retval ::NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN
+ */
+uint32_t sd_nvic_SystemReset(void);
+
+/**@brief Enters critical region.
+ *
+ * @post Application interrupts will be disabled.
+ * @sa sd_nvic_critical_region_exit
+ *
+ * @param[out] p_is_nested_critical_region 1: If in a nested critical region.
+ * 0: Otherwise.
+ *
+ * @retval ::NRF_SUCCESS
+ */
+uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region);
+
+/**@brief Exit critical region.
+ *
+ * @pre Application has entered a critical region using ::sd_nvic_critical_region_enter.
+ * @post If not in a nested critical region, the application interrupts will restored to the state before ::sd_nvic_critical_region_enter was called.
+ *
+ * @param[in] is_nested_critical_region If this is set to 1, the critical region won't be exited. @sa sd_nvic_critical_region_enter.
+ *
+ * @retval ::NRF_SUCCESS
+ */
+uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRF_NVIC_H__ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_sdm.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_sdm.h
new file mode 100644
index 0000000..ec3f150
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_sdm.h
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NRF_SDM_H__
+#define NRF_SDM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define NRF_FAULT_ID_SD_RANGE_START 0x00000000 /**< SoftDevice ID range start. */
+#define NRF_FAULT_ID_APP_RANGE_START 0x00001000 /**< Application ID range start. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif // NRF_SDM_H__
+
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c
new file mode 100644
index 0000000..da25fbb
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <stdlib.h>
+#include "nrf_soc.h"
+#include "nrf_error.h"
+
+uint32_t sd_app_evt_wait(void)
+{
+ __WFE();
+ return NRF_SUCCESS;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_soc.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_soc.h
new file mode 100644
index 0000000..c1c9d04
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/nrf_soc_nosd/nrf_soc.h
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NRF_SOC_H__
+#define NRF_SOC_H__
+
+#include <stdint.h>
+#include "nrf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Waits for an application event.
+ *
+ * An application event is either an application interrupt or a pended interrupt when the
+ * interrupt is disabled. When the interrupt is enabled it will be taken immediately since
+ * this function will wait in thread mode, then the execution will return in the application's
+ * main thread. When an interrupt is disabled and gets pended it will return to the application's
+ * thread main. The application must ensure that the pended flag is cleared using
+ * ::sd_nvic_ClearPendingIRQ in order to sleep using this function. This is only necessary for
+ * disabled interrupts, as the interrupt handler will clear the pending flag automatically for
+ * enabled interrupts.
+ *
+ * In order to wake up from disabled interrupts, the SEVONPEND flag has to be set in the Cortex-M0
+ * System Control Register (SCR). @sa CMSIS_SCB
+ *
+ * @note If an application interrupt has happened since the last time sd_app_evt_wait was
+ * called this function will return immediately and not go to sleep. This is to avoid race
+ * conditions that can occur when a flag is updated in the interrupt handler and processed
+ * in the main loop.
+ *
+ * @post An application interrupt has happened or a interrupt pending flag is set.
+ *
+ * @retval ::NRF_SUCCESS
+ */
+uint32_t sd_app_evt_wait(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRF_SOC_H__ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/radio_config/radio_config.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/radio_config/radio_config.c
new file mode 100644
index 0000000..e3849df
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/radio_config/radio_config.c
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/** @file
+* @addtogroup nrf_dev_radio_rx_example_main nrf_dev_radio_tx_example_main
+* @{
+*/
+
+#include "radio_config.h"
+#include "nrf_delay.h"
+
+/* These are set to zero as ShockBurst packets don't have corresponding fields. */
+#define PACKET_S1_FIELD_SIZE (0UL) /**< Packet S1 field size in bits. */
+#define PACKET_S0_FIELD_SIZE (0UL) /**< Packet S0 field size in bits. */
+#define PACKET_LENGTH_FIELD_SIZE (0UL) /**< Packet length field size in bits. */
+
+/**
+ * @brief Function for swapping/mirroring bits in a byte.
+ *
+ *@verbatim
+ * output_bit_7 = input_bit_0
+ * output_bit_6 = input_bit_1
+ * :
+ * output_bit_0 = input_bit_7
+ *@endverbatim
+ *
+ * @param[in] inp is the input byte to be swapped.
+ *
+ * @return
+ * Returns the swapped/mirrored input byte.
+ */
+static uint32_t swap_bits(uint32_t inp);
+
+/**
+ * @brief Function for swapping bits in a 32 bit word for each byte individually.
+ *
+ * The bits are swapped as follows:
+ * @verbatim
+ * output[31:24] = input[24:31]
+ * output[23:16] = input[16:23]
+ * output[15:8] = input[8:15]
+ * output[7:0] = input[0:7]
+ * @endverbatim
+ * @param[in] input is the input word to be swapped.
+ *
+ * @return
+ * Returns the swapped input byte.
+ */
+static uint32_t bytewise_bitswap(uint32_t inp);
+
+static uint32_t swap_bits(uint32_t inp)
+{
+ uint32_t i;
+ uint32_t retval = 0;
+
+ inp = (inp & 0x000000FFUL);
+
+ for (i = 0; i < 8; i++)
+ {
+ retval |= ((inp >> i) & 0x01) << (7 - i);
+ }
+
+ return retval;
+}
+
+
+static uint32_t bytewise_bitswap(uint32_t inp)
+{
+ return (swap_bits(inp >> 24) << 24)
+ | (swap_bits(inp >> 16) << 16)
+ | (swap_bits(inp >> 8) << 8)
+ | (swap_bits(inp));
+}
+
+
+/**
+ * @brief Function for configuring the radio to operate in ShockBurst compatible mode.
+ *
+ * To configure the application running on nRF24L series devices:
+ *
+ * @verbatim
+ * uint8_t tx_address[5] = { 0xC0, 0x01, 0x23, 0x45, 0x67 };
+ * hal_nrf_set_rf_channel(7);
+ * hal_nrf_set_address_width(HAL_NRF_AW_5BYTES);
+ * hal_nrf_set_address(HAL_NRF_TX, tx_address);
+ * hal_nrf_set_address(HAL_NRF_PIPE0, tx_address);
+ * hal_nrf_open_pipe(0, false);
+ * hal_nrf_set_datarate(HAL_NRF_1MBPS);
+ * hal_nrf_set_crc_mode(HAL_NRF_CRC_16BIT);
+ * hal_nrf_setup_dynamic_payload(0xFF);
+ * hal_nrf_enable_dynamic_payload(false);
+ * @endverbatim
+ *
+ * When transmitting packets with hal_nrf_write_tx_payload(const uint8_t *tx_pload, uint8_t length),
+ * match the length with PACKET_STATIC_LENGTH.
+ * hal_nrf_write_tx_payload(payload, PACKET_STATIC_LENGTH);
+ *
+*/
+void radio_configure()
+{
+ // Radio config
+ NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos);
+ NRF_RADIO->FREQUENCY = 7UL; // Frequency bin 7, 2407MHz
+ NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos);
+
+ // Radio address config
+ NRF_RADIO->PREFIX0 =
+ ((uint32_t)swap_bits(0xC3) << 24) // Prefix byte of address 3 converted to nRF24L series format
+ | ((uint32_t)swap_bits(0xC2) << 16) // Prefix byte of address 2 converted to nRF24L series format
+ | ((uint32_t)swap_bits(0xC1) << 8) // Prefix byte of address 1 converted to nRF24L series format
+ | ((uint32_t)swap_bits(0xC0) << 0); // Prefix byte of address 0 converted to nRF24L series format
+
+ NRF_RADIO->PREFIX1 =
+ ((uint32_t)swap_bits(0xC7) << 24) // Prefix byte of address 7 converted to nRF24L series format
+ | ((uint32_t)swap_bits(0xC6) << 16) // Prefix byte of address 6 converted to nRF24L series format
+ | ((uint32_t)swap_bits(0xC4) << 0); // Prefix byte of address 4 converted to nRF24L series format
+
+ NRF_RADIO->BASE0 = bytewise_bitswap(0x01234567UL); // Base address for prefix 0 converted to nRF24L series format
+ NRF_RADIO->BASE1 = bytewise_bitswap(0x89ABCDEFUL); // Base address for prefix 1-7 converted to nRF24L series format
+
+ NRF_RADIO->TXADDRESS = 0x00UL; // Set device address 0 to use when transmitting
+ NRF_RADIO->RXADDRESSES = 0x01UL; // Enable device address 0 to use to select which addresses to receive
+
+ // Packet configuration
+ NRF_RADIO->PCNF0 = (PACKET_S1_FIELD_SIZE << RADIO_PCNF0_S1LEN_Pos) |
+ (PACKET_S0_FIELD_SIZE << RADIO_PCNF0_S0LEN_Pos) |
+ (PACKET_LENGTH_FIELD_SIZE << RADIO_PCNF0_LFLEN_Pos); //lint !e845 "The right argument to operator '|' is certain to be 0"
+
+ // Packet configuration
+ NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
+ (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
+ (PACKET_BASE_ADDRESS_LENGTH << RADIO_PCNF1_BALEN_Pos) |
+ (PACKET_STATIC_LENGTH << RADIO_PCNF1_STATLEN_Pos) |
+ (PACKET_PAYLOAD_MAXSIZE << RADIO_PCNF1_MAXLEN_Pos); //lint !e845 "The right argument to operator '|' is certain to be 0"
+
+ // CRC Config
+ NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits
+ if ((NRF_RADIO->CRCCNF & RADIO_CRCCNF_LEN_Msk) == (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos))
+ {
+ NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
+ NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16 + x^12^x^5 + 1
+ }
+ else if ((NRF_RADIO->CRCCNF & RADIO_CRCCNF_LEN_Msk) == (RADIO_CRCCNF_LEN_One << RADIO_CRCCNF_LEN_Pos))
+ {
+ NRF_RADIO->CRCINIT = 0xFFUL; // Initial value
+ NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8 + x^2^x^1 + 1
+ }
+}
+
+/**
+ * @}
+ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/radio_config/radio_config.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/radio_config/radio_config.h
new file mode 100644
index 0000000..f8e8be5
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/radio_config/radio_config.h
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef RADIO_CONFIG_H
+#define RADIO_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PACKET_BASE_ADDRESS_LENGTH (4UL) //!< Packet base address length field size in bytes
+#define PACKET_STATIC_LENGTH (1UL) //!< Packet static length in bytes
+#define PACKET_PAYLOAD_MAXSIZE (PACKET_STATIC_LENGTH) //!< Packet payload maximum size in bytes
+
+void radio_configure(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/config/sdio_config.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/config/sdio_config.h
new file mode 100644
index 0000000..6551ec0
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/config/sdio_config.h
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef SDIO_CONFIG_H
+#define SDIO_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SDIO_CONFIG_CLOCK_PIN_NUMBER 24
+#define SDIO_CONFIG_DATA_PIN_NUMBER 25
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/sdio.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/sdio.c
new file mode 100644
index 0000000..68763b0
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/sdio.c
@@ -0,0 +1,244 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <stdint.h>
+
+#include "nrf.h"
+#include "nrf_delay.h"
+#include "sdio.h"
+#include "nrf_gpio.h"
+
+#include "sdio_config.h"
+
+/*lint ++flb "Enter library region" */
+
+/*lint -e717 -save "Suppress do {} while (0) for these macros" */
+#define SDIO_CLOCK_HIGH() do { NRF_GPIO->OUTSET = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line high */
+#define SDIO_CLOCK_LOW() do { NRF_GPIO->OUTCLR = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line low */
+#define SDIO_DATA_HIGH() do { NRF_GPIO->OUTSET = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line high */
+#define SDIO_DATA_LOW() do { NRF_GPIO->OUTCLR = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line low */
+#define SDIO_DATA_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Configures SDA pin as output */
+#define SDIO_CLOCK_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Configures SCL pin as output */
+/*lint -restore */
+
+/*lint -emacro(845,SDIO_DATA_INPUT) // A zero has been given as right argument to operator '|'" */
+
+#define SDIO_DATA_INPUT() do { \
+ nrf_gpio_cfg_input(25, NRF_GPIO_PIN_NOPULL); \
+} while (0)
+
+#define SDIO_DATA_READ() ((NRF_GPIO->IN >> SDIO_CONFIG_DATA_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SDA */
+#define SDIO_CLOCK_READ() ((NRF_GPIO->IN >> SDIO_CONFIG_CLOCK_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SCL */
+#define SDIO_DELAY() nrf_delay_us(10) /*!< Time to wait when pin states are changed. For fast-mode the delay can be zero and for standard-mode 4 us delay is sufficient. */
+
+void sdio_init(void)
+{
+ SDIO_CLOCK_HIGH();
+ SDIO_DATA_HIGH();
+ SDIO_CLOCK_OUTPUT();
+ SDIO_DATA_INPUT();
+
+ // If slave is stuck in the middle of transfer, clock out bits until the slave ACKs the transfer
+ for (uint_fast8_t i = 16; i--;)
+ {
+ SDIO_DELAY();
+ SDIO_CLOCK_LOW();
+ SDIO_DELAY();
+ SDIO_CLOCK_HIGH();
+ SDIO_DELAY();
+
+ if (SDIO_DATA_READ())
+ {
+ break;
+ }
+ }
+
+ for (uint_fast8_t i = 5; i--;)
+ {
+ SDIO_DELAY();
+ SDIO_CLOCK_LOW();
+ SDIO_DELAY();
+ SDIO_CLOCK_HIGH();
+ }
+
+ SDIO_DATA_OUTPUT();
+ SDIO_DATA_HIGH();
+
+ SDIO_DELAY();
+}
+
+uint8_t sdio_read_byte(uint8_t address)
+{
+ uint8_t data_byte = 0;
+
+ SDIO_DATA_OUTPUT();
+
+ for (uint_fast8_t i = 8; i--;)
+ {
+ SDIO_DELAY();
+
+ SDIO_CLOCK_LOW();
+
+ if (address & (1U << i))
+ {
+ SDIO_DATA_HIGH();
+ }
+ else
+ {
+ SDIO_DATA_LOW();
+ }
+
+ SDIO_DELAY();
+
+ SDIO_CLOCK_HIGH();
+ }
+
+ nrf_delay_us(20);
+
+ SDIO_DATA_INPUT();
+
+ for (uint_fast8_t i = 8; i--;)
+ {
+ SDIO_CLOCK_LOW();
+ SDIO_DELAY();
+ SDIO_CLOCK_HIGH();
+ SDIO_DELAY();
+ data_byte |= (uint8_t)(SDIO_DATA_READ() << i);
+ }
+
+ SDIO_DATA_HIGH();
+ SDIO_DATA_OUTPUT();
+
+ SDIO_DELAY();
+
+ return data_byte;
+}
+
+void sdio_read_burst(uint8_t * target_buffer, uint8_t target_buffer_size)
+{
+ uint_fast8_t address = 0x63;
+
+ SDIO_DATA_OUTPUT();
+
+ for (uint_fast8_t bit_index=8; bit_index--;)
+ {
+ SDIO_CLOCK_LOW();
+
+ if (address & (1U << bit_index))
+ {
+ SDIO_DATA_HIGH();
+ }
+ else
+ {
+ SDIO_DATA_LOW();
+ }
+
+ SDIO_CLOCK_HIGH();
+ }
+
+ SDIO_DATA_INPUT();
+
+ for (uint_fast8_t target_buffer_index = 0; target_buffer_index < target_buffer_size; target_buffer_index++)
+ {
+ target_buffer[target_buffer_index] = 0;
+
+ for (uint_fast8_t bit_index = 8; bit_index--;)
+ {
+ SDIO_CLOCK_LOW();
+ SDIO_CLOCK_HIGH();
+ target_buffer[target_buffer_index] |= (uint8_t)(SDIO_DATA_READ() << bit_index);
+ }
+ }
+}
+
+void sdio_write_byte(uint8_t address, uint8_t data_byte)
+{
+ // Add write indication bit
+ address |= 0x80;
+
+ SDIO_DATA_OUTPUT();
+
+ for (uint_fast8_t i = 8; i--;)
+ {
+ SDIO_DELAY();
+
+ SDIO_CLOCK_LOW();
+
+ if (address & (1U << i))
+ {
+ SDIO_DATA_HIGH();
+ }
+ else
+ {
+ SDIO_DATA_LOW();
+ }
+
+ SDIO_DELAY();
+
+ SDIO_CLOCK_HIGH();
+ }
+
+ SDIO_DELAY();
+
+ for (uint_fast8_t i = 8; i--;)
+ {
+ SDIO_CLOCK_LOW();
+
+ if (data_byte & (1U << i))
+ {
+ SDIO_DATA_HIGH();
+ }
+ else
+ {
+ SDIO_DATA_LOW();
+ }
+
+ SDIO_DELAY();
+
+ SDIO_CLOCK_HIGH();
+
+ SDIO_DELAY();
+ }
+
+ SDIO_DATA_HIGH();
+
+ SDIO_DELAY();
+}
+
+/*lint --flb "Leave library region" */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/sdio.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/sdio.h
new file mode 100644
index 0000000..bea2062
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/sdio/sdio.h
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef SDIO_H
+#define SDIO_H
+
+/*lint ++flb "Enter library region" */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @file
+* @brief 2-wire serial interface driver (compatible with ADNS2080 mouse sensor driver)
+*
+*
+* @defgroup nrf_drivers_sdio SDIO driver
+* @{
+* @ingroup nrf_drivers
+* @brief 2-wire serial interface driver.
+*/
+
+/**
+ * @brief Function for initializing 2-wire serial interface and trying to handle stuck slaves.
+ *
+ */
+void sdio_init(void);
+
+/**
+ * @brief Function for reading a byte over 2-wire serial interface.
+ *
+ * Developer needs to implement this function in a way that suits the hardware.
+ * @param address Register address to read from
+ * @return Byte read
+ */
+uint8_t sdio_read_byte(uint8_t address);
+
+/**
+ * @brief Function for reading several bytes over 2-wire serial interface using burst mode.
+ *
+ * Developer needs to implement this function in a way that suits the hardware.
+ * @param target_buffer Buffer location to store read bytes to
+ * @param target_buffer_size Bytes allocated for target_buffer
+ */
+void sdio_read_burst(uint8_t *target_buffer, uint8_t target_buffer_size);
+
+/**
+ * @brief Function for writing a byte over 2-wire serial interface.
+ *
+ * Developer needs to implement this function in a way that suits the hardware.
+ * @param address Register address to write to
+ * @param data_byte Data byte to write
+ */
+void sdio_write_byte(uint8_t address, uint8_t data_byte);
+
+/**
+ *@}
+ **/
+
+/*lint --flb "Leave library region" */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/spi_master/spi_5W_master.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/spi_master/spi_5W_master.c
new file mode 100644
index 0000000..031863d
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/spi_master/spi_5W_master.c
@@ -0,0 +1,629 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**@file
+ *
+ * @defgroup ser_phy_spi_5W_hw_driver_master spi_5W_master.c
+ * @{
+ * @ingroup ser_phy_spi_5W_hw_driver_master
+ *
+ * @brief SPI_5W_RAW hardware driver.
+ */
+
+#include "app_error.h"
+#include "app_util_platform.h"
+#include "nrf_gpio.h"
+#include "nrf.h"
+#include "spi_5W_master.h"
+#include "ser_config_5W_app.h"
+#include "ser_phy_debug_app.h"
+#include "sdk_common.h"
+
+
+#define _static
+
+#define DOUBLE_BUFFERED /**< A flag for enabling double buffering. */
+
+#define SPI_PIN_DISCONNECTED 0xFFFFFFFF /**< A value used to the PIN deinitialization. */
+#define SPI_DEFAULT_TX_BYTE 0x00 /**< Default byte (used to clock transmission
+ from slave to the master) */
+
+typedef struct
+{
+ NRF_SPI_Type * p_nrf_spi; /**< A pointer to the NRF SPI master */
+ IRQn_Type irq_type; /**< A type of NVIC IRQn */
+
+ uint8_t * p_tx_buffer; /**< A pointer to TX buffer. */
+ uint16_t tx_length; /**< A length of TX buffer. */
+ uint16_t tx_index; /**< A index of the current element in the TX buffer. */
+
+ uint8_t * p_rx_buffer; /**< A pointer to RX buffer. */
+ uint16_t rx_length; /**< A length RX buffer. */
+ uint16_t rx_index; /**< A index of the current element in the RX buffer. */
+
+ uint16_t max_length; /**< Max length (Max of the TX and RX length). */
+ uint16_t bytes_count;
+ uint8_t pin_slave_select; /**< A pin for Slave Select. */
+
+ spi_master_event_handler_t callback_event_handler; /**< A handler for event callback function. */
+ spi_master_state_t state; /**< A state of an instance of SPI master. */
+ bool start_flag;
+ bool abort_flag;
+
+} spi_master_instance_t;
+
+#ifdef _SPI_5W_
+typedef enum
+{
+ HOOK_STATE_DISABLED,
+ HOOK_STATE_IDLE,
+ HOOK_STATE_GUARDED,
+ HOOK_STATE_ABORTED,
+ HOOK_STATE_RESTARTED,
+ HOOK_STATE_PASSING
+} spi_hook_state_t;
+
+
+_static spi_master_event_handler_t m_ser_phy_event_handler;
+_static spi_master_hw_instance_t m_spi_master_hw_instance;
+_static spi_hook_state_t m_hook_state = HOOK_STATE_DISABLED;
+#endif
+
+#ifdef SER_PHY_DEBUG_APP_ENABLE
+_static spi_master_raw_callback_t m_debug_callback;
+#endif
+
+_static spi_master_instance_t m_spi_master_instances[SPI_MASTER_HW_ENABLED_COUNT];
+
+static __INLINE spi_master_instance_t * spi_master_get_instance(
+ const spi_master_hw_instance_t spi_master_hw_instance);
+static __INLINE void spi_master_send_recv_irq(spi_master_instance_t * const p_spi_instance);
+static __INLINE void spi_master_signal_evt(spi_master_instance_t * const p_spi_instance,
+ spi_master_evt_type_t event_type,
+ const uint16_t data);
+
+#ifdef SPI_MASTER_0_ENABLE
+/**
+ * @brief SPI0 interrupt handler.
+ */
+void SPI0_TWI0_IRQHandler(void)
+{
+ if (NRF_SPI0->EVENTS_READY != 0)
+ {
+ NRF_SPI0->EVENTS_READY = 0;
+
+ spi_master_instance_t * p_spi_instance = spi_master_get_instance(SPI_MASTER_0);
+
+ spi_master_send_recv_irq(p_spi_instance);
+ }
+}
+#endif //SPI_MASTER_0_ENABLE
+
+#ifdef SPI_MASTER_1_ENABLE
+/**
+ * @brief SPI0 interrupt handler.
+ */
+void SPI1_TWI1_IRQHandler(void)
+{
+ if (NRF_SPI1->EVENTS_READY != 0)
+ {
+ NRF_SPI1->EVENTS_READY = 0;
+
+ spi_master_instance_t * p_spi_instance = spi_master_get_instance(SPI_MASTER_1);
+
+ spi_master_send_recv_irq(p_spi_instance);
+ }
+}
+#endif //SPI_MASTER_1_ENABLE
+
+#if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
+
+/**@brief Function for getting an instance of SPI master. */
+static __INLINE spi_master_instance_t * spi_master_get_instance(
+ const spi_master_hw_instance_t spi_master_hw_instance)
+{
+ return &(m_spi_master_instances[(uint8_t)spi_master_hw_instance]);
+}
+
+/** @brief Function for initializing instance of SPI master by default values. */
+static __INLINE void spi_master_init_hw_instance(NRF_SPI_Type * p_nrf_spi,
+ IRQn_Type irq_type,
+ spi_master_instance_t * p_spi_instance)
+{
+ APP_ERROR_CHECK_BOOL(p_spi_instance != NULL);
+
+ p_spi_instance->p_nrf_spi = p_nrf_spi;
+ p_spi_instance->irq_type = irq_type;
+
+ p_spi_instance->p_tx_buffer = NULL;
+ p_spi_instance->tx_length = 0;
+ p_spi_instance->tx_index = 0;
+
+ p_spi_instance->p_rx_buffer = NULL;
+ p_spi_instance->rx_length = 0;
+ p_spi_instance->rx_index = 0;
+
+ p_spi_instance->bytes_count = 0;
+ p_spi_instance->max_length = 0;
+ p_spi_instance->pin_slave_select = 0;
+
+ p_spi_instance->callback_event_handler = NULL;
+
+ p_spi_instance->state = SPI_MASTER_STATE_DISABLED;
+ p_spi_instance->abort_flag = false;
+ p_spi_instance->start_flag = false;
+}
+
+/**@brief Function for initializing TX or RX buffer. */
+static __INLINE void spi_master_buffer_init(uint8_t * const p_buf,
+ const uint16_t buf_len,
+ uint8_t * * pp_buf,
+ uint16_t * const p_buf_len,
+ uint16_t * const p_index)
+{
+ APP_ERROR_CHECK_BOOL(pp_buf != NULL);
+ APP_ERROR_CHECK_BOOL(p_buf_len != NULL);
+ APP_ERROR_CHECK_BOOL(p_index != NULL);
+
+ *pp_buf = p_buf;
+ *p_buf_len = (p_buf != NULL) ? buf_len : 0;
+ *p_index = 0;
+}
+
+/**@brief Function for releasing TX or RX buffer. */
+static __INLINE void spi_master_buffer_release(uint8_t * * const pp_buf, uint16_t * const p_buf_len)
+{
+ APP_ERROR_CHECK_BOOL(pp_buf != NULL);
+ APP_ERROR_CHECK_BOOL(p_buf_len != NULL);
+
+ *pp_buf = NULL;
+ *p_buf_len = 0;
+}
+
+/**@brief Function for sending events by callback. */
+static __INLINE void spi_master_signal_evt(spi_master_instance_t * const p_spi_instance,
+ spi_master_evt_type_t event_type,
+ const uint16_t data)
+{
+ APP_ERROR_CHECK_BOOL(p_spi_instance != NULL);
+
+ if (p_spi_instance->callback_event_handler != NULL)
+ {
+ spi_master_evt_t event = {SPI_MASTER_EVT_TYPE_MAX, 0};
+ event.type = event_type;
+ event.data = data;
+ p_spi_instance->callback_event_handler(event);
+ }
+}
+
+/**@brief Function insert to a TX buffer another byte or two bytes (depends on flag @ref DOUBLE_BUFFERED). */
+static __INLINE void spi_master_send_initial_bytes(spi_master_instance_t * const p_spi_instance)
+{
+ APP_ERROR_CHECK_BOOL(p_spi_instance != NULL);
+
+ p_spi_instance->p_nrf_spi->TXD = ((p_spi_instance->p_tx_buffer != NULL) &&
+ (p_spi_instance->tx_index < p_spi_instance->tx_length)) ?
+ p_spi_instance->p_tx_buffer[p_spi_instance->tx_index] :
+ SPI_DEFAULT_TX_BYTE;
+ (p_spi_instance->tx_index)++;
+
+ #ifdef DOUBLE_BUFFERED
+
+ if (p_spi_instance->tx_index < p_spi_instance->max_length)
+ {
+ p_spi_instance->p_nrf_spi->TXD = ((p_spi_instance->p_tx_buffer != NULL) &&
+ (p_spi_instance->tx_index < p_spi_instance->tx_length)) ?
+ p_spi_instance->p_tx_buffer[p_spi_instance->tx_index] :
+ SPI_DEFAULT_TX_BYTE;
+ (p_spi_instance->tx_index)++;
+ }
+ #endif
+}
+
+/**@brief Function for receiving and sending data from IRQ. (The same for both IRQs). */
+static __INLINE void spi_master_send_recv_irq(spi_master_instance_t * const p_spi_instance)
+{
+
+ uint8_t rx_byte;
+
+ APP_ERROR_CHECK_BOOL(p_spi_instance != NULL);
+ APP_ERROR_CHECK_BOOL(p_spi_instance->state == SPI_MASTER_STATE_BUSY);
+
+ p_spi_instance->bytes_count++;
+ rx_byte = p_spi_instance->p_nrf_spi->RXD;
+
+ if (p_spi_instance->start_flag)
+ {
+ p_spi_instance->start_flag = false;
+ spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_FIRST_BYTE_RECEIVED, (uint16_t)rx_byte);
+ }
+ else if (p_spi_instance->abort_flag ) //this is tricky, but callback for SPI_MASTER_EVT_FIRST_BYTE_RECEIVED will set this flag for a first byte, which is bad because there is still byte in a buffer
+ { //and for a single byte transaction you will get XFERDONE event to restart
+ p_spi_instance->abort_flag = false;
+ p_spi_instance->state = SPI_MASTER_STATE_ABORTED;
+ nrf_gpio_pin_set(p_spi_instance->pin_slave_select);
+ spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_TRANSFER_ABORTED, 0);
+ return;
+ }
+
+ if ((p_spi_instance->p_rx_buffer != NULL) &&
+ (p_spi_instance->rx_index < p_spi_instance->rx_length))
+ {
+ p_spi_instance->p_rx_buffer[p_spi_instance->rx_index++] = rx_byte;
+ }
+
+ if ((p_spi_instance->tx_index < p_spi_instance->max_length) && (!(p_spi_instance->abort_flag))) //do not TX if you know that there is an abort to be done - this should work for a DOUBLE BUFFERING ???
+ {
+ p_spi_instance->p_nrf_spi->TXD = ((p_spi_instance->p_tx_buffer != NULL) &&
+ (p_spi_instance->tx_index < p_spi_instance->tx_length)) ?
+ p_spi_instance->p_tx_buffer[p_spi_instance->tx_index] :
+ SPI_DEFAULT_TX_BYTE;
+ (p_spi_instance->tx_index)++;
+ }
+
+ if (p_spi_instance->bytes_count >= p_spi_instance->max_length)
+ {
+ APP_ERROR_CHECK_BOOL(p_spi_instance->bytes_count == p_spi_instance->max_length);
+ nrf_gpio_pin_set(p_spi_instance->pin_slave_select);
+ p_spi_instance->state = SPI_MASTER_STATE_IDLE;
+ spi_master_signal_evt(p_spi_instance,
+ SPI_MASTER_EVT_TRANSFER_COMPLETED,
+ p_spi_instance->tx_index);
+ }
+ return;
+}
+#endif //defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
+
+
+/**
+ * @brief Function for opening and initializing a SPI master driver. */
+uint32_t spi_master_open(const spi_master_hw_instance_t spi_master_hw_instance,
+ spi_master_config_t const * const p_spi_master_config)
+{
+ #if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
+
+
+ VERIFY_PARAM_NOT_NULL(p_spi_master_config);
+
+ spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
+
+ switch (spi_master_hw_instance)
+ {
+ #ifdef SPI_MASTER_0_ENABLE
+ case SPI_MASTER_0:
+ spi_master_init_hw_instance(NRF_SPI0, SPI0_TWI0_IRQn, p_spi_instance);
+ break;
+ #endif //SPI_MASTER_0_ENABLE
+
+ #ifdef SPI_MASTER_1_ENABLE
+ case SPI_MASTER_1:
+ spi_master_init_hw_instance(NRF_SPI1, SPI1_TWI1_IRQn, p_spi_instance);
+ break;
+ #endif //SPI_MASTER_1_ENABLE
+
+ default:
+ break;
+ }
+
+ //A Slave select must be set as high before setting it as output,
+ //because during connect it to the pin it causes glitches.
+ nrf_gpio_pin_set(p_spi_master_config->SPI_Pin_SS);
+ nrf_gpio_cfg_output(p_spi_master_config->SPI_Pin_SS);
+ nrf_gpio_pin_set(p_spi_master_config->SPI_Pin_SS);
+
+ //Configure GPIO
+ nrf_gpio_cfg_output(p_spi_master_config->SPI_Pin_SCK);
+ nrf_gpio_cfg_output(p_spi_master_config->SPI_Pin_MOSI);
+ nrf_gpio_cfg_input(p_spi_master_config->SPI_Pin_MISO, NRF_GPIO_PIN_NOPULL);
+ p_spi_instance->pin_slave_select = p_spi_master_config->SPI_Pin_SS;
+
+ /* Configure SPI hardware */
+ p_spi_instance->p_nrf_spi->PSELSCK = p_spi_master_config->SPI_Pin_SCK;
+ p_spi_instance->p_nrf_spi->PSELMOSI = p_spi_master_config->SPI_Pin_MOSI;
+ p_spi_instance->p_nrf_spi->PSELMISO = p_spi_master_config->SPI_Pin_MISO;
+
+ p_spi_instance->p_nrf_spi->FREQUENCY = p_spi_master_config->SPI_Freq;
+
+ p_spi_instance->p_nrf_spi->CONFIG =
+ (uint32_t)(p_spi_master_config->SPI_CPHA << SPI_CONFIG_CPHA_Pos) |
+ (p_spi_master_config->SPI_CPOL << SPI_CONFIG_CPOL_Pos) |
+ (p_spi_master_config->SPI_ORDER << SPI_CONFIG_ORDER_Pos);
+
+
+ /* Clear waiting interrupts and events */
+ p_spi_instance->p_nrf_spi->EVENTS_READY = 0;
+
+ NVIC_ClearPendingIRQ(p_spi_instance->irq_type);
+ NVIC_SetPriority(p_spi_instance->irq_type, APP_IRQ_PRIORITY_MID);
+
+ /* Clear event handler */
+ p_spi_instance->callback_event_handler = NULL;
+
+ /* Enable interrupt */
+ p_spi_instance->p_nrf_spi->INTENSET = (SPI_INTENSET_READY_Set << SPI_INTENCLR_READY_Pos);
+ NVIC_EnableIRQ(p_spi_instance->irq_type);
+
+ /* Enable SPI hardware */
+ p_spi_instance->p_nrf_spi->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
+
+ /* Change state to IDLE */
+ p_spi_instance->state = SPI_MASTER_STATE_IDLE;
+
+ return NRF_SUCCESS;
+ #else
+ return NRF_ERROR_NOT_SUPPORTED;
+ #endif
+}
+
+/**
+ * @brief Function for closing a SPI master driver.
+ */
+void spi_master_close(const spi_master_hw_instance_t spi_master_hw_instance)
+{
+ #if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
+ spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
+
+ /* Disable interrupt */
+ NVIC_ClearPendingIRQ(p_spi_instance->irq_type);
+ NVIC_DisableIRQ(p_spi_instance->irq_type);
+
+ p_spi_instance->p_nrf_spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
+
+ /* Set Slave Select pin as input with pull-up. */
+ nrf_gpio_pin_set(p_spi_instance->pin_slave_select);
+ nrf_gpio_cfg_input(p_spi_instance->pin_slave_select, NRF_GPIO_PIN_PULLUP);
+ p_spi_instance->pin_slave_select = (uint8_t)0xFF;
+
+ /* Disconnect pins from SPI hardware */
+ p_spi_instance->p_nrf_spi->PSELSCK = (uint32_t)SPI_PIN_DISCONNECTED;
+ p_spi_instance->p_nrf_spi->PSELMOSI = (uint32_t)SPI_PIN_DISCONNECTED;
+ p_spi_instance->p_nrf_spi->PSELMISO = (uint32_t)SPI_PIN_DISCONNECTED;
+
+ /* Reset to default values */
+ spi_master_init_hw_instance(NULL, (IRQn_Type)0, p_spi_instance);
+ #else
+ return;
+ #endif
+}
+
+/**
+ * @brief Function for getting current state of the SPI master driver.
+ */
+__INLINE spi_master_state_t spi_master_get_state(
+ const spi_master_hw_instance_t spi_master_hw_instance)
+{
+ #if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
+ spi_master_instance_t * spi_instance = spi_master_get_instance(spi_master_hw_instance);
+ return spi_instance->state;
+ #else
+ return SPI_MASTER_STATE_DISABLED;
+ #endif
+}
+
+/**
+ * @brief Function for event handler registration.
+ */
+__INLINE void spi_master_evt_handler_reg(const spi_master_hw_instance_t spi_master_hw_instance,
+ spi_master_event_handler_t event_handler)
+{
+ #if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
+ spi_master_instance_t * spi_instance = spi_master_get_instance(spi_master_hw_instance);
+ spi_instance->callback_event_handler = event_handler;
+ #else
+ return;
+ #endif
+}
+
+/**
+ * @brief Function for transmitting data between SPI master and SPI slave.
+ */
+uint32_t spi_master_send_recv(const spi_master_hw_instance_t spi_master_hw_instance,
+ uint8_t * const p_tx_buf, const uint16_t tx_buf_len,
+ uint8_t * const p_rx_buf, const uint16_t rx_buf_len)
+{
+ #if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
+ spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
+
+ uint32_t err_code = NRF_SUCCESS;
+ uint16_t max_length = 0;
+
+ if (p_spi_instance->state == SPI_MASTER_STATE_IDLE)
+ {
+ NVIC_DisableIRQ(p_spi_instance->irq_type);
+
+ max_length = (rx_buf_len > tx_buf_len) ? rx_buf_len : tx_buf_len;
+
+ if (max_length > 0)
+ {
+ p_spi_instance->state = SPI_MASTER_STATE_BUSY;
+ p_spi_instance->start_flag = true; //abort_flag should set by abort and cleared only by restart
+ p_spi_instance->bytes_count = 0;
+ p_spi_instance->max_length = max_length;
+ spi_master_buffer_release(&(p_spi_instance->p_tx_buffer), &(p_spi_instance->tx_length));
+ spi_master_buffer_release(&(p_spi_instance->p_rx_buffer), &(p_spi_instance->rx_length));
+ /* Initialize buffers */
+ spi_master_buffer_init(p_tx_buf, tx_buf_len, &(p_spi_instance->p_tx_buffer),
+ &(p_spi_instance->tx_length), &(p_spi_instance->tx_index));
+ spi_master_buffer_init(p_rx_buf, rx_buf_len, &(p_spi_instance->p_rx_buffer),
+ &(p_spi_instance->rx_length), &(p_spi_instance->rx_index));
+ nrf_gpio_pin_clear(p_spi_instance->pin_slave_select);
+ spi_master_send_initial_bytes(p_spi_instance);
+ spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_TRANSFER_STARTED, max_length);
+ }
+ else
+ {
+ err_code = NRF_ERROR_INVALID_PARAM;
+ }
+
+ NVIC_EnableIRQ(p_spi_instance->irq_type);
+ }
+ else
+ {
+ err_code = NRF_ERROR_BUSY;
+ }
+
+ return err_code;
+ #else
+ return NRF_ERROR_NOT_SUPPORTED;
+ #endif
+}
+
+#ifdef _SPI_5W_
+
+/**
+ * @brief Function for aborting transfer
+ */
+uint32_t spi_master_abort(const spi_master_hw_instance_t spi_master_hw_instance)
+{
+ spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
+
+ NVIC_DisableIRQ(p_spi_instance->irq_type);
+
+ if (p_spi_instance->state == SPI_MASTER_STATE_BUSY)
+ {
+ //set_flag - but only when there are events pending
+ //ignore when in IDLE - must be able to restart a completed transfer
+ p_spi_instance->abort_flag = true;
+ }
+ NVIC_EnableIRQ(p_spi_instance->irq_type);
+ return NRF_SUCCESS;
+}
+
+/**
+ * @brief Function for restarting transfer
+ */
+uint32_t spi_master_restart(const spi_master_hw_instance_t spi_master_hw_instance)
+{
+ spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
+
+ NVIC_DisableIRQ(p_spi_instance->irq_type);
+ spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_TRANSFER_RESTARTED, 0);
+ p_spi_instance->state = SPI_MASTER_STATE_BUSY;
+ p_spi_instance->bytes_count = 0;
+ p_spi_instance->tx_index = 0;
+ p_spi_instance->rx_index = 0;
+ p_spi_instance->start_flag = true;
+ p_spi_instance->abort_flag = false; //you should force clearing abort flag - no other way for 1 byte transfer
+ nrf_gpio_pin_clear(p_spi_instance->pin_slave_select);
+ spi_master_send_initial_bytes(p_spi_instance);
+ NVIC_EnableIRQ(p_spi_instance->irq_type);
+
+ return NRF_SUCCESS;
+}
+
+static void spi_5W_master_event_handler(spi_master_evt_t evt)
+{
+
+ switch (m_hook_state)
+ {
+ case HOOK_STATE_IDLE:
+
+ if (evt.type == SPI_MASTER_EVT_TRANSFER_STARTED)
+ {
+ DEBUG_EVT_SPI_MASTER_RAW_XFER_GUARDED(0);
+ m_hook_state = HOOK_STATE_GUARDED;
+ m_ser_phy_event_handler(evt);
+ }
+ break;
+
+ case HOOK_STATE_GUARDED:
+
+ if (evt.type == SPI_MASTER_EVT_FIRST_BYTE_RECEIVED)
+ {
+ if (evt.data == 0)
+ {
+ DEBUG_EVT_SPI_MASTER_RAW_XFER_PASSED(0);
+ m_hook_state = HOOK_STATE_PASSING;
+ }
+ else
+ {
+ DEBUG_EVT_SPI_MASTER_RAW_XFER_ABORTED(0);
+ m_hook_state = HOOK_STATE_ABORTED;
+ (void)spi_master_abort(m_spi_master_hw_instance);
+ }
+ }
+ break;
+
+ case HOOK_STATE_ABORTED:
+
+ if ((evt.type == SPI_MASTER_EVT_TRANSFER_ABORTED) ||
+ (evt.type == SPI_MASTER_EVT_TRANSFER_COMPLETED))
+ {
+ DEBUG_EVT_SPI_MASTER_RAW_XFER_RESTARTED(0);
+ m_hook_state = HOOK_STATE_RESTARTED;
+ (void)spi_master_restart(m_spi_master_hw_instance);
+ }
+ break;
+
+ case HOOK_STATE_RESTARTED:
+
+ if (evt.type == SPI_MASTER_EVT_TRANSFER_RESTARTED)
+ {
+ DEBUG_EVT_SPI_MASTER_RAW_XFER_GUARDED(0);
+ m_hook_state = HOOK_STATE_GUARDED;
+ }
+ break;
+
+ case HOOK_STATE_PASSING:
+
+ if (evt.type == SPI_MASTER_EVT_TRANSFER_COMPLETED)
+ {
+ m_hook_state = HOOK_STATE_IDLE;
+ m_ser_phy_event_handler(evt); //this is the only way to get a signal from complete transaction
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void spi_5W_master_evt_handler_reg(const spi_master_hw_instance_t spi_master_hw_instance,
+ spi_master_event_handler_t event_handler)
+{
+ m_ser_phy_event_handler = event_handler;
+ m_spi_master_hw_instance = spi_master_hw_instance;
+ m_hook_state = HOOK_STATE_IDLE;
+ spi_master_evt_handler_reg(spi_master_hw_instance, spi_5W_master_event_handler);
+ return;
+}
+
+#endif
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/spi_master/spi_5W_master.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/spi_master/spi_5W_master.h
new file mode 100644
index 0000000..a0017c5
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/spi_master/spi_5W_master.h
@@ -0,0 +1,206 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef APP_SPI_MASTER_H
+#define APP_SPI_MASTER_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "boards.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _SPI_5W_
+
+/**@brief Struct containing configuration parameters of the SPI master. */
+typedef struct
+{
+ uint32_t SPI_Freq; /**< SPI frequency. */
+ uint32_t SPI_Pin_SCK; /**< SCK pin number. */
+ uint32_t SPI_Pin_MISO; /**< MISO pin number. */
+ uint32_t SPI_Pin_MOSI; /**< MOSI pin number .*/
+ uint32_t SPI_Pin_SS; /**< Slave select pin number. */
+ uint8_t SPI_ORDER; /**< Bytes order MSBFIRST or LSBFIRST. */
+ uint8_t SPI_CPOL; /**< Serial clock polarity ACTIVEHIGH or ACTIVELOW. */
+ uint8_t SPI_CPHA; /**< Serial clock phase LEADING or TRAILING. */
+ } spi_master_config_t;
+
+/**@brief SPI master driver events types. */
+typedef enum
+{
+ SPI_MASTER_EVT_TRANSFER_STARTED = 0, /**< An event indicating that transfer has been started */
+ SPI_MASTER_EVT_TRANSFER_COMPLETED, /**< An event indicating that transfer has been completed */
+ SPI_MASTER_EVT_TRANSFER_ABORTED, /**< An event indicating that transfer has been aborted */
+ SPI_MASTER_EVT_TRANSFER_RESTARTED, /**< An event indicating that transfer has been resumed */
+ SPI_MASTER_EVT_FIRST_BYTE_RECEIVED, /**< An event indicating end of one byte transfer */
+ SPI_MASTER_EVT_TYPE_MAX /**< Enumeration upper bound. */
+} spi_master_evt_type_t;
+
+/**@brief Struct containing parameters of the SPI MASTER event */
+ typedef struct
+ {
+ spi_master_evt_type_t type; /**< Type of an event */
+ uint16_t data; /**< event data - context dependent */
+ } spi_master_evt_t;
+
+ /**@brief SPI MASTER internal states types. */
+ typedef enum
+ {
+ SPI_MASTER_STATE_DISABLED, /**< A state indicating that SPI master is disabled. */
+ SPI_MASTER_STATE_BUSY, /**< A state indicating that SPI master is sending now. */
+ SPI_MASTER_STATE_ABORTED,
+ SPI_MASTER_STATE_IDLE /**< A state indicating that SPI master is idle now. */
+ } spi_master_state_t;
+
+ /**@brief Instances of SPI master module. */
+ typedef enum
+ {
+ #ifdef SPI_MASTER_0_ENABLE
+ SPI_MASTER_0, /**< A instance of SPI master 0. */
+ #endif
+
+ #ifdef SPI_MASTER_1_ENABLE
+ SPI_MASTER_1, /**< A instance of SPI master 1. */
+ #endif
+
+ SPI_MASTER_HW_ENABLED_COUNT /**< A number of enabled instances of SPI master. */
+ } spi_master_hw_instance_t;
+
+/**@brief Type of generic callback function handler to be used by all SPI MASTER driver events.
+ *
+ * @param[in] spi_master_evt SPI MASTER driver event.
+ */
+typedef void (*spi_master_event_handler_t) (spi_master_evt_t spi_master_evt);
+
+
+/**@brief Function for opening and initializing a SPI master driver.
+ *
+ * @note Function initializes SPI master hardware and internal module states, unregister events callback.
+ *
+ * @warning If the function has been already called, the function @ref spi_master_close has to be
+ * called before spi_master_open can be called again.
+ *
+ * @param[in] spi_master_hw_instance Instance of SPI master module.
+ * @param[in] p_spi_master_config Pointer to configuration structure which will be used
+ * to initialize SPI MASTER hardware.
+ *
+ * @retval NRF_SUCCESS Operation success.
+ * @retval NRF_ERROR_INVALID_STATE Operation failure. The function has been already called.
+ * To call it again the function @ref spi_master_close
+ * has to be called previously.
+ * @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
+ */
+uint32_t spi_master_open(const spi_master_hw_instance_t spi_master_hw_instance,
+ spi_master_config_t const * const p_spi_master_config);
+
+
+/**@brief Function for closing a SPI MASTER driver.
+ *
+ * @note Function disable hardware, reset internal module states and unregister events callback
+ * function.
+ *
+ * @param[in] spi_master_hw_instance A instance of SPI master.
+ */
+void spi_master_close(const spi_master_hw_instance_t spi_master_hw_instance);
+
+
+/**@brief Function for transferring data between SPI master and SPI slave
+ *
+ * @note Function registers buffers pointed by p_tx_buf and p_rx_buf parameters, after that starts transmission.
+ * Function generates an event of type @ref SPI_MASTER_EVT_TRANSFER_STARTED when transfer has been started
+ * and @ref SPI_MASTER_EVT_TRANSFER_COMPLETED when transfer has been completed.
+ *
+ * @param[in] spi_master_hw_instance Instance of SPI master module.
+ * @param[in] p_tx_buf Pointer to a transmit buffer.
+ * @param[in] tx_buf_len Number of octets to the transfer.
+ * @param[out] p_rx_buf Pointer to a receive buffer.
+ * @param[in] rx_buf_len Number of octets to be received.
+ *
+ * @retval NRF_SUCCESS Operation success. Packet was registered to the transmission
+ * and event will be send upon transmission completion.
+ * @retval NRF_ERROR_BUSY Operation failure. Transmitting of a data is in progress.
+ */
+ uint32_t spi_master_send_recv(const spi_master_hw_instance_t spi_master_hw_instance,
+ uint8_t * const p_tx_buf, const uint16_t tx_buf_len,
+ uint8_t * const p_rx_buf, const uint16_t rx_buf_len);
+
+
+/**@brief Function for registration event handler.
+*
+* @note Function registers a event handler to be used by SPI MASTER driver for sending events.
+* @ref SPI_MASTER_EVT_TRANSFER_STARTED and @ref SPI_MASTER_EVT_TRANSFER_COMPLETED.
+*
+* @param[in] spi_master_hw_instance Instance of SPI master module.
+* @param[in] event_handler Generic callback function handler to be used
+* by all SPI master driver events.
+*/
+void spi_master_evt_handler_reg(const spi_master_hw_instance_t spi_master_hw_instance,
+ spi_master_event_handler_t event_handler);
+
+
+/**@brief Function for getting current state of the SPI master driver.
+ *
+ * @note Function gets current state of the SPI master driver.
+ *
+ * @param[in] spi_master_hw_instance Instance of SPI master module.
+ *
+ * @retval SPI_MASTER_STATE_DISABLED SPI MASTER is disabled.
+ * @retval SPI_MASTER_STATE_BUSY SPI_MASTER is sending now.
+ * @retval SPI_MASTER_STATE_IDLE SPI_MASTER is idle now.
+ */
+spi_master_state_t spi_master_get_state(const spi_master_hw_instance_t spi_master_hw_instance);
+
+#ifdef _SPI_5W_
+
+uint32_t spi_master_abort(const spi_master_hw_instance_t spi_master_hw_instance);
+
+uint32_t spi_master_restart(const spi_master_hw_instance_t spi_master_hw_instance);
+
+void spi_5W_master_evt_handler_reg(const spi_master_hw_instance_t spi_master_hw_instance,
+ spi_master_event_handler_t event_handler);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/config/twi_master_config.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/config/twi_master_config.h
new file mode 100644
index 0000000..9c182e6
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/config/twi_master_config.h
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef TWI_MASTER_CONFIG
+#define TWI_MASTER_CONFIG
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER (24U)
+#define TWI_MASTER_CONFIG_DATA_PIN_NUMBER (25U)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_hw_master.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_hw_master.c
new file mode 100644
index 0000000..e3692a3
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_hw_master.c
@@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "twi_master.h"
+#include "twi_master_config.h"
+#include <stdbool.h>
+#include <stdint.h>
+#include "nrf.h"
+#include "nrf_delay.h"
+#include "nrf_gpio.h"
+
+/* Max cycles approximately to wait on RXDREADY and TXDREADY event,
+ * This is optimized way instead of using timers, this is not power aware. */
+#define MAX_TIMEOUT_LOOPS (20000UL) /**< MAX while loops to wait for RXD/TXD event */
+
+static bool twi_master_write(uint8_t * data, uint8_t data_length, bool issue_stop_condition)
+{
+ uint32_t timeout = MAX_TIMEOUT_LOOPS; /* max loops to wait for EVENTS_TXDSENT event*/
+
+ if (data_length == 0)
+ {
+ /* Return false for requesting data of size 0 */
+ return false;
+ }
+
+ NRF_TWI1->TXD = *data++;
+ NRF_TWI1->TASKS_STARTTX = 1;
+
+ /** @snippet [TWI HW master write] */
+ while (true)
+ {
+ while (NRF_TWI1->EVENTS_TXDSENT == 0 && NRF_TWI1->EVENTS_ERROR == 0 && (--timeout))
+ {
+ // Do nothing.
+ }
+
+ if (timeout == 0 || NRF_TWI1->EVENTS_ERROR != 0)
+ {
+ // Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at
+ // Product Anomaly Notification document found at
+ // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
+ NRF_TWI1->EVENTS_ERROR = 0;
+ NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
+ NRF_TWI1->POWER = 0;
+ nrf_delay_us(5);
+ NRF_TWI1->POWER = 1;
+ NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
+
+ (void)twi_master_init();
+
+ return false;
+ }
+ NRF_TWI1->EVENTS_TXDSENT = 0;
+ if (--data_length == 0)
+ {
+ break;
+ }
+
+ NRF_TWI1->TXD = *data++;
+ }
+ /** @snippet [TWI HW master write] */
+
+ if (issue_stop_condition)
+ {
+ NRF_TWI1->EVENTS_STOPPED = 0;
+ NRF_TWI1->TASKS_STOP = 1;
+ /* Wait until stop sequence is sent */
+ while (NRF_TWI1->EVENTS_STOPPED == 0)
+ {
+ // Do nothing.
+ }
+ }
+ return true;
+}
+
+
+/** @brief Function for read by twi_master.
+ */
+static bool twi_master_read(uint8_t * data, uint8_t data_length, bool issue_stop_condition)
+{
+ uint32_t timeout = MAX_TIMEOUT_LOOPS; /* max loops to wait for RXDREADY event*/
+
+ if (data_length == 0)
+ {
+ /* Return false for requesting data of size 0 */
+ return false;
+ }
+ else if (data_length == 1)
+ {
+ NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
+ }
+ else
+ {
+ NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
+ }
+
+ NRF_PPI->CHENSET = PPI_CHENSET_CH0_Msk;
+ NRF_TWI1->EVENTS_RXDREADY = 0;
+ NRF_TWI1->TASKS_STARTRX = 1;
+
+ /** @snippet [TWI HW master read] */
+ while (true)
+ {
+ while (NRF_TWI1->EVENTS_RXDREADY == 0 && NRF_TWI1->EVENTS_ERROR == 0 && (--timeout))
+ {
+ // Do nothing.
+ }
+ NRF_TWI1->EVENTS_RXDREADY = 0;
+
+ if (timeout == 0 || NRF_TWI1->EVENTS_ERROR != 0)
+ {
+ // Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at
+ // Product Anomaly Notification document found at
+ // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
+ NRF_TWI1->EVENTS_ERROR = 0;
+ NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
+ NRF_TWI1->POWER = 0;
+ nrf_delay_us(5);
+ NRF_TWI1->POWER = 1;
+ NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
+
+ (void)twi_master_init();
+
+ return false;
+ }
+
+ *data++ = NRF_TWI1->RXD;
+
+ /* Configure PPI to stop TWI master before we get last BB event */
+ if (--data_length == 1)
+ {
+ NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
+ }
+
+ if (data_length == 0)
+ {
+ break;
+ }
+
+ // Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at
+ // Product Anomaly Notification document found at
+ // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
+ nrf_delay_us(20);
+ NRF_TWI1->TASKS_RESUME = 1;
+ }
+ /** @snippet [TWI HW master read] */
+
+ /* Wait until stop sequence is sent */
+ while (NRF_TWI1->EVENTS_STOPPED == 0)
+ {
+ // Do nothing.
+ }
+ NRF_TWI1->EVENTS_STOPPED = 0;
+
+ NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;
+ return true;
+}
+
+
+/**
+ * @brief Function for detecting stuck slaves (SDA = 0 and SCL = 1) and tries to clear the bus.
+ *
+ * @return
+ * @retval false Bus is stuck.
+ * @retval true Bus is clear.
+ */
+static bool twi_master_clear_bus(void)
+{
+ uint32_t twi_state;
+ bool bus_clear;
+ uint32_t clk_pin_config;
+ uint32_t data_pin_config;
+
+ // Save and disable TWI hardware so software can take control over the pins.
+ twi_state = NRF_TWI1->ENABLE;
+ NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
+
+ clk_pin_config = \
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER];
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = \
+ (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
+ | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
+ | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
+ | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
+
+ data_pin_config = \
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER];
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = \
+ (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
+ | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
+ | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
+ | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
+
+ TWI_SDA_HIGH();
+ TWI_SCL_HIGH();
+ TWI_DELAY();
+
+ if ((TWI_SDA_READ() == 1) && (TWI_SCL_READ() == 1))
+ {
+ bus_clear = true;
+ }
+ else
+ {
+ uint_fast8_t i;
+ bus_clear = false;
+
+ // Clock max 18 pulses worst case scenario(9 for master to send the rest of command and 9
+ // for slave to respond) to SCL line and wait for SDA come high.
+ for (i=18; i--;)
+ {
+ TWI_SCL_LOW();
+ TWI_DELAY();
+ TWI_SCL_HIGH();
+ TWI_DELAY();
+
+ if (TWI_SDA_READ() == 1)
+ {
+ bus_clear = true;
+ break;
+ }
+ }
+ }
+
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = clk_pin_config;
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = data_pin_config;
+
+ NRF_TWI1->ENABLE = twi_state;
+
+ return bus_clear;
+}
+
+
+/** @brief Function for initializing the twi_master.
+ */
+bool twi_master_init(void)
+{
+ /* To secure correct signal levels on the pins used by the TWI
+ master when the system is in OFF mode, and when the TWI master is
+ disabled, these pins must be configured in the GPIO peripheral.
+ */
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = \
+ (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
+ | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
+ | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
+ | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
+ | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = \
+ (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
+ | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
+ | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
+ | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
+ | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
+
+ NRF_TWI1->EVENTS_RXDREADY = 0;
+ NRF_TWI1->EVENTS_TXDSENT = 0;
+ NRF_TWI1->PSELSCL = TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER;
+ NRF_TWI1->PSELSDA = TWI_MASTER_CONFIG_DATA_PIN_NUMBER;
+ NRF_TWI1->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K100 << TWI_FREQUENCY_FREQUENCY_Pos;
+ NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TWI1->EVENTS_BB;
+ NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
+ NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;
+ NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
+
+ return twi_master_clear_bus();
+}
+
+
+/** @brief Function for transfer by twi_master.
+ */
+bool twi_master_transfer(uint8_t address,
+ uint8_t * data,
+ uint8_t data_length,
+ bool issue_stop_condition)
+{
+ bool transfer_succeeded = false;
+ if (data_length > 0 && twi_master_clear_bus())
+ {
+ NRF_TWI1->ADDRESS = (address >> 1);
+
+ if ((address & TWI_READ_BIT))
+ {
+ transfer_succeeded = twi_master_read(data, data_length, issue_stop_condition);
+ }
+ else
+ {
+ transfer_succeeded = twi_master_write(data, data_length, issue_stop_condition);
+ }
+ }
+ return transfer_succeeded;
+}
+
+/*lint --flb "Leave library region" */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_master.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_master.h
new file mode 100644
index 0000000..3cd975e
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_master.h
@@ -0,0 +1,137 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef TWI_MASTER_H
+#define TWI_MASTER_H
+
+/*lint ++flb "Enter library region" */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @file
+* @brief Software controlled TWI Master driver.
+*
+*
+* @defgroup lib_driver_twi_master Software controlled TWI Master driver
+* @{
+* @ingroup nrf_twi
+* @brief Software controlled TWI Master driver (deprecated).
+*
+* @warning This module is deprecated.
+*
+* Supported features:
+* - Repeated start
+* - No multi-master
+* - Only 7-bit addressing
+* - Supports clock stretching (with optional SMBus style slave timeout)
+* - Tries to handle slaves stuck in the middle of transfer
+*/
+
+#define TWI_READ_BIT (0x01) //!< If this bit is set in the address field, transfer direction is from slave to master.
+
+#define TWI_ISSUE_STOP ((bool)true) //!< Parameter for @ref twi_master_transfer
+#define TWI_DONT_ISSUE_STOP ((bool)false) //!< Parameter for @ref twi_master_transfer
+
+/* These macros are needed to see if the slave is stuck and we as master send dummy clock cycles to end its wait */
+/*lint -e717 -save "Suppress do {} while (0) for these macros" */
+/*lint ++flb "Enter library region" */
+#define TWI_SCL_HIGH() do { NRF_GPIO->OUTSET = (1UL << TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line high */
+#define TWI_SCL_LOW() do { NRF_GPIO->OUTCLR = (1UL << TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line low */
+#define TWI_SDA_HIGH() do { NRF_GPIO->OUTSET = (1UL << TWI_MASTER_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line high */
+#define TWI_SDA_LOW() do { NRF_GPIO->OUTCLR = (1UL << TWI_MASTER_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line low */
+#define TWI_SDA_INPUT() do { NRF_GPIO->DIRCLR = (1UL << TWI_MASTER_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Configures SDA pin as input */
+#define TWI_SDA_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << TWI_MASTER_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Configures SDA pin as output */
+#define TWI_SCL_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Configures SCL pin as output */
+/*lint -restore */
+
+#define TWI_SDA_READ() ((NRF_GPIO->IN >> TWI_MASTER_CONFIG_DATA_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SDA */
+#define TWI_SCL_READ() ((NRF_GPIO->IN >> TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SCL */
+
+#define TWI_DELAY() nrf_delay_us(4) /*!< Time to wait when pin states are changed. For fast-mode the delay can be zero and for standard-mode 4 us delay is sufficient. */
+
+
+/**
+ * @brief Function for initializing TWI bus IO pins and checks if the bus is operational.
+ *
+ * Both pins are configured as Standard-0, No-drive-1 (open drain).
+ *
+ * @return
+ * @retval true TWI bus is clear for transfers.
+ * @retval false TWI bus is stuck.
+ */
+bool twi_master_init(void);
+
+/**
+ * @brief Function for transferring data over TWI bus.
+ *
+ * If TWI master detects even one NACK from the slave or timeout occurs, STOP condition is issued
+ * and the function returns false.
+ * Bit 0 (@ref TWI_READ_BIT) in the address parameter controls transfer direction;
+ * - If 1, master reads data_length number of bytes from the slave
+ * - If 0, master writes data_length number of bytes to the slave.
+ *
+ * @note Make sure at least data_length number of bytes is allocated in data if TWI_READ_BIT is set.
+ * @note @ref TWI_ISSUE_STOP
+ *
+ * @param address Data transfer direction (LSB) / Slave address (7 MSBs).
+ * @param data Pointer to data.
+ * @param data_length Number of bytes to transfer.
+ * @param issue_stop_condition If @ref TWI_ISSUE_STOP, STOP condition is issued before exiting function. If @ref TWI_DONT_ISSUE_STOP, STOP condition is not issued before exiting function. If transfer failed for any reason, STOP condition will be issued in any case.
+ * @return
+ * @retval true Data transfer succeeded without errors.
+ * @retval false Data transfer failed.
+ */
+bool twi_master_transfer(uint8_t address, uint8_t *data, uint8_t data_length, bool issue_stop_condition);
+
+/**
+ *@}
+ **/
+
+/*lint --flb "Leave library region" */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //TWI_MASTER_H
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_sw_master.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_sw_master.c
new file mode 100644
index 0000000..115e997
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/twi_master/deprecated/twi_sw_master.c
@@ -0,0 +1,519 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <stdbool.h>
+#include <stdint.h>
+#include "twi_master.h"
+#include "nrf_delay.h"
+
+#include "twi_master_config.h"
+
+/*lint -e415 -e845 -save "Out of bounds access" */
+#define TWI_SDA_STANDARD0_NODRIVE1() do { \
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
+ |(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
+ |(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
+ |(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
+ |(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
+} while (0) /*!< Configures SDA pin to Standard-0, No-drive 1 */
+
+
+#define TWI_SCL_STANDARD0_NODRIVE1() do { \
+ NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
+ |(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
+ |(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
+ |(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
+ |(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
+} while (0) /*!< Configures SCL pin to Standard-0, No-drive 1 */
+
+
+/*lint -restore */
+
+#ifndef TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE
+#define TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE (0UL) //!< Unit is number of empty loops. Timeout for SMBus devices is 35 ms. Set to zero to disable slave timeout altogether.
+#endif
+
+static bool twi_master_clear_bus(void);
+static bool twi_master_issue_startcondition(void);
+static bool twi_master_issue_stopcondition(void);
+static bool twi_master_clock_byte(uint_fast8_t databyte);
+static bool twi_master_clock_byte_in(uint8_t * databyte, bool ack);
+static bool twi_master_wait_while_scl_low(void);
+
+bool twi_master_init(void)
+{
+ // Configure both pins to output Standard 0, No-drive (open-drain) 1
+ TWI_SDA_STANDARD0_NODRIVE1(); /*lint !e416 "Creation of out of bounds pointer" */
+ TWI_SCL_STANDARD0_NODRIVE1(); /*lint !e416 "Creation of out of bounds pointer" */
+
+ // Configure SCL as output
+ TWI_SCL_HIGH();
+ TWI_SCL_OUTPUT();
+
+ // Configure SDA as output
+ TWI_SDA_HIGH();
+ TWI_SDA_OUTPUT();
+
+ return twi_master_clear_bus();
+}
+
+bool twi_master_transfer(uint8_t address, uint8_t * data, uint8_t data_length, bool issue_stop_condition)
+{
+ bool transfer_succeeded = true;
+
+ transfer_succeeded &= twi_master_issue_startcondition();
+ transfer_succeeded &= twi_master_clock_byte(address);
+
+ if (address & TWI_READ_BIT)
+ {
+ /* Transfer direction is from Slave to Master */
+ while (data_length-- && transfer_succeeded)
+ {
+ // To indicate to slave that we've finished transferring last data byte
+ // we need to NACK the last transfer.
+ if (data_length == 0)
+ {
+ transfer_succeeded &= twi_master_clock_byte_in(data, (bool)false);
+ }
+ else
+ {
+ transfer_succeeded &= twi_master_clock_byte_in(data, (bool)true);
+ }
+ data++;
+ }
+ }
+ else
+ {
+ /* Transfer direction is from Master to Slave */
+ while (data_length-- && transfer_succeeded)
+ {
+ transfer_succeeded &= twi_master_clock_byte(*data);
+ data++;
+ }
+ }
+
+ if (issue_stop_condition || !transfer_succeeded)
+ {
+ transfer_succeeded &= twi_master_issue_stopcondition();
+ }
+
+ return transfer_succeeded;
+}
+
+/**
+ * @brief Function for detecting stuck slaves and tries to clear the bus.
+ *
+ * @return
+ * @retval false Bus is stuck.
+ * @retval true Bus is clear.
+ */
+static bool twi_master_clear_bus(void)
+{
+ bool bus_clear;
+
+ TWI_SDA_HIGH();
+ TWI_SCL_HIGH();
+ TWI_DELAY();
+
+
+ if (TWI_SDA_READ() == 1 && TWI_SCL_READ() == 1)
+ {
+ bus_clear = true;
+ }
+ else if (TWI_SCL_READ() == 1)
+ {
+ bus_clear = false;
+ // Clock max 18 pulses worst case scenario(9 for master to send the rest of command and 9 for slave to respond) to SCL line and wait for SDA come high
+ for (uint_fast8_t i = 18; i--;)
+ {
+ TWI_SCL_LOW();
+ TWI_DELAY();
+ TWI_SCL_HIGH();
+ TWI_DELAY();
+
+ if (TWI_SDA_READ() == 1)
+ {
+ bus_clear = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ bus_clear = false;
+ }
+
+ return bus_clear;
+}
+
+/**
+ * @brief Function for issuing TWI START condition to the bus.
+ *
+ * START condition is signaled by pulling SDA low while SCL is high. After this function SCL and SDA will be low.
+ *
+ * @return
+ * @retval false Timeout detected
+ * @retval true Clocking succeeded
+ */
+static bool twi_master_issue_startcondition(void)
+{
+#if 0
+ if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 1)
+ {
+ // Pull SDA low
+ TWI_SDA_LOW();
+ }
+ else if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 0)
+ {
+ // Issue Stop by pulling SDA high
+ TWI_SDA_HIGH();
+ TWI_DELAY();
+
+ // Then Start by pulling SDA low
+ TWI_SDA_LOW();
+ }
+ else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 0)
+ {
+ // First pull SDA high
+ TWI_SDA_HIGH();
+
+ // Then SCL high
+ if (!twi_master_wait_while_scl_low())
+ {
+ return false;
+ }
+
+ // Then SDA low
+ TWI_SDA_LOW();
+ }
+ else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 1)
+ {
+ // SCL high
+ if (!twi_master_wait_while_scl_low())
+ {
+ return false;
+ }
+
+ // Then SDA low
+ TWI_SDA_LOW();
+ }
+
+ TWI_DELAY();
+ TWI_SCL_LOW();
+#endif
+
+ // Make sure both SDA and SCL are high before pulling SDA low.
+ TWI_SDA_HIGH();
+ TWI_DELAY();
+ if (!twi_master_wait_while_scl_low())
+ {
+ return false;
+ }
+
+ TWI_SDA_LOW();
+ TWI_DELAY();
+
+ // Other module function expect SCL to be low
+ TWI_SCL_LOW();
+ TWI_DELAY();
+
+ return true;
+}
+
+/**
+ * @brief Function for issuing TWI STOP condition to the bus.
+ *
+ * STOP condition is signaled by pulling SDA high while SCL is high. After this function SDA and SCL will be high.
+ *
+ * @return
+ * @retval false Timeout detected
+ * @retval true Clocking succeeded
+ */
+static bool twi_master_issue_stopcondition(void)
+{
+#if 0
+ if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 1)
+ {
+ // Issue start, then issue stop
+
+ // Pull SDA low to issue START
+ TWI_SDA_LOW();
+ TWI_DELAY();
+
+ // Pull SDA high while SCL is high to issue STOP
+ TWI_SDA_HIGH();
+ }
+ else if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 0)
+ {
+ // Pull SDA high while SCL is high to issue STOP
+ TWI_SDA_HIGH();
+ }
+ else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 0)
+ {
+ if (!twi_master_wait_while_scl_low())
+ {
+ return false;
+ }
+
+ // Pull SDA high while SCL is high to issue STOP
+ TWI_SDA_HIGH();
+ }
+ else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 1)
+ {
+ TWI_SDA_LOW();
+ TWI_DELAY();
+
+ // SCL high
+ if (!twi_master_wait_while_scl_low())
+ {
+ return false;
+ }
+
+ // Pull SDA high while SCL is high to issue STOP
+ TWI_SDA_HIGH();
+ }
+
+ TWI_DELAY();
+#endif
+
+ TWI_SDA_LOW();
+ TWI_DELAY();
+ if (!twi_master_wait_while_scl_low())
+ {
+ return false;
+ }
+
+ TWI_SDA_HIGH();
+ TWI_DELAY();
+
+ return true;
+}
+
+/**
+ * @brief Function for clocking one data byte out and reads slave acknowledgment.
+ *
+ * Can handle clock stretching.
+ * After calling this function SCL is low and SDA low/high depending on the
+ * value of LSB of the data byte.
+ * SCL is expected to be output and low when entering this function.
+ *
+ * @param databyte Data byte to clock out.
+ * @return
+ * @retval true Slave acknowledged byte.
+ * @retval false Timeout or slave didn't acknowledge byte.
+ */
+static bool twi_master_clock_byte(uint_fast8_t databyte)
+{
+ bool transfer_succeeded = true;
+
+ /** @snippet [TWI SW master write] */
+ // Make sure SDA is an output
+ TWI_SDA_OUTPUT();
+
+ // MSB first
+ for (uint_fast8_t i = 0x80; i != 0; i >>= 1)
+ {
+ TWI_SCL_LOW();
+ TWI_DELAY();
+
+ if (databyte & i)
+ {
+ TWI_SDA_HIGH();
+ }
+ else
+ {
+ TWI_SDA_LOW();
+ }
+
+ if (!twi_master_wait_while_scl_low())
+ {
+ transfer_succeeded = false; // Timeout
+ break;
+ }
+ }
+
+ // Finish last data bit by pulling SCL low
+ TWI_SCL_LOW();
+ TWI_DELAY();
+
+ /** @snippet [TWI SW master write] */
+
+ // Configure TWI_SDA pin as input for receiving the ACK bit
+ TWI_SDA_INPUT();
+
+ // Give some time for the slave to load the ACK bit on the line
+ TWI_DELAY();
+
+ // Pull SCL high and wait a moment for SDA line to settle
+ // Make sure slave is not stretching the clock
+ transfer_succeeded &= twi_master_wait_while_scl_low();
+
+ // Read ACK/NACK. NACK == 1, ACK == 0
+ transfer_succeeded &= !(TWI_SDA_READ());
+
+ // Finish ACK/NACK bit clock cycle and give slave a moment to release control
+ // of the SDA line
+ TWI_SCL_LOW();
+ TWI_DELAY();
+
+ // Configure TWI_SDA pin as output as other module functions expect that
+ TWI_SDA_OUTPUT();
+
+ return transfer_succeeded;
+}
+
+
+/**
+ * @brief Function for clocking one data byte in and sends ACK/NACK bit.
+ *
+ * Can handle clock stretching.
+ * SCL is expected to be output and low when entering this function.
+ * After calling this function, SCL is high and SDA low/high depending if ACK/NACK was sent.
+ *
+ * @param databyte Data byte to clock out.
+ * @param ack If true, send ACK. Otherwise send NACK.
+ * @return
+ * @retval true Byte read succesfully
+ * @retval false Timeout detected
+ */
+static bool twi_master_clock_byte_in(uint8_t *databyte, bool ack)
+{
+ uint_fast8_t byte_read = 0;
+ bool transfer_succeeded = true;
+
+ /** @snippet [TWI SW master read] */
+ // Make sure SDA is an input
+ TWI_SDA_INPUT();
+
+ // SCL state is guaranteed to be high here
+
+ // MSB first
+ for (uint_fast8_t i = 0x80; i != 0; i >>= 1)
+ {
+ if (!twi_master_wait_while_scl_low())
+ {
+ transfer_succeeded = false;
+ break;
+ }
+
+ if (TWI_SDA_READ())
+ {
+ byte_read |= i;
+ }
+ else
+ {
+ // No need to do anything
+ }
+
+ TWI_SCL_LOW();
+ TWI_DELAY();
+ }
+
+ // Make sure SDA is an output before we exit the function
+ TWI_SDA_OUTPUT();
+ /** @snippet [TWI SW master read] */
+
+ *databyte = (uint8_t)byte_read;
+
+ // Send ACK bit
+
+ // SDA high == NACK, SDA low == ACK
+ if (ack)
+ {
+ TWI_SDA_LOW();
+ }
+ else
+ {
+ TWI_SDA_HIGH();
+ }
+
+ // Let SDA line settle for a moment
+ TWI_DELAY();
+
+ // Drive SCL high to start ACK/NACK bit transfer
+ // Wait until SCL is high, or timeout occurs
+ if (!twi_master_wait_while_scl_low())
+ {
+ transfer_succeeded = false; // Timeout
+ }
+
+ // Finish ACK/NACK bit clock cycle and give slave a moment to react
+ TWI_SCL_LOW();
+ TWI_DELAY();
+
+ return transfer_succeeded;
+}
+
+
+/**
+ * @brief Function for pulling SCL high and waits until it is high or timeout occurs.
+ *
+ * SCL is expected to be output before entering this function.
+ * @note If TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE is set to zero, timeout functionality is not compiled in.
+ * @return
+ * @retval true SCL is now high.
+ * @retval false Timeout occurred and SCL is still low.
+ */
+static bool twi_master_wait_while_scl_low(void)
+{
+#if TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE != 0
+ uint32_t volatile timeout_counter = TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE;
+#endif
+
+ // Pull SCL high just in case if something left it low
+ TWI_SCL_HIGH();
+ TWI_DELAY();
+
+ while (TWI_SCL_READ() == 0)
+ {
+ // If SCL is low, one of the slaves is busy and we must wait
+
+#if TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE != 0
+ if (timeout_counter-- == 0)
+ {
+ // If timeout_detected, return false
+ return false;
+ }
+#endif
+ }
+
+ return true;
+}
+
+/*lint --flb "Leave library region" */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd.c
new file mode 100644
index 0000000..1432d9f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd.c
@@ -0,0 +1,2333 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "sdk_common.h"
+#if NRF_MODULE_ENABLED(USBD)
+
+#include "nrf_drv_usbd.h"
+#include "nrf.h"
+#include "nrf_atomic.h"
+#include "app_util_platform.h"
+#include "nrf_delay.h"
+
+#include <stdbool.h>
+#include <string.h>
+#include <inttypes.h>
+
+#define NRF_LOG_MODULE_NAME USBD
+
+#if USBD_CONFIG_LOG_ENABLED
+#define NRF_LOG_LEVEL USBD_CONFIG_LOG_LEVEL
+#define NRF_LOG_INFO_COLOR USBD_CONFIG_INFO_COLOR
+#define NRF_LOG_DEBUG_COLOR USBD_CONFIG_DEBUG_COLOR
+#else //USBD_CONFIG_LOG_ENABLED
+#define NRF_LOG_LEVEL 0
+#endif //USBD_CONFIG_LOG_ENABLED
+#include "nrf_log.h"
+NRF_LOG_MODULE_REGISTER();
+
+#ifndef NRF_DRV_USBD_EARLY_DMA_PROCESS
+/* Try to process DMA request when endpoint transmission has been detected
+ * and just after last EasyDMA has been processed.
+ * It speeds up the transmission a little (about 10% measured)
+ * with a cost of more CPU power used.
+ */
+#define NRF_DRV_USBD_EARLY_DMA_PROCESS 1
+#endif
+
+#ifndef NRF_DRV_USBD_PROTO1_FIX_DEBUG
+/* Debug information when events are fixed*/
+#define NRF_DRV_USBD_PROTO1_FIX_DEBUG 1
+#endif
+
+#define NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(...) \
+ do{ \
+ if (NRF_DRV_USBD_PROTO1_FIX_DEBUG){ NRF_LOG_DEBUG(__VA_ARGS__); }\
+ } while (0)
+
+#ifndef NRF_DRV_USBD_STARTED_EV_ENABLE
+#define NRF_DRV_USBD_STARTED_EV_ENABLE 0
+#endif
+
+#ifndef NRF_USBD_ISO_DEBUG
+/* Also generate information about ISOCHRONOUS events and transfers.
+ * Turn this off if no ISOCHRONOUS transfers are going to be debugged and this
+ * option generates a lot of useless messages. */
+#define NRF_USBD_ISO_DEBUG 1
+#endif
+
+#ifndef NRF_USBD_FAILED_TRANSFERS_DEBUG
+/* Also generate debug information for failed transfers.
+ * It might be useful but may generate a lot of useless debug messages
+ * in some library usages (for example when transfer is generated and the
+ * result is used to check whatever endpoint was busy. */
+#define NRF_USBD_FAILED_TRANSFERS_DEBUG 1
+#endif
+
+#ifndef NRF_USBD_DMAREQ_PROCESS_DEBUG
+/* Generate additional messages that mark the status inside
+ * @ref usbd_dmareq_process.
+ * It is useful to debug library internals but may generate a lot of
+ * useless debug messages. */
+#define NRF_USBD_DMAREQ_PROCESS_DEBUG 1
+#endif
+
+
+/**
+ * @defgroup nrf_drv_usbd_int USB Device driver internal part
+ * @internal
+ * @ingroup nrf_drv_usbd
+ *
+ * This part contains auxiliary internal macros, variables and functions.
+ * @{
+ */
+
+/**
+ * @brief Assert endpoint number validity
+ *
+ * Internal macro to be used during program creation in debug mode.
+ * Generates assertion if endpoint number is not valid.
+ *
+ * @param ep Endpoint number to validity check
+ */
+#define USBD_ASSERT_EP_VALID(ep) ASSERT( \
+ ((NRF_USBD_EPIN_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < NRF_USBD_EPIN_CNT )) \
+ || \
+ (NRF_USBD_EPOUT_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < NRF_USBD_EPOUT_CNT))) \
+);
+
+/**
+ * @brief Lowest position of bit for IN endpoint
+ *
+ * The first bit position corresponding to IN endpoint.
+ * @sa ep2bit bit2ep
+ */
+#define USBD_EPIN_BITPOS_0 0
+
+/**
+ * @brief Lowest position of bit for OUT endpoint
+ *
+ * The first bit position corresponding to OUT endpoint
+ * @sa ep2bit bit2ep
+ */
+#define USBD_EPOUT_BITPOS_0 16
+
+/**
+ * @brief Input endpoint bits mask
+ */
+#define USBD_EPIN_BIT_MASK (0xFFFFU << USBD_EPIN_BITPOS_0)
+
+/**
+ * @brief Output endpoint bits mask
+ */
+#define USBD_EPOUT_BIT_MASK (0xFFFFU << USBD_EPOUT_BITPOS_0)
+
+/**
+ * @brief Auxiliary macro to change EP number into bit position
+ *
+ * This macro is used by @ref ep2bit function but also for statically check
+ * the bitpos values integrity during compilation.
+ *
+ * @param[in] ep Endpoint number.
+ * @return Endpoint bit position.
+ */
+#define USBD_EP_BITPOS(ep) \
+ ((NRF_USBD_EPIN_CHECK(ep) ? USBD_EPIN_BITPOS_0 : USBD_EPOUT_BITPOS_0) + NRF_USBD_EP_NR_GET(ep))
+
+/**
+ * @brief Helper macro for creating an endpoint transfer event.
+ *
+ * @param[in] name Name of the created transfer event variable.
+ * @param[in] endpoint Endpoint number.
+ * @param[in] ep_stat Endpoint state to report.
+ *
+ * @return Initialized event constant variable.
+ */
+#define NRF_DRV_USBD_EP_TRANSFER_EVENT(name, endpont, ep_stat) \
+ const nrf_drv_usbd_evt_t name = { \
+ NRF_DRV_USBD_EVT_EPTRANSFER, \
+ .data = { \
+ .eptransfer = { \
+ .ep = endpont, \
+ .status = ep_stat \
+ } \
+ } \
+ }
+
+/* Check it the bit positions values match defined DATAEPSTATUS bit positions */
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN1) == USBD_EPDATASTATUS_EPIN1_Pos );
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN2) == USBD_EPDATASTATUS_EPIN2_Pos );
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN3) == USBD_EPDATASTATUS_EPIN3_Pos );
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN4) == USBD_EPDATASTATUS_EPIN4_Pos );
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN5) == USBD_EPDATASTATUS_EPIN5_Pos );
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN6) == USBD_EPDATASTATUS_EPIN6_Pos );
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN7) == USBD_EPDATASTATUS_EPIN7_Pos );
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT1) == USBD_EPDATASTATUS_EPOUT1_Pos);
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT2) == USBD_EPDATASTATUS_EPOUT2_Pos);
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT3) == USBD_EPDATASTATUS_EPOUT3_Pos);
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT4) == USBD_EPDATASTATUS_EPOUT4_Pos);
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT5) == USBD_EPDATASTATUS_EPOUT5_Pos);
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT6) == USBD_EPDATASTATUS_EPOUT6_Pos);
+STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT7) == USBD_EPDATASTATUS_EPOUT7_Pos);
+
+
+/**
+ * @name Internal auxiliary definitions for SETUP packet
+ *
+ * Definitions used to take out the information about last SETUP packet direction
+ * from @c bmRequestType.
+ * @{
+ */
+/** The position of DIR bit in bmRequestType inside SETUP packet */
+#define USBD_DRV_REQUESTTYPE_DIR_BITPOS 7
+/** The mask of DIR bit in bmRequestType inside SETUP packet */
+#define USBD_DRV_REQUESTTYPE_DIR_MASK (1U << USBD_DRV_REQUESTTYPE_DIR_BITPOS)
+/** The value of DIR bit for OUT direction (Host -> Device) */
+#define USBD_DRV_REQUESTTYPE_DIR_OUT (0U << USBD_DRV_REQUESTTYPE_DIR_BITPOS)
+/** The value of DIR bit for IN direction (Device -> Host) */
+#define USBD_DRV_REQUESTTYPE_DIR_IN (1U << USBD_DRV_REQUESTTYPE_DIR_BITPOS)
+/** @} */
+
+/**
+ * @brief Current driver state
+ */
+static nrfx_drv_state_t m_drv_state = NRFX_DRV_STATE_UNINITIALIZED;
+
+/**
+ * @brief Event handler for the library
+ *
+ * Event handler that would be called on events.
+ *
+ * @note Currently it cannot be null if any interrupt is activated.
+ */
+static nrf_drv_usbd_event_handler_t m_event_handler;
+
+/**
+ * @brief Detected state of the bus
+ *
+ * Internal state changed in interrupts handling when
+ * RESUME or SUSPEND event is processed.
+ *
+ * Values:
+ * - true - bus suspended
+ * - false - ongoing normal communication on the bus
+ *
+ * @note This is only the bus state and does not mean that the peripheral is in suspend state.
+ */
+static volatile bool m_bus_suspend;
+
+/**
+ * @brief Internal constant that contains interrupts disabled in suspend state
+ *
+ * Internal constant used in @ref nrf_drv_usbd_suspend_irq_config and @ref nrf_drv_usbd_active_irq_config
+ * functions.
+ */
+static const uint32_t m_irq_disabled_in_suspend =
+ NRF_USBD_INT_ENDEPIN0_MASK |
+ NRF_USBD_INT_EP0DATADONE_MASK |
+ NRF_USBD_INT_ENDEPOUT0_MASK |
+ NRF_USBD_INT_EP0SETUP_MASK |
+ NRF_USBD_INT_DATAEP_MASK;
+
+/**
+ * @brief Direction of last received Setup transfer
+ *
+ * This variable is used to redirect internal setup data event
+ * into selected endpoint (IN or OUT).
+ */
+static nrf_drv_usbd_ep_t m_last_setup_dir;
+
+/**
+ * @brief Mark endpoint readiness for DMA transfer
+ *
+ * Bits in this variable are cleared and set in interrupts.
+ * 1 means that endpoint is ready for DMA transfer.
+ * 0 means that DMA transfer cannot be performed on selected endpoint.
+ */
+static uint32_t m_ep_ready;
+
+/**
+ * @brief Mark endpoint with prepared data to transfer by DMA
+ *
+ * This variable can be from any place in the code (interrupt or main thread).
+ * It would be cleared only from USBD interrupt.
+ *
+ * Mask prepared USBD data for transmission.
+ * It is cleared when no more data to transmit left.
+ */
+static uint32_t m_ep_dma_waiting;
+
+/**
+ * @brief Current EasyDMA state
+ *
+ * Single flag, updated only inside interrupts, that marks current EasyDMA state.
+ * In USBD there is only one DMA channel working in background, and new transfer
+ * cannot be started when there is ongoing transfer on any other channel.
+ */
+static bool m_dma_pending;
+
+/**
+ * @brief Simulated data EP status bits required for errata 104
+ *
+ * Marker to delete when not required anymore: >> NRF_DRV_USBD_ERRATA_ENABLE <<
+ */
+static uint32_t m_simulated_dataepstatus;
+
+/**
+ * @brief The structure that would hold transfer configuration to every endpoint
+ *
+ * The structure that holds all the data required by the endpoint to proceed
+ * with LIST functionality and generate quick callback directly when data
+ * buffer is ready.
+ */
+typedef struct
+{
+ nrf_drv_usbd_handler_t handler; //!< Handler for current transfer, function pointer
+ void * p_context; //!< Context for transfer handler
+ size_t transfer_cnt; //!< Number of transferred bytes in the current transfer
+ uint16_t max_packet_size; //!< Configured endpoint size
+ nrf_drv_usbd_ep_status_t status; //!< NRF_SUCCESS or error code, never NRF_ERROR_BUSY - this one is calculated
+}usbd_drv_ep_state_t;
+
+/**
+ * @brief The array of transfer configurations for the endpoints.
+ *
+ * The status of the transfer on each endpoint.
+ */
+static struct
+{
+ usbd_drv_ep_state_t ep_out[NRF_USBD_EPOUT_CNT]; //!< Status for OUT endpoints.
+ usbd_drv_ep_state_t ep_in [NRF_USBD_EPIN_CNT ]; //!< Status for IN endpoints.
+}m_ep_state;
+
+/**
+ * @brief Status variables for integrated feeders.
+ *
+ * Current status for integrated feeders (IN transfers).
+ * Integrated feeders are used for default transfers:
+ * 1. Simple RAM transfer
+ * 2. Simple flash transfer
+ * 3. RAM transfer with automatic ZLP
+ * 4. Flash transfer with automatic ZLP
+ */
+nrf_drv_usbd_transfer_t m_ep_feeder_state[NRF_USBD_EPIN_CNT];
+
+/**
+ * @brief Status variables for integrated consumers
+ *
+ * Current status for integrated consumers
+ * Currently one type of transfer is supported:
+ * 1. Transfer to RAM
+ *
+ * Transfer is finished automatically when received data block is smaller
+ * than the endpoint buffer or all the required data is received.
+ */
+nrf_drv_usbd_transfer_t m_ep_consumer_state[NRF_USBD_EPOUT_CNT];
+
+
+/**
+ * @brief Buffer used to send data directly from FLASH
+ *
+ * This is internal buffer that would be used to emulate the possibility
+ * to transfer data directly from FLASH.
+ * We do not have to care about the source of data when calling transfer functions.
+ *
+ * We do not need more buffers that one, because only one transfer can be pending
+ * at once.
+ */
+static uint32_t m_tx_buffer[CEIL_DIV(
+ NRF_DRV_USBD_FEEDER_BUFFER_SIZE, sizeof(uint32_t))];
+
+
+/* Early declaration. Documentation above definition. */
+static void usbd_dmareq_process(void);
+
+
+/**
+ * @brief Change endpoint number to endpoint event code
+ *
+ * @param ep Endpoint number
+ *
+ * @return Connected endpoint event code.
+ *
+ * Marker to delete when not required anymore: >> NRF_DRV_USBD_ERRATA_ENABLE <<
+ */
+static inline nrf_usbd_event_t nrf_drv_usbd_ep_to_endevent(nrf_drv_usbd_ep_t ep)
+{
+ USBD_ASSERT_EP_VALID(ep);
+
+ static const nrf_usbd_event_t epin_endev[] =
+ {
+ NRF_USBD_EVENT_ENDEPIN0,
+ NRF_USBD_EVENT_ENDEPIN1,
+ NRF_USBD_EVENT_ENDEPIN2,
+ NRF_USBD_EVENT_ENDEPIN3,
+ NRF_USBD_EVENT_ENDEPIN4,
+ NRF_USBD_EVENT_ENDEPIN5,
+ NRF_USBD_EVENT_ENDEPIN6,
+ NRF_USBD_EVENT_ENDEPIN7,
+ NRF_USBD_EVENT_ENDISOIN0
+ };
+ static const nrf_usbd_event_t epout_endev[] =
+ {
+ NRF_USBD_EVENT_ENDEPOUT0,
+ NRF_USBD_EVENT_ENDEPOUT1,
+ NRF_USBD_EVENT_ENDEPOUT2,
+ NRF_USBD_EVENT_ENDEPOUT3,
+ NRF_USBD_EVENT_ENDEPOUT4,
+ NRF_USBD_EVENT_ENDEPOUT5,
+ NRF_USBD_EVENT_ENDEPOUT6,
+ NRF_USBD_EVENT_ENDEPOUT7,
+ NRF_USBD_EVENT_ENDISOOUT0
+ };
+
+ return (NRF_USBD_EPIN_CHECK(ep) ? epin_endev : epout_endev)[NRF_USBD_EP_NR_GET(ep)];
+}
+
+
+/**
+ * @brief Get interrupt mask for selected endpoint
+ *
+ * @param[in] ep Endpoint number
+ *
+ * @return Interrupt mask related to the EasyDMA transfer end for the
+ * chosen endpoint.
+ */
+static inline uint32_t nrf_drv_usbd_ep_to_int(nrf_drv_usbd_ep_t ep)
+{
+ USBD_ASSERT_EP_VALID(ep);
+
+ static const uint8_t epin_bitpos[] =
+ {
+ USBD_INTEN_ENDEPIN0_Pos,
+ USBD_INTEN_ENDEPIN1_Pos,
+ USBD_INTEN_ENDEPIN2_Pos,
+ USBD_INTEN_ENDEPIN3_Pos,
+ USBD_INTEN_ENDEPIN4_Pos,
+ USBD_INTEN_ENDEPIN5_Pos,
+ USBD_INTEN_ENDEPIN6_Pos,
+ USBD_INTEN_ENDEPIN7_Pos,
+ USBD_INTEN_ENDISOIN_Pos
+ };
+ static const uint8_t epout_bitpos[] =
+ {
+ USBD_INTEN_ENDEPOUT0_Pos,
+ USBD_INTEN_ENDEPOUT1_Pos,
+ USBD_INTEN_ENDEPOUT2_Pos,
+ USBD_INTEN_ENDEPOUT3_Pos,
+ USBD_INTEN_ENDEPOUT4_Pos,
+ USBD_INTEN_ENDEPOUT5_Pos,
+ USBD_INTEN_ENDEPOUT6_Pos,
+ USBD_INTEN_ENDEPOUT7_Pos,
+ USBD_INTEN_ENDISOOUT_Pos
+ };
+
+ return 1UL << (NRF_USBD_EPIN_CHECK(ep) ? epin_bitpos : epout_bitpos)[NRF_USBD_EP_NR_GET(ep)];
+}
+
+/**
+ * @name Integrated feeders and consumers
+ *
+ * Internal, default functions for transfer processing.
+ * @{
+ */
+
+/**
+ * @brief Integrated consumer to RAM buffer.
+ *
+ * @param p_next See @ref nrf_drv_usbd_consumer_t documentation.
+ * @param p_context See @ref nrf_drv_usbd_consumer_t documentation.
+ * @param ep_size See @ref nrf_drv_usbd_consumer_t documentation.
+ * @param data_size See @ref nrf_drv_usbd_consumer_t documentation.
+ *
+ * @retval true Continue transfer.
+ * @retval false This was the last transfer.
+ */
+bool nrf_drv_usbd_consumer(
+ nrf_drv_usbd_ep_transfer_t * p_next,
+ void * p_context,
+ size_t ep_size,
+ size_t data_size)
+{
+ nrf_drv_usbd_transfer_t * p_transfer = p_context;
+ ASSERT(ep_size >= data_size);
+ ASSERT((p_transfer->p_data.rx == NULL) ||
+ nrfx_is_in_ram((const void*)(p_transfer->p_data.ptr)));
+
+ size_t size = p_transfer->size;
+ if (size < data_size)
+ {
+ NRF_LOG_DEBUG("consumer: buffer too small: r: %u, l: %u", data_size, size);
+ /* Buffer size to small */
+ p_next->size = 0;
+ p_next->p_data = p_transfer->p_data;
+ }
+ else
+ {
+ p_next->size = data_size;
+ p_next->p_data = p_transfer->p_data;
+ size -= data_size;
+ p_transfer->size = size;
+ p_transfer->p_data.ptr += data_size;
+ }
+ return (ep_size == data_size) && (size != 0);
+}
+
+/**
+ * @brief Integrated feeder from RAM source.
+ *
+ * @param[out] p_next See @ref nrf_drv_usbd_feeder_t documentation.
+ * @param[in,out] p_context See @ref nrf_drv_usbd_feeder_t documentation.
+ * @param[in] ep_size See @ref nrf_drv_usbd_feeder_t documentation.
+ *
+ * @retval true Continue transfer.
+ * @retval false This was the last transfer.
+ */
+bool nrf_drv_usbd_feeder_ram(
+ nrf_drv_usbd_ep_transfer_t * p_next,
+ void * p_context,
+ size_t ep_size)
+{
+ nrf_drv_usbd_transfer_t * p_transfer = p_context;
+ ASSERT(nrfx_is_in_ram((const void*)(p_transfer->p_data.ptr)));
+
+ size_t tx_size = p_transfer->size;
+ if (tx_size > ep_size)
+ {
+ tx_size = ep_size;
+ }
+
+ p_next->p_data = p_transfer->p_data;
+ p_next->size = tx_size;
+
+ p_transfer->size -= tx_size;
+ p_transfer->p_data.ptr += tx_size;
+
+ return (p_transfer->size != 0);
+}
+
+/**
+ * @brief Integrated feeder from RAM source with ZLP.
+ *
+ * @param[out] p_next See @ref nrf_drv_usbd_feeder_t documentation.
+ * @param[in,out] p_context See @ref nrf_drv_usbd_feeder_t documentation.
+ * @param[in] ep_size See @ref nrf_drv_usbd_feeder_t documentation.
+ *
+ * @retval true Continue transfer.
+ * @retval false This was the last transfer.
+ */
+bool nrf_drv_usbd_feeder_ram_zlp(
+ nrf_drv_usbd_ep_transfer_t * p_next,
+ void * p_context,
+ size_t ep_size)
+{
+ nrf_drv_usbd_transfer_t * p_transfer = p_context;
+ ASSERT(nrfx_is_in_ram((const void*)(p_transfer->p_data.ptr)));
+
+ size_t tx_size = p_transfer->size;
+ if (tx_size > ep_size)
+ {
+ tx_size = ep_size;
+ }
+
+ p_next->p_data.tx = (tx_size == 0) ? NULL : p_transfer->p_data.tx;
+ p_next->size = tx_size;
+
+ p_transfer->size -= tx_size;
+ p_transfer->p_data.ptr += tx_size;
+
+ return (tx_size != 0);
+}
+
+/**
+ * @brief Integrated feeder from a flash source.
+ *
+ * @param[out] p_next See @ref nrf_drv_usbd_feeder_t documentation.
+ * @param[in,out] p_context See @ref nrf_drv_usbd_feeder_t documentation.
+ * @param[in] ep_size See @ref nrf_drv_usbd_feeder_t documentation.
+ *
+ * @retval true Continue transfer.
+ * @retval false This was the last transfer.
+ */
+bool nrf_drv_usbd_feeder_flash(
+ nrf_drv_usbd_ep_transfer_t * p_next,
+ void * p_context,
+ size_t ep_size)
+{
+ nrf_drv_usbd_transfer_t * p_transfer = p_context;
+ ASSERT(!nrfx_is_in_ram((const void*)(p_transfer->p_data.ptr)));
+
+ size_t tx_size = p_transfer->size;
+ void * p_buffer = nrf_drv_usbd_feeder_buffer_get();
+
+ if (tx_size > ep_size)
+ {
+ tx_size = ep_size;
+ }
+
+ ASSERT(tx_size <= NRF_DRV_USBD_FEEDER_BUFFER_SIZE);
+ memcpy(p_buffer, (p_transfer->p_data.tx), tx_size);
+
+ p_next->p_data.tx = p_buffer;
+ p_next->size = tx_size;
+
+ p_transfer->size -= tx_size;
+ p_transfer->p_data.ptr += tx_size;
+
+ return (p_transfer->size != 0);
+}
+
+/**
+ * @brief Integrated feeder from a flash source with ZLP.
+ *
+ * @param[out] p_next See @ref nrf_drv_usbd_feeder_t documentation.
+ * @param[in,out] p_context See @ref nrf_drv_usbd_feeder_t documentation.
+ * @param[in] ep_size See @ref nrf_drv_usbd_feeder_t documentation.
+ *
+ * @retval true Continue transfer.
+ * @retval false This was the last transfer.
+ */
+bool nrf_drv_usbd_feeder_flash_zlp(
+ nrf_drv_usbd_ep_transfer_t * p_next,
+ void * p_context,
+ size_t ep_size)
+{
+ nrf_drv_usbd_transfer_t * p_transfer = p_context;
+ ASSERT(!nrfx_is_in_ram((const void*)(p_transfer->p_data.ptr)));
+
+ size_t tx_size = p_transfer->size;
+ void * p_buffer = nrf_drv_usbd_feeder_buffer_get();
+
+ if (tx_size > ep_size)
+ {
+ tx_size = ep_size;
+ }
+
+ ASSERT(tx_size <= NRF_DRV_USBD_FEEDER_BUFFER_SIZE);
+
+ if (tx_size != 0)
+ {
+ memcpy(p_buffer, (p_transfer->p_data.tx), tx_size);
+ p_next->p_data.tx = p_buffer;
+ }
+ else
+ {
+ p_next->p_data.tx = NULL;
+ }
+ p_next->size = tx_size;
+
+ p_transfer->size -= tx_size;
+ p_transfer->p_data.ptr += tx_size;
+
+ return (tx_size != 0);
+}
+
+/** @} */
+
+/**
+ * @brief Change Driver endpoint number to HAL endpoint number
+ *
+ * @param ep Driver endpoint identifier
+ *
+ * @return Endpoint identifier in HAL
+ *
+ * @sa nrf_drv_usbd_ep_from_hal
+ */
+static inline uint8_t ep_to_hal(nrf_drv_usbd_ep_t ep)
+{
+ USBD_ASSERT_EP_VALID(ep);
+ return (uint8_t)ep;
+}
+
+/**
+ * @brief Generate start task number for selected endpoint index
+ *
+ * @param ep Endpoint number
+ *
+ * @return Task for starting EasyDMA transfer on selected endpoint.
+ */
+static inline nrf_usbd_task_t task_start_ep(nrf_drv_usbd_ep_t ep)
+{
+ USBD_ASSERT_EP_VALID(ep);
+ return (nrf_usbd_task_t)(
+ (NRF_USBD_EPIN_CHECK(ep) ? NRF_USBD_TASK_STARTEPIN0 : NRF_USBD_TASK_STARTEPOUT0) +
+ (NRF_USBD_EP_NR_GET(ep) * sizeof(uint32_t)));
+}
+
+/**
+ * @brief Access selected endpoint state structure
+ *
+ * Function used to change or just read the state of selected endpoint.
+ * It is used for internal transmission state.
+ *
+ * @param ep Endpoint number
+ */
+static inline usbd_drv_ep_state_t* ep_state_access(nrf_drv_usbd_ep_t ep)
+{
+ USBD_ASSERT_EP_VALID(ep);
+ return ((NRF_USBD_EPIN_CHECK(ep) ? m_ep_state.ep_in : m_ep_state.ep_out) +
+ NRF_USBD_EP_NR_GET(ep));
+}
+
+/**
+ * @brief Change endpoint number to bit position
+ *
+ * Bit positions are defined the same way as they are placed in DATAEPSTATUS register,
+ * but bits for endpoint 0 are included.
+ *
+ * @param ep Endpoint number
+ *
+ * @return Bit position related to the given endpoint number
+ *
+ * @sa bit2ep
+ */
+static inline uint8_t ep2bit(nrf_drv_usbd_ep_t ep)
+{
+ USBD_ASSERT_EP_VALID(ep);
+ return USBD_EP_BITPOS(ep);
+}
+
+/**
+ * @brief Change bit position to endpoint number
+ *
+ * @param bitpos Bit position
+ *
+ * @return Endpoint number corresponding to given bit position.
+ *
+ * @sa ep2bit
+ */
+static inline nrf_drv_usbd_ep_t bit2ep(uint8_t bitpos)
+{
+ STATIC_ASSERT(USBD_EPOUT_BITPOS_0 > USBD_EPIN_BITPOS_0);
+ return (nrf_drv_usbd_ep_t)((bitpos >= USBD_EPOUT_BITPOS_0) ?
+ NRF_USBD_EPOUT(bitpos - USBD_EPOUT_BITPOS_0) : NRF_USBD_EPIN(bitpos));
+}
+
+/**
+ * @brief Mark that EasyDMA is working
+ *
+ * Internal function to set the flag informing about EasyDMA transfer pending.
+ * This function is called always just after the EasyDMA transfer is started.
+ */
+static inline void usbd_dma_pending_set(void)
+{
+ if (nrf_drv_usb_errata_199())
+ {
+ *((volatile uint32_t *)0x40027C1C) = 0x00000082;
+ }
+ m_dma_pending = true;
+}
+
+/**
+ * @brief Mark that EasyDMA is free
+ *
+ * Internal function to clear the flag informing about EasyDMA transfer pending.
+ * This function is called always just after the finished EasyDMA transfer is detected.
+ */
+static inline void usbd_dma_pending_clear(void)
+{
+ if (nrf_drv_usb_errata_199())
+ {
+ *((volatile uint32_t *)0x40027C1C) = 0x00000000;
+ }
+ m_dma_pending = false;
+}
+
+/**
+ * @brief Start selected EasyDMA transmission
+ *
+ * This is internal auxiliary function.
+ * No checking is made if EasyDMA is ready for new transmission.
+ *
+ * @param[in] ep Number of endpoint for transmission.
+ * If it is OUT endpoint transmission would be directed from endpoint to RAM.
+ * If it is in endpoint transmission would be directed from RAM to endpoint.
+ */
+static inline void usbd_dma_start(nrf_drv_usbd_ep_t ep)
+{
+ nrf_usbd_task_trigger(task_start_ep(ep));
+}
+
+/**
+ * @brief Abort pending transfer on selected endpoint
+ *
+ * @param ep Endpoint number.
+ *
+ * @note
+ * This function locks interrupts that may be costly.
+ * It is good idea to test if the endpoint is still busy before calling this function:
+ * @code
+ (m_ep_dma_waiting & (1U << ep2bit(ep)))
+ * @endcode
+ * This function would check it again, but it makes it inside critical section.
+ */
+static inline void usbd_ep_abort(nrf_drv_usbd_ep_t ep)
+{
+ CRITICAL_REGION_ENTER();
+
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+
+ if (NRF_USBD_EPOUT_CHECK(ep))
+ {
+ /* Host -> Device */
+ if ((~m_ep_dma_waiting) & (1U << ep2bit(ep)))
+ {
+ /* If the bit in m_ep_dma_waiting in cleared - nothing would be
+ * processed inside transfer processing */
+ nrf_drv_usbd_transfer_out_drop(ep);
+ }
+ else
+ {
+ p_state->handler.consumer = NULL;
+ m_ep_dma_waiting &= ~(1U << ep2bit(ep));
+ m_ep_ready &= ~(1U << ep2bit(ep));
+ }
+ /* Aborted */
+ p_state->status = NRF_USBD_EP_ABORTED;
+ }
+ else
+ {
+ if ((m_ep_dma_waiting | (~m_ep_ready)) & (1U << ep2bit(ep)))
+ {
+ /* Device -> Host */
+ m_ep_dma_waiting &= ~(1U << ep2bit(ep));
+ m_ep_ready |= 1U << ep2bit(ep) ;
+
+ p_state->handler.feeder = NULL;
+ p_state->status = NRF_USBD_EP_ABORTED;
+ NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_ABORTED);
+ m_event_handler(&evt);
+ }
+ }
+ CRITICAL_REGION_EXIT();
+}
+
+void nrf_drv_usbd_ep_abort(nrf_drv_usbd_ep_t ep)
+{
+ usbd_ep_abort(ep);
+}
+
+
+/**
+ * @brief Abort all pending endpoints
+ *
+ * Function aborts all pending endpoint transfers.
+ */
+static void usbd_ep_abort_all(void)
+{
+ uint32_t ep_waiting = m_ep_dma_waiting | (m_ep_ready & USBD_EPOUT_BIT_MASK);
+ while (0 != ep_waiting)
+ {
+ uint8_t bitpos = __CLZ(__RBIT(ep_waiting));
+ if(!NRF_USBD_EPISO_CHECK(bit2ep(bitpos)))
+ {
+ usbd_ep_abort(bit2ep(bitpos));
+ }
+ ep_waiting &= ~(1U << bitpos);
+ }
+
+ m_ep_ready = (((1U << NRF_USBD_EPIN_CNT) - 1U) << USBD_EPIN_BITPOS_0);
+}
+
+/**
+ * @brief Force the USBD interrupt into pending state
+ *
+ * This function is used to force USBD interrupt to be processed right now.
+ * It makes it possible to process all EasyDMA access on one thread priority level.
+ */
+static inline void usbd_int_rise(void)
+{
+ NVIC_SetPendingIRQ(USBD_IRQn);
+}
+
+/**
+ * @name USBD interrupt runtimes
+ *
+ * Interrupt runtimes that would be vectorized using @ref m_ivec_isr
+ * @{
+ */
+
+static void ev_usbreset_handler(void)
+{
+ m_bus_suspend = false;
+ m_last_setup_dir = NRF_DRV_USBD_EPOUT0;
+
+ const nrf_drv_usbd_evt_t evt = {
+ .type = NRF_DRV_USBD_EVT_RESET
+ };
+
+ m_event_handler(&evt);
+}
+
+static void ev_started_handler(void)
+{
+#if NRF_DRV_USBD_STARTED_EV_ENABLE
+ uint32_t epstatus = nrf_usbd_epstatus_get_and_clear();
+
+ /* All finished endpoint have to be marked as busy */
+ // #warning Check this one
+ // ASSERT(epstatus == ((~m_ep_ready) & epstatus));
+ while (epstatus)
+ {
+ uint8_t bitpos = __CLZ(__RBIT(epstatus));
+ nrf_drv_usbd_ep_t ep = bit2ep(bitpos);
+ epstatus &= ~(1UL << bitpos);
+
+ UNUSED_VARIABLE(ep);
+ }
+#endif
+}
+
+/**
+ * @brief Handler for EasyDMA event without endpoint clearing.
+ *
+ * This handler would be called when EasyDMA transfer for endpoints that does not require clearing.
+ * All in endpoints are cleared automatically when new EasyDMA transfer is initialized.
+ * For endpoint 0 see @ref nrf_usbd_ep0out_dma_handler
+ *
+ * @param[in] ep Endpoint number
+ */
+static inline void nrf_usbd_ep0in_dma_handler(void)
+{
+ const nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPIN0;
+ NRF_LOG_DEBUG("USB event: DMA ready IN0");
+ usbd_dma_pending_clear();
+
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ if (NRF_USBD_EP_ABORTED == p_state->status)
+ {
+ /* Clear transfer information just in case */
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ }
+ else if (p_state->handler.feeder == NULL)
+ {
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief Handler for EasyDMA event without endpoint clearing.
+ *
+ * This handler would be called when EasyDMA transfer for endpoints that does not require clearing.
+ * All in endpoints are cleared automatically when new EasyDMA transfer is initialized.
+ * For endpoint 0 see @ref nrf_usbd_ep0out_dma_handler
+ *
+ * @param[in] ep Endpoint number
+ */
+static inline void nrf_usbd_epin_dma_handler(nrf_drv_usbd_ep_t ep)
+{
+
+ NRF_LOG_DEBUG("USB event: DMA ready IN: %x", ep);
+ ASSERT(NRF_USBD_EPIN_CHECK(ep));
+ ASSERT(!NRF_USBD_EPISO_CHECK(ep));
+ ASSERT(NRF_USBD_EP_NR_GET(ep) > 0);
+ usbd_dma_pending_clear();
+
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ if (NRF_USBD_EP_ABORTED == p_state->status)
+ {
+ /* Clear transfer information just in case */
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ }
+ else if (p_state->handler.feeder == NULL)
+ {
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief Handler for EasyDMA event from in isochronous endpoint
+ *
+ * @todo RK documentation
+ */
+static inline void nrf_usbd_epiniso_dma_handler(nrf_drv_usbd_ep_t ep)
+{
+ if (NRF_USBD_ISO_DEBUG)
+ {
+ NRF_LOG_DEBUG("USB event: DMA ready ISOIN: %x", ep);
+ }
+ ASSERT(NRF_USBD_EPIN_CHECK(ep));
+ ASSERT(NRF_USBD_EPISO_CHECK(ep));
+ usbd_dma_pending_clear();
+
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ if (NRF_USBD_EP_ABORTED == p_state->status)
+ {
+ /* Clear transfer information just in case */
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ }
+ else if (p_state->handler.feeder == NULL)
+ {
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ /* Send event to the user - for an ISO IN endpoint, the whole transfer is finished in this moment */
+ NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK);
+ m_event_handler(&evt);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief Handler for EasyDMA event for OUT endpoint 0.
+ *
+ * EP0 OUT have to be cleared automatically in special way - only in the middle of the transfer.
+ * It cannot be cleared when required transfer is finished because it means the same that accepting the comment.
+ */
+static inline void nrf_usbd_ep0out_dma_handler(void)
+{
+ const nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPOUT0;
+ NRF_LOG_DEBUG("USB event: DMA ready OUT0");
+ usbd_dma_pending_clear();
+
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ if (NRF_USBD_EP_ABORTED == p_state->status)
+ {
+ /* Clear transfer information just in case */
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ }
+ else if (p_state->handler.consumer == NULL)
+ {
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */
+ NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK);
+ m_event_handler(&evt);
+ }
+ else
+ {
+ nrf_drv_usbd_setup_data_clear();
+ }
+}
+
+/**
+ * @brief Handler for EasyDMA event from endpoinpoint that requires clearing.
+ *
+ * This handler would be called when EasyDMA transfer for OUT endpoint has been finished.
+ *
+ * @param[in] ep Endpoint number
+ *
+ */
+static inline void nrf_usbd_epout_dma_handler(nrf_drv_usbd_ep_t ep)
+{
+ NRF_LOG_DEBUG("USB drv: DMA ready OUT: %x", ep);
+ ASSERT(NRF_USBD_EPOUT_CHECK(ep));
+ ASSERT(!NRF_USBD_EPISO_CHECK(ep));
+ ASSERT(NRF_USBD_EP_NR_GET(ep) > 0);
+ usbd_dma_pending_clear();
+
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ if (NRF_USBD_EP_ABORTED == p_state->status)
+ {
+ /* Clear transfer information just in case */
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ }
+ else if (p_state->handler.consumer == NULL)
+ {
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */
+ NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK);
+ m_event_handler(&evt);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+#if NRF_DRV_USBD_EARLY_DMA_PROCESS
+ /* Speed up */
+ usbd_dmareq_process();
+#endif
+}
+
+/**
+ * @brief Handler for EasyDMA event from out isochronous endpoint
+ *
+ * @todo RK documentation
+ */
+
+static inline void nrf_usbd_epoutiso_dma_handler(nrf_drv_usbd_ep_t ep)
+{
+ if (NRF_USBD_ISO_DEBUG)
+ {
+ NRF_LOG_DEBUG("USB drv: DMA ready ISOOUT: %x", ep);
+ }
+ ASSERT(NRF_USBD_EPISO_CHECK(ep));
+ usbd_dma_pending_clear();
+
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ if (NRF_USBD_EP_ABORTED == p_state->status)
+ {
+ /* Nothing to do - just ignore */
+ }
+ else if (p_state->handler.consumer == NULL)
+ {
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
+ /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */
+ NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK);
+ m_event_handler(&evt);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+
+static void ev_dma_epin0_handler(void) { nrf_usbd_ep0in_dma_handler(); }
+static void ev_dma_epin1_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN1 ); }
+static void ev_dma_epin2_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN2 ); }
+static void ev_dma_epin3_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN3 ); }
+static void ev_dma_epin4_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN4 ); }
+static void ev_dma_epin5_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN5 ); }
+static void ev_dma_epin6_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN6 ); }
+static void ev_dma_epin7_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN7 ); }
+static void ev_dma_epin8_handler(void) { nrf_usbd_epiniso_dma_handler(NRF_DRV_USBD_EPIN8 ); }
+
+static void ev_dma_epout0_handler(void) { nrf_usbd_ep0out_dma_handler(); }
+static void ev_dma_epout1_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT1); }
+static void ev_dma_epout2_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT2); }
+static void ev_dma_epout3_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT3); }
+static void ev_dma_epout4_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT4); }
+static void ev_dma_epout5_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT5); }
+static void ev_dma_epout6_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT6); }
+static void ev_dma_epout7_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT7); }
+static void ev_dma_epout8_handler(void) { nrf_usbd_epoutiso_dma_handler(NRF_DRV_USBD_EPOUT8); }
+
+static void ev_sof_handler(void)
+{
+ nrf_drv_usbd_evt_t evt = {
+ NRF_DRV_USBD_EVT_SOF,
+ .data = { .sof = { .framecnt = nrf_usbd_framecntr_get() }}
+ };
+
+ /* Process isochronous endpoints */
+ m_ep_ready |=
+ (1U << ep2bit(NRF_DRV_USBD_EPIN8 )) |
+ (1U << ep2bit(NRF_DRV_USBD_EPOUT8));
+
+ m_event_handler(&evt);
+}
+
+/**
+ * @brief React on data transfer finished
+ *
+ * Auxiliary internal function.
+ * @param ep Endpoint number
+ * @param bitpos Bit position for selected endpoint number
+ */
+static void usbd_ep_data_handler(nrf_drv_usbd_ep_t ep, uint8_t bitpos)
+{
+ NRF_LOG_DEBUG("USBD event: EndpointData: %x", ep);
+ /* Mark endpoint ready for next DMA access */
+ m_ep_ready |= (1U << bitpos);
+
+ if (NRF_USBD_EPIN_CHECK(ep))
+ {
+ /* IN endpoint (Device -> Host) */
+ if (0 == (m_ep_dma_waiting & (1U << bitpos)))
+ {
+ NRF_LOG_DEBUG("USBD event: EndpointData: In finished");
+ /* No more data to be send - transmission finished */
+ NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK);
+ m_event_handler(&evt);
+ }
+ }
+ else
+ {
+ /* OUT endpoint (Host -> Device) */
+ if (0 == (m_ep_dma_waiting & (1U << bitpos)))
+ {
+ NRF_LOG_DEBUG("USBD event: EndpointData: Out waiting");
+ /* No buffer prepared - send event to the application */
+ NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_WAITING);
+ m_event_handler(&evt);
+ }
+ }
+}
+
+static void ev_setup_data_handler(void)
+{
+ usbd_ep_data_handler(m_last_setup_dir, ep2bit(m_last_setup_dir));
+}
+
+static void ev_setup_handler(void)
+{
+ NRF_LOG_DEBUG("USBD event: Setup (rt:%.2x r:%.2x v:%.4x i:%.4x l:%u )",
+ nrf_usbd_setup_bmrequesttype_get(),
+ nrf_usbd_setup_brequest_get(),
+ nrf_usbd_setup_wvalue_get(),
+ nrf_usbd_setup_windex_get(),
+ nrf_usbd_setup_wlength_get());
+ uint8_t bmRequestType = nrf_usbd_setup_bmrequesttype_get();
+
+
+ if ((m_ep_dma_waiting | ((~m_ep_ready) & USBD_EPIN_BIT_MASK)) & (1U <<ep2bit(m_last_setup_dir)))
+ {
+ NRF_LOG_DEBUG("USBD drv: Trying to abort last transfer on EP0");
+ usbd_ep_abort(m_last_setup_dir);
+ }
+
+ m_last_setup_dir =
+ ((bmRequestType & USBD_DRV_REQUESTTYPE_DIR_MASK) == USBD_DRV_REQUESTTYPE_DIR_OUT) ?
+ NRF_DRV_USBD_EPOUT0 : NRF_DRV_USBD_EPIN0;
+
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(
+ &m_ep_dma_waiting,
+ ~((1U << ep2bit(NRF_DRV_USBD_EPOUT0)) | (1U << ep2bit(NRF_DRV_USBD_EPIN0)))));
+ m_ep_ready |= 1U << ep2bit(NRF_DRV_USBD_EPIN0);
+
+
+ const nrf_drv_usbd_evt_t evt = {
+ .type = NRF_DRV_USBD_EVT_SETUP
+ };
+ m_event_handler(&evt);
+}
+
+static void ev_usbevent_handler(void)
+{
+ uint32_t event = nrf_usbd_eventcause_get_and_clear();
+
+ if (event & NRF_USBD_EVENTCAUSE_ISOOUTCRC_MASK)
+ {
+ /* Currently no support */
+ }
+ if (event & NRF_USBD_EVENTCAUSE_SUSPEND_MASK)
+ {
+ m_bus_suspend = true;
+ const nrf_drv_usbd_evt_t evt = {
+ .type = NRF_DRV_USBD_EVT_SUSPEND
+ };
+ m_event_handler(&evt);
+ }
+ if (event & NRF_USBD_EVENTCAUSE_RESUME_MASK)
+ {
+ m_bus_suspend = false;
+ const nrf_drv_usbd_evt_t evt = {
+ .type = NRF_DRV_USBD_EVT_RESUME
+ };
+ m_event_handler(&evt);
+ }
+ if (event & NRF_USBD_EVENTCAUSE_WUREQ_MASK)
+ {
+ if (m_bus_suspend)
+ {
+ ASSERT(!nrf_usbd_lowpower_check());
+ m_bus_suspend = false;
+
+ nrf_usbd_dpdmvalue_set(NRF_USBD_DPDMVALUE_RESUME);
+ nrf_usbd_task_trigger(NRF_USBD_TASK_DRIVEDPDM);
+
+ const nrf_drv_usbd_evt_t evt = {
+ .type = NRF_DRV_USBD_EVT_WUREQ
+ };
+ m_event_handler(&evt);
+ }
+ }
+}
+
+static void ev_epdata_handler(void)
+{
+ /* Get all endpoints that have acknowledged transfer */
+ uint32_t dataepstatus = nrf_usbd_epdatastatus_get_and_clear();
+ if (nrf_drv_usbd_errata_104())
+ {
+ dataepstatus |= (m_simulated_dataepstatus &
+ ~((1U << USBD_EPOUT_BITPOS_0) | (1U << USBD_EPIN_BITPOS_0)));
+ m_simulated_dataepstatus &=
+ ((1U << USBD_EPOUT_BITPOS_0) | (1U << USBD_EPIN_BITPOS_0));
+ }
+ NRF_LOG_DEBUG("USBD event: EndpointEPStatus: %x", dataepstatus);
+
+ /* All finished endpoint have to be marked as busy */
+ while (dataepstatus)
+ {
+ uint8_t bitpos = __CLZ(__RBIT(dataepstatus));
+ nrf_drv_usbd_ep_t ep = bit2ep(bitpos);
+ dataepstatus &= ~(1UL << bitpos);
+
+ UNUSED_RETURN_VALUE(usbd_ep_data_handler(ep, bitpos));
+ }
+ if (NRF_DRV_USBD_EARLY_DMA_PROCESS)
+ {
+ /* Speed up */
+ usbd_dmareq_process();
+ }
+}
+
+/**
+ * @brief Function to select the endpoint to start
+ *
+ * Function that realizes algorithm to schedule right channel for EasyDMA transfer.
+ * It gets a variable with flags for the endpoints currently requiring transfer.
+ *
+ * @param[in] req Bit flags for channels currently requiring transfer.
+ * Bits 0...8 used for IN endpoints.
+ * Bits 16...24 used for OUT endpoints.
+ * @note
+ * This function would be never called with 0 as a @c req argument.
+ * @return The bit number of the endpoint that should be processed now.
+ */
+static uint8_t usbd_dma_scheduler_algorithm(uint32_t req)
+{
+ /* Only prioritized scheduling mode is supported */
+ STATIC_ASSERT(USBD_CONFIG_DMASCHEDULER_MODE == NRF_DRV_USBD_DMASCHEDULER_PRIORITIZED);
+ return __CLZ(__RBIT(req));
+}
+
+/**
+ * @brief Get the size of isochronous endpoint
+ *
+ * The size of isochronous endpoint is configurable.
+ * This function returns the size of isochronous buffer taking into account
+ * current configuration.
+ *
+ * @param[in] ep Endpoint number.
+ *
+ * @return The size of endpoint buffer.
+ */
+static inline size_t usbd_ep_iso_capacity(nrf_drv_usbd_ep_t ep)
+{
+ UNUSED_PARAMETER(ep);
+ nrf_usbd_isosplit_t split = nrf_usbd_isosplit_get();
+ if (NRF_USBD_ISOSPLIT_Half == split)
+ {
+ return NRF_DRV_USBD_ISOSIZE / 2;
+ }
+ return NRF_DRV_USBD_ISOSIZE;
+}
+
+/**
+ * @brief Process all DMA requests
+ *
+ * Function that have to be called from USBD interrupt handler.
+ * It have to be called when all the interrupts connected with endpoints transfer
+ * and DMA transfer are already handled.
+ */
+static void usbd_dmareq_process(void)
+{
+ if (!m_dma_pending)
+ {
+ uint32_t req;
+ while (0 != (req = m_ep_dma_waiting & m_ep_ready))
+ {
+ uint8_t pos = usbd_dma_scheduler_algorithm(req);
+ nrf_drv_usbd_ep_t ep = bit2ep(pos);
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+
+ nrf_drv_usbd_ep_transfer_t transfer;
+ bool continue_transfer;
+
+ STATIC_ASSERT(offsetof(usbd_drv_ep_state_t, handler.feeder) ==
+ offsetof(usbd_drv_ep_state_t, handler.consumer));
+ ASSERT((p_state->handler.feeder) != NULL);
+
+ if (NRF_USBD_EPIN_CHECK(ep))
+ {
+ /* Device -> Host */
+ continue_transfer = p_state->handler.feeder(
+ &transfer,
+ p_state->p_context,
+ p_state->max_packet_size);
+
+ if (!continue_transfer)
+ {
+ p_state->handler.feeder = NULL;
+ }
+ }
+ else
+ {
+ /* Host -> Device */
+ const size_t rx_size = nrf_drv_usbd_epout_size_get(ep);
+ continue_transfer = p_state->handler.consumer(
+ &transfer,
+ p_state->p_context,
+ p_state->max_packet_size,
+ rx_size);
+
+ if (transfer.p_data.rx == NULL)
+ {
+ /* Dropping transfer - allow processing */
+ ASSERT(transfer.size == 0);
+ }
+ else if (transfer.size < rx_size)
+ {
+ NRF_LOG_DEBUG("Endpoint %x overload (r: %u, e: %u)", ep, rx_size, transfer.size);
+ p_state->status = NRF_USBD_EP_OVERLOAD;
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << pos)));
+ NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OVERLOAD);
+ m_event_handler(&evt);
+ /* This endpoint will not be transmitted now, repeat the loop */
+ continue;
+ }
+ else
+ {
+ /* Nothing to do - only check integrity if assertions are enabled */
+ ASSERT(transfer.size == rx_size);
+ }
+
+ if (!continue_transfer)
+ {
+ p_state->handler.consumer = NULL;
+ }
+ }
+
+ usbd_dma_pending_set();
+ m_ep_ready &= ~(1U << pos);
+ if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
+ {
+ NRF_LOG_DEBUG(
+ "USB DMA process: Starting transfer on EP: %x, size: %u",
+ ep,
+ transfer.size);
+ }
+ /* Update number of currently transferred bytes */
+ p_state->transfer_cnt += transfer.size;
+ /* Start transfer to the endpoint buffer */
+ nrf_usbd_ep_easydma_set(ep, transfer.p_data.ptr, (uint32_t)transfer.size);
+
+ if (nrf_drv_usbd_errata_104())
+ {
+ uint32_t cnt_end = (uint32_t)(-1);
+ do
+ {
+ uint32_t cnt = (uint32_t)(-1);
+ do
+ {
+ nrf_usbd_event_clear(NRF_USBD_EVENT_STARTED);
+ usbd_dma_start(ep);
+ nrf_delay_us(2);
+ ++cnt;
+ }while (!nrf_usbd_event_check(NRF_USBD_EVENT_STARTED));
+ if (cnt)
+ {
+ NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" DMA restarted: %u times", cnt);
+ }
+
+ nrf_delay_us(30);
+ while (0 == (0x20 & *((volatile uint32_t *)(NRF_USBD_BASE + 0x474))))
+ {
+ nrf_delay_us(2);
+ }
+ nrf_delay_us(1);
+
+ ++cnt_end;
+ } while (!nrf_usbd_event_check(nrf_drv_usbd_ep_to_endevent(ep)));
+ if (cnt_end)
+ {
+ NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" DMA fully restarted: %u times", cnt_end);
+ }
+ }
+ else
+ {
+ usbd_dma_start(ep);
+ /* There is a lot of USBD registers that cannot be accessed during EasyDMA transfer.
+ * This is quick fix to maintain stability of the stack.
+ * It cost some performance but makes stack stable. */
+ while (!nrf_usbd_event_check(nrf_drv_usbd_ep_to_endevent(ep)))
+ {
+ /* Empty */
+ }
+ }
+
+ if (NRF_USBD_DMAREQ_PROCESS_DEBUG)
+ {
+ NRF_LOG_DEBUG("USB DMA process - finishing");
+ }
+ /* Transfer started - exit the loop */
+ break;
+ }
+ }
+ else
+ {
+ if (NRF_USBD_DMAREQ_PROCESS_DEBUG)
+ {
+ NRF_LOG_DEBUG("USB DMA process - EasyDMA busy");
+ }
+ }
+}
+/** @} */
+
+typedef void (*nrf_drv_usbd_isr_t)(void);
+
+/**
+ * @brief USBD interrupt service runtimes
+ *
+ */
+static const nrf_drv_usbd_isr_t m_isr[] =
+{
+ [USBD_INTEN_USBRESET_Pos ] = ev_usbreset_handler,
+ [USBD_INTEN_STARTED_Pos ] = ev_started_handler,
+ [USBD_INTEN_ENDEPIN0_Pos ] = ev_dma_epin0_handler,
+ [USBD_INTEN_ENDEPIN1_Pos ] = ev_dma_epin1_handler,
+ [USBD_INTEN_ENDEPIN2_Pos ] = ev_dma_epin2_handler,
+ [USBD_INTEN_ENDEPIN3_Pos ] = ev_dma_epin3_handler,
+ [USBD_INTEN_ENDEPIN4_Pos ] = ev_dma_epin4_handler,
+ [USBD_INTEN_ENDEPIN5_Pos ] = ev_dma_epin5_handler,
+ [USBD_INTEN_ENDEPIN6_Pos ] = ev_dma_epin6_handler,
+ [USBD_INTEN_ENDEPIN7_Pos ] = ev_dma_epin7_handler,
+ [USBD_INTEN_EP0DATADONE_Pos] = ev_setup_data_handler,
+ [USBD_INTEN_ENDISOIN_Pos ] = ev_dma_epin8_handler,
+ [USBD_INTEN_ENDEPOUT0_Pos ] = ev_dma_epout0_handler,
+ [USBD_INTEN_ENDEPOUT1_Pos ] = ev_dma_epout1_handler,
+ [USBD_INTEN_ENDEPOUT2_Pos ] = ev_dma_epout2_handler,
+ [USBD_INTEN_ENDEPOUT3_Pos ] = ev_dma_epout3_handler,
+ [USBD_INTEN_ENDEPOUT4_Pos ] = ev_dma_epout4_handler,
+ [USBD_INTEN_ENDEPOUT5_Pos ] = ev_dma_epout5_handler,
+ [USBD_INTEN_ENDEPOUT6_Pos ] = ev_dma_epout6_handler,
+ [USBD_INTEN_ENDEPOUT7_Pos ] = ev_dma_epout7_handler,
+ [USBD_INTEN_ENDISOOUT_Pos ] = ev_dma_epout8_handler,
+ [USBD_INTEN_SOF_Pos ] = ev_sof_handler,
+ [USBD_INTEN_USBEVENT_Pos ] = ev_usbevent_handler,
+ [USBD_INTEN_EP0SETUP_Pos ] = ev_setup_handler,
+ [USBD_INTEN_EPDATA_Pos ] = ev_epdata_handler
+};
+
+/**
+ * @name Interrupt handlers
+ *
+ * @{
+ */
+void USBD_IRQHandler(void)
+{
+ const uint32_t enabled = nrf_usbd_int_enable_get();
+ uint32_t to_process = enabled;
+ uint32_t active = 0;
+
+ /* Check all enabled interrupts */
+ while (to_process)
+ {
+ uint8_t event_nr = __CLZ(__RBIT(to_process));
+ if (nrf_usbd_event_get_and_clear((nrf_usbd_event_t)nrfx_bitpos_to_event(event_nr)))
+ {
+ active |= 1UL << event_nr;
+ }
+ to_process &= ~(1UL << event_nr);
+ }
+
+ if (nrf_drv_usbd_errata_104())
+ {
+ /* Event correcting */
+ if ((!m_dma_pending) && (0 != (active & (USBD_INTEN_SOF_Msk))))
+ {
+ uint8_t usbi, uoi, uii;
+ /* Testing */
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7A9;
+ uii = (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+ if (0 != uii)
+ {
+ uii &= (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+ }
+
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AA;
+ uoi = (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+ if (0 != uoi)
+ {
+ uoi &= (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+ }
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AB;
+ usbi = (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+ if (0 != usbi)
+ {
+ usbi &= (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+ }
+ /* Processing */
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AC;
+ uii &= (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804));
+ if (0 != uii)
+ {
+ uint8_t rb;
+ m_simulated_dataepstatus |= ((uint32_t)uii) << USBD_EPIN_BITPOS_0;
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7A9;
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = uii;
+ rb = (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804));
+ NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" uii: 0x%.2x (0x%.2x)", uii, rb);
+ }
+
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AD;
+ uoi &= (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804));
+ if (0 != uoi)
+ {
+ uint8_t rb;
+ m_simulated_dataepstatus |= ((uint32_t)uoi) << USBD_EPOUT_BITPOS_0;
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AA;
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = uoi;
+ rb = (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804));
+ NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" uoi: 0x%.2u (0x%.2x)", uoi, rb);
+ }
+
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AE;
+ usbi &= (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804));
+ if (0 != usbi)
+ {
+ uint8_t rb;
+ if (usbi & 0x01)
+ {
+ active |= USBD_INTEN_EP0SETUP_Msk;
+ }
+ if (usbi & 0x10)
+ {
+ active |= USBD_INTEN_USBRESET_Msk;
+ }
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AB;
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = usbi;
+ rb = (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804));
+ NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" usbi: 0x%.2u (0x%.2x)", usbi, rb);
+ }
+
+ if (0 != (m_simulated_dataepstatus &
+ ~((1U << USBD_EPOUT_BITPOS_0) | (1U << USBD_EPIN_BITPOS_0))))
+ {
+ active |= enabled & NRF_USBD_INT_DATAEP_MASK;
+ }
+ if (0 != (m_simulated_dataepstatus &
+ ((1U << USBD_EPOUT_BITPOS_0) | (1U << USBD_EPIN_BITPOS_0))))
+ {
+ if (0 != (enabled & NRF_USBD_INT_EP0DATADONE_MASK))
+ {
+ m_simulated_dataepstatus &=
+ ~((1U << USBD_EPOUT_BITPOS_0) | (1U << USBD_EPIN_BITPOS_0));
+ active |= NRF_USBD_INT_EP0DATADONE_MASK;
+ }
+ }
+ }
+ }
+
+ /* Process the active interrupts */
+ bool setup_active = 0 != (active & NRF_USBD_INT_EP0SETUP_MASK);
+ active &= ~NRF_USBD_INT_EP0SETUP_MASK;
+
+ while (active)
+ {
+ uint8_t event_nr = __CLZ(__RBIT(active));
+ m_isr[event_nr]();
+ active &= ~(1UL << event_nr);
+ }
+ usbd_dmareq_process();
+
+ if (setup_active)
+ {
+ m_isr[USBD_INTEN_EP0SETUP_Pos]();
+ }
+}
+
+/** @} */
+/** @} */
+
+ret_code_t nrf_drv_usbd_init(nrf_drv_usbd_event_handler_t const event_handler)
+{
+ if (NULL == event_handler)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ if ( m_drv_state != NRFX_DRV_STATE_UNINITIALIZED)
+ {
+ return NRF_ERROR_INVALID_STATE;
+ }
+
+ m_event_handler = event_handler;
+ m_drv_state = NRFX_DRV_STATE_INITIALIZED;
+
+ uint8_t n;
+ for (n=0; n<NRF_USBD_EPIN_CNT; ++n)
+ {
+ nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPIN(n);
+ nrf_drv_usbd_ep_max_packet_size_set(ep, NRF_USBD_EPISO_CHECK(ep) ?
+ (NRF_DRV_USBD_ISOSIZE / 2) : NRF_DRV_USBD_EPSIZE);
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ p_state->status = NRF_USBD_EP_OK;
+ p_state->handler.feeder = NULL;
+ p_state->transfer_cnt = 0;
+ }
+ for (n=0; n<NRF_USBD_EPOUT_CNT; ++n)
+ {
+ nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPOUT(n);
+ nrf_drv_usbd_ep_max_packet_size_set(ep, NRF_USBD_EPISO_CHECK(ep) ?
+ (NRF_DRV_USBD_ISOSIZE / 2) : NRF_DRV_USBD_EPSIZE);
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ p_state->status = NRF_USBD_EP_OK;
+ p_state->handler.consumer = NULL;
+ p_state->transfer_cnt = 0;
+ }
+
+ return NRF_SUCCESS;
+}
+
+ret_code_t nrf_drv_usbd_uninit(void)
+{
+ if (m_drv_state != NRFX_DRV_STATE_INITIALIZED)
+ {
+ return NRF_ERROR_INVALID_STATE;
+ }
+
+ m_event_handler = NULL;
+ m_drv_state = NRFX_DRV_STATE_UNINITIALIZED;
+ return NRF_SUCCESS;
+}
+
+void nrf_drv_usbd_enable(void)
+{
+ ASSERT(m_drv_state == NRFX_DRV_STATE_INITIALIZED);
+
+ /* Prepare for READY event receiving */
+ nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK);
+
+ if (nrf_drv_usbd_errata_187())
+ {
+ CRITICAL_REGION_ENTER();
+ if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
+ {
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ }
+ else
+ {
+ *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
+ }
+ CRITICAL_REGION_EXIT();
+ }
+
+ if (nrf_drv_usbd_errata_171())
+ {
+ CRITICAL_REGION_ENTER();
+ if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
+ {
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ }
+ else
+ {
+ *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
+ }
+ CRITICAL_REGION_EXIT();
+ }
+
+ /* Enable the peripheral */
+ nrf_usbd_enable();
+ /* Waiting for peripheral to enable, this should take a few us */
+ while (0 == (NRF_USBD_EVENTCAUSE_READY_MASK & nrf_usbd_eventcause_get()))
+ {
+ /* Empty loop */
+ }
+ nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK);
+
+ if (nrf_drv_usbd_errata_171())
+ {
+ CRITICAL_REGION_ENTER();
+ if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
+ {
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ *((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ }
+ else
+ {
+ *((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
+ }
+
+ CRITICAL_REGION_EXIT();
+ }
+
+ if (nrf_drv_usbd_errata_187())
+ {
+ CRITICAL_REGION_ENTER();
+ if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
+ {
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ *((volatile uint32_t *)(0x4006ED14)) = 0x00000000;
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ }
+ else
+ {
+ *((volatile uint32_t *)(0x4006ED14)) = 0x00000000;
+ }
+ CRITICAL_REGION_EXIT();
+ }
+
+ if (nrf_drv_usbd_errata_166())
+ {
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7E3;
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0x40;
+ __ISB();
+ __DSB();
+ }
+
+ nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half);
+
+ m_ep_ready = (((1U << NRF_USBD_EPIN_CNT) - 1U) << USBD_EPIN_BITPOS_0);
+ m_ep_dma_waiting = 0;
+ usbd_dma_pending_clear();
+ m_last_setup_dir = NRF_DRV_USBD_EPOUT0;
+
+ m_drv_state = NRFX_DRV_STATE_POWERED_ON;
+}
+
+void nrf_drv_usbd_disable(void)
+{
+ ASSERT(m_drv_state != NRFX_DRV_STATE_UNINITIALIZED);
+
+ /* Stop just in case */
+ nrf_drv_usbd_stop();
+
+ /* Disable all parts */
+ nrf_usbd_int_disable(nrf_usbd_int_enable_get());
+ nrf_usbd_disable();
+ usbd_dma_pending_clear();
+ m_drv_state = NRFX_DRV_STATE_INITIALIZED;
+}
+
+void nrf_drv_usbd_start(bool enable_sof)
+{
+ ASSERT(m_drv_state == NRFX_DRV_STATE_POWERED_ON);
+ m_bus_suspend = false;
+
+ uint32_t ints_to_enable =
+ NRF_USBD_INT_USBRESET_MASK |
+ NRF_USBD_INT_STARTED_MASK |
+ NRF_USBD_INT_ENDEPIN0_MASK |
+ NRF_USBD_INT_EP0DATADONE_MASK |
+ NRF_USBD_INT_ENDEPOUT0_MASK |
+ NRF_USBD_INT_USBEVENT_MASK |
+ NRF_USBD_INT_EP0SETUP_MASK |
+ NRF_USBD_INT_DATAEP_MASK;
+
+ if (enable_sof || nrf_drv_usbd_errata_104())
+ {
+ ints_to_enable |= NRF_USBD_INT_SOF_MASK;
+ }
+
+ /* Enable all required interrupts */
+ nrf_usbd_int_enable(ints_to_enable);
+
+ /* Enable interrupt globally */
+ NRFX_IRQ_PRIORITY_SET(USBD_IRQn, USBD_CONFIG_IRQ_PRIORITY);
+ NRFX_IRQ_ENABLE(USBD_IRQn);
+
+ /* Enable pullups */
+ nrf_usbd_pullup_enable();
+}
+
+void nrf_drv_usbd_stop(void)
+{
+ ASSERT(m_drv_state == NRFX_DRV_STATE_POWERED_ON);
+
+ if(NRFX_IRQ_IS_ENABLED(USBD_IRQn))
+ {
+ /* Abort transfers */
+ usbd_ep_abort_all();
+
+ /* Disable pullups */
+ nrf_usbd_pullup_disable();
+
+ /* Disable interrupt globally */
+ NRFX_IRQ_DISABLE(USBD_IRQn);
+
+ /* Disable all interrupts */
+ nrf_usbd_int_disable(~0U);
+ }
+}
+
+bool nrf_drv_usbd_is_initialized(void)
+{
+ return (m_drv_state >= NRFX_DRV_STATE_INITIALIZED);
+}
+
+bool nrf_drv_usbd_is_enabled(void)
+{
+ return (m_drv_state >= NRFX_DRV_STATE_POWERED_ON);
+}
+
+bool nrf_drv_usbd_is_started(void)
+{
+ return (nrf_drv_usbd_is_enabled() && NRFX_IRQ_IS_ENABLED(USBD_IRQn));
+}
+
+bool nrf_drv_usbd_suspend(void)
+{
+ bool suspended = false;
+
+ CRITICAL_REGION_ENTER();
+ if (m_bus_suspend)
+ {
+ usbd_ep_abort_all();
+
+ if (!(nrf_usbd_eventcause_get() & NRF_USBD_EVENTCAUSE_RESUME_MASK))
+ {
+ nrf_usbd_lowpower_enable();
+ if (nrf_usbd_eventcause_get() & NRF_USBD_EVENTCAUSE_RESUME_MASK)
+ {
+ nrf_usbd_lowpower_disable();
+ }
+ else
+ {
+ suspended = true;
+
+ if (nrf_drv_usbd_errata_171())
+ {
+ if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
+ {
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ *((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ }
+ else
+ {
+ *((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
+ }
+ }
+ }
+ }
+ }
+ CRITICAL_REGION_EXIT();
+
+ return suspended;
+}
+
+bool nrf_drv_usbd_wakeup_req(void)
+{
+ bool started = false;
+
+ CRITICAL_REGION_ENTER();
+ if (m_bus_suspend && nrf_usbd_lowpower_check())
+ {
+ nrf_usbd_lowpower_disable();
+ started = true;
+
+ if (nrf_drv_usbd_errata_171())
+ {
+ if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
+ {
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
+ *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+ }
+ else
+ {
+ *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
+ }
+
+ }
+ }
+ CRITICAL_REGION_EXIT();
+
+ return started;
+}
+
+bool nrf_drv_usbd_suspend_check(void)
+{
+ return nrf_usbd_lowpower_check();
+}
+
+void nrf_drv_usbd_suspend_irq_config(void)
+{
+ nrf_usbd_int_disable(m_irq_disabled_in_suspend);
+}
+
+void nrf_drv_usbd_active_irq_config(void)
+{
+ nrf_usbd_int_enable(m_irq_disabled_in_suspend);
+}
+
+bool nrf_drv_usbd_bus_suspend_check(void)
+{
+ return m_bus_suspend;
+}
+
+void nrf_drv_usbd_ep_max_packet_size_set(nrf_drv_usbd_ep_t ep, uint16_t size)
+{
+ /* Only power of 2 size allowed */
+ ASSERT((size != 0) && (size & (size - 1)) == 0);
+ /* Packet size cannot be higher than maximum buffer size */
+ ASSERT( ( NRF_USBD_EPISO_CHECK(ep) && (size <= usbd_ep_iso_capacity(ep)))
+ ||
+ ((!NRF_USBD_EPISO_CHECK(ep)) && (size <= NRF_DRV_USBD_EPSIZE)));
+
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ p_state->max_packet_size = size;
+}
+
+uint16_t nrf_drv_usbd_ep_max_packet_size_get(nrf_drv_usbd_ep_t ep)
+{
+ usbd_drv_ep_state_t const * p_state = ep_state_access(ep);
+ return p_state->max_packet_size;
+}
+
+bool nrf_drv_usbd_ep_enable_check(nrf_drv_usbd_ep_t ep)
+{
+ return nrf_usbd_ep_enable_check(ep_to_hal(ep));
+}
+
+void nrf_drv_usbd_ep_enable(nrf_drv_usbd_ep_t ep)
+{
+ nrf_usbd_int_enable(nrf_drv_usbd_ep_to_int(ep));
+
+ if(nrf_usbd_ep_enable_check(ep))
+ {
+ return;
+ }
+ nrf_usbd_ep_enable(ep_to_hal(ep));
+ if ((NRF_USBD_EP_NR_GET(ep) != 0) && NRF_USBD_EPOUT_CHECK(ep) && (!NRF_USBD_EPISO_CHECK(ep)))
+ {
+ CRITICAL_REGION_ENTER();
+ nrf_drv_usbd_transfer_out_drop(ep);
+ m_ep_dma_waiting &= ~(1U << ep2bit(ep));
+ CRITICAL_REGION_EXIT();
+ }
+}
+
+void nrf_drv_usbd_ep_disable(nrf_drv_usbd_ep_t ep)
+{
+ usbd_ep_abort(ep);
+ nrf_usbd_ep_disable(ep_to_hal(ep));
+ nrf_usbd_int_disable(nrf_drv_usbd_ep_to_int(ep));
+}
+
+void nrf_drv_usbd_ep_default_config(void)
+{
+ nrf_usbd_int_disable(
+ NRF_USBD_INT_ENDEPIN1_MASK |
+ NRF_USBD_INT_ENDEPIN2_MASK |
+ NRF_USBD_INT_ENDEPIN3_MASK |
+ NRF_USBD_INT_ENDEPIN4_MASK |
+ NRF_USBD_INT_ENDEPIN5_MASK |
+ NRF_USBD_INT_ENDEPIN6_MASK |
+ NRF_USBD_INT_ENDEPIN7_MASK |
+ NRF_USBD_INT_ENDISOIN0_MASK |
+ NRF_USBD_INT_ENDEPOUT1_MASK |
+ NRF_USBD_INT_ENDEPOUT2_MASK |
+ NRF_USBD_INT_ENDEPOUT3_MASK |
+ NRF_USBD_INT_ENDEPOUT4_MASK |
+ NRF_USBD_INT_ENDEPOUT5_MASK |
+ NRF_USBD_INT_ENDEPOUT6_MASK |
+ NRF_USBD_INT_ENDEPOUT7_MASK |
+ NRF_USBD_INT_ENDISOOUT0_MASK
+ );
+ nrf_usbd_int_enable(NRF_USBD_INT_ENDEPIN0_MASK | NRF_USBD_INT_ENDEPOUT0_MASK);
+ nrf_usbd_ep_all_disable();
+}
+
+ret_code_t nrf_drv_usbd_ep_transfer(
+ nrf_drv_usbd_ep_t ep,
+ nrf_drv_usbd_transfer_t const * const p_transfer)
+{
+ ret_code_t ret;
+ const uint8_t ep_bitpos = ep2bit(ep);
+ ASSERT(NULL != p_transfer);
+
+ CRITICAL_REGION_ENTER();
+ /* Setup data transaction can go only in one direction at a time */
+ if ((NRF_USBD_EP_NR_GET(ep) == 0) && (ep != m_last_setup_dir))
+ {
+ ret = NRF_ERROR_INVALID_ADDR;
+ if (NRF_USBD_FAILED_TRANSFERS_DEBUG && (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))))
+ {
+ NRF_LOG_DEBUG("USB driver: Transfer failed: Invalid EPr\n");
+ }
+ }
+ else if ((m_ep_dma_waiting | ((~m_ep_ready) & USBD_EPIN_BIT_MASK)) & (1U << ep_bitpos))
+ {
+ /* IN (Device -> Host) transfer has to be transmitted out to allow new transmission */
+ ret = NRF_ERROR_BUSY;
+ if (NRF_USBD_FAILED_TRANSFERS_DEBUG)
+ {
+ NRF_LOG_DEBUG("USB driver: Transfer failed: EP is busy");
+ }
+ }
+ else
+ {
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+ /* Prepare transfer context and handler description */
+ nrf_drv_usbd_transfer_t * p_context;
+ if (NRF_USBD_EPIN_CHECK(ep))
+ {
+ p_context = m_ep_feeder_state + NRF_USBD_EP_NR_GET(ep);
+ if (nrfx_is_in_ram(p_transfer->p_data.tx))
+ {
+ /* RAM */
+ if (0 == (p_transfer->flags & NRF_DRV_USBD_TRANSFER_ZLP_FLAG))
+ {
+ p_state->handler.feeder = nrf_drv_usbd_feeder_ram;
+ if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
+ {
+ NRF_LOG_DEBUG(
+ "USB driver: Transfer called on endpoint %x, size: %u, mode: "
+ "RAM",
+ ep,
+ p_transfer->size);
+ }
+ }
+ else
+ {
+ p_state->handler.feeder = nrf_drv_usbd_feeder_ram_zlp;
+ if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
+ {
+ NRF_LOG_DEBUG(
+ "USB driver: Transfer called on endpoint %x, size: %u, mode: "
+ "RAM_ZLP",
+ ep,
+ p_transfer->size);
+ }
+ }
+ }
+ else
+ {
+ /* Flash */
+ if (0 == (p_transfer->flags & NRF_DRV_USBD_TRANSFER_ZLP_FLAG))
+ {
+ p_state->handler.feeder = nrf_drv_usbd_feeder_flash;
+ if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
+ {
+ NRF_LOG_DEBUG(
+ "USB driver: Transfer called on endpoint %x, size: %u, mode: "
+ "FLASH",
+ ep,
+ p_transfer->size);
+ }
+ }
+ else
+ {
+ p_state->handler.feeder = nrf_drv_usbd_feeder_flash_zlp;
+ if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
+ {
+ NRF_LOG_DEBUG(
+ "USB driver: Transfer called on endpoint %x, size: %u, mode: "
+ "FLASH_ZLP",
+ ep,
+ p_transfer->size);
+ }
+ }
+ }
+ }
+ else
+ {
+ p_context = m_ep_consumer_state + NRF_USBD_EP_NR_GET(ep);
+ ASSERT((p_transfer->p_data.rx == NULL) || (nrfx_is_in_ram(p_transfer->p_data.rx)));
+ p_state->handler.consumer = nrf_drv_usbd_consumer;
+ }
+ *p_context = *p_transfer;
+ p_state->p_context = p_context;
+
+ p_state->transfer_cnt = 0;
+ p_state->status = NRF_USBD_EP_OK;
+ m_ep_dma_waiting |= 1U << ep_bitpos;
+ ret = NRF_SUCCESS;
+ usbd_int_rise();
+ }
+ CRITICAL_REGION_EXIT();
+ return ret;
+}
+
+ret_code_t nrf_drv_usbd_ep_handled_transfer(
+ nrf_drv_usbd_ep_t ep,
+ nrf_drv_usbd_handler_desc_t const * const p_handler)
+{
+ ret_code_t ret;
+ const uint8_t ep_bitpos = ep2bit(ep);
+ ASSERT(NULL != p_handler);
+
+ CRITICAL_REGION_ENTER();
+ /* Setup data transaction can go only in one direction at a time */
+ if ((NRF_USBD_EP_NR_GET(ep) == 0) && (ep != m_last_setup_dir))
+ {
+ ret = NRF_ERROR_INVALID_ADDR;
+ if (NRF_USBD_FAILED_TRANSFERS_DEBUG && (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))))
+ {
+ NRF_LOG_DEBUG("USB driver: Transfer failed: Invalid EP");
+ }
+ }
+ else if ((m_ep_dma_waiting | ((~m_ep_ready) & USBD_EPIN_BIT_MASK)) & (1U << ep_bitpos))
+ {
+ /* IN (Device -> Host) transfer has to be transmitted out to allow a new transmission */
+ ret = NRF_ERROR_BUSY;
+ if (NRF_USBD_FAILED_TRANSFERS_DEBUG && (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))))
+ {
+ NRF_LOG_DEBUG("USB driver: Transfer failed: EP is busy");\
+ }
+ }
+ else
+ {
+ /* Transfer can be configured now */
+ usbd_drv_ep_state_t * p_state = ep_state_access(ep);
+
+ p_state->transfer_cnt = 0;
+ p_state->handler = p_handler->handler;
+ p_state->p_context = p_handler->p_context;
+ p_state->status = NRF_USBD_EP_OK;
+ m_ep_dma_waiting |= 1U << ep_bitpos;
+
+ ret = NRF_SUCCESS;
+ if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
+ {
+ NRF_LOG_DEBUG("USB driver: Transfer called on endpoint %x, mode: Handler", ep);
+ }
+ usbd_int_rise();
+ }
+ CRITICAL_REGION_EXIT();
+ return ret;
+}
+
+void * nrf_drv_usbd_feeder_buffer_get(void)
+{
+ return m_tx_buffer;
+}
+
+ret_code_t nrf_drv_usbd_ep_status_get(nrf_drv_usbd_ep_t ep, size_t * p_size)
+{
+ ret_code_t ret;
+
+ usbd_drv_ep_state_t const * p_state = ep_state_access(ep);
+ CRITICAL_REGION_ENTER();
+ *p_size = p_state->transfer_cnt;
+ ret = (p_state->handler.consumer == NULL) ? p_state->status : NRF_ERROR_BUSY;
+ CRITICAL_REGION_EXIT();
+ return ret;
+}
+
+size_t nrf_drv_usbd_epout_size_get(nrf_drv_usbd_ep_t ep)
+{
+ return nrf_usbd_epout_size_get(ep_to_hal(ep));
+}
+
+bool nrf_drv_usbd_ep_is_busy(nrf_drv_usbd_ep_t ep)
+{
+ return (0 != ((m_ep_dma_waiting | ((~m_ep_ready) & USBD_EPIN_BIT_MASK)) & (1U << ep2bit(ep))));
+}
+
+void nrf_drv_usbd_ep_stall(nrf_drv_usbd_ep_t ep)
+{
+ NRF_LOG_DEBUG("USB: EP %x stalled.", ep);
+ nrf_usbd_ep_stall(ep_to_hal(ep));
+}
+
+void nrf_drv_usbd_ep_stall_clear(nrf_drv_usbd_ep_t ep)
+{
+ nrf_usbd_ep_unstall(ep_to_hal(ep));
+}
+
+bool nrf_drv_usbd_ep_stall_check(nrf_drv_usbd_ep_t ep)
+{
+ return nrf_usbd_ep_is_stall(ep_to_hal(ep));
+}
+
+void nrf_drv_usbd_ep_dtoggle_clear(nrf_drv_usbd_ep_t ep)
+{
+ nrf_usbd_dtoggle_set(ep, NRF_USBD_DTOGGLE_DATA0);
+}
+
+void nrf_drv_usbd_setup_get(nrf_drv_usbd_setup_t * const p_setup)
+{
+ memset(p_setup, 0, sizeof(nrf_drv_usbd_setup_t));
+ p_setup->bmRequestType = nrf_usbd_setup_bmrequesttype_get();
+ p_setup->bmRequest = nrf_usbd_setup_brequest_get();
+ p_setup->wValue = nrf_usbd_setup_wvalue_get();
+ p_setup->wIndex = nrf_usbd_setup_windex_get();
+ p_setup->wLength = nrf_usbd_setup_wlength_get();
+}
+
+void nrf_drv_usbd_setup_data_clear(void)
+{
+ if (nrf_drv_usbd_errata_104())
+ {
+ /* For this fix to work properly, it must be ensured that the task is
+ * executed twice one after another - blocking ISR. This is however a temporary
+ * solution to be used only before production version of the chip. */
+ uint32_t primask_copy = __get_PRIMASK();
+ __disable_irq();
+ nrf_usbd_task_trigger(NRF_USBD_TASK_EP0RCVOUT);
+ nrf_usbd_task_trigger(NRF_USBD_TASK_EP0RCVOUT);
+ __set_PRIMASK(primask_copy);
+ }
+ else
+ {
+ nrf_usbd_task_trigger(NRF_USBD_TASK_EP0RCVOUT);
+ }
+}
+
+void nrf_drv_usbd_setup_clear(void)
+{
+ nrf_usbd_task_trigger(NRF_USBD_TASK_EP0STATUS);
+}
+
+void nrf_drv_usbd_setup_stall(void)
+{
+ NRF_LOG_DEBUG("Setup stalled.");
+ nrf_usbd_task_trigger(NRF_USBD_TASK_EP0STALL);
+}
+
+nrf_drv_usbd_ep_t nrf_drv_usbd_last_setup_dir_get(void)
+{
+ return m_last_setup_dir;
+}
+
+void nrf_drv_usbd_transfer_out_drop(nrf_drv_usbd_ep_t ep)
+{
+ ASSERT(NRF_USBD_EPOUT_CHECK(ep));
+
+ if (nrf_drv_usbd_errata_sizeepout_rw())
+ {
+ CRITICAL_REGION_ENTER();
+ m_ep_ready &= ~(1U << ep2bit(ep));
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7C5 + (2u * NRF_USBD_EP_NR_GET(ep));
+ *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0;
+ UNUSED_VARIABLE(((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+ CRITICAL_REGION_EXIT();
+ }
+ else
+ {
+ CRITICAL_REGION_ENTER();
+ m_ep_ready &= ~(1U << ep2bit(ep));
+ if (!NRF_USBD_EPISO_CHECK(ep))
+ {
+ nrf_usbd_epout_clear(ep);
+ }
+ CRITICAL_REGION_EXIT();
+ }
+}
+
+#endif // NRF_MODULE_ENABLED(USBD)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd.h
new file mode 100644
index 0000000..24a14f4
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd.h
@@ -0,0 +1,943 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRF_DRV_USBD_H__
+#define NRF_DRV_USBD_H__
+
+#include "sdk_errors.h"
+#include "nrf_usbd.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include "app_util.h"
+#include "nrf_drv_usbd_errata.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrf_drv_usbd USB Device HAL and driver
+ * @ingroup nrf_drivers
+ * @brief @tagAPI52840 USB Device APIs.
+ * @details The USB Device HAL provides basic APIs for accessing
+ * the registers of the USBD.
+ * The USB Device driver provides APIs on a higher level.
+ *
+ * @{
+ */
+
+/**
+ * @name Possible schemes of DMA scheduling
+ *
+ * Definition of available configuration constants used by DMA scheduler
+ * @{
+ */
+ /**
+ * @brief Highly prioritized access
+ *
+ * Endpoint with lower number has always higher priority and its data would
+ * be transfered first.
+ * OUT endpoints ale processed before IN endpoints
+ */
+ #define NRF_DRV_USBD_DMASCHEDULER_PRIORITIZED 0
+
+ /**
+ * @brief Round robin scheme
+ *
+ * All endpoints are processed in round-robin scheme.
+ * It means that when one endpoint is processed next in order would be
+ * the nearest with lower number.
+ * When no endpoints with lower number requires processing - then
+ * all endpoints from 0 are tested.
+ */
+ #define NRF_DRV_USBD_DMASCHEDULER_ROUNDROBIN 1
+
+/** @} */
+
+/**
+ * @brief Number of bytes in the endpoint
+ *
+ * Constant that informs about endpoint size
+ */
+#define NRF_DRV_USBD_EPSIZE 64
+
+/**
+ * @brief Number of bytes for isochronous endpoints
+ *
+ * Number of bytes for isochronous endpoints in total.
+ * This number would be shared between IN and OUT endpoint.
+ * It may be also assigned totaly to one endpoint.
+ * @sa nrf_usbd_isosplit_set
+ * @sa nrf_usbd_isosplit_get
+ */
+#define NRF_DRV_USBD_ISOSIZE 1024
+
+/**
+ * @brief The size of internal feeder buffer.
+ *
+ * @sa nrf_drv_usbd_feeder_buffer_get
+ */
+#define NRF_DRV_USBD_FEEDER_BUFFER_SIZE NRF_DRV_USBD_EPSIZE
+
+/**
+ * @name Macros for creating endpoint identifiers
+ *
+ * Auxiliary macros to be used to create Endpoint identifier that is compatible
+ * with USB specification.
+ * @{
+ */
+
+ /**
+ * @brief Create identifier for IN endpoint
+ *
+ * Simple macro to create IN endpoint identifier for given endpoint number.
+ *
+ * @param[in] n Endpoint number.
+ *
+ * @return Endpoint identifier that connects endpoint number and endpoint direction.
+ */
+ #define NRF_DRV_USBD_EPIN(n) ((nrf_drv_usbd_ep_t)NRF_USBD_EPIN(n))
+ /**
+ * @brief Create identifier for OUT endpoint
+ *
+ * Simple macro to create OUT endpoint identifier for given endpoint number.
+ *
+ * @param[in] n Endpoint number.
+ *
+ * @return Endpoint identifier that connects endpoint number and endpoint direction.
+ */
+ #define NRF_DRV_USBD_EPOUT(n) ((nrf_drv_usbd_ep_t)NRF_USBD_EPOUT(n))
+
+/** @} */
+
+/**
+ * @brief Endpoint identifier
+ *
+ * Endpoint identifier used in the driver.
+ * This endpoint number is consistent with USB 2.0 specification.
+ */
+typedef enum
+{
+ NRF_DRV_USBD_EPOUT0 = NRF_USBD_EPOUT(0), /**< Endpoint OUT 0 */
+ NRF_DRV_USBD_EPOUT1 = NRF_USBD_EPOUT(1), /**< Endpoint OUT 1 */
+ NRF_DRV_USBD_EPOUT2 = NRF_USBD_EPOUT(2), /**< Endpoint OUT 2 */
+ NRF_DRV_USBD_EPOUT3 = NRF_USBD_EPOUT(3), /**< Endpoint OUT 3 */
+ NRF_DRV_USBD_EPOUT4 = NRF_USBD_EPOUT(4), /**< Endpoint OUT 4 */
+ NRF_DRV_USBD_EPOUT5 = NRF_USBD_EPOUT(5), /**< Endpoint OUT 5 */
+ NRF_DRV_USBD_EPOUT6 = NRF_USBD_EPOUT(6), /**< Endpoint OUT 6 */
+ NRF_DRV_USBD_EPOUT7 = NRF_USBD_EPOUT(7), /**< Endpoint OUT 7 */
+ NRF_DRV_USBD_EPOUT8 = NRF_USBD_EPOUT(8), /**< Endpoint OUT 8 */
+
+ NRF_DRV_USBD_EPIN0 = NRF_USBD_EPIN(0), /**< Endpoint IN 0 */
+ NRF_DRV_USBD_EPIN1 = NRF_USBD_EPIN(1), /**< Endpoint IN 1 */
+ NRF_DRV_USBD_EPIN2 = NRF_USBD_EPIN(2), /**< Endpoint IN 2 */
+ NRF_DRV_USBD_EPIN3 = NRF_USBD_EPIN(3), /**< Endpoint IN 3 */
+ NRF_DRV_USBD_EPIN4 = NRF_USBD_EPIN(4), /**< Endpoint IN 4 */
+ NRF_DRV_USBD_EPIN5 = NRF_USBD_EPIN(5), /**< Endpoint IN 5 */
+ NRF_DRV_USBD_EPIN6 = NRF_USBD_EPIN(6), /**< Endpoint IN 6 */
+ NRF_DRV_USBD_EPIN7 = NRF_USBD_EPIN(7), /**< Endpoint IN 7 */
+ NRF_DRV_USBD_EPIN8 = NRF_USBD_EPIN(8), /**< Endpoint IN 8 */
+}nrf_drv_usbd_ep_t;
+
+/**
+ * @brief Events generated by the library
+ *
+ * Enumeration of possible events that may be generated by the library.
+ */
+typedef enum
+{
+ NRF_DRV_USBD_EVT_SOF, /**< Start Of Frame event on USB bus detected */
+ NRF_DRV_USBD_EVT_RESET, /**< Reset condition on USB bus detected */
+ NRF_DRV_USBD_EVT_SUSPEND, /**< This device should go to suspend mode now */
+ NRF_DRV_USBD_EVT_RESUME, /**< This device should resume from suspend now */
+ NRF_DRV_USBD_EVT_WUREQ, /**< Wakeup request - the USBD peripheral is ready to generate WAKEUP signal after exiting low power mode. */
+ NRF_DRV_USBD_EVT_SETUP, /**< Setup frame received and decoded */
+ NRF_DRV_USBD_EVT_EPTRANSFER, /**<
+ * For Rx (OUT: Host->Device):
+ * 1. The packet has been received but there is no buffer prepared for transfer already.
+ * 2. Whole transfer has been finished
+ *
+ * For Tx (IN: Device->Host):
+ * The last packet from requested transfer has been transfered over USB bus and acknowledged
+ */
+ NRF_DRV_USBD_EVT_CNT /**< Number of defined events */
+}nrf_drv_usbd_event_type_t;
+
+/**
+ * @brief Possible endpoint error codes
+ *
+ * Error codes that may be returned with @ref NRF_DRV_USBD_EVT_EPTRANSFER
+ */
+typedef enum
+{
+ NRF_USBD_EP_OK, /**< No error */
+ NRF_USBD_EP_WAITING, /**< Data received, no buffer prepared already - waiting for configured transfer */
+ NRF_USBD_EP_OVERLOAD, /**< Received number of bytes cannot fit given buffer
+ * This error would also be returned when next_transfer function has been defined
+ * but currently received data cannot fit completely in current buffer.
+ * No data split from single endpoint transmission is supported.
+ *
+ * When this error is reported - data is left inside endpoint buffer.
+ * Clear endpoint or prepare new buffer and read it.
+ */
+ NRF_USBD_EP_ABORTED, /**< EP0 transfer can be aborted when new setup comes.
+ * Any other transfer can be aborted by USB reset or library stopping.
+ */
+}nrf_drv_usbd_ep_status_t;
+
+
+/**
+ * @brief Event structure
+ *
+ * Structure passed to event handler
+ */
+typedef struct
+{
+ nrf_drv_usbd_event_type_t type;
+ union
+ {
+ struct{
+ uint16_t framecnt; //!< Current value of frame counter
+ }sof; //!< Data aviable for @ref NRF_DRV_USBD_EVT_SOF
+ struct{
+ nrf_drv_usbd_ep_t ep; //!< Endpoint number
+ }isocrc;
+ struct{
+ nrf_drv_usbd_ep_t ep; //!< Endpoint number
+ nrf_drv_usbd_ep_status_t status; //!< Status for the endpoint
+ }eptransfer;
+ }data;
+}nrf_drv_usbd_evt_t;
+
+/**
+ * @brief USBD event callback function type.
+ *
+ * @param[in] p_event Event information structure.
+ */
+typedef void (*nrf_drv_usbd_event_handler_t)(nrf_drv_usbd_evt_t const * const p_event);
+
+/**
+ * @brief Universal data pointer.
+ *
+ * Universal data pointer that can be used for any type of transfer.
+ */
+typedef union
+{
+ void const * tx; //!< Constant TX buffer pointer.
+ void * rx; //!< Writable RX buffer pointer.
+ uint32_t ptr; //!< Numeric value used internally by the library.
+}nrf_drv_usbd_data_ptr_t;
+
+/**
+ * @brief Structure to be filled with information about the next transfer.
+ *
+ * This is used mainly for transfer feeders and consumers.
+ * It describes a single endpoint transfer and therefore the size of the buffer
+ * can never be higher than the endpoint size.
+ */
+typedef struct
+{
+ nrf_drv_usbd_data_ptr_t p_data; //!< Union with available data pointers used by the library.
+ size_t size; //!< Size of the requested transfer.
+}nrf_drv_usbd_ep_transfer_t;
+
+/**
+ * @brief Flags for the current transfer.
+ *
+ * Flags configured for the transfer that can be merged using the bitwise 'or' operator (|).
+ */
+typedef enum
+{
+ NRF_DRV_USBD_TRANSFER_ZLP_FLAG = 1U << 0, //!< Add a zero-length packet.
+}nrf_drv_usbd_transfer_flags_t;
+
+/**
+ * @brief Total transfer configuration.
+ *
+ * This structure is used to configure total transfer information.
+ * It is used by internal built-in feeders and consumers.
+ */
+typedef struct
+{
+ nrf_drv_usbd_data_ptr_t p_data; //!< Union with available data pointers used by the library.
+ size_t size; //!< Total size of the requested transfer.
+ uint32_t flags; //!< Transfer flags.
+ /**< Use the @ref nrf_drv_usbd_transfer_flags_t values. */
+}nrf_drv_usbd_transfer_t;
+
+
+/**
+ * @brief Auxiliary macro for declaring IN transfer description with flags.
+ *
+ * The base macro for creating transfers with any configuration option.
+ *
+ * @param name Instance name.
+ * @param tx_buff Buffer to transfer.
+ * @param tx_size Transfer size.
+ * @param tx_flags Flags for the transfer (see @ref nrf_drv_usbd_transfer_flags_t).
+ *
+ * @return Configured variable with total transfer description.
+ */
+#define NRF_DRV_USBD_TRANSFER_IN_FLAGS(name, tx_buff, tx_size, tx_flags) \
+ const nrf_drv_usbd_transfer_t name = { \
+ .p_data = { .tx = (tx_buff) }, \
+ .size = (tx_size), \
+ .flags = (tx_flags) \
+ }
+
+/**
+ * @brief Helper macro for declaring IN transfer description
+ *
+ * Normal transfer mode, no ZLP would be automatically generated.
+ *
+ * @sa nrf_drv_usbd_transfer_t
+ * @sa NRF_DRV_USBD_TRANSFER_IN_ZLP
+ *
+ * @param name Instance name
+ * @param tx_buff Buffer to transfer
+ * @param tx_size Transfer size
+ *
+ * @return Configured variable with total transfer description
+ *
+ */
+#define NRF_DRV_USBD_TRANSFER_IN(name, tx_buff, tx_size) \
+ NRF_DRV_USBD_TRANSFER_IN_FLAGS(name, tx_buff, tx_size, 0)
+
+/**
+ * @brief Helper macro for declaring IN transfer description
+ *
+ * ZLP mode - Zero Length Packet would be generated on the end of the transfer
+ * (always!).
+ *
+ * @sa nrf_drv_usbd_transfer_t
+ * @sa NRF_DRV_USBD_TRANSFER_IN
+ *
+ * @param name Instance name
+ * @param tx_buff Buffer to transfer
+ * @param tx_size Transfer size
+ *
+ * @return Configured variable with total transfer description
+ */
+#define NRF_DRV_USBD_TRANSFER_IN_ZLP(name, tx_buff, tx_size) \
+ NRF_DRV_USBD_TRANSFER_IN_FLAGS( \
+ name, \
+ tx_buff, \
+ tx_size, \
+ NRF_DRV_USBD_TRANSFER_ZLP_FLAG)
+
+/**
+ * @brief Helper macro for declaring OUT transfer item (@ref nrf_drv_usbd_transfer_t)
+ *
+ * @param name Instance name
+ * @param rx_buff Buffer to transfer
+ * @param rx_size Transfer size
+ * */
+#define NRF_DRV_USBD_TRANSFER_OUT(name, rx_buff, rx_size) \
+ const nrf_drv_usbd_transfer_t name = { \
+ .p_data = { .rx = (rx_buff) }, \
+ .size = (rx_size), \
+ .flags = 0 \
+ }
+
+/**
+ * @brief USBD transfer feeder.
+ *
+ * Pointer for a transfer feeder.
+ * Transfer feeder is a feedback function used to prepare a single
+ * TX (Device->Host) endpoint transfer.
+ *
+ * The transfers provided by the feeder must be simple:
+ * - The size of the transfer provided by this function is limited to a single endpoint buffer.
+ * Bigger transfers are not handled automatically in this case.
+ * - Flash transfers are not automatically supported- you must copy them to the RAM buffer before.
+ *
+ * @note
+ * This function may use @ref nrf_drv_usbd_feeder_buffer_get to gain a temporary buffer
+ * that can be used to prepare transfer.
+ *
+ * @param[out] p_next Structure with the data for the next transfer to be filled.
+ * Required only if the function returns true.
+ * @param[in,out] p_context Context variable configured with the transfer.
+ * @param[in] ep_size The endpoint size.
+ *
+ * @retval false The current transfer is the last one - you do not need to call
+ * the function again.
+ * @retval true There is more data to be prepared and when the current transfer
+ * finishes, the feeder function is expected to be called again.
+ */
+typedef bool (*nrf_drv_usbd_feeder_t)(
+ nrf_drv_usbd_ep_transfer_t * p_next,
+ void * p_context,
+ size_t ep_size);
+
+/**
+ * @brief USBD transfer consumer.
+ *
+ * Pointer for a transfer consumer.
+ * Transfer consumer is a feedback function used to prepare a single
+ * RX (Host->Device) endpoint transfer.
+ *
+ * The transfer must provide a buffer big enough to fit the whole data from the endpoint.
+ * Otherwise, the NRF_USBD_EP_OVERLOAD event is generated.
+ *
+ * @param[out] p_next Structure with the data for the next transfer to be filled.
+ * Required only if the function returns true.
+ * @param[in,out] p_context Context variable configured with the transfer.
+ * @param[in] ep_size The endpoint size.
+ * @param[in] data_size Number of received bytes in the endpoint buffer.
+ *
+ * @retval false Current transfer is the last one - you do not need to call
+ * the function again.
+ * @retval true There is more data to be prepared and when current transfer
+ * finishes, the feeder function is expected to be called again.
+ */
+typedef bool (*nrf_drv_usbd_consumer_t)(
+ nrf_drv_usbd_ep_transfer_t * p_next,
+ void * p_context,
+ size_t ep_size,
+ size_t data_size);
+
+/**
+ * @brief Universal transfer handler.
+ *
+ * Union with feeder and consumer function pointer.
+ */
+typedef union
+{
+ nrf_drv_usbd_feeder_t feeder; //!< Feeder function pointer.
+ nrf_drv_usbd_consumer_t consumer; //!< Consumer function pointer.
+}nrf_drv_usbd_handler_t;
+
+/**
+ * @brief USBD transfer descriptor.
+ *
+ * Universal structure that may hold the setup for callback configuration for
+ * IN or OUT type of the transfer.
+ */
+typedef struct
+{
+ nrf_drv_usbd_handler_t handler; //!< Handler for the current transfer, function pointer.
+ void * p_context; //!< Context for the transfer handler.
+}nrf_drv_usbd_handler_desc_t;
+
+/**
+ * @brief Setup packet structure
+ *
+ * Structure that contains interpreted SETUP packet.
+ */
+typedef struct
+{
+ uint8_t bmRequestType; //!< byte 0
+ uint8_t bmRequest; //!< byte 1
+ uint16_t wValue; //!< byte 2
+ uint16_t wIndex; //!< byte 4, 5
+ uint16_t wLength; //!< byte 6, 7
+}nrf_drv_usbd_setup_t;
+
+/**
+ * @brief Library initialization
+ *
+ * @param[in] event_handler Event handler provided by the user.
+ */
+ret_code_t nrf_drv_usbd_init(nrf_drv_usbd_event_handler_t const event_handler);
+
+/**
+ * @brief Library deinitialization
+ */
+ret_code_t nrf_drv_usbd_uninit(void);
+
+/**
+ * @brief Enable the USBD port
+ *
+ * After calling this function USBD peripheral would be enabled.
+ * The USB LDO would be enabled.
+ * Enabled USBD peripheral would request HFCLK.
+ * This function does not enable external oscillator, so if it is not enabled by other part of the
+ * program after enabling USBD driver HFINT would be used for the USBD peripheral.
+ * It is perfectly fine until USBD is started. See @ref nrf_drv_usbd_start.
+ *
+ * In normal situation this function should be called in reaction to USBDETECTED
+ * event from POWER peripheral.
+ *
+ * Interrupts and USB pins pull-up would stay disabled until @ref nrf_drv_usbd_start
+ * function is called.
+ */
+void nrf_drv_usbd_enable(void);
+
+/**
+ * @brief Disable the USBD port
+ *
+ * After calling this function USBD peripheral would be disabled.
+ * No events would be detected or processed by the library.
+ * Clock for the peripheral would be disconnected.
+ */
+void nrf_drv_usbd_disable(void);
+
+/**
+ * @brief Start USB functionality
+ *
+ * After calling this function USBD peripheral should be fully functional
+ * and all new incoming events / interrupts would be processed by the library.
+ *
+ * Also only after calling this function host sees new connected device.
+ *
+ * Call this function when USBD power LDO regulator is ready - on USBPWRRDY event
+ * from POWER peripheral.
+ *
+ * Before USBD interrupts are enabled, external HFXO is requested.
+ *
+ * @param enable_sof The flag that is used to enable SOF processing.
+ * If it is false, SOF interrupt is left disabled and will not be generated.
+ * This improves power saving if SOF is not required.
+ *
+ * @note If the isochronous endpoints are going to be used,
+ * it is required to enable the SOF.
+ * In other case any isochronous endpoint would stay busy
+ * after first transmission.
+ */
+void nrf_drv_usbd_start(bool enable_sof);
+
+/**
+ * @brief Stop USB functionality
+ *
+ * This function disables USBD pull-up and interrupts.
+ *
+ * The HFXO request is released in this function.
+ *
+ * @note
+ * This function can also be used to logically disconnect USB from the HOST that
+ * would force it to enumerate device after calling @ref nrf_drv_usbd_start.
+ */
+void nrf_drv_usbd_stop(void);
+
+/**
+ * @brief Check if driver is initialized
+ *
+ * @retval false Driver is not initialized
+ * @retval true Driver is initialized
+ */
+bool nrf_drv_usbd_is_initialized(void);
+
+/**
+ * @brief Check if driver is enabled
+ *
+ * @retval false Driver is disabled
+ * @retval true Driver is enabled
+ */
+bool nrf_drv_usbd_is_enabled(void);
+
+/**
+ * @brief Check if driver is started
+ *
+ * @retval false Driver is not started
+ * @retval true Driver is started (fully functional)
+ * @note The USBD peripheral interrupt state is checked
+ */
+bool nrf_drv_usbd_is_started(void);
+
+/**
+ * @brief Suspend USBD operation
+ *
+ * The USBD peripheral is forced to go into the low power mode.
+ * The function has to be called in the reaction to @ref NRF_DRV_USBD_EVT_SUSPEND event
+ * when the firmware is ready.
+ *
+ * After successful call of this function most of the USBD registers would be unavailable.
+ *
+ * @note Check returned value for the feedback if suspending was successful.
+ *
+ * @retval true USBD peripheral successfully suspended
+ * @retval false USBD peripheral was not suspended due to resume detection.
+ *
+ */
+bool nrf_drv_usbd_suspend(void);
+
+/**
+ * @brief Start wake up procedure
+ *
+ * The USBD peripheral is forced to quit the low power mode.
+ * After calling this function all the USBD registers would be available.
+ *
+ * The hardware starts measuring time when wake up is possible.
+ * This may take 0-5&nbsp;ms depending on how long the SUSPEND state was kept on the USB line.
+
+ * When NRF_DRV_USBD_EVT_WUREQ event is generated it means that Wake Up signaling has just been
+ * started on the USB lines.
+ *
+ * @note Do not expect only @ref NRF_DRV_USBD_EVT_WUREQ event.
+ * There always may appear @ref NRF_DRV_USBD_EVT_RESUME event.
+ * @note NRF_DRV_USBD_EVT_WUREQ event means that Remote WakeUp signal
+ * has just begun to be generated.
+ * This may take up to 20&nbsp;ms for the bus to become active.
+ *
+ * @retval true WakeUp procedure started.
+ * @retval false No WakeUp procedure started - bus is already active.
+ */
+bool nrf_drv_usbd_wakeup_req(void);
+
+/**
+ * @brief Check if USBD is in SUSPEND mode
+ *
+ * @note This is the information about peripheral itself, not about the bus state.
+ *
+ * @retval true USBD peripheral is suspended
+ * @retval false USBD peripheral is active
+ */
+bool nrf_drv_usbd_suspend_check(void);
+
+/**
+ * @brief Enable only interrupts that should be processed in SUSPEND mode
+ *
+ * Auxiliary function to help with SUSPEND mode integration.
+ * It enables only the interrupts that can be properly processed without stable HFCLK.
+ *
+ * Normally all the interrupts are enabled.
+ * Use this function to suspend interrupt processing that may require stable HFCLK until the
+ * clock is enabled.
+ *
+ * @sa nrf_drv_usbd_active_irq_config
+ */
+void nrf_drv_usbd_suspend_irq_config(void);
+
+/**
+ * @brief Default active interrupt configuration
+ *
+ * Default interrupt configuration.
+ * Use in a pair with @ref nrf_drv_usbd_active_irq_config.
+ *
+ * @sa nrf_drv_usbd_suspend_irq_config
+ */
+void nrf_drv_usbd_active_irq_config(void);
+
+/**
+ * @brief Check the bus state
+ *
+ * This function checks if the bus state is suspended
+ *
+ * @note The value returned by this function changes on SUSPEND and RESUME event processing.
+ *
+ * @retval true USBD bus is suspended
+ * @retval false USBD bus is active
+ */
+bool nrf_drv_usbd_bus_suspend_check(void);
+
+/**
+ * @brief Configure packet size that should be supported by the endpoint
+ *
+ * The real endpoint buffer size is always the same.
+ * This value sets max packet size that would be transmitted over the endpoint.
+ * This is required by the library
+ *
+ * @param[in] ep Endpoint number
+ * @param[in] size Required maximum packet size
+ *
+ * @note Endpoint size is always set to @ref NRF_DRV_USBD_EPSIZE or @ref NRF_DRV_USBD_ISOSIZE / 2
+ * when @ref nrf_drv_usbd_ep_enable function is called.
+ */
+void nrf_drv_usbd_ep_max_packet_size_set(nrf_drv_usbd_ep_t ep, uint16_t size);
+
+/**
+ * @brief Get configured endpoint packet size
+ *
+ * Function to get configured endpoint size on the buffer.
+ *
+ * @param[in] ep Endpoint number
+ *
+ * @return Maximum pocket size configured on selected endpoint
+ */
+uint16_t nrf_drv_usbd_ep_max_packet_size_get(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Check if the selected endpoint is enabled.
+ *
+ * @param ep Endpoint number to check.
+ *
+ * @retval true Endpoint is enabled.
+ * @retval false Endpoint is disabled.
+ */
+bool nrf_drv_usbd_ep_enable_check(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Enable selected endpoint
+ *
+ * This function enables endpoint itself and its interrupts.
+ * @param ep Endpoint number to enable
+ *
+ * @note
+ * Max packet size is set to endpoint default maximum value.
+ *
+ * @sa nrf_drv_usbd_ep_max_packet_size_set
+ */
+void nrf_drv_usbd_ep_enable(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Disable selected endpoint
+ *
+ * This function disables endpoint itself and its interrupts.
+ * @param ep Endpoint number to disable
+ */
+void nrf_drv_usbd_ep_disable(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Disable all endpoints except for EP0
+ *
+ * Disable all endpoints that can be disabled in USB device while it is still active.
+ */
+void nrf_drv_usbd_ep_default_config(void);
+
+/**
+ * @brief Start sending data over endpoint
+ *
+ * Function initializes endpoint transmission.
+ * This is asynchronous function - it finishes immediately after configuration
+ * for transmission is prepared.
+ *
+ * @note Data buffer pointed by p_data have to be kept active till
+ * @ref NRF_DRV_USBD_EVT_EPTRANSFER event is generated.
+ *
+ * @param[in] ep Endpoint number.
+ * For IN endpoint sending would be initiated.
+ * For OUT endpoint receiving would be initiated.
+ * @param[in] p_transfer
+ *
+ * @retval NRF_ERROR_BUSY Selected endpoint is pending.
+ * @retval NRF_ERROR_INVALID_ADDR Unexpected transfer on EPIN0 or EPOUT0.
+ * @retval NRF_ERROR_FORBIDDEN Endpoint stalled.
+ * @retval NRF_SUCCESS Transfer queued or started.
+ */
+ret_code_t nrf_drv_usbd_ep_transfer(
+ nrf_drv_usbd_ep_t ep,
+ nrf_drv_usbd_transfer_t const * const p_transfer);
+
+/**
+ * @brief Start sending data over the endpoint using the transfer handler function.
+ *
+ * This function initializes an endpoint transmission.
+ * Just before data is transmitted, the transfer handler
+ * is called and it prepares a data chunk.
+ *
+ * @param[in] ep Endpoint number.
+ * For an IN endpoint, sending is initiated.
+ * For an OUT endpoint, receiving is initiated.
+ * @param p_handler Transfer handler - feeder for IN direction and consumer for
+ * OUT direction.
+ *
+ * @retval NRF_ERROR_BUSY Selected endpoint is pending.
+ * @retval NRF_ERROR_INVALID_ADDR Unexpected transfer on EPIN0 or EPOUT0.
+ * @retval NRF_ERROR_FORBIDDEN Endpoint stalled.
+ * @retval NRF_SUCCESS Transfer queued or started.
+ */
+ret_code_t nrf_drv_usbd_ep_handled_transfer(
+ nrf_drv_usbd_ep_t ep,
+ nrf_drv_usbd_handler_desc_t const * const p_handler);
+
+/**
+ * @brief Get the temporary buffer to be used by the feeder.
+ *
+ * This buffer is used for TX transfers and it can be reused automatically
+ * when the transfer is finished.
+ * Use it for transfer preparation.
+ *
+ * May be used inside the feeder configured in @ref nrf_drv_usbd_ep_handled_transfer.
+ *
+ * @return Pointer to the buffer that can be used temporarily.
+ *
+ * @sa NRF_DRV_USBD_FEEDER_BUFFER_SIZE
+ */
+void * nrf_drv_usbd_feeder_buffer_get(void);
+
+/**
+ * @brief Get the information about last finished or current transfer
+ *
+ * Function returns the status of the last buffer set for transfer on selected endpoint.
+ * The status considers last buffer set by @ref nrf_drv_usbd_ep_transfer function or
+ * by transfer callback function.
+ *
+ * @param[in] ep Endpoint number.
+ * @param[out] p_size Information about the current/last transfer size.
+ *
+ * @retval NRF_SUCCESS Transfer already finished
+ * @retval NRF_ERROR_BUSY Ongoing transfer
+ * @retval NRF_ERROR_DATA_SIZE Too much of data received that cannot fit into buffer and cannot be splited into chunks.
+ * This may happen if buffer size is not a multiplication of endpoint buffer size.
+ */
+ret_code_t nrf_drv_usbd_ep_status_get(nrf_drv_usbd_ep_t ep, size_t * p_size);
+
+/**
+ * @brief Get number of received bytes
+ *
+ * Get the number of received bytes.
+ * The function behavior is undefined when called on IN endpoint.
+ *
+ * @param ep Endpoint number.
+ *
+ * @return Number of received bytes
+ */
+size_t nrf_drv_usbd_epout_size_get(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Check if endpoint buffer is ready or is under USB IP control
+ *
+ * Function to test if endpoint is busy.
+ * Endpoint that is busy cannot be accessed by MCU.
+ * It means that:
+ * - OUT (TX) endpoint: Last uploaded data is still in endpoint and is waiting
+ * to be received by the host.
+ * - IN (RX) endpoint: Endpoint is ready to receive data from the host
+ * and the endpoint does not have any data.
+ * When endpoint is not busy:
+ * - OUT (TX) endpoint: New data can be uploaded.
+ * - IN (RX) endpoint: New data can be downloaded using @ref nrf_drv_usbd_ep_transfer
+ * function.
+ */
+bool nrf_drv_usbd_ep_is_busy(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Stall endpoint
+ *
+ * Stall endpoit to send error information during next transfer request from
+ * the host.
+ *
+ * @note To stall endpoint it is safer to use @ref nrf_drv_usbd_setup_stall
+ * @note Stalled endpoint would not be cleared when DMA transfer finishes.
+ *
+ * @param ep Endpoint number to stall
+ *
+ */
+void nrf_drv_usbd_ep_stall(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Clear stall flag on endpoint
+ *
+ * This function clears endpoint that is stalled.
+ * @note
+ * If it is OUT endpoint (receiving) it would be also prepared for reception.
+ * It means that busy flag would be set.
+ * @note
+ * In endpoint (transmitting) would not be cleared - it gives possibility to
+ * write new data before transmitting.
+ */
+void nrf_drv_usbd_ep_stall_clear(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Check if endpoint is stalled
+ *
+ * This function gets stall state of selected endpoint
+ *
+ * @param ep Endpoint number to check
+ */
+bool nrf_drv_usbd_ep_stall_check(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Clear current endpoint data toggle
+ *
+ * @param ep Endpoint number to clear
+ */
+void nrf_drv_usbd_ep_dtoggle_clear(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Get parsed setup data
+ *
+ * Function fills the parsed setup data structure.
+ *
+ * @param[out] p_setup Pointer to data structure that would be filled by
+ * parsed data.
+ */
+void nrf_drv_usbd_setup_get(nrf_drv_usbd_setup_t * const p_setup);
+
+/**
+ * @brief Clear only for data transmission on setup endpoint
+ *
+ * This function may be called if any more data in control write transfer is expected.
+ * Clears only OUT endpoint to be able to take another OUT data token.
+ * It does not allow STATUS stage.
+ * @sa nrf_drv_usbd_setup_clear
+ */
+void nrf_drv_usbd_setup_data_clear(void);
+
+/**
+ * @brief Clear setup endpoint
+ *
+ * This function acknowledges setup when SETUP command was received and processed.
+ * It has to be called if no data respond for the SETUP command is sent.
+ */
+void nrf_drv_usbd_setup_clear(void);
+
+/**
+ * @brief Stall setup endpoint
+ *
+ * Mark and error on setup endpoint.
+ */
+void nrf_drv_usbd_setup_stall(void);
+
+/**
+* @note
+* This function locks interrupts that may be costly.
+* It is good idea to test if the endpoint is still busy before calling this function:
+* @code
+ (m_ep_dma_waiting & (1U << ep2bit(ep)))
+* @endcode
+* This function would check it again, but it makes it inside critical section.
+*/
+void nrf_drv_usbd_ep_abort(nrf_drv_usbd_ep_t ep);
+
+/**
+ * @brief Get the information about expected transfer SETUP data direction
+ *
+ * Function returns the information about last expected transfer direction.
+ *
+ * @retval NRF_DRV_USBD_EPOUT0 Expecting OUT (Host->Device) direction or no data
+ * @retval NRF_DRV_USBD_EPIN0 Expecting IN (Device->Host) direction
+ */
+nrf_drv_usbd_ep_t nrf_drv_usbd_last_setup_dir_get(void);
+
+/**
+ * @brief Drop transfer on OUT endpoint
+ *
+ * @param[in] ep OUT endpoint ID
+ */
+void nrf_drv_usbd_transfer_out_drop(nrf_drv_usbd_ep_t ep);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+#endif /* NRF_DRV_USBD_H__ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd_errata.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd_errata.h
new file mode 100644
index 0000000..ad24f3c
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/drivers_nrf/usbd/nrf_drv_usbd_errata.h
@@ -0,0 +1,193 @@
+/**
+ * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NRF_DRV_USBD_ERRATA_H__
+#define NRF_DRV_USBD_ERRATA_H__
+
+#include <stdbool.h>
+/**
+ * @defgroup nrf_drv_usbd_errata Functions to check if selected PAN is present in current chip
+ * @{
+ * @ingroup nrf_drv_usbd
+ *
+ * Functions here are checking the presence of an error in current chip.
+ * The checking is done at runtime based on the microcontroller version.
+ * This file is subject to removal when nRF51840 prototype support is removed.
+ */
+
+#ifndef NRF_DRV_USBD_ERRATA_ENABLE
+/**
+ * @brief The constant that informs if errata should be enabled at all
+ *
+ * If this constant is set to 0, all the Errata bug fixes will be automatically disabled.
+ */
+#define NRF_DRV_USBD_ERRATA_ENABLE 1
+#endif
+
+/**
+ * @brief Internal auxiliary function to check if the program is running on NRF52840 chip
+ * @retval true It is NRF52480 chip
+ * @retval false It is other chip
+ */
+static inline bool nrf_drv_usbd_errata_type_52840(void)
+{
+ return ((((*(uint32_t *)0xF0000FE0) & 0xFF) == 0x08) &&
+ (((*(uint32_t *)0xF0000FE4) & 0x0F) == 0x0));
+}
+
+/**
+ * @brief Internal auxiliary function to check if the program is running on first sample of
+ * NRF52840 chip
+ * @retval true It is NRF52480 chip and it is first sample version
+ * @retval false It is other chip
+ */
+static inline bool nrf_drv_usbd_errata_type_52840_proto1(void)
+{
+ return ( nrf_drv_usbd_errata_type_52840() &&
+ ( ((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x00 ) &&
+ ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) );
+}
+
+/**
+ * @brief Internal auxiliary function to check if the program is running on first final product of
+ * NRF52840 chip
+ * @retval true It is NRF52480 chip and it is first final product
+ * @retval false It is other chip
+ */
+static inline bool nrf_drv_usbd_errata_type_52840_fp1(void)
+{
+ return ( nrf_drv_usbd_errata_type_52840() &&
+ ( ((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x10 ) &&
+ ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) );
+}
+
+/**
+ * @brief Function to check if chip requires errata 104
+ *
+ * Errata: USBD: EPDATA event is not always generated.
+ *
+ * @retval true Errata should be implemented
+ * @retval false Errata should not be implemented
+ */
+static inline bool nrf_drv_usbd_errata_104(void)
+{
+ return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_proto1();
+}
+
+/**
+ * @brief Function to check if chip requires errata 154
+ *
+ * Errata: During setup read/write transfer USBD acknowledges setup stage without SETUP task.
+ *
+ * @retval true Errata should be implemented
+ * @retval false Errata should not be implemented
+ */
+static inline bool nrf_drv_usbd_errata_154(void)
+{
+ return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_proto1();
+}
+
+/**
+ * @brief Function to check if chip requires errata 166
+ *
+ * Errata: ISO double buffering not functional
+ *
+ * @retval true Errata should be implemented
+ * @retval false Errata should not be implemented
+ */
+static inline bool nrf_drv_usbd_errata_166(void)
+{
+ return NRF_DRV_USBD_ERRATA_ENABLE && true;
+}
+
+/**
+ * @brief Function to check if chip requires errata 171
+ *
+ * Errata: USBD might not reach its active state.
+ *
+ * @retval true Errata should be implemented
+ * @retval false Errata should not be implemented
+ */
+static inline bool nrf_drv_usbd_errata_171(void)
+{
+ return NRF_DRV_USBD_ERRATA_ENABLE && true;
+}
+
+/**
+ * @brief Function to check if chip requires errata 187
+ *
+ * Errata: USB cannot be enabled
+ *
+ * @retval true Errata should be implemented
+ * @retval false Errata should not be implemented
+ */
+static inline bool nrf_drv_usbd_errata_187(void)
+{
+ return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_fp1();
+}
+
+/**
+ * @brief Function to check if chip requires errata ???
+ *
+ * Errata: SIZE.EPOUT not writable
+ *
+ * @retval true Errata should be implemented
+ * @retval false Errata should not be implemented
+ */
+static inline bool nrf_drv_usbd_errata_sizeepout_rw(void)
+{
+ return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_proto1();
+}
+
+/**
+ * @brief Function to check if chip requires errata 199
+ *
+ * Errata: USBD cannot receive tasks during DMA
+ *
+ * @retval true Errata should be implemented
+ * @retval false Errata should not be implemented
+ */
+static inline bool nrf_drv_usb_errata_199(void)
+{
+ return NRF_DRV_USBD_ERRATA_ENABLE && true;
+}
+
+/** @} */
+#endif /* NRF_DRV_USBD_ERRATA_H__ */