From 44cb528a7adbcc9b1371d7932578b1105a479cfb Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 2 Oct 2017 19:14:33 +0200 Subject: [PATCH] [nRF52840] add USB CDC ACM support (#2215) --- examples/Makefile-nrf52840 | 4 + examples/platforms/nrf52840/Makefile.am | 23 +- examples/platforms/nrf52840/README.md | 11 + examples/platforms/nrf52840/alarm.c | 2 - examples/platforms/nrf52840/misc.c | 4 + examples/platforms/nrf52840/platform-config.h | 65 + examples/platforms/nrf52840/uart.c | 4 + examples/platforms/nrf52840/usb-cdc-uart.c | 372 +++ third_party/NordicSemiconductor/README.md | 16 +- .../dependencies/app_error.h | 239 ++ .../dependencies/app_error_weak.h | 85 + .../dependencies/app_util.h | 1060 ++++++++ .../dependencies/app_util_platform.c | 127 + .../dependencies/app_util_platform.h | 262 ++ .../dependencies/nordic_common.h | 211 ++ .../dependencies/nrf_atomic.h | 495 ++++ .../dependencies/nrf_atomic_internal.h | 234 ++ .../dependencies/nrf_delay.h | 268 ++ .../dependencies/nrf_error.h | 87 + .../dependencies/nrf_log.h | 234 ++ .../dependencies/nrf_log_internal.h | 534 ++++ .../dependencies/nrf_section.h | 191 ++ .../dependencies/sdk_common.h | 77 + .../dependencies/sdk_config.h | 254 ++ .../dependencies/sdk_errors.h | 152 ++ .../dependencies/sdk_macros.h | 191 ++ .../NordicSemiconductor/dependencies/sdk_os.h | 76 + .../NordicSemiconductor/device/nrf52840.h | 191 +- .../device/nrf52840_bitfields.h | 510 ++-- .../device/nrf52840_peripherals.h | 70 +- .../drivers/clock/nrf_drv_clock.c | 615 ++++- .../drivers/clock/nrf_drv_clock.h | 210 +- .../drivers/common/nrf_drv_common.c | 297 +++ .../drivers/common/nrf_drv_common.h | 357 +++ .../drivers/power/nrf_drv_power.c | 477 ++++ .../drivers/power/nrf_drv_power.h | 371 +++ .../drivers/systick/nrf_drv_systick.c | 172 ++ .../drivers/systick/nrf_drv_systick.h | 133 + .../drivers/usbd/nrf_drv_usbd.c | 2179 +++++++++++++++++ .../drivers/usbd/nrf_drv_usbd.h | 925 +++++++ .../drivers/usbd/nrf_drv_usbd_errata.h | 133 + .../NordicSemiconductor/hal/nrf_power.h | 1065 ++++++++ .../NordicSemiconductor/hal/nrf_systick.h | 184 ++ .../NordicSemiconductor/hal/nrf_usbd.h | 1422 +++++++++++ .../libraries/atfifo/nrf_atfifo.c | 160 ++ .../libraries/atfifo/nrf_atfifo.h | 408 +++ .../libraries/atfifo/nrf_atfifo_internal.h | 577 +++++ .../libraries/usb/app_usbd.c | 1356 ++++++++++ .../libraries/usb/app_usbd.h | 563 +++++ .../libraries/usb/app_usbd_class_base.h | 841 +++++++ .../libraries/usb/app_usbd_core.c | 1086 ++++++++ .../libraries/usb/app_usbd_core.h | 297 +++ .../libraries/usb/app_usbd_descriptor.h | 335 +++ .../libraries/usb/app_usbd_langid.h | 286 +++ .../libraries/usb/app_usbd_request.h | 355 +++ .../libraries/usb/app_usbd_string_desc.c | 188 ++ .../libraries/usb/app_usbd_string_desc.h | 119 + .../libraries/usb/app_usbd_types.h | 232 ++ .../usb/class/cdc/acm/app_usbd_cdc_acm.c | 735 ++++++ .../usb/class/cdc/acm/app_usbd_cdc_acm.h | 295 +++ .../class/cdc/acm/app_usbd_cdc_acm_internal.h | 221 ++ .../usb/class/cdc/app_usbd_cdc_desc.h | 208 ++ .../usb/class/cdc/app_usbd_cdc_types.h | 360 +++ .../usb/config/app_usbd_string_config.h | 130 + .../libraries/usb/nordic_cdc_acm_example.inf | 102 + 65 files changed, 23004 insertions(+), 439 deletions(-) create mode 100644 examples/platforms/nrf52840/usb-cdc-uart.c create mode 100644 third_party/NordicSemiconductor/dependencies/app_error.h create mode 100644 third_party/NordicSemiconductor/dependencies/app_error_weak.h create mode 100644 third_party/NordicSemiconductor/dependencies/app_util.h create mode 100644 third_party/NordicSemiconductor/dependencies/app_util_platform.c create mode 100644 third_party/NordicSemiconductor/dependencies/app_util_platform.h create mode 100644 third_party/NordicSemiconductor/dependencies/nordic_common.h create mode 100644 third_party/NordicSemiconductor/dependencies/nrf_atomic.h create mode 100644 third_party/NordicSemiconductor/dependencies/nrf_atomic_internal.h create mode 100644 third_party/NordicSemiconductor/dependencies/nrf_delay.h create mode 100644 third_party/NordicSemiconductor/dependencies/nrf_error.h create mode 100644 third_party/NordicSemiconductor/dependencies/nrf_log.h create mode 100644 third_party/NordicSemiconductor/dependencies/nrf_log_internal.h create mode 100644 third_party/NordicSemiconductor/dependencies/nrf_section.h create mode 100644 third_party/NordicSemiconductor/dependencies/sdk_common.h create mode 100644 third_party/NordicSemiconductor/dependencies/sdk_config.h create mode 100644 third_party/NordicSemiconductor/dependencies/sdk_errors.h create mode 100644 third_party/NordicSemiconductor/dependencies/sdk_macros.h create mode 100644 third_party/NordicSemiconductor/dependencies/sdk_os.h create mode 100644 third_party/NordicSemiconductor/drivers/common/nrf_drv_common.c create mode 100644 third_party/NordicSemiconductor/drivers/common/nrf_drv_common.h create mode 100644 third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c create mode 100644 third_party/NordicSemiconductor/drivers/power/nrf_drv_power.h create mode 100644 third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.c create mode 100644 third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h create mode 100644 third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.c create mode 100644 third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.h create mode 100644 third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd_errata.h create mode 100644 third_party/NordicSemiconductor/hal/nrf_power.h create mode 100644 third_party/NordicSemiconductor/hal/nrf_systick.h create mode 100644 third_party/NordicSemiconductor/hal/nrf_usbd.h create mode 100644 third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c create mode 100644 third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.h create mode 100644 third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo_internal.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd.c create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_class_base.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_core.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_descriptor.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_langid.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_request.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/app_usbd_types.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c create mode 100644 third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm_internal.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_desc.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_types.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/config/app_usbd_string_config.h create mode 100644 third_party/NordicSemiconductor/libraries/usb/nordic_cdc_acm_example.inf diff --git a/examples/Makefile-nrf52840 b/examples/Makefile-nrf52840 index a771e35d5..0f173c063 100644 --- a/examples/Makefile-nrf52840 +++ b/examples/Makefile-nrf52840 @@ -85,6 +85,10 @@ else COMMONCFLAGS += -DOPENTHREAD_CONFIG_LOG_OUTPUT=OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED endif +ifeq ($(USB),1) +COMMONCFLAGS += -DUSB_CDC_AS_SERIAL_TRANSPORT=1 +endif + CPPFLAGS += \ $(COMMONCFLAGS) \ $(target_CPPFLAGS) \ diff --git a/examples/platforms/nrf52840/Makefile.am b/examples/platforms/nrf52840/Makefile.am index e0e719fdc..dd03df530 100644 --- a/examples/platforms/nrf52840/Makefile.am +++ b/examples/platforms/nrf52840/Makefile.am @@ -45,10 +45,20 @@ COMMONCPPFLAGS -I$(top_srcdir)/third_party/NordicSemiconductor \ -I$(top_srcdir)/third_party/NordicSemiconductor/cmsis \ -I$(top_srcdir)/third_party/NordicSemiconductor/device \ + -I$(top_srcdir)/third_party/NordicSemiconductor/dependencies \ -I$(top_srcdir)/third_party/NordicSemiconductor/drivers/clock \ + -I$(top_srcdir)/third_party/NordicSemiconductor/drivers/common \ -I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio \ -I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal \ + -I$(top_srcdir)/third_party/NordicSemiconductor/drivers/power \ + -I$(top_srcdir)/third_party/NordicSemiconductor/drivers/systick \ + -I$(top_srcdir)/third_party/NordicSemiconductor/drivers/usbd \ -I$(top_srcdir)/third_party/NordicSemiconductor/hal \ + -I$(top_srcdir)/third_party/NordicSemiconductor/libraries/atfifo \ + -I$(top_srcdir)/third_party/NordicSemiconductor/libraries/usb \ + -I$(top_srcdir)/third_party/NordicSemiconductor/libraries/usb/config \ + -I$(top_srcdir)/third_party/NordicSemiconductor/libraries/usb/class/cdc \ + -I$(top_srcdir)/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm \ -I$(top_srcdir)/third_party/NordicSemiconductor/segger_rtt \ $(NULL) @@ -59,13 +69,14 @@ PLATFORM_COMMON_SOURCES logging.c \ misc.c \ platform.c \ - uart.c \ platform-config.h \ platform-fem.h \ platform-nrf5.h \ radio.c \ random.c \ temp.c \ + uart.c \ + usb-cdc-uart.c \ $(NULL) SINGLEPHY_SOURCES = \ @@ -140,7 +151,17 @@ libopenthread_nrf52840_a_SOURCES $(PLATFORM_SOURCES) \ $(NORDICSEMI_SOURCES) \ $(SINGLEPHY_SOURCES) \ + @top_builddir@/third_party/NordicSemiconductor/dependencies/app_util_platform.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.c \ + @top_builddir@/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c \ + @top_builddir@/third_party/NordicSemiconductor/libraries/usb/app_usbd.c \ + @top_builddir@/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c \ + @top_builddir@/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c \ + @top_builddir@/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c \ $(NULL) libopenthread_nrf52840_sdk_a_CPPFLAGS = \ diff --git a/examples/platforms/nrf52840/README.md b/examples/platforms/nrf52840/README.md index dc28c5cd4..7739f5a44 100644 --- a/examples/platforms/nrf52840/README.md +++ b/examples/platforms/nrf52840/README.md @@ -37,6 +37,17 @@ files using `arm-none-eabi-objcopy`: $ arm-none-eabi-objcopy -O ihex ot-cli-ftd ot-cli-ftd.hex ``` +## Native USB support + +You can build the libraries with support for native USB CDC ACM as a serial transport. +To do so, build the libraries with the following parameter: +``` +$ make -f examples/Makefile-nrf52840 USB=1 +``` + +Note, that if Windows 7 or earlier is used, an additional USB CDC driver has to be loaded. +It can be found in third_party/NordicSemiconductor/libraries/usb/nordic_cdc_acm_example.inf + ## Flashing the binaries Flash the compiled binaries onto nRF52840 using `nrfjprog` which is diff --git a/examples/platforms/nrf52840/alarm.c b/examples/platforms/nrf52840/alarm.c index fdbfce7ab..6d7cd7f1c 100644 --- a/examples/platforms/nrf52840/alarm.c +++ b/examples/platforms/nrf52840/alarm.c @@ -57,8 +57,6 @@ #define RTC_FREQUENCY 32768ULL -#define CEIL_DIV(A, B) (((A) + (B) - 1ULL) / (B)) - #define US_PER_MS 1000ULL #define US_PER_S 1000000ULL #define US_PER_TICK CEIL_DIV(US_PER_S, RTC_FREQUENCY) diff --git a/examples/platforms/nrf52840/misc.c b/examples/platforms/nrf52840/misc.c index 99e594db5..da3175fd8 100644 --- a/examples/platforms/nrf52840/misc.c +++ b/examples/platforms/nrf52840/misc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -69,6 +70,9 @@ void nrf5MiscDeinit(void) void otPlatReset(otInstance *aInstance) { (void)aInstance; + + PlatformDeinit(); + NVIC_SystemReset(); } diff --git a/examples/platforms/nrf52840/platform-config.h b/examples/platforms/nrf52840/platform-config.h index df9313142..290f358e1 100644 --- a/examples/platforms/nrf52840/platform-config.h +++ b/examples/platforms/nrf52840/platform-config.h @@ -52,7 +52,9 @@ * UART Instance. * */ +#ifndef UART_INSTANCE #define UART_INSTANCE NRF_UART0 +#endif /** * @def UART_PARITY @@ -64,7 +66,9 @@ * \ref NRF_UART_PARITY_INCLUDED - Parity bit is present. * */ +#ifndef UART_PARITY #define UART_PARITY NRF_UART_PARITY_EXCLUDED +#endif /** * @def UART_HWFC @@ -76,7 +80,9 @@ * \ref NRF_UART_HWFC_DISABLED - HW Flow control disabled. * */ +#ifndef UART_HWFC #define UART_HWFC NRF_UART_HWFC_ENABLED +#endif /** * @def UART_BAUDRATE @@ -102,7 +108,9 @@ * \ref NRF_UART_BAUDRATE_1000000 - 1000000 baud. * */ +#ifndef UART_BAUDRATE #define UART_BAUDRATE NRF_UART_BAUDRATE_115200 +#endif /** * @def UART_IRQN @@ -110,7 +118,9 @@ * UART Interrupt number. * */ +#ifndef UART_IRQN #define UART_IRQN UARTE0_UART0_IRQn +#endif /** * @def UART_IRQ_PRIORITY @@ -118,7 +128,9 @@ * UART Interrupt priority. * */ +#ifndef UART_IRQ_PRIORITY #define UART_IRQ_PRIORITY 6 +#endif /** * @def UART_RX_BUFFER_SIZE @@ -126,7 +138,9 @@ * UART Receive buffer size. * */ +#ifndef UART_RX_BUFFER_SIZE #define UART_RX_BUFFER_SIZE 256 +#endif /** * @def UART_PIN_TX @@ -134,7 +148,9 @@ * UART TX Pin. * */ +#ifndef UART_PIN_TX #define UART_PIN_TX 6 +#endif /** * @def UART_PIN_RX @@ -142,7 +158,9 @@ * UART RX Pin. * */ +#ifndef UART_PIN_RX #define UART_PIN_RX 8 +#endif /** * @def UART_PIN_CTS @@ -150,7 +168,9 @@ * UART CTS Pin. * */ +#ifndef UART_PIN_CTS #define UART_PIN_CTS 7 +#endif /** * @def UART_PIN_RTS @@ -158,7 +178,9 @@ * UART RTS Pin. * */ +#ifndef UART_PIN_RTS #define UART_PIN_RTS 5 +#endif /******************************************************************************* * @section Alarm Driver Configuration. @@ -170,7 +192,9 @@ * RTC Instance. * */ +#ifndef RTC_INSTANCE #define RTC_INSTANCE NRF_RTC2 +#endif /** * @def RTC_IRQ_HANDLER @@ -178,7 +202,9 @@ * RTC interrupt handler name * */ +#ifndef RTC_IRQ_HANDLER #define RTC_IRQ_HANDLER RTC2_IRQHandler +#endif /** * @def RTC_IRQN @@ -186,7 +212,9 @@ * RTC Interrupt number. * */ +#ifndef RTC_IRQN #define RTC_IRQN RTC2_IRQn +#endif /** * @def RTC_IRQ_PRIORITY @@ -194,7 +222,9 @@ * RTC Interrupt priority. * */ +#ifndef RTC_IRQ_PRIORITY #define RTC_IRQ_PRIORITY 6 +#endif /******************************************************************************* * @section Random Number Generator Driver Configuration. @@ -206,7 +236,9 @@ * True Random Number Generator buffer size. * */ +#ifndef RNG_BUFFER_SIZE #define RNG_BUFFER_SIZE 64 +#endif /** * @def RNG_IRQ_PRIORITY @@ -214,7 +246,9 @@ * RNG Interrupt priority. * */ +#ifndef RNG_IRQ_PRIORITY #define RNG_IRQ_PRIORITY 6 +#endif /******************************************************************************* * @section Log module configuration. @@ -226,7 +260,9 @@ * RTT's buffer index. * */ +#ifndef LOG_RTT_BUFFER_INDEX #define LOG_RTT_BUFFER_INDEX 0 +#endif /** * @def LOG_RTT_BUFFER_NAME @@ -234,7 +270,9 @@ * RTT's name. * */ +#ifndef LOG_RTT_BUFFER_NAME #define LOG_RTT_BUFFER_NAME "Terminal" +#endif /** * @def LOG_RTT_BUFFER_SIZE @@ -242,7 +280,9 @@ * LOG RTT's buffer size. * */ +#ifndef LOG_RTT_BUFFER_SIZE #define LOG_RTT_BUFFER_SIZE 256 +#endif /** * @def LOG_RTT_COLOR_ENABLE @@ -250,7 +290,9 @@ * Enable colors on RTT Viewer. * */ +#ifndef LOG_RTT_COLOR_ENABLE #define LOG_RTT_COLOR_ENABLE 1 +#endif /** * @def LOG_PARSE_BUFFER_SIZE @@ -259,7 +301,9 @@ * stack. * */ +#ifndef LOG_PARSE_BUFFER_SIZE #define LOG_PARSE_BUFFER_SIZE 128 +#endif /** * @def LOG_TIMESTAMP_ENABLE @@ -267,6 +311,27 @@ * Enable timestamp in the logs. * */ +#ifndef LOG_TIMESTAMP_ENABLE #define LOG_TIMESTAMP_ENABLE 1 +#endif + +/** + * @def USB_INITIAL_DELAY_MS + * + * Init delay for USB driver, used when software reset was detected to help OS to re-enumerate the device. + * + */ +#ifndef USB_INITIAL_DELAY_MS +#define USB_INITIAL_DELAY_MS 600 +#endif + +/** + * @def USB_CDC_AS_SERIAL_TRANSPORT + * + * Use USB CDC driver for serial communication. + */ +#ifndef USB_CDC_AS_SERIAL_TRANSPORT +#define USB_CDC_AS_SERIAL_TRANSPORT 0 +#endif #endif // PLATFORM_CONFIG_H_ diff --git a/examples/platforms/nrf52840/uart.c b/examples/platforms/nrf52840/uart.c index e9836dc4e..82c69d9bd 100644 --- a/examples/platforms/nrf52840/uart.c +++ b/examples/platforms/nrf52840/uart.c @@ -49,6 +49,8 @@ #include #include "platform-nrf5.h" +#if (USB_CDC_AS_SERIAL_TRANSPORT == 0) + /** * UART TX buffer variables. */ @@ -288,6 +290,8 @@ void UARTE0_UART0_IRQHandler(void) } } +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 0 + /** * The UART driver weak functions definition. * diff --git a/examples/platforms/nrf52840/usb-cdc-uart.c b/examples/platforms/nrf52840/usb-cdc-uart.c new file mode 100644 index 000000000..d1605bc97 --- /dev/null +++ b/examples/platforms/nrf52840/usb-cdc-uart.c @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * 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 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 the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 + * This file implements the OpenThread platform abstraction for UART communication over USB CDC. + * + */ + +#pragma GCC diagnostic ignored "-Wpedantic" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "platform-nrf5.h" + +#include "drivers/clock/nrf_drv_clock.h" +#include "drivers/power/nrf_drv_power.h" +#include "libraries/usb/app_usbd.h" +#include "libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h" + +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) + +static void cdcAcmUserEventHandler(app_usbd_class_inst_t const *aInstance, + app_usbd_cdc_acm_user_event_t aEvent); + +#define CDC_ACM_COMM_INTERFACE 0 +#define CDC_ACM_COMM_EPIN NRF_DRV_USBD_EPIN2 + +#define CDC_ACM_DATA_INTERFACE 1 +#define CDC_ACM_DATA_EPIN NRF_DRV_USBD_EPIN1 +#define CDC_ACM_DATA_EPOUT NRF_DRV_USBD_EPOUT1 + +#define SERIAL_NUMBER_STRING_SIZE 16 + +#define CDC_ACM_INTERFACES_CONFIG() \ + APP_USBD_CDC_ACM_CONFIG(CDC_ACM_COMM_INTERFACE, \ + CDC_ACM_COMM_EPIN, \ + CDC_ACM_DATA_INTERFACE, \ + CDC_ACM_DATA_EPIN, \ + CDC_ACM_DATA_EPOUT) + + +static const uint8_t sCdcAcmClassDescriptors[] = +{ + APP_USBD_CDC_ACM_DEFAULT_DESC( + CDC_ACM_COMM_INTERFACE, + CDC_ACM_COMM_EPIN, + CDC_ACM_DATA_INTERFACE, + CDC_ACM_DATA_EPIN, + CDC_ACM_DATA_EPOUT) +}; + +APP_USBD_CDC_ACM_GLOBAL_DEF(sAppCdcAcm, + CDC_ACM_INTERFACES_CONFIG(), + cdcAcmUserEventHandler, + sCdcAcmClassDescriptors); + +// Rx buffer length must by multiple of NRF_DRV_USBD_EPSIZE. +static char sRxBuffer[NRF_DRV_USBD_EPSIZE * ((UART_RX_BUFFER_SIZE + NRF_DRV_USBD_EPSIZE - 1) / NRF_DRV_USBD_EPSIZE)]; + +static volatile struct +{ + const uint8_t *mTxBuffer; + uint16_t mTxSize; + size_t mReceivedDataSize; + bool mUartEnabled; + bool mLastConnectionStatus; + bool mConnected; + bool mReady; + bool mTransferDone; + bool mReceiveDone; +} sUsbState; + +uint16_t gExternSerialNumber[SERIAL_NUMBER_STRING_SIZE + 1]; + +static void serialNumberStringCreate(void) +{ + gExternSerialNumber[0] = (uint16_t)APP_USBD_DESCRIPTOR_STRING << 8 | sizeof(gExternSerialNumber); + + uint32_t deviceIdHi = NRF_FICR->DEVICEID[1]; + uint32_t deviceIdLo = NRF_FICR->DEVICEID[0]; + + uint64_t deviceId = (((uint64_t)deviceIdHi) << 32) | deviceIdLo; + + for (size_t i = 1; i < SERIAL_NUMBER_STRING_SIZE + 1; ++i) + { + char tmp[2]; + snprintf(tmp, sizeof(tmp), "%x", (unsigned int)(deviceId & 0xF)); + gExternSerialNumber[i] = tmp[0]; + deviceId >>= 4; + } +} + +static void cdcAcmUserEventHandler(app_usbd_class_inst_t const *aCdcAcmInstance, + app_usbd_cdc_acm_user_event_t aEvent) +{ + app_usbd_cdc_acm_t const *cdcAcmClass = app_usbd_cdc_acm_class_get(aCdcAcmInstance); + + switch (aEvent) + { + case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN: + // Setup first transfer. + (void)app_usbd_cdc_acm_read(&sAppCdcAcm, sRxBuffer, sizeof(sRxBuffer)); + break; + + case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE: + break; + + case APP_USBD_CDC_ACM_USER_EVT_TX_DONE: + sUsbState.mTransferDone = true; + break; + + case APP_USBD_CDC_ACM_USER_EVT_RX_DONE: + sUsbState.mReceiveDone = true; + // Get amount of data received. + sUsbState.mReceivedDataSize = app_usbd_cdc_acm_rx_size(cdcAcmClass); + break; + + default: + break; + } +} + +static void usbdUserEventHandler(app_usbd_event_type_t aEvent) +{ + switch (aEvent) + { + case APP_USBD_EVT_STOPPED: + app_usbd_disable(); + break; + + default: + break; + } +} + +static void powerUsbEventHandler(nrf_drv_power_usb_evt_t aEvent) +{ + switch (aEvent) + { + case NRF_DRV_POWER_USB_EVT_DETECTED: + // Workaround for missing port open event. + sAppCdcAcm.specific.p_data->ctx.line_state = 0; + + sUsbState.mConnected = true; + break; + + case NRF_DRV_POWER_USB_EVT_REMOVED: + sUsbState.mConnected = false; + break; + + case NRF_DRV_POWER_USB_EVT_READY: + sUsbState.mReady = true; + break; + + default: + assert(false); + } +} + +static bool isPortOpened(void) +{ + uint32_t value; + + if (app_usbd_cdc_acm_line_state_get(&sAppCdcAcm, APP_USBD_CDC_ACM_LINE_STATE_DTR, &value) == NRF_SUCCESS) + { + return value; + } + + return false; +} + +static void processConnection(void) +{ + if (sUsbState.mLastConnectionStatus != (sUsbState.mUartEnabled && sUsbState.mConnected)) + { + sUsbState.mLastConnectionStatus = sUsbState.mUartEnabled && sUsbState.mConnected; + + if (sUsbState.mUartEnabled && sUsbState.mConnected) + { + if (!nrf_drv_usbd_is_enabled()) + { + app_usbd_enable(); + } + } + else + { + if (nrf_drv_usbd_is_started()) + { + app_usbd_stop(); + } + else + { + app_usbd_disable(); + } + } + } + + // Provide some delay so the OS can re-enumerate the device in case of reset. + if (sUsbState.mReady) + { + if (((otPlatGetResetReason(NULL) == OT_PLAT_RESET_REASON_EXTERNAL) || + (otPlatGetResetReason(NULL) == OT_PLAT_RESET_REASON_SOFTWARE)) && + (otPlatAlarmMilliGetNow() < USB_INITIAL_DELAY_MS)) + { + return; + } + + sUsbState.mReady = false; + + if (nrf_drv_usbd_is_enabled()) + { + app_usbd_start(); + } + } +} + +static void processReceive(void) +{ + if (sUsbState.mReceiveDone) + { + sUsbState.mReceiveDone = false; + + otPlatUartReceived((const uint8_t *)sRxBuffer, sUsbState.mReceivedDataSize); + + // Setup next transfer. + (void)app_usbd_cdc_acm_read(&sAppCdcAcm, sRxBuffer, sizeof(sRxBuffer)); + } +} + +static void processTransmit(void) +{ + // If some data was requested to send while port was closed, send it now. + if ((sUsbState.mTxBuffer != NULL) && isPortOpened()) + { + if (app_usbd_cdc_acm_write(&sAppCdcAcm, sUsbState.mTxBuffer, sUsbState.mTxSize) == NRF_SUCCESS) + { + sUsbState.mTxBuffer = NULL; + sUsbState.mTxSize = 0; + } + } + + if (sUsbState.mTransferDone) + { + sUsbState.mTransferDone = false; + + otPlatUartSendDone(); + } +} + +void nrf5UartInit(void) +{ + static const nrf_drv_power_usbevt_config_t powerConfig = + { + .handler = powerUsbEventHandler + }; + + static const app_usbd_config_t usbdConfig = + { + .ev_state_proc = usbdUserEventHandler + }; + + memset((void *)&sUsbState, 0, sizeof(sUsbState)); + + serialNumberStringCreate(); + + ret_code_t ret = nrf_drv_power_init(NULL); + assert(ret == NRF_SUCCESS); + + ret = app_usbd_init(&usbdConfig); + assert(ret == NRF_SUCCESS); + + app_usbd_class_inst_t const *cdcAcmInstance = app_usbd_cdc_acm_class_inst_get(&sAppCdcAcm); + ret = app_usbd_class_append(cdcAcmInstance); + assert(ret == NRF_SUCCESS); + + ret = nrf_drv_power_usbevt_init(&powerConfig); + assert(ret == NRF_SUCCESS); +} + +void nrf5UartDeinit(void) +{ + nrf_drv_power_usbevt_uninit(); + + app_usbd_class_remove_all(); + app_usbd_uninit(); + + nrf_drv_power_uninit(); +} + +void nrf5UartProcess(void) +{ + while (app_usbd_event_queue_process()) { } + + processConnection(); + processReceive(); + processTransmit(); +} + +otError otPlatUartEnable(void) +{ + sUsbState.mUartEnabled = true; + + return OT_ERROR_NONE; +} + +otError otPlatUartDisable(void) +{ + sUsbState.mUartEnabled = false; + + return OT_ERROR_NONE; +} + +otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) +{ + if (!isPortOpened()) + { + // If port is closed, queue the message until it can be sent. + if (sUsbState.mTxBuffer == NULL) + { + sUsbState.mTxBuffer = aBuf; + sUsbState.mTxSize = aBufLength; + } + else + { + return OT_ERROR_BUSY; + } + } + else if (app_usbd_cdc_acm_write(&sAppCdcAcm, aBuf, aBufLength) != NRF_SUCCESS) + { + return OT_ERROR_FAILED; + } + + return OT_ERROR_NONE; +} + +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 diff --git a/third_party/NordicSemiconductor/README.md b/third_party/NordicSemiconductor/README.md index 1d7d24f76..e6696fcec 100644 --- a/third_party/NordicSemiconductor/README.md +++ b/third_party/NordicSemiconductor/README.md @@ -5,14 +5,18 @@ in process of building the OpenThread's nRF52840 platform. nRF5 SDKs used: - nRF5 SDK 12.2.0: [URL][nrf5-sdk-12-2-0] - nRF5 SDK 13.0.0: [URL][nrf5-sdk-13-0-0] + - nRF5 SDK 14.0.0: [URL][nrf5-sdk-14-0-0] Directory consists of following folders: - - /cmsis - Core Peripheral Access Layer Headers files (nRF5 SDK 12.2.0) - - /device - MDK for the nRF52840 chip (nRF5 SDK 12.2.0) - - /drivers - Drivers for the nRF52840 that are used in the platform (custom files) - - /hal - Hardware Access Layer for the nRF52840 chip (nRF5 SDK 12.2.0) - - /segger_rtt - Library for the RTT communication (nRF5 SDK 12.2.0) - - /softdevice - SoftDevice s140 headers (nRF5 SDK 13.0.0) + - /cmsis - Core Peripheral Access Layer Headers files (nRF5 SDK 12.2.0) + - /dependencies - Dependencies for drivers and libraries from nrf5 SDK (nRF5 SDK 14.0.0) + - /device - MDK for the nRF52840 chip (nRF5 SDK 12.2.0) + - /drivers - Drivers for the nRF52840 that are used in the platform (custom files) + - /hal - Hardware Access Layer for the nRF52840 chip (nRF5 SDK 12.2.0) + - /libraries - Libraries for the nRF52840 chip (nRF5 SDK 14.0.0) + - /segger_rtt - Library for the RTT communication (nRF5 SDK 12.2.0) + - /softdevice - SoftDevice s140 headers (nRF5 SDK 13.0.0) [nrf5-sdk-12-2-0]: http://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v12.x.x/nRF5_SDK_12.2.0_f012efa.zip [nrf5-sdk-13-0-0]: http://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v13.x.x/nRF5_SDK_13.0.0_04a0bfd.zip + [nrf5-sdk-14-0-0]: http://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v14.x.x/nRF5_SDK_14.0.0_3bcc1f7.zip diff --git a/third_party/NordicSemiconductor/dependencies/app_error.h b/third_party/NordicSemiconductor/dependencies/app_error.h new file mode 100644 index 000000000..45471c9f7 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/app_error.h @@ -0,0 +1,239 @@ +/** + * Copyright (c) 2013 - 2017, 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 app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler and macros for utilizing a common error handler. + */ + +#ifndef APP_ERROR_H__ +#define APP_ERROR_H__ + +#include +#include +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "nordic_common.h" +#include "app_error_weak.h" +#ifdef ANT_STACK_SUPPORT_REQD +#include "ant_error.h" +#endif // ANT_STACK_SUPPORT_REQD + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_FAULT_ID_SDK_RANGE_START 0x00004000 /**< The start of the range of error IDs defined in the SDK. */ + +/**@defgroup APP_ERROR_FAULT_IDS Fault ID types + * @{ */ +#define NRF_FAULT_ID_SDK_ERROR NRF_FAULT_ID_SDK_RANGE_START + 1 /**< An error stemming from a call to @ref APP_ERROR_CHECK or @ref APP_ERROR_CHECK_BOOL. The info parameter is a pointer to an @ref error_info_t variable. */ +#define NRF_FAULT_ID_SDK_ASSERT NRF_FAULT_ID_SDK_RANGE_START + 2 /**< An error stemming from a call to ASSERT (nrf_assert.h). The info parameter is a pointer to an @ref assert_info_t variable. */ +/**@} */ + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ERROR. + */ +typedef struct +{ + uint16_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ + uint32_t err_code; /**< The error code representing the error that occurred. */ +} error_info_t; + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ASSERT. + */ +typedef struct +{ + uint16_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ +} assert_info_t; + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name); + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + */ +void app_error_handler_bare(ret_code_t error_code); + +/**@brief Function for saving the parameters and entering an eternal loop, for debug purposes. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info); + +/**@brief Function for printing all error info (using nrf_log). + * + * @details Nrf_log library must be initialized using NRF_LOG_INIT macro before calling + * this function. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +static __INLINE void app_error_log(uint32_t id, uint32_t pc, uint32_t info) +{ + switch (id) + { + case NRF_FAULT_ID_SDK_ASSERT: + //NRF_LOG_INFO(NRF_LOG_COLOR_RED "\r\n*** ASSERTION FAILED ***\r\n"); + if (((assert_info_t *)(info))->p_file_name) + { + // NRF_LOG_INFO(NRF_LOG_COLOR_WHITE "Line Number: %u\r\n", (unsigned int) ((assert_info_t *)(info))->line_num); + //NRF_LOG_INFO("File Name: %s\r\n", ((assert_info_t *)(info))->p_file_name); + } + //NRF_LOG_INFO(NRF_LOG_COLOR_DEFAULT "\r\n"); + break; + + case NRF_FAULT_ID_SDK_ERROR: + //NRF_LOG_INFO(NRF_LOG_COLOR_RED "\r\n*** APPLICATION ERROR *** \r\n" NRF_LOG_COLOR_WHITE); + if (((error_info_t *)(info))->p_file_name) + { + //NRF_LOG_INFO("Line Number: %u\r\n", (unsigned int) ((error_info_t *)(info))->line_num); + //NRF_LOG_INFO("File Name: %s\r\n", ((error_info_t *)(info))->p_file_name); + } + //NRF_LOG_INFO("Error Code: 0x%X\r\n" NRF_LOG_COLOR_DEFAULT "\r\n", (unsigned int) ((error_info_t *)(info))->err_code); + break; + } +} + +/**@brief Function for printing all error info (using printf). + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +//lint -save -e438 +static __INLINE void app_error_print(uint32_t id, uint32_t pc, uint32_t info) +{ + unsigned int tmp = id; + printf("app_error_print():\r\n"); + printf("Fault identifier: 0x%X\r\n", tmp); + printf("Program counter: 0x%X\r\n", tmp = pc); + printf("Fault information: 0x%X\r\n", tmp = info); + + switch (id) + { + case NRF_FAULT_ID_SDK_ASSERT: + printf("Line Number: %u\r\n", tmp = ((assert_info_t *)(info))->line_num); + printf("File Name: %s\r\n", ((assert_info_t *)(info))->p_file_name); + break; + + case NRF_FAULT_ID_SDK_ERROR: + printf("Line Number: %u\r\n", tmp = ((error_info_t *)(info))->line_num); + printf("File Name: %s\r\n", ((error_info_t *)(info))->p_file_name); + printf("Error Code: 0x%X\r\n", tmp = ((error_info_t *)(info))->err_code); + break; + } +} +//lint -restore + + +/**@brief Macro for calling error handler function. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#ifdef DEBUG +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \ + } while (0) +#else +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler_bare((ERR_CODE)); \ + } while (0) +#endif +/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#define APP_ERROR_CHECK(ERR_CODE) \ + do \ + { \ + const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \ + if (LOCAL_ERR_CODE != NRF_SUCCESS) \ + { \ + APP_ERROR_HANDLER(LOCAL_ERR_CODE); \ + } \ + } while (0) + +/**@brief Macro for calling error handler function if supplied boolean value is false. + * + * @param[in] BOOLEAN_VALUE Boolean value to be evaluated. + */ +#define APP_ERROR_CHECK_BOOL(BOOLEAN_VALUE) \ + do \ + { \ + const uint32_t LOCAL_BOOLEAN_VALUE = (BOOLEAN_VALUE); \ + if (!LOCAL_BOOLEAN_VALUE) \ + { \ + APP_ERROR_HANDLER(0); \ + } \ + } while (0) + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_H__ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/app_error_weak.h b/third_party/NordicSemiconductor/dependencies/app_error_weak.h new file mode 100644 index 000000000..c4e19f2c2 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/app_error_weak.h @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2016 - 2017, 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_ERROR_WEAK_H__ +#define APP_ERROR_WEAK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +/**@brief Callback function for errors, asserts, and faults. + * + * @details This function is called every time an error is raised in app_error, nrf_assert, or + * in the SoftDevice. Information about the error can be found in the @p info + * parameter. + * + * See also @ref nrf_fault_handler_t for more details. + * + * @note The function is implemented as weak so that it can be redefined by a custom error + * handler when needed. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. The value of the @p id + * parameter dictates how to interpret this parameter. Refer to the documentation + * for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for + * details about interpreting @p info. + */ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info); + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_WEAK_H__ diff --git a/third_party/NordicSemiconductor/dependencies/app_util.h b/third_party/NordicSemiconductor/dependencies/app_util.h new file mode 100644 index 000000000..4f6eee6df --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/app_util.h @@ -0,0 +1,1060 @@ +/** + * Copyright (c) 2012 - 2017, 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 app_util Utility Functions and Definitions + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications. + */ + +#ifndef APP_UTIL_H__ +#define APP_UTIL_H__ + +#include +#include +#include +#include "compiler_abstraction.h" +#include "nordic_common.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//lint -save -e27 -e10 -e19 +#if defined ( __CC_ARM ) && !defined (__LINT__) +extern char STACK$$Base; +extern char STACK$$Length; +#define STACK_BASE &STACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&STACK$$Length)) +#elif defined ( __ICCARM__ ) +extern char CSTACK$$Base; +extern char CSTACK$$Length; +#define STACK_BASE &CSTACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&CSTACK$$Length)) +#elif defined ( __GNUC__ ) +extern uint32_t __StackTop; +extern uint32_t __StackLimit; +#define STACK_BASE &__StackLimit +#define STACK_TOP &__StackTop +#endif +//lint -restore + +enum +{ + UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ + UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ + UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ +}; + + +/**@brief Implementation specific macro for delayed macro expansion used in string concatenation +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE_IMPL(lhs, rhs) lhs ## rhs + + +/**@brief Macro used to concatenate string using delayed macro expansion +* +* @note This macro will delay concatenation until the expressions have been resolved +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE(lhs, rhs) STRING_CONCATENATE_IMPL(lhs, rhs) + + +// Disable lint-warnings/errors for STATIC_ASSERT +//lint -emacro(10, STATIC_ASSERT) +//lint -emacro(15, STATIC_ASSERT) +//lint -emacro(18, STATIC_ASSERT) +//lint -emacro(19, STATIC_ASSERT) +//lint -emacro(30, STATIC_ASSERT) +//lint -emacro(37, STATIC_ASSERT) +//lint -emacro(42, STATIC_ASSERT) +//lint -emacro(26, STATIC_ASSERT) +//lint -emacro(102,STATIC_ASSERT) +//lint -emacro(533,STATIC_ASSERT) +//lint -emacro(534,STATIC_ASSERT) +//lint -emacro(132,STATIC_ASSERT) +//lint -emacro(414,STATIC_ASSERT) +//lint -emacro(578,STATIC_ASSERT) +//lint -emacro(628,STATIC_ASSERT) +//lint -emacro(648,STATIC_ASSERT) +//lint -emacro(830,STATIC_ASSERT) + +/**@brief Macro for doing static (i.e. compile time) assertion. +* +* @note If the EXPR isn't resolvable, then the error message won't be shown. +* @note The output of STATIC_ASSERT will be different across different compilers. +* +* @param[in] EXPR Constant expression to be verified. +* @hideinitializer +*/ +#define STATIC_ASSERT(EXPR) \ + extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] + + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_IMPL( \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + + +/**@brief Macro to get the number of arguments in a call variadic macro call + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_LESS_1_IMPL( \ + _ignored, \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + +/**@brief Macro to get the number of arguments in a call variadic macro call. + * First argument is not counted. + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS_LESS_1(...) NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) + + +/**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */ +typedef uint8_t uint16_le_t[2]; + +/**@brief Type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */ +typedef uint8_t uint32_le_t[4]; + +/**@brief Byte array type. */ +typedef struct +{ + uint16_t size; /**< Number of array entries. */ + uint8_t * p_data; /**< Pointer to array entries. */ +} uint8_array_t; + + +/**@brief Macro for performing rounded integer division (as opposed to truncating the result). + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Rounded (integer) result of dividing A by B. + */ +#define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B)) + + +/**@brief Macro for checking if an integer is a power of two. + * + * @param[in] A Number to be tested. + * + * @return true if value is power of two. + * @return false if value not power of two. + */ +#define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) ) + + +/**@brief Macro for converting milliseconds to ticks. + * + * @param[in] TIME Number of milliseconds to convert. + * @param[in] RESOLUTION Unit to be converted to in [us/ticks]. + */ +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) + + +/**@brief Macro for performing integer division, making sure the result is rounded up. + * + * @details One typical use for this is to compute the number of objects with size B is needed to + * hold A number of bytes. + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Integer result of dividing A by B, rounded up. + */ +#define CEIL_DIV(A, B) \ + (((A) + (B) - 1) / (B)) + + +/**@brief Macro for creating a buffer aligned to 4 bytes. + * + * @param[in] NAME Name of the buffor. + * @param[in] MIN_SIZE Size of this buffor (it will be rounded up to multiples of 4 bytes). + */ +#define WORD_ALIGNED_MEM_BUFF(NAME, MIN_SIZE) static uint32_t NAME[CEIL_DIV(MIN_SIZE, sizeof(uint32_t))] + + +/**@brief Macro for calculating the number of words that are needed to hold a number of bytes. + * + * @details Adds 3 and divides by 4. + * + * @param[in] n_bytes The number of bytes. + * + * @return The number of words that @p n_bytes take up (rounded up). + */ +#define BYTES_TO_WORDS(n_bytes) (((n_bytes) + 3) >> 2) + + +/**@brief The number of bytes in a word. + */ +#define BYTES_PER_WORD (4) + + +/**@brief Macro for increasing a number to the nearest (larger) multiple of another number. + * + * @param[in] alignment The number to align to. + * @param[in] number The number to align (increase). + * + * @return The aligned (increased) @p number. + */ +#define ALIGN_NUM(alignment, number) ((number - 1) + alignment - ((number - 1) % alignment)) + +/**@brief Macro for getting first of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_1(a1, a2) a1 + +/**@brief Macro for getting second of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_2(a1, a2) a2 + + +/**@brief Container of macro (borrowed from Linux kernel). + * + * This macro returns parent structure address basing on child member address. + * + * @param ptr Address of child type. + * @param type Type of parent structure. + * @param member Name of child field in parent structure. + * + * @return Parent structure address. + * */ +#define CONTAINER_OF(ptr, type, member) \ + (type *)((char *)ptr - offsetof(type, member)) + + +/** + * @brief Define Bit-field mask + * + * Macro that defined the mask with selected number of bits set, starting from + * provided bit number. + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + */ +#define BF_MASK(bcnt, boff) ( ((1U << (bcnt)) - 1U) << (boff) ) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value + * + * @param[in] val Value from witch selected bit-field would be extracted + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return Value of the selected bits + */ +#define BF_GET(val, bcnt, boff) ( ( (val) & BF_MASK((bcnt), (boff)) ) >> (boff) ) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field + * + * @param[in] val Value to set on bit-field + * @param[in] bcnt Number of bits for bit-field + * @param[in] boff Offset of bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_VAL(val, bcnt, boff) ( (((uint32_t)(val)) << (boff)) & BF_MASK(bcnt, boff) ) + +/** + * @name Configuration of complex bit-field + * + * @sa BF_CX + * @{ + */ +/** @brief Position of bit count in complex bit-field value */ +#define BF_CX_BCNT_POS 0U +/** @brief Mask of bit count in complex bit-field value */ +#define BF_CX_BCNT_MASK (0xffU << BF_CX_BCNT_POS) +/** @brief Position of bit position in complex bit-field value */ +#define BF_CX_BOFF_POS 8U +/** @brief Mask of bit position in complex bit-field value */ +#define BF_CX_BOFF_MASK (0xffU << BF_CX_BOFF_POS) +/** @} */ + +/** + * @brief Define complex bit-field + * + * Complex bit-field would contain its position and size in one number. + * @sa BF_CX_MASK + * @sa BF_CX_POS + * @sa BF_CX_GET + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return The single number that describes the bit-field completely. + */ +#define BF_CX(bcnt, boff) ( ((((uint32_t)(bcnt)) << BF_CX_BCNT_POS) & BF_CX_BCNT_MASK) | ((((uint32_t)(boff)) << BF_CX_BOFF_POS) & BF_CX_BOFF_MASK) ) + +/** + * @brief Get number of bits in bit-field + * + * @sa BF_CX + * + * @param bf_cx Complex bit-field + * + * @return Number of bits in given bit-field + */ +#define BF_CX_BCNT(bf_cx) ( ((bf_cx) & BF_CX_BCNT_MASK) >> BF_CX_BCNT_POS ) + +/** + * @brief Get lowest bit number in the field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Lowest bit number in given bit-field + */ +#define BF_CX_BOFF(bf_cx) ( ((bf_cx) & BF_CX_BOFF_MASK) >> BF_CX_BOFF_POS ) + +/** + * @brief Get bit mask of the selected field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Mask of given bit-field + */ +#define BF_CX_MASK(bf_cx) BF_MASK(BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value. + * Bit-field is given as a complex value. + * + * @sa BF_CX + * @sa BF_GET + * + * @param[in] val Value from witch selected bit-field would be extracted + * @param[in] bf_cx Complex bit-field + * + * @return Value of the selected bits. + */ +#define BF_CX_GET(val, bf_cx) BF_GET(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field. + * + * @param[in] val Value to set on bit-field + * @param[in] bf_cx Complex bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_CX_VAL(val, bf_cx) BF_VAL(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Extracting data from the brackets + * + * This macro get rid of brackets around the argument. + * It can be used to pass multiple arguments in logical one argument to a macro. + * Call it with arguments inside brackets: + * @code + * #define ARGUMENTS (a, b, c) + * BRACKET_EXTRACT(ARGUMENTS) + * @endcode + * It would produce: + * @code + * a, b, c + * @endcode + * + * @param a Argument with anything inside brackets + * @return Anything that appears inside the brackets of the argument + * + * @note + * The argument of the macro have to be inside brackets. + * In other case the compilation would fail. + */ +#define BRACKET_EXTRACT(a) BRACKET_EXTRACT_(a) +#define BRACKET_EXTRACT_(a) BRACKET_EXTRACT__ a +#define BRACKET_EXTRACT__(...) __VA_ARGS__ + + +/** + * @brief Check if number of parameters is more than 1 + * + * @param ... Arguments to count + * + * @return 0 If argument count is <= 1 + * @return 1 If argument count is > 1 + * + * @sa NUM_VA_ARGS + * @sa NUM_IS_MORE_THAN_1 + */ +#define NUM_VA_ARGS_IS_MORE_THAN_1(...) NUM_IS_MORE_THAN_1(NUM_VA_ARGS(__VA_ARGS__)) + +/** + * @brief Check if given numeric value is bigger than 1 + * + * This macro accepts numeric value, that may be the result of argument expansion. + * This numeric value is then converted to 0 if it is lover than 1 or to 1 if + * its value is higher than 1. + * The generated result can be used to glue it into other macro mnemonic name. + * + * @param N Numeric value to check + * + * @return 0 If argument is <= 1 + * @return 1 If argument is > 1 + * + * @note Any existing definition of a form NUM_IS_MORE_THAN_1_PROBE_[N] can + * broke the result of this macro + */ +#define NUM_IS_MORE_THAN_1(N) NUM_IS_MORE_THAN_1_(N) +#define NUM_IS_MORE_THAN_1_(N) NUM_IS_MORE_THAN_1_PROBE_(NUM_IS_MORE_THAN_1_PROBE_ ## N, 1) +#define NUM_IS_MORE_THAN_1_PROBE_(...) GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__)) +#define NUM_IS_MORE_THAN_1_PROBE_0 ~, 0 +#define NUM_IS_MORE_THAN_1_PROBE_1 ~, 0 + +/** + * @brief Get the first argument + * + * @param ... Arguments to select + * + * @return First argument or empty if no arguments are provided + */ +#define GET_VA_ARG_1(...) GET_VA_ARG_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_VA_ARG_1_(a1, ...) a1 + +/** + * @brief Get all the arguments but the first one + * + * @param ... Arguments to select + * + * @return All arguments after the first one or empty if less than 2 arguments are provided + */ +#define GET_ARGS_AFTER_1(...) GET_ARGS_AFTER_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_ARGS_AFTER_1_(a1, ...) __VA_ARGS__ + +/** + * @brief Size of a field in declared structure + * + * Macro that returns the size of the structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. It can be even field inside field (field.somethingelse.and_another). + * + * @return Size of the field + */ +#define FIELD_SIZE(struct_type, field) sizeof(((struct struct_type*)NULL)->field) + +/** + * @brief Number of elements in field array in declared structure + * + * Macro that returns number of elementy in structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. + * + * @return Number of elements in field array + * + * @sa FIELD_SIZE + */ +#define FIELD_ARRAY_SIZE(struct_type, field) (FIELD_SIZE(struct_type, field) / FIELD_SIZE(struct_type, field[0])) + +/** + * @brief Mapping macro + * + * Macro that process all arguments using given macro + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP(...) MACRO_MAP_(__VA_ARGS__) +#define MACRO_MAP_(...) MACRO_MAP_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total + +/** + * @brief Mapping macro, recursive version + * + * Can be used in @ref MACRO_MAP macro + */ +#define MACRO_MAP_REC(...) MACRO_MAP_REC_(__VA_ARGS__) +#define MACRO_MAP_REC_(...) MACRO_MAP_REC_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total +/** + * @brief Mapping N arguments macro + * + * Macro similar to @ref MACRO_MAP but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_N(N, ...) MACRO_MAP_N_(N, __VA_ARGS__) +#define MACRO_MAP_N_(N, ...) CONCAT_2(MACRO_MAP_, N)(__VA_ARGS__, ) + +/** + * @brief Mapping N arguments macro, recursive version + * + * Can be used in @ref MACRO_MAP_N macro + */ +#define MACRO_MAP_REC_N(N, ...) MACRO_MAP_REC_N_(N, __VA_ARGS__) +#define MACRO_MAP_REC_N_(N, ...) CONCAT_2(MACRO_MAP_REC_, N)(__VA_ARGS__, ) + +#define MACRO_MAP_0( ...) +#define MACRO_MAP_1( macro, a, ...) macro(a) +#define MACRO_MAP_2( macro, a, ...) macro(a) MACRO_MAP_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_3( macro, a, ...) macro(a) MACRO_MAP_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_4( macro, a, ...) macro(a) MACRO_MAP_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_5( macro, a, ...) macro(a) MACRO_MAP_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_6( macro, a, ...) macro(a) MACRO_MAP_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_7( macro, a, ...) macro(a) MACRO_MAP_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_8( macro, a, ...) macro(a) MACRO_MAP_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_9( macro, a, ...) macro(a) MACRO_MAP_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_10(macro, a, ...) macro(a) MACRO_MAP_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_11(macro, a, ...) macro(a) MACRO_MAP_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_12(macro, a, ...) macro(a) MACRO_MAP_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_13(macro, a, ...) macro(a) MACRO_MAP_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_14(macro, a, ...) macro(a) MACRO_MAP_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_15(macro, a, ...) macro(a) MACRO_MAP_14(macro, __VA_ARGS__, ) + +#define MACRO_MAP_REC_0( ...) +#define MACRO_MAP_REC_1( macro, a, ...) macro(a) +#define MACRO_MAP_REC_2( macro, a, ...) macro(a) MACRO_MAP_REC_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_3( macro, a, ...) macro(a) MACRO_MAP_REC_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_4( macro, a, ...) macro(a) MACRO_MAP_REC_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_5( macro, a, ...) macro(a) MACRO_MAP_REC_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_6( macro, a, ...) macro(a) MACRO_MAP_REC_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_7( macro, a, ...) macro(a) MACRO_MAP_REC_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_8( macro, a, ...) macro(a) MACRO_MAP_REC_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_9( macro, a, ...) macro(a) MACRO_MAP_REC_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_10(macro, a, ...) macro(a) MACRO_MAP_REC_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_11(macro, a, ...) macro(a) MACRO_MAP_REC_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_12(macro, a, ...) macro(a) MACRO_MAP_REC_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_13(macro, a, ...) macro(a) MACRO_MAP_REC_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_14(macro, a, ...) macro(a) MACRO_MAP_REC_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_15(macro, a, ...) macro(a) MACRO_MAP_REC_14(macro, __VA_ARGS__, ) + +/** + * @brief Mapping macro with current index + * + * Basically macro similar to @ref MACRO_MAP, but the processing function would get an argument + * and current argument index (beginning from 0). + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR(...) MACRO_MAP_FOR_(__VA_ARGS__) +#define MACRO_MAP_FOR_N_LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +#define MACRO_MAP_FOR_(...) MACRO_MAP_FOR_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with current index + * + * Macro is similar to @ref MACRO_MAP_FOR but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_FOR_N(N, ...) MACRO_MAP_FOR_N_(N, __VA_ARGS__) +#define MACRO_MAP_FOR_N_(N, ...) CONCAT_2(MACRO_MAP_FOR_, N)((MACRO_MAP_FOR_N_LIST), __VA_ARGS__, ) + +#define MACRO_MAP_FOR_0( n_list, ...) +#define MACRO_MAP_FOR_1( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) +#define MACRO_MAP_FOR_2( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_3( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_4( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_5( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_6( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_7( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_8( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_9( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_10(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_11(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_12(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_13(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_14(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_15(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) + + +/** + * @brief Mapping macro with current index and parameter + * + * Version of @ref MACRO_MAP_FOR that passes also the same parameter to all macros. + * + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM(param, ...) MACRO_MAP_FOR_PARAM_(param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_(param, ...) MACRO_MAP_FOR_PARAM_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), param, __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with with current index and parameter + * + * @param N Number of arguments to map + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM_N(N, param, ...) MACRO_MAP_FOR_PARAM_N_(N, param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_N_(N, param, ...) CONCAT_2(MACRO_MAP_FOR_PARAM_, N)((MACRO_MAP_FOR_N_LIST), param, __VA_ARGS__, ) + + +#define MACRO_MAP_FOR_PARAM_0( n_list, param, ...) +#define MACRO_MAP_FOR_PARAM_1( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) +#define MACRO_MAP_FOR_PARAM_2( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_3( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_4( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_5( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_6( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_7( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_8( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_9( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_10(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_11(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_12(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_13(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_14(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_15(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) + + +/** + * @brief Repeating macro. + * + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT(count, macro, ...) MACRO_REPEAT_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_(count, macro, ...) CONCAT_2(MACRO_REPEAT_, count)(macro, __VA_ARGS__) + +#define MACRO_REPEAT_0(macro, ...) +#define MACRO_REPEAT_1(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_0(macro, __VA_ARGS__) +#define MACRO_REPEAT_2(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_1(macro, __VA_ARGS__) +#define MACRO_REPEAT_3(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_2(macro, __VA_ARGS__) +#define MACRO_REPEAT_4(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_3(macro, __VA_ARGS__) +#define MACRO_REPEAT_5(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_4(macro, __VA_ARGS__) +#define MACRO_REPEAT_6(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_5(macro, __VA_ARGS__) +#define MACRO_REPEAT_7(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_6(macro, __VA_ARGS__) +#define MACRO_REPEAT_8(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_7(macro, __VA_ARGS__) +#define MACRO_REPEAT_9(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_8(macro, __VA_ARGS__) +#define MACRO_REPEAT_10(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_9(macro, __VA_ARGS__) +#define MACRO_REPEAT_11(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_10(macro, __VA_ARGS__) +#define MACRO_REPEAT_12(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_11(macro, __VA_ARGS__) +#define MACRO_REPEAT_13(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_12(macro, __VA_ARGS__) +#define MACRO_REPEAT_14(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_13(macro, __VA_ARGS__) +#define MACRO_REPEAT_15(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_14(macro, __VA_ARGS__) + + +/** + * @brief Repeating macro with current index. + * + * Macro similar to @ref MACRO_REPEAT but the processing function gets the arguments + * and the current argument index (beginning from 0). + + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(index, arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT_FOR(count, macro, ...) MACRO_REPEAT_FOR_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_(count, macro, ...) CONCAT_2(MACRO_REPEAT_FOR_, count)((MACRO_MAP_FOR_N_LIST), macro, __VA_ARGS__) + +#define MACRO_REPEAT_FOR_0(n_list, macro, ...) +#define MACRO_REPEAT_FOR_1(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_0((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_2(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_1((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_3(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_2((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_4(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_3((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_5(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_4((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_6(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_5((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_7(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_6((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_8(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_7((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_9(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_8((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_10(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_9((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_11(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_12(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_13(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_14(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_15(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) + +/**@brief Adding curly brace to the macro parameter. + * + * Useful in array of structures initialization. + * + * @param p Parameter to put into the curly brace. */ +#define PARAM_CBRACE(p) { p }, + + +/**@brief Function for changing the value unit. + * + * @param[in] value Value to be rescaled. + * @param[in] old_unit_reversal Reversal of the incoming unit. + * @param[in] new_unit_reversal Reversal of the desired unit. + * + * @return Number of bytes written. + */ +static __INLINE uint64_t value_rescale(uint32_t value, uint32_t old_unit_reversal, uint16_t new_unit_reversal) +{ + return (uint64_t)ROUNDED_DIV((uint64_t)value * new_unit_reversal, old_unit_reversal); +} + +/**@brief Function for encoding a uint16 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8); + return sizeof(uint16_t); +} + +/**@brief Function for encoding a three-byte value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint24_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + return 3; +} + +/**@brief Function for encoding a uint32 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24); + return sizeof(uint32_t); +} + +/**@brief Function for encoding a uint48 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint48_encode(uint64_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x0000000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x00000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x000000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0x0000FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((value & 0x00FF00000000) >> 32); + p_encoded_data[5] = (uint8_t) ((value & 0xFF0000000000) >> 40); + return 6; +} + +/**@brief Function for decoding a uint16 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) | + (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 )); +} + +/**@brief Function for decoding a uint16 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0]) << 8 ) | + (((uint16_t)((uint8_t *)p_encoded_data)[1])) ); +} + +/**@brief Function for decoding a three-byte value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value (uint32_t). + */ +static __INLINE uint32_t uint24_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16)); +} + +/**@brief Function for decoding a uint32 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 )); +} + +/**@brief Function for decoding a uint32 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 24) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 0) ); +} + +/** + * @brief Function for encoding an uint16 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_big_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) (value >> 8); + p_encoded_data[1] = (uint8_t) (value & 0xFF); + + return sizeof(uint16_t); +} + +/**@brief Function for encoding a uint32 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_big_encode(uint32_t value, uint8_t * p_encoded_data) +{ + *(uint32_t *)p_encoded_data = __REV(value); + return sizeof(uint32_t); +} + +/**@brief Function for decoding a uint48 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. (uint64_t) + */ +static __INLINE uint64_t uint48_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32) | + (((uint64_t)((uint8_t *)p_encoded_data)[5]) << 40 )); +} + +/** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts. + * + * @details The calculation is based on a linearized version of the battery's discharge + * curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and + * is considered to be the lower boundary. + * + * The discharge curve for CR2032 is non-linear. In this model it is split into + * 4 linear sections: + * - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV) + * - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV) + * - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV) + * - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV) + * + * These numbers are by no means accurate. Temperature and + * load in the actual application is not accounted for! + * + * @param[in] mvolts The voltage in mV + * + * @return Battery level in percent. +*/ +static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts) +{ + uint8_t battery_level; + + if (mvolts >= 3000) + { + battery_level = 100; + } + else if (mvolts > 2900) + { + battery_level = 100 - ((3000 - mvolts) * 58) / 100; + } + else if (mvolts > 2740) + { + battery_level = 42 - ((2900 - mvolts) * 24) / 160; + } + else if (mvolts > 2440) + { + battery_level = 18 - ((2740 - mvolts) * 12) / 300; + } + else if (mvolts > 2100) + { + battery_level = 6 - ((2440 - mvolts) * 6) / 340; + } + else + { + battery_level = 0; + } + + return battery_level; +} + +/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. + * + * @param[in] p Pointer value to be checked. + * + * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. + */ +static __INLINE bool is_word_aligned(void const* p) +{ + return (((uintptr_t)p & 0x03) == 0); +} + +/** + * @brief Function for checking if provided address is located in stack space. + * + * @param[in] ptr Pointer to be checked. + * + * @return true if address is in stack space, false otherwise. + */ +static __INLINE bool is_address_from_stack(void * ptr) +{ + if (((uint32_t)ptr >= (uint32_t)STACK_BASE) && + ((uint32_t)ptr < (uint32_t)STACK_TOP) ) + { + return true; + } + else + { + return false; + } +} + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_H__ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/app_util_platform.c b/third_party/NordicSemiconductor/dependencies/app_util_platform.c new file mode 100644 index 000000000..bbe5856a1 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/app_util_platform.c @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2014 - 2017, 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 "app_util_platform.h" + +#ifdef SOFTDEVICE_PRESENT +/* Global nvic state instance, required by nrf_nvic.h */ +nrf_nvic_state_t nrf_nvic_state; +#endif + +static uint32_t m_in_critical_region = 0; + +void app_util_disable_irq(void) +{ + __disable_irq(); + m_in_critical_region++; +} + +void app_util_enable_irq(void) +{ + m_in_critical_region--; + if (m_in_critical_region == 0) + { + __enable_irq(); + } +} + +void app_util_critical_region_enter(uint8_t *p_nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +#if defined(SOFTDEVICE_PRESENT) + /* return value can be safely ignored */ + (void) sd_nvic_critical_region_enter(p_nested); +#else + app_util_disable_irq(); +#endif +} + +void app_util_critical_region_exit(uint8_t nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +#if defined(SOFTDEVICE_PRESENT) + /* return value can be safely ignored */ + (void) sd_nvic_critical_region_exit(nested); +#else + app_util_enable_irq(); +#endif +} + + +uint8_t privilege_level_get(void) +{ +#if __CORTEX_M == (0x00U) || defined(_WIN32) || defined(__unix) || defined(__APPLE__) + /* the Cortex-M0 has no concept of privilege */ + return APP_LEVEL_PRIVILEGED; +#elif __CORTEX_M == (0x04U) + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (0 == isr_vector_num) + { + /* Thread Mode, check nPRIV */ + int32_t control = __get_CONTROL(); + return control & CONTROL_nPRIV_Msk ? APP_LEVEL_UNPRIVILEGED : APP_LEVEL_PRIVILEGED; + } + else + { + /* Handler Mode, always privileged */ + return APP_LEVEL_PRIVILEGED; + } +#endif +} + + +uint8_t current_int_priority_get(void) +{ + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (isr_vector_num > 0) + { + int32_t irq_type = ((int32_t)isr_vector_num - EXTERNAL_INT_VECTOR_OFFSET); + return (NVIC_GetPriority((IRQn_Type)irq_type) & 0xFF); + } + else + { + return APP_IRQ_PRIORITY_THREAD; + } +} diff --git a/third_party/NordicSemiconductor/dependencies/app_util_platform.h b/third_party/NordicSemiconductor/dependencies/app_util_platform.h new file mode 100644 index 000000000..61db926b9 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/app_util_platform.h @@ -0,0 +1,262 @@ +/** + * Copyright (c) 2014 - 2017, 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 app_util_platform Utility Functions and Definitions (Platform) + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications when using SoftDevice. + */ + +#ifndef APP_UTIL_PLATFORM_H__ +#define APP_UTIL_PLATFORM_H__ + +#include +#include "compiler_abstraction.h" +#include "nrf.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#include "nrf_nvic.h" +#endif +#include "nrf_assert.h" +#include "app_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if __CORTEX_M == (0x00U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_APP_HIGH 1 +#define _PRIO_APP_MID 1 +#define _PRIO_SD_LOW 2 +#define _PRIO_APP_LOW 3 +#define _PRIO_APP_LOWEST 3 +#define _PRIO_THREAD 4 +#elif __CORTEX_M == (0x04U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_SD_MID 1 +#define _PRIO_APP_HIGH 2 +#define _PRIO_APP_MID 3 +#define _PRIO_SD_LOW 4 +#define _PRIO_SD_LOWEST 5 +#define _PRIO_APP_LOW 6 +#define _PRIO_APP_LOWEST 7 +#define _PRIO_THREAD 15 +#else + #error "No platform defined" +#endif + + +//lint -save -e113 -e452 +/**@brief The interrupt priorities available to the application while the SoftDevice is active. */ +typedef enum +{ +#ifndef SOFTDEVICE_PRESENT + APP_IRQ_PRIORITY_HIGHEST = _PRIO_SD_HIGH, +#else + APP_IRQ_PRIORITY_HIGHEST = _PRIO_APP_HIGH, +#endif + APP_IRQ_PRIORITY_HIGH = _PRIO_APP_HIGH, +#ifndef SOFTDEVICE_PRESENT + APP_IRQ_PRIORITY_MID = _PRIO_SD_LOW, +#else + APP_IRQ_PRIORITY_MID = _PRIO_APP_MID, +#endif + APP_IRQ_PRIORITY_LOW = _PRIO_APP_LOW, + APP_IRQ_PRIORITY_LOWEST = _PRIO_APP_LOWEST, + APP_IRQ_PRIORITY_THREAD = _PRIO_THREAD /**< "Interrupt level" when running in Thread Mode. */ +} app_irq_priority_t; +//lint -restore + + +/*@brief The privilege levels available to applications in Thread Mode */ +typedef enum +{ + APP_LEVEL_UNPRIVILEGED, + APP_LEVEL_PRIVILEGED +} app_level_t; + +/**@cond NO_DOXYGEN */ +#define EXTERNAL_INT_VECTOR_OFFSET 16 +/**@endcond */ + +/**@brief Macro for setting a breakpoint. + */ +#if defined(__GNUC__) +#define NRF_BREAKPOINT __builtin_trap() +#else +#define NRF_BREAKPOINT __BKPT(0) +#endif + +/** @brief Macro for setting a breakpoint. + * + * If it is possible to detect debugger presence then it is set only in that case. + * + */ +#if __CORTEX_M == 0x04 +#define NRF_BREAKPOINT_COND do { \ + /* C_DEBUGEN == 1 -> Debugger Connected */ \ + if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) \ + { \ + /* Generate breakpoint if debugger is connected */ \ + NRF_BREAKPOINT; \ + } \ + }while (0) +#else +#define NRF_BREAKPOINT_COND NRF_BREAKPOINT +#endif // __CORTEX_M == 0x04 + +#if defined ( __CC_ARM ) +#define PACKED(TYPE) __packed TYPE +#define PACKED_STRUCT PACKED(struct) +#elif defined ( __GNUC__ ) +#define PACKED __attribute__((packed)) +#define PACKED_STRUCT struct PACKED +#elif defined (__ICCARM__) +#define PACKED_STRUCT __packed struct +#endif + +void app_util_critical_region_enter (uint8_t *p_nested); +void app_util_critical_region_exit (uint8_t nested); + +/**@brief Macro for entering a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +#ifdef SOFTDEVICE_PRESENT +#define CRITICAL_REGION_ENTER() \ + { \ + uint8_t __CR_NESTED = 0; \ + app_util_critical_region_enter(&__CR_NESTED); +#else +#define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL) +#endif + +/**@brief Macro for leaving a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +#ifdef SOFTDEVICE_PRESENT +#define CRITICAL_REGION_EXIT() \ + app_util_critical_region_exit(__CR_NESTED); \ + } +#else +#define CRITICAL_REGION_EXIT() app_util_critical_region_exit(0) +#endif + +/* Workaround for Keil 4 */ +#ifndef IPSR_ISR_Msk +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ +#endif + + + +/**@brief Macro to enable anonymous unions from a certain point in the code. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_ENABLE _Pragma("push") \ + _Pragma("anon_unions") +#elif defined(__ICCARM__) + #define ANON_UNIONS_ENABLE _Pragma("language=extended") +#else + #define ANON_UNIONS_ENABLE + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro to disable anonymous unions from a certain point in the code. + * @note Call only after first calling @ref ANON_UNIONS_ENABLE. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_DISABLE _Pragma("pop") +#elif defined(__ICCARM__) + #define ANON_UNIONS_DISABLE + // for IAR leave anonymous unions enabled +#else + #define ANON_UNIONS_DISABLE + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro for adding pragma directive only for GCC. + */ +#ifdef __GNUC__ +#define GCC_PRAGMA(v) _Pragma(v) +#else +#define GCC_PRAGMA(v) +#endif + +/* Workaround for Keil 4 */ +#ifndef CONTROL_nPRIV_Msk +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ +#endif + +/**@brief Function for finding the current interrupt level. + * + * @return Current interrupt level. + * @retval APP_IRQ_PRIORITY_HIGH We are running in Application High interrupt level. + * @retval APP_IRQ_PRIORITY_LOW We are running in Application Low interrupt level. + * @retval APP_IRQ_PRIORITY_THREAD We are running in Thread Mode. + */ +uint8_t current_int_priority_get(void); + + +/**@brief Function for finding out the current privilege level. + * + * @return Current privilege level. + * @retval APP_LEVEL_UNPRIVILEGED We are running in unprivileged level. + * @retval APP_LEVEL_PRIVILEGED We are running in privileged level. + */ +uint8_t privilege_level_get(void); + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_PLATFORM_H__ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/nordic_common.h b/third_party/NordicSemiconductor/dependencies/nordic_common.h new file mode 100644 index 000000000..9e1d87de6 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/nordic_common.h @@ -0,0 +1,211 @@ +/** + * Copyright (c) 2008 - 2017, 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 + * @brief Common defines and macros for firmware developed by Nordic Semiconductor. + */ + +#ifndef NORDIC_COMMON_H__ +#define NORDIC_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Check if selected module is enabled + * + * This is save function for driver enable checking. + * Correct from Lint point of view (not using default of undefined value). + * + * Usage: + * @code + #if NRF_MODULE_ENABLED(UART) + ... + #endif + * @endcode + * + * @param module The module name. + * + * @retval 1 The macro _ENABLE is defined and is non-zero. + * @retval 0 The macro _ENABLE is not defined or it equals zero. + * + * @note + * This macro intentionally does not implement second expansion level. + * The name of the module to be checked has to be given directly as a parameter. + * And given parameter would be connected with @c _ENABLED postfix directly + * without evaluating its value. + */ +//lint -emacro(491,NRF_MODULE_ENABLED) // Suppers warning 491 "non-standard use of 'defined' preprocessor operator" +#define NRF_MODULE_ENABLED(module) \ + ((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0) + +/** The upper 8 bits of a 32 bit value */ +//lint -emacro(572,MSB_32) // Suppress warning 572 "Excessive shift value" +#define MSB_32(a) (((a) & 0xFF000000) >> 24) +/** The lower 8 bits (of a 32 bit value) */ +#define LSB_32(a) ((a) & 0x000000FF) + +/** The upper 8 bits of a 16 bit value */ +//lint -emacro(572,MSB_16) // Suppress warning 572 "Excessive shift value" +#define MSB_16(a) (((a) & 0xFF00) >> 8) +/** The lower 8 bits (of a 16 bit value) */ +#define LSB_16(a) ((a) & 0x00FF) + +/** Leaves the minimum of the two 32-bit arguments */ +/*lint -emacro(506, MIN) */ /* Suppress "Constant value Boolean */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +/** Leaves the maximum of the two 32-bit arguments */ +/*lint -emacro(506, MAX) */ /* Suppress "Constant value Boolean */ +#define MAX(a, b) ((a) < (b) ? (b) : (a)) + +/**@brief Concatenates two parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * + * @return Two parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_3 + */ +#define CONCAT_2(p1, p2) CONCAT_2_(p1, p2) +/** Auxiliary macro used by @ref CONCAT_2 */ +#define CONCAT_2_(p1, p2) p1##p2 + +/**@brief Concatenates three parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * @param p3 Third parameter to concatenating + * + * @return Three parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_2 + */ +#define CONCAT_3(p1, p2, p3) CONCAT_3_(p1, p2, p3) +/** Auxiliary macro used by @ref CONCAT_3 */ +#define CONCAT_3_(p1, p2, p3) p1##p2##p3 + +#define STRINGIFY_(val) #val +/** Converts a macro argument into a character constant. + */ +#define STRINGIFY(val) STRINGIFY_(val) + +/** Counts number of elements inside the array + */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/**@brief Set a bit in the uint32 word. + * + * @param[in] W Word whose bit is being set. + * @param[in] B Bit number in the word to be set. + */ +#define SET_BIT(W, B) ((W) |= (uint32_t)(1U << (B))) + + +/**@brief Clears a bit in the uint32 word. + * + * @param[in] W Word whose bit is to be cleared. + * @param[in] B Bit number in the word to be cleared. + */ +#define CLR_BIT(W, B) ((W) &= (~(uint32_t)(1U << (B)))) + + +/**@brief Checks if a bit is set. + * + * @param[in] W Word whose bit is to be checked. + * @param[in] B Bit number in the word to be checked. + * + * @retval 1 if bit is set. + * @retval 0 if bit is not set. + */ +#define IS_SET(W, B) (((W) >> (B)) & 1) + +#define BIT_0 0x01 /**< The value of bit 0 */ +#define BIT_1 0x02 /**< The value of bit 1 */ +#define BIT_2 0x04 /**< The value of bit 2 */ +#define BIT_3 0x08 /**< The value of bit 3 */ +#define BIT_4 0x10 /**< The value of bit 4 */ +#define BIT_5 0x20 /**< The value of bit 5 */ +#define BIT_6 0x40 /**< The value of bit 6 */ +#define BIT_7 0x80 /**< The value of bit 7 */ +#define BIT_8 0x0100 /**< The value of bit 8 */ +#define BIT_9 0x0200 /**< The value of bit 9 */ +#define BIT_10 0x0400 /**< The value of bit 10 */ +#define BIT_11 0x0800 /**< The value of bit 11 */ +#define BIT_12 0x1000 /**< The value of bit 12 */ +#define BIT_13 0x2000 /**< The value of bit 13 */ +#define BIT_14 0x4000 /**< The value of bit 14 */ +#define BIT_15 0x8000 /**< The value of bit 15 */ +#define BIT_16 0x00010000 /**< The value of bit 16 */ +#define BIT_17 0x00020000 /**< The value of bit 17 */ +#define BIT_18 0x00040000 /**< The value of bit 18 */ +#define BIT_19 0x00080000 /**< The value of bit 19 */ +#define BIT_20 0x00100000 /**< The value of bit 20 */ +#define BIT_21 0x00200000 /**< The value of bit 21 */ +#define BIT_22 0x00400000 /**< The value of bit 22 */ +#define BIT_23 0x00800000 /**< The value of bit 23 */ +#define BIT_24 0x01000000 /**< The value of bit 24 */ +#define BIT_25 0x02000000 /**< The value of bit 25 */ +#define BIT_26 0x04000000 /**< The value of bit 26 */ +#define BIT_27 0x08000000 /**< The value of bit 27 */ +#define BIT_28 0x10000000 /**< The value of bit 28 */ +#define BIT_29 0x20000000 /**< The value of bit 29 */ +#define BIT_30 0x40000000 /**< The value of bit 30 */ +#define BIT_31 0x80000000 /**< The value of bit 31 */ + +#define UNUSED_VARIABLE(X) ((void)(X)) +#define UNUSED_PARAMETER(X) UNUSED_VARIABLE(X) +#define UNUSED_RETURN_VALUE(X) UNUSED_VARIABLE(X) + +#ifdef __cplusplus +} +#endif + +#endif // NORDIC_COMMON_H__ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_atomic.h b/third_party/NordicSemiconductor/dependencies/nrf_atomic.h new file mode 100644 index 000000000..9a8c10bc1 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/nrf_atomic.h @@ -0,0 +1,495 @@ +/** + * Copyright (c) 2016 - 2017, 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 nrf_atomic Atomic operations API + * @ingroup nrf_atfifo + * @{ + * + * @brief @tagAPI52 This module implements C11 stdatomic.h simplified API. + At this point only Cortex-M3/M4 cores are supported (LDREX/STREX instructions). + * Atomic types are limited to @ref nrf_atomic_u32_t and @ref nrf_atomic_flag_t. + */ + +#ifndef NRF_ATOMIC_H__ +#define NRF_ATOMIC_H__ + +#include "sdk_common.h" + + +#ifndef NRF_ATOMIC_USE_BUILD_IN +#if (defined(__GNUC__) && defined(WIN32)) + #define NRF_ATOMIC_USE_BUILD_IN 1 +#else + #define NRF_ATOMIC_USE_BUILD_IN 0 +#endif +#endif // NRF_ATOMIC_USE_BUILD_IN + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) +#define STREX_LDREX_PRESENT +#else +#include "app_util_platform.h" +#endif + +/** + * @brief Atomic 32 bit unsigned type + * */ +typedef volatile uint32_t nrf_atomic_u32_t; + +/** + * @brief Atomic 1 bit flag type (technically 32 bit) + * */ +typedef volatile uint32_t nrf_atomic_flag_t; + +#if (NRF_ATOMIC_USE_BUILD_IN == 0) && defined(STREX_LDREX_PRESENT) +#include "nrf_atomic_internal.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_exchange_n(p_data, value, __ATOMIC_SEQ_CST); + +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data = value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + __atomic_store_n(p_data, value, __ATOMIC_SEQ_CST); + return value; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data = value; + CRITICAL_REGION_EXIT(); + return value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_or(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data |= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_or_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data |= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_and(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data &= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_and_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data &= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_xor(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data ^= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_xor_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data ^= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_add(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data += value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_add_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data += value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_sub(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_sub_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/**************************************************************************************************/ + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +static inline uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_or(p_data, 1); +} + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +static inline uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_or(p_data, 1); +} + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +static inline uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_and(p_data, 0); +} + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +static inline uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_and(p_data, 0); +} + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_H__ */ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_atomic_internal.h b/third_party/NordicSemiconductor/dependencies/nrf_atomic_internal.h new file mode 100644 index 000000000..8486df5aa --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/nrf_atomic_internal.h @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2016 - 2017, 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_ATOMIC_INTERNAL_H__ +#define NRF_ATOMIC_INTERNAL_H__ + +#include "sdk_common.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @defgroup nrf_atomic_internal Atomic operations internals + * @ingroup nrf_atomic + * @{ + * + */ + +/* Only Cortex M cores > 3 support LDREX/STREX instructions*/ +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error "Unsupported core version" +#endif + +#if defined ( __CC_ARM ) +static __asm uint32_t nrf_atomic_internal_mov(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + /* The base standard provides for passing arguments in core registers (r0-r3) and on the stack. + * Registers r4 and r5 have to be saved on stack. Note that only even number of register push are + * allowed. This is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS]. + * */ + push {r4, r5} + mov r4, r0 + +loop_mov + ldrex r0, [r4] + mov r5, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_mov + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +static __asm uint32_t nrf_atomic_internal_orr(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_orr + ldrex r0, [r4] + orr r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_orr + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_and(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_and + ldrex r0, [r4] + and r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_and + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_eor(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_eor + ldrex r0, [r4] + eor r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_eor + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_add(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_add + ldrex r0, [r4] + add r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_add + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_sub(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub + ldrex r0, [r4] + sub r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ + old_val = nrf_atomic_internal_##asm_op(ptr, value, &new_val) + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +/** + * @brief Atomic operation generic macro + * @param[in] asm_op operation: mov, orr, and, eor, add, sub + * @param[out] old_val atomic object output (uint32_t), value before operation + * @param[out] new_val atomic object output (uint32_t), value after operation + * @param[in] value atomic operation operand + * */ +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ +{ \ + uint32_t str_res; \ + __ASM volatile( \ + "1: ldrex %["#old_val"], [%["#ptr"]]\n" \ + NRF_ATOMIC_OP_##asm_op(new_val, old_val, value) \ + " strex %[str_res], %["#new_val"], [%["#ptr"]]\n" \ + " teq %[str_res], #0\n" \ + " bne.n 1b" \ + : \ + [old_val]"=&r" (old_val), \ + [new_val]"=&r" (new_val), \ + [str_res]"=&r" (str_res) \ + : \ + [ptr]"r" (ptr), \ + [value]"r" (value) \ + : "cc"); \ + UNUSED_PARAMETER(str_res); \ +} + +#define NRF_ATOMIC_OP_mov(new_val, old_val, value) "mov %["#new_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_orr(new_val, old_val, value) "orr %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_and(new_val, old_val, value) "and %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_eor(new_val, old_val, value) "eor %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_add(new_val, old_val, value) "add %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub(new_val, old_val, value) "sub %["#new_val"], %["#old_val"], %["#value"]\n" + +#else +#error "Unsupported compiler" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_INTERNAL_H__ */ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_delay.h b/third_party/NordicSemiconductor/dependencies/nrf_delay.h new file mode 100644 index 000000000..42d5beb10 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/nrf_delay.h @@ -0,0 +1,268 @@ +/** + * Copyright (c) 2011 - 2017, 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_DELAY_H +#define _NRF_DELAY_H + +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CLOCK_FREQ_16MHz (16000000UL) + +#ifdef NRF52_SERIES + #define CPU_FREQ_64MHz +#endif + +/** + * @brief Function for delaying execution for number of microseconds. + * + * @note NRF52 has instruction cache and because of that delay is not precise. + * + * @param number_of_us + * + */ +/*lint -e{438, 522, 40, 10, 563} */ +__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us); + + +/** + * @brief Function for delaying execution for number of miliseconds. + * + * @note NRF52 has instruction cache and because of that delay is not precise. + * + * @note Function internally calls @ref nrf_delay_us so the maximum delay is the + * same as in case of @ref nrf_delay_us, approx. 71 minutes. + * + * @param number_of_ms + * + */ + +/*lint -e{438, 522, 40, 10, 563} */ +__STATIC_INLINE void nrf_delay_ms(uint32_t number_of_ms); + +#if defined ( __CC_ARM ) +__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us) +{ + if (!number_of_us) + return; +__asm + { +loop: + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + CMP SystemCoreClock, CLOCK_FREQ_16MHz + BEQ cond + NOP +#ifdef CPU_FREQ_64MHz + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP +#endif //CPU_FREQ_64MHz +cond: + SUBS number_of_us, #1 + BNE loop + } +} + +#elif defined ( _WIN32 ) || defined ( __unix ) || defined( __APPLE__ ) + + +#ifndef CUSTOM_NRF_DELAY_US +__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us) +{} +#endif + +#elif defined ( __GNUC__ ) || ( __ICCARM__ ) + +__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us) +{ + const uint32_t clock16MHz = CLOCK_FREQ_16MHz; + if (number_of_us) + { +__ASM volatile ( +#if ( defined(__GNUC__) && (__CORTEX_M == (0x00U) ) ) + ".syntax unified\n" +#endif +"1:\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " CMP %[SystemCoreClock], %[clock16MHz]\n" + " BEQ.N 2f\n" + " NOP\n" +#ifdef CPU_FREQ_64MHz + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" +#endif //CPU_FREQ_64MHz +"2:\n" + " SUBS %[number_of_us], %[number_of_us], #1\n" + " BNE.N 1b\n" +#if ( defined(__GNUC__) && (__CORTEX_M == (0x00U) ) ) + ".syntax divided\n" +#endif +#if ( __CORTEX_M == (0x00U) ) + // The SUBS instruction in Cortex-M0 is available only in 16-bit encoding, + // hence it requires a "lo" register (r0-r7) as an operand. + : [number_of_us] "=l" (number_of_us) +#else + : [number_of_us] "=r" (number_of_us) +#endif + : [SystemCoreClock] "r" (SystemCoreClock), + [clock16MHz] "r" (clock16MHz), + "[number_of_us]" (number_of_us) + ); + } +} +#endif + +__STATIC_INLINE void nrf_delay_ms(uint32_t number_of_ms) +{ + nrf_delay_us(1000*number_of_ms); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/NordicSemiconductor/dependencies/nrf_error.h b/third_party/NordicSemiconductor/dependencies/nrf_error.h new file mode 100644 index 000000000..49efa47ae --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/nrf_error.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2012 - 2017, 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 NRF_ERROR_H__ +#define NRF_ERROR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/// @cond Make doxygen skip this file + +/** @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__ + +/// @endcond +/** + @} +*/ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_log.h b/third_party/NordicSemiconductor/dependencies/nrf_log.h new file mode 100644 index 000000000..6e7a185e4 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/nrf_log.h @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2016 - 2017, 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 nrf_log Logger module + * @{ + * @ingroup app_common + * + * @brief The nrf_log module interface. + */ + +#ifndef NRF_LOG_H_ +#define NRF_LOG_H_ + +#include "sdk_common.h" +#include "nrf_section.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_strerror.h" +#define NRF_LOG_ERROR_STRING_GET(code) nrf_strerror_get(code) +#else +#define NRF_LOG_ERROR_STRING_GET(code) "" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Severity level for the module. + * + * The severity level can be defined in a module to override the default. + */ +#ifndef NRF_LOG_LEVEL + #define NRF_LOG_LEVEL NRF_LOG_DEFAULT_LEVEL +#endif + + +#include "nrf_log_internal.h" + +/** @def NRF_LOG_ERROR + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_WARNING + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + */ + +/** @def NRF_LOG_INFO + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + */ + +/** @def NRF_LOG_DEBUG + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + */ + +#define NRF_LOG_ERROR(...) NRF_LOG_INTERNAL_ERROR(__VA_ARGS__) +#define NRF_LOG_WARNING(...) NRF_LOG_INTERNAL_WARNING( __VA_ARGS__) +#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__) +#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__) + +/** + * @brief A macro for logging a formatted string without any prefix or timestamp. + */ +#define NRF_LOG_RAW_INFO(...) NRF_LOG_INTERNAL_RAW_INFO( __VA_ARGS__) + +/** @def NRF_LOG_HEXDUMP_ERROR + * @brief Macro for logging raw bytes. + * @details It is compiled in only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_WARNING + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INFO + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_DEBUG + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +#define NRF_LOG_HEXDUMP_ERROR(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) +#define NRF_LOG_HEXDUMP_WARNING(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) +#define NRF_LOG_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) +#define NRF_LOG_HEXDUMP_DEBUG(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) + +/** + * @brief Macro for logging hexdump without any prefix or timestamp. + */ +#define NRF_LOG_RAW_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) + +/** + * @brief A macro for blocking reading from bidirectional backend used for logging. + * + * Macro call is blocking and returns when single byte is received. + */ +#define NRF_LOG_GETCHAR() NRF_LOG_INTERNAL_GETCHAR() + +/** + * @brief A macro for copying a string to internal logger buffer if logs are deferred. + * + * @param _str String. + */ +#define NRF_LOG_PUSH(_str) NRF_LOG_INTERNAL_LOG_PUSH(_str) + +/** + * @brief Function for copying a string to the internal logger buffer if logs are deferred. + * + * Use this function to store a string that is volatile (for example allocated + * on stack) or that may change before the deferred logs are processed. Such string is copied + * into the internal logger buffer and is persistent until the log is processed. + * + * @note If the logs are not deferred, then this function returns the input parameter. + * + * @param p_str Pointer to the user string. + * + * @return Address to the location where the string is stored in the internal logger buffer. + */ +uint32_t nrf_log_push(char * const p_str); + +/** + * @brief Macro to be used in a formatted string to a pass float number to the log. + * + * Macro should be used in formatted string instead of the %f specifier together with + * @ref NRF_LOG_FLOAT macro. + * Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f))) + */ +#define NRF_LOG_FLOAT_MARKER "%s%d.%02d" + +/** + * @brief Macro for dissecting a float number into two numbers (integer and residuum). + */ +#define NRF_LOG_FLOAT(val) (uint32_t)(((val) < 0 && (val) > -1.0) ? "-" : ""), \ + (int32_t)(val), \ + (int32_t)((((val) > 0) ? (val) - (int32_t)(val) \ + : (int32_t)(val) - (val))*100) + + + +/** + * @def NRF_LOG_MODULE_REGISTER + * @brief Macro for registering an independent module. + */ +#if NRF_LOG_ENABLED + +#ifdef UNIT_TEST +#define _CONST +#define COMPILED_LOG_LEVEL 4 +#else +#define _CONST const +#define COMPILED_LOG_LEVEL NRF_LOG_LEVEL +#endif +#define NRF_LOG_MODULE_REGISTER() \ + NRF_SECTION_ITEM_REGISTER(log_const_data, \ + _CONST nrf_log_module_const_data_t NRF_LOG_MODULE_DATA_CONST) = { \ + .p_module_name = STRINGIFY(NRF_LOG_MODULE_NAME), \ + .info_color_id = NRF_LOG_INFO_COLOR, \ + .debug_color_id = NRF_LOG_DEBUG_COLOR, \ + .compiled_lvl = COMPILED_LOG_LEVEL, \ + }; \ + NRF_SECTION_ITEM_REGISTER(log_dynamic_data, \ + nrf_log_module_dynamic_data_t NRF_LOG_MODULE_DATA_DYNAMIC) +#else +#define NRF_LOG_MODULE_REGISTER() /*lint -save -e19*/ /*lint -restore*/ +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NRF_LOG_H_ + +/** @} */ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_log_internal.h b/third_party/NordicSemiconductor/dependencies/nrf_log_internal.h new file mode 100644 index 000000000..6403a34f0 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/nrf_log_internal.h @@ -0,0 +1,534 @@ +/** + * Copyright (c) 2016 - 2017, 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_LOG_INTERNAL_H__ +#define NRF_LOG_INTERNAL_H__ +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_error.h" +#include "app_util.h" +#include +#include + +#ifndef NRF_LOG_ERROR_COLOR + #define NRF_LOG_ERROR_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_WARNING_COLOR + #define NRF_LOG_WARNING_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_INFO_COLOR + #define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_DEBUG_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT +#endif + + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 0 +#endif + +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif + +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 0 +#endif + +#ifndef NRF_LOG_MODULE_NAME + #define NRF_LOG_MODULE_NAME app +#endif + +#define NRF_LOG_LEVEL_ERROR 1UL +#define NRF_LOG_LEVEL_WARNING 2UL +#define NRF_LOG_LEVEL_INFO 3UL +#define NRF_LOG_LEVEL_DEBUG 4UL +#define NRF_LOG_LEVEL_INTERNAL 5UL +#define NRF_LOG_LEVEL_BITS 3 +#define NRF_LOG_LEVEL_MASK ((1UL << NRF_LOG_LEVEL_BITS) - 1) +#define NRF_LOG_RAW_POS 4U +#define NRF_LOG_RAW (1UL << NRF_LOG_RAW_POS) +#define NRF_LOG_MODULE_ID_BITS 16 +#define NRF_LOG_MODULE_ID_POS 16 +#define NRF_LOG_LEVEL_INFO_RAW (NRF_LOG_RAW | NRF_LOG_LEVEL_INFO) + +#define NRF_LOG_MAX_NUM_OF_ARGS 6 + +#define NRF_LOG_MODULE_DATA CONCAT_3(m_nrf_log_,NRF_LOG_MODULE_NAME,_logs_data) +#define NRF_LOG_MODULE_DATA_DYNAMIC CONCAT_2(NRF_LOG_MODULE_DATA,_dynamic) +#define NRF_LOG_MODULE_DATA_CONST CONCAT_2(NRF_LOG_MODULE_DATA,_const) + +#if NRF_LOG_FILTERS_ENABLED && NRF_LOG_ENABLED + #define NRF_LOG_FILTER NRF_LOG_MODULE_DATA_DYNAMIC.filter +#else + #undef NRF_LOG_FILTER + #define NRF_LOG_FILTER NRF_LOG_LEVEL_DEBUG +#endif + +#if NRF_LOG_ENABLED +#define NRF_LOG_MODULE_ID NRF_LOG_MODULE_DATA_DYNAMIC.module_id +#else +#define NRF_LOG_MODULE_ID 0 +#endif + + +#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__) +#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \ + __VA_ARGS__), type, __VA_ARGS__) +#if NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) nrf_log_push(_str) +#define LOG_INTERNAL_0(type, str) \ + nrf_log_frontend_std_0(type, str) +#define LOG_INTERNAL_1(type, str, arg0) \ + /*lint -save -e571*/nrf_log_frontend_std_1(type, str, (uint32_t)(arg0))/*lint -restore*/ +#define LOG_INTERNAL_2(type, str, arg0, arg1) \ + /*lint -save -e571*/nrf_log_frontend_std_2(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1))/*lint -restore*/ +#define LOG_INTERNAL_3(type, str, arg0, arg1, arg2) \ + /*lint -save -e571*/nrf_log_frontend_std_3(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2))/*lint -restore*/ +#define LOG_INTERNAL_4(type, str, arg0, arg1, arg2, arg3) \ + /*lint -save -e571*/nrf_log_frontend_std_4(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3))/*lint -restore*/ +#define LOG_INTERNAL_5(type, str, arg0, arg1, arg2, arg3, arg4) \ + /*lint -save -e571*/nrf_log_frontend_std_5(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4))/*lint -restore*/ +#define LOG_INTERNAL_6(type, str, arg0, arg1, arg2, arg3, arg4, arg5) \ + /*lint -save -e571*/nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))/*lint -restore*/ + + +#else //NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) (void)(_str) +#define LOG_INTERNAL_0(_type, _str) \ + (void)(_type); (void)(_str) +#define LOG_INTERNAL_1(_type, _str, _arg0) \ + (void)(_type); (void)(_str); (void)(_arg0) +#define LOG_INTERNAL_2(_type, _str, _arg0, _arg1) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1) +#define LOG_INTERNAL_3(_type, _str, _arg0, _arg1, _arg2) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2) +#define LOG_INTERNAL_4(_type, _str, _arg0, _arg1, _arg2, _arg3) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3) +#define LOG_INTERNAL_5(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4) +#define LOG_INTERNAL_6(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4, _arg5) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4); (void)(_arg5) +#endif //NRF_LOG_ENABLED && (NRF_LOG_DEFAULT_LEVEL >= NRF_LOG_LEVEL_ERROR) + +#define LOG_SEVERITY_MOD_ID(severity) ((severity) | NRF_LOG_MODULE_ID << NRF_LOG_MODULE_ID_POS) + +#if NRF_LOG_ENABLED +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + nrf_log_frontend_hexdump((_severity), (_p_data), (_length)) +#else +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + (void)(_severity); (void)(_p_data); (void)_length +#endif + +#define NRF_LOG_INTERNAL_ERROR(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_ERROR) && \ + (NRF_LOG_LEVEL_ERROR <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_ERROR) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_ERROR), __VA_ARGS__); \ + } \ + } +#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_ERROR) && \ + (NRF_LOG_LEVEL_ERROR <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_ERROR) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_ERROR), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_WARNING(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_WARNING) && \ + (NRF_LOG_LEVEL_WARNING <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_WARNING) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_WARNING), __VA_ARGS__); \ + } \ + } +#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_WARNING) && \ + (NRF_LOG_LEVEL_WARNING <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_WARNING) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_WARNING, \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_INFO(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \ + (NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_INFO) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_INFO), __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_RAW_INFO(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \ + (NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_INFO) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_INFO | NRF_LOG_RAW), \ + __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \ + (NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_INFO) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_INFO), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \ + (NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_INFO) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_INFO_RAW), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_DEBUG(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_DEBUG) && \ + (NRF_LOG_LEVEL_DEBUG <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_DEBUG) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_DEBUG), __VA_ARGS__); \ + } \ + } +#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_DEBUG) && \ + (NRF_LOG_LEVEL_DEBUG <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_DEBUG) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_DEBUG), \ + (p_data), (len)); \ + } \ + } + +#if NRF_MODULE_ENABLED(NRF_LOG) +#define NRF_LOG_INTERNAL_GETCHAR() nrf_log_getchar() +#else +#define NRF_LOG_INTERNAL_GETCHAR() (void) +#endif + +typedef struct +{ + uint16_t module_id; + uint16_t order_idx; + uint32_t filter; + uint32_t filter_lvls; +} nrf_log_module_dynamic_data_t; + +typedef struct +{ + const char * p_module_name; + uint8_t info_color_id; + uint8_t debug_color_id; + uint8_t compiled_lvl; +} nrf_log_module_const_data_t; + +extern nrf_log_module_dynamic_data_t NRF_LOG_MODULE_DATA_DYNAMIC; + +/** + * Set of macros for encoding and decoding header for log entries. + * There are 3 types of entries: + * 1. Standard entry (STD) + * An entry consists of header, pointer to string and values. Header contains + * severity leveland determines number of arguments and thus size of the entry. + * Since flash address space starts from 0x00000000 and is limited to kB rather + * than MB 22 bits are used to store the address (4MB). It is used that way to + * save one RAM memory. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS| P_STR | + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | ARG0 | + * |------------------------------| + * | .... | + * |------------------------------| + * | ARG(nargs-1) | + * -------------------------------- + * + * 2. Hexdump entry (HEXDUMP) is used for dumping raw data. An entry consists of + * header, optional timestamp, pointer to string and data. A header contains + * length (10bit) and offset which is updated after backend processes part of + * data. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS|OFFSET|LEN| + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | P_STR | + * |------------------------------| + * | data | + * |------------------------------| + * | data | dummy | + * -------------------------------- + * + * 3. Pushed string. If string is pushed into the logger internal buffer it is + * stored as PUSHED entry. It consists of header, unused data (optional) and + * string. Unused data is present if string does not not fit into a buffer + * without wrapping (and string cannot be wrapped). In that case header + * contains information about offset. + * + * -------------------------------- + * |TYPE| OFFSET | LEN | + * |------------------------------| + * | OFFSET | + * |------------------------------| + * end| OFFSET | + * 0|------------------------------| + * | STRING | + * |------------------------------| + * | STRING | dummy | + * -------------------------------- + */ + +#define STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U) +#define HEADER_TYPE_STD 1U +#define HEADER_TYPE_HEXDUMP 2U +#define HEADER_TYPE_PUSHED 0U + +typedef struct +{ + uint32_t type : 2; + uint32_t raw : 1; + uint32_t data : 29; +} nrf_log_generic_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t raw : 1; + uint32_t severity : 3; + uint32_t nargs : 4; + uint32_t addr : 22; +} nrf_log_std_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t raw : 1; + uint32_t severity : 3; + uint32_t offset : 10; + uint32_t reserved : 6; + uint32_t len : 10; +} nrf_log_hexdump_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t reserved0 : 4; + uint32_t offset : 10; + uint32_t reserved1 : 6; + uint32_t len : 10; +} nrf_log_pushed_header_t; + +typedef struct +{ + union { + nrf_log_generic_header_t generic; + nrf_log_std_header_t std; + nrf_log_hexdump_header_t hexdump; + nrf_log_pushed_header_t pushed; + uint32_t raw; + } base; + uint32_t module_id; + uint32_t timestamp; +} nrf_log_header_t; + +#define HEADER_SIZE (sizeof(nrf_log_header_t)/sizeof(uint32_t) - \ + (NRF_LOG_USES_TIMESTAMP ? 0 : 1)) + +#define PUSHED_HEADER_SIZE (sizeof(nrf_log_pushed_header_t)/sizeof(uint32_t)) + +//Implementation assumes that pushed header has one word. +STATIC_ASSERT(PUSHED_HEADER_SIZE == 1); +/** + * @brief A function for logging raw string. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string. + */ +void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str); + +/** + * @brief A function for logging a formatted string with one argument. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0 An argument. + */ +void nrf_log_frontend_std_1(uint32_t severity_mid, + char const * const p_str, + uint32_t val0); + +/** + * @brief A function for logging a formatted string with 2 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1 Arguments for formatting string. + */ +void nrf_log_frontend_std_2(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1); + +/** + * @brief A function for logging a formatted string with 3 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2 Arguments for formatting string. + */ +void nrf_log_frontend_std_3(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2); + +/** + * @brief A function for logging a formatted string with 4 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3 Arguments for formatting string. + */ +void nrf_log_frontend_std_4(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3); + +/** + * @brief A function for logging a formatted string with 5 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4 Arguments for formatting string. + */ +void nrf_log_frontend_std_5(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4); + +/** + * @brief A function for logging a formatted string with 6 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4, val5 Arguments for formatting string. + */ +void nrf_log_frontend_std_6(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4, + uint32_t val5); + +/** + * @brief A function for logging raw data. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string which is prefixing the data. + * @param p_data A pointer to data to be dumped. + * @param length Length of data (in bytes). + * + */ +void nrf_log_frontend_hexdump(uint32_t severity_mid, + const void * const p_data, + uint16_t length); + +/** + * @brief A function for reading a byte from log backend. + * + * @return Byte. + */ +uint8_t nrf_log_getchar(void); +#endif // NRF_LOG_INTERNAL_H__ diff --git a/third_party/NordicSemiconductor/dependencies/nrf_section.h b/third_party/NordicSemiconductor/dependencies/nrf_section.h new file mode 100644 index 000000000..4ac2b3a4a --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/nrf_section.h @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2016 - 2017, 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_SECTION_H__ +#define NRF_SECTION_H__ + +#include "nordic_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup section_vars Section variables + * @ingroup app_common + * @{ + * + * @brief Section variables. + */ + +//lint -save -e27 -esym(526,*) + +#if defined(__ICCARM__) +// Enable IAR language extensions +#pragma language=extended +#endif + +/**@brief Macro for obtaining the address of the beginning of a section. + * + * param[in] section_name Name of the section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(section_name, $$Base) + +#elif defined(__GNUC__) +#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(__start_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_START_ADDR(section_name) __section_begin(STRINGIFY(section_name)) +#endif + + +/**@brief Macro for obtaining the address of the end of a section. + * + * @param[in] section_name Name of the section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(section_name, $$Limit) + +#elif defined(__GNUC__) +#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(__stop_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_END_ADDR(section_name) __section_end(STRINGIFY(section_name)) +#endif + + +/**@brief Macro for retrieving the length of a given section, in bytes. + * + * @param[in] section_name Name of the section. + * @hideinitializer + */ +#define NRF_SECTION_LENGTH(section_name) \ + ((size_t)NRF_SECTION_END_ADDR(section_name) - \ + (size_t)NRF_SECTION_START_ADDR(section_name)) + + +/**@brief Macro for creating a section. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variables to be registered in the section. + * + * @warning Data type must be word aligned to prevent padding. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_DEF(section_name, data_type) \ + extern data_type * CONCAT_2(section_name, $$Base); \ + extern void * CONCAT_2(section_name, $$Limit) + +#elif defined(__GNUC__) +#define NRF_SECTION_DEF(section_name, data_type) \ + extern data_type * CONCAT_2(__start_, section_name); \ + extern void * CONCAT_2(__stop_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_DEF(section_name, data_type) \ + _Pragma(STRINGIFY(section = STRINGIFY(section_name))); + +#endif + + +/**@brief Macro for declaring a variable and registering it in a section. + * + * @details Declares a variable and registers it in a named section. This macro ensures that the + * variable is not stripped away when using optimizations. + * + * @note The order in which variables are placed in a section is dependent on the order in + * which the linker script encounters the variables during linking. + * + * @param[in] section_name Name of the section. + * @param[in] section_var Variable to register in the given section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + section_var __attribute__ ((section(STRINGIFY(section_name)))) __attribute__((used)) + +#elif defined(__GNUC__) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + section_var __attribute__ ((section("." STRINGIFY(section_name)))) __attribute__((used)) + +#elif defined(__ICCARM__) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + __root section_var @ STRINGIFY(section_name) +#endif + + +/**@brief Macro for retrieving a variable from a section. + * + * @warning The stored symbol can only be resolved using this macro if the + * type of the data is word aligned. The operation of acquiring + * the stored symbol relies on the size of the stored type. No + * padding can exist in the named section in between individual + * stored items or this macro will fail. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variable. + * @param[in] i Index of the variable in section. + * @hideinitializer + */ +#define NRF_SECTION_ITEM_GET(section_name, data_type, i) \ + ((data_type*)NRF_SECTION_START_ADDR(section_name) + (i)) + + +/**@brief Macro for getting the number of variables in a section. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variables in the section. + * @hideinitializer + */ +#define NRF_SECTION_ITEM_COUNT(section_name, data_type) \ + NRF_SECTION_LENGTH(section_name) / sizeof(data_type) + +/** @} */ + +//lint -restore + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SECTION_H__ diff --git a/third_party/NordicSemiconductor/dependencies/sdk_common.h b/third_party/NordicSemiconductor/dependencies/sdk_common.h new file mode 100644 index 000000000..b2201518d --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/sdk_common.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2013 - 2017, 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. + * + */ +/** @cond */ +/**@file + * + * @ingroup experimental_api + * @defgroup sdk_common SDK Common Header + * @brief All common headers needed for SDK examples will be included here so that application + * developer does not have to include headers on him/herself. + * @{ + */ + +#ifndef SDK_COMMON_H__ +#define SDK_COMMON_H__ + +#include +#include +#include +#include "sdk_config.h" +#include "nordic_common.h" +#include "compiler_abstraction.h" +#include "sdk_os.h" +#include "sdk_errors.h" +#include "app_util.h" +#include "sdk_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_COMMON_H__ + diff --git a/third_party/NordicSemiconductor/dependencies/sdk_config.h b/third_party/NordicSemiconductor/dependencies/sdk_config.h new file mode 100644 index 000000000..b0017b8d1 --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/sdk_config.h @@ -0,0 +1,254 @@ +#ifndef SDK_CONFIG_H +#define SDK_CONFIG_H + +#include +#undef PACKAGE + +#pragma GCC diagnostic ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +//========================================================== +// APP_USBD_ENABLED - app_usbd - USB Device library +//========================================================== +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) +#ifndef APP_USBD_ENABLED +#define APP_USBD_ENABLED 1 +#endif +#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 +#ifndef APP_USBD_ENABLED +#define APP_USBD_ENABLED 0 +#endif +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 + +// APP_USBD_VID - Vendor ID + +// Vendor ID ordered from USB IF: http://www.usb.org/developers/vendor/ +#ifndef APP_USBD_VID +#define APP_USBD_VID 0x1915 +#endif + +// APP_USBD_PID - Product ID + +// Selected Product ID +#ifndef APP_USBD_PID +#define APP_USBD_PID 0xCAFE +#endif + +// APP_USBD_DEVICE_VER_MAJOR - Device version, major part <0-99> + + +// Device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MAJOR +#define APP_USBD_DEVICE_VER_MAJOR 1 +#endif + +// APP_USBD_DEVICE_VER_MINOR - Device version, minor part <0-99> + + +// Device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MINOR +#define APP_USBD_DEVICE_VER_MINOR 0 +#endif + +// APP_USBD_EVENT_QUEUE_ENABLE - Enable event queue + +// This is the default configuration when all the events are placed into internal queue. +// Disable it when external queue is used like app_scheduler or if you wish to process all events inside interrupts. +// Processing all events from the interrupt level adds requirement not to call any functions that modifies the USBD library state from the context higher than USB interrupt context. +// Functions that modify USBD state are functions for sleep, wakeup, start, stop, enable and disable. +//========================================================== +#ifndef APP_USBD_EVENT_QUEUE_ENABLE +#define APP_USBD_EVENT_QUEUE_ENABLE 1 +#endif +// APP_USBD_EVENT_QUEUE_SIZE - The size of event queue <16-64> + + +// The size of the queue for the events that would be processed in the main loop. + +#ifndef APP_USBD_EVENT_QUEUE_SIZE +#define APP_USBD_EVENT_QUEUE_SIZE 32 +#endif + +// + +// APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef APP_USBD_CONFIG_LOG_ENABLED +#define APP_USBD_CONFIG_LOG_ENABLED 0 +#endif + +// + +// + +// CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver +//========================================================== +#ifndef CLOCK_ENABLED +#define CLOCK_ENABLED 1 +#endif +// CLOCK_CONFIG_XTAL_FREQ - HF XTAL Frequency + +// <0=> Default (64 MHz) + +#ifndef CLOCK_CONFIG_XTAL_FREQ +#define CLOCK_CONFIG_XTAL_FREQ 0 +#endif + +// CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth + +#ifndef CLOCK_CONFIG_LF_SRC +#define CLOCK_CONFIG_LF_SRC 1 +#endif + +// CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef CLOCK_CONFIG_IRQ_PRIORITY +#define CLOCK_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// POWER_ENABLED - nrf_drv_power - POWER peripheral driver +//========================================================== + +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) +#ifndef POWER_ENABLED +#define POWER_ENABLED 1 +#endif +#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 +#ifndef POWER_ENABLED +#define POWER_ENABLED 0 +#endif +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 + +// POWER_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef POWER_CONFIG_IRQ_PRIORITY +#define POWER_CONFIG_IRQ_PRIORITY 7 +#endif + +// POWER_CONFIG_DEFAULT_DCDCEN - The default configuration of main DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCEN +#define POWER_CONFIG_DEFAULT_DCDCEN 0 +#endif + +// POWER_CONFIG_DEFAULT_DCDCENHV - The default configuration of High Voltage DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCENHV +#define POWER_CONFIG_DEFAULT_DCDCENHV 0 +#endif + +// + +// SYSTICK_ENABLED - nrf_drv_systick - SysTick driver + +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) +#ifndef SYSTICK_ENABLED +#define SYSTICK_ENABLED 1 +#endif +#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 +#ifndef SYSTICK_ENABLED +#define SYSTICK_ENABLED 0 +#endif +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 + +// USBD_ENABLED - nrf_drv_usbd - USB driver +//========================================================== +#if (USB_CDC_AS_SERIAL_TRANSPORT == 1) +#ifndef USBD_ENABLED +#define USBD_ENABLED 1 +#endif +#else // USB_CDC_AS_SERIAL_TRANSPORT == 1 +#ifndef USBD_ENABLED +#define USBD_ENABLED 0 +#endif +#endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 +// USBD_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef USBD_CONFIG_IRQ_PRIORITY +#define USBD_CONFIG_IRQ_PRIORITY 7 +#endif + +// NRF_DRV_USBD_DMASCHEDULER_MODE - USBD SMA scheduler working scheme + +// <0=> Prioritized access +// <1=> Round Robin + +#ifndef NRF_DRV_USBD_DMASCHEDULER_MODE +#define NRF_DRV_USBD_DMASCHEDULER_MODE 0 +#endif + +// + +// app_usbd_cdc_acm - USB CDC ACM class + +//========================================================== +// APP_USBD_CLASS_CDC_ACM_ENABLED - Enabling USBD CDC ACM Class library + + +#ifndef APP_USBD_CLASS_CDC_ACM_ENABLED +#define APP_USBD_CLASS_CDC_ACM_ENABLED 1 +#endif + +// +//========================================================== + +// nrf_log - Logging + +//========================================================== +// NRF_LOG_ENABLED - Logging module for nRF5 SDK +//========================================================== +#ifndef NRF_LOG_ENABLED +#define NRF_LOG_ENABLED 0 +#endif + +// +// + +#endif //SDK_CONFIG_H diff --git a/third_party/NordicSemiconductor/dependencies/sdk_errors.h b/third_party/NordicSemiconductor/dependencies/sdk_errors.h new file mode 100644 index 000000000..7c73357ed --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/sdk_errors.h @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2013 - 2017, 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 sdk_error SDK Error codes + * @{ + * @ingroup app_common + * @{ + * @details Error codes are 32-bit unsigned integers with the most significant 16-bit reserved for + * identifying the module where the error occurred while the least least significant LSB + * are used to provide the cause or nature of error. Each module is assigned a 16-bit + * unsigned integer. Which it will use to identify all errors that occurred in it. 16-bit + * LSB range is with module id as the MSB in the 32-bit error code is reserved for the + * module. As an example, if 0x8800 identifies a certain SDK module, all values from + * 0x88000000 - 0x8800FFFF are reserved for this module. + * It should be noted that common error reasons have been assigned values to make it + * possible to decode error reason easily. As an example, lets module uninitialized has + * been assigned an error code 0x000A0. Then, if application encounters an error code + * 0xZZZZ00A0, it knows that it accessing a certain module without initializing it. + * Apart from this, each module is allowed to define error codes that are not covered by + * the common ones, however, these values are defined in a range that does not conflict + * with common error values. For module, specific error however, it is possible that the + * same error value is used by two different modules to indicated errors of very different + * nature. If error is already defined by the NRF common error codes, these are reused. + * A range is reserved for application as well, it can use this range for defining + * application specific errors. + * + * @note Success code, NRF_SUCCESS, does not include any module identifier. + + */ + +#ifndef SDK_ERRORS_H__ +#define SDK_ERRORS_H__ + +#include +#include "nrf_error.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup sdk_err_base Base defined for SDK Modules + * @{ + */ +#define NRF_ERROR_SDK_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x8000) /**< Base value defined for SDK module identifiers. */ +#define NRF_ERROR_SDK_COMMON_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x0080) /**< Base error value to be used for SDK error values. */ +/** @} */ + +/** + * @defgroup sdk_module_codes Codes reserved as identification for module where the error occurred. + * @{ + */ +#define NRF_ERROR_MEMORY_MANAGER_ERR_BASE (0x8100) +#define NRF_ERROR_PERIPH_DRIVERS_ERR_BASE (0x8200) +#define NRF_ERROR_GAZELLE_ERR_BASE (0x8300) +/** @} */ + + +/** + * @defgroup sdk_iot_errors Codes reserved as identification for IoT errors. + * @{ + */ +#define NRF_ERROR_IOT_ERR_BASE_START (0xA000) +#define NRF_ERROR_IOT_ERR_BASE_STOP (0xAFFF) +/** @} */ + + +/** + * @defgroup sdk_common_errors Codes reserved as identification for common errors. + * @{ + */ +#define NRF_ERROR_MODULE_NOT_INITIALZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000) +#define NRF_ERROR_MUTEX_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0001) +#define NRF_ERROR_MUTEX_LOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0002) +#define NRF_ERROR_MUTEX_UNLOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0003) +#define NRF_ERROR_MUTEX_COND_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0004) +#define NRF_ERROR_MODULE_ALREADY_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0005) +#define NRF_ERROR_STORAGE_FULL (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0006) +#define NRF_ERROR_API_NOT_IMPLEMENTED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0010) +#define NRF_ERROR_FEATURE_NOT_ENABLED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0011) +/** @} */ + + +/** + * @defgroup drv_specific_errors Error / status codes specific to drivers. + * @{ + */ +#define NRF_ERROR_DRV_TWI_ERR_OVERRUN (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0000) +#define NRF_ERROR_DRV_TWI_ERR_ANACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0001) +#define NRF_ERROR_DRV_TWI_ERR_DNACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0002) +/** @} */ + +/** + * @brief API Result. + * + * @details Indicates success or failure of an API procedure. In case of failure, a comprehensive + * error code indicating cause or reason for failure is provided. + * + * Though called an API result, it could used in Asynchronous notifications callback along + * with asynchronous callback as event result. This mechanism is employed when an event + * marks the end of procedure initiated using API. API result, in this case, will only be + * an indicative of whether the procedure has been requested successfully. + */ +typedef uint32_t ret_code_t; + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_ERRORS_H__ diff --git a/third_party/NordicSemiconductor/dependencies/sdk_macros.h b/third_party/NordicSemiconductor/dependencies/sdk_macros.h new file mode 100644 index 000000000..785d4866d --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/sdk_macros.h @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2013 - 2017, 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 sdk_common_macros SDK Common Header + * @ingroup app_common + * @brief Macros for parameter checking and similar tasks + * @{ + */ + +#ifndef SDK_MACROS_H__ +#define SDK_MACROS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * err_code if the statement is not true. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is false. + */ +#define VERIFY_TRUE(statement, err_code) \ +do \ +{ \ + if (!(statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * if the statement is not true. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_TRUE_VOID(statement) VERIFY_TRUE((statement), ) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * err_code if the statement is not false. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is true. + */ +#define VERIFY_FALSE(statement, err_code) \ +do \ +{ \ + if ((statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * if the statement is not false. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_FALSE_VOID(statement) VERIFY_FALSE((statement), ) + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return err_code if the err_code is not @ref NRF_SUCCESS. + * + * @param[in] err_code The error code to check. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_SUCCESS() +#else +#define VERIFY_SUCCESS(err_code) VERIFY_TRUE((err_code) == NRF_SUCCESS, (err_code)) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return if the err_code is not @ref NRF_SUCCESS. + * + * @param[in] err_code The error code to check. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_SUCCESS_VOID() +#else +#define VERIFY_SUCCESS_VOID(err_code) VERIFY_TRUE_VOID((err_code) == NRF_SUCCESS) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return @ref NRF_ERROR_INVALID_STATE if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_MODULE_INITIALIZED() +#else +#define VERIFY_MODULE_INITIALIZED() VERIFY_TRUE((MODULE_INITIALIZED), NRF_ERROR_INVALID_STATE) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_MODULE_INITIALIZED_VOID() +#else +#define VERIFY_MODULE_INITIALIZED_VOID() VERIFY_TRUE_VOID((MODULE_INITIALIZED)) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_PARAM_NOT_NULL() +#else +#define VERIFY_PARAM_NOT_NULL(param) VERIFY_FALSE(((param) == NULL), NRF_ERROR_NULL) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_PARAM_NOT_NULL_VOID() +#else +#define VERIFY_PARAM_NOT_NULL_VOID(param) VERIFY_FALSE_VOID(((param) == NULL)) +#endif /* DISABLE_PARAM_CHECK */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_MACROS_H__ + diff --git a/third_party/NordicSemiconductor/dependencies/sdk_os.h b/third_party/NordicSemiconductor/dependencies/sdk_os.h new file mode 100644 index 000000000..569aaff3c --- /dev/null +++ b/third_party/NordicSemiconductor/dependencies/sdk_os.h @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2013 - 2017, 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. + * + */ +/** @cond */ +/**@file + * + * @defgroup sdk_os SDK OS Abstraction + * @ingroup experimental_api + * @details In order to made SDK modules independent of use of an embedded OS, and permit + * application with varied task architecture, SDK abstracts the OS specific + * elements here in order to make all other modules agnostic to the OS or task + * architecture. + * @{ + */ + +#ifndef SDK_OS_H__ +#define SDK_OS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SDK_MUTEX_DEFINE(X) +#define SDK_MUTEX_INIT(X) +#define SDK_MUTEX_LOCK(X) +#define SDK_MUTEX_UNLOCK(X) + +/** + * @defgroup os_data_type Data types. + */ + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_OS_H__ + diff --git a/third_party/NordicSemiconductor/device/nrf52840.h b/third_party/NordicSemiconductor/device/nrf52840.h index e01a77f3b..53f5e97cc 100644 --- a/third_party/NordicSemiconductor/device/nrf52840.h +++ b/third_party/NordicSemiconductor/device/nrf52840.h @@ -6,38 +6,47 @@ * nrf52840 from Nordic Semiconductor. * * @version V1 - * @date 18. November 2016 + * @date 6. June 2017 * * @note Generated with SVDConv V2.81d * from CMSIS SVD File 'nrf52840.svd' Version 1, * - * @par Copyright (c) 2016, Nordic Semiconductor ASA + * @par Copyright (c) 2010 - 2017, 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: + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: * - * * Redistributions of source code must retain the above copyright notice, this + * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - * * Redistributions in binary form 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. + * 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. * - * * 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. + * 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. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * 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. * * *******************************************************************************************************/ @@ -118,8 +127,8 @@ typedef enum { UARTE1_IRQn = 40, /*!< 40 UARTE1 */ QSPI_IRQn = 41, /*!< 41 QSPI */ CRYPTOCELL_IRQn = 42, /*!< 42 CRYPTOCELL */ - SPIM3_IRQn = 43, /*!< 43 SPIM3 */ - PWM3_IRQn = 45 /*!< 45 PWM3 */ + PWM3_IRQn = 45, /*!< 45 PWM3 */ + SPIM3_IRQn = 47 /*!< 47 SPIM3 */ } IRQn_Type; @@ -181,7 +190,7 @@ typedef enum { typedef struct { __I uint32_t PART; /*!< Part code */ - __I uint32_t VARIANT; /*!< Part variant (hardware version and production configuration). */ + __I uint32_t VARIANT; /*!< Part variant (hardware version and production configuration) */ __I uint32_t PACKAGE; /*!< Package option */ __I uint32_t RAM; /*!< RAM variant */ __I uint32_t FLASH; /*!< Flash variant */ @@ -189,33 +198,33 @@ typedef struct { } FICR_INFO_Type; typedef struct { - __I uint32_t A0; /*!< Slope definition A0. */ - __I uint32_t A1; /*!< Slope definition A1. */ - __I uint32_t A2; /*!< Slope definition A2. */ - __I uint32_t A3; /*!< Slope definition A3. */ - __I uint32_t A4; /*!< Slope definition A4. */ - __I uint32_t A5; /*!< Slope definition A5. */ - __I uint32_t B0; /*!< y-intercept B0. */ - __I uint32_t B1; /*!< y-intercept B1. */ - __I uint32_t B2; /*!< y-intercept B2. */ - __I uint32_t B3; /*!< y-intercept B3. */ - __I uint32_t B4; /*!< y-intercept B4. */ - __I uint32_t B5; /*!< y-intercept B5. */ - __I uint32_t T0; /*!< Segment end T0. */ - __I uint32_t T1; /*!< Segment end T1. */ - __I uint32_t T2; /*!< Segment end T2. */ - __I uint32_t T3; /*!< Segment end T3. */ - __I uint32_t T4; /*!< Segment end T4. */ + __I uint32_t A0; /*!< Slope definition A0 */ + __I uint32_t A1; /*!< Slope definition A1 */ + __I uint32_t A2; /*!< Slope definition A2 */ + __I uint32_t A3; /*!< Slope definition A3 */ + __I uint32_t A4; /*!< Slope definition A4 */ + __I uint32_t A5; /*!< Slope definition A5 */ + __I uint32_t B0; /*!< Y-intercept B0 */ + __I uint32_t B1; /*!< Y-intercept B1 */ + __I uint32_t B2; /*!< Y-intercept B2 */ + __I uint32_t B3; /*!< Y-intercept B3 */ + __I uint32_t B4; /*!< Y-intercept B4 */ + __I uint32_t B5; /*!< Y-intercept B5 */ + __I uint32_t T0; /*!< Segment end T0 */ + __I uint32_t T1; /*!< Segment end T1 */ + __I uint32_t T2; /*!< Segment end T2 */ + __I uint32_t T3; /*!< Segment end T3 */ + __I uint32_t T4; /*!< Segment end T4 */ } FICR_TEMP_Type; typedef struct { - __I uint32_t TAGHEADER0; /*!< Default header for NFC Tag. Software can read these values to + __I uint32_t TAGHEADER0; /*!< Default header for NFC tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ - __I uint32_t TAGHEADER1; /*!< Default header for NFC Tag. Software can read these values to + __I uint32_t TAGHEADER1; /*!< Default header for NFC tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ - __I uint32_t TAGHEADER2; /*!< Default header for NFC Tag. Software can read these values to + __I uint32_t TAGHEADER2; /*!< Default header for NFC tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ - __I uint32_t TAGHEADER3; /*!< Default header for NFC Tag. Software can read these values to + __I uint32_t TAGHEADER3; /*!< Default header for NFC tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ } FICR_NFC_Type; @@ -385,12 +394,12 @@ typedef struct { } QDEC_PSEL_Type; typedef struct { - __IO uint32_t PTR; /*!< Description cluster[0]: Beginning address in Data RAM of sequence - A */ - __IO uint32_t CNT; /*!< Description cluster[0]: Amount of values (duty cycles) in sequence - A */ + __IO uint32_t PTR; /*!< Description cluster[0]: Beginning address in Data RAM of this + sequence */ + __IO uint32_t CNT; /*!< Description cluster[0]: Amount of values (duty cycles) in this + sequence */ __IO uint32_t REFRESH; /*!< Description cluster[0]: Amount of additional PWM periods between - samples loaded to compare register (load every CNT+1 PWM periods) */ + samples loaded into compare register */ __IO uint32_t ENDDELAY; /*!< Description cluster[0]: Time added after the sequence */ __I uint32_t RESERVED1[4]; } PWM_SEQ_Type; @@ -511,7 +520,7 @@ typedef struct { typedef struct { __IO uint32_t EPOUT[8]; /*!< Description collection[0]: Amount of bytes received last in the data stage of this OUT endpoint */ - __IO uint32_t ISOOUT; /*!< Amount of bytes received last on this iso OUT data endpoint */ + __I uint32_t ISOOUT; /*!< Amount of bytes received last on this iso OUT data endpoint */ } USBD_SIZE_Type; typedef struct { @@ -576,7 +585,7 @@ typedef struct { /** - * @brief Factory Information Configuration Registers (FICR) + * @brief Factory information configuration registers (FICR) */ typedef struct { /*!< FICR Structure */ @@ -605,7 +614,7 @@ typedef struct { /*!< FICR Structure /** - * @brief User Information Configuration Registers (UICR) + * @brief User information configuration registers (UICR) */ typedef struct { /*!< UICR Structure */ @@ -622,11 +631,12 @@ typedef struct { /*!< UICR Structure __IO uint32_t APPROTECT; /*!< Access port protection */ __IO uint32_t NFCPINS; /*!< Setting of pins dedicated to NFC functionality: NFC antenna or GPIO */ - __I uint32_t RESERVED2[60]; + __IO uint32_t DEBUGCTRL; /*!< Processor debug control */ + __I uint32_t RESERVED2[59]; __IO uint32_t EXTSUPPLY; /*!< Enable external circuitry to be supplied from VDD pin. Applicable - in 'High voltage mode' only. */ - __IO uint32_t REGOUT0; /*!< GPIO reference voltage / external output supply voltage in 'High - voltage mode'. */ + in high voltage mode only. */ + __IO uint32_t REGOUT0; /*!< GPIO reference voltage / external output supply voltage in high + voltage mode */ } NRF_UICR_Type; @@ -713,10 +723,15 @@ typedef struct { /*!< CLOCK Structure __I uint32_t LFCLKSRCCOPY; /*!< Copy of LFCLKSRC register, set when LFCLKSTART task was triggered */ __I uint32_t RESERVED5[62]; __IO uint32_t LFCLKSRC; /*!< Clock source for the LFCLK */ - __I uint32_t RESERVED6[7]; + __I uint32_t RESERVED6[3]; + __IO uint32_t HFXODEBOUNCE; /*!< HFXO debounce time. The HFXO is started by triggering the TASKS_HFCLKSTART + task. */ + __I uint32_t RESERVED7[3]; __IO uint32_t CTIV; /*!< Calibration timer interval */ - __I uint32_t RESERVED7[8]; + __I uint32_t RESERVED8[8]; __IO uint32_t TRACECONFIG; /*!< Clocking options for the Trace Port debug interface */ + __I uint32_t RESERVED9[21]; + __IO uint32_t LFRCMODE; /*!< LFRC mode configuration */ } NRF_CLOCK_Type; @@ -770,18 +785,22 @@ typedef struct { /*!< RADIO Structure __IO uint32_t EVENTS_TXREADY; /*!< RADIO has ramped up and is ready to be started TX path */ __IO uint32_t EVENTS_RXREADY; /*!< RADIO has ramped up and is ready to be started RX path */ __IO uint32_t EVENTS_MHRMATCH; /*!< MAC Header match found. */ - __I uint32_t RESERVED3[40]; + __I uint32_t RESERVED3[3]; + __IO uint32_t EVENTS_PHYEND; /*!< Generated in Ble_LR125Kbit, Ble_LR500Kbit and BleIeee802154_250Kbit + modes when last bit is sent on air. */ + __I uint32_t RESERVED4[36]; __IO uint32_t SHORTS; /*!< Shortcut register */ - __I uint32_t RESERVED4[64]; + __I uint32_t RESERVED5[64]; __IO uint32_t INTENSET; /*!< Enable interrupt */ __IO uint32_t INTENCLR; /*!< Disable interrupt */ - __I uint32_t RESERVED5[61]; + __I uint32_t RESERVED6[61]; __I uint32_t CRCSTATUS; /*!< CRC status */ - __I uint32_t RESERVED6; + __I uint32_t RESERVED7; __I uint32_t RXMATCH; /*!< Received address */ __I uint32_t RXCRC; /*!< CRC field of previously received packet */ __I uint32_t DAI; /*!< Device address match index */ - __I uint32_t RESERVED7[60]; + __I uint32_t PDUSTAT; /*!< Payload status */ + __I uint32_t RESERVED8[59]; __IO uint32_t PACKETPTR; /*!< Packet pointer */ __IO uint32_t FREQUENCY; /*!< Frequency */ __IO uint32_t TXPOWER; /*!< Output power */ @@ -797,28 +816,28 @@ typedef struct { /*!< RADIO Structure __IO uint32_t CRCCNF; /*!< CRC configuration */ __IO uint32_t CRCPOLY; /*!< CRC polynomial */ __IO uint32_t CRCINIT; /*!< CRC initial value */ - __I uint32_t RESERVED8; + __I uint32_t RESERVED9; __IO uint32_t TIFS; /*!< Inter Frame Spacing in us */ __I uint32_t RSSISAMPLE; /*!< RSSI sample */ - __I uint32_t RESERVED9; + __I uint32_t RESERVED10; __I uint32_t STATE; /*!< Current radio state */ __IO uint32_t DATAWHITEIV; /*!< Data whitening initial value */ - __I uint32_t RESERVED10[2]; + __I uint32_t RESERVED11[2]; __IO uint32_t BCC; /*!< Bit counter compare */ - __I uint32_t RESERVED11[39]; + __I uint32_t RESERVED12[39]; __IO uint32_t DAB[8]; /*!< Description collection[0]: Device address base segment 0 */ __IO uint32_t DAP[8]; /*!< Description collection[0]: Device address prefix 0 */ __IO uint32_t DACNF; /*!< Device address match configuration */ __IO uint32_t MHRMATCHCONF; /*!< Search Pattern Configuration */ __IO uint32_t MHRMATCHMAS; /*!< Pattern mask */ - __I uint32_t RESERVED12; + __I uint32_t RESERVED13; __IO uint32_t MODECNF0; /*!< Radio mode configuration register 0 */ - __I uint32_t RESERVED13[3]; + __I uint32_t RESERVED14[3]; __IO uint32_t SFD; /*!< IEEE 802.15.4 Start of Frame Delimiter */ __IO uint32_t EDCNT; /*!< IEEE 802.15.4 Energy Detect Loop Count */ __IO uint32_t EDSAMPLE; /*!< IEEE 802.15.4 Energy Detect Level */ __IO uint32_t CCACTRL; /*!< IEEE 802.15.4 Clear Channel Assessment Control */ - __I uint32_t RESERVED14[611]; + __I uint32_t RESERVED15[611]; __IO uint32_t POWER; /*!< Peripheral power control */ } NRF_RADIO_Type; @@ -1891,17 +1910,16 @@ typedef struct { /*!< NVMC Structure __I uint32_t READY; /*!< Ready flag */ __I uint32_t RESERVED1[64]; __IO uint32_t CONFIG; /*!< Configuration register */ - - __IO uint32_t ERASEPAGE; /*!< Register for erasing a page in Code area */ + __IO uint32_t ERASEPAGE; /*!< Register for erasing a page in code area */ __IO uint32_t ERASEALL; /*!< Register for erasing all non-volatile user memory */ - __IO uint32_t ERASEPCR0; /*!< Deprecated register - Register for erasing a page in Code area. + __IO uint32_t ERASEPCR0; /*!< Deprecated register - Register for erasing a page in code area. Equivalent to ERASEPAGE. */ - __IO uint32_t ERASEUICR; /*!< Register for erasing User Information Configuration Registers */ + __IO uint32_t ERASEUICR; /*!< Register for erasing user information configuration registers */ __I uint32_t RESERVED2[10]; - __IO uint32_t ICACHECNF; /*!< I-Code cache configuration register. */ + __IO uint32_t ICACHECNF; /*!< I-code cache configuration register. */ __I uint32_t RESERVED3; - __IO uint32_t IHIT; /*!< I-Code cache hit counter. */ - __IO uint32_t IMISS; /*!< I-Code cache miss counter. */ + __IO uint32_t IHIT; /*!< I-code cache hit counter. */ + __IO uint32_t IMISS; /*!< I-code cache miss counter. */ } NRF_NVMC_Type; @@ -1915,10 +1933,7 @@ typedef struct { /*!< NVMC Structure */ typedef struct { /*!< ACL Structure */ - __I uint32_t RESERVED0[449]; - __IO uint32_t DISABLEINDEBUG; /*!< Disable all ACL protection mechanisms for regions while in debug - mode */ - __I uint32_t RESERVED1[62]; + __I uint32_t RESERVED0[512]; ACL_ACL_Type ACL[8]; /*!< Unspecified */ } NRF_ACL_Type; @@ -2134,7 +2149,9 @@ typedef struct { /*!< USBD Structure __O uint32_t EPSTALL; /*!< STALL endpoints */ __IO uint32_t ISOSPLIT; /*!< Controls the split of ISO buffers */ __I uint32_t FRAMECNTR; /*!< Returns the current value of the start of frame counter */ - __I uint32_t RESERVED9[3]; + __I uint32_t RESERVED9[2]; + __IO uint32_t LOWPOWER; /*!< First silicon only: Controls USBD peripheral low-power mode + during USB suspend */ __IO uint32_t ISOINCONFIG; /*!< Controls the response of the ISO IN endpoint to an IN token when no data is ready to be sent */ __I uint32_t RESERVED10[51]; @@ -2160,7 +2177,8 @@ typedef struct { /*!< QSPI Structure __O uint32_t TASKS_READSTART; /*!< Start transfer from external flash memory to internal RAM */ __O uint32_t TASKS_WRITESTART; /*!< Start transfer from internal RAM to external flash memory */ __O uint32_t TASKS_ERASESTART; /*!< Start external flash memory erase operation */ - __I uint32_t RESERVED0[60]; + __O uint32_t TASKS_DEACTIVATE; /*!< Deactivate QSPI interface */ + __I uint32_t RESERVED0[59]; __IO uint32_t EVENTS_READY; /*!< QSPI peripheral is ready. This event will be generated as a response to any QSPI task. */ __I uint32_t RESERVED1[127]; @@ -2323,8 +2341,8 @@ typedef struct { /*!< CRYPTOCELL Structure #define NRF_USBD_BASE 0x40027000UL #define NRF_UARTE1_BASE 0x40028000UL #define NRF_QSPI_BASE 0x40029000UL -#define NRF_SPIM3_BASE 0x4002B000UL #define NRF_PWM3_BASE 0x4002D000UL +#define NRF_SPIM3_BASE 0x4002F000UL #define NRF_P0_BASE 0x50000000UL #define NRF_P1_BASE 0x50000300UL #define NRF_CRYPTOCELL_BASE 0x5002A000UL @@ -2401,8 +2419,8 @@ typedef struct { /*!< CRYPTOCELL Structure #define NRF_USBD ((NRF_USBD_Type *) NRF_USBD_BASE) #define NRF_UARTE1 ((NRF_UARTE_Type *) NRF_UARTE1_BASE) #define NRF_QSPI ((NRF_QSPI_Type *) NRF_QSPI_BASE) -#define NRF_SPIM3 ((NRF_SPIM_Type *) NRF_SPIM3_BASE) #define NRF_PWM3 ((NRF_PWM_Type *) NRF_PWM3_BASE) +#define NRF_SPIM3 ((NRF_SPIM_Type *) NRF_SPIM3_BASE) #define NRF_P0 ((NRF_GPIO_Type *) NRF_P0_BASE) #define NRF_P1 ((NRF_GPIO_Type *) NRF_P1_BASE) #define NRF_CRYPTOCELL ((NRF_CRYPTOCELL_Type *) NRF_CRYPTOCELL_BASE) @@ -2418,3 +2436,4 @@ typedef struct { /*!< CRYPTOCELL Structure #endif /* nrf52840_H */ + diff --git a/third_party/NordicSemiconductor/device/nrf52840_bitfields.h b/third_party/NordicSemiconductor/device/nrf52840_bitfields.h index 00f1a0b2c..01e5250c2 100644 --- a/third_party/NordicSemiconductor/device/nrf52840_bitfields.h +++ b/third_party/NordicSemiconductor/device/nrf52840_bitfields.h @@ -1,32 +1,43 @@ -/* Copyright (c) 2016, 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: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form 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. - * - * * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - * - */ +/* + +Copyright (c) 2010 - 2017, 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 __NRF52840_BITS_H #define __NRF52840_BITS_H @@ -132,15 +143,6 @@ /* Peripheral: ACL */ /* Description: Access control lists */ -/* Register: ACL_DISABLEINDEBUG */ -/* Description: Disable all ACL protection mechanisms for regions while in debug mode */ - -/* Bit 0 : Disable the protection mechanism for regions while in debug mode. */ -#define ACL_DISABLEINDEBUG_DISABLEINDEBUG_Pos (0UL) /*!< Position of DISABLEINDEBUG field. */ -#define ACL_DISABLEINDEBUG_DISABLEINDEBUG_Msk (0x1UL << ACL_DISABLEINDEBUG_DISABLEINDEBUG_Pos) /*!< Bit mask of DISABLEINDEBUG field. */ -#define ACL_DISABLEINDEBUG_DISABLEINDEBUG_Enabled (0UL) /*!< ACL is enabled in debug mode */ -#define ACL_DISABLEINDEBUG_DISABLEINDEBUG_Disabled (1UL) /*!< ACL is disabled in debug mode */ - /* Register: ACL_ACL_ADDR */ /* Description: Description cluster[0]: Configure the word-aligned start address of region 0 to protect */ @@ -255,8 +257,8 @@ /* Bit 24 : Packet length configuration */ #define CCM_MODE_LENGTH_Pos (24UL) /*!< Position of LENGTH field. */ #define CCM_MODE_LENGTH_Msk (0x1UL << CCM_MODE_LENGTH_Pos) /*!< Bit mask of LENGTH field. */ -#define CCM_MODE_LENGTH_Default (0UL) /*!< Default length. Effective length of LENGTH field in encrypted/decrypted packet is 5 bits. A key-stream for packets up to 27 bytes will be generated. */ -#define CCM_MODE_LENGTH_Extended (1UL) /*!< Extended length. Effective length of LENGTH field in encrypted/decrypted packet is 8 bits. A key-stream for packets up to MAXPACKETSIZE bytes will be generated. */ +#define CCM_MODE_LENGTH_Default (0UL) /*!< Default length. Effective length of LENGTH field in encrypted/decrypted packet is 5 bits. A key-stream for packet payloads up to 27 bytes will be generated. */ +#define CCM_MODE_LENGTH_Extended (1UL) /*!< Extended length. Effective length of LENGTH field in encrypted/decrypted packet is 8 bits. A key-stream for packet payloads up to MAXPACKETSIZE bytes will be generated. */ /* Bits 17..16 : Radio data rate that the CCM shall run synchronous with */ #define CCM_MODE_DATARATE_Pos (16UL) /*!< Position of DATARATE field. */ @@ -303,7 +305,7 @@ /* Register: CCM_MAXPACKETSIZE */ /* Description: Length of key-stream generated when MODE.LENGTH = Extended. */ -/* Bits 7..0 : Length of key-stream generated when MODE.LENGTH = Extended. This value must be greater or equal to the subsequent packet to be encrypted/decrypted. */ +/* Bits 7..0 : Length of key-stream generated when MODE.LENGTH = Extended. This value must be greater or equal to the subsequent packet payload to be encrypted/decrypted. */ #define CCM_MAXPACKETSIZE_MAXPACKETSIZE_Pos (0UL) /*!< Position of MAXPACKETSIZE field. */ #define CCM_MAXPACKETSIZE_MAXPACKETSIZE_Msk (0xFFUL << CCM_MAXPACKETSIZE_MAXPACKETSIZE_Pos) /*!< Bit mask of MAXPACKETSIZE field. */ @@ -432,7 +434,6 @@ #define CLOCK_LFCLKSTAT_SRC_RC (0UL) /*!< 32.768 kHz RC oscillator */ #define CLOCK_LFCLKSTAT_SRC_Xtal (1UL) /*!< 32.768 kHz crystal oscillator */ #define CLOCK_LFCLKSTAT_SRC_Synth (2UL) /*!< 32.768 kHz synthesized from HFCLK */ -#define CLOCK_LFCLKSTAT_SRC_LFULP (3UL) /*!< 32.768 kHz ultra low power RC oscillator */ /* Register: CLOCK_LFCLKSRCCOPY */ /* Description: Copy of LFCLKSRC register, set when LFCLKSTART task was triggered */ @@ -443,7 +444,6 @@ #define CLOCK_LFCLKSRCCOPY_SRC_RC (0UL) /*!< 32.768 kHz RC oscillator */ #define CLOCK_LFCLKSRCCOPY_SRC_Xtal (1UL) /*!< 32.768 kHz crystal oscillator */ #define CLOCK_LFCLKSRCCOPY_SRC_Synth (2UL) /*!< 32.768 kHz synthesized from HFCLK */ -#define CLOCK_LFCLKSRCCOPY_SRC_LFULP (3UL) /*!< 32.768 kHz ultra low power RC oscillator */ /* Register: CLOCK_LFCLKSRC */ /* Description: Clock source for the LFCLK */ @@ -466,7 +466,13 @@ #define CLOCK_LFCLKSRC_SRC_RC (0UL) /*!< 32.768 kHz RC oscillator */ #define CLOCK_LFCLKSRC_SRC_Xtal (1UL) /*!< 32.768 kHz crystal oscillator */ #define CLOCK_LFCLKSRC_SRC_Synth (2UL) /*!< 32.768 kHz synthesized from HFCLK */ -#define CLOCK_LFCLKSRC_SRC_LFULP (3UL) /*!< 32.768 kHz ultra low power RC oscillator */ + +/* Register: CLOCK_HFXODEBOUNCE */ +/* Description: HFXO debounce time. The HFXO is started by triggering the TASKS_HFCLKSTART task. */ + +/* Bits 7..0 : HFXO debounce time. Debounce time = HFXODEBOUNCE * 16 us. */ +#define CLOCK_HFXODEBOUNCE_HFXODEBOUNCE_Pos (0UL) /*!< Position of HFXODEBOUNCE field. */ +#define CLOCK_HFXODEBOUNCE_HFXODEBOUNCE_Msk (0xFFUL << CLOCK_HFXODEBOUNCE_HFXODEBOUNCE_Pos) /*!< Bit mask of HFXODEBOUNCE field. */ /* Register: CLOCK_CTIV */ /* Description: Calibration timer interval */ @@ -478,12 +484,12 @@ /* Register: CLOCK_TRACECONFIG */ /* Description: Clocking options for the Trace Port debug interface */ -/* Bits 17..16 : Pin multiplexing of trace signals. */ +/* Bits 17..16 : Pin multiplexing of trace signals. See pin assignment chapter for more details. */ #define CLOCK_TRACECONFIG_TRACEMUX_Pos (16UL) /*!< Position of TRACEMUX field. */ #define CLOCK_TRACECONFIG_TRACEMUX_Msk (0x3UL << CLOCK_TRACECONFIG_TRACEMUX_Pos) /*!< Bit mask of TRACEMUX field. */ -#define CLOCK_TRACECONFIG_TRACEMUX_GPIO (0UL) /*!< GPIOs multiplexed onto all trace-pins */ -#define CLOCK_TRACECONFIG_TRACEMUX_Serial (1UL) /*!< SWO multiplexed onto P0.18, GPIO multiplexed onto other trace pins */ -#define CLOCK_TRACECONFIG_TRACEMUX_Parallel (2UL) /*!< TRACECLK and TRACEDATA multiplexed onto P0.20, P0.18, P0.16, P0.15 and P0.14. */ +#define CLOCK_TRACECONFIG_TRACEMUX_GPIO (0UL) /*!< No trace signals routed to pins. All pins can be used as regular GPIOs. */ +#define CLOCK_TRACECONFIG_TRACEMUX_Serial (1UL) /*!< SWO trace signal routed to pin. Remaining pins can be used as regular GPIOs. */ +#define CLOCK_TRACECONFIG_TRACEMUX_Parallel (2UL) /*!< All trace signals (TRACECLK and TRACEDATA[n]) routed to pins. */ /* Bits 1..0 : Speed of Trace Port clock. Note that the TRACECLK pin will output this clock divided by two. */ #define CLOCK_TRACECONFIG_TRACEPORTSPEED_Pos (0UL) /*!< Position of TRACEPORTSPEED field. */ @@ -493,6 +499,21 @@ #define CLOCK_TRACECONFIG_TRACEPORTSPEED_8MHz (2UL) /*!< 8 MHz Trace Port clock (TRACECLK = 4 MHz) */ #define CLOCK_TRACECONFIG_TRACEPORTSPEED_4MHz (3UL) /*!< 4 MHz Trace Port clock (TRACECLK = 2 MHz) */ +/* Register: CLOCK_LFRCMODE */ +/* Description: LFRC mode configuration */ + +/* Bit 16 : Active LFRC mode. This field is read only. */ +#define CLOCK_LFRCMODE_STATUS_Pos (16UL) /*!< Position of STATUS field. */ +#define CLOCK_LFRCMODE_STATUS_Msk (0x1UL << CLOCK_LFRCMODE_STATUS_Pos) /*!< Bit mask of STATUS field. */ +#define CLOCK_LFRCMODE_STATUS_Normal (0UL) /*!< Normal mode */ +#define CLOCK_LFRCMODE_STATUS_ULP (1UL) /*!< Ultra-low power mode (ULP) */ + +/* Bit 0 : Set LFRC mode */ +#define CLOCK_LFRCMODE_MODE_Pos (0UL) /*!< Position of MODE field. */ +#define CLOCK_LFRCMODE_MODE_Msk (0x1UL << CLOCK_LFRCMODE_MODE_Pos) /*!< Bit mask of MODE field. */ +#define CLOCK_LFRCMODE_MODE_Normal (0UL) /*!< Normal mode */ +#define CLOCK_LFRCMODE_MODE_ULP (1UL) /*!< Ultra-low power mode (ULP) */ + /* Peripheral: COMP */ /* Description: Comparator */ @@ -662,7 +683,7 @@ #define COMP_REFSEL_REFSEL_Int1V8 (1UL) /*!< VREF = internal 1.8 V reference (VDD >= VREF + 0.2 V) */ #define COMP_REFSEL_REFSEL_Int2V4 (2UL) /*!< VREF = internal 2.4 V reference (VDD >= VREF + 0.2 V) */ #define COMP_REFSEL_REFSEL_VDD (4UL) /*!< VREF = VDD */ -#define COMP_REFSEL_REFSEL_ARef (7UL) /*!< VREF = AREF (VDD >= VREF >= AREFMIN) */ +#define COMP_REFSEL_REFSEL_ARef (5UL) /*!< VREF = AREF (VDD >= VREF >= AREFMIN) */ /* Register: COMP_EXTREFSEL */ /* Description: External reference select */ @@ -1113,7 +1134,7 @@ /* Peripheral: FICR */ -/* Description: Factory Information Configuration Registers */ +/* Description: Factory information configuration registers */ /* Register: FICR_CODEPAGESIZE */ /* Description: Code memory page size */ @@ -1176,7 +1197,7 @@ #define FICR_INFO_PART_PART_Unspecified (0xFFFFFFFFUL) /*!< Unspecified */ /* Register: FICR_INFO_VARIANT */ -/* Description: Part variant (hardware version and production configuration). */ +/* Description: Part variant (hardware version and production configuration) */ /* Bits 31..0 : Part variant (hardware version and production configuration). Encoded as ASCII. */ #define FICR_INFO_VARIANT_VARIANT_Pos (0UL) /*!< Position of VARIANT field. */ @@ -1225,126 +1246,126 @@ #define FICR_INFO_FLASH_FLASH_Unspecified (0xFFFFFFFFUL) /*!< Unspecified */ /* Register: FICR_TEMP_A0 */ -/* Description: Slope definition A0. */ +/* Description: Slope definition A0 */ /* Bits 11..0 : A (slope definition) register. */ #define FICR_TEMP_A0_A_Pos (0UL) /*!< Position of A field. */ #define FICR_TEMP_A0_A_Msk (0xFFFUL << FICR_TEMP_A0_A_Pos) /*!< Bit mask of A field. */ /* Register: FICR_TEMP_A1 */ -/* Description: Slope definition A1. */ +/* Description: Slope definition A1 */ /* Bits 11..0 : A (slope definition) register. */ #define FICR_TEMP_A1_A_Pos (0UL) /*!< Position of A field. */ #define FICR_TEMP_A1_A_Msk (0xFFFUL << FICR_TEMP_A1_A_Pos) /*!< Bit mask of A field. */ /* Register: FICR_TEMP_A2 */ -/* Description: Slope definition A2. */ +/* Description: Slope definition A2 */ /* Bits 11..0 : A (slope definition) register. */ #define FICR_TEMP_A2_A_Pos (0UL) /*!< Position of A field. */ #define FICR_TEMP_A2_A_Msk (0xFFFUL << FICR_TEMP_A2_A_Pos) /*!< Bit mask of A field. */ /* Register: FICR_TEMP_A3 */ -/* Description: Slope definition A3. */ +/* Description: Slope definition A3 */ /* Bits 11..0 : A (slope definition) register. */ #define FICR_TEMP_A3_A_Pos (0UL) /*!< Position of A field. */ #define FICR_TEMP_A3_A_Msk (0xFFFUL << FICR_TEMP_A3_A_Pos) /*!< Bit mask of A field. */ /* Register: FICR_TEMP_A4 */ -/* Description: Slope definition A4. */ +/* Description: Slope definition A4 */ /* Bits 11..0 : A (slope definition) register. */ #define FICR_TEMP_A4_A_Pos (0UL) /*!< Position of A field. */ #define FICR_TEMP_A4_A_Msk (0xFFFUL << FICR_TEMP_A4_A_Pos) /*!< Bit mask of A field. */ /* Register: FICR_TEMP_A5 */ -/* Description: Slope definition A5. */ +/* Description: Slope definition A5 */ /* Bits 11..0 : A (slope definition) register. */ #define FICR_TEMP_A5_A_Pos (0UL) /*!< Position of A field. */ #define FICR_TEMP_A5_A_Msk (0xFFFUL << FICR_TEMP_A5_A_Pos) /*!< Bit mask of A field. */ /* Register: FICR_TEMP_B0 */ -/* Description: y-intercept B0. */ +/* Description: Y-intercept B0 */ /* Bits 13..0 : B (y-intercept) */ #define FICR_TEMP_B0_B_Pos (0UL) /*!< Position of B field. */ #define FICR_TEMP_B0_B_Msk (0x3FFFUL << FICR_TEMP_B0_B_Pos) /*!< Bit mask of B field. */ /* Register: FICR_TEMP_B1 */ -/* Description: y-intercept B1. */ +/* Description: Y-intercept B1 */ /* Bits 13..0 : B (y-intercept) */ #define FICR_TEMP_B1_B_Pos (0UL) /*!< Position of B field. */ #define FICR_TEMP_B1_B_Msk (0x3FFFUL << FICR_TEMP_B1_B_Pos) /*!< Bit mask of B field. */ /* Register: FICR_TEMP_B2 */ -/* Description: y-intercept B2. */ +/* Description: Y-intercept B2 */ /* Bits 13..0 : B (y-intercept) */ #define FICR_TEMP_B2_B_Pos (0UL) /*!< Position of B field. */ #define FICR_TEMP_B2_B_Msk (0x3FFFUL << FICR_TEMP_B2_B_Pos) /*!< Bit mask of B field. */ /* Register: FICR_TEMP_B3 */ -/* Description: y-intercept B3. */ +/* Description: Y-intercept B3 */ /* Bits 13..0 : B (y-intercept) */ #define FICR_TEMP_B3_B_Pos (0UL) /*!< Position of B field. */ #define FICR_TEMP_B3_B_Msk (0x3FFFUL << FICR_TEMP_B3_B_Pos) /*!< Bit mask of B field. */ /* Register: FICR_TEMP_B4 */ -/* Description: y-intercept B4. */ +/* Description: Y-intercept B4 */ /* Bits 13..0 : B (y-intercept) */ #define FICR_TEMP_B4_B_Pos (0UL) /*!< Position of B field. */ #define FICR_TEMP_B4_B_Msk (0x3FFFUL << FICR_TEMP_B4_B_Pos) /*!< Bit mask of B field. */ /* Register: FICR_TEMP_B5 */ -/* Description: y-intercept B5. */ +/* Description: Y-intercept B5 */ /* Bits 13..0 : B (y-intercept) */ #define FICR_TEMP_B5_B_Pos (0UL) /*!< Position of B field. */ #define FICR_TEMP_B5_B_Msk (0x3FFFUL << FICR_TEMP_B5_B_Pos) /*!< Bit mask of B field. */ /* Register: FICR_TEMP_T0 */ -/* Description: Segment end T0. */ +/* Description: Segment end T0 */ -/* Bits 7..0 : T (segment end)register. */ +/* Bits 7..0 : T (segment end) register */ #define FICR_TEMP_T0_T_Pos (0UL) /*!< Position of T field. */ #define FICR_TEMP_T0_T_Msk (0xFFUL << FICR_TEMP_T0_T_Pos) /*!< Bit mask of T field. */ /* Register: FICR_TEMP_T1 */ -/* Description: Segment end T1. */ +/* Description: Segment end T1 */ -/* Bits 7..0 : T (segment end)register. */ +/* Bits 7..0 : T (segment end) register */ #define FICR_TEMP_T1_T_Pos (0UL) /*!< Position of T field. */ #define FICR_TEMP_T1_T_Msk (0xFFUL << FICR_TEMP_T1_T_Pos) /*!< Bit mask of T field. */ /* Register: FICR_TEMP_T2 */ -/* Description: Segment end T2. */ +/* Description: Segment end T2 */ -/* Bits 7..0 : T (segment end)register. */ +/* Bits 7..0 : T (segment end) register */ #define FICR_TEMP_T2_T_Pos (0UL) /*!< Position of T field. */ #define FICR_TEMP_T2_T_Msk (0xFFUL << FICR_TEMP_T2_T_Pos) /*!< Bit mask of T field. */ /* Register: FICR_TEMP_T3 */ -/* Description: Segment end T3. */ +/* Description: Segment end T3 */ -/* Bits 7..0 : T (segment end)register. */ +/* Bits 7..0 : T (segment end) register */ #define FICR_TEMP_T3_T_Pos (0UL) /*!< Position of T field. */ #define FICR_TEMP_T3_T_Msk (0xFFUL << FICR_TEMP_T3_T_Pos) /*!< Bit mask of T field. */ /* Register: FICR_TEMP_T4 */ -/* Description: Segment end T4. */ +/* Description: Segment end T4 */ -/* Bits 7..0 : T (segment end)register. */ +/* Bits 7..0 : T (segment end) register */ #define FICR_TEMP_T4_T_Pos (0UL) /*!< Position of T field. */ #define FICR_TEMP_T4_T_Msk (0xFFUL << FICR_TEMP_T4_T_Pos) /*!< Bit mask of T field. */ /* Register: FICR_NFC_TAGHEADER0 */ -/* Description: Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ +/* Description: Default header for NFC tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ /* Bits 31..24 : Unique identifier byte 3 */ #define FICR_NFC_TAGHEADER0_UD3_Pos (24UL) /*!< Position of UD3 field. */ @@ -1363,7 +1384,7 @@ #define FICR_NFC_TAGHEADER0_MFGID_Msk (0xFFUL << FICR_NFC_TAGHEADER0_MFGID_Pos) /*!< Bit mask of MFGID field. */ /* Register: FICR_NFC_TAGHEADER1 */ -/* Description: Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ +/* Description: Default header for NFC tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ /* Bits 31..24 : Unique identifier byte 7 */ #define FICR_NFC_TAGHEADER1_UD7_Pos (24UL) /*!< Position of UD7 field. */ @@ -1382,7 +1403,7 @@ #define FICR_NFC_TAGHEADER1_UD4_Msk (0xFFUL << FICR_NFC_TAGHEADER1_UD4_Pos) /*!< Bit mask of UD4 field. */ /* Register: FICR_NFC_TAGHEADER2 */ -/* Description: Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ +/* Description: Default header for NFC tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ /* Bits 31..24 : Unique identifier byte 11 */ #define FICR_NFC_TAGHEADER2_UD11_Pos (24UL) /*!< Position of UD11 field. */ @@ -1401,7 +1422,7 @@ #define FICR_NFC_TAGHEADER2_UD8_Msk (0xFFUL << FICR_NFC_TAGHEADER2_UD8_Pos) /*!< Bit mask of UD8 field. */ /* Register: FICR_NFC_TAGHEADER3 */ -/* Description: Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ +/* Description: Default header for NFC tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. */ /* Bits 31..24 : Unique identifier byte 15 */ #define FICR_NFC_TAGHEADER3_UD15_Pos (24UL) /*!< Position of UD15 field. */ @@ -1572,9 +1593,9 @@ #define GPIOTE_CONFIG_POLARITY_HiToLo (2UL) /*!< Task mode: Clear pin from OUT[n] task. Event mode: Generate IN[n] event when falling edge on pin. */ #define GPIOTE_CONFIG_POLARITY_Toggle (3UL) /*!< Task mode: Toggle pin from OUT[n]. Event mode: Generate IN[n] when any change on pin. */ -/* Bits 14..13 : Port number */ +/* Bit 13 : Port number */ #define GPIOTE_CONFIG_PORT_Pos (13UL) /*!< Position of PORT field. */ -#define GPIOTE_CONFIG_PORT_Msk (0x3UL << GPIOTE_CONFIG_PORT_Pos) /*!< Bit mask of PORT field. */ +#define GPIOTE_CONFIG_PORT_Msk (0x1UL << GPIOTE_CONFIG_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 12..8 : GPIO number associated with SET[n], CLR[n] and OUT[n] tasks and IN[n] event */ #define GPIOTE_CONFIG_PSEL_Pos (8UL) /*!< Position of PSEL field. */ @@ -1814,9 +1835,9 @@ #define I2S_PSEL_MCK_CONNECT_Connected (0UL) /*!< Connect */ #define I2S_PSEL_MCK_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 9..8 : Port number */ +/* Bit 8 : Port number */ #define I2S_PSEL_MCK_PORT_Pos (8UL) /*!< Position of PORT field. */ -#define I2S_PSEL_MCK_PORT_Msk (0x3UL << I2S_PSEL_MCK_PORT_Pos) /*!< Bit mask of PORT field. */ +#define I2S_PSEL_MCK_PORT_Msk (0x1UL << I2S_PSEL_MCK_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define I2S_PSEL_MCK_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -1831,9 +1852,9 @@ #define I2S_PSEL_SCK_CONNECT_Connected (0UL) /*!< Connect */ #define I2S_PSEL_SCK_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 9..8 : Port number */ +/* Bit 8 : Port number */ #define I2S_PSEL_SCK_PORT_Pos (8UL) /*!< Position of PORT field. */ -#define I2S_PSEL_SCK_PORT_Msk (0x3UL << I2S_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ +#define I2S_PSEL_SCK_PORT_Msk (0x1UL << I2S_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define I2S_PSEL_SCK_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -1848,9 +1869,9 @@ #define I2S_PSEL_LRCK_CONNECT_Connected (0UL) /*!< Connect */ #define I2S_PSEL_LRCK_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 9..8 : Port number */ +/* Bit 8 : Port number */ #define I2S_PSEL_LRCK_PORT_Pos (8UL) /*!< Position of PORT field. */ -#define I2S_PSEL_LRCK_PORT_Msk (0x3UL << I2S_PSEL_LRCK_PORT_Pos) /*!< Bit mask of PORT field. */ +#define I2S_PSEL_LRCK_PORT_Msk (0x1UL << I2S_PSEL_LRCK_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define I2S_PSEL_LRCK_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -1865,9 +1886,9 @@ #define I2S_PSEL_SDIN_CONNECT_Connected (0UL) /*!< Connect */ #define I2S_PSEL_SDIN_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 9..8 : Port number */ +/* Bit 8 : Port number */ #define I2S_PSEL_SDIN_PORT_Pos (8UL) /*!< Position of PORT field. */ -#define I2S_PSEL_SDIN_PORT_Msk (0x3UL << I2S_PSEL_SDIN_PORT_Pos) /*!< Bit mask of PORT field. */ +#define I2S_PSEL_SDIN_PORT_Msk (0x1UL << I2S_PSEL_SDIN_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define I2S_PSEL_SDIN_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -1882,9 +1903,9 @@ #define I2S_PSEL_SDOUT_CONNECT_Connected (0UL) /*!< Connect */ #define I2S_PSEL_SDOUT_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 9..8 : Port number */ +/* Bit 8 : Port number */ #define I2S_PSEL_SDOUT_PORT_Pos (8UL) /*!< Position of PORT field. */ -#define I2S_PSEL_SDOUT_PORT_Msk (0x3UL << I2S_PSEL_SDOUT_PORT_Pos) /*!< Bit mask of PORT field. */ +#define I2S_PSEL_SDOUT_PORT_Msk (0x1UL << I2S_PSEL_SDOUT_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define I2S_PSEL_SDOUT_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -3837,9 +3858,9 @@ /* Register: NFCT_FRAMEDELAYMAX */ /* Description: Maximum frame delay */ -/* Bits 15..0 : Maximum frame delay in number of 13.56 MHz clocks */ +/* Bits 19..0 : Maximum frame delay in number of 13.56 MHz clocks */ #define NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Pos (0UL) /*!< Position of FRAMEDELAYMAX field. */ -#define NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Msk (0xFFFFUL << NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Pos) /*!< Bit mask of FRAMEDELAYMAX field. */ +#define NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Msk (0xFFFFFUL << NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Pos) /*!< Bit mask of FRAMEDELAYMAX field. */ /* Register: NFCT_FRAMEDELAYMODE */ /* Description: Configuration register for the Frame Delay Timer */ @@ -4016,7 +4037,7 @@ #define NFCT_SENSRES_RFU5_Pos (5UL) /*!< Position of RFU5 field. */ #define NFCT_SENSRES_RFU5_Msk (0x1UL << NFCT_SENSRES_RFU5_Pos) /*!< Bit mask of RFU5 field. */ -/* Bits 4..0 : Bit frame SDD as defined by the b5:b1 of byte 1 in SENS_RES response in the NFC Forum, NFC Digital Protocol Technical Specification */ +/* Bits 4..0 : Bit frame SDD as defined by the b5:b1 of byte 1 in SENS_RES response in the NFC Forum, NFC Digital Protocol Technical Specification */ #define NFCT_SENSRES_BITFRAMESDD_Pos (0UL) /*!< Position of BITFRAMESDD field. */ #define NFCT_SENSRES_BITFRAMESDD_Msk (0x1FUL << NFCT_SENSRES_BITFRAMESDD_Pos) /*!< Bit mask of BITFRAMESDD field. */ #define NFCT_SENSRES_BITFRAMESDD_SDD00000 (0UL) /*!< SDD pattern 00000 */ @@ -4069,20 +4090,20 @@ #define NVMC_CONFIG_WEN_Pos (0UL) /*!< Position of WEN field. */ #define NVMC_CONFIG_WEN_Msk (0x3UL << NVMC_CONFIG_WEN_Pos) /*!< Bit mask of WEN field. */ #define NVMC_CONFIG_WEN_Ren (0UL) /*!< Read only access */ -#define NVMC_CONFIG_WEN_Wen (1UL) /*!< Write Enabled */ +#define NVMC_CONFIG_WEN_Wen (1UL) /*!< Write enabled */ #define NVMC_CONFIG_WEN_Een (2UL) /*!< Erase enabled */ /* Register: NVMC_ERASEPAGE */ -/* Description: Register for erasing a page in Code area */ +/* Description: Register for erasing a page in code area */ -/* Bits 31..0 : Register for starting erase of a page in Code area */ +/* Bits 31..0 : Register for starting erase of a page in code area */ #define NVMC_ERASEPAGE_ERASEPAGE_Pos (0UL) /*!< Position of ERASEPAGE field. */ #define NVMC_ERASEPAGE_ERASEPAGE_Msk (0xFFFFFFFFUL << NVMC_ERASEPAGE_ERASEPAGE_Pos) /*!< Bit mask of ERASEPAGE field. */ /* Register: NVMC_ERASEPCR1 */ -/* Description: Deprecated register - Register for erasing a page in Code area. Equivalent to ERASEPAGE. */ +/* Description: Deprecated register - Register for erasing a page in code area. Equivalent to ERASEPAGE. */ -/* Bits 31..0 : Register for erasing a page in Code area. Equivalent to ERASEPAGE. */ +/* Bits 31..0 : Register for erasing a page in code area. Equivalent to ERASEPAGE. */ #define NVMC_ERASEPCR1_ERASEPCR1_Pos (0UL) /*!< Position of ERASEPCR1 field. */ #define NVMC_ERASEPCR1_ERASEPCR1_Msk (0xFFFFFFFFUL << NVMC_ERASEPCR1_ERASEPCR1_Pos) /*!< Bit mask of ERASEPCR1 field. */ @@ -4096,23 +4117,23 @@ #define NVMC_ERASEALL_ERASEALL_Erase (1UL) /*!< Start chip erase */ /* Register: NVMC_ERASEPCR0 */ -/* Description: Deprecated register - Register for erasing a page in Code area. Equivalent to ERASEPAGE. */ +/* Description: Deprecated register - Register for erasing a page in code area. Equivalent to ERASEPAGE. */ -/* Bits 31..0 : Register for starting erase of a page in Code area. Equivalent to ERASEPAGE. */ +/* Bits 31..0 : Register for starting erase of a page in code area. Equivalent to ERASEPAGE. */ #define NVMC_ERASEPCR0_ERASEPCR0_Pos (0UL) /*!< Position of ERASEPCR0 field. */ #define NVMC_ERASEPCR0_ERASEPCR0_Msk (0xFFFFFFFFUL << NVMC_ERASEPCR0_ERASEPCR0_Pos) /*!< Bit mask of ERASEPCR0 field. */ /* Register: NVMC_ERASEUICR */ -/* Description: Register for erasing User Information Configuration Registers */ +/* Description: Register for erasing user information configuration registers */ -/* Bit 0 : Register starting erase of all User Information Configuration Registers. Note that the erase must be enabled using CONFIG.WEN before the UICR can be erased. */ +/* Bit 0 : Register starting erase of all user information configuration registers. Note that the erase must be enabled using CONFIG.WEN before the UICR can be erased. */ #define NVMC_ERASEUICR_ERASEUICR_Pos (0UL) /*!< Position of ERASEUICR field. */ #define NVMC_ERASEUICR_ERASEUICR_Msk (0x1UL << NVMC_ERASEUICR_ERASEUICR_Pos) /*!< Bit mask of ERASEUICR field. */ #define NVMC_ERASEUICR_ERASEUICR_NoOperation (0UL) /*!< No operation */ #define NVMC_ERASEUICR_ERASEUICR_Erase (1UL) /*!< Start erase of UICR */ /* Register: NVMC_ICACHECNF */ -/* Description: I-Code cache configuration register. */ +/* Description: I-code cache configuration register. */ /* Bit 8 : Cache profiling enable */ #define NVMC_ICACHECNF_CACHEPROFEN_Pos (8UL) /*!< Position of CACHEPROFEN field. */ @@ -4127,14 +4148,14 @@ #define NVMC_ICACHECNF_CACHEEN_Enabled (1UL) /*!< Enable cache */ /* Register: NVMC_IHIT */ -/* Description: I-Code cache hit counter. */ +/* Description: I-code cache hit counter. */ /* Bits 31..0 : Number of cache hits */ #define NVMC_IHIT_HITS_Pos (0UL) /*!< Position of HITS field. */ #define NVMC_IHIT_HITS_Msk (0xFFFFFFFFUL << NVMC_IHIT_HITS_Pos) /*!< Bit mask of HITS field. */ /* Register: NVMC_IMISS */ -/* Description: I-Code cache miss counter. */ +/* Description: I-code cache miss counter. */ /* Bits 31..0 : Number of cache misses */ #define NVMC_IMISS_MISSES_Pos (0UL) /*!< Position of MISSES field. */ @@ -6030,9 +6051,9 @@ #define PDM_PSEL_CLK_CONNECT_Connected (0UL) /*!< Connect */ #define PDM_PSEL_CLK_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define PDM_PSEL_CLK_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define PDM_PSEL_CLK_PORT_Msk (0x3UL << PDM_PSEL_CLK_PORT_Pos) /*!< Bit mask of PORT field. */ +#define PDM_PSEL_CLK_PORT_Msk (0x1UL << PDM_PSEL_CLK_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define PDM_PSEL_CLK_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -6047,9 +6068,9 @@ #define PDM_PSEL_DIN_CONNECT_Connected (0UL) /*!< Connect */ #define PDM_PSEL_DIN_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define PDM_PSEL_DIN_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define PDM_PSEL_DIN_PORT_Msk (0x3UL << PDM_PSEL_DIN_PORT_Pos) /*!< Bit mask of PORT field. */ +#define PDM_PSEL_DIN_PORT_Msk (0x1UL << PDM_PSEL_DIN_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define PDM_PSEL_DIN_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -6273,7 +6294,7 @@ /* Register: POWER_POFCON */ /* Description: Power failure comparator configuration */ -/* Bits 11..8 : Power failure comparator threshold setting for voltage supply on VDDH */ +/* Bits 11..8 : Power failure comparator threshold setting for high voltage mode (supply connected to VDDH only). This setting does not apply for normal voltage mode (supply connected to both VDD and VDDH). */ #define POWER_POFCON_THRESHOLDVDDH_Pos (8UL) /*!< Position of THRESHOLDVDDH field. */ #define POWER_POFCON_THRESHOLDVDDH_Msk (0xFUL << POWER_POFCON_THRESHOLDVDDH_Pos) /*!< Bit mask of THRESHOLDVDDH field. */ #define POWER_POFCON_THRESHOLDVDDH_V27 (0UL) /*!< Set threshold to 2.7 V */ @@ -6293,7 +6314,7 @@ #define POWER_POFCON_THRESHOLDVDDH_V41 (14UL) /*!< Set threshold to 4.1 V */ #define POWER_POFCON_THRESHOLDVDDH_V42 (15UL) /*!< Set threshold to 4.2 V */ -/* Bits 4..1 : Power failure comparator threshold setting */ +/* Bits 4..1 : Power failure comparator threshold setting. This setting applies both for normal voltage mode (supply connected to both VDD and VDDH) and high voltage mode (supply connected to VDDH only). */ #define POWER_POFCON_THRESHOLD_Pos (1UL) /*!< Position of THRESHOLD field. */ #define POWER_POFCON_THRESHOLD_Msk (0xFUL << POWER_POFCON_THRESHOLD_Pos) /*!< Bit mask of THRESHOLD field. */ #define POWER_POFCON_THRESHOLD_V17 (4UL) /*!< Set threshold to 1.7 V */ @@ -7998,24 +8019,24 @@ #define PWM_LOOP_CNT_Disabled (0UL) /*!< Looping disabled (stop at the end of the sequence) */ /* Register: PWM_SEQ_PTR */ -/* Description: Description cluster[0]: Beginning address in Data RAM of sequence A */ +/* Description: Description cluster[0]: Beginning address in Data RAM of this sequence */ -/* Bits 31..0 : Beginning address in Data RAM of sequence A */ +/* Bits 31..0 : Beginning address in Data RAM of this sequence */ #define PWM_SEQ_PTR_PTR_Pos (0UL) /*!< Position of PTR field. */ #define PWM_SEQ_PTR_PTR_Msk (0xFFFFFFFFUL << PWM_SEQ_PTR_PTR_Pos) /*!< Bit mask of PTR field. */ /* Register: PWM_SEQ_CNT */ -/* Description: Description cluster[0]: Amount of values (duty cycles) in sequence A */ +/* Description: Description cluster[0]: Amount of values (duty cycles) in this sequence */ -/* Bits 14..0 : Amount of values (duty cycles) in sequence A */ +/* Bits 14..0 : Amount of values (duty cycles) in this sequence */ #define PWM_SEQ_CNT_CNT_Pos (0UL) /*!< Position of CNT field. */ #define PWM_SEQ_CNT_CNT_Msk (0x7FFFUL << PWM_SEQ_CNT_CNT_Pos) /*!< Bit mask of CNT field. */ #define PWM_SEQ_CNT_CNT_Disabled (0UL) /*!< Sequence is disabled, and shall not be started as it is empty */ /* Register: PWM_SEQ_REFRESH */ -/* Description: Description cluster[0]: Amount of additional PWM periods between samples loaded to compare register (load every CNT+1 PWM periods) */ +/* Description: Description cluster[0]: Amount of additional PWM periods between samples loaded into compare register */ -/* Bits 23..0 : Amount of additional PWM periods between samples loaded to compare register (load every CNT+1 PWM periods) */ +/* Bits 23..0 : Amount of additional PWM periods between samples loaded into compare register (load every REFRESH.CNT+1 PWM periods) */ #define PWM_SEQ_REFRESH_CNT_Pos (0UL) /*!< Position of CNT field. */ #define PWM_SEQ_REFRESH_CNT_Msk (0xFFFFFFUL << PWM_SEQ_REFRESH_CNT_Pos) /*!< Bit mask of CNT field. */ #define PWM_SEQ_REFRESH_CNT_Continuous (0UL) /*!< Update every PWM period */ @@ -8036,9 +8057,9 @@ #define PWM_PSEL_OUT_CONNECT_Connected (0UL) /*!< Connect */ #define PWM_PSEL_OUT_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 9..8 : Port number */ -#define PWM_PSEL_OUT_PORT_Pos (8UL) /*!< Position of PORT field. */ -#define PWM_PSEL_OUT_PORT_Msk (0x3UL << PWM_PSEL_OUT_PORT_Pos) /*!< Bit mask of PORT field. */ +/* Bit 5 : Port number */ +#define PWM_PSEL_OUT_PORT_Pos (5UL) /*!< Position of PORT field. */ +#define PWM_PSEL_OUT_PORT_Msk (0x1UL << PWM_PSEL_OUT_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define PWM_PSEL_OUT_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8251,9 +8272,9 @@ #define QDEC_PSEL_LED_CONNECT_Connected (0UL) /*!< Connect */ #define QDEC_PSEL_LED_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QDEC_PSEL_LED_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QDEC_PSEL_LED_PORT_Msk (0x3UL << QDEC_PSEL_LED_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QDEC_PSEL_LED_PORT_Msk (0x1UL << QDEC_PSEL_LED_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QDEC_PSEL_LED_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8268,9 +8289,9 @@ #define QDEC_PSEL_A_CONNECT_Connected (0UL) /*!< Connect */ #define QDEC_PSEL_A_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QDEC_PSEL_A_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QDEC_PSEL_A_PORT_Msk (0x3UL << QDEC_PSEL_A_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QDEC_PSEL_A_PORT_Msk (0x1UL << QDEC_PSEL_A_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QDEC_PSEL_A_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8285,9 +8306,9 @@ #define QDEC_PSEL_B_CONNECT_Connected (0UL) /*!< Connect */ #define QDEC_PSEL_B_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QDEC_PSEL_B_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QDEC_PSEL_B_PORT_Msk (0x3UL << QDEC_PSEL_B_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QDEC_PSEL_B_PORT_Msk (0x1UL << QDEC_PSEL_B_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QDEC_PSEL_B_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8433,9 +8454,9 @@ #define QSPI_PSEL_SCK_CONNECT_Connected (0UL) /*!< Connect */ #define QSPI_PSEL_SCK_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QSPI_PSEL_SCK_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QSPI_PSEL_SCK_PORT_Msk (0x3UL << QSPI_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QSPI_PSEL_SCK_PORT_Msk (0x1UL << QSPI_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QSPI_PSEL_SCK_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8450,9 +8471,9 @@ #define QSPI_PSEL_CSN_CONNECT_Connected (0UL) /*!< Connect */ #define QSPI_PSEL_CSN_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QSPI_PSEL_CSN_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QSPI_PSEL_CSN_PORT_Msk (0x3UL << QSPI_PSEL_CSN_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QSPI_PSEL_CSN_PORT_Msk (0x1UL << QSPI_PSEL_CSN_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QSPI_PSEL_CSN_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8467,9 +8488,9 @@ #define QSPI_PSEL_IO0_CONNECT_Connected (0UL) /*!< Connect */ #define QSPI_PSEL_IO0_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QSPI_PSEL_IO0_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QSPI_PSEL_IO0_PORT_Msk (0x3UL << QSPI_PSEL_IO0_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QSPI_PSEL_IO0_PORT_Msk (0x1UL << QSPI_PSEL_IO0_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QSPI_PSEL_IO0_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8484,9 +8505,9 @@ #define QSPI_PSEL_IO1_CONNECT_Connected (0UL) /*!< Connect */ #define QSPI_PSEL_IO1_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QSPI_PSEL_IO1_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QSPI_PSEL_IO1_PORT_Msk (0x3UL << QSPI_PSEL_IO1_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QSPI_PSEL_IO1_PORT_Msk (0x1UL << QSPI_PSEL_IO1_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QSPI_PSEL_IO1_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8501,9 +8522,9 @@ #define QSPI_PSEL_IO2_CONNECT_Connected (0UL) /*!< Connect */ #define QSPI_PSEL_IO2_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QSPI_PSEL_IO2_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QSPI_PSEL_IO2_PORT_Msk (0x3UL << QSPI_PSEL_IO2_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QSPI_PSEL_IO2_PORT_Msk (0x1UL << QSPI_PSEL_IO2_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QSPI_PSEL_IO2_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8518,9 +8539,9 @@ #define QSPI_PSEL_IO3_CONNECT_Connected (0UL) /*!< Connect */ #define QSPI_PSEL_IO3_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define QSPI_PSEL_IO3_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define QSPI_PSEL_IO3_PORT_Msk (0x3UL << QSPI_PSEL_IO3_PORT_Pos) /*!< Bit mask of PORT field. */ +#define QSPI_PSEL_IO3_PORT_Msk (0x1UL << QSPI_PSEL_IO3_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define QSPI_PSEL_IO3_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -8536,6 +8557,12 @@ /* Register: QSPI_IFCONFIG0 */ /* Description: Interface configuration. */ +/* Bit 12 : Page size for commands PP, PP2O, PP4O and PP4IO. */ +#define QSPI_IFCONFIG0_PPSIZE_Pos (12UL) /*!< Position of PPSIZE field. */ +#define QSPI_IFCONFIG0_PPSIZE_Msk (0x1UL << QSPI_IFCONFIG0_PPSIZE_Pos) /*!< Bit mask of PPSIZE field. */ +#define QSPI_IFCONFIG0_PPSIZE_256Bytes (0UL) /*!< 256 bytes. */ +#define QSPI_IFCONFIG0_PPSIZE_512Bytes (1UL) /*!< 512 bytes. */ + /* Bit 7 : Enable deep power-down mode (DPM) feature. */ #define QSPI_IFCONFIG0_DPMENABLE_Pos (7UL) /*!< Position of DPMENABLE field. */ #define QSPI_IFCONFIG0_DPMENABLE_Msk (0x1UL << QSPI_IFCONFIG0_DPMENABLE_Pos) /*!< Bit mask of DPMENABLE field. */ @@ -8575,8 +8602,8 @@ /* Bit 25 : Select SPI mode. */ #define QSPI_IFCONFIG1_SPIMODE_Pos (25UL) /*!< Position of SPIMODE field. */ #define QSPI_IFCONFIG1_SPIMODE_Msk (0x1UL << QSPI_IFCONFIG1_SPIMODE_Pos) /*!< Bit mask of SPIMODE field. */ -#define QSPI_IFCONFIG1_SPIMODE_MODE0 (0UL) /*!< Mode 0: Data are captured on the clock's rising edge and data is output on a falling edge. Base level of clock is 0 (CPOL=0, CPHA=0). */ -#define QSPI_IFCONFIG1_SPIMODE_MODE3 (1UL) /*!< Mode 3: Data are captured on the clock's falling edge and data is output on a rising edge. Base level of clock is 1 (CPOL=1, CPHA=1). */ +#define QSPI_IFCONFIG1_SPIMODE_MODE0 (0UL) /*!< Mode 0: Data are captured on the clock rising edge and data is output on a falling edge. Base level of clock is 0 (CPOL=0, CPHA=0). */ +#define QSPI_IFCONFIG1_SPIMODE_MODE3 (1UL) /*!< Mode 3: Data are captured on the clock falling edge and data is output on a rising edge. Base level of clock is 1 (CPOL=1, CPHA=1). */ /* Bit 24 : Enter/exit deep power-down mode (DPM) for external flash memory. */ #define QSPI_IFCONFIG1_DPMEN_Pos (24UL) /*!< Position of DPMEN field. */ @@ -8591,7 +8618,7 @@ /* Register: QSPI_STATUS */ /* Description: Status register. */ -/* Bits 31..24 : Value of external flash devices Status Register. When the external flash has two bytes status register this field includes the value of the low byte. */ +/* Bits 31..24 : Value of external flash device Status Register. When the external flash has two bytes status register this field includes the value of the low byte. */ #define QSPI_STATUS_SREG_Pos (24UL) /*!< Position of SREG field. */ #define QSPI_STATUS_SREG_Msk (0xFFUL << QSPI_STATUS_SREG_Pos) /*!< Bit mask of SREG field. */ @@ -8656,6 +8683,17 @@ /* Register: QSPI_CINSTRCONF */ /* Description: Custom instruction configuration register. */ +/* Bit 17 : Stop (finalize) long frame transaction */ +#define QSPI_CINSTRCONF_LFSTOP_Pos (17UL) /*!< Position of LFSTOP field. */ +#define QSPI_CINSTRCONF_LFSTOP_Msk (0x1UL << QSPI_CINSTRCONF_LFSTOP_Pos) /*!< Bit mask of LFSTOP field. */ +#define QSPI_CINSTRCONF_LFSTOP_Stop (1UL) /*!< Stop */ + +/* Bit 16 : Enable long frame mode. When enabled, a custom instruction transaction has to be ended by writing the LFSTOP field. */ +#define QSPI_CINSTRCONF_LFEN_Pos (16UL) /*!< Position of LFEN field. */ +#define QSPI_CINSTRCONF_LFEN_Msk (0x1UL << QSPI_CINSTRCONF_LFEN_Pos) /*!< Bit mask of LFEN field. */ +#define QSPI_CINSTRCONF_LFEN_Disable (0UL) /*!< Long frame mode disabled */ +#define QSPI_CINSTRCONF_LFEN_Enable (1UL) /*!< Long frame mode enabled */ + /* Bit 15 : Send WREN (write enable opcode 0x06) before instruction. */ #define QSPI_CINSTRCONF_WREN_Pos (15UL) /*!< Position of WREN field. */ #define QSPI_CINSTRCONF_WREN_Msk (0x1UL << QSPI_CINSTRCONF_WREN_Pos) /*!< Bit mask of WREN field. */ @@ -8745,6 +8783,18 @@ /* Register: RADIO_SHORTS */ /* Description: Shortcut register */ +/* Bit 21 : Shortcut between PHYEND event and START task */ +#define RADIO_SHORTS_PHYEND_START_Pos (21UL) /*!< Position of PHYEND_START field. */ +#define RADIO_SHORTS_PHYEND_START_Msk (0x1UL << RADIO_SHORTS_PHYEND_START_Pos) /*!< Bit mask of PHYEND_START field. */ +#define RADIO_SHORTS_PHYEND_START_Disabled (0UL) /*!< Disable shortcut */ +#define RADIO_SHORTS_PHYEND_START_Enabled (1UL) /*!< Enable shortcut */ + +/* Bit 20 : Shortcut between PHYEND event and DISABLE task */ +#define RADIO_SHORTS_PHYEND_DISABLE_Pos (20UL) /*!< Position of PHYEND_DISABLE field. */ +#define RADIO_SHORTS_PHYEND_DISABLE_Msk (0x1UL << RADIO_SHORTS_PHYEND_DISABLE_Pos) /*!< Bit mask of PHYEND_DISABLE field. */ +#define RADIO_SHORTS_PHYEND_DISABLE_Disabled (0UL) /*!< Disable shortcut */ +#define RADIO_SHORTS_PHYEND_DISABLE_Enabled (1UL) /*!< Enable shortcut */ + /* Bit 19 : Shortcut between RXREADY event and START task */ #define RADIO_SHORTS_RXREADY_START_Pos (19UL) /*!< Position of RXREADY_START field. */ #define RADIO_SHORTS_RXREADY_START_Msk (0x1UL << RADIO_SHORTS_RXREADY_START_Pos) /*!< Bit mask of RXREADY_START field. */ @@ -8850,6 +8900,13 @@ /* Register: RADIO_INTENSET */ /* Description: Enable interrupt */ +/* Bit 27 : Write '1' to Enable interrupt for PHYEND event */ +#define RADIO_INTENSET_PHYEND_Pos (27UL) /*!< Position of PHYEND field. */ +#define RADIO_INTENSET_PHYEND_Msk (0x1UL << RADIO_INTENSET_PHYEND_Pos) /*!< Bit mask of PHYEND field. */ +#define RADIO_INTENSET_PHYEND_Disabled (0UL) /*!< Read: Disabled */ +#define RADIO_INTENSET_PHYEND_Enabled (1UL) /*!< Read: Enabled */ +#define RADIO_INTENSET_PHYEND_Set (1UL) /*!< Enable */ + /* Bit 23 : Write '1' to Enable interrupt for MHRMATCH event */ #define RADIO_INTENSET_MHRMATCH_Pos (23UL) /*!< Position of MHRMATCH field. */ #define RADIO_INTENSET_MHRMATCH_Msk (0x1UL << RADIO_INTENSET_MHRMATCH_Pos) /*!< Bit mask of MHRMATCH field. */ @@ -9000,6 +9057,13 @@ /* Register: RADIO_INTENCLR */ /* Description: Disable interrupt */ +/* Bit 27 : Write '1' to Disable interrupt for PHYEND event */ +#define RADIO_INTENCLR_PHYEND_Pos (27UL) /*!< Position of PHYEND field. */ +#define RADIO_INTENCLR_PHYEND_Msk (0x1UL << RADIO_INTENCLR_PHYEND_Pos) /*!< Bit mask of PHYEND field. */ +#define RADIO_INTENCLR_PHYEND_Disabled (0UL) /*!< Read: Disabled */ +#define RADIO_INTENCLR_PHYEND_Enabled (1UL) /*!< Read: Enabled */ +#define RADIO_INTENCLR_PHYEND_Clear (1UL) /*!< Disable */ + /* Bit 23 : Write '1' to Disable interrupt for MHRMATCH event */ #define RADIO_INTENCLR_MHRMATCH_Pos (23UL) /*!< Position of MHRMATCH field. */ #define RADIO_INTENCLR_MHRMATCH_Msk (0x1UL << RADIO_INTENCLR_MHRMATCH_Pos) /*!< Bit mask of MHRMATCH field. */ @@ -9177,6 +9241,21 @@ #define RADIO_DAI_DAI_Pos (0UL) /*!< Position of DAI field. */ #define RADIO_DAI_DAI_Msk (0x7UL << RADIO_DAI_DAI_Pos) /*!< Bit mask of DAI field. */ +/* Register: RADIO_PDUSTAT */ +/* Description: Payload status */ + +/* Bits 2..1 : Status on what rate packet is received with in Long Range */ +#define RADIO_PDUSTAT_CISTAT_Pos (1UL) /*!< Position of CISTAT field. */ +#define RADIO_PDUSTAT_CISTAT_Msk (0x3UL << RADIO_PDUSTAT_CISTAT_Pos) /*!< Bit mask of CISTAT field. */ +#define RADIO_PDUSTAT_CISTAT_LR125kbit (0UL) /*!< Frame is received at 125kbps */ +#define RADIO_PDUSTAT_CISTAT_LR500kbit (1UL) /*!< Frame is received at 500kbps */ + +/* Bit 0 : Status on payload length vs. PCNF1.MAXLEN */ +#define RADIO_PDUSTAT_PDUSTAT_Pos (0UL) /*!< Position of PDUSTAT field. */ +#define RADIO_PDUSTAT_PDUSTAT_Msk (0x1UL << RADIO_PDUSTAT_PDUSTAT_Pos) /*!< Bit mask of PDUSTAT field. */ +#define RADIO_PDUSTAT_PDUSTAT_LessThan (0UL) /*!< Payload less than PCNF1.MAXLEN */ +#define RADIO_PDUSTAT_PDUSTAT_GreaterThan (1UL) /*!< Payload greater than PCNF1.MAXLEN */ + /* Register: RADIO_PACKETPTR */ /* Description: Packet pointer */ @@ -9211,7 +9290,6 @@ #define RADIO_TXPOWER_TXPOWER_Pos6dBm (0x6UL) /*!< +6 dBm */ #define RADIO_TXPOWER_TXPOWER_Pos7dBm (0x7UL) /*!< +7 dBm */ #define RADIO_TXPOWER_TXPOWER_Pos8dBm (0x8UL) /*!< +8 dBm */ -#define RADIO_TXPOWER_TXPOWER_Pos9dBm (0x9UL) /*!< +9 dBm */ #define RADIO_TXPOWER_TXPOWER_Neg30dBm (0xD8UL) /*!< Deprecated enumerator - -40 dBm */ #define RADIO_TXPOWER_TXPOWER_Neg40dBm (0xD8UL) /*!< -40 dBm */ #define RADIO_TXPOWER_TXPOWER_Neg20dBm (0xECUL) /*!< -20 dBm */ @@ -9607,7 +9685,7 @@ /* Register: RADIO_SFD */ /* Description: IEEE 802.15.4 Start of Frame Delimiter */ -/* Bits 7..0 : IEEE 802.15.4 Start of Frame Delimiter */ +/* Bits 7..0 : IEEE 802.15.4 Start of Frame Delimiter. Note, the least significant 4-bits of the SFD cannot all be zeros. */ #define RADIO_SFD_SFD_Pos (0UL) /*!< Position of SFD field. */ #define RADIO_SFD_SFD_Msk (0xFFUL << RADIO_SFD_SFD_Pos) /*!< Bit mask of SFD field. */ @@ -10438,7 +10516,7 @@ #define SAADC_CH_PSELP_PSELP_AnalogInput6 (7UL) /*!< AIN6 */ #define SAADC_CH_PSELP_PSELP_AnalogInput7 (8UL) /*!< AIN7 */ #define SAADC_CH_PSELP_PSELP_VDD (9UL) /*!< VDD */ -#define SAADC_CH_PSELP_PSELP_VDDHDIV5 (0x11UL) /*!< VDDH/5 */ +#define SAADC_CH_PSELP_PSELP_VDDHDIV5 (0x0DUL) /*!< VDDH/5 */ /* Register: SAADC_CH_PSELN */ /* Description: Description cluster[0]: Input negative pin selection for CH[0] */ @@ -10456,7 +10534,7 @@ #define SAADC_CH_PSELN_PSELN_AnalogInput6 (7UL) /*!< AIN6 */ #define SAADC_CH_PSELN_PSELN_AnalogInput7 (8UL) /*!< AIN7 */ #define SAADC_CH_PSELN_PSELN_VDD (9UL) /*!< VDD */ -#define SAADC_CH_PSELN_PSELN_VDDHDIV5 (0x11UL) /*!< VDDH/5 */ +#define SAADC_CH_PSELN_PSELN_VDDHDIV5 (0x0DUL) /*!< VDDH/5 */ /* Register: SAADC_CH_CONFIG */ /* Description: Description cluster[0]: Input configuration for CH[0] */ @@ -10631,9 +10709,9 @@ #define SPI_PSEL_SCK_CONNECT_Connected (0UL) /*!< Connect */ #define SPI_PSEL_SCK_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPI_PSEL_SCK_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPI_PSEL_SCK_PORT_Msk (0x3UL << SPI_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPI_PSEL_SCK_PORT_Msk (0x1UL << SPI_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPI_PSEL_SCK_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -10648,9 +10726,9 @@ #define SPI_PSEL_MOSI_CONNECT_Connected (0UL) /*!< Connect */ #define SPI_PSEL_MOSI_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPI_PSEL_MOSI_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPI_PSEL_MOSI_PORT_Msk (0x3UL << SPI_PSEL_MOSI_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPI_PSEL_MOSI_PORT_Msk (0x1UL << SPI_PSEL_MOSI_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPI_PSEL_MOSI_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -10665,9 +10743,9 @@ #define SPI_PSEL_MISO_CONNECT_Connected (0UL) /*!< Connect */ #define SPI_PSEL_MISO_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPI_PSEL_MISO_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPI_PSEL_MISO_PORT_Msk (0x3UL << SPI_PSEL_MISO_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPI_PSEL_MISO_PORT_Msk (0x1UL << SPI_PSEL_MISO_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPI_PSEL_MISO_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -10844,9 +10922,9 @@ #define SPIM_PSEL_SCK_CONNECT_Connected (0UL) /*!< Connect */ #define SPIM_PSEL_SCK_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPIM_PSEL_SCK_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPIM_PSEL_SCK_PORT_Msk (0x3UL << SPIM_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPIM_PSEL_SCK_PORT_Msk (0x1UL << SPIM_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPIM_PSEL_SCK_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -10861,9 +10939,9 @@ #define SPIM_PSEL_MOSI_CONNECT_Connected (0UL) /*!< Connect */ #define SPIM_PSEL_MOSI_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPIM_PSEL_MOSI_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPIM_PSEL_MOSI_PORT_Msk (0x3UL << SPIM_PSEL_MOSI_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPIM_PSEL_MOSI_PORT_Msk (0x1UL << SPIM_PSEL_MOSI_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPIM_PSEL_MOSI_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -10878,9 +10956,9 @@ #define SPIM_PSEL_MISO_CONNECT_Connected (0UL) /*!< Connect */ #define SPIM_PSEL_MISO_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPIM_PSEL_MISO_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPIM_PSEL_MISO_PORT_Msk (0x3UL << SPIM_PSEL_MISO_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPIM_PSEL_MISO_PORT_Msk (0x1UL << SPIM_PSEL_MISO_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPIM_PSEL_MISO_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -10895,9 +10973,9 @@ #define SPIM_PSEL_CSN_CONNECT_Connected (0UL) /*!< Connect */ #define SPIM_PSEL_CSN_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPIM_PSEL_CSN_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPIM_PSEL_CSN_PORT_Msk (0x3UL << SPIM_PSEL_CSN_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPIM_PSEL_CSN_PORT_Msk (0x1UL << SPIM_PSEL_CSN_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPIM_PSEL_CSN_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -11128,9 +11206,9 @@ #define SPIS_PSEL_SCK_CONNECT_Connected (0UL) /*!< Connect */ #define SPIS_PSEL_SCK_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPIS_PSEL_SCK_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPIS_PSEL_SCK_PORT_Msk (0x3UL << SPIS_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPIS_PSEL_SCK_PORT_Msk (0x1UL << SPIS_PSEL_SCK_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPIS_PSEL_SCK_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -11145,9 +11223,9 @@ #define SPIS_PSEL_MISO_CONNECT_Connected (0UL) /*!< Connect */ #define SPIS_PSEL_MISO_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPIS_PSEL_MISO_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPIS_PSEL_MISO_PORT_Msk (0x3UL << SPIS_PSEL_MISO_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPIS_PSEL_MISO_PORT_Msk (0x1UL << SPIS_PSEL_MISO_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPIS_PSEL_MISO_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -11162,9 +11240,9 @@ #define SPIS_PSEL_MOSI_CONNECT_Connected (0UL) /*!< Connect */ #define SPIS_PSEL_MOSI_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPIS_PSEL_MOSI_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPIS_PSEL_MOSI_PORT_Msk (0x3UL << SPIS_PSEL_MOSI_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPIS_PSEL_MOSI_PORT_Msk (0x1UL << SPIS_PSEL_MOSI_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPIS_PSEL_MOSI_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -11179,9 +11257,9 @@ #define SPIS_PSEL_CSN_CONNECT_Connected (0UL) /*!< Connect */ #define SPIS_PSEL_CSN_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define SPIS_PSEL_CSN_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define SPIS_PSEL_CSN_PORT_Msk (0x3UL << SPIS_PSEL_CSN_PORT_Pos) /*!< Bit mask of PORT field. */ +#define SPIS_PSEL_CSN_PORT_Msk (0x1UL << SPIS_PSEL_CSN_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define SPIS_PSEL_CSN_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -11775,9 +11853,9 @@ #define TWI_PSEL_SCL_CONNECT_Connected (0UL) /*!< Connect */ #define TWI_PSEL_SCL_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define TWI_PSEL_SCL_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define TWI_PSEL_SCL_PORT_Msk (0x3UL << TWI_PSEL_SCL_PORT_Pos) /*!< Bit mask of PORT field. */ +#define TWI_PSEL_SCL_PORT_Msk (0x1UL << TWI_PSEL_SCL_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define TWI_PSEL_SCL_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -11792,9 +11870,9 @@ #define TWI_PSEL_SDA_CONNECT_Connected (0UL) /*!< Connect */ #define TWI_PSEL_SDA_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define TWI_PSEL_SDA_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define TWI_PSEL_SDA_PORT_Msk (0x3UL << TWI_PSEL_SDA_PORT_Pos) /*!< Bit mask of PORT field. */ +#define TWI_PSEL_SDA_PORT_Msk (0x1UL << TWI_PSEL_SDA_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define TWI_PSEL_SDA_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -12056,9 +12134,9 @@ #define TWIM_PSEL_SCL_CONNECT_Connected (0UL) /*!< Connect */ #define TWIM_PSEL_SCL_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define TWIM_PSEL_SCL_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define TWIM_PSEL_SCL_PORT_Msk (0x3UL << TWIM_PSEL_SCL_PORT_Pos) /*!< Bit mask of PORT field. */ +#define TWIM_PSEL_SCL_PORT_Msk (0x1UL << TWIM_PSEL_SCL_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define TWIM_PSEL_SCL_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -12073,9 +12151,9 @@ #define TWIM_PSEL_SDA_CONNECT_Connected (0UL) /*!< Connect */ #define TWIM_PSEL_SDA_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define TWIM_PSEL_SDA_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define TWIM_PSEL_SDA_PORT_Msk (0x3UL << TWIM_PSEL_SDA_PORT_Pos) /*!< Bit mask of PORT field. */ +#define TWIM_PSEL_SDA_PORT_Msk (0x1UL << TWIM_PSEL_SDA_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define TWIM_PSEL_SDA_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -12352,9 +12430,9 @@ #define TWIS_PSEL_SCL_CONNECT_Connected (0UL) /*!< Connect */ #define TWIS_PSEL_SCL_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define TWIS_PSEL_SCL_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define TWIS_PSEL_SCL_PORT_Msk (0x3UL << TWIS_PSEL_SCL_PORT_Pos) /*!< Bit mask of PORT field. */ +#define TWIS_PSEL_SCL_PORT_Msk (0x1UL << TWIS_PSEL_SCL_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define TWIS_PSEL_SCL_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -12369,9 +12447,9 @@ #define TWIS_PSEL_SDA_CONNECT_Connected (0UL) /*!< Connect */ #define TWIS_PSEL_SDA_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define TWIS_PSEL_SDA_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define TWIS_PSEL_SDA_PORT_Msk (0x3UL << TWIS_PSEL_SDA_PORT_Pos) /*!< Bit mask of PORT field. */ +#define TWIS_PSEL_SDA_PORT_Msk (0x1UL << TWIS_PSEL_SDA_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define TWIS_PSEL_SDA_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -12602,9 +12680,9 @@ #define UART_PSEL_RTS_CONNECT_Connected (0UL) /*!< Connect */ #define UART_PSEL_RTS_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define UART_PSEL_RTS_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UART_PSEL_RTS_PORT_Msk (0x3UL << UART_PSEL_RTS_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UART_PSEL_RTS_PORT_Msk (0x1UL << UART_PSEL_RTS_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define UART_PSEL_RTS_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -12619,9 +12697,9 @@ #define UART_PSEL_TXD_CONNECT_Connected (0UL) /*!< Connect */ #define UART_PSEL_TXD_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define UART_PSEL_TXD_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UART_PSEL_TXD_PORT_Msk (0x3UL << UART_PSEL_TXD_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UART_PSEL_TXD_PORT_Msk (0x1UL << UART_PSEL_TXD_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define UART_PSEL_TXD_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -12636,9 +12714,9 @@ #define UART_PSEL_CTS_CONNECT_Connected (0UL) /*!< Connect */ #define UART_PSEL_CTS_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define UART_PSEL_CTS_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UART_PSEL_CTS_PORT_Msk (0x3UL << UART_PSEL_CTS_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UART_PSEL_CTS_PORT_Msk (0x1UL << UART_PSEL_CTS_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define UART_PSEL_CTS_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -12653,9 +12731,9 @@ #define UART_PSEL_RXD_CONNECT_Connected (0UL) /*!< Connect */ #define UART_PSEL_RXD_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define UART_PSEL_RXD_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UART_PSEL_RXD_PORT_Msk (0x3UL << UART_PSEL_RXD_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UART_PSEL_RXD_PORT_Msk (0x1UL << UART_PSEL_RXD_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define UART_PSEL_RXD_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -13008,9 +13086,9 @@ #define UARTE_PSEL_RTS_CONNECT_Connected (0UL) /*!< Connect */ #define UARTE_PSEL_RTS_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define UARTE_PSEL_RTS_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UARTE_PSEL_RTS_PORT_Msk (0x3UL << UARTE_PSEL_RTS_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UARTE_PSEL_RTS_PORT_Msk (0x1UL << UARTE_PSEL_RTS_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define UARTE_PSEL_RTS_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -13025,9 +13103,9 @@ #define UARTE_PSEL_TXD_CONNECT_Connected (0UL) /*!< Connect */ #define UARTE_PSEL_TXD_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define UARTE_PSEL_TXD_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UARTE_PSEL_TXD_PORT_Msk (0x3UL << UARTE_PSEL_TXD_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UARTE_PSEL_TXD_PORT_Msk (0x1UL << UARTE_PSEL_TXD_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define UARTE_PSEL_TXD_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -13042,9 +13120,9 @@ #define UARTE_PSEL_CTS_CONNECT_Connected (0UL) /*!< Connect */ #define UARTE_PSEL_CTS_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define UARTE_PSEL_CTS_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UARTE_PSEL_CTS_PORT_Msk (0x3UL << UARTE_PSEL_CTS_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UARTE_PSEL_CTS_PORT_Msk (0x1UL << UARTE_PSEL_CTS_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define UARTE_PSEL_CTS_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -13059,9 +13137,9 @@ #define UARTE_PSEL_RXD_CONNECT_Connected (0UL) /*!< Connect */ #define UARTE_PSEL_RXD_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number */ +/* Bit 5 : Port number */ #define UARTE_PSEL_RXD_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UARTE_PSEL_RXD_PORT_Msk (0x3UL << UARTE_PSEL_RXD_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UARTE_PSEL_RXD_PORT_Msk (0x1UL << UARTE_PSEL_RXD_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number */ #define UARTE_PSEL_RXD_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -13157,7 +13235,7 @@ /* Peripheral: UICR */ -/* Description: User Information Configuration Registers */ +/* Description: User information configuration registers */ /* Register: UICR_NRFFW */ /* Description: Description collection[0]: Reserved for Nordic firmware design */ @@ -13189,9 +13267,9 @@ #define UICR_PSELRESET_CONNECT_Connected (0UL) /*!< Connect */ #define UICR_PSELRESET_CONNECT_Disconnected (1UL) /*!< Disconnect */ -/* Bits 6..5 : Port number onto which nRESET is exposed */ +/* Bit 5 : Port number onto which nRESET is exposed */ #define UICR_PSELRESET_PORT_Pos (5UL) /*!< Position of PORT field. */ -#define UICR_PSELRESET_PORT_Msk (0x3UL << UICR_PSELRESET_PORT_Pos) /*!< Bit mask of PORT field. */ +#define UICR_PSELRESET_PORT_Msk (0x1UL << UICR_PSELRESET_PORT_Pos) /*!< Bit mask of PORT field. */ /* Bits 4..0 : Pin number of PORT onto which nRESET is exposed */ #define UICR_PSELRESET_PIN_Pos (0UL) /*!< Position of PIN field. */ @@ -13200,7 +13278,7 @@ /* Register: UICR_APPROTECT */ /* Description: Access port protection */ -/* Bits 7..0 : Enable or disable Access Port protection. */ +/* Bits 7..0 : Enable or disable access port protection. */ #define UICR_APPROTECT_PALL_Pos (0UL) /*!< Position of PALL field. */ #define UICR_APPROTECT_PALL_Msk (0xFFUL << UICR_APPROTECT_PALL_Pos) /*!< Bit mask of PALL field. */ #define UICR_APPROTECT_PALL_Enabled (0x00UL) /*!< Enable */ @@ -13215,17 +13293,32 @@ #define UICR_NFCPINS_PROTECT_Disabled (0UL) /*!< Operation as GPIO pins. Same protection as normal GPIO pins */ #define UICR_NFCPINS_PROTECT_NFC (1UL) /*!< Operation as NFC antenna pins. Configures the protection for NFC operation */ -/* Register: UICR_EXTSUPPLY */ -/* Description: Enable external circuitry to be supplied from VDD pin. Applicable in 'High voltage mode' only. */ +/* Register: UICR_DEBUGCTRL */ +/* Description: Processor debug control */ -/* Bit 0 : Enable external circuitry to be supplied from VDD pin (output of REG0 stage). */ +/* Bits 15..8 : Configure CPU flash patch and breakpoint (FPB) unit behavior */ +#define UICR_DEBUGCTRL_CPUFPBEN_Pos (8UL) /*!< Position of CPUFPBEN field. */ +#define UICR_DEBUGCTRL_CPUFPBEN_Msk (0xFFUL << UICR_DEBUGCTRL_CPUFPBEN_Pos) /*!< Bit mask of CPUFPBEN field. */ +#define UICR_DEBUGCTRL_CPUFPBEN_Disabled (0x00UL) /*!< Disable CPU FPB unit. Writes into the FPB registers will be ignored. */ +#define UICR_DEBUGCTRL_CPUFPBEN_Enabled (0xFFUL) /*!< Enable CPU FPB unit (default behavior) */ + +/* Bits 7..0 : Configure CPU non-intrusive debug features */ +#define UICR_DEBUGCTRL_CPUNIDEN_Pos (0UL) /*!< Position of CPUNIDEN field. */ +#define UICR_DEBUGCTRL_CPUNIDEN_Msk (0xFFUL << UICR_DEBUGCTRL_CPUNIDEN_Pos) /*!< Bit mask of CPUNIDEN field. */ +#define UICR_DEBUGCTRL_CPUNIDEN_Disabled (0x00UL) /*!< Disable CPU ITM and ETM functionality */ +#define UICR_DEBUGCTRL_CPUNIDEN_Enabled (0xFFUL) /*!< Enable CPU ITM and ETM functionality (default behavior) */ + +/* Register: UICR_EXTSUPPLY */ +/* Description: Enable external circuitry to be supplied from VDD pin. Applicable in high voltage mode only. */ + +/* Bit 0 : Enable external circuitry to be supplied from VDD pin (output of REG0 stage) */ #define UICR_EXTSUPPLY_EXTSUPPLY_Pos (0UL) /*!< Position of EXTSUPPLY field. */ #define UICR_EXTSUPPLY_EXTSUPPLY_Msk (0x1UL << UICR_EXTSUPPLY_EXTSUPPLY_Pos) /*!< Bit mask of EXTSUPPLY field. */ -#define UICR_EXTSUPPLY_EXTSUPPLY_Disabled (0UL) /*!< No current can be drawn from the VDD pin. */ -#define UICR_EXTSUPPLY_EXTSUPPLY_Enabled (1UL) /*!< It is allowed to supply external circuitry from the VDD pin. */ +#define UICR_EXTSUPPLY_EXTSUPPLY_Disabled (0UL) /*!< No current can be drawn from the VDD pin */ +#define UICR_EXTSUPPLY_EXTSUPPLY_Enabled (1UL) /*!< It is allowed to supply external circuitry from the VDD pin */ /* Register: UICR_REGOUT0 */ -/* Description: GPIO reference voltage / external output supply voltage in 'High voltage mode'. */ +/* Description: GPIO reference voltage / external output supply voltage in high voltage mode */ /* Bits 2..0 : Output voltage from of REG0 regulator stage. The maximum output voltage from this stage is given as VDDH - VEXDIF. */ #define UICR_REGOUT0_VOUT_Pos (0UL) /*!< Position of VOUT field. */ @@ -14370,6 +14463,15 @@ #define USBD_FRAMECNTR_FRAMECNTR_Pos (0UL) /*!< Position of FRAMECNTR field. */ #define USBD_FRAMECNTR_FRAMECNTR_Msk (0x7FFUL << USBD_FRAMECNTR_FRAMECNTR_Pos) /*!< Bit mask of FRAMECNTR field. */ +/* Register: USBD_LOWPOWER */ +/* Description: First silicon only: Controls USBD peripheral low-power mode during USB suspend */ + +/* Bit 0 : Controls USBD peripheral low-power mode during USB suspend */ +#define USBD_LOWPOWER_LOWPOWER_Pos (0UL) /*!< Position of LOWPOWER field. */ +#define USBD_LOWPOWER_LOWPOWER_Msk (0x1UL << USBD_LOWPOWER_LOWPOWER_Pos) /*!< Bit mask of LOWPOWER field. */ +#define USBD_LOWPOWER_LOWPOWER_ForceNormal (0UL) /*!< Software must write this value to exit low power mode and before performing a remote wake-up */ +#define USBD_LOWPOWER_LOWPOWER_LowPower (1UL) /*!< Software must write this value to enter low power mode after DMA and software have finished interacting with the USB peripheral */ + /* Register: USBD_ISOINCONFIG */ /* Description: Controls the response of the ISO IN endpoint to an IN token when no data is ready to be sent */ diff --git a/third_party/NordicSemiconductor/device/nrf52840_peripherals.h b/third_party/NordicSemiconductor/device/nrf52840_peripherals.h index 4cf3ad920..aefd2fa09 100644 --- a/third_party/NordicSemiconductor/device/nrf52840_peripherals.h +++ b/third_party/NordicSemiconductor/device/nrf52840_peripherals.h @@ -1,32 +1,43 @@ -/* Copyright (c) 2016, 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: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form 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. - * - * * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - * - */ +/* + +Copyright (c) 2010 - 2017, 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 _NRF52840_PERIPHERALS_H #define _NRF52840_PERIPHERALS_H @@ -87,6 +98,7 @@ #define PPI_COUNT 1 #define PPI_CH_NUM 20 +#define PPI_FIXED_CH_NUM 12 #define PPI_GROUP_NUM 6 #define PPI_FEATURE_FORKS_PRESENT diff --git a/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c b/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c index 579469cad..a034469e0 100644 --- a/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c +++ b/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.c @@ -1,36 +1,72 @@ -/* Copyright (c) 2016, Nordic Semiconductor ASA +/** + * Copyright (c) 2016 - 2017, 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 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. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - * + * + * 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(CLOCK) #include "nrf_drv_clock.h" +#include "nrf_error.h" +#include "app_util_platform.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#endif -#define NRF_ERROR_MODULE_ALREADY_INITIALIZED 0x8085 +#define NRF_LOG_MODULE_NAME clock + +#if CLOCK_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL CLOCK_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR CLOCK_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR CLOCK_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \ + (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : "UNKNOWN EVENT")))) +#else //CLOCK_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //CLOCK_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/* Validate configuration */ +INTERRUPT_PRIORITY_VALIDATION(CLOCK_CONFIG_IRQ_PRIORITY); /*lint -save -e652 */ #define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC @@ -38,14 +74,46 @@ #define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth /*lint -restore */ -volatile uint32_t m_hfclk_requests; /*< High frequency clock requests. */ -volatile uint32_t m_lfclk_requests; /*< Low frequency clock requests. */ +#if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC) && !defined(SOFTDEVICE_PRESENT) +#define CALIBRATION_SUPPORT 1 +#else +#define CALIBRATION_SUPPORT 0 +#endif +typedef enum +{ + CAL_STATE_IDLE, + CAL_STATE_CT, + CAL_STATE_HFCLK_REQ, + CAL_STATE_CAL, + CAL_STATE_ABORT, +} nrf_drv_clock_cal_state_t; + +/**@brief CLOCK control block. */ +typedef struct +{ + bool module_initialized; /*< Indicate the state of module */ + volatile bool hfclk_on; /*< High-frequency clock state. */ + volatile bool lfclk_on; /*< Low-frequency clock state. */ + volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_hf_head; + volatile uint32_t lfclk_requests; /*< Low-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_lf_head; +#if CALIBRATION_SUPPORT + nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item; + nrf_drv_clock_event_handler_t cal_done_handler; + volatile nrf_drv_clock_cal_state_t cal_state; +#endif // CALIBRATION_SUPPORT +} nrf_drv_clock_cb_t; + +static nrf_drv_clock_cb_t m_clock_cb; + /**@brief Function for starting LFCLK. This function will return immediately without waiting for start. */ static void lfclk_start(void) { nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED); + nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK); nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART); } @@ -53,114 +121,507 @@ static void lfclk_start(void) */ static void lfclk_stop(void) { - nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTOP); +#if CALIBRATION_SUPPORT + (void)nrf_drv_clock_calibration_abort(); +#endif - while (nrf_clock_lf_is_running()) {} +#ifdef SOFTDEVICE_PRESENT + // If LFCLK is requested to stop while SD is still enabled, + // it indicates an error in the application. + // Enabling SD should increment the LFCLK request. + ASSERT(!nrf_sdh_is_enabled()); +#endif // SOFTDEVICE_PRESENT + + nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTOP); + while (nrf_clock_lf_is_running()) + {} + m_clock_cb.lfclk_on = false; } static void hfclk_start(void) { +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void)sd_clock_hfclk_request(); + return; + } +#endif // SOFTDEVICE_PRESENT + nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED); + nrf_clock_int_enable(NRF_CLOCK_INT_HF_STARTED_MASK); nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART); } static void hfclk_stop(void) { - nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP); +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void)sd_clock_hfclk_release(); + return; + } +#endif // SOFTDEVICE_PRESENT - while (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY)) {} + nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP); + while (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY)) + {} + m_clock_cb.hfclk_on = false; } -uint32_t nrf_drv_clock_init(void) +bool nrf_drv_clock_init_check(void) { - nrf_clock_lf_src_set(NRF_CLOCK_LFCLK_Xtal); - return 0; + return m_clock_cb.module_initialized; +} + +ret_code_t nrf_drv_clock_init(void) +{ + ret_code_t err_code = NRF_SUCCESS; + if (m_clock_cb.module_initialized) + { + err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + else + { + m_clock_cb.p_hf_head = NULL; + m_clock_cb.hfclk_requests = 0; + m_clock_cb.p_lf_head = NULL; + m_clock_cb.lfclk_requests = 0; + nrf_drv_common_power_clock_irq_init(); +#ifdef SOFTDEVICE_PRESENT + if (!nrf_sdh_is_enabled()) +#endif + { + nrf_clock_lf_src_set((nrf_clock_lfclk_t)CLOCK_CONFIG_LF_SRC); + } + +#if CALIBRATION_SUPPORT + m_clock_cb.cal_state = CAL_STATE_IDLE; +#endif + + m_clock_cb.module_initialized = true; + } + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; } void nrf_drv_clock_uninit(void) { + ASSERT(m_clock_cb.module_initialized); + nrf_drv_common_clock_irq_disable(); + nrf_clock_int_disable(0xFFFFFFFF); + lfclk_stop(); hfclk_stop(); + m_clock_cb.module_initialized = false; + NRF_LOG_INFO("Uninitialized."); } -void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t *p_handler_item) +static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head, + nrf_drv_clock_handler_item_t * p_item) { - volatile uint32_t lfclk_requests; - (void) p_handler_item; - - do + nrf_drv_clock_handler_item_t * p_next = *p_head; + while (p_next) { - - lfclk_requests = __LDREXW(&m_lfclk_requests); - lfclk_requests += 1; + if (p_next == p_item) + { + return; + } + p_next = p_next->p_next; } - while (__STREXW(lfclk_requests, &m_lfclk_requests)); - if (!nrf_clock_lf_is_running()) + p_item->p_next = (*p_head ? *p_head : NULL); + *p_head = p_item; +} + +static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head) +{ + nrf_drv_clock_handler_item_t * p_item = *p_head; + if (p_item) { - lfclk_start(); + *p_head = p_item->p_next; } + return p_item; +} + +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.lfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, + p_handler_item); + } + if (m_clock_cb.lfclk_requests == 0) + { + lfclk_start(); + } + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.lfclk_requests > 0); } void nrf_drv_clock_lfclk_release(void) { - volatile uint32_t lfclk_requests; + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.lfclk_requests > 0); - do - { - lfclk_requests = __LDREXW(&m_lfclk_requests); - lfclk_requests -= 1; - } - while (__STREXW(lfclk_requests, &m_lfclk_requests)); - - if (nrf_clock_lf_is_running() && m_lfclk_requests == 0) + CRITICAL_REGION_ENTER(); + --(m_clock_cb.lfclk_requests); + if (m_clock_cb.lfclk_requests == 0) { lfclk_stop(); } + CRITICAL_REGION_EXIT(); } bool nrf_drv_clock_lfclk_is_running(void) { + ASSERT(m_clock_cb.module_initialized); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + return true; + } +#endif // SOFTDEVICE_PRESENT + return nrf_clock_lf_is_running(); } -void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t *p_handler_item) +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) { - volatile uint32_t hfclk_requests; - (void) p_handler_item; + ASSERT(m_clock_cb.module_initialized); - do + if (m_clock_cb.hfclk_on) { - - hfclk_requests = __LDREXW(&m_hfclk_requests); - hfclk_requests += 1; + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); } - while (__STREXW(hfclk_requests, &m_hfclk_requests)); - - if (!nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY)) + else { - hfclk_start(); + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, + p_handler_item); + } + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_start(); + } + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); } + + ASSERT(m_clock_cb.hfclk_requests > 0); } void nrf_drv_clock_hfclk_release(void) { - volatile uint32_t hfclk_requests; + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.hfclk_requests > 0); - do - { - hfclk_requests = __LDREXW(&m_hfclk_requests); - hfclk_requests -= 1; - } - while (__STREXW(hfclk_requests, &m_hfclk_requests)); - - if (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY) && m_hfclk_requests == 0) + CRITICAL_REGION_ENTER(); + --(m_clock_cb.hfclk_requests); + if (m_clock_cb.hfclk_requests == 0) { hfclk_stop(); } + CRITICAL_REGION_EXIT(); } bool nrf_drv_clock_hfclk_is_running(void) { + ASSERT(m_clock_cb.module_initialized); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + uint32_t is_running; + UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running)); + return (is_running ? true : false); + } +#endif // SOFTDEVICE_PRESENT + return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY); } + +#if CALIBRATION_SUPPORT +static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event) +{ + if (m_clock_cb.cal_state == CAL_STATE_ABORT) + { + nrf_drv_clock_hfclk_release(); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + } + else + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE); + nrf_clock_int_enable(NRF_CLOCK_INT_DONE_MASK); + m_clock_cb.cal_state = CAL_STATE_CAL; + nrf_clock_task_trigger(NRF_CLOCK_TASK_CAL); + } +} +#endif // CALIBRATION_SUPPORT + +ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE); + if (m_clock_cb.lfclk_on == false) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (m_clock_cb.cal_state == CAL_STATE_IDLE) + { + m_clock_cb.cal_done_handler = handler; + m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started; + if (interval == 0) + { + m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ; + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + else + { + m_clock_cb.cal_state = CAL_STATE_CT; + nrf_clock_cal_timer_timeout_set(interval); + nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO); + nrf_clock_int_enable(NRF_CLOCK_INT_CTTO_MASK); + nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTART); + } + } + else + { + err_code = NRF_ERROR_BUSY; + } + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_calibration_abort(void) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + CRITICAL_REGION_ENTER(); + switch (m_clock_cb.cal_state) + { + case CAL_STATE_CT: + nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK); + nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTOP); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + break; + case CAL_STATE_HFCLK_REQ: + /* fall through. */ + case CAL_STATE_CAL: + m_clock_cb.cal_state = CAL_STATE_ABORT; + break; + default: + break; + } + CRITICAL_REGION_EXIT(); + + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.module_initialized); + *p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE); + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +__STATIC_INLINE void clock_clk_started_notify(nrf_drv_clock_evt_type_t evt_type) +{ + nrf_drv_clock_handler_item_t **p_head; + if (evt_type == NRF_DRV_CLOCK_EVT_HFCLK_STARTED) + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head; + } + else + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head; + } + + while (1) + { + nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head); + if (!p_item) + { + break; + } + + p_item->event_handler(evt_type); + } +} + +#if NRF_DRV_COMMON_POWER_CLOCK_ISR +void nrf_drv_clock_onIRQ(void) +#else +void POWER_CLOCK_IRQHandler(void) +#endif +{ + if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED)) + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_HFCLKSTARTED)); + nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK); + m_clock_cb.hfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED)) + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_LFCLKSTARTED)); + nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK); + m_clock_cb.lfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } +#if CALIBRATION_SUPPORT + if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO)) + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_CTTO)); + nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK); + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + + if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE)) + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_DONE)); + nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK); + nrf_drv_clock_hfclk_release(); + bool aborted = (m_clock_cb.cal_state == CAL_STATE_ABORT); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(aborted ? + NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE); + } + } +#endif // CALIBRATION_SUPPORT +} + +#ifdef SOFTDEVICE_PRESENT +/** + * @brief SoftDevice SoC event handler. + * + * @param[in] evt_id SoC event. + * @param[in] p_context Context. + */ +static void soc_evt_handler(uint32_t evt_id, void * p_context) +{ + if (evt_id == NRF_EVT_HFCLKSTARTED) + { + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } +} + +NRF_SDH_SOC_OBSERVER(m_soc_evt_observer, CLOCK_CONFIG_SOC_OBSERVER_PRIO, soc_evt_handler, NULL); + +/** + * @brief SoftDevice enable/disable state handler. + * + * @param[in] state State. + * @param[in] p_context Context. + */ +static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLE_PREPARE: + NVIC_DisableIRQ(POWER_CLOCK_IRQn); + break; + + case NRF_SDH_EVT_STATE_ENABLED: + CRITICAL_REGION_ENTER(); + /* Make sure that nrf_drv_clock module is initialized */ + if (!m_clock_cb.module_initialized) + { + (void)nrf_drv_clock_init(); + } + /* SD is one of the LFCLK requesters, but it will enable it by itself. */ + ++(m_clock_cb.lfclk_requests); + m_clock_cb.lfclk_on = true; + CRITICAL_REGION_EXIT(); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + /* Reinit interrupts */ + ASSERT(m_clock_cb.module_initialized); + nrf_drv_common_irq_enable(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY); + + /* SD leaves LFCLK enabled - disable it if it is no longer required. */ + nrf_drv_clock_lfclk_release(); + break; + + default: + break; + } +} + +NRF_SDH_STATE_OBSERVER(m_sd_state_observer, CLOCK_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = sd_state_evt_handler, + .p_context = NULL, +}; + +#endif // SOFTDEVICE_PRESENT + +#undef NRF_CLOCK_LFCLK_RC +#undef NRF_CLOCK_LFCLK_Xtal +#undef NRF_CLOCK_LFCLK_Synth + +#endif // NRF_MODULE_ENABLED(CLOCK) diff --git a/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h b/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h index 82227c6d3..fd436a0aa 100644 --- a/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h +++ b/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h @@ -1,48 +1,108 @@ -/* Copyright (c) 2016, Nordic Semiconductor ASA +/** + * Copyright (c) 2016 - 2017, 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 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. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - * + * + * 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_CLOCK_H__ #define NRF_DRV_CLOCK_H__ #include #include -#include +#include "sdk_errors.h" +#include "nrf_assert.h" +#include "nrf_clock.h" +#include "sdk_config.h" +#include "nrf_drv_common.h" #ifdef __cplusplus extern "C" { #endif /** - * @brief Simplify version to keep API of SDK. + * + * @addtogroup nrf_clock Clock HAL and driver + * @ingroup nrf_drivers + * @brief Clock APIs. + * @details The clock HAL provides basic APIs for accessing the registers of the clock. + * The clock driver provides APIs on a higher level. + * + * @defgroup nrf_drv_clock Clock driver + * @{ + * @ingroup nrf_clock + * @brief Driver for managing the low-frequency clock (LFCLK) and the high-frequency clock (HFCLK). */ -typedef void nrf_drv_clock_handler_item_t; + +/** + * @brief Clock events. + */ +typedef enum +{ + NRF_DRV_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started. + NRF_DRV_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started. + NRF_DRV_CLOCK_EVT_CAL_DONE, ///< Calibration is done. + NRF_DRV_CLOCK_EVT_CAL_ABORTED, ///< Calibration has been aborted. +} nrf_drv_clock_evt_type_t; + +/** + * @brief Clock event handler. + * + * @param[in] event Event. + */ +typedef void (*nrf_drv_clock_event_handler_t)(nrf_drv_clock_evt_type_t event); + +// Forward declaration of the nrf_drv_clock_handler_item_t type. +typedef struct nrf_drv_clock_handler_item_s nrf_drv_clock_handler_item_t; + +struct nrf_drv_clock_handler_item_s +{ + nrf_drv_clock_handler_item_t * p_next; ///< A pointer to the next handler that should be called when the clock is started. + nrf_drv_clock_event_handler_t event_handler; ///< Function to be called when the clock is started. +}; + +/** + * @brief Function for checking if driver is already initialized + * + * This function is used to check whatever common POWER_CLOCK common interrupt + * should be disabled or not if @ref nrf_drv_power tries to disable the interrupt. + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + */ +bool nrf_drv_clock_init_check(void); /** * @brief Function for initializing the nrf_drv_clock module. @@ -52,7 +112,7 @@ typedef void nrf_drv_clock_handler_item_t; * @retval NRF_SUCCESS If the procedure was successful. * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the driver was already initialized. */ -uint32_t nrf_drv_clock_init(void); +ret_code_t nrf_drv_clock_init(void); /** * @brief Function for uninitializing the clock module. @@ -81,7 +141,7 @@ void nrf_drv_clock_uninit(void); * * @param[in] p_handler_item A pointer to the event handler structure. */ -void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t *p_handler_item); +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); /** * @brief Function for releasing the LFCLK. @@ -119,7 +179,7 @@ bool nrf_drv_clock_lfclk_is_running(void); * * @param[in] p_handler_item A pointer to the event handler structure. */ -void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t *p_handler_item); +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); /** * @brief Function for releasing the high-accuracy source HFCLK. @@ -136,6 +196,88 @@ void nrf_drv_clock_hfclk_release(void); */ bool nrf_drv_clock_hfclk_is_running(void); +/** + * @brief Function for starting a single calibration process. + * + * This function can also delay the start of calibration by a user-specified value. The delay will use + * a low-power timer that is part of the CLOCK module. @ref nrf_drv_clock_is_calibrating can be called to + * check if calibration is still in progress. If a handler is provided, the user can be notified when + * calibration is completed. The ext calibration can be started from the handler context. + * + * The calibration process consists of three phases: + * - Delay (optional) + * - Requesting the high-accuracy HFCLK + * - Hardware-supported calibration + * + * @param[in] delay Time after which the calibration will be started (in 0.25 s units). + * @param[in] handler NULL or user function to be called when calibration is completed or aborted. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + * @retval NRF_ERROR_INVALID_STATE If the low-frequency clock is off. + * @retval NRF_ERROR_BUSY If calibration is in progress. + */ +ret_code_t nrf_drv_clock_calibration_start(uint8_t delay, nrf_drv_clock_event_handler_t handler); + +/** + * @brief Function for aborting calibration. + * + * This function aborts on-going calibration. If calibration was started, it cannot be stopped. If a handler + * was provided by @ref nrf_drv_clock_calibration_start, this handler will be called once + * aborted calibration is completed. @ref nrf_drv_clock_is_calibrating can also be used to check + * if the system is calibrating. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_calibration_abort(void); + +/** + * @brief Function for checking if calibration is in progress. + * + * This function indicates that the system is + * in calibration if it is in any of the calibration process phases (see @ref nrf_drv_clock_calibration_start). + * + * @param[out] p_is_calibrating True if calibration is in progress, false if not. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating); + +/**@brief Function for returning a requested task address for the clock driver module. + * + * @param[in] task One of the peripheral tasks. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task); + +/**@brief Function for returning a requested event address for the clock driver module. + * + * @param[in] event One of the peripheral events. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event); +/** + *@} + **/ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task) +{ + return nrf_clock_task_address_get(task); +} + +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event) +{ + return nrf_clock_event_address_get(event); +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +/*lint --flb "Leave library region" */ + #ifdef __cplusplus } #endif diff --git a/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.c b/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.c new file mode 100644 index 000000000..8d93e97f6 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.c @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2015 - 2017, 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 +#include "nrf_drv_common.h" +#include "nrf_assert.h" +#include "app_util_platform.h" +#include "nrf_peripherals.h" + +#if NRF_DRV_COMMON_POWER_CLOCK_ISR +#include "nrf_drv_power.h" +#include "nrf_drv_clock.h" +#endif +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#endif + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +#define NRF_LOG_MODULE_NAME common + +#if COMMON_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL COMMON_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR COMMON_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR COMMON_CONFIG_DEBUG_COLOR +#else //COMMON_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //COMMON_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +typedef struct { + nrf_drv_irq_handler_t handler; + bool acquired; +} shared_resource_t; + +// SPIM0, SPIS0, SPI0, TWIM0, TWIS0, TWI0 +#if (NRF_MODULE_ENABLED(SPI0) || NRF_MODULE_ENABLED(SPIS0) || NRF_MODULE_ENABLED(TWI0) || NRF_MODULE_ENABLED(TWIS0)) + #define SERIAL_BOX_0_IN_USE + // [this checking may need a different form in unit tests, hence macro] + #ifndef IS_SERIAL_BOX_0 + #define IS_SERIAL_BOX_0(p_per_base) (p_per_base == NRF_SPI0) + #endif + + static shared_resource_t m_serial_box_0 = { .acquired = false }; + void SPI0_TWI0_IRQHandler(void) + { + ASSERT(m_serial_box_0.handler); + m_serial_box_0.handler(); + } +#endif // (NRF_MODULE_ENABLED(SPI0) || NRF_MODULE_ENABLED(SPIS0) || NRF_MODULE_ENABLED(TWI0) || NRF_MODULE_ENABLED(TWIS0)) + +// SPIM1, SPIS1, SPI1, TWIM1, TWIS1, TWI1 +#if (NRF_MODULE_ENABLED(SPI1) || NRF_MODULE_ENABLED(SPIS1) || NRF_MODULE_ENABLED(TWI1) || NRF_MODULE_ENABLED(TWIS1)) + #define SERIAL_BOX_1_IN_USE + // [this checking may need a different form in unit tests, hence macro] + #ifndef IS_SERIAL_BOX_1 + #define IS_SERIAL_BOX_1(p_per_base) (p_per_base == NRF_SPI1) + #endif + + static shared_resource_t m_serial_box_1 = { .acquired = false }; +#ifdef TWIM_PRESENT + void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void) +#else + void SPI1_TWI1_IRQHandler(void) +#endif + { + ASSERT(m_serial_box_1.handler); + m_serial_box_1.handler(); + } +#endif // (NRF_MODULE_ENABLED(SPI1) || NRF_MODULE_ENABLED(SPIS1) || NRF_MODULE_ENABLED(TWI1) || NRF_MODULE_ENABLED(TWIS1)) + +// SPIM2, SPIS2, SPI2 +#if (NRF_MODULE_ENABLED(SPI2) || NRF_MODULE_ENABLED(SPIS2)) + #define SERIAL_BOX_2_IN_USE + // [this checking may need a different form in unit tests, hence macro] + #ifndef IS_SERIAL_BOX_2 + #define IS_SERIAL_BOX_2(p_per_base) (p_per_base == NRF_SPI2) + #endif + + static shared_resource_t m_serial_box_2 = { .acquired = false }; + void SPIM2_SPIS2_SPI2_IRQHandler(void) + { + ASSERT(m_serial_box_2.handler); + m_serial_box_2.handler(); + } +#endif // (NRF_MODULE_ENABLED(SPI2) || NRF_MODULE_ENABLED(SPIS2)) + +// COMP, LPCOMP +#if (NRF_MODULE_ENABLED(COMP) || NRF_MODULE_ENABLED(LPCOMP)) + #define COMP_LPCOMP_IN_USE + + #ifndef IS_COMP_LPCOMP + #define IS_COMP_LPCOMP(p_per_base) ((p_per_base) == NRF_LPCOMP) + #endif + + static shared_resource_t m_comp_lpcomp = { .acquired = false }; + void LPCOMP_IRQHandler(void) + { + ASSERT(m_comp_lpcomp.handler); + m_comp_lpcomp.handler(); + } +#endif // (NRF_MODULE_ENABLED(COMP) || NRF_MODULE_ENABLED(LPCOMP)) + +#if defined(SERIAL_BOX_0_IN_USE) || \ + defined(SERIAL_BOX_1_IN_USE) || \ + defined(SERIAL_BOX_2_IN_USE) || \ + defined(COMP_LPCOMP_IN_USE) +static ret_code_t acquire_shared_resource(shared_resource_t * p_resource, + nrf_drv_irq_handler_t handler) +{ + ret_code_t err_code; + + bool busy = false; + + CRITICAL_REGION_ENTER(); + if (p_resource->acquired) + { + busy = true; + } + else + { + p_resource->acquired = true; + } + CRITICAL_REGION_EXIT(); + + if (busy) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + p_resource->handler = handler; + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} +#endif + +ret_code_t nrf_drv_common_per_res_acquire(void const * p_per_base, + nrf_drv_irq_handler_t handler) +{ +#ifdef SERIAL_BOX_0_IN_USE + if (IS_SERIAL_BOX_0(p_per_base)) + { + return acquire_shared_resource(&m_serial_box_0, handler); + } +#endif + +#ifdef SERIAL_BOX_1_IN_USE + if (IS_SERIAL_BOX_1(p_per_base)) + { + return acquire_shared_resource(&m_serial_box_1, handler); + } +#endif + +#ifdef SERIAL_BOX_2_IN_USE + if (IS_SERIAL_BOX_2(p_per_base)) + { + return acquire_shared_resource(&m_serial_box_2, handler); + } +#endif + +#ifdef COMP_LPCOMP_IN_USE + if (IS_COMP_LPCOMP(p_per_base)) + { + return acquire_shared_resource(&m_comp_lpcomp, handler); + } +#endif + ret_code_t err_code; + + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_common_per_res_release(void const * p_per_base) +{ +#ifdef SERIAL_BOX_0_IN_USE + if (IS_SERIAL_BOX_0(p_per_base)) + { + m_serial_box_0.acquired = false; + } + else +#endif + +#ifdef SERIAL_BOX_1_IN_USE + if (IS_SERIAL_BOX_1(p_per_base)) + { + m_serial_box_1.acquired = false; + } + else +#endif + +#ifdef SERIAL_BOX_2_IN_USE + if (IS_SERIAL_BOX_2(p_per_base)) + { + m_serial_box_2.acquired = false; + } + else +#endif + +#ifdef COMP_LPCOMP_IN_USE + if (IS_COMP_LPCOMP(p_per_base)) + { + m_comp_lpcomp.acquired = false; + } + else +#endif + + {} +} + +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +#if NRF_MODULE_ENABLED(POWER) +void nrf_drv_common_power_irq_disable(void) +{ +#if NRF_DRV_COMMON_POWER_CLOCK_ISR + if (!nrf_drv_clock_init_check()) +#endif + { + nrf_drv_common_irq_disable(POWER_CLOCK_IRQn); + } +} +#endif + +#if NRF_MODULE_ENABLED(CLOCK) +void nrf_drv_common_clock_irq_disable(void) +{ +#if NRF_DRV_COMMON_POWER_CLOCK_ISR + if (!nrf_drv_power_init_check()) +#endif + { + nrf_drv_common_irq_disable(POWER_CLOCK_IRQn); + } +} +#endif + +#if NRF_DRV_COMMON_POWER_CLOCK_ISR +void POWER_CLOCK_IRQHandler(void) +{ + extern void nrf_drv_clock_onIRQ(void); + extern void nrf_drv_power_onIRQ(void); + + nrf_drv_clock_onIRQ(); + nrf_drv_power_onIRQ(); +} +#endif // NRF_DRV_COMMON_POWER_CLOCK_ISR + + +void nrf_drv_common_irq_enable(IRQn_Type IRQn, uint8_t priority) +{ + INTERRUPT_PRIORITY_ASSERT(priority); + + NVIC_SetPriority(IRQn, priority); + NVIC_ClearPendingIRQ(IRQn); + NVIC_EnableIRQ(IRQn); +} diff --git a/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.h b/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.h new file mode 100644 index 000000000..e874170c6 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/common/nrf_drv_common.h @@ -0,0 +1,357 @@ +/** + * Copyright (c) 2015 - 2017, 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_COMMON_H__ +#define NRF_DRV_COMMON_H__ + +#include +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "sdk_common.h" +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NRF51 +#ifdef SOFTDEVICE_PRESENT +#define INTERRUPT_PRIORITY_IS_VALID(pri) (((pri) == 1) || ((pri) == 3)) +#else +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((pri) < 4) +#endif //SOFTDEVICE_PRESENT +#else +#ifdef SOFTDEVICE_PRESENT +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((((pri) > 1) && ((pri) < 4)) || (((pri) > 5) && ((pri) < 8))) +#else +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((pri) < 8) +#endif //SOFTDEVICE_PRESENT +#endif //NRF52 + +#define INTERRUPT_PRIORITY_VALIDATION(pri) STATIC_ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) +#define INTERRUPT_PRIORITY_ASSERT(pri) ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) + +/** + * @defgroup nrf_drv_common Peripheral drivers common module + * @{ + * @ingroup nrf_drivers + */ + +/** + * @brief Offset of event registers in every peripheral instance. + * + * This is the offset where event registers start in every peripheral. + */ +#define NRF_DRV_COMMON_EVREGS_OFFSET 0x100U + +/** + * @brief The flag that is set when POWER_CLOCK ISR is implemented in common module + * + * This flag means that the function POWER_CLOCK_IRQHandler is implemented in + * nrf_drv_common.c file. In the @c clock and @c power modules functions + * nrf_drv_clock_onIRQ nrf_drv_power_onIRQ should be implemented + * and they would be called from common implementation. + * + * None of the checking is done here. + * The implementation functions in @c clock and @c power are required to handle + * correctly the case when they are called without any event bit set. + */ +#define NRF_DRV_COMMON_POWER_CLOCK_ISR (NRF_MODULE_ENABLED(CLOCK) && NRF_MODULE_ENABLED(POWER)) + +/** + * @brief Driver state. + */ +typedef enum +{ + NRF_DRV_STATE_UNINITIALIZED, /**< Uninitialized. */ + NRF_DRV_STATE_INITIALIZED, /**< Initialized but powered off. */ + NRF_DRV_STATE_POWERED_ON +} nrf_drv_state_t; + +/** + * @brief Driver power state selection. + */ +typedef enum +{ + NRF_DRV_PWR_CTRL_ON, /**< Power on request. */ + NRF_DRV_PWR_CTRL_OFF /**< Power off request. */ +} nrf_drv_pwr_ctrl_t; + +/** + * @brief IRQ handler type. + */ +typedef void (*nrf_drv_irq_handler_t)(void); + + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +/** + * @brief Function for acquiring shared peripheral resources associated with + * the specified peripheral. + * + * Certain resources and registers are shared among peripherals that have + * the same ID (for example: SPI0, SPIM0, SPIS0, TWI0, TWIM0, and TWIS0). + * Only one of them can be utilized at a given time. This function reserves + * proper resources to be used by the specified peripheral. + * If PERIPHERAL_RESOURCE_SHARING_ENABLED is set to a non-zero value, IRQ + * handlers for peripherals that are sharing resources with others are + * implemented by the nrf_drv_common module instead of individual drivers. + * The drivers must then specify their interrupt handling routines and + * register them by using this function. + * + * @param[in] p_per_base Requested peripheral base pointer. + * @param[in] handler Interrupt handler to register. May be NULL + * if interrupts are not used for the peripheral. + * + * @retval NRF_SUCCESS If resources were acquired successfully. + * @retval NRF_ERROR_BUSY If resources were already acquired. + * @retval NRF_ERROR_INVALID_PARAM If the specified peripheral is not enabled + * or the peripheral does not share resources + * with other peripherals. + */ +ret_code_t nrf_drv_common_per_res_acquire(void const * p_per_base, + nrf_drv_irq_handler_t handler); + +/** + * @brief Function for releasing shared resources reserved previously by + * @ref nrf_drv_common_per_res_acquire() for the specified peripheral. + * + * @param[in] p_per_base Requested peripheral base pointer. + */ +void nrf_drv_common_per_res_release(void const * p_per_base); + +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + + +/** + * @brief Function sets priority and enables NVIC interrupt + * + * @note Function checks if correct priority is used when softdevice is present + * + * @param[in] IRQn Interrupt id + * @param[in] priority Interrupt priority + */ +void nrf_drv_common_irq_enable(IRQn_Type IRQn, uint8_t priority); + +#if NRF_MODULE_ENABLED(POWER) +/** + * @brief Disable power IRQ + * + * Power and clock peripheral uses the same IRQ. + * This function disables POWER_CLOCK IRQ only if CLOCK driver + * is uninitialized. + * + * @sa nrf_drv_common_power_clock_irq_init + */ +void nrf_drv_common_power_irq_disable(void); +#endif + +#if NRF_MODULE_ENABLED(CLOCK) +/** + * @brief Disable clock IRQ + * + * Power and clock peripheral uses the same IRQ. + * This function disables POWER_CLOCK IRQ only if POWER driver + * is uninitialized. + * + * @sa nrf_drv_common_power_clock_irq_init + */ +void nrf_drv_common_clock_irq_disable(void); +#endif + +/** + * @brief Check if interrupt is enabled + * + * Function that checks if selected interrupt is enabled. + * + * @param[in] IRQn Interrupt id + * + * @retval true Selected IRQ is enabled. + * @retval false Selected IRQ is disabled. + */ +__STATIC_INLINE bool nrf_drv_common_irq_enable_check(IRQn_Type IRQn); + +/** + * @brief Function disables NVIC interrupt + * + * @param[in] IRQn Interrupt id + */ +__STATIC_INLINE void nrf_drv_common_irq_disable(IRQn_Type IRQn); + +/** + * @brief Convert bit position to event code + * + * Function for converting the bit position in INTEN register to event code + * that is equivalent to the offset of the event register from the beginning + * of peripheral instance. + * + * For example the result of this function can be casted directly to + * the types like @ref nrf_twis_event_t or @ref nrf_rng_event_t + * + * @param bit Bit position in INTEN register + * @return Event code to be casted to the right enum type or to be used in functions like + * @ref nrf_rng_event_get + * + * @sa nrf_drv_event_to_bitpos + */ +__STATIC_INLINE uint32_t nrf_drv_bitpos_to_event(uint32_t bit); + +/** + * @brief Convert event code to bit position + * + * This function can be used to get bit position in INTEN register from event code. + * + * @param event Event code that may be casted from enum values from types like + * @ref nrf_twis_event_t or @ref nrf_rng_event_t + * @return Bit position in INTEN register that corresponds to the given code. + * + * @sa nrf_drv_bitpos_to_event + */ +__STATIC_INLINE uint32_t nrf_drv_event_to_bitpos(uint32_t event); + +/** + * @brief Get interrupt number connected with given instance + * + * Function returns interrupt number for a given instance of any peripheral. + * @param[in] pinst Pointer to peripheral registry + * @return Interrupt number + */ +__STATIC_INLINE IRQn_Type nrf_drv_get_IRQn(void const * const pinst); + +#if NRF_MODULE_ENABLED(CLOCK) || NRF_MODULE_ENABLED(POWER) +/** + * @brief Enable and setup power clock IRQ + * + * This function would be called from @ref nrf_drv_clock and @ref nrf_drv_power + * to enable related interrupt. + * This function avoids multiple interrupt configuration. + * + * @note + * This function is aviable only if @ref nrf_drv_clock or @ref nrf_drv_power + * module is enabled. + * + * @note + * If both @ref nrf_drv_clock and @ref nrf_drv_power modules are enabled, + * during the compilation the check is made that + * @ref CLOCK_CONFIG_IRQ_PRIORITY equals @ref POWER_CONFIG_IRQ_PRIORITY. + * + * @sa nrf_drv_common_power_irq_disable + * @sa nrf_drv_common_clock_irq_disable + */ +__STATIC_INLINE void nrf_drv_common_power_clock_irq_init(void); +#endif + +/** + * @brief Check if given object is in RAM + * + * Function for analyzing if given location is placed in RAM. + * This function is used to determine if we have address that can be supported by EasyDMA. + * @param[in] ptr Pointer to the object + * @retval true Object is located in RAM + * @retval false Object is not located in RAM + */ +__STATIC_INLINE bool nrf_drv_is_in_RAM(void const * const ptr); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE bool nrf_drv_common_irq_enable_check(IRQn_Type IRQn) +{ + return 0 != (NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & + (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); +} + +__STATIC_INLINE void nrf_drv_common_irq_disable(IRQn_Type IRQn) +{ + NVIC_DisableIRQ(IRQn); +} + +__STATIC_INLINE uint32_t nrf_drv_bitpos_to_event(uint32_t bit) +{ + return NRF_DRV_COMMON_EVREGS_OFFSET + bit * sizeof(uint32_t); +} + +__STATIC_INLINE uint32_t nrf_drv_event_to_bitpos(uint32_t event) +{ + return (event - NRF_DRV_COMMON_EVREGS_OFFSET) / sizeof(uint32_t); +} + +__STATIC_INLINE IRQn_Type nrf_drv_get_IRQn(void const * const pinst) +{ + uint8_t ret = (uint8_t)((uint32_t)pinst>>12U); + return (IRQn_Type) ret; +} + +#if NRF_MODULE_ENABLED(CLOCK) || NRF_MODULE_ENABLED(POWER) +__STATIC_INLINE void nrf_drv_common_power_clock_irq_init(void) +{ + if (!nrf_drv_common_irq_enable_check(POWER_CLOCK_IRQn)) + { + nrf_drv_common_irq_enable( + POWER_CLOCK_IRQn, +#if NRF_DRV_COMMON_POWER_CLOCK_ISR + #if CLOCK_CONFIG_IRQ_PRIORITY != POWER_CONFIG_IRQ_PRIORITY + #error CLOCK_CONFIG_IRQ_PRIORITY and POWER_CONFIG_IRQ_PRIORITY have to be the same. + #endif + CLOCK_CONFIG_IRQ_PRIORITY +#elif NRF_MODULE_ENABLED(CLOCK) + CLOCK_CONFIG_IRQ_PRIORITY +#elif NRF_MODULE_ENABLED(POWER) + POWER_CONFIG_IRQ_PRIORITY +#endif + ); + } +} +#endif + +__STATIC_INLINE bool nrf_drv_is_in_RAM(void const * const ptr) +{ + return ((((uintptr_t)ptr) & 0xE0000000u) == 0x20000000u); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_COMMON_H__ + +/** @} */ diff --git a/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c b/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c new file mode 100644 index 000000000..a09436230 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.c @@ -0,0 +1,477 @@ +/** + * Copyright (c) 2017 - 2017, 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(POWER) + +#include "nrf_drv_power.h" +#include "nrf_assert.h" +#include "nordic_common.h" +#include "app_util_platform.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdm.h" +#include "nrf_soc.h" +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#endif + +/* Validate configuration */ +INTERRUPT_PRIORITY_VALIDATION(POWER_CONFIG_IRQ_PRIORITY); + +/** + * @internal + * @defgroup nrf_drv_power_internals POWER driver internals + * @ingroup nrf_drv_power + * + * Internal variables, auxiliary macros and functions of POWER driver. + * @{ + */ + +/** + * @brief Default configuration + * + * The structure with default configuration data. + * This structure would be used if configuration pointer given + * to the @ref nrf_drv_power_init is set to NULL. + */ +static const nrf_drv_power_config_t m_drv_power_config_default = +{ + .dcdcen = POWER_CONFIG_DEFAULT_DCDCEN, +#if NRF_POWER_HAS_VDDH + .dcdcenhv = POWER_CONFIG_DEFAULT_DCDCENHV, +#endif +}; + +/** + * @brief The initialization flag + */ +static bool m_initialized; + +/** + * @brief The handler of power fail comparator warning event + */ +static nrf_drv_power_pofwarn_event_handler_t m_pofwarn_handler; + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief The handler of sleep event handler + */ +static nrf_drv_power_sleep_event_handler_t m_sleepevt_handler; +#endif + +#if NRF_POWER_HAS_USBREG +/** + * @brief The handler of USB power events + */ +static nrf_drv_power_usb_event_handler_t m_usbevt_handler; +#endif + +/** @} */ + +bool nrf_drv_power_init_check(void) +{ + return m_initialized; +} + +ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config) +{ + nrf_drv_power_config_t const * p_used_config; + if (m_initialized) + { + return NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + return NRF_ERROR_INVALID_STATE; + } +#endif + + p_used_config = (p_config != NULL) ? + p_config : (&m_drv_power_config_default); +#if NRF_POWER_HAS_VDDH + nrf_power_dcdcen_vddh_set(p_used_config->dcdcenhv); +#endif + nrf_power_dcdcen_set(p_used_config->dcdcen); + + nrf_drv_common_power_clock_irq_init(); + + m_initialized = true; + return NRF_SUCCESS; +} + +void nrf_drv_power_uninit(void) +{ + ASSERT(m_initialized); + nrf_drv_power_pof_uninit(); +#if NRF_POWER_HAS_SLEEPEVT + nrf_drv_power_sleepevt_uninit(); +#endif +#if NRF_POWER_HAS_USBREG + nrf_drv_power_usbevt_uninit(); +#endif + m_initialized = false; +} + +ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config) +{ + ASSERT(p_config != NULL); + + nrf_drv_power_pof_uninit(); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /* Currently when SD is enabled - the configuration can be changed + * in very limited range. + * It is the SoftDevice limitation. + */ +#if NRF_POWER_HAS_VDDH + if (p_config->thrvddh != nrf_power_pofcon_vddh_get()) + { + /* Cannot change THRVDDH with current SD API */ + return NRF_ERROR_INVALID_STATE; + } +#endif + if (p_config->thr != nrf_power_pofcon_get(NULL)) + { + /* Only limited number of THR values are supported and + * the values taken by SD is different than the one in hardware + */ + uint8_t thr; + switch (p_config->thr) + { + case NRF_POWER_POFTHR_V21: + thr = NRF_POWER_THRESHOLD_V21; + break; + case NRF_POWER_POFTHR_V23: + thr = NRF_POWER_THRESHOLD_V23; + break; + case NRF_POWER_POFTHR_V25: + thr = NRF_POWER_THRESHOLD_V25; + break; + case NRF_POWER_POFTHR_V27: + thr = NRF_POWER_THRESHOLD_V27; + break; + default: + /* Cannot configure */ + return NRF_ERROR_INVALID_STATE; + } + ASSERT(sd_power_pof_threshold_set(thr)); + } + } + else +#endif /* SOFTDEVICE_PRESENT */ + { + nrf_power_pofcon_set(true, p_config->thr); +#if NRF_POWER_HAS_VDDH + nrf_power_pofcon_vddh_set(p_config->thrvddh); +#endif + } + + if (p_config->handler != NULL) + { + m_pofwarn_handler = p_config->handler; +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void) sd_power_pof_enable(true); + } + else +#endif + { + nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK); + } + } + return NRF_SUCCESS; +} + +void nrf_drv_power_pof_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void) sd_power_pof_enable(false); + } + else +#endif + { + nrf_power_int_disable(NRF_POWER_INT_POFWARN_MASK); + } + m_pofwarn_handler = NULL; +} + +#if NRF_POWER_HAS_SLEEPEVT +ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config) +{ + ASSERT(p_config != NULL); + + nrf_drv_power_sleepevt_uninit(); + if (p_config->handler != NULL) + { + uint32_t enmask = 0; + m_sleepevt_handler = p_config->handler; + if (p_config->en_enter) + { + enmask |= NRF_POWER_INT_SLEEPENTER_MASK; + nrf_power_event_clear(NRF_POWER_EVENT_SLEEPENTER); + } + if (p_config->en_exit) + { + enmask |= NRF_POWER_INT_SLEEPEXIT_MASK; + nrf_power_event_clear(NRF_POWER_EVENT_SLEEPEXIT); + } +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + if (enmask != 0) + { + return NRF_ERROR_INVALID_STATE; + } + } + else +#endif + { + nrf_power_int_enable(enmask); + } + } + + return NRF_SUCCESS; +} + +void nrf_drv_power_sleepevt_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /* Nothing to do */ + } + else +#endif + { + nrf_power_int_disable( + NRF_POWER_INT_SLEEPENTER_MASK | + NRF_POWER_INT_SLEEPEXIT_MASK); + } + m_sleepevt_handler = NULL; +} +#endif /* NRF_POWER_HAS_SLEEPEVT */ + +#if NRF_POWER_HAS_USBREG +ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config) +{ + nrf_drv_power_usbevt_uninit(); + if (p_config->handler != NULL) + { + m_usbevt_handler = p_config->handler; +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /** @todo Implement USB power events when SD support it */ + return NRF_ERROR_INVALID_STATE; + } + else +#endif + { + nrf_power_int_enable( + NRF_POWER_INT_USBDETECTED_MASK | + NRF_POWER_INT_USBREMOVED_MASK | + NRF_POWER_INT_USBPWRRDY_MASK); + } + } + return NRF_SUCCESS; +} + +void nrf_drv_power_usbevt_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /** @todo Implement USB power events when SD support it */ + } + else +#endif + { + nrf_power_int_disable( + NRF_POWER_INT_USBDETECTED_MASK | + NRF_POWER_INT_USBREMOVED_MASK | + NRF_POWER_INT_USBPWRRDY_MASK); + } + m_usbevt_handler = NULL; +} +#endif /* NRF_POWER_HAS_USBREG */ + + +/** + * @ingroup nrf_drv_power_internals + * @brief Interrupt handler + * + * POWER peripheral interrupt handler + */ +#if NRF_DRV_COMMON_POWER_CLOCK_ISR +void nrf_drv_power_onIRQ(void) +#else +void POWER_CLOCK_IRQHandler(void) +#endif +{ + uint32_t enabled = nrf_power_int_enable_get(); + if ((0 != (enabled & NRF_POWER_INT_POFWARN_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_POFWARN)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_pofwarn_handler != NULL); + m_pofwarn_handler(); + } +#if NRF_POWER_HAS_SLEEPEVT + if ((0 != (enabled & NRF_POWER_INT_SLEEPENTER_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_SLEEPENTER)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_sleepevt_handler != NULL); + m_sleepevt_handler(NRF_DRV_POWER_SLEEP_EVT_ENTER); + } + if ((0 != (enabled & NRF_POWER_INT_SLEEPEXIT_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_SLEEPEXIT)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_sleepevt_handler != NULL); + m_sleepevt_handler(NRF_DRV_POWER_SLEEP_EVT_EXIT); + } +#endif +#if NRF_POWER_HAS_USBREG + if ((0 != (enabled & NRF_POWER_INT_USBDETECTED_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBDETECTED)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_usbevt_handler != NULL); + m_usbevt_handler(NRF_DRV_POWER_USB_EVT_DETECTED); + } + if ((0 != (enabled & NRF_POWER_INT_USBREMOVED_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBREMOVED)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_usbevt_handler != NULL); + m_usbevt_handler(NRF_DRV_POWER_USB_EVT_REMOVED); + } + if ((0 != (enabled & NRF_POWER_INT_USBPWRRDY_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBPWRRDY)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_usbevt_handler != NULL); + m_usbevt_handler(NRF_DRV_POWER_USB_EVT_READY); + } +#endif +} + +#ifdef SOFTDEVICE_PRESENT + +static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context); +static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context); + +NRF_SDH_SOC_OBSERVER(m_soc_observer, POWER_CONFIG_SOC_OBSERVER_PRIO, + nrf_drv_power_sdh_soc_evt_handler, NULL); + +NRF_SDH_STATE_OBSERVER(m_sd_observer, POWER_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = nrf_drv_power_sdh_state_evt_handler, + .p_context = NULL +}; + +static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context) +{ + if (evt_id == NRF_EVT_POWER_FAILURE_WARNING) + { + /* Cannot be null if event is enabled */ + ASSERT(m_pofwarn_handler != NULL); + m_pofwarn_handler(); + } +} + +static void nrf_drv_power_on_sd_enable(void) +{ + ASSERT(m_initialized); /* This module has to be enabled first */ + CRITICAL_REGION_ENTER(); + if (m_pofwarn_handler != NULL) + { + (void) sd_power_pof_enable(true); + } + CRITICAL_REGION_EXIT(); +} + +static void nrf_drv_power_on_sd_disable(void) +{ + /* Reinit interrupts */ + ASSERT(m_initialized); + nrf_drv_common_irq_enable(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY); + if (m_pofwarn_handler != NULL) + { + nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK); + } +#if NRF_POWER_HAS_USBREG + if (m_usbevt_handler != NULL) + { + nrf_power_int_enable( + NRF_POWER_INT_USBDETECTED_MASK | + NRF_POWER_INT_USBREMOVED_MASK | + NRF_POWER_INT_USBPWRRDY_MASK); + } +#endif +} + +static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLED: + nrf_drv_power_on_sd_enable(); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + nrf_drv_power_on_sd_disable(); + break; + + default: + break; + } +} + +#endif // SOFTDEVICE_PRESENT + +#endif /* NRF_MODULE_ENABLED(POWER) */ diff --git a/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.h b/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.h new file mode 100644 index 000000000..e691b8eb8 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/power/nrf_drv_power.h @@ -0,0 +1,371 @@ +/** + * Copyright (c) 2017 - 2017, 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_POWER_H__ +#define NRF_DRV_POWER_H__ + +#include +#include +#include "nrf_power.h" +#include "sdk_config.h" +#include "nrf_drv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_power Power HAL and driver + * @ingroup nrf_drivers + * @brief POWER peripheral APIs. + * + * The power peripheral HAL provides basic APIs for accessing + * the registers of the POWER peripheral. + * The POWER driver provides APIs on a higher level. + */ + +/** + * @defgroup nrf_drv_power POWER driver + * @{ + * @ingroup nrf_power + * @brief Driver for managing events and the state of POWER peripheral. + * + */ + +/** + * @brief Power mode possible configurations + */ +typedef enum +{ + NRF_DRV_POWER_MODE_CONSTLAT, /**< Constant latency mode *///!< NRF_DRV_POWER_MODE_CONSTLAT + NRF_DRV_POWER_MODE_LOWPWR /**< Low power mode *///!< NRF_DRV_POWER_MODE_LOWPWR +}nrf_drv_power_mode_t; + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief Events from power system + */ +typedef enum +{ + NRF_DRV_POWER_SLEEP_EVT_ENTER, /**< CPU entered WFI/WFE sleep + * + * Keep in mind that if this interrupt is enabled, + * it means that CPU was waken up just after WFI by this interrupt. + */ + NRF_DRV_POWER_SLEEP_EVT_EXIT /**< CPU exited WFI/WFE sleep */ +}nrf_drv_power_sleep_evt_t; +#endif /* NRF_POWER_HAS_SLEEPEVT */ + +#if NRF_POWER_HAS_USBREG +/** + * @brief Events from USB power system + */ +typedef enum +{ + NRF_DRV_POWER_USB_EVT_DETECTED, /**< USB power detected on the connector (plugged in). */ + NRF_DRV_POWER_USB_EVT_REMOVED, /**< USB power removed from the connector. */ + NRF_DRV_POWER_USB_EVT_READY /**< USB power regulator ready. */ +}nrf_drv_power_usb_evt_t; + +/** + * @brief USB power state + * + * The single enumerator that holds all data about current state of USB + * related POWER. + * + * Organized this way that higher power state has higher numeric value + */ +typedef enum +{ + NRF_DRV_POWER_USB_STATE_DISCONNECTED, /**< No power on USB lines detected */ + NRF_DRV_POWER_USB_STATE_CONNECTED, /**< The USB power is detected, but USB power regulator is not ready */ + NRF_DRV_POWER_USB_STATE_READY /**< From the power point of view USB is ready for working */ +}nrf_drv_power_usb_state_t; +#endif /* NRF_POWER_HAS_USBREG */ + +/** + * @name Callback types + * + * Defined types of callback functions + * @{ + */ +/** + * @brief Event handler for power failure warning + */ +typedef void (*nrf_drv_power_pofwarn_event_handler_t)(void); + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief Event handler for entering/exiting sleep + * + * @param event Event type + */ +typedef void (*nrf_drv_power_sleep_event_handler_t)(nrf_drv_power_sleep_evt_t event); +#endif + +#if NRF_POWER_HAS_USBREG +/** + * @brief Event handler for USB related power events + * + * @param event Event type + */ +typedef void (*nrf_drv_power_usb_event_handler_t)(nrf_drv_power_usb_evt_t event); +#endif +/** @} */ + +/** + * @brief General power configuration + * + * Parameters required to initialize power driver. + */ +typedef struct +{ + /** + * @brief Enable main DCDC regulator + * + * This bit only informs the driver that elements for DCDC regulator + * are installed and regulator can be used. + * The regulator would be enabled or disabled automatically + * automatically by the hardware, basing on current power requirement. + */ + bool dcdcen:1; + +#if NRF_POWER_HAS_VDDH + /** + * @brief Enable HV DCDC regulator + * + * This bit only informs the driver that elements for DCDC regulator + * are installed and regulator can be used. + * The regulator would be enabled or disabled automatically + * automatically by the hardware, basing on current power requirement. + */ + bool dcdcenhv: 1; +#endif +}nrf_drv_power_config_t; + +/** + * @brief The configuration for power failure comparator + * + * Configuration used to enable and configure power failure comparator + */ +typedef struct +{ + nrf_drv_power_pofwarn_event_handler_t handler; //!< Event handler + nrf_power_pof_thr_t thr; //!< Threshold for power failure detection +#if NRF_POWER_HAS_VDDH + nrf_power_pof_thrvddh_t thrvddh; //!< Threshold for power failure detection on VDDH pin +#endif +}nrf_drv_power_pofwarn_config_t; + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief The configuration of sleep event processing + * + * Configuration used to enable and configure sleep event handling + */ +typedef struct +{ + nrf_drv_power_sleep_event_handler_t handler; //!< Event handler + bool en_enter:1; //!< Enable event on sleep entering + bool en_exit :1; //!< Enable event on sleep exiting +}nrf_drv_power_sleepevt_config_t; +#endif + +#if NRF_POWER_HAS_USBREG +/** + * @brief The configuration of USB related power events + * + * Configuration used to enable and configure USB power event handling + */ +typedef struct +{ + nrf_drv_power_usb_event_handler_t handler; //!< Event processing +}nrf_drv_power_usbevt_config_t; +#endif /* NRF_POWER_HAS_USBREG */ + +/** + * @brief Function for checking if driver is already initialized + * + * This function is used to check whatever common POWER_CLOCK common interrupt + * should be disabled or not if @ref nrf_drv_clock tries to disable the interrupt. + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + * + * @sa nrf_drv_power_uninit + */ +bool nrf_drv_power_init_check(void); + +/** + * @brief Initialize power module driver + * + * Enabled power module driver would process all the interrupts from power system. + * + * @param[in] p_config Driver configuration. Can be NULL - the default configuration + * from @em sdk_config.h file would be used then. + * + * @retval NRF_ERROR_INVALID_STATE Power driver has to be enabled + * before SoftDevice. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED Module is initialized already. + * @retval NRF_SUCCESS Successfully initialized. + */ +ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config); + +/** + * @brief Unintialize power module driver + * + * Disables all the interrupt handling in the module. + * + * @sa nrf_drv_power_init + */ +void nrf_drv_power_uninit(void); + +/** + * @brief Initialize power failure comparator + * + * Configures and setups the power failure comparator and enables it. + * + * @param[in] p_config Configuration with values and event handler. + * If event handler is set to NULL, interrupt would be disabled. + * + * @retval NRF_ERROR_INVALID_STATE POF is initialized when SD is enabled and + * the configuration differs from the old one and + * is not possible to be set using SD interface. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config); + +/** + * @brief Turn off the power failure comparator + * + * Disables and clears the settings of the power failure comparator. + */ +void nrf_drv_power_pof_uninit(void); + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief Initialize sleep entering and exiting events processing + * + * Configures and setups the sleep event processing. + * + * @param[in] p_config Configuration with values and event handler. + * + * @sa nrf_drv_power_sleepevt_uninit + * + * @note Sleep events are not available when SoftDevice is enabled. + * @note If sleep event is enabled when SoftDevice is initialized, sleep events + * would be automatically disabled - it is the limitation of the + * SoftDevice itself. + * + * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized + * when SD is enabled. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config); + +/** + * @brief Uninitialize sleep entering and exiting events processing + * + * @sa nrf_drv_power_sleepevt_init + */ +void nrf_drv_power_sleepevt_uninit(void); +#endif /* NRF_POWER_HAS_SLEEPEVT */ + +#if NRF_POWER_HAS_USBREG +/** + * @brief Initialize USB power event processing + * + * Configures and setups the USB power event processing. + * + * @param[in] p_config Configuration with values and event handler. + * + * @sa nrf_drv_power_usbevt_uninit + * + * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized + * when SD is enabled and SD does not support + * USB power events. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config); + +/** + * @brief Uninitalize USB power event processing + * + * @sa nrf_drv_power_usbevt_init + */ +void nrf_drv_power_usbevt_uninit(void); + +/** + * @brief Get the status of USB power + * + * @return Current USB power status + */ +__STATIC_INLINE nrf_drv_power_usb_state_t nrf_drv_power_usbstatus_get(void); + +#endif /* NRF_POWER_HAS_USBREG */ + +/** @} */ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +#if NRF_POWER_HAS_USBREG +__STATIC_INLINE nrf_drv_power_usb_state_t nrf_drv_power_usbstatus_get(void) +{ + uint32_t status = nrf_power_usbregstatus_get(); + if (0 == (status & NRF_POWER_USBREGSTATUS_VBUSDETECT_MASK)) + { + return NRF_DRV_POWER_USB_STATE_DISCONNECTED; + } + if (0 == (status & NRF_POWER_USBREGSTATUS_OUTPUTRDY_MASK)) + { + return NRF_DRV_POWER_USB_STATE_CONNECTED; + } + return NRF_DRV_POWER_USB_STATE_READY; +} +#endif /* NRF_POWER_HAS_USBREG */ + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_DRV_POWER_H__ */ diff --git a/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.c b/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.c new file mode 100644 index 000000000..041c41f1d --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.c @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2016 - 2017, 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(SYSTICK) +#include "nrf_drv_systick.h" +#include "nrf_systick.h" +#include "nrf.h" +#include "nrf_assert.h" + +/** + * @brief Maximum number of ticks to delay + * + * The maximum number of ticks should be much lower than + * Physical maximum count of the SysTick timer. + * It is dictated by the fact that it would be impossible to detect delay + * properly when the timer value warps around the starting point. + */ +#define NRF_DRV_SYSTICK_TICKS_MAX (NRF_SYSTICK_VAL_MASK / 2UL) + +/** + * @brief Number of milliseconds in a second + */ +#define NRF_DRV_SYSTICK_MS (1000UL) + +/** + * @brief Number of microseconds in a second + */ +#define NRF_DRV_SYSTICK_US (1000UL * NRF_DRV_SYSTICK_MS) + +/** + * @brief Number of milliseconds to wait in single loop + * + * Constant used by @ref nrd_drv_systick_delay_ms function + * to split waiting into loops and rest. + * + * It describes the number of milliseconds to wait in single loop. + * + * See @ref nrf_drv_systick_delay_ms source code for details. + */ +#define NRF_DRV_SYSTICK_MS_STEP (64U) + +/** + * @brief Checks if the given time is in correct range + * + * Function tests given time is not to big for this library. + * Assertion is used for testing. + * + * @param us Time in microseconds to check + */ +#define NRF_DRV_SYSTICK_ASSERT_TIMEOUT(us) \ + ASSERT(us <= (NRF_DRV_SYSTICK_TICKS_MAX / ((SystemCoreClock) / NRF_DRV_SYSTICK_US))); + +/** + * @brief Function that converts microseconds to ticks + * + * Function converts from microseconds to CPU ticks. + * + * @param us Number of microseconds + * + * @return Number of ticks + * + * @sa nrf_drv_systick_ms_tick + */ +static inline uint32_t nrf_drv_systick_us_tick(uint32_t us) +{ + return us * ((SystemCoreClock) / NRF_DRV_SYSTICK_US); +} + +/** + * @brief Function that converts milliseconds to ticks + * + * Function converts from milliseconds to CPU ticks. + * + * @param us Number of milliseconds + * + * @return Number of ticks + * + * @sa nrf_drv_systick_us_tick + */ +static inline uint32_t nrf_drv_systick_ms_tick(uint32_t ms) +{ + return ms * ((SystemCoreClock) / NRF_DRV_SYSTICK_MS); +} + +void nrf_drv_systick_init(void) +{ + nrf_systick_load_set(NRF_SYSTICK_VAL_MASK); + nrf_systick_csr_set( + NRF_SYSTICK_CSR_CLKSOURCE_CPU | + NRF_SYSTICK_CSR_TICKINT_DISABLE | + NRF_SYSTICK_CSR_ENABLE); +} + +void nrf_drv_systick_get(nrf_drv_systick_state_t * p_state) +{ + p_state->time = nrf_systick_val_get(); +} + +bool nrf_drv_systick_test(nrf_drv_systick_state_t const * p_state, uint32_t us) +{ + NRF_DRV_SYSTICK_ASSERT_TIMEOUT(us); + + const uint32_t diff = NRF_SYSTICK_VAL_MASK & ((p_state->time) - nrf_systick_val_get()); + return (diff >= nrf_drv_systick_us_tick(us)); +} + +void nrf_drv_systick_delay_ticks(uint32_t ticks) +{ + ASSERT(ticks <= NRF_DRV_SYSTICK_TICKS_MAX) + + const uint32_t start = nrf_systick_val_get(); + while ((NRF_SYSTICK_VAL_MASK & (start - nrf_systick_val_get())) < ticks) + { + /* Nothing to do */ + } +} + +void nrf_drv_systick_delay_us(uint32_t us) +{ + NRF_DRV_SYSTICK_ASSERT_TIMEOUT(us); + nrf_drv_systick_delay_ticks(nrf_drv_systick_us_tick(us)); +} + +void nrf_drv_systick_delay_ms(uint32_t ms) +{ + uint32_t n = ms / NRF_DRV_SYSTICK_MS_STEP; + uint32_t r = ms % NRF_DRV_SYSTICK_MS_STEP; + while (0 != (n--)) + { + nrf_drv_systick_delay_ticks(nrf_drv_systick_ms_tick(NRF_DRV_SYSTICK_MS_STEP)); + } + nrf_drv_systick_delay_ticks(nrf_drv_systick_ms_tick(r)); +} + +#endif // NRF_MODULE_ENABLED(SYSTICK) diff --git a/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h b/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h new file mode 100644 index 000000000..34492af2a --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2016 - 2017, 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_SYSTICK_H__ +#define NRF_DRV_SYSTICK_H__ +#include +#include + + +/** + * @addtogroup nrf_systick SysTick HAL and driver + * @ingroup nrf_drivers + * @brief System Timer (SysTick) APIs + * + * The SysTick HAL provides basic APIs for accessing the registers of the system timer (SysTick). + * The SysTick driver provides APIs on a higher level. + */ + +/** + * @defgroup nrf_drv_systick SysTick driver + * @{ + * @ingroup nrf_systick + * + * This library configures SysTick as a free-running timer. + * This timer is used to generate delays and pool for timeouts. + * Only relatively short timeouts are supported. + * The SysTick works on 64MHz and is 24-bits wide. + * It means that it overflows around 4 times per second and around 250 ms + * would be the highest supported time in the library. + * But it would be really hard to detect if overflow was generated without + * using interrupts. For safely we would limit the maximum delay range by half. + */ + +/** + * @brief The value type that holds the SysTick state + * + * This variable is used to count the requested timeout. + * @sa nrf_drv_systick_get + */ +typedef struct { + uint32_t time; //!< Registered time value +}nrf_drv_systick_state_t; + +/** + * @brief Configure and start the timer + * + * Function configures SysTick as a free-running timer without interrupt. + */ +void nrf_drv_systick_init(void); + +/** + * @brief Get current SysTick state + * + * Function gets current state of the SysTick timer. + * It can be used to check time-out by @ref nrf_drv_systick_test. + * + * @param[out] p_state The pointer to the state variable to be filled + */ +void nrf_drv_systick_get(nrf_drv_systick_state_t * p_state); + +/** + * @brief Test if specified time is up in relation to remembered state + * + * @param[in] p_state Remembered state set by @ref nrf_drv_systick_get + * @param[in] us Required time-out. + * + * @retval true If current time is higher than specified state plus given time-out. + * @retval false If current time is lower than specified state plus given time-out + */ +bool nrf_drv_systick_test(nrf_drv_systick_state_t const * p_state, uint32_t us); + +/** + * @brief Blocking delay in CPU ticks + * + * @param[in] ticks Number of CPU ticks to delay. + */ +void nrf_drv_systick_delay_ticks(uint32_t ticks); + +/** + * @brief Blocking delay in us + * + * @param[in] us Number of microseconds to delay. + */ +void nrf_drv_systick_delay_us(uint32_t us); + +/** + * @brief Blocking delay in ms + * + * This delay function removes the limits of the highest possible delay value. + * + * @param[in] ms Number of milliseconds to delay. + */ +void nrf_drv_systick_delay_ms(uint32_t ms); + + +/** @} */ +#endif /* NRF_DRV_SYSTICK_H__ */ diff --git a/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.c b/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.c new file mode 100644 index 000000000..207bd5dbd --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.c @@ -0,0 +1,2179 @@ +/** + * Copyright (c) 2016 - 2017, 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_config.h" +#if USBD_ENABLED +#include "nrf_drv_usbd.h" +#include "nrf.h" +#include "nordic_common.h" +#include "nrf_drv_common.h" +#include "nrf_atomic.h" +#include "nrf_delay.h" +#include "app_util_platform.h" +#include "nrf_drv_systick.h" /* Marker to delete when not required anymore: >> NRF_DRV_USBD_ERRATA_ENABLE << */ + +#include +#include + +#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 1 +#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 nrf_drv_state_t m_drv_state = NRF_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 uint8_t 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) || + nrf_drv_is_in_RAM((const void*)(p_transfer->p_data.ptr))); + + size_t size = p_transfer->size; + if (size < data_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(nrf_drv_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(nrf_drv_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(!nrf_drv_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(!nrf_drv_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 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<handler.consumer = NULL; + m_ep_dma_waiting &= ~(1U<status = NRF_USBD_EP_ABORTED; + } + else + { + if ((m_ep_dma_waiting | (~m_ep_ready)) & (1U< Host */ + m_ep_dma_waiting &= ~(1U<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 usbd_drv_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)); + usbd_ep_abort(bit2ep(bitpos)); + ep_waiting &= ~(1U << bitpos); + } + + m_ep_ready = (((1U<status) + { + /* Nothing to do - just ignore */ + } + else if (p_state->handler.feeder == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U< 0); + m_dma_pending = 0; + + 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.feeder == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U<status) + { + /* Nothing to do - just ignore */ + } + else if (p_state->handler.feeder == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U<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< 0); + m_dma_pending = 0; + + 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<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< Host) */ + if (0 == (m_ep_dma_waiting & (1U< Device) */ + if (0 == (m_ep_dma_waiting & (1U<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; + if (ep == NRF_DRV_USBD_EPIN0) + { + /** Configure short right now - now if the last data is transferred, + * when host tries another data transfer, the endpoint will stall. */ + NRF_LOG_DEBUG("USB DMA process: Enable status short"); + nrf_usbd_shorts_enable(NRF_USBD_SHORT_EP0DATADONE_EP0STATUS_MASK); + } + } + } + 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) + { + p_state->status = NRF_USBD_EP_OVERLOAD; + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U<handler.consumer = NULL; + } + } + + m_dma_pending = 1; + 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_drv_systick_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_drv_systick_delay_us(30); + while (0 == (0x20 & *((volatile uint32_t *)(NRF_USBD_BASE + 0x474)))) + { + nrf_drv_systick_delay_us(2); + } + nrf_drv_systick_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); + } + + 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, + [USBD_INTEN_ACCESSFAULT_Pos] = ev_accessfault_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)nrf_drv_bitpos_to_event(event_nr))) + { + active |= 1UL << event_nr; + } + to_process &= ~(1UL << event_nr); + } + + if (nrf_drv_usbd_errata_104()) + { + /* Event correcting */ + if ((0 == 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)<status = NRF_USBD_EP_OK; + p_state->handler.feeder = NULL; + p_state->transfer_cnt = 0; + } + for (n=0; nstatus = 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 != NRF_DRV_STATE_INITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + + m_event_handler = NULL; + m_drv_state = NRF_DRV_STATE_UNINITIALIZED; + return NRF_SUCCESS; +} + +void nrf_drv_usbd_enable(void) +{ + ASSERT(m_drv_state == NRF_DRV_STATE_INITIALIZED); + + /* Prepare for READY event receiving */ + nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); + /* 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_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_DRV_STATE_INITIALIZED); +} + +bool nrf_drv_usbd_is_enabled(void) +{ + return (m_drv_state >= NRF_DRV_STATE_POWERED_ON); +} + +bool nrf_drv_usbd_is_started(void) +{ + return (nrf_drv_usbd_is_enabled() && nrf_drv_common_irq_enable_check(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; + } + } + } + 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; + } + 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_ep_enable(ep_to_hal(ep)); + nrf_usbd_int_enable(nrf_drv_usbd_ep_to_int(ep)); + + if ((NRF_USBD_EP_NR_GET(ep) != 0) && NRF_USBD_EPOUT_CHECK(ep)) + { + CRITICAL_REGION_ENTER(); + + m_ep_ready |= 1U<status = NRF_USBD_EP_ABORTED; + + CRITICAL_REGION_EXIT(); + } +} + +void nrf_drv_usbd_ep_disable(nrf_drv_usbd_ep_t ep) +{ + nrf_usbd_ep_disable(ep_to_hal(ep)); + nrf_usbd_int_disable(nrf_drv_usbd_ep_to_int(ep)); +} + +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 if (nrf_usbd_ep_is_stall(ep)) + { + ret = NRF_ERROR_FORBIDDEN; + if (NRF_USBD_FAILED_TRANSFERS_DEBUG && (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))) + { + NRF_LOG_DEBUG("USB driver: Transfer failed: EP is stalled"); + } + } + 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 (nrf_drv_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) || (nrf_drv_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 if (nrf_usbd_ep_is_stall(ep)) + { + ret = NRF_ERROR_FORBIDDEN; + if (NRF_USBD_FAILED_TRANSFERS_DEBUG && (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))) + { + NRF_LOG_DEBUG("USB driver: Transfer failed: EP is stalled"); + } + } + 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 & (1UL << 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_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 (m_ep_ready & (1U << ep2bit(ep))) + { + if (!NRF_USBD_EPISO_CHECK(ep)) + { + ret_code_t ret; + NRF_DRV_USBD_TRANSFER_OUT(transfer, 0, 0); + ret = nrf_drv_usbd_ep_transfer(ep, &transfer); + ASSERT(ret == NRF_SUCCESS); + UNUSED_VARIABLE(ret); + } + } +} + +#endif // USBD_ENABLED diff --git a/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.h b/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.h new file mode 100644 index 000000000..dda6e9e02 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.h @@ -0,0 +1,925 @@ +/** + * Copyright (c) 2016 - 2017, 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 "nrf_drv_common.h" +#include "sdk_errors.h" +#include "nrf_usbd.h" +#include +#include +#include "app_util.h" +#include "nrf_drv_usbd_errata.h" + +/** + * @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 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 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 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 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. + * + * When there is any data transmission after SETUP command the data transmission + * itself would clear the endpoint. + */ +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 usbd_drv_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); + +/** @} */ +#endif /* NRF_DRV_USBD_H__ */ diff --git a/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd_errata.h b/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd_errata.h new file mode 100644 index 000000000..369230723 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd_errata.h @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2017 - 2017, 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 +/** + * @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 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); + +/** + * @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); + +#if NRF_DRV_USBD_ERRATA_ENABLE + +static inline bool nrf_drv_usbd_errata_type_52840(void) +{ + return ((((*(uint32_t *)0xF0000FE0) & 0xFF) == 0x08) && (((*(uint32_t *)0xF0000FE4) & 0x0F) == 0x0)); +} + +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 ) ); +} + +static inline bool nrf_drv_usbd_errata_104(void) +{ + return nrf_drv_usbd_errata_type_52840_proto1(); +} + + +static inline bool nrf_drv_usbd_errata_154(void) +{ + return nrf_drv_usbd_errata_type_52840_proto1(); +} + +static inline bool nrf_drv_usbd_errata_166(void) +{ + return true; +} + +#else /* NRF_DRV_USBD_ERRATA_ENABLE */ + +static inline bool nrf_drv_usbd_errata_104(void) +{ + return false; +} + +static inline bool nrf_drv_usbd_errata_154(void) +{ + return false; +} + +static inline bool nrf_drv_usbd_errata_166(void) +{ + return false; +} + +#endif /* NRF_DRV_USBD_ERRATA_ENABLE */ +/** @} */ +#endif /* NRF_DRV_USBD_ERRATA_H__ */ diff --git a/third_party/NordicSemiconductor/hal/nrf_power.h b/third_party/NordicSemiconductor/hal/nrf_power.h new file mode 100644 index 000000000..dc16978c2 --- /dev/null +++ b/third_party/NordicSemiconductor/hal/nrf_power.h @@ -0,0 +1,1065 @@ +/** + * Copyright (c) 2017 - 2017, 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_POWER_H__ +#define NRF_POWER_H__ + +/** + * @ingroup nrf_power + * @defgroup nrf_power_hal POWER HAL + * @{ + * + * Hardware access layer for (POWER) peripheral. + */ +#include "nrf.h" +#include "sdk_config.h" +#include "nordic_common.h" +#include "nrf_assert.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(POWER_RAMSTATUS_RAMBLOCK0_Msk) +#define NRF_POWER_HAS_RAMSTATUS 1 +#else +#define NRF_POWER_HAS_RAMSTATUS 0 +#endif + +/** + * @name The implemented functionality + * @{ + * + * Macros that defines functionality that is implemented into POWER peripheral. + */ +#if defined(POWER_INTENSET_SLEEPENTER_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief The fact that sleep events are present + * + * In some MCUs there is possibility to process sleep entering and exiting + * events. + */ +#define NRF_POWER_HAS_SLEEPEVT 1 +#else +#define NRF_POWER_HAS_SLEEPEVT 0 +#endif + +#if defined(POWER_RAM_POWER_S0POWER_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief The fact that RAMPOWER registers are present + * + * After nRF51, new way to manage RAM power was implemented. + * Special registers, one for every RAM block that makes it possible to + * power ON or OFF RAM segments and turn ON and OFF RAM retention in system OFF + * state. + */ +#define NRF_POWER_HAS_RAMPOWER_REGS 1 +#else +#define NRF_POWER_HAS_RAMPOWER_REGS 0 +#endif + +#if defined(POWER_POFCON_THRESHOLDVDDH_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief Auxiliary definition to mark the fact that VDDH is present + * + * This definition can be used in a code to decide if the part with VDDH + * related settings should be implemented. + */ +#define NRF_POWER_HAS_VDDH 1 +#else +#define NRF_POWER_HAS_VDDH 0 +#endif + +#if defined(POWER_USBREGSTATUS_VBUSDETECT_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief The fact that power module manages USB regulator + * + * In devices that have USB, power peripheral manages also connection + * detection and USB power regulator, that converts 5 V to 3.3 V + * used by USBD peripheral. + */ +#define NRF_POWER_HAS_USBREG 1 +#else +#define NRF_POWER_HAS_USBREG 0 +#endif +/** @} */ + +/* ------------------------------------------------------------------------------------------------ + * Begin of automatically generated part + * ------------------------------------------------------------------------------------------------ + */ + +/** + * @brief POWER tasks + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_POWER_TASK_CONSTLAT = offsetof(NRF_POWER_Type, TASKS_CONSTLAT), /**< Enable constant latency mode */ + NRF_POWER_TASK_LOWPWR = offsetof(NRF_POWER_Type, TASKS_LOWPWR ), /**< Enable low power mode (variable latency) */ +}nrf_power_task_t; /*lint -restore */ + +/** + * @brief POWER events + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_POWER_EVENT_POFWARN = offsetof(NRF_POWER_Type, EVENTS_POFWARN ), /**< Power failure warning */ +#if NRF_POWER_HAS_SLEEPEVT + NRF_POWER_EVENT_SLEEPENTER = offsetof(NRF_POWER_Type, EVENTS_SLEEPENTER ), /**< CPU entered WFI/WFE sleep */ + NRF_POWER_EVENT_SLEEPEXIT = offsetof(NRF_POWER_Type, EVENTS_SLEEPEXIT ), /**< CPU exited WFI/WFE sleep */ +#endif +#if NRF_POWER_HAS_USBREG + NRF_POWER_EVENT_USBDETECTED = offsetof(NRF_POWER_Type, EVENTS_USBDETECTED), /**< Voltage supply detected on VBUS */ + NRF_POWER_EVENT_USBREMOVED = offsetof(NRF_POWER_Type, EVENTS_USBREMOVED ), /**< Voltage supply removed from VBUS */ + NRF_POWER_EVENT_USBPWRRDY = offsetof(NRF_POWER_Type, EVENTS_USBPWRRDY ), /**< USB 3.3 V supply ready */ +#endif +}nrf_power_event_t; /*lint -restore */ + +/** + * @brief POWER interrupts + */ +typedef enum +{ + NRF_POWER_INT_POFWARN_MASK = POWER_INTENSET_POFWARN_Msk , /**< Write '1' to Enable interrupt for POFWARN event */ +#if NRF_POWER_HAS_SLEEPEVT + NRF_POWER_INT_SLEEPENTER_MASK = POWER_INTENSET_SLEEPENTER_Msk , /**< Write '1' to Enable interrupt for SLEEPENTER event */ + NRF_POWER_INT_SLEEPEXIT_MASK = POWER_INTENSET_SLEEPEXIT_Msk , /**< Write '1' to Enable interrupt for SLEEPEXIT event */ +#endif +#if NRF_POWER_HAS_USBREG + NRF_POWER_INT_USBDETECTED_MASK = POWER_INTENSET_USBDETECTED_Msk, /**< Write '1' to Enable interrupt for USBDETECTED event */ + NRF_POWER_INT_USBREMOVED_MASK = POWER_INTENSET_USBREMOVED_Msk , /**< Write '1' to Enable interrupt for USBREMOVED event */ + NRF_POWER_INT_USBPWRRDY_MASK = POWER_INTENSET_USBPWRRDY_Msk , /**< Write '1' to Enable interrupt for USBPWRRDY event */ +#endif +}nrf_power_int_mask_t; + +/** + * @brief Function for activating a specific POWER task. + * + * @param task Task. + */ +__STATIC_INLINE void nrf_power_task_trigger(nrf_power_task_t task); + +/** + * @brief Function for returning the address of a specific POWER task register. + * + * @param task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_power_task_address_get(nrf_power_task_t task); + +/** + * @brief Function for clearing a specific event. + * + * @param event Event. + */ +__STATIC_INLINE void nrf_power_event_clear(nrf_power_event_t event); + +/** + * @brief Function for returning the state of a specific event. + * + * @param event Event. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_power_event_check(nrf_power_event_t event); + +/** + * @brief Function for getting and clearing the state of specific event + * + * This function checks the state of the event and clears it. + * + * @param event Event. + * + * @retval true If the event was set. + * @retval false If the event was not set. + */ +__STATIC_INLINE bool nrf_power_event_get_and_clear(nrf_power_event_t event); + +/** + * @brief Function for returning the address of a specific POWER event register. + * + * @param event Event. + * + * @return Address. + */ +__STATIC_INLINE uint32_t nrf_power_event_address_get(nrf_power_event_t event); + +/** + * @brief Function for enabling selected interrupts. + * + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_power_int_enable(uint32_t int_mask); + +/** + * @brief Function for retrieving the state of selected interrupts. + * + * @param int_mask Interrupts mask. + * + * @retval true If any of selected interrupts is enabled. + * @retval false If none of selected interrupts is enabled. + */ +__STATIC_INLINE bool nrf_power_int_enable_check(uint32_t int_mask); + +/** + * @brief Function for retrieving the information about enabled interrupts. + * + * @return The flags of enabled interrupts. + */ +__STATIC_INLINE uint32_t nrf_power_int_enable_get(void); + +/** + * @brief Function for disabling selected interrupts. + * + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_power_int_disable(uint32_t int_mask); + + +/** @} */ /* End of nrf_power_hal */ + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +/* ------------------------------------------------------------------------------------------------ + * Internal functions + */ + +/** + * @internal + * @brief Internal function for getting task/event register address + * + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile uint32_t * nrf_power_regptr_get(uint32_t offset) +{ + return (volatile uint32_t *)(((uint8_t *)NRF_POWER) + (uint32_t)offset); +} + +/** + * @internal + * @brief Internal function for getting task/event register address - constant version + * + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile const uint32_t * nrf_power_regptr_get_c( + uint32_t offset) +{ + return (volatile const uint32_t *)(((uint8_t *)NRF_POWER) + + (uint32_t)offset); +} + +/* ------------------------------------------------------------------------------------------------ + * Interface functions definitions + */ + +void nrf_power_task_trigger(nrf_power_task_t task) +{ + *(nrf_power_regptr_get((uint32_t)task)) = 1UL; +} + +uint32_t nrf_power_task_address_get(nrf_power_task_t task) +{ + return (uint32_t)nrf_power_regptr_get_c((uint32_t)task); +} + +void nrf_power_event_clear(nrf_power_event_t event) +{ + *(nrf_power_regptr_get((uint32_t)event)) = 0UL; +} + +bool nrf_power_event_check(nrf_power_event_t event) +{ + return (bool)*nrf_power_regptr_get_c((uint32_t)event); +} + +bool nrf_power_event_get_and_clear(nrf_power_event_t event) +{ + bool ret = nrf_power_event_check(event); + if (ret) + { + nrf_power_event_clear(event); + } + return ret; +} + +uint32_t nrf_power_event_address_get(nrf_power_event_t event) +{ + return (uint32_t)nrf_power_regptr_get_c((uint32_t)event); +} + +void nrf_power_int_enable(uint32_t int_mask) +{ + NRF_POWER->INTENSET = int_mask; +} + +bool nrf_power_int_enable_check(uint32_t int_mask) +{ + return !!(NRF_POWER->INTENSET & int_mask); +} + +uint32_t nrf_power_int_enable_get(void) +{ + return NRF_POWER->INTENSET; +} + +void nrf_power_int_disable(uint32_t int_mask) +{ + NRF_POWER->INTENCLR = int_mask; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/* ------------------------------------------------------------------------------------------------ + * End of automatically generated part + * ------------------------------------------------------------------------------------------------ + */ +/** + * @ingroup nrf_power_hal + * @{ + */ + +/** + * @brief Reset reason + */ +typedef enum +{ + NRF_POWER_RESETREAS_RESETPIN_MASK = POWER_RESETREAS_RESETPIN_Msk, /*!< Bit mask of RESETPIN field. *///!< NRF_POWER_RESETREAS_RESETPIN_MASK + NRF_POWER_RESETREAS_DOG_MASK = POWER_RESETREAS_DOG_Msk , /*!< Bit mask of DOG field. */ //!< NRF_POWER_RESETREAS_DOG_MASK + NRF_POWER_RESETREAS_SREQ_MASK = POWER_RESETREAS_SREQ_Msk , /*!< Bit mask of SREQ field. */ //!< NRF_POWER_RESETREAS_SREQ_MASK + NRF_POWER_RESETREAS_LOCKUP_MASK = POWER_RESETREAS_LOCKUP_Msk , /*!< Bit mask of LOCKUP field. */ //!< NRF_POWER_RESETREAS_LOCKUP_MASK + NRF_POWER_RESETREAS_OFF_MASK = POWER_RESETREAS_OFF_Msk , /*!< Bit mask of OFF field. */ //!< NRF_POWER_RESETREAS_OFF_MASK +#if defined(POWER_RESETREAS_LPCOMP_Msk) || defined(__SDK_DOXYGEN__) + NRF_POWER_RESETREAS_LPCOMP_MASK = POWER_RESETREAS_LPCOMP_Msk , /*!< Bit mask of LPCOMP field. */ //!< NRF_POWER_RESETREAS_LPCOMP_MASK +#endif + NRF_POWER_RESETREAS_DIF_MASK = POWER_RESETREAS_DIF_Msk , /*!< Bit mask of DIF field. */ //!< NRF_POWER_RESETREAS_DIF_MASK +#if defined(POWER_RESETREAS_NFC_Msk) || defined(__SDK_DOXYGEN__) + NRF_POWER_RESETREAS_NFC_MASK = POWER_RESETREAS_NFC_Msk , /*!< Bit mask of NFC field. */ +#endif +#if defined(POWER_RESETREAS_VBUS_Msk) || defined(__SDK_DOXYGEN__) + NRF_POWER_RESETREAS_VBUS_MASK = POWER_RESETREAS_VBUS_Msk , /*!< Bit mask of VBUS field. */ +#endif +}nrf_power_resetreas_mask_t; + +#if NRF_POWER_HAS_USBREG +/** + * @brief USBREGSTATUS register bit masks + * + * @sa nrf_power_usbregstatus_get + */ +typedef enum +{ + NRF_POWER_USBREGSTATUS_VBUSDETECT_MASK = POWER_USBREGSTATUS_VBUSDETECT_Msk, /**< USB detected or removed */ + NRF_POWER_USBREGSTATUS_OUTPUTRDY_MASK = POWER_USBREGSTATUS_OUTPUTRDY_Msk /**< USB 3.3 V supply ready */ +}nrf_power_usbregstatus_mask_t; +#endif + +#if NRF_POWER_HAS_RAMSTATUS +/** + * @brief RAM blocks numbers + * + * @sa nrf_power_ramblock_mask_t + * @note + * Ram blocks has to been used in nrf51. + * In new CPU ram is divided into segments and this functionality is depreciated. + * For the newer MCU see the PS for mapping between internal RAM and RAM blocks, + * because this mapping is not 1:1, and functions related to old style blocks + * should not be used. + */ +typedef enum +{ + NRF_POWER_RAMBLOCK0 = POWER_RAMSTATUS_RAMBLOCK0_Pos, + NRF_POWER_RAMBLOCK1 = POWER_RAMSTATUS_RAMBLOCK1_Pos, + NRF_POWER_RAMBLOCK2 = POWER_RAMSTATUS_RAMBLOCK2_Pos, + NRF_POWER_RAMBLOCK3 = POWER_RAMSTATUS_RAMBLOCK3_Pos +}nrf_power_ramblock_t; + +/** + * @brief RAM blocks masks + * + * @sa nrf_power_ramblock_t + */ + +typedef enum +{ + NRF_POWER_RAMBLOCK0_MASK = POWER_RAMSTATUS_RAMBLOCK0_Msk, + NRF_POWER_RAMBLOCK1_MASK = POWER_RAMSTATUS_RAMBLOCK1_Msk, + NRF_POWER_RAMBLOCK2_MASK = POWER_RAMSTATUS_RAMBLOCK2_Msk, + NRF_POWER_RAMBLOCK3_MASK = POWER_RAMSTATUS_RAMBLOCK3_Msk +}nrf_power_ramblock_mask_t; +#endif // NRF_POWER_HAS_RAMSTATUS + +/** + * @brief RAM power state position of the bits + * + * @sa nrf_power_onoffram_mask_t + */ +typedef enum +{ + NRF_POWER_ONRAM0, /**< Keep RAM block 0 on or off in system ON Mode */ + NRF_POWER_OFFRAM0, /**< Keep retention on RAM block 0 when RAM block is switched off */ + NRF_POWER_ONRAM1, /**< Keep RAM block 1 on or off in system ON Mode */ + NRF_POWER_OFFRAM1, /**< Keep retention on RAM block 1 when RAM block is switched off */ + NRF_POWER_ONRAM2, /**< Keep RAM block 2 on or off in system ON Mode */ + NRF_POWER_OFFRAM2, /**< Keep retention on RAM block 2 when RAM block is switched off */ + NRF_POWER_ONRAM3, /**< Keep RAM block 3 on or off in system ON Mode */ + NRF_POWER_OFFRAM3, /**< Keep retention on RAM block 3 when RAM block is switched off */ +}nrf_power_onoffram_t; + +/** + * @brief RAM power state bit masks + * + * @sa nrf_power_onoffram_t + */ +typedef enum +{ + NRF_POWER_ONRAM0_MASK = 1U << NRF_POWER_ONRAM0, /**< Keep RAM block 0 on or off in system ON Mode */ + NRF_POWER_OFFRAM0_MASK = 1U << NRF_POWER_OFFRAM0, /**< Keep retention on RAM block 0 when RAM block is switched off */ + NRF_POWER_ONRAM1_MASK = 1U << NRF_POWER_ONRAM1, /**< Keep RAM block 1 on or off in system ON Mode */ + NRF_POWER_OFFRAM1_MASK = 1U << NRF_POWER_OFFRAM1, /**< Keep retention on RAM block 1 when RAM block is switched off */ + NRF_POWER_ONRAM2_MASK = 1U << NRF_POWER_ONRAM2, /**< Keep RAM block 2 on or off in system ON Mode */ + NRF_POWER_OFFRAM2_MASK = 1U << NRF_POWER_OFFRAM2, /**< Keep retention on RAM block 2 when RAM block is switched off */ + NRF_POWER_ONRAM3_MASK = 1U << NRF_POWER_ONRAM3, /**< Keep RAM block 3 on or off in system ON Mode */ + NRF_POWER_OFFRAM3_MASK = 1U << NRF_POWER_OFFRAM3, /**< Keep retention on RAM block 3 when RAM block is switched off */ +}nrf_power_onoffram_mask_t; + +/** + * @brief Power failure comparator thresholds + */ +typedef enum +{ + NRF_POWER_POFTHR_V21 = POWER_POFCON_THRESHOLD_V21, /**< Set threshold to 2.1 V */ + NRF_POWER_POFTHR_V23 = POWER_POFCON_THRESHOLD_V23, /**< Set threshold to 2.3 V */ + NRF_POWER_POFTHR_V25 = POWER_POFCON_THRESHOLD_V25, /**< Set threshold to 2.5 V */ + NRF_POWER_POFTHR_V27 = POWER_POFCON_THRESHOLD_V27, /**< Set threshold to 2.7 V */ +#if defined(POWER_POFCON_THRESHOLD_V17) || defined(__SDK_DOXYGEN__) + NRF_POWER_POFTHR_V17 = POWER_POFCON_THRESHOLD_V17, /**< Set threshold to 1.7 V */ + NRF_POWER_POFTHR_V18 = POWER_POFCON_THRESHOLD_V18, /**< Set threshold to 1.8 V */ + NRF_POWER_POFTHR_V19 = POWER_POFCON_THRESHOLD_V19, /**< Set threshold to 1.9 V */ + NRF_POWER_POFTHR_V20 = POWER_POFCON_THRESHOLD_V20, /**< Set threshold to 2.0 V */ + NRF_POWER_POFTHR_V22 = POWER_POFCON_THRESHOLD_V22, /**< Set threshold to 2.2 V */ + NRF_POWER_POFTHR_V24 = POWER_POFCON_THRESHOLD_V24, /**< Set threshold to 2.4 V */ + NRF_POWER_POFTHR_V26 = POWER_POFCON_THRESHOLD_V26, /**< Set threshold to 2.6 V */ + NRF_POWER_POFTHR_V28 = POWER_POFCON_THRESHOLD_V28, /**< Set threshold to 2.8 V */ +#endif +}nrf_power_pof_thr_t; + +#if NRF_POWER_HAS_VDDH +/** + * @brief Power failure comparator thresholds for VDDH + */ +typedef enum +{ + NRF_POWER_POFTHRVDDH_V27 = POWER_POFCON_THRESHOLDVDDH_V27, /**< Set threshold to 2.7 V */ + NRF_POWER_POFTHRVDDH_V28 = POWER_POFCON_THRESHOLDVDDH_V28, /**< Set threshold to 2.8 V */ + NRF_POWER_POFTHRVDDH_V29 = POWER_POFCON_THRESHOLDVDDH_V29, /**< Set threshold to 2.9 V */ + NRF_POWER_POFTHRVDDH_V30 = POWER_POFCON_THRESHOLDVDDH_V30, /**< Set threshold to 3.0 V */ + NRF_POWER_POFTHRVDDH_V31 = POWER_POFCON_THRESHOLDVDDH_V31, /**< Set threshold to 3.1 V */ + NRF_POWER_POFTHRVDDH_V32 = POWER_POFCON_THRESHOLDVDDH_V32, /**< Set threshold to 3.2 V */ + NRF_POWER_POFTHRVDDH_V33 = POWER_POFCON_THRESHOLDVDDH_V33, /**< Set threshold to 3.3 V */ + NRF_POWER_POFTHRVDDH_V34 = POWER_POFCON_THRESHOLDVDDH_V34, /**< Set threshold to 3.4 V */ + NRF_POWER_POFTHRVDDH_V35 = POWER_POFCON_THRESHOLDVDDH_V35, /**< Set threshold to 3.5 V */ + NRF_POWER_POFTHRVDDH_V36 = POWER_POFCON_THRESHOLDVDDH_V36, /**< Set threshold to 3.6 V */ + NRF_POWER_POFTHRVDDH_V37 = POWER_POFCON_THRESHOLDVDDH_V37, /**< Set threshold to 3.7 V */ + NRF_POWER_POFTHRVDDH_V38 = POWER_POFCON_THRESHOLDVDDH_V38, /**< Set threshold to 3.8 V */ + NRF_POWER_POFTHRVDDH_V39 = POWER_POFCON_THRESHOLDVDDH_V39, /**< Set threshold to 3.9 V */ + NRF_POWER_POFTHRVDDH_V40 = POWER_POFCON_THRESHOLDVDDH_V40, /**< Set threshold to 4.0 V */ + NRF_POWER_POFTHRVDDH_V41 = POWER_POFCON_THRESHOLDVDDH_V41, /**< Set threshold to 4.1 V */ + NRF_POWER_POFTHRVDDH_V42 = POWER_POFCON_THRESHOLDVDDH_V42, /**< Set threshold to 4.2 V */ +}nrf_power_pof_thrvddh_t; + +/** + * @brief Main regulator status + */ +typedef enum +{ + NRF_POWER_MAINREGSTATUS_NORMAL = POWER_MAINREGSTATUS_MAINREGSTATUS_Normal, /**< Normal voltage mode. Voltage supplied on VDD. */ + NRF_POWER_MAINREGSTATUS_HIGH = POWER_MAINREGSTATUS_MAINREGSTATUS_High /**< High voltage mode. Voltage supplied on VDDH. */ +}nrf_power_mainregstatus_t; + +#endif /* NRF_POWER_HAS_VDDH */ + +#if NRF_POWER_HAS_RAMPOWER_REGS +/** + * @brief Bit positions for RAMPOWER register + * + * All possible bits described, even if they are not used in selected MCU. + */ +typedef enum +{ + /** Keep RAM section S0 ON in System ON mode */ + NRF_POWER_RAMPOWER_S0POWER = POWER_RAM_POWER_S0POWER_Pos, + NRF_POWER_RAMPOWER_S1POWER, /**< Keep RAM section S1 ON in System ON mode */ + NRF_POWER_RAMPOWER_S2POWER, /**< Keep RAM section S2 ON in System ON mode */ + NRF_POWER_RAMPOWER_S3POWER, /**< Keep RAM section S3 ON in System ON mode */ + NRF_POWER_RAMPOWER_S4POWER, /**< Keep RAM section S4 ON in System ON mode */ + NRF_POWER_RAMPOWER_S5POWER, /**< Keep RAM section S5 ON in System ON mode */ + NRF_POWER_RAMPOWER_S6POWER, /**< Keep RAM section S6 ON in System ON mode */ + NRF_POWER_RAMPOWER_S7POWER, /**< Keep RAM section S7 ON in System ON mode */ + NRF_POWER_RAMPOWER_S8POWER, /**< Keep RAM section S8 ON in System ON mode */ + NRF_POWER_RAMPOWER_S9POWER, /**< Keep RAM section S9 ON in System ON mode */ + NRF_POWER_RAMPOWER_S10POWER, /**< Keep RAM section S10 ON in System ON mode */ + NRF_POWER_RAMPOWER_S11POWER, /**< Keep RAM section S11 ON in System ON mode */ + NRF_POWER_RAMPOWER_S12POWER, /**< Keep RAM section S12 ON in System ON mode */ + NRF_POWER_RAMPOWER_S13POWER, /**< Keep RAM section S13 ON in System ON mode */ + NRF_POWER_RAMPOWER_S14POWER, /**< Keep RAM section S14 ON in System ON mode */ + NRF_POWER_RAMPOWER_S15POWER, /**< Keep RAM section S15 ON in System ON mode */ + + /** Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S0RETENTION = POWER_RAM_POWER_S0RETENTION_Pos, + NRF_POWER_RAMPOWER_S1RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S2RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S3RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S4RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S5RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S6RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S7RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S8RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S9RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S10RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S11RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S12RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S13RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S14RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S15RETENTION, /**< Keep section retention in OFF mode when section is OFF */ +}nrf_power_rampower_t; + +#if defined ( __CC_ARM ) +#pragma push +#pragma diag_suppress 66 +#endif +/** + * @brief Bit masks for RAMPOWER register + * + * All possible bits described, even if they are not used in selected MCU. + */ +typedef enum +{ + NRF_POWER_RAMPOWER_S0POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S0POWER , + NRF_POWER_RAMPOWER_S1POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S1POWER , + NRF_POWER_RAMPOWER_S2POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S2POWER , + NRF_POWER_RAMPOWER_S3POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S3POWER , + NRF_POWER_RAMPOWER_S4POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S4POWER , + NRF_POWER_RAMPOWER_S5POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S5POWER , + NRF_POWER_RAMPOWER_S7POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S7POWER , + NRF_POWER_RAMPOWER_S8POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S8POWER , + NRF_POWER_RAMPOWER_S9POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S9POWER , + NRF_POWER_RAMPOWER_S10POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S10POWER, + NRF_POWER_RAMPOWER_S11POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S11POWER, + NRF_POWER_RAMPOWER_S12POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S12POWER, + NRF_POWER_RAMPOWER_S13POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S13POWER, + NRF_POWER_RAMPOWER_S14POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S14POWER, + NRF_POWER_RAMPOWER_S15POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S15POWER, + + NRF_POWER_RAMPOWER_S0RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S0RETENTION , + NRF_POWER_RAMPOWER_S1RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S1RETENTION , + NRF_POWER_RAMPOWER_S2RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S2RETENTION , + NRF_POWER_RAMPOWER_S3RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S3RETENTION , + NRF_POWER_RAMPOWER_S4RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S4RETENTION , + NRF_POWER_RAMPOWER_S5RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S5RETENTION , + NRF_POWER_RAMPOWER_S7RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S7RETENTION , + NRF_POWER_RAMPOWER_S8RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S8RETENTION , + NRF_POWER_RAMPOWER_S9RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S9RETENTION , + NRF_POWER_RAMPOWER_S10RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S10RETENTION, + NRF_POWER_RAMPOWER_S11RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S11RETENTION, + NRF_POWER_RAMPOWER_S12RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S12RETENTION, + NRF_POWER_RAMPOWER_S13RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S13RETENTION, + NRF_POWER_RAMPOWER_S14RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S14RETENTION, + NRF_POWER_RAMPOWER_S15RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S15RETENTION, +}nrf_power_rampower_mask_t; +#if defined ( __CC_ARM ) +#pragma pop +#endif +#endif /* NRF_POWER_HAS_RAMPOWER_REGS */ + + +/** + * @brief Get reset reason mask + * + * Function returns the reset reason. + * Unless cleared, the RESETREAS register is cumulative. + * A field is cleared by writing '1' to it (see @ref nrf_power_resetreas_clear). + * If none of the reset sources are flagged, + * this indicates that the chip was reset from the on-chip reset generator, + * which indicates a power-on-reset or a brown out reset. + * + * @return The mask of reset reasons constructed with @ref nrf_power_resetreas_mask_t. + */ +__STATIC_INLINE uint32_t nrf_power_resetreas_get(void); + +/** + * @brief Clear selected reset reason field + * + * Function clears selected reset reason fields. + * + * @param[in] mask The mask constructed from @ref nrf_power_resetreas_mask_t enumerator values. + * @sa nrf_power_resetreas_get + */ +__STATIC_INLINE void nrf_power_resetreas_clear(uint32_t mask); + +#if NRF_POWER_HAS_RAMSTATUS +/** + * @brief Get RAMSTATUS register + * + * Returns the masks of RAM blocks that are powered ON. + * + * @return Value with bits sets according to masks in @ref nrf_power_ramblock_mask_t. + */ +__STATIC_INLINE uint32_t nrf_power_ramstatus_get(void); +#endif // NRF_POWER_HAS_RAMSTATUS + +/** + * @brief Go to system OFF + * + * This function puts the CPU into system off mode. + * The only way to wake up the CPU is by reset. + * + * @note This function never returns. + */ +__STATIC_INLINE void nrf_power_system_off(void); + +/** + * @brief Set power failure comparator configuration + * + * Sets power failure comparator threshold and enable/disable flag. + * + * @param enabled Set to true if power failure comparator should be enabled. + * @param thr Set the voltage threshold value. + * + * @note + * If VDDH settings is present in the device, this function would + * clear it settings (set to the lowest voltage). + * Use @ref nrf_power_pofcon_vddh_set function to set new value. + */ +__STATIC_INLINE void nrf_power_pofcon_set(bool enabled, nrf_power_pof_thr_t thr); + +/** + * @brief Get power failure comparator configuration + * + * Get power failure comparator threshold and enable bit. + * + * @param[out] p_enabled Function would set this boolean variable to true + * if power failure comparator is enabled. + * The pointer can be NULL if we do not need this information. + * @return Threshold setting for power failure comparator + */ +__STATIC_INLINE nrf_power_pof_thr_t nrf_power_pofcon_get(bool * p_enabled); + +#if NRF_POWER_HAS_VDDH +/** + * @brief Set VDDH power failure comparator threshold + * + * @param thr Threshold to be set + */ +__STATIC_INLINE void nrf_power_pofcon_vddh_set(nrf_power_pof_thrvddh_t thr); + +/** + * @brief Get VDDH power failure comparator threshold + * + * @return VDDH threshold currently configured + */ +__STATIC_INLINE nrf_power_pof_thrvddh_t nrf_power_pofcon_vddh_get(void); +#endif + +/** + * @brief Set general purpose retention register + * + * @param val Value to be set in the register + */ +__STATIC_INLINE void nrf_power_gpregret_set(uint8_t val); + +/** + * @brief Get general purpose retention register + * + * @return The value from the register + */ +__STATIC_INLINE uint8_t nrf_power_gpregret_get(void); + +#if defined(POWER_GPREGRET2_GPREGRET_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief Set general purpose retention register 2 + * + * @param val Value to be set in the register + * @note This register is not available in nrf51 MCU family + */ +__STATIC_INLINE void nrf_power_gpregret2_set(uint8_t val); + +/** + * @brief Get general purpose retention register 2 + * + * @return The value from the register + * @note This register is not available in all MCUs. + */ +__STATIC_INLINE uint8_t nrf_power_gpregret2_get(void); +#endif + +/** + * @brief Enable or disable DCDC converter + * + * @param enable Set true to enable or false to disable DCDC converter. + * + * @note + * If the device consist of high voltage power input (VDDH) this setting + * would relate to the converter on low voltage side (1.3 V output). + */ +__STATIC_INLINE void nrf_power_dcdcen_set(bool enable); + +/** + * @brief Get the state of DCDC converter + * + * @retval true Converter is enabled + * @retval false Converter is disabled + * + * @note + * If the device consist of high voltage power input (VDDH) this setting + * would relate to the converter on low voltage side (1.3 V output). + */ +__STATIC_INLINE bool nrf_power_dcdcen_get(void); + +#if NRF_POWER_HAS_RAMPOWER_REGS +/** + * @brief Turn ON sections in selected RAM block. + * + * This function turns ON sections in block and also block retention. + * + * @sa nrf_power_rampower_mask_t + * @sa nrf_power_rampower_mask_off + * + * @param block RAM block index. + * @param section_mask Mask of the sections created by merging + * @ref nrf_power_rampower_mask_t flags. + */ +__STATIC_INLINE void nrf_power_rampower_mask_on(uint8_t block, uint32_t section_mask); + +/** + * @brief Turn ON sections in selected RAM block. + * + * This function turns OFF sections in block and also block retention. + * + * @sa nrf_power_rampower_mask_t + * @sa nrf_power_rampower_mask_off + * + * @param block RAM block index. + * @param section_mask Mask of the sections created by merging + * @ref nrf_power_rampower_mask_t flags. + */ +__STATIC_INLINE void nrf_power_rampower_mask_off(uint8_t block, uint32_t section_mask); + +/** + * @brief Get the mask of ON and retention sections in selected RAM block. + * + * @param block RAM block index. + * @return Mask of sections state composed from @ref nrf_power_rampower_mask_t flags. + */ +__STATIC_INLINE uint32_t nrf_power_rampower_mask_get(uint8_t block); +#endif /* NRF_POWER_HAS_RAMPOWER_REGS */ + +#if NRF_POWER_HAS_VDDH +/** + * @brief Enable of disable DCDC converter on VDDH + * + * @param enable Set true to enable or false to disable DCDC converter. + */ +__STATIC_INLINE void nrf_power_dcdcen_vddh_set(bool enable); + +/** + * @brief Get the state of DCDC converter on VDDH + * + * @retval true Converter is enabled + * @retval false Converter is disabled + */ +__STATIC_INLINE bool nrf_power_dcdcen_vddh_get(void); + +/** + * @brief Get main supply status + * + * @return Current main supply status + */ +__STATIC_INLINE nrf_power_mainregstatus_t nrf_power_mainregstatus_get(void); +#endif /* NRF_POWER_HAS_VDDH */ + +#if NRF_POWER_HAS_USBREG +/** + * + * @return Get the whole USBREGSTATUS register + * + * @return The USBREGSTATUS register value. + * Use @ref nrf_power_usbregstatus_mask_t values for bit masking. + * + * @sa nrf_power_usbregstatus_vbusdet_get + * @sa nrf_power_usbregstatus_outrdy_get + */ +__STATIC_INLINE uint32_t nrf_power_usbregstatus_get(void); + +/** + * @brief VBUS input detection status + * + * USBDETECTED and USBREMOVED events are derived from this information + * + * @retval false VBUS voltage below valid threshold + * @retval true VBUS voltage above valid threshold + * + * @sa nrf_power_usbregstatus_get + */ +__STATIC_INLINE bool nrf_power_usbregstatus_vbusdet_get(void); + +/** + * @brief USB supply output settling time elapsed + * + * @retval false USBREG output settling time not elapsed + * @retval true USBREG output settling time elapsed + * (same information as USBPWRRDY event) + * + * @sa nrf_power_usbregstatus_get + */ +__STATIC_INLINE bool nrf_power_usbregstatus_outrdy_get(void); +#endif /* NRF_POWER_HAS_USBREG */ + +/** @} */ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE uint32_t nrf_power_resetreas_get(void) +{ + return NRF_POWER->RESETREAS; +} + +__STATIC_INLINE void nrf_power_resetreas_clear(uint32_t mask) +{ + NRF_POWER->RESETREAS = mask; +} + +#if NRF_POWER_HAS_RAMSTATUS +__STATIC_INLINE uint32_t nrf_power_ramstatus_get(void) +{ + return NRF_POWER->RAMSTATUS; +} +#endif // NRF_POWER_HAS_RAMSTATUS + +__STATIC_INLINE void nrf_power_system_off(void) +{ + NRF_POWER->SYSTEMOFF = POWER_SYSTEMOFF_SYSTEMOFF_Enter; + __DSB(); + + /* Solution for simulated System OFF in debug mode */ + while (true) + { + __WFE(); + } +} + +__STATIC_INLINE void nrf_power_pofcon_set(bool enabled, nrf_power_pof_thr_t thr) +{ + ASSERT(thr == (thr & (POWER_POFCON_THRESHOLD_Msk >> POWER_POFCON_THRESHOLD_Pos))); +#if NRF_POWER_HAS_VDDH + uint32_t pofcon = NRF_POWER->POFCON; + pofcon &= ~(POWER_POFCON_THRESHOLD_Msk | POWER_POFCON_POF_Msk); + pofcon |= +#else /* NRF_POWER_HAS_VDDH */ + NRF_POWER->POFCON = +#endif + (((uint32_t)thr) << POWER_POFCON_THRESHOLD_Pos) | + (enabled ? + (POWER_POFCON_POF_Enabled << POWER_POFCON_POF_Pos) + : + (POWER_POFCON_POF_Disabled << POWER_POFCON_POF_Pos)); +#if NRF_POWER_HAS_VDDH + NRF_POWER->POFCON = pofcon; +#endif +} + +__STATIC_INLINE nrf_power_pof_thr_t nrf_power_pofcon_get(bool * p_enabled) +{ + uint32_t pofcon = NRF_POWER->POFCON; + if (NULL != p_enabled) + { + (*p_enabled) = ((pofcon & POWER_POFCON_POF_Msk) >> POWER_POFCON_POF_Pos) + == POWER_POFCON_POF_Enabled; + } + return (nrf_power_pof_thr_t)((pofcon & POWER_POFCON_THRESHOLD_Msk) >> + POWER_POFCON_THRESHOLD_Pos); +} + +#if NRF_POWER_HAS_VDDH +__STATIC_INLINE void nrf_power_pofcon_vddh_set(nrf_power_pof_thrvddh_t thr) +{ + ASSERT(thr == (thr & (POWER_POFCON_THRESHOLDVDDH_Msk >> POWER_POFCON_THRESHOLDVDDH_Pos))); + uint32_t pofcon = NRF_POWER->POFCON; + pofcon &= ~POWER_POFCON_THRESHOLDVDDH_Msk; + pofcon |= (((uint32_t)thr) << POWER_POFCON_THRESHOLDVDDH_Pos); + NRF_POWER->POFCON = pofcon; +} + +__STATIC_INLINE nrf_power_pof_thrvddh_t nrf_power_pofcon_vddh_get(void) +{ + return (nrf_power_pof_thrvddh_t)((NRF_POWER->POFCON & + POWER_POFCON_THRESHOLDVDDH_Msk) >> POWER_POFCON_THRESHOLDVDDH_Pos); +} +#endif /* NRF_POWER_HAS_VDDH */ + +__STATIC_INLINE void nrf_power_gpregret_set(uint8_t val) +{ + NRF_POWER->GPREGRET = val; +} + +__STATIC_INLINE uint8_t nrf_power_gpregret_get(void) +{ + return NRF_POWER->GPREGRET; +} + +#if defined(POWER_GPREGRET2_GPREGRET_Msk) || defined(__SDK_DOXYGEN__) +void nrf_power_gpregret2_set(uint8_t val) +{ + NRF_POWER->GPREGRET2 = val; +} + +__STATIC_INLINE uint8_t nrf_power_gpregret2_get(void) +{ + return NRF_POWER->GPREGRET2; +} +#endif + +__STATIC_INLINE void nrf_power_dcdcen_set(bool enable) +{ +#if NRF_POWER_HAS_VDDH + NRF_POWER->DCDCEN = (enable ? + POWER_DCDCEN_DCDCEN_Enabled : POWER_DCDCEN_DCDCEN_Disabled) << + POWER_DCDCEN_DCDCEN_Pos; +#else + NRF_POWER->DCDCEN = (enable ? + POWER_DCDCEN_DCDCEN_Enabled : POWER_DCDCEN_DCDCEN_Disabled) << + POWER_DCDCEN_DCDCEN_Pos; +#endif +} + +__STATIC_INLINE bool nrf_power_dcdcen_get(void) +{ +#if NRF_POWER_HAS_VDDH + return (NRF_POWER->DCDCEN & POWER_DCDCEN_DCDCEN_Msk) + == + (POWER_DCDCEN_DCDCEN_Enabled << POWER_DCDCEN_DCDCEN_Pos); +#else + return (NRF_POWER->DCDCEN & POWER_DCDCEN_DCDCEN_Msk) + == + (POWER_DCDCEN_DCDCEN_Enabled << POWER_DCDCEN_DCDCEN_Pos); +#endif +} + +#if NRF_POWER_HAS_RAMPOWER_REGS +__STATIC_INLINE void nrf_power_rampower_mask_on(uint8_t block, uint32_t section_mask) +{ + ASSERT(block < ARRAY_SIZE(NRF_POWER->RAM)); + NRF_POWER->RAM[block].POWERSET = section_mask; +} + +__STATIC_INLINE void nrf_power_rampower_mask_off(uint8_t block, uint32_t section_mask) +{ + ASSERT(block < ARRAY_SIZE(NRF_POWER->RAM)); + NRF_POWER->RAM[block].POWERCLR = section_mask; +} + +__STATIC_INLINE uint32_t nrf_power_rampower_mask_get(uint8_t block) +{ + ASSERT(block < ARRAY_SIZE(NRF_POWER->RAM)); + return NRF_POWER->RAM[block].POWER; +} +#endif /* NRF_POWER_HAS_RAMPOWER_REGS */ + +#if NRF_POWER_HAS_VDDH +__STATIC_INLINE void nrf_power_dcdcen_vddh_set(bool enable) +{ + NRF_POWER->DCDCEN0 = (enable ? + POWER_DCDCEN0_DCDCEN_Enabled : POWER_DCDCEN0_DCDCEN_Disabled) << + POWER_DCDCEN0_DCDCEN_Pos; +} + +bool nrf_power_dcdcen_vddh_get(void) +{ + return (NRF_POWER->DCDCEN0 & POWER_DCDCEN0_DCDCEN_Msk) + == + (POWER_DCDCEN0_DCDCEN_Enabled << POWER_DCDCEN0_DCDCEN_Pos); +} + +nrf_power_mainregstatus_t nrf_power_mainregstatus_get(void) +{ + return (nrf_power_mainregstatus_t)(((NRF_POWER->MAINREGSTATUS) & + POWER_MAINREGSTATUS_MAINREGSTATUS_Msk) >> + POWER_MAINREGSTATUS_MAINREGSTATUS_Pos); +} +#endif /* NRF_POWER_HAS_VDDH */ + +#if NRF_POWER_HAS_USBREG +__STATIC_INLINE uint32_t nrf_power_usbregstatus_get(void) +{ + return NRF_POWER->USBREGSTATUS; +} + +__STATIC_INLINE bool nrf_power_usbregstatus_vbusdet_get(void) +{ + return (nrf_power_usbregstatus_get() & + NRF_POWER_USBREGSTATUS_VBUSDETECT_MASK) != 0; +} + +__STATIC_INLINE bool nrf_power_usbregstatus_outrdy_get(void) +{ + return (nrf_power_usbregstatus_get() & + NRF_POWER_USBREGSTATUS_OUTPUTRDY_MASK) != 0; +} +#endif /* NRF_POWER_HAS_USBREG */ + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_POWER_H__ */ diff --git a/third_party/NordicSemiconductor/hal/nrf_systick.h b/third_party/NordicSemiconductor/hal/nrf_systick.h new file mode 100644 index 000000000..26fbf37e3 --- /dev/null +++ b/third_party/NordicSemiconductor/hal/nrf_systick.h @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2016 - 2017, 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_SYSTICK_H__ +#define NRF_SYSTICK_H__ + +#include "nrf.h" +#include +#include +#include + +/** + * @defgroup nrf_systick_hal SYSTICK HAL + * @{ + * @ingroup nrf_systick + * + * @brief Hardware access layer for accessing the SYSTICK peripheral. + * + * SYSTICK is ARM peripheral, not Nordic design. + * It means that it has no Nordic-typical interface with Tasks and Events. + * + * Its usage is limited here to implement simple delays. + * Also keep in mind that this timer would be stopped when CPU is sleeping + * (WFE/WFI instruction is successfully executed). + */ + +/** + * @brief Mask of usable bits in the SysTick value + */ +#define NRF_SYSTICK_VAL_MASK SysTick_VAL_CURRENT_Msk + +/** + * @brief Flags used by SysTick configuration. + * + * @sa nrf_systick_csr_set + * @sa nrf_systick_csr_get + */ +typedef enum { + NRF_SYSTICK_CSR_COUNTFLAG_MASK = SysTick_CTRL_COUNTFLAG_Msk, /**< Status flag: Returns 1 if timer counted to 0 since the last read of this register. */ + + NRF_SYSTICK_CSR_CLKSOURCE_MASK = SysTick_CTRL_CLKSOURCE_Msk, /**< Configuration bit: Select the SysTick clock source. */ + NRF_SYSTICK_CSR_CLKSOURCE_REF = 0U << SysTick_CTRL_CLKSOURCE_Pos, /**< Configuration value: Select reference clock. */ + NRF_SYSTICK_CSR_CLKSOURCE_CPU = 1U << SysTick_CTRL_CLKSOURCE_Pos, /**< Configuration value: Select CPU clock. */ + + NRF_SYSTICK_CSR_TICKINT_MASK = SysTick_CTRL_TICKINT_Msk, /**< Configuration bit: Enables SysTick exception request. */ + NRF_SYSTICK_CSR_TICKINT_ENABLE = 1U << SysTick_CTRL_TICKINT_Pos, /**< Configuration value: Counting down to zero does not assert the SysTick exception request. */ + NRF_SYSTICK_CSR_TICKINT_DISABLE = 0U << SysTick_CTRL_TICKINT_Pos, /**< Configuration value: Counting down to zero to asserts the SysTick exception request. */ + + NRF_SYSTICK_CSR_ENABLE_MASK = SysTick_CTRL_ENABLE_Msk, /**< Configuration bit: Enable the SysTick timer. */ + NRF_SYSTICK_CSR_ENABLE = 1U << SysTick_CTRL_ENABLE_Pos, /**< Configuration value: Counter enabled. */ + NRF_SYSTICK_CSR_DISABLE = 0U << SysTick_CTRL_ENABLE_Pos /**< Configuration value: Counter disabled. */ +} nrf_systick_csr_flags_t; + +/** + * @brief Get Configuration and Status Register + * + * @return Values composed by @ref nrf_systick_csr_flags_t. + * @note The @ref NRF_SYSTICK_CSR_COUNTFLAG_MASK value is cleared when CSR register is read. + */ +__STATIC_INLINE uint32_t nrf_systick_csr_get(void); + +/** + * @brief Set Configuration and Status Register + * + * @param[in] val The value composed from @ref nrf_systick_csr_flags_t. + */ +__STATIC_INLINE void nrf_systick_csr_set(uint32_t val); + +/** + * @brief Get the current reload value. + * + * @return The reload register value. + */ +__STATIC_INLINE uint32_t nrf_systick_load_get(void); + +/** + * @brief Configure the reload value. + * + * @param[in] val The value to set in the reload register. + */ +__STATIC_INLINE void nrf_systick_load_set(uint32_t val); + +/** + * @brief Read the SysTick current value + * + * @return The current SysTick value + * @sa NRF_SYSTICK_VAL_MASK + */ +__STATIC_INLINE uint32_t nrf_systick_val_get(void); + +/** + * @brief Clear the SysTick current value + * + * @note The SysTick does not allow setting current value. + * Any write to VAL register would clear the timer. + */ +__STATIC_INLINE void nrf_systick_val_clear(void); + +/** + * @brief Read the calibration register + * + * @return The calibration register value + */ +__STATIC_INLINE uint32_t nrf_systick_calib_get(void); + + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE uint32_t nrf_systick_csr_get(void) +{ + return SysTick->CTRL; +} + +__STATIC_INLINE void nrf_systick_csr_set(uint32_t val) +{ + SysTick->CTRL = val; +} + +__STATIC_INLINE uint32_t nrf_systick_load_get(void) +{ + return SysTick->LOAD; +} + +__STATIC_INLINE void nrf_systick_load_set(uint32_t val) +{ + SysTick->LOAD = val; +} + +__STATIC_INLINE uint32_t nrf_systick_val_get(void) +{ + return SysTick->VAL; +} + +__STATIC_INLINE void nrf_systick_val_clear(void) +{ + SysTick->VAL = 0; +} + +__STATIC_INLINE uint32_t nrf_systick_calib_get(void) +{ + return SysTick->CALIB; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/** @} */ +#endif /* NRF_SYSTICK_H__ */ diff --git a/third_party/NordicSemiconductor/hal/nrf_usbd.h b/third_party/NordicSemiconductor/hal/nrf_usbd.h new file mode 100644 index 000000000..c796e4ed2 --- /dev/null +++ b/third_party/NordicSemiconductor/hal/nrf_usbd.h @@ -0,0 +1,1422 @@ +/** + * Copyright (c) 2017 - 2017, 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_USBD_H__ +#define NRF_USBD_H__ + +/** + * @ingroup nrf_drivers + * @defgroup nrf_usbd_hal USBD HAL + * @{ + * + * @brief @tagAPI52840 Hardware access layer for Universal Serial Bus Device (USBD) peripheral. + */ + +#include "nrf_peripherals.h" +#include "nrf.h" +#include "nrf_assert.h" +#include +#include +#include + +/** + * @brief USBD tasks + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_USBD_TASK_STARTEPIN0 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[0] ), /**< Captures the EPIN[0].PTR, EPIN[0].MAXCNT and EPIN[0].CONFIG registers values, and enables control endpoint IN 0 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN1 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[1] ), /**< Captures the EPIN[1].PTR, EPIN[1].MAXCNT and EPIN[1].CONFIG registers values, and enables data endpoint IN 1 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN2 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[2] ), /**< Captures the EPIN[2].PTR, EPIN[2].MAXCNT and EPIN[2].CONFIG registers values, and enables data endpoint IN 2 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN3 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[3] ), /**< Captures the EPIN[3].PTR, EPIN[3].MAXCNT and EPIN[3].CONFIG registers values, and enables data endpoint IN 3 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN4 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[4] ), /**< Captures the EPIN[4].PTR, EPIN[4].MAXCNT and EPIN[4].CONFIG registers values, and enables data endpoint IN 4 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN5 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[5] ), /**< Captures the EPIN[5].PTR, EPIN[5].MAXCNT and EPIN[5].CONFIG registers values, and enables data endpoint IN 5 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN6 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[6] ), /**< Captures the EPIN[6].PTR, EPIN[6].MAXCNT and EPIN[6].CONFIG registers values, and enables data endpoint IN 6 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN7 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[7] ), /**< Captures the EPIN[7].PTR, EPIN[7].MAXCNT and EPIN[7].CONFIG registers values, and enables data endpoint IN 7 to respond to traffic from host */ + NRF_USBD_TASK_STARTISOIN = offsetof(NRF_USBD_Type, TASKS_STARTISOIN ), /**< Captures the ISOIN.PTR, ISOIN.MAXCNT and ISOIN.CONFIG registers values, and enables sending data on iso endpoint 8 */ + NRF_USBD_TASK_STARTEPOUT0 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[0]), /**< Captures the EPOUT[0].PTR, EPOUT[0].MAXCNT and EPOUT[0].CONFIG registers values, and enables control endpoint 0 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT1 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[1]), /**< Captures the EPOUT[1].PTR, EPOUT[1].MAXCNT and EPOUT[1].CONFIG registers values, and enables data endpoint 1 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT2 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[2]), /**< Captures the EPOUT[2].PTR, EPOUT[2].MAXCNT and EPOUT[2].CONFIG registers values, and enables data endpoint 2 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT3 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[3]), /**< Captures the EPOUT[3].PTR, EPOUT[3].MAXCNT and EPOUT[3].CONFIG registers values, and enables data endpoint 3 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT4 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[4]), /**< Captures the EPOUT[4].PTR, EPOUT[4].MAXCNT and EPOUT[4].CONFIG registers values, and enables data endpoint 4 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT5 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[5]), /**< Captures the EPOUT[5].PTR, EPOUT[5].MAXCNT and EPOUT[5].CONFIG registers values, and enables data endpoint 5 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT6 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[6]), /**< Captures the EPOUT[6].PTR, EPOUT[6].MAXCNT and EPOUT[6].CONFIG registers values, and enables data endpoint 6 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT7 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[7]), /**< Captures the EPOUT[7].PTR, EPOUT[7].MAXCNT and EPOUT[7].CONFIG registers values, and enables data endpoint 7 to respond to traffic from host */ + NRF_USBD_TASK_STARTISOOUT = offsetof(NRF_USBD_Type, TASKS_STARTISOOUT ), /**< Captures the ISOOUT.PTR, ISOOUT.MAXCNT and ISOOUT.CONFIG registers values, and enables receiving of data on iso endpoint 8 */ + NRF_USBD_TASK_EP0RCVOUT = offsetof(NRF_USBD_Type, TASKS_EP0RCVOUT ), /**< Allows OUT data stage on control endpoint 0 */ + NRF_USBD_TASK_EP0STATUS = offsetof(NRF_USBD_Type, TASKS_EP0STATUS ), /**< Allows status stage on control endpoint 0 */ + NRF_USBD_TASK_EP0STALL = offsetof(NRF_USBD_Type, TASKS_EP0STALL ), /**< STALLs data and status stage on control endpoint 0 */ + NRF_USBD_TASK_DRIVEDPDM = offsetof(NRF_USBD_Type, TASKS_DPDMDRIVE ), /**< Forces D+ and D-lines to the state defined in the DPDMVALUE register */ + NRF_USBD_TASK_NODRIVEDPDM = offsetof(NRF_USBD_Type, TASKS_DPDMNODRIVE ), /**< Stops forcing D+ and D- lines to any state (USB engine takes control) */ + /*lint -restore*/ +}nrf_usbd_task_t; + +/** + * @brief USBD events + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_USBD_EVENT_USBRESET = offsetof(NRF_USBD_Type, EVENTS_USBRESET ), /**< Signals that a USB reset condition has been detected on the USB lines */ + NRF_USBD_EVENT_STARTED = offsetof(NRF_USBD_Type, EVENTS_STARTED ), /**< Confirms that the EPIN[n].PTR, EPIN[n].MAXCNT, EPIN[n].CONFIG, or EPOUT[n].PTR, EPOUT[n].MAXCNT and EPOUT[n].CONFIG registers have been captured on all endpoints reported in the EPSTATUS register */ + NRF_USBD_EVENT_ENDEPIN0 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[0] ), /**< The whole EPIN[0] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN1 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[1] ), /**< The whole EPIN[1] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN2 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[2] ), /**< The whole EPIN[2] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN3 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[3] ), /**< The whole EPIN[3] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN4 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[4] ), /**< The whole EPIN[4] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN5 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[5] ), /**< The whole EPIN[5] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN6 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[6] ), /**< The whole EPIN[6] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN7 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[7] ), /**< The whole EPIN[7] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_EP0DATADONE = offsetof(NRF_USBD_Type, EVENTS_EP0DATADONE), /**< An acknowledged data transfer has taken place on the control endpoint */ + NRF_USBD_EVENT_ENDISOIN0 = offsetof(NRF_USBD_Type, EVENTS_ENDISOIN ), /**< The whole ISOIN buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT0 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[0]), /**< The whole EPOUT[0] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT1 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[1]), /**< The whole EPOUT[1] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT2 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[2]), /**< The whole EPOUT[2] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT3 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[3]), /**< The whole EPOUT[3] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT4 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[4]), /**< The whole EPOUT[4] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT5 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[5]), /**< The whole EPOUT[5] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT6 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[6]), /**< The whole EPOUT[6] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT7 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[7]), /**< The whole EPOUT[7] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDISOOUT0 = offsetof(NRF_USBD_Type, EVENTS_ENDISOOUT ), /**< The whole ISOOUT buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_SOF = offsetof(NRF_USBD_Type, EVENTS_SOF ), /**< Signals that a SOF (start of frame) condition has been detected on the USB lines */ + NRF_USBD_EVENT_USBEVENT = offsetof(NRF_USBD_Type, EVENTS_USBEVENT ), /**< An event or an error not covered by specific events has occurred, check EVENTCAUSE register to find the cause */ + NRF_USBD_EVENT_EP0SETUP = offsetof(NRF_USBD_Type, EVENTS_EP0SETUP ), /**< A valid SETUP token has been received (and acknowledged) on the control endpoint */ + NRF_USBD_EVENT_DATAEP = offsetof(NRF_USBD_Type, EVENTS_EPDATA ), /**< A data transfer has occurred on a data endpoint, indicated by the EPDATASTATUS register */ + NRF_USBD_EVENT_ACCESSFAULT = offsetof(NRF_USBD_Type, EVENTS_ACCESSFAULT), /**< >Access to an unavailable USB register has been attempted (software or EasyDMA) */ + /*lint -restore*/ +}nrf_usbd_event_t; + +/** + * @brief USBD shorts + */ +typedef enum +{ + NRF_USBD_SHORT_EP0DATADONE_STARTEPIN0_MASK = USBD_SHORTS_EP0DATADONE_STARTEPIN0_Msk , /**< Shortcut between EP0DATADONE event and STARTEPIN0 task */ + NRF_USBD_SHORT_EP0DATADONE_STARTEPOUT0_MASK = USBD_SHORTS_EP0DATADONE_STARTEPOUT0_Msk, /**< Shortcut between EP0DATADONE event and STARTEPOUT0 task */ + NRF_USBD_SHORT_EP0DATADONE_EP0STATUS_MASK = USBD_SHORTS_EP0DATADONE_EP0STATUS_Msk , /**< Shortcut between EP0DATADONE event and EP0STATUS task */ + NRF_USBD_SHORT_ENDEPOUT0_EP0STATUS_MASK = USBD_SHORTS_ENDEPOUT0_EP0STATUS_Msk , /**< Shortcut between ENDEPOUT[0] event and EP0STATUS task */ + NRF_USBD_SHORT_ENDEPOUT0_EP0RCVOUT_MASK = USBD_SHORTS_ENDEPOUT0_EP0RCVOUT_Msk , /**< Shortcut between ENDEPOUT[0] event and EP0RCVOUT task */ +}nrf_usbd_short_mask_t; + +/** + * @brief USBD interrupts + */ +typedef enum +{ + NRF_USBD_INT_USBRESET_MASK = USBD_INTEN_USBRESET_Msk , /**< Enable or disable interrupt for USBRESET event */ + NRF_USBD_INT_STARTED_MASK = USBD_INTEN_STARTED_Msk , /**< Enable or disable interrupt for STARTED event */ + NRF_USBD_INT_ENDEPIN0_MASK = USBD_INTEN_ENDEPIN0_Msk , /**< Enable or disable interrupt for ENDEPIN[0] event */ + NRF_USBD_INT_ENDEPIN1_MASK = USBD_INTEN_ENDEPIN1_Msk , /**< Enable or disable interrupt for ENDEPIN[1] event */ + NRF_USBD_INT_ENDEPIN2_MASK = USBD_INTEN_ENDEPIN2_Msk , /**< Enable or disable interrupt for ENDEPIN[2] event */ + NRF_USBD_INT_ENDEPIN3_MASK = USBD_INTEN_ENDEPIN3_Msk , /**< Enable or disable interrupt for ENDEPIN[3] event */ + NRF_USBD_INT_ENDEPIN4_MASK = USBD_INTEN_ENDEPIN4_Msk , /**< Enable or disable interrupt for ENDEPIN[4] event */ + NRF_USBD_INT_ENDEPIN5_MASK = USBD_INTEN_ENDEPIN5_Msk , /**< Enable or disable interrupt for ENDEPIN[5] event */ + NRF_USBD_INT_ENDEPIN6_MASK = USBD_INTEN_ENDEPIN6_Msk , /**< Enable or disable interrupt for ENDEPIN[6] event */ + NRF_USBD_INT_ENDEPIN7_MASK = USBD_INTEN_ENDEPIN7_Msk , /**< Enable or disable interrupt for ENDEPIN[7] event */ + NRF_USBD_INT_EP0DATADONE_MASK = USBD_INTEN_EP0DATADONE_Msk, /**< Enable or disable interrupt for EP0DATADONE event */ + NRF_USBD_INT_ENDISOIN0_MASK = USBD_INTEN_ENDISOIN_Msk , /**< Enable or disable interrupt for ENDISOIN[0] event */ + NRF_USBD_INT_ENDEPOUT0_MASK = USBD_INTEN_ENDEPOUT0_Msk , /**< Enable or disable interrupt for ENDEPOUT[0] event */ + NRF_USBD_INT_ENDEPOUT1_MASK = USBD_INTEN_ENDEPOUT1_Msk , /**< Enable or disable interrupt for ENDEPOUT[1] event */ + NRF_USBD_INT_ENDEPOUT2_MASK = USBD_INTEN_ENDEPOUT2_Msk , /**< Enable or disable interrupt for ENDEPOUT[2] event */ + NRF_USBD_INT_ENDEPOUT3_MASK = USBD_INTEN_ENDEPOUT3_Msk , /**< Enable or disable interrupt for ENDEPOUT[3] event */ + NRF_USBD_INT_ENDEPOUT4_MASK = USBD_INTEN_ENDEPOUT4_Msk , /**< Enable or disable interrupt for ENDEPOUT[4] event */ + NRF_USBD_INT_ENDEPOUT5_MASK = USBD_INTEN_ENDEPOUT5_Msk , /**< Enable or disable interrupt for ENDEPOUT[5] event */ + NRF_USBD_INT_ENDEPOUT6_MASK = USBD_INTEN_ENDEPOUT6_Msk , /**< Enable or disable interrupt for ENDEPOUT[6] event */ + NRF_USBD_INT_ENDEPOUT7_MASK = USBD_INTEN_ENDEPOUT7_Msk , /**< Enable or disable interrupt for ENDEPOUT[7] event */ + NRF_USBD_INT_ENDISOOUT0_MASK = USBD_INTEN_ENDISOOUT_Msk , /**< Enable or disable interrupt for ENDISOOUT[0] event */ + NRF_USBD_INT_SOF_MASK = USBD_INTEN_SOF_Msk , /**< Enable or disable interrupt for SOF event */ + NRF_USBD_INT_USBEVENT_MASK = USBD_INTEN_USBEVENT_Msk , /**< Enable or disable interrupt for USBEVENT event */ + NRF_USBD_INT_EP0SETUP_MASK = USBD_INTEN_EP0SETUP_Msk , /**< Enable or disable interrupt for EP0SETUP event */ + NRF_USBD_INT_DATAEP_MASK = USBD_INTEN_EPDATA_Msk , /**< Enable or disable interrupt for EPDATA event */ + NRF_USBD_INT_ACCESSFAULT_MASK = USBD_INTEN_ACCESSFAULT_Msk, /**< Enable or disable interrupt for ACCESSFAULT event */ +}nrf_usbd_int_mask_t; + + +/** + * @brief Function for activating a specific USBD task. + * + * @param task Task. + */ +__STATIC_INLINE void nrf_usbd_task_trigger(nrf_usbd_task_t task); + +/** + * @brief Function for returning the address of a specific USBD task register. + * + * @param task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_usbd_task_address_get(nrf_usbd_task_t task); + +/** + * @brief Function for clearing a specific event. + * + * @param event Event. + */ +__STATIC_INLINE void nrf_usbd_event_clear(nrf_usbd_event_t event); + +/** + * @brief Function for returning the state of a specific event. + * + * @param event Event. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_usbd_event_check(nrf_usbd_event_t event); + +/** + * @brief Function for getting and clearing the state of specific event + * + * This function checks the state of the event and clears it. + * + * @param event Event. + * + * @retval true If the event was set. + * @retval false If the event was not set. + */ +__STATIC_INLINE bool nrf_usbd_event_get_and_clear(nrf_usbd_event_t event); + +/** + * @brief Function for returning the address of a specific USBD event register. + * + * @param event Event. + * + * @return Address. + */ +__STATIC_INLINE uint32_t nrf_usbd_event_address_get(nrf_usbd_event_t event); + +/** + * @brief Function for setting a shortcut. + * + * @param short_mask Shortcuts mask. + */ +__STATIC_INLINE void nrf_usbd_shorts_enable(uint32_t short_mask); + +/** + * @brief Function for clearing shortcuts. + * + * @param short_mask Shortcuts mask. + */ +__STATIC_INLINE void nrf_usbd_shorts_disable(uint32_t short_mask); + +/** + * @brief Get the shorts mask + * + * Function returns shorts register. + * + * @return Flags of currently enabled shortcuts + */ +__STATIC_INLINE uint32_t nrf_usbd_shorts_get(void); + +/** + * @brief Function for enabling selected interrupts. + * + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_usbd_int_enable(uint32_t int_mask); + +/** + * @brief Function for retrieving the state of selected interrupts. + * + * @param int_mask Interrupts mask. + * + * @retval true If any of selected interrupts is enabled. + * @retval false If none of selected interrupts is enabled. + */ +__STATIC_INLINE bool nrf_usbd_int_enable_check(uint32_t int_mask); + +/** + * @brief Function for retrieving the information about enabled interrupts. + * + * @return The flags of enabled interrupts. + */ +__STATIC_INLINE uint32_t nrf_usbd_int_enable_get(void); + +/** + * @brief Function for disabling selected interrupts. + * + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_usbd_int_disable(uint32_t int_mask); + + +/** @} */ /* End of nrf_usbd_hal */ + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +/* ------------------------------------------------------------------------------------------------ + * Internal functions + */ + +/** + * @internal + * @brief Internal function for getting task/event register address + * + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile uint32_t* nrf_usbd_getRegPtr(uint32_t offset) +{ + return (volatile uint32_t*)(((uint8_t *)NRF_USBD) + (uint32_t)offset); +} + +/** + * @internal + * @brief Internal function for getting task/event register address - constant version + * + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile const uint32_t* nrf_usbd_getRegPtr_c(uint32_t offset) +{ + return (volatile const uint32_t*)(((uint8_t *)NRF_USBD) + (uint32_t)offset); +} + +/* ------------------------------------------------------------------------------------------------ + * Interface functions definitions + */ + +void nrf_usbd_task_trigger(nrf_usbd_task_t task) +{ + *(nrf_usbd_getRegPtr((uint32_t)task)) = 1UL; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_task_address_get(nrf_usbd_task_t task) +{ + return (uint32_t)nrf_usbd_getRegPtr_c((uint32_t)task); +} + +void nrf_usbd_event_clear(nrf_usbd_event_t event) +{ + *(nrf_usbd_getRegPtr((uint32_t)event)) = 0UL; + __ISB(); + __DSB(); +} + +bool nrf_usbd_event_check(nrf_usbd_event_t event) +{ + return (bool)*nrf_usbd_getRegPtr_c((uint32_t)event); +} + +bool nrf_usbd_event_get_and_clear(nrf_usbd_event_t event) +{ + bool ret = nrf_usbd_event_check(event); + if (ret) + { + nrf_usbd_event_clear(event); + } + return ret; +} + +uint32_t nrf_usbd_event_address_get(nrf_usbd_event_t event) +{ + return (uint32_t)nrf_usbd_getRegPtr_c((uint32_t)event); +} + +void nrf_usbd_shorts_enable(uint32_t short_mask) +{ + NRF_USBD->SHORTS |= short_mask; +} + +void nrf_usbd_shorts_disable(uint32_t short_mask) +{ + if (~0U == short_mask) + { + /* Optimized version for "disable all" */ + NRF_USBD->SHORTS = 0; + } + else + { + NRF_USBD->SHORTS &= ~short_mask; + } +} + +uint32_t nrf_usbd_shorts_get(void) +{ + return NRF_USBD->SHORTS; +} + +void nrf_usbd_int_enable(uint32_t int_mask) +{ + NRF_USBD->INTENSET = int_mask; +} + +bool nrf_usbd_int_enable_check(uint32_t int_mask) +{ + return !!(NRF_USBD->INTENSET & int_mask); +} + +uint32_t nrf_usbd_int_enable_get(void) +{ + return NRF_USBD->INTENSET; +} + +void nrf_usbd_int_disable(uint32_t int_mask) +{ + NRF_USBD->INTENCLR = int_mask; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/* ------------------------------------------------------------------------------------------------ + * End of automatically generated part + * ------------------------------------------------------------------------------------------------ + */ +/** + * @addtogroup nrf_usbd_hal + * @{ + */ + +/** + * @brief Frame counter size + * + * The number of counts that can be fitted into frame counter + */ +#define NRF_USBD_FRAMECNTR_SIZE \ + ( (USBD_FRAMECNTR_FRAMECNTR_Msk >> USBD_FRAMECNTR_FRAMECNTR_Pos) + 1UL ) +#ifndef USBD_FRAMECNTR_FRAMECNTR_Msk +#error USBD_FRAMECNTR_FRAMECNTR_Msk should be changed into USBD_FRAMECNTR_FRAMECNTR_Msk +#endif + +/** + * @brief First isochronous endpoint number + * + * The number of the first isochronous endpoint + */ +#define NRF_USBD_EPISO_FIRST 8 + +/** + * @brief Total number of IN endpoints + * + * Total number of IN endpoint (including ISOCHRONOUS). + */ +#define NRF_USBD_EPIN_CNT 9 + +/** + * @brief Total number of OUT endpoints + * + * Total number of OUT endpoint (including ISOCHRONOUS). + */ +#define NRF_USBD_EPOUT_CNT 9 + +/** + * @brief Mask of the direction bit in endpoint number + */ +#define NRF_USBD_EP_DIR_Msk (1U << 7) + +/** + * @brief The value of direction bit for IN endpoint direction + */ +#define NRF_USBD_EP_DIR_IN (1U << 7) + +/** + * @brief The value of direction bit for OUT endpoint direction + */ +#define NRF_USBD_EP_DIR_OUT (0U << 7) + +/** + * @brief Macro for making IN endpoint identifier from endpoint number + * + * Macro that sets direction bit to make IN endpoint + * @param[in] epnr Endpoint number + * @return IN Endpoint identifier + */ +#define NRF_USBD_EPIN(epnr) (((uint8_t)(epnr)) | NRF_USBD_EP_DIR_IN) + +/** + * @brief Macro for making OUT endpoint identifier from endpoint number + * + * Macro that sets direction bit to make OUT endpoint + * @param[in] epnr Endpoint number + * @return OUT Endpoint identifier + */ +#define NRF_USBD_EPOUT(epnr) (((uint8_t)(epnr)) | NRF_USBD_EP_DIR_OUT) + +/** + * @brief Macro for extracting the endpoint number from endpoint identifier + * + * Macro that strips out the information about endpoint direction. + * @param[in] ep Endpoint identifier + * @return Endpoint number + */ +#define NRF_USBD_EP_NR_GET(ep) ((uint8_t)(((uint8_t)(ep)) & 0xFU)) + +/** + * @brief Macro for checking endpoint direction + * + * This macro checks if given endpoint has IN direction + * @param ep Endpoint identifier + * @retval true If the endpoint direction is IN + * @retval false If the endpoint direction is OUT + */ +#define NRF_USBD_EPIN_CHECK(ep) ( (((uint8_t)(ep)) & NRF_USBD_EP_DIR_Msk) == NRF_USBD_EP_DIR_IN ) + +/** + * @brief Macro for checking endpoint direction + * + * This macro checks if given endpoint has OUT direction + * @param ep Endpoint identifier + * @retval true If the endpoint direction is OUT + * @retval false If the endpoint direction is IN + */ +#define NRF_USBD_EPOUT_CHECK(ep) ( (((uint8_t)(ep)) & NRF_USBD_EP_DIR_Msk) == NRF_USBD_EP_DIR_OUT ) + +/** + * @brief Macro for checking if endpoint is isochronous + * + * @param ep It can be endpoint identifier or just endpoint number to check + * @retval true The endpoint is isochronous type + * @retval false The endpoint is bulk of interrupt type + */ +#define NRF_USBD_EPISO_CHECK(ep) (NRF_USBD_EP_NR_GET(ep) >= NRF_USBD_EPISO_FIRST) + +/** + * @brief Macro for checking if given number is valid endpoint number + * + * @param ep Endpoint number to check + * @retval true The endpoint is valid + * @retval false The endpoint is not valid + */ +#define NRF_USBD_EP_VALIDATE(ep) ( \ + (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 Not isochronous data frame received + * + * Special value returned by @ref nrf_usbd_episoout_size_get function that means that + * data frame was not received at all. + * This allows differentiate between situations when zero size data comes or no data comes at all + * on isochronous endpoint. + */ +#define NRF_USBD_EPISOOUT_NO_DATA ((size_t)(-1)) + +/** + * @brief EVENTCAUSE register bit masks + */ +typedef enum +{ + NRF_USBD_EVENTCAUSE_ISOOUTCRC_MASK = USBD_EVENTCAUSE_ISOOUTCRC_Msk, /**< CRC error was detected on isochronous OUT endpoint 8. */ + NRF_USBD_EVENTCAUSE_SUSPEND_MASK = USBD_EVENTCAUSE_SUSPEND_Msk , /**< Signals that the USB lines have been seen idle long enough for the device to enter suspend. */ + NRF_USBD_EVENTCAUSE_RESUME_MASK = USBD_EVENTCAUSE_RESUME_Msk , /**< Signals that a RESUME condition (K state or activity restart) has been detected on the USB lines. */ + NRF_USBD_EVENTCAUSE_READY_MASK = USBD_EVENTCAUSE_READY_Msk, /**< MAC is ready for normal operation, rised few us after USBD enabling */ + NRF_USBD_EVENTCAUSE_WUREQ_MASK = (1U << 10) /**< The USBD peripheral has exited Low Power mode */ +}nrf_usbd_eventcause_mask_t; + +/** + * @brief BUSSTATE register bit masks + */ +typedef enum +{ + NRF_USBD_BUSSTATE_DM_MASK = USBD_BUSSTATE_DM_Msk, /**< Negative line mask */ + NRF_USBD_BUSSTATE_DP_MASK = USBD_BUSSTATE_DP_Msk, /**< Positive line mask */ + /** Both lines are low */ + NRF_USBD_BUSSTATE_DPDM_LL = (USBD_BUSSTATE_DM_Low << USBD_BUSSTATE_DM_Pos) | (USBD_BUSSTATE_DP_Low << USBD_BUSSTATE_DP_Pos), + /** Positive line is high, negative line is low */ + NRF_USBD_BUSSTATE_DPDM_HL = (USBD_BUSSTATE_DM_Low << USBD_BUSSTATE_DM_Pos) | (USBD_BUSSTATE_DP_High << USBD_BUSSTATE_DP_Pos), + /** Positive line is low, negative line is high */ + NRF_USBD_BUSSTATE_DPDM_LH = (USBD_BUSSTATE_DM_High << USBD_BUSSTATE_DM_Pos) | (USBD_BUSSTATE_DP_Low << USBD_BUSSTATE_DP_Pos), + /** Both lines are high */ + NRF_USBD_BUSSTATE_DPDM_HH = (USBD_BUSSTATE_DM_High << USBD_BUSSTATE_DM_Pos) | (USBD_BUSSTATE_DP_High << USBD_BUSSTATE_DP_Pos), + /** J state */ + NRF_USBD_BUSSTATE_J = NRF_USBD_BUSSTATE_DPDM_HL, + /** K state */ + NRF_USBD_BUSSTATE_K = NRF_USBD_BUSSTATE_DPDM_LH, + /** Single ended 0 */ + NRF_USBD_BUSSTATE_SE0 = NRF_USBD_BUSSTATE_DPDM_LL, + /** Single ended 1 */ + NRF_USBD_BUSSTATE_SE1 = NRF_USBD_BUSSTATE_DPDM_HH +}nrf_usbd_busstate_t; + +/** + * @brief DPDMVALUE register + */ +typedef enum +{ + /**Generate Resume signal. Signal is generated for 50 us or 5 ms, + * depending on bus state */ + NRF_USBD_DPDMVALUE_RESUME = USBD_DPDMVALUE_STATE_Resume, + /** D+ Forced high, D- forced low (J state) */ + NRF_USBD_DPDMVALUE_J = USBD_DPDMVALUE_STATE_J, + /** D+ Forced low, D- forced high (K state) */ + NRF_USBD_DPMVALUE_K = USBD_DPDMVALUE_STATE_K +}nrf_usbd_dpdmvalue_t; + +/** + * @brief Dtoggle value or operation + */ +typedef enum +{ + NRF_USBD_DTOGGLE_NOP = USBD_DTOGGLE_VALUE_Nop, /**< No operation - do not change current data toggle on selected endpoint */ + NRF_USBD_DTOGGLE_DATA0 = USBD_DTOGGLE_VALUE_Data0,/**< Data toggle is DATA0 on selected endpoint */ + NRF_USBD_DTOGGLE_DATA1 = USBD_DTOGGLE_VALUE_Data1 /**< Data toggle is DATA1 on selected endpoint */ +}nrf_usbd_dtoggle_t; + +/** + * @brief EPSTATUS bit masks + */ +typedef enum +{ + NRF_USBD_EPSTATUS_EPIN0_MASK = USBD_EPSTATUS_EPIN0_Msk, + NRF_USBD_EPSTATUS_EPIN1_MASK = USBD_EPSTATUS_EPIN1_Msk, + NRF_USBD_EPSTATUS_EPIN2_MASK = USBD_EPSTATUS_EPIN2_Msk, + NRF_USBD_EPSTATUS_EPIN3_MASK = USBD_EPSTATUS_EPIN3_Msk, + NRF_USBD_EPSTATUS_EPIN4_MASK = USBD_EPSTATUS_EPIN4_Msk, + NRF_USBD_EPSTATUS_EPIN5_MASK = USBD_EPSTATUS_EPIN5_Msk, + NRF_USBD_EPSTATUS_EPIN6_MASK = USBD_EPSTATUS_EPIN6_Msk, + NRF_USBD_EPSTATUS_EPIN7_MASK = USBD_EPSTATUS_EPIN7_Msk, + + NRF_USBD_EPSTATUS_EPOUT0_MASK = USBD_EPSTATUS_EPOUT0_Msk, + NRF_USBD_EPSTATUS_EPOUT1_MASK = USBD_EPSTATUS_EPOUT1_Msk, + NRF_USBD_EPSTATUS_EPOUT2_MASK = USBD_EPSTATUS_EPOUT2_Msk, + NRF_USBD_EPSTATUS_EPOUT3_MASK = USBD_EPSTATUS_EPOUT3_Msk, + NRF_USBD_EPSTATUS_EPOUT4_MASK = USBD_EPSTATUS_EPOUT4_Msk, + NRF_USBD_EPSTATUS_EPOUT5_MASK = USBD_EPSTATUS_EPOUT5_Msk, + NRF_USBD_EPSTATUS_EPOUT6_MASK = USBD_EPSTATUS_EPOUT6_Msk, + NRF_USBD_EPSTATUS_EPOUT7_MASK = USBD_EPSTATUS_EPOUT7_Msk, +}nrf_usbd_epstatus_mask_t; + +/** + * @brief DATAEPSTATUS bit masks + */ +typedef enum +{ + NRF_USBD_EPDATASTATUS_EPIN1_MASK = USBD_EPDATASTATUS_EPIN1_Msk, + NRF_USBD_EPDATASTATUS_EPIN2_MASK = USBD_EPDATASTATUS_EPIN2_Msk, + NRF_USBD_EPDATASTATUS_EPIN3_MASK = USBD_EPDATASTATUS_EPIN3_Msk, + NRF_USBD_EPDATASTATUS_EPIN4_MASK = USBD_EPDATASTATUS_EPIN4_Msk, + NRF_USBD_EPDATASTATUS_EPIN5_MASK = USBD_EPDATASTATUS_EPIN5_Msk, + NRF_USBD_EPDATASTATUS_EPIN6_MASK = USBD_EPDATASTATUS_EPIN6_Msk, + NRF_USBD_EPDATASTATUS_EPIN7_MASK = USBD_EPDATASTATUS_EPIN7_Msk, + + NRF_USBD_EPDATASTATUS_EPOUT1_MASK = USBD_EPDATASTATUS_EPOUT1_Msk, + NRF_USBD_EPDATASTATUS_EPOUT2_MASK = USBD_EPDATASTATUS_EPOUT2_Msk, + NRF_USBD_EPDATASTATUS_EPOUT3_MASK = USBD_EPDATASTATUS_EPOUT3_Msk, + NRF_USBD_EPDATASTATUS_EPOUT4_MASK = USBD_EPDATASTATUS_EPOUT4_Msk, + NRF_USBD_EPDATASTATUS_EPOUT5_MASK = USBD_EPDATASTATUS_EPOUT5_Msk, + NRF_USBD_EPDATASTATUS_EPOUT6_MASK = USBD_EPDATASTATUS_EPOUT6_Msk, + NRF_USBD_EPDATASTATUS_EPOUT7_MASK = USBD_EPDATASTATUS_EPOUT7_Msk, +}nrf_usbd_dataepstatus_mask_t; + +/** + * @brief ISOSPLIT configurations + */ +typedef enum +{ + NRF_USBD_ISOSPLIT_OneDir = USBD_ISOSPLIT_SPLIT_OneDir, /**< Full buffer dedicated to either iso IN or OUT */ + NRF_USBD_ISOSPLIT_Half = USBD_ISOSPLIT_SPLIT_HalfIN, /**< Buffer divided in half */ +}nrf_usbd_isosplit_t; + +/** + * @brief Function for enabling USBD + */ +__STATIC_INLINE void nrf_usbd_enable(void); + +/** + * @brief Function for disabling USBD + */ +__STATIC_INLINE void nrf_usbd_disable(void); + +/** + * @brief Function for getting EVENTCAUSE register + * + * @return Flag values defined in @ref nrf_usbd_eventcause_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_eventcause_get(void); + +/** + * @brief Function for clearing EVENTCAUSE flags + * + * @param flags Flags defined in @ref nrf_usbd_eventcause_mask_t + */ +__STATIC_INLINE void nrf_usbd_eventcause_clear(uint32_t flags); + +/** + * @brief Function for getting EVENTCAUSE register and clear flags that are set + * + * The safest way to return current EVENTCAUSE register. + * All the flags that are returned would be cleared inside EVENTCAUSE register. + * + * @return Flag values defined in @ref nrf_usbd_eventcause_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_eventcause_get_and_clear(void); + +/** + * @brief Function for getting BUSSTATE register value + * + * @return The value of BUSSTATE register + */ +__STATIC_INLINE nrf_usbd_busstate_t nrf_usbd_busstate_get(void); + +/** + * @brief Function for getting HALTEDEPIN register value + * + * @param ep Endpoint number with IN/OUT flag + * + * @return The value of HALTEDEPIN or HALTEDOUT register for selected endpoint + * + * @note + * Use this function for the response for GetStatus() request to endpoint. + * To check if endpoint is stalled in the code use @ref nrf_usbd_ep_is_stall. + */ +__STATIC_INLINE uint32_t nrf_usbd_haltedep(uint8_t ep); + +/** + * @brief Function for checking if selected endpoint is stalled + * + * Function to be used as a syntax sweeter for @ref nrf_usbd_haltedep. + * + * Also as the isochronous endpoint cannot be halted - it returns always false + * if isochronous endpoint is checked. + * + * @param ep Endpoint number with IN/OUT flag + * + * @return The information if the enepoint is halted. + */ +__STATIC_INLINE bool nrf_usbd_ep_is_stall(uint8_t ep); + +/** + * @brief Function for getting EPSTATUS register value + * + * @return Flag values defined in @ref nrf_usbd_epstatus_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_epstatus_get(void); + +/** + * @brief Function for clearing EPSTATUS register value + * + * @param flags Flags defined in @ref nrf_usbd_epstatus_mask_t + */ +__STATIC_INLINE void nrf_usbd_epstatus_clear(uint32_t flags); + +/** + * @brief Function for getting and clearing EPSTATUS register value + * + * Function clears all flags in register set before returning its value. + * @return Flag values defined in @ref nrf_usbd_epstatus_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_epstatus_get_and_clear(void); + +/** + * @brief Function for getting DATAEPSTATUS register value + * + * @return Flag values defined in @ref nrf_usbd_dataepstatus_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_epdatastatus_get(void); + +/** + * @brief Function for clearing DATAEPSTATUS register value + * + * @param flags Flags defined in @ref nrf_usbd_dataepstatus_mask_t + */ +__STATIC_INLINE void nrf_usbd_epdatastatus_clear(uint32_t flags); + +/** + * @brief Function for getting and clearing DATAEPSTATUS register value + * + * Function clears all flags in register set before returning its value. + * @return Flag values defined in @ref nrf_usbd_dataepstatus_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_epdatastatus_get_and_clear(void); + +/** + * @name Setup command frame functions + * + * Functions for setup command frame parts access + * @{ + */ + /** + * @brief Function for reading BMREQUESTTYPE - part of SETUP packet + * + * @return the value of BREQUESTTYPE on last received SETUP frame + */ + __STATIC_INLINE uint8_t nrf_usbd_setup_bmrequesttype_get(void); + + /** + * @brief Function for reading BMREQUEST - part of SETUP packet + * + * @return the value of BREQUEST on last received SETUP frame + */ + __STATIC_INLINE uint8_t nrf_usbd_setup_brequest_get(void); + + /** + * @brief Function for reading WVALUE - part of SETUP packet + * + * @return the value of WVALUE on last received SETUP frame + */ + __STATIC_INLINE uint16_t nrf_usbd_setup_wvalue_get(void); + + /** + * @brief Function for reading WINDEX - part of SETUP packet + * + * @return the value of WINDEX on last received SETUP frame + */ + __STATIC_INLINE uint16_t nrf_usbd_setup_windex_get(void); + + /** + * @brief Function for reading WLENGTH - part of SETUP packet + * + * @return the value of WLENGTH on last received SETUP frame + */ + __STATIC_INLINE uint16_t nrf_usbd_setup_wlength_get(void); +/** @} */ + +/** + * @brief Function for getting number of received bytes on selected endpoint + * + * @param ep Endpoint identifier. + * + * @return Number of received bytes. + * + * @note This function may be used on Bulk/Interrupt and Isochronous endpoints. + * @note For the function that returns different value for ISOOUT zero transfer or no transfer at all, + * see @ref nrf_usbd_episoout_size_get function. This function would return 0 for both cases. + */ +__STATIC_INLINE size_t nrf_usbd_epout_size_get(uint8_t ep); + +/** + * @brief Function for getting number of received bytes on isochronous endpoint. + * + * @param ep Endpoint identifier, has to be isochronous out endpoint. + * + * @return Number of bytes received or @ref NRF_USBD_EPISOOUT_NO_DATA + */ +__STATIC_INLINE size_t nrf_usbd_episoout_size_get(uint8_t ep); + +/** + * @brief Function for clearing out endpoint to accept any new incoming traffic + * + * @param ep ep Endpoint identifier. Only OUT Interrupt/Bulk endpoints are accepted. + */ +__STATIC_INLINE void nrf_usbd_epout_clear(uint8_t ep); + +/** + * @brief Function for enabling USB pullup + */ +__STATIC_INLINE void nrf_usbd_pullup_enable(void); + +/** + * @brief Function for disabling USB pullup + */ +__STATIC_INLINE void nrf_usbd_pullup_disable(void); + +/** + * @brief Function for returning current USB pullup state + * + * @retval true USB pullup is enabled + * @retval false USB pullup is disabled + */ +__STATIC_INLINE bool nrf_usbd_pullup_check(void); + +/** + * @brief Function for configuring the value to be forced on the bus on DRIVEDPDM task + * + * Selected state would be forced on the bus when @ref NRF_USBD_TASK_DRIVEDPDM is set. + * The state would be removed from the bus on @ref NRF_USBD_TASK_NODRIVEDPDM and + * the control would be returned to the USBD peripheral. + * @param val State to be set + */ +__STATIC_INLINE void nrf_usbd_dpdmvalue_set(nrf_usbd_dpdmvalue_t val); + +/** + * @brief Function for setting data toggle + * + * Configuration of current state of data toggling + * @param ep Endpoint number with the information about its direction + * @param op Operation to execute + */ +__STATIC_INLINE void nrf_usbd_dtoggle_set(uint8_t ep, nrf_usbd_dtoggle_t op); + +/** + * @brief Function for getting data toggle + * + * Get the current state of data toggling + * @param ep Endpoint number to return the information about current data toggling + * @retval NRF_USBD_DTOGGLE_DATA0 Data toggle is DATA0 on selected endpoint + * @retval NRF_USBD_DTOGGLE_DATA1 Data toggle is DATA1 on selected endpoint + */ +__STATIC_INLINE nrf_usbd_dtoggle_t nrf_usbd_dtoggle_get(uint8_t ep); + +/** + * @brief Function for checking if endpoint is enabled + * + * @param ep Endpoint id to check + * + * @retval true Endpoint is enabled + * @retval false Endpoint is disabled + */ +__STATIC_INLINE bool nrf_usbd_ep_enable_check(uint8_t ep); + +/** + * @brief Function for enabling selected endpoint + * + * Enabled endpoint responds for the tokens on the USB bus + * + * @param ep Endpoint id to enable + */ +__STATIC_INLINE void nrf_usbd_ep_enable(uint8_t ep); + +/** + * @brief Function for disabling selected endpoint + * + * Disabled endpoint does not respond for the tokens on the USB bus + * + * @param ep Endpoint id to disable + */ +__STATIC_INLINE void nrf_usbd_ep_disable(uint8_t ep); + +/** + * @brief Function for disabling all endpoints + * + * Auxiliary function to simply disable all aviable endpoints. + * It lefts only EP0 IN and OUT enabled. + */ +__STATIC_INLINE void nrf_usbd_ep_all_disable(void); + +/** + * @brief Function for stalling selected endpoint + * + * @param ep Endpoint identifier + * @note This function cannot be called on isochronous endpoint + */ +__STATIC_INLINE void nrf_usbd_ep_stall(uint8_t ep); + +/** + * @brief Function for unstalling selected endpoint + * + * @param ep Endpoint identifier + * @note This function cannot be called on isochronous endpoint + */ +__STATIC_INLINE void nrf_usbd_ep_unstall(uint8_t ep); + +/** + * @brief Function for configuration of isochronous buffer splitting + * + * Configure isochronous buffer splitting between IN and OUT endpoints. + * + * @param split Required configuration + */ +__STATIC_INLINE void nrf_usbd_isosplit_set(nrf_usbd_isosplit_t split); + +/** + * @brief Function for getting the isochronous buffer splitting configuration + * + * Get the current isochronous buffer splitting configuration. + * + * @return Current configuration + */ +__STATIC_INLINE nrf_usbd_isosplit_t nrf_usbd_isosplit_get(void); + +/** + * @brief Function for getting current frame counter + * + * @return Current frame counter + */ +__STATIC_INLINE uint32_t nrf_usbd_framecntr_get(void); + +/** + * @brief Function for entering into low power mode + * + * After this function is called the clock source from the USBD is disconnected internally. + * After this function is called most of the USBD registers cannot be accessed anymore. + * + * @sa nrf_usbd_lowpower_disable + * @sa nrf_usbd_lowpower_check + */ +__STATIC_INLINE void nrf_usbd_lowpower_enable(void); + +/** + * @brief Function for exiting from low power mode + * + * After this function is called the clock source for the USBD is connected internally. + * The @ref NRF_USBD_EVENTCAUSE_WUREQ_MASK event would be generated and + * then the USBD registers may be accessed. + * + * @sa nrf_usbd_lowpower_enable + * @sa nrf_usbd_lowpower_check + */ +__STATIC_INLINE void nrf_usbd_lowpower_disable(void); + +/** + * @brief Function for checking the state of the low power mode + * + * @retval true USBD is in low power mode + * @retval false USBD is not in low power mode + */ +__STATIC_INLINE bool nrf_usbd_lowpower_check(void); + +/** + * @brief Function for configuring EasyDMA channel + * + * Configures EasyDMA for the transfer. + * + * @param ep Endpoint identifier (with direction) + * @param ptr Pointer to the data + * @param maxcnt Number of bytes to transfer + */ +__STATIC_INLINE void nrf_usbd_ep_easydma_set(uint8_t ep, uint32_t ptr, uint32_t maxcnt); + +/** + * @brief Function for getting number of transferred bytes + * + * Get number of transferred bytes in the last transaction + * + * @param ep Endpoint identifier + * + * @return The content of the AMOUNT register + */ +__STATIC_INLINE uint32_t nrf_usbd_ep_amount_get(uint8_t ep); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +void nrf_usbd_enable(void) +{ +#ifdef NRF_FPGA_IMPLEMENTATION + *(volatile uint32_t *)0x400005F4 = 3; + __ISB(); + __DSB(); + *(volatile uint32_t *)0x400005F0 = 3; + __ISB(); + __DSB(); +#endif + + NRF_USBD->ENABLE = USBD_ENABLE_ENABLE_Enabled << USBD_ENABLE_ENABLE_Pos; + __ISB(); + __DSB(); +} + +void nrf_usbd_disable(void) +{ + NRF_USBD->ENABLE = USBD_ENABLE_ENABLE_Disabled << USBD_ENABLE_ENABLE_Pos; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_eventcause_get(void) +{ + return NRF_USBD->EVENTCAUSE; +} + +void nrf_usbd_eventcause_clear(uint32_t flags) +{ + NRF_USBD->EVENTCAUSE = flags; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_eventcause_get_and_clear(void) +{ + uint32_t ret; + ret = nrf_usbd_eventcause_get(); + nrf_usbd_eventcause_clear(ret); + __ISB(); + __DSB(); + return ret; +} + +nrf_usbd_busstate_t nrf_usbd_busstate_get(void) +{ + return (nrf_usbd_busstate_t)(NRF_USBD->BUSSTATE); +} + +uint32_t nrf_usbd_haltedep(uint8_t ep) +{ + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + if (NRF_USBD_EPIN_CHECK(ep)) + { + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->HALTED.EPIN)); + return NRF_USBD->HALTED.EPIN[epnr]; + } + else + { + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->HALTED.EPOUT)); + return NRF_USBD->HALTED.EPOUT[epnr]; + } +} + +bool nrf_usbd_ep_is_stall(uint8_t ep) +{ + if (NRF_USBD_EPISO_CHECK(ep)) + return false; + return USBD_HALTED_EPOUT_GETSTATUS_Halted == nrf_usbd_haltedep(ep); +} + +uint32_t nrf_usbd_epstatus_get(void) +{ + return NRF_USBD->EPSTATUS; +} + +void nrf_usbd_epstatus_clear(uint32_t flags) +{ + NRF_USBD->EPSTATUS = flags; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_epstatus_get_and_clear(void) +{ + uint32_t ret; + ret = nrf_usbd_epstatus_get(); + nrf_usbd_epstatus_clear(ret); + return ret; +} + +uint32_t nrf_usbd_epdatastatus_get(void) +{ + return NRF_USBD->EPDATASTATUS; +} + +void nrf_usbd_epdatastatus_clear(uint32_t flags) +{ + NRF_USBD->EPDATASTATUS = flags; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_epdatastatus_get_and_clear(void) +{ + uint32_t ret; + ret = nrf_usbd_epdatastatus_get(); + nrf_usbd_epdatastatus_clear(ret); + __ISB(); + __DSB(); + return ret; +} + +uint8_t nrf_usbd_setup_bmrequesttype_get(void) +{ + return (uint8_t)(NRF_USBD->BMREQUESTTYPE); +} + +uint8_t nrf_usbd_setup_brequest_get(void) +{ + return (uint8_t)(NRF_USBD->BREQUEST); +} + +uint16_t nrf_usbd_setup_wvalue_get(void) +{ + const uint16_t val = NRF_USBD->WVALUEL; + return (uint16_t)(val | ((NRF_USBD->WVALUEH) << 8)); +} + +uint16_t nrf_usbd_setup_windex_get(void) +{ + const uint16_t val = NRF_USBD->WINDEXL; + return (uint16_t)(val | ((NRF_USBD->WINDEXH) << 8)); +} + +uint16_t nrf_usbd_setup_wlength_get(void) +{ + const uint16_t val = NRF_USBD->WLENGTHL; + return (uint16_t)(val | ((NRF_USBD->WLENGTHH) << 8)); +} + +size_t nrf_usbd_epout_size_get(uint8_t ep) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + ASSERT(NRF_USBD_EPOUT_CHECK(ep)); + if (NRF_USBD_EPISO_CHECK(ep)) + { + size_t size_isoout = NRF_USBD->SIZE.ISOOUT; + if ((size_isoout & USBD_SIZE_ISOOUT_ZERO_Msk) == (USBD_SIZE_ISOOUT_ZERO_ZeroData << USBD_SIZE_ISOOUT_ZERO_Pos)) + { + size_isoout = 0; + } + return size_isoout; + } + + ASSERT(NRF_USBD_EP_NR_GET(ep) < ARRAY_SIZE(NRF_USBD->SIZE.EPOUT)); + return NRF_USBD->SIZE.EPOUT[NRF_USBD_EP_NR_GET(ep)]; +} + +size_t nrf_usbd_episoout_size_get(uint8_t ep) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + ASSERT(NRF_USBD_EPOUT_CHECK(ep)); + ASSERT(NRF_USBD_EPISO_CHECK(ep)); + + size_t size_isoout = NRF_USBD->SIZE.ISOOUT; + if (size_isoout == 0) + { + size_isoout = NRF_USBD_EPISOOUT_NO_DATA; + } + else if ((size_isoout & USBD_SIZE_ISOOUT_ZERO_Msk) == (USBD_SIZE_ISOOUT_ZERO_ZeroData << USBD_SIZE_ISOOUT_ZERO_Pos)) + { + size_isoout = 0; + } + return size_isoout; +} + +void nrf_usbd_epout_clear(uint8_t ep) +{ + ASSERT(NRF_USBD_EPOUT_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < ARRAY_SIZE(NRF_USBD->SIZE.EPOUT))); + NRF_USBD->SIZE.EPOUT[NRF_USBD_EP_NR_GET(ep)] = 0; + __ISB(); + __DSB(); +} + +void nrf_usbd_pullup_enable(void) +{ + NRF_USBD->USBPULLUP = USBD_USBPULLUP_CONNECT_Enabled << USBD_USBPULLUP_CONNECT_Pos; + __ISB(); + __DSB(); +} + +void nrf_usbd_pullup_disable(void) +{ + NRF_USBD->USBPULLUP = USBD_USBPULLUP_CONNECT_Disabled << USBD_USBPULLUP_CONNECT_Pos; + __ISB(); + __DSB(); +} + +bool nrf_usbd_pullup_check(void) +{ + return NRF_USBD->USBPULLUP == (USBD_USBPULLUP_CONNECT_Enabled << USBD_USBPULLUP_CONNECT_Pos); +} + +void nrf_usbd_dpdmvalue_set(nrf_usbd_dpdmvalue_t val) +{ + NRF_USBD->DPDMVALUE = ((uint32_t)val) << USBD_DPDMVALUE_STATE_Pos; +} + +void nrf_usbd_dtoggle_set(uint8_t ep, nrf_usbd_dtoggle_t op) +{ + NRF_USBD->DTOGGLE = ep | (op << USBD_DTOGGLE_VALUE_Pos); + __ISB(); + __DSB(); +} + +nrf_usbd_dtoggle_t nrf_usbd_dtoggle_get(uint8_t ep) +{ + uint32_t retval; + /* Select the endpoint to read */ + nrf_usbd_dtoggle_set(ep, NRF_USBD_DTOGGLE_NOP); + retval = ((NRF_USBD->DTOGGLE) & USBD_DTOGGLE_VALUE_Msk) >> USBD_DTOGGLE_VALUE_Pos; + return (nrf_usbd_dtoggle_t)retval; +} + +bool nrf_usbd_ep_enable_check(uint8_t ep) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + + if (NRF_USBD_EPIN_CHECK(ep)) + { + return 0 != (NRF_USBD->EPINEN & (1UL<EPOUTEN & (1UL<EPINEN |= 1UL<EPOUTEN |= 1UL<EPINEN &= ~(1UL<EPOUTEN &= ~(1UL<EPINEN = USBD_EPINEN_IN0_Enable << USBD_EPINEN_IN0_Pos; + NRF_USBD->EPOUTEN = USBD_EPOUTEN_OUT0_Enable << USBD_EPOUTEN_OUT0_Pos; + __ISB(); + __DSB(); +} + +void nrf_usbd_ep_stall(uint8_t ep) +{ + ASSERT(!NRF_USBD_EPISO_CHECK(ep)); + NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep; + __ISB(); + __DSB(); +} + +void nrf_usbd_ep_unstall(uint8_t ep) +{ + ASSERT(!NRF_USBD_EPISO_CHECK(ep)); + NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep; + __ISB(); + __DSB(); +} + +void nrf_usbd_isosplit_set(nrf_usbd_isosplit_t split) +{ + NRF_USBD->ISOSPLIT = split << USBD_ISOSPLIT_SPLIT_Pos; +} + +nrf_usbd_isosplit_t nrf_usbd_isosplit_get(void) +{ + return (nrf_usbd_isosplit_t) + (((NRF_USBD->ISOSPLIT) & USBD_ISOSPLIT_SPLIT_Msk) >> USBD_ISOSPLIT_SPLIT_Pos); +} + +uint32_t nrf_usbd_framecntr_get(void) +{ + return NRF_USBD->FRAMECNTR; +} + +void nrf_usbd_lowpower_enable(void) +{ + NRF_USBD->LOWPOWER = USBD_LOWPOWER_LOWPOWER_LowPower << USBD_LOWPOWER_LOWPOWER_Pos; +} + +void nrf_usbd_lowpower_disable(void) +{ + NRF_USBD->LOWPOWER = USBD_LOWPOWER_LOWPOWER_ForceNormal << USBD_LOWPOWER_LOWPOWER_Pos; +} + +bool nrf_usbd_lowpower_check(void) +{ + return (NRF_USBD->LOWPOWER != (USBD_LOWPOWER_LOWPOWER_ForceNormal << USBD_LOWPOWER_LOWPOWER_Pos)); +} + + +void nrf_usbd_ep_easydma_set(uint8_t ep, uint32_t ptr, uint32_t maxcnt) +{ + if (NRF_USBD_EPIN_CHECK(ep)) + { + if (NRF_USBD_EPISO_CHECK(ep)) + { + NRF_USBD->ISOIN.PTR = ptr; + NRF_USBD->ISOIN.MAXCNT = maxcnt; + } + else + { + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->EPIN)); + NRF_USBD->EPIN[epnr].PTR = ptr; + NRF_USBD->EPIN[epnr].MAXCNT = maxcnt; + } + } + else + { + if (NRF_USBD_EPISO_CHECK(ep)) + { + NRF_USBD->ISOOUT.PTR = ptr; + NRF_USBD->ISOOUT.MAXCNT = maxcnt; + } + else + { + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->EPOUT)); + NRF_USBD->EPOUT[epnr].PTR = ptr; + NRF_USBD->EPOUT[epnr].MAXCNT = maxcnt; + } + } +} + +uint32_t nrf_usbd_ep_amount_get(uint8_t ep) +{ + uint32_t ret; + + if (NRF_USBD_EPIN_CHECK(ep)) + { + if (NRF_USBD_EPISO_CHECK(ep)) + { + ret = NRF_USBD->ISOIN.AMOUNT; + } + else + { + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->EPOUT)); + ret = NRF_USBD->EPIN[epnr].AMOUNT; + } + } + else + { + if (NRF_USBD_EPISO_CHECK(ep)) + { + ret = NRF_USBD->ISOOUT.AMOUNT; + } + else + { + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->EPOUT)); + ret = NRF_USBD->EPOUT[epnr].AMOUNT; + } + } + + return ret; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/** @} */ +#endif /* NRF_USBD_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c new file mode 100644 index 000000000..ab7b0fdaa --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.c @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2011 - 2017, 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 +#include "app_util.h" +#include "nrf_atfifo.h" +#include "nrf_atfifo_internal.h" + + +/* Unions testing */ +STATIC_ASSERT(sizeof(nrf_atfifo_postag_t) == sizeof(uint32_t)); + + +ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size) +{ + if (NULL == p_buf) + { + return NRF_ERROR_NULL; + } + if (0 != (buf_size % item_size)) + { + return NRF_ERROR_INVALID_LENGTH; + } + + p_fifo->p_buf = p_buf; + p_fifo->tail.tag = 0; + p_fifo->head.tag = 0; + p_fifo->buf_size = buf_size; + p_fifo->item_size = item_size; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo) +{ + bool released = nrf_atfifo_space_clear(p_fifo); + return released ? NRF_SUCCESS : NRF_ERROR_BUSY; +} + + +ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * p_var, size_t size, bool * const p_visible) +{ + nrf_atfifo_item_put_t context; + bool visible; + void * p_data = nrf_atfifo_item_alloc(p_fifo, &context); + if (NULL == p_data) + { + return NRF_ERROR_NO_MEM; + } + + memcpy(p_data, p_var, size); + + visible = nrf_atfifo_item_put(p_fifo, &context); + if (NULL != p_visible) + { + *p_visible = visible; + } + return NRF_SUCCESS; +} + + +void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) +{ + if (nrf_atfifo_wspace_req(p_fifo, &(p_context->last_tail))) + { + return ((uint8_t*)(p_fifo->p_buf)) + p_context->last_tail.pos.wr; + } + return NULL; +} + + +bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) +{ + if ((p_context->last_tail.pos.wr) == (p_context->last_tail.pos.rd)) + { + nrf_atfifo_wspace_close(p_fifo); + return true; + } + return false; +} + + +ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released) +{ + nrf_atfifo_item_get_t context; + bool released; + void const * p_s = nrf_atfifo_item_get(p_fifo, &context); + if (NULL == p_s) + { + return NRF_ERROR_NOT_FOUND; + } + + memcpy(p_var, p_s, size); + + released = nrf_atfifo_item_free(p_fifo, &context); + if (NULL != p_released) + { + *p_released = released; + } + return NRF_SUCCESS; +} + + +void const * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) +{ + if (nrf_atfifo_rspace_req(p_fifo, &(p_context->last_head))) + { + return ((uint8_t*)(p_fifo->p_buf)) + p_context->last_head.pos.rd; + } + return NULL; +} + + +bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) +{ + if ((p_context->last_head.pos.wr) == (p_context->last_head.pos.rd)) + { + nrf_atfifo_rspace_close(p_fifo); + return true; + } + return false; +} diff --git a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.h b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.h new file mode 100644 index 000000000..f87e08a20 --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo.h @@ -0,0 +1,408 @@ +/** + * Copyright (c) 2011 - 2017, 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_ATFIFO_H__ +#define NRF_ATFIFO_H__ + +#include +#include "nordic_common.h" +#include "nrf_assert.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_atfifo Atomic FIFO + * @ingroup app_common + * + * @brief @tagAPI52 FIFO implementation that allows for making atomic transactions without + * locking interrupts. + * + * @details There are two types of functions to prepare the FIFO writing: + * - Single function for simple access: + * @code + * if (NRF_SUCCESS != nrf_atfifo_simple_put(my_fifo, &data, NULL)) + * { + * // Error handling + * } + * @endcode + * - Function pair to limit data copying: + * @code + * struct point3d + * { + * int x, y, z; + * }point3d_t; + * nrf_atfifo_context_t context; + * point3d_t * point; + * + * if (NULL != (point = nrf_atfifo_item_alloc(my_fifo, &context))) + * { + * point->x = a; + * point->y = b; + * point->z = c; + * if (nrf_atfifo_item_put(my_fifo, &context)) + * { + * // Send information to the rest of the system + * // that there is new data in the FIFO available for reading. + * } + * } + * else + * { + * // Error handling + * } + * + * @endcode + * @note + * This atomic FIFO implementation requires that the operation that is + * opened last is finished (committed/flushed) first. + * This is typical for operations performed from the interrupt runtime + * when the other operation is performed from the main thread. + * + * This implementation does not support typical multithreading operating system + * access where operations can be started and finished in totally unrelated order. + * + * @{ + */ + +/** + * @brief Read and write position structure. + * + * A structure that holds the read and write position used by the FIFO head and tail. + */ +typedef struct nrf_atfifo_postag_pos_s +{ + uint16_t wr; //!< First free space to write the data + uint16_t rd; //!< A place after the last data to read +}nrf_atfifo_postag_pos_t; + +/** + * @brief End data index tag. + * + * A tag used to mark the end of data. + * To properly realize atomic data committing, the whole variable has to be + * accessed atomically. + */ +typedef union nrf_atfifo_postag_u +{ + uint32_t tag; //!< Whole tag, used for atomic, 32-bit access + nrf_atfifo_postag_pos_t pos; //!< Structure that holds reading and writing position separately +}nrf_atfifo_postag_t; + +/** + * @brief The FIFO instance. + * + * The instance of atomic FIFO. + * Used with all FIFO functions. + */ +typedef struct nrf_atfifo_s +{ + void * p_buf; //!< Pointer to the data buffer + nrf_atfifo_postag_t tail; //!< Read and write tail position tag + nrf_atfifo_postag_t head; //!< Read and write head position tag + uint16_t buf_size; //!< FIFO size in number of bytes (has to be divisible by @c item_size) + uint16_t item_size; //!< Size of a single FIFO item +}nrf_atfifo_t; + +/** + * @brief FIFO write operation item context. + * + * Context structure used to mark an allocated space in FIFO that is ready for put. + * All the data required to properly put allocated and written data. + */ +typedef struct nrf_atfifo_item_put_s +{ + nrf_atfifo_postag_t last_tail; //!< Tail tag value that was here when opening the FIFO to write +}nrf_atfifo_item_put_t; + + +/** + * @brief FIFO read operation item context. + * + * Context structure used to mark an opened get operation to properly free an item after reading. + */ +typedef struct nrf_atfifo_rcontext_s +{ + nrf_atfifo_postag_t last_head; //!< Head tag value that was here when opening the FIFO to read +}nrf_atfifo_item_get_t; + + +/** + * @defgroup nrf_atfifo_instmacros FIFO instance macros + * + * A group of macros helpful for FIFO instance creation and initialization. + * They may be used to create and initialize instances for most use cases. + * + * FIFO may also be created and initialized directly using + * @ref nrf_atfifo_init function. + * @{ + */ + /** + * @brief Macro for generating the name for a data buffer. + * + * The name of the data buffer that would be created by + * @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Name of the buffer variable. + * + * @note This is auxiliary internal macro and in normal usage + * it should not be called. + */ + #define NRF_ATFIFO_BUF_NAME(fifo_id) CONCAT_2(fifo_id, _data) + + /** + * @brief Macro for generating the name for a FIFO instance. + * + * The name of the instance variable that will be created by the + * @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Name of the instance variable. + * + * @note This is auxiliary internal macro and in normal usage + * it should not be called. + */ + #define NRF_ATFIFO_INST_NAME(fifo_id) CONCAT_2(fifo_id, _inst) + + /** + * @brief Macro for creating an instance. + * + * Creates the FIFO object variable itself. + * + * Usage example: + * @code + * NRF_ATFIFO_DEF(my_fifo, uint16_t, 12); + * NRF_ATFIFO_INIT(my_fifo); + * + * uint16_t some_val = 45; + * nrf_atfifo_item_put(my_fifo, &some_val, sizeof(some_val), NULL); + * nrf_atfifo_item_get(my_fifo, &some_val, sizeof(some_val), NULL); + * @endcode + * + * @param[in] fifo_id Identifier of a FIFO object. + * This identifier will be a pointer to the instance. + * It makes it possible to use this directly for the functions + * that operate on the FIFO. + * Because it is a static const object, it should be optimized by the compiler. + * @param[in] storage_type Type of data that will be stored in the FIFO. + * @param[in] item_cnt Capacity of the created FIFO in maximum number of items that may be stored. + * The phisical size of the buffer will be 1 element bigger. + */ + #define NRF_ATFIFO_DEF(fifo_id, storage_type, item_cnt) \ + static storage_type NRF_ATFIFO_BUF_NAME(fifo_id)[(item_cnt)+1]; \ + static nrf_atfifo_t NRF_ATFIFO_INST_NAME(fifo_id); \ + static nrf_atfifo_t * const fifo_id = &NRF_ATFIFO_INST_NAME(fifo_id) + + /** + * @brief Macro for initializing the FIFO that was previously declared by the macro. + * + * Use this macro to simplify FIFO initialization. + * + * @note + * This macro can be only used on a FIFO object defined by @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Value from the @ref nrf_atfifo_init function. + */ + #define NRF_ATFIFO_INIT(fifo_id) \ + nrf_atfifo_init( \ + fifo_id, \ + NRF_ATFIFO_BUF_NAME(fifo_id), \ + sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)), \ + sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)[0]) \ + ) + +/** @} */ + +/** + * @brief Function for initializing the FIFO. + * + * Preparing the FIFO instance to work. + * + * @param[out] p_fifo FIFO object to initialize. + * @param[in,out] p_buf FIFO buffer for storing data. + * @param[in] buf_size Total buffer size (has to be divisible by @c item_size). + * @param[in] item_size Size of a single item held inside the FIFO. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If a NULL pointer is provided as the buffer. + * @retval NRF_ERROR_INVALID_LENGTH If size of the buffer provided is not divisible by @c item_size. + * + * @note + * Buffer size must be able to hold one element more than the designed FIFO capacity. + * This one, empty element is used for overflow checking. + */ +ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size); + +/** + * @brief Function for clearing the FIFO. + * + * Function for clearing the FIFO. + * + * If this function is called during an opened and uncommitted write operation, + * the FIFO is cleared up to the currently ongoing commit. + * There is no possibility to cancel an ongoing commit. + * + * If this function is called during an opened and unflushed read operation, + * the read position in the head is set, but copying it into the write head position + * is left to read closing operation. + * + * This way, there is no more data to read, but the memory is released + * in the moment when it is safe. + * + * @param[in,out] p_fifo FIFO object. + * + * @retval NRF_SUCCESS FIFO totally cleared. + * @retval NRF_ERROR_BUSY Function called in the middle of writing or reading operation. + * If it is called in the middle of writing operation, + * FIFO was cleared up to the already started and uncommitted write. + * If it is called in the middle of reading operation, + * write head was only moved. It will be copied into read tail when the reading operation + * is flushed. + */ +ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo); + +/** + * @brief Function for atomically putting data into the FIFO. + * + * It uses memcpy function inside and in most situations, it is more suitable to + * use @ref nrf_atfifo_item_alloc, write the data, and @ref nrf_atfifo_item_put to store a new value + * in a FIFO. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_var Variable to copy. + * @param[in] size Size of the variable to copy. + * Can be smaller or equal to the FIFO item size. + * @param[out] p_visible See value returned by @ref nrf_atfifo_item_put. + * It may be NULL if the caller does not require the current operation status. + * + * @retval NRF_SUCCESS If an element has been successfully added to the FIFO. + * @retval NRF_ERROR_NO_MEM If the FIFO is full. + * + * @note + * To avoid data copying, you can use the @ref nrf_atfifo_item_alloc and @ref nrf_atfifo_item_put + * functions pair. + */ +ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * const p_var, size_t size, bool * const p_visible); + +/** + * @brief Function for opening the FIFO for writing. + * + * Function called to start the FIFO write operation and access the given FIFO buffer directly. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_context Operation context, required by @ref nrf_atfifo_item_put. + * + * @return Pointer to the space where variable data can be stored. + * NULL if there is no space in the buffer. + */ +void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); + +/** + * @brief Function for closing the writing operation. + * + * Puts a previously allocated context into FIFO. + * This function must be called to commit an opened write operation. + * It sets all the buffers and marks the data, so that it is visible to read. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_context Operation context, filled by the @ref nrf_atfifo_item_alloc function. + * + * @retval true Data is currently ready and will be visible to read. + * @retval false The internal commit was marked, but the writing operation interrupted another writing operation. + * The data will be available to read when the interrupted operation is committed. + */ +bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); + +/** + * @brief Function for getting a single value from the FIFO. + * + * This function gets the value from the top of the FIFO. + * The value is removed from the FIFO memory. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_var Pointer to the variable to store the data. + * @param[in] size Size of the data to be loaded. + * @param[out] p_released See the values returned by @ref nrf_atfifo_item_free. + * + * @retval NRF_SUCCESS Element was successfully copied from the FIFO memory. + * @retval NRF_ERROR_NOT_FOUND No data in the FIFO. + */ +ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released); + +/** + * @brief Function for opening the FIFO for reading. + * + * Function called to start the FIFO read operation and access the given FIFO buffer directly. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_context The operation context, required by @ref nrf_atfifo_item_free + * + * @return Pointer to data buffer or NULL if there is no data in the FIFO. + */ +void const * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); + +/** + * @brief Function for closing the reading operation. + * + * Function used to finish the reading operation. + * If this reading operation does not interrupt another reading operation, the head write buffer is moved. + * If this reading operation is placed in the middle of another reading, only the new read pointer is written. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_context Context of the reading operation to be closed. + * + * @retval true This operation is not generated in the middle of another read operation and the write head will be updated to the read head (space is released). + * @retval false This operation was performed in the middle of another read operation and the write buffer head was not moved (no space is released). + */ +bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); + + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATFIFO_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo_internal.h b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo_internal.h new file mode 100644 index 000000000..477b91ff2 --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/atfifo/nrf_atfifo_internal.h @@ -0,0 +1,577 @@ +/** + * Copyright (c) 2011 - 2017, 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 + * @brief Atomic FIFO internal file + * + * This file should be included only by nrf_atfifo internally. + * Needs nrf_atfifo.h included first. + */ +#ifndef NRF_ATFIFO_H__ +#error This is internal file. Do not include this file in your program. +#endif + +#ifndef NRF_ATFIFO_INTERNAL_H__ +#define NRF_ATFIFO_INTERNAL_H__ +#include +#include "nrf.h" +#include "app_util.h" +#include "nordic_common.h" + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error Unsupported core version +#endif + +/* + * Make sure that rd and wr pos in a tag are aligned like expected + * Changing this would require changes inside assembly code! + */ +STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, wr) == 0); +STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, rd) == 2); + +/** + * @brief Atomically reserve space for a new write. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] old_tail Tail position tag before new space is reserved. + * + * @retval true Space available. + * @retval false Memory full. + * + * @sa nrf_atfifo_wspace_close + */ +static bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail); + +/** + * @brief Atomically mark all written data available. + * + * This function marks all data available for reading. + * This marking is done by copying tail.pos.wr into tail.pos.rd. + * + * It must be called only when closing the first write. + * It cannot be called if any write access was interrupted. + * See the code below: + * @code + * if (old_tail.pos.wr == old_tail.pos.rd) + * { + * nrf_atfifo_wspace_close(my_fifo); + * return true; + * } + * return false; + * @endcode + * + * @param[in,out] p_fifo FIFO object. + * + * @sa nrf_atfifo_wspace_req + */ +static void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo); + +/** + * @brief Atomically get a part of a buffer to read data. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] old_head Head position tag before the data buffer is read. + * + * @retval true Data available for reading. + * @retval false No data in the buffer. + * + * @sa nrf_atfifo_rspace_close + */ +static bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head); + +/** + * @brief Atomically release all read data. + * + * This function marks all data that was read as free space, + * which is available for writing. + * This marking is done by copying head.pos.rd into head.pos.wr. + * + * It must be called only when closing the first read. + * It cannot be called when the current read access interrupted any other read access. + * See code below: + * @code + * if (old_head.pos.wr == old_head.pos.rd) + * { + * nrf_atfifo_rspace_close(my_fifo); + * return true; + * } + * return false; + * @endcode + * + * @param[in,out] p_fifo FIFO object. + * + * @sa nrf_atfifo_rspace_req + */ +static void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo); + +/** + * @brief Safely clear the FIFO, internal function. + * + * This function realizes the functionality required by @ref nrf_atfifo_clear. + * + * @param[in,out] p_fifo FIFO object. + * + * @retval true All the data was released. + * @retval false All the data available for releasing was released, but there is some pending transfer. + */ +static bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo); + + +/* --------------------------------------------------------------------------- + * Implementation starts here + */ + +#if defined ( __CC_ARM ) + + +__ASM bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - p_old_tail + * R2 - internal variable old_tail (saved by caller) + * R3 - internal variable new_tail (saved by caller) + * R4 - internal temporary register (saved by this function) + * R5 - not used stored to keep the stack aligned to 8 bytes + * Returned value: + * R0 (bool - 32 bits) + */ + push {r4, r5} +nrf_atfifo_wspace_req_repeat + /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + /* Extract write position !!! R3 !!! */ + uxth r3, r2 + /* Increment address with overload support !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] + add r3, r4 + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] + cmp r3, r4 + it hs + subhs r3, r3, r4 + + /* Check if FIFO would overload after making this increment !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr))] + cmp r3, r4 + ittt eq + clrexeq + moveq r0, #__cpp(false) + beq nrf_atfifo_wspace_req_exit + + /* Pack everything back !!! R3 - new tail !!! */ + /* Copy lower byte from new_tail, and higher byte is a value from the top of old_tail */ + pkhbt r3, r3, r2 + + /* Store new value clearing memory monitor !!! R4 used temporary !!! */ + strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r4, #0 + bne nrf_atfifo_wspace_req_repeat + + /* Return true */ + mov r0, #__cpp(true) +nrf_atfifo_wspace_req_exit + /* Save old tail */ + str r2, [r1] + pop {r4, r5} + bx lr +} + + +__ASM void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - internal temporary register + * R2 - new_tail + */ +nrf_atfifo_wspace_close_repeat + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + /* Copy from lower byte to higher */ + pkhbt r2, r2, r2, lsl #16 + + strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r1, #0 + bne nrf_atfifo_wspace_close_repeat + bx lr +} + + +__ASM bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - p_old_head + * R2 - internal variable old_head (saved by caller) + * R3 - internal variable new_head (saved by caller) + * R4 - internal temporary register (saved by this function) + * R5 - not used stored to keep the stack aligned to 8 bytes + * Returned value: + * R0 (bool - 32 bits) + */ + push {r4, r5} +nrf_atfifo_rspace_req_repeat + /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + /* Extract read position !!! R3 !!! */ + uxth r3, r2, ror #16 + + /* Check if we have any data !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] + cmp r3, r4 + ittt eq + clrexeq + moveq r0, #__cpp(false) + beq nrf_atfifo_rspace_req_exit + + /* Increment address with overload support !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] + add r3, r4 + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] + cmp r3, r4 + it hs + subhs r3, r3, r4 + + /* Pack everything back !!! R3 - new tail !!! */ + /* Copy lower byte from old_head, and higher byte is a value from write_pos */ + pkhbt r3, r2, r3, lsl #16 + + /* Store new value clearing memory monitor !!! R4 used temporary !!! */ + strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r4, #0 + bne nrf_atfifo_rspace_req_repeat + + /* Return true */ + mov r0, #__cpp(true) +nrf_atfifo_rspace_req_exit + /* Save old head */ + str r2, [r1] + pop {r4, r5} + bx lr +} + + +__ASM void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - internal temporary register + * R2 - new_tail + */ +nrf_atfifo_rspace_close_repeat + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + /* Copy from higher byte to lower */ + pkhtb r2, r2, r2, asr #16 + + strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r1, #0 + bne nrf_atfifo_rspace_close_repeat + bx lr +} + + +__ASM bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo as input, bool output after + * R1 - tail, rd pointer, new_head + * R2 - head_old, destroyed when creating new_head + * R3 - p_fifo - copy + */ + mov r3, r0 +nrf_atfifo_space_clear_repeat + /* Load old head in !!! R2 register !!! and read pointer of tail in !!! R1 register !!! */ + ldrex r2, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] + ldrh r1, [r3, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] + cmp r2, r2, ror #16 + /* Return false as default */ + mov r0, #__cpp(false) + /* Create new head in !!! R1 register !!! Data in !!! R2 register broken !!! */ + itett ne + uxthne r2, r2 + orreq r1, r1, r1, lsl #16 + orrne r1, r2, r1, lsl #16 + + /* Skip header test */ + bne nrf_atfifo_space_clear_head_test_skip + + /* Load whole tail and test it !!! R2 used !!! */ + ldr r2, [r3, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r2, r2, ror #16 + /* Return true if equal */ + it eq + moveq r0, #__cpp(true) + +nrf_atfifo_space_clear_head_test_skip + /* Store and test if success !!! R2 used temporary !!! */ + strex r2, r1, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r2, #0 + bne nrf_atfifo_space_clear_repeat + bx lr +} + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) +{ + volatile bool ret; + volatile uint32_t old_tail; + uint32_t new_tail; + uint32_t temp; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[old_tail], [%[p_fifo], %[offset_tail]] \n" + " uxth %[new_tail], %[old_tail] \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" + " add %[new_tail], %[temp] \n" + " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" + " cmp %[new_tail], %[temp] \n" + " it hs \n" + " subhs %[new_tail], %[new_tail], %[temp] \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_head_wr]] \n" + " cmp %[new_tail], %[temp] \n" + " ittt eq \n" + " clrexeq \n" + " moveq %[ret], %[false_val] \n" + " beq.n 2f \n" + " \n" + " pkhbt %[new_tail], %[new_tail], %[old_tail] \n" + " \n" + " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + " \n" + " mov %[ret], %[true_val] \n" + "2: \n" + : /* Output operands */ + [ret] "=r"(ret), + [temp] "=&r"(temp), + [old_tail]"=&r"(old_tail), + [new_tail]"=&r"(new_tail) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), + [offset_head_wr] "J"(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr)), + [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), + [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + p_old_tail->tag = old_tail; + UNUSED_VARIABLE(new_tail); + UNUSED_VARIABLE(temp); + return ret; +} + + +void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) +{ + uint32_t temp; + uint32_t new_tail; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " pkhbt %[new_tail],%[new_tail], %[new_tail], lsl #16 \n" + " \n" + " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [temp] "=&r"(temp), + [new_tail] "=&r"(new_tail) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(temp); + UNUSED_VARIABLE(new_tail); +} + + +bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) +{ + volatile bool ret; + volatile uint32_t old_head; + uint32_t new_head; + uint32_t temp; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" + " uxth %[new_head], %[old_head], ror #16 \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_tail_rd]] \n" + " cmp %[new_head], %[temp] \n" + " ittt eq \n" + " clrexeq \n" + " moveq %[ret], %[false_val] \n" + " beq.n 2f \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" + " add %[new_head], %[temp] \n" + " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" + " cmp %[new_head], %[temp] \n" + " it hs \n" + " subhs %[new_head], %[new_head], %[temp] \n" + " \n" + " pkhbt %[new_head], %[old_head], %[new_head], lsl #16 \n" + " \n" + " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + " \n" + " mov %[ret], %[true_val] \n" + "2: \n" + : /* Output operands */ + [ret] "=r"(ret), + [temp] "=&r"(temp), + [old_head]"=&r"(old_head), + [new_head]"=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)), + [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), + [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), + [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + p_old_head->tag = old_head; + UNUSED_VARIABLE(new_head); + UNUSED_VARIABLE(temp); + return ret; +} + + +void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) +{ + uint32_t temp; + uint32_t new_head; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[new_head], [%[p_fifo], %[offset_head]] \n" + " pkhtb %[new_head],%[new_head], %[new_head], asr #16 \n" + " \n" + " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [temp] "=&r"(temp), + [new_head] "=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(temp); + UNUSED_VARIABLE(new_head); +} + + +bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) +{ + volatile bool ret; + uint32_t old_head; /* This variable is left broken after assembly code finishes */ + uint32_t new_head; + + __ASM volatile( + "1: \n" + " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" + " ldrh %[new_head], [%[p_fifo], %[offset_tail_rd]] \n" + " cmp %[old_head], %[old_head], ror #16 \n" + " \n" + " mov %[ret], %[false_val] \n" + " \n" + " itett ne \n" + " uxthne %[old_head], %[old_head] \n" + " orreq %[new_head], %[new_head], %[new_head], lsl #16 \n" + " orrne %[new_head], %[old_head], %[new_head], lsl #16 \n" + " \n" + " bne.n 2f \n" + " \n" + " ldr %[old_head], [%[p_fifo], %[offset_tail]] \n" + " cmp %[old_head], %[old_head], ror #16 \n" + " it eq \n" + " moveq %[ret], %[true_val] \n" + " \n" + "2: \n" + " strex %[old_head], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[old_head], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [ret] "=&r"(ret), + [old_head] "=&r"(old_head), + [new_head] "=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), + [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(old_head); + UNUSED_VARIABLE(new_head); + return ret; +} + +#else +#error Unsupported compiler +#endif + +#endif /* NRF_ATFIFO_INTERNAL_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd.c b/third_party/NordicSemiconductor/libraries/usb/app_usbd.c new file mode 100644 index 000000000..e3036eb81 --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd.c @@ -0,0 +1,1356 @@ +/** + * Copyright (c) 2016 - 2017, 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_config.h" +#if APP_USBD_ENABLED +#include "sdk_common.h" +#include "app_usbd.h" +#include "app_usbd_core.h" +#include "nrf_power.h" +#include "nrf_drv_clock.h" +#if APP_USBD_EVENT_QUEUE_ENABLE +#include "nrf_atfifo.h" +#endif + +#define NRF_LOG_MODULE_NAME app_usbd + +#if APP_USBD_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL APP_USBD_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR APP_USBD_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR APP_USBD_CONFIG_DEBUG_COLOR +#else //APP_USBD_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //APP_USBD_CONFIG_LOG_ENABLED +#include "nrf_log.h" + +/* Base variables tests */ + +/* Check event of app_usbd_event_type_t enumerator */ +STATIC_ASSERT((int32_t)APP_USBD_EVT_FIRST_APP == (int32_t)NRF_DRV_USBD_EVT_CNT); +STATIC_ASSERT(sizeof(app_usbd_event_type_t) == sizeof(nrf_drv_usbd_event_type_t)); + +STATIC_ASSERT(sizeof(app_usbd_descriptor_header_t) == 2); +STATIC_ASSERT(sizeof(app_usbd_descriptor_device_t) == 18); +STATIC_ASSERT(sizeof(app_usbd_descriptor_configuration_t) == 9); +STATIC_ASSERT(sizeof(app_usbd_descriptor_iface_t) == 9); +STATIC_ASSERT(sizeof(app_usbd_descriptor_ep_t) == 7); +STATIC_ASSERT(sizeof(app_usbd_descriptor_iad_t) == 8); + +STATIC_ASSERT(sizeof(app_usbd_setup_t) == sizeof(nrf_drv_usbd_setup_t)); + +/** + * @internal + * @defgroup app_usbd_internals USBD library internals + * @ingroup app_usbd + * + * Internal variables, auxiliary macros and functions of USBD library. + * @{ + */ + +/** + * @brief Variable type for endpoint configuration + * + * Each endpoint would have assigned this type of configuration structure. + */ +typedef struct +{ + /** + * @brief The class instance + * + * The pointer to the class instance that is connected to the endpoint. + */ + app_usbd_class_inst_t const * p_cinst; + + /** + * @brief Endpoint event handler. + * + * Event handler for the endpoint. + * It is set to event handler for the class instance during connection by default, + * but it can be then updated for as a reaction for @ref APP_USBD_EVT_ATTACHED event. + * This way we can speed up the interpretation of endpoint related events. + */ + app_usbd_ep_event_handler_t event_handler; +}app_usbd_ep_conf_t; + +#if (APP_USBD_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) +/** + * @brief Event queue + * + * The queue with events to be processed + */ +NRF_ATFIFO_DEF(m_event_queue, app_usbd_internal_evt_t, APP_USBD_EVENT_QUEUE_SIZE); +#endif + +/** + * @brief Instances connected with IN endpoints + * + * Array of instance pointers connected with every IN endpoint. + * @sa m_epout_instances + */ +static app_usbd_ep_conf_t m_epin_conf[NRF_USBD_EPIN_CNT]; + +/** + * @brief Instances connected with OUT endpoints + * + * Array of instance pointers connected with every OUT endpoint. + * @sa m_epin_instances + */ +static app_usbd_ep_conf_t m_epout_conf[NRF_USBD_EPIN_CNT]; + +/** + * @brief Beginning of classes list + * + * All enabled in current configuration instances are connected into + * a single linked list chain. + * This variable points to first element. + * Core class instance (connected to endpoint 0) is not listed here. + */ +static app_usbd_class_inst_t const * m_p_first_cinst; + +/** + * @brief Classes list that requires SOF events + * + * @todo RK Implement and documentation + */ +static app_usbd_class_inst_t const * m_p_first_sof_cinst; + +/** + * @brief Default configuration (when NULL is passed to @ref app_usbd_init). + */ +static const app_usbd_config_t m_default_conf = { +#if (!(APP_USBD_EVENT_QUEUE_ENABLE)) || defined(__SDK_DOXYGEN__) + .ev_handler = app_usbd_event_execute, +#endif +#if (APP_USBD_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) + .ev_isr_handler = NULL, +#endif + .ev_state_proc = NULL, + .enable_sof = false +}; + +/** + * @brief SUSPEND state machine states + * + * The enumeration of internal SUSPEND state machine states. + */ +typedef enum +{ + SUSTATE_STOPPED, /**< The USB driver was not started */ + SUSTATE_STARTED, /**< The USB driver was started - waiting for USB RESET */ + SUSTATE_ACTIVE, /**< Active state */ + SUSTATE_SUSPENDING, /**< Suspending - waiting for the user to acknowledge */ + SUSTATE_SUSPEND, /**< Suspended */ + SUSTATE_RESUMING, /**< Resuming - waiting for clock */ + SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ, /**< Waking up - waiting for clock and WUREQ from driver */ + SUSTATE_WAKINGUP_WAITING_HFCLK, /**< Waking up - waiting for HFCLK (WUREQ detected) */ + SUSTATE_WAKINGUP_WAITING_WREQ, /**< Waking up - waiting for WREQ (HFCLK active) */ +}app_usbd_sustate_t; + +/** + * @brief Current suspend state + * + * The state of the suspend state machine + */ +static app_usbd_sustate_t m_sustate; + +/** + * @brief Remote wake-up register/unregister + * + * Counter incremented when appended instance required remote wake-up functionality. + * It should be decremented when the class is removed. + * When this counter is not zero, remote wake-up functionality is activated inside core. + */ +static uint8_t m_rwu_registered_counter; + +/** + * @brief Current configuration. + */ +static app_usbd_config_t m_current_conf; + +/** + * @brief Class interface call: event handler + * + * @ref app_usbd_class_interface_t::event_handler + * + * @param[in] p_cinst Class instance + * @param[in] p_event Event passed to class instance + * + * @return Standard error code @ref ret_code_t + * @retval NRF_SUCCESS event handled successfully + * @retval NRF_ERROR_NOT_SUPPORTED unsupported event + * */ +static inline ret_code_t class_event_handler(app_usbd_class_inst_t const * const p_cinst, + app_usbd_complex_evt_t const * const p_event) +{ + ASSERT(p_cinst != NULL); + ASSERT(p_cinst->p_class_methods != NULL); + ASSERT(p_cinst->p_class_methods->event_handler != NULL); + return p_cinst->p_class_methods->event_handler(p_cinst, p_event); +} + +#if (APP_USBD_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) +/** + * @brief User event handler call (passed via configuration). + * + * @param p_event Handler of an event that is going to be added into queue. + * @param queued The event is visible in the queue. + */ +static inline void user_event_handler(app_usbd_internal_evt_t const * const p_event, bool queued) +{ + if ((m_current_conf.ev_isr_handler) != NULL) + { + m_current_conf.ev_isr_handler(p_event, queued); + } +} +#endif + +/** + * @brief User event processor call (passed via configuration) + * + * @param event Event type. + */ +static inline void user_event_state_proc(app_usbd_event_type_t event) +{ + if ((m_current_conf.ev_state_proc) != NULL) + { + m_current_conf.ev_state_proc(event); + } +} + +/** + * @brief Class interface call: get descriptors + * + * @ref app_usbd_class_interface_t::get_descriptors + * + * @param[in] p_inst Class instance + * @param[out] p_size Descriptors size + * + * @return Class descriptors start address + * */ +static inline const void * class_get_descriptors(app_usbd_class_inst_t const * const p_cinst, + size_t * p_size) +{ + ASSERT(p_cinst != NULL); + ASSERT(p_cinst->p_class_methods != NULL); + ASSERT(p_cinst->p_class_methods->get_descriptors != NULL); + return p_cinst->p_class_methods->get_descriptors(p_cinst, p_size); +} + +const void * app_usbd_class_descriptor_find(app_usbd_class_inst_t const * const p_cinst, + uint8_t desc_type, + uint8_t desc_index, + size_t * p_desc_len) +{ + app_usbd_descriptor_header_t const * p_header; + uint8_t const * p_raw = class_get_descriptors(p_cinst, p_desc_len); + if (p_raw == NULL) + { + return NULL; + } + + size_t pos = 0; + uint8_t index = 0; + while (pos < *p_desc_len) + { + p_header = (app_usbd_descriptor_header_t const *)(p_raw + pos); + if (p_header->bDescriptorType == desc_type) + { + if (desc_index == index) + { + *p_desc_len = p_header->bLength; + return p_header; + } + + index++; + } + + pos += p_header->bLength; + } + + return NULL; +} + +/** + * @brief Access into selected endpoint configuration structure + * + * @param ep Endpoint address + * @return A pointer to the endpoint configuration structure + * + * @note This function would assert when endpoint number is not correct and debugging is enabled. + */ +static app_usbd_ep_conf_t * app_usbd_ep_conf_access(nrf_drv_usbd_ep_t ep) +{ + if (NRF_USBD_EPIN_CHECK(ep)) + { + uint8_t nr = NRF_USBD_EP_NR_GET(ep); + ASSERT(nr < NRF_USBD_EPIN_CNT); + return &m_epin_conf[nr]; + } + else + { + uint8_t nr = NRF_USBD_EP_NR_GET(ep); + ASSERT(nr < NRF_USBD_EPOUT_CNT); + return &m_epout_conf[nr]; + } +} + +/** + * @brief Accessing instance connected with selected endpoint + * + * @param ep Endpoint number + * + * @return The pointer to the instance connected with endpoint + */ +static inline app_usbd_class_inst_t const * app_usbd_ep_instance_get(nrf_drv_usbd_ep_t ep) +{ + return app_usbd_ep_conf_access(ep)->p_cinst; +} + +/** + * @brief Connect instance with selected endpoint + * + * This function configures instance connected to endpoint but also sets + * default event handler function pointer. + * + * @param ep Endpoint number + * @param p_cinst The instance to connect into the selected endpoint. + * NULL if endpoint is going to be disconnected. + * + * @note Disconnecting EP0 is not allowed and protected by assertion. + */ +static void app_usbd_ep_instance_set(nrf_drv_usbd_ep_t ep, app_usbd_class_inst_t const * p_cinst) +{ + app_usbd_ep_conf_t * p_ep_conf = app_usbd_ep_conf_access(ep); + /* Set instance and default event handler */ + p_ep_conf->p_cinst = p_cinst; + if (p_cinst == NULL) + { + ASSERT((ep != NRF_DRV_USBD_EPOUT0) && (ep != NRF_DRV_USBD_EPIN0)); /* EP0 should never be disconnected */ + p_ep_conf->event_handler = NULL; + } + else + { + p_ep_conf->event_handler = p_cinst->p_class_methods->event_handler; + } +} + +/** + * @brief Call the core handler + * + * Core instance is special kind of instance that is connected only to endpoint 0. + * It is not present in instance list. + * This auxiliary function makes future changes easier. + * Just call the event instance for core module here. + */ +static inline ret_code_t app_usbd_core_handler_call(app_usbd_internal_evt_t const * const p_event) +{ + return m_epout_conf[0].event_handler( + m_epout_conf[0].p_cinst, + (app_usbd_complex_evt_t const *)p_event); +} + +/** + * @brief Add event for execution + * + * Dependent on configuration event would be executed in place or would be added into queue + * to be executed later. + * + * @param p_event Event to be executed + */ +static inline void app_usbd_event_add(app_usbd_internal_evt_t const * const p_event) +{ +#if (APP_USBD_EVENT_QUEUE_ENABLE) + nrf_atfifo_item_put_t cx; + app_usbd_internal_evt_t * p_event_item = nrf_atfifo_item_alloc(m_event_queue, &cx); + if (NULL != p_event_item) + { + bool visible; + *p_event_item = *p_event; + visible = nrf_atfifo_item_put(m_event_queue, &cx); + user_event_handler(p_event, visible); + } + else + { + NRF_LOG_ERROR("Event queue full."); + } +#else + m_current_conf.ev_handler(p_event); +#endif +} + +/** + * @brief Event handler + * + * The function that pushes the event into the queue + * @param p_event + */ +static void app_usbd_event_handler(nrf_drv_usbd_evt_t const * const p_event) +{ + app_usbd_event_add((app_usbd_internal_evt_t const *)p_event); +} + +/** + * @brief HF clock ready event handler + * + * Function that is called when high frequency clock is started + * + * @param event Event type that comes from clock driver + */ +static void app_usbd_hfclk_ready(nrf_drv_clock_evt_type_t event) +{ + ASSERT(NRF_DRV_CLOCK_EVT_HFCLK_STARTED == event); + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_HFCLK_READY + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); +} + +/** + * @brief Check if the HFCLK was requested in selected suspend state machine state + * + * + * @param sustate State to be checked + * + * @retval true High frequency clock was requested in selected state + * @retval false High frequency clock was released in selected state + */ +static inline bool app_usbd_sustate_with_requested_hfclk(app_usbd_sustate_t sustate) +{ + switch(sustate) + { + case SUSTATE_STOPPED: return false; + case SUSTATE_STARTED: return false; + case SUSTATE_ACTIVE: return true; + case SUSTATE_SUSPENDING: return false; + case SUSTATE_SUSPEND: return false; + case SUSTATE_RESUMING: return true; + case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: return true; + case SUSTATE_WAKINGUP_WAITING_HFCLK: return true; + case SUSTATE_WAKINGUP_WAITING_WREQ: return true; + default: + return false; + } +} + +/** + * @brief Check it the HFCLK is running in selected suspend state machine state + * + * @param sustate State to be checked + * + * @retval true High frequency clock is running in selected state + * @retval false High frequency clock is released in selected state + */ +static inline bool app_usbd_sustate_with_running_hfclk(app_usbd_sustate_t sustate) +{ + switch(sustate) + { + case SUSTATE_STOPPED: return false; + case SUSTATE_STARTED: return false; + case SUSTATE_ACTIVE: return true; + case SUSTATE_SUSPENDING: return false; + case SUSTATE_SUSPEND: return false; + case SUSTATE_RESUMING: return false; + case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: return false; + case SUSTATE_WAKINGUP_WAITING_HFCLK: return false; + case SUSTATE_WAKINGUP_WAITING_WREQ: return true; + default: + return false; + } +} + +/** + * @brief Get current suspend state machine state + * + * @return The state of the suspend state machine + */ +static inline app_usbd_sustate_t sustate_get(void) +{ + return m_sustate; +} + +/** + * @brief Set current suspend state machine state + * + * @param sustate The requested state of the state machine + */ +static inline void sustate_set(app_usbd_sustate_t sustate) +{ + if (app_usbd_sustate_with_requested_hfclk(sustate) != app_usbd_sustate_with_requested_hfclk(m_sustate)) + { + if (app_usbd_sustate_with_requested_hfclk(sustate)) + { + static nrf_drv_clock_handler_item_t clock_handler_item = + { + .event_handler = app_usbd_hfclk_ready + }; + nrf_drv_clock_hfclk_request(&clock_handler_item); + } + else + { + nrf_drv_clock_hfclk_release(); + } + } + if (app_usbd_sustate_with_running_hfclk(sustate) != app_usbd_sustate_with_running_hfclk(m_sustate)) + { + if (app_usbd_sustate_with_running_hfclk(sustate)) + { + nrf_drv_usbd_active_irq_config(); + } + else + { + nrf_drv_usbd_suspend_irq_config(); + } + } + m_sustate = sustate; +} + + +/** @} */ + + +ret_code_t app_usbd_init(app_usbd_config_t const * p_config) +{ + ret_code_t ret; + +#if (APP_USBD_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) + ret = NRF_ATFIFO_INIT(m_event_queue); + if (NRF_SUCCESS != ret) + { + return NRF_ERROR_INTERNAL; + } +#endif + + UNUSED_RETURN_VALUE(nrf_drv_clock_init()); + + ret = nrf_drv_usbd_init(app_usbd_event_handler); + if (NRF_SUCCESS != ret) + { + return ret; + } + + if (p_config == NULL) + { + m_current_conf = m_default_conf; + } + else + { + m_current_conf = *p_config; + } + + /* Clear variables */ + m_sustate = SUSTATE_STOPPED; + m_p_first_cinst = NULL; + m_p_first_sof_cinst = NULL; + memset(m_epin_conf , 0, sizeof(m_epin_conf )); + memset(m_epout_conf, 0, sizeof(m_epout_conf)); + + /*Pin core class to required endpoints*/ + uint8_t iface_idx; + app_usbd_class_iface_conf_t const * p_iface; + app_usbd_class_inst_t const * const p_inst = app_usbd_core_instance_access(); + iface_idx = 0; + while ((p_iface = app_usbd_class_iface_get(p_inst, iface_idx++)) != NULL) + { + uint8_t ep_idx = 0; + app_usbd_class_ep_conf_t const * p_ep; + while ((p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++)) != NULL) + { + app_usbd_ep_instance_set(app_usbd_class_ep_address_get(p_ep), p_inst); + } + } + + /* Successfully attached */ + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_INST_APPEND + }; + + return class_event_handler(p_inst, (app_usbd_complex_evt_t const *)(&evt_data)); +} + + +ret_code_t app_usbd_uninit(void) +{ + ret_code_t ret; + + ret = nrf_drv_usbd_uninit(); + if (NRF_SUCCESS != ret) + return ret; + + /* Unchain instance list */ + app_usbd_class_inst_t const * * pp_inst; + pp_inst = &m_p_first_cinst; + while (NULL != (*pp_inst)) + { + app_usbd_class_inst_t const * * pp_next = &app_usbd_class_data_access(*pp_inst)->p_next; + (*pp_inst) = NULL; + pp_inst = pp_next; + } + + /* Unchain SOF list */ + pp_inst = &m_p_first_sof_cinst; + while (NULL != (*pp_inst)) + { + app_usbd_class_inst_t const * * pp_next = &app_usbd_class_data_access(*pp_inst)->p_sof_next; + (*pp_inst) = NULL; + pp_inst = pp_next; + } + + /* Clear all endpoints configurations */ + memset(m_epin_conf , 0, sizeof(m_epin_conf )); + memset(m_epout_conf, 0, sizeof(m_epout_conf)); + /* Clear current configuration */ + memset(&m_current_conf, 0, sizeof(m_current_conf)); + + return ret; +} + + +void app_usbd_enable(void) +{ + nrf_drv_usbd_enable(); +} + + +void app_usbd_disable(void) +{ + ASSERT(!nrf_drv_usbd_is_started()); + nrf_drv_usbd_disable(); +} + + +void app_usbd_start(void) +{ + ASSERT(nrf_drv_usbd_is_enabled()); + + /* Power should be already enabled - wait just in case if user calls + * app_usbd_start just after app_usbd_enable without waiting for the event. */ + while (!nrf_power_usbregstatus_outrdy_get()) + { + /* Wait for the power but terminate the function if USBD power disappears */ + if (!nrf_power_usbregstatus_vbusdet_get()) + return; + } + + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_START_REQ + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); +} + + +void app_usbd_stop(void) +{ + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_STOP_REQ + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); +} + +void app_usbd_suspend_req(void) +{ + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_SUSPEND_REQ + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); +} + +bool app_usbd_wakeup_req(void) +{ + ASSERT(app_usbd_class_rwu_enabled_check()); + if (!app_usbd_core_feature_state_get(APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP)) + return false; + + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_WAKEUP_REQ + }; + app_usbd_event_add((app_usbd_internal_evt_t const * )&evt_data); + return true; +} + + +void app_usbd_event_execute(app_usbd_internal_evt_t const * const p_event) +{ + ASSERT(NULL != m_p_first_cinst); + /* If no event queue is implemented, it has to be ensured that this function is never called + * from the context higher than USB interrupt level + * If queue is implemented it would be called always from Thread level + * if the library is used correctly. + * NOTE: Higher interrupt level -> lower priority value. + */ + ASSERT(USBD_CONFIG_IRQ_PRIORITY <= current_int_priority_get()); + + /* Note - there should never be situation that event is generated on disconnected endpoint */ + switch (p_event->type) + { + case APP_USBD_EVT_START_REQ: + { + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_STARTED + }; + /* Enable all connected endpoints */ + uint8_t n; + for (n = 1; n < ARRAY_SIZE(m_epin_conf); ++n) + { + if (NULL != m_epin_conf[n].p_cinst) + { + nrf_drv_usbd_ep_enable(NRF_DRV_USBD_EPIN(n)); + } + } + for (n = 1; n < ARRAY_SIZE(m_epout_conf); ++n) + { + if (NULL != m_epout_conf[n].p_cinst) + { + nrf_drv_usbd_ep_enable(NRF_DRV_USBD_EPOUT(n)); + } + } + + /* Send event to all classes */ + UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const * )&evt_data)); + app_usbd_all_call((app_usbd_complex_evt_t const *)&evt_data); + user_event_state_proc(APP_USBD_EVT_STARTED); + + nrf_drv_usbd_start((NULL != m_p_first_sof_cinst) || (m_current_conf.enable_sof)); + sustate_set(SUSTATE_STARTED); + break; + } + case APP_USBD_EVT_STOP_REQ: + { + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_STOPPED + }; + + nrf_drv_usbd_stop(); + sustate_set(SUSTATE_STOPPED); + + /* Send event to all classes */ + app_usbd_all_call((app_usbd_complex_evt_t const * )&evt_data); + UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const *)&evt_data)); + user_event_state_proc(APP_USBD_EVT_STOPPED); + if (app_usbd_sustate_with_requested_hfclk(sustate_get())) + { + nrf_drv_clock_hfclk_release(); + } + + break; + } + case APP_USBD_EVT_HFCLK_READY: + { + switch(sustate_get()) + { + case SUSTATE_RESUMING: + { + sustate_set(SUSTATE_ACTIVE); + break; + } + case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: + { + sustate_set(SUSTATE_WAKINGUP_WAITING_WREQ); + break; + } + case SUSTATE_WAKINGUP_WAITING_HFCLK: + { + sustate_set(SUSTATE_ACTIVE); + break; + } + default: + break; // Just ignore - it can happen in specyfic situation + } + break; + } + case APP_USBD_EVT_SUSPEND_REQ: + { + /* Suspend request can be only processed when we are in suspending state */ + if (SUSTATE_SUSPENDING == sustate_get()) + { + if (nrf_drv_usbd_suspend()) + { + sustate_set(SUSTATE_SUSPEND); + } + } + break; + } + case APP_USBD_EVT_WAKEUP_REQ: + { + /* Suspend temporary if no suspend function was called from the application. + * This makes it possible to generate APP_USBD_EVT_DRV_WUREQ event from the driver */ + if (sustate_get() == SUSTATE_SUSPENDING) + { + if (nrf_drv_usbd_suspend()) + { + sustate_set(SUSTATE_SUSPEND); + } + } + if (nrf_drv_usbd_wakeup_req()) + { + sustate_set(SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ); + } + break; + } + + case APP_USBD_EVT_DRV_SOF: + { + user_event_state_proc(APP_USBD_EVT_DRV_SOF); + + app_usbd_class_inst_t const * p_inst = app_usbd_class_sof_first_get(); + while (NULL != p_inst) + { + ret_code_t r = class_event_handler(p_inst, (app_usbd_complex_evt_t const *)p_event); + UNUSED_VARIABLE(r); + p_inst = app_usbd_class_sof_next_get(p_inst); + } + break; + } + + case APP_USBD_EVT_DRV_RESET: + { + sustate_set(SUSTATE_ACTIVE); + user_event_state_proc(APP_USBD_EVT_DRV_RESUME); + /* Processing core interface (connected only to EP0) and then all instances from the list */ + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + break; + } + case APP_USBD_EVT_DRV_RESUME: + { + sustate_set(SUSTATE_RESUMING); + user_event_state_proc(APP_USBD_EVT_DRV_RESUME); + /* Processing core interface (connected only to EP0) and then all instances from the list */ + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + break; + } + case APP_USBD_EVT_DRV_WUREQ: + { + static const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_DRV_RESUME + }; + user_event_state_proc(APP_USBD_EVT_DRV_RESUME); + /* Processing core interface (connected only to EP0) and then all instances from the list */ + UNUSED_RETURN_VALUE(app_usbd_core_handler_call((app_usbd_internal_evt_t const *)&evt_data)); + app_usbd_all_call((app_usbd_complex_evt_t const *)&evt_data); + + switch(sustate_get()) + { + case SUSTATE_WAKINGUP_WAITING_HFCLK_WREQ: + sustate_set(SUSTATE_WAKINGUP_WAITING_HFCLK); + break; + case SUSTATE_WAKINGUP_WAITING_WREQ: + sustate_set(SUSTATE_ACTIVE); + break; + default: + { + // This should not happen - but try to recover by setting directly active state + NRF_LOG_WARNING("Unexpected state on WUREQ event (%u)", sustate_get()); + sustate_set(SUSTATE_ACTIVE); + } + } + break; + } + case APP_USBD_EVT_DRV_SUSPEND: + { + sustate_set(SUSTATE_SUSPENDING); + + user_event_state_proc(APP_USBD_EVT_DRV_SUSPEND); + + /* Processing all instances from the list and then core interface (connected only to EP0) */ + app_usbd_all_call((app_usbd_complex_evt_t const *)p_event); + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + break; + } + + case APP_USBD_EVT_DRV_SETUP: + { + UNUSED_RETURN_VALUE(app_usbd_core_handler_call(p_event)); + break; + } + + case APP_USBD_EVT_DRV_EPTRANSFER: + { + app_usbd_ep_conf_t const * p_ep_conf = + app_usbd_ep_conf_access(p_event->drv_evt.data.eptransfer.ep); + ASSERT(NULL != p_ep_conf->p_cinst); + ASSERT(NULL != p_ep_conf->event_handler); + + if (NRF_SUCCESS != p_ep_conf->event_handler(p_ep_conf->p_cinst, + (app_usbd_complex_evt_t const *)p_event)) + { + /* If error returned, every bulk/interrupt endpoint would be stalled */ + if (!(0 == NRF_USBD_EP_NR_GET(p_event->drv_evt.data.eptransfer.ep) || + NRF_USBD_EPISO_CHECK(p_event->drv_evt.data.eptransfer.ep))) + { + nrf_drv_usbd_ep_stall(p_event->drv_evt.data.eptransfer.ep); + } + } + break; + } + + default: + ASSERT(0); + break; + } +} + + +#if (APP_USBD_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) +bool app_usbd_event_queue_process(void) +{ + nrf_atfifo_item_get_t cx; + app_usbd_internal_evt_t const * p_event_item = nrf_atfifo_item_get(m_event_queue, &cx); + if (NULL != p_event_item) + { + app_usbd_event_execute(p_event_item); + UNUSED_RETURN_VALUE(nrf_atfifo_item_free(m_event_queue, &cx)); + return true; + } + else + { + return false; + } +} +#endif + + +ret_code_t app_usbd_class_append(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != p_cinst->p_class_methods); + ASSERT(NULL != p_cinst->p_class_methods->event_handler); + ASSERT(NULL == app_usbd_class_data_access(p_cinst)->p_next); + + /* This should be only called if USBD is disabled + * We simply assume that USBD is enabled if its interrupts are */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + /* Check if all required endpoints are available + * Checking is splitted from setting to avoid situation that anything + * is modified and then operation finishes with error */ + uint8_t iface_idx; + app_usbd_class_iface_conf_t const * p_iface; + + iface_idx = 0; + while (NULL != (p_iface = app_usbd_class_iface_get(p_cinst, iface_idx++))) + { + uint8_t ep_idx = 0; + app_usbd_class_ep_conf_t const * p_ep; + while (NULL != (p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++))) + { + if (NULL != app_usbd_ep_instance_get(app_usbd_class_ep_address_get(p_ep))) + { + return NRF_ERROR_BUSY; + } + } + } + + /* Connecting all required endpoints */ + iface_idx = 0; + while (NULL != (p_iface = app_usbd_class_iface_get(p_cinst, iface_idx++))) + { + uint8_t ep_idx = 0; + app_usbd_class_ep_conf_t const * p_ep; + while (NULL != (p_ep = app_usbd_class_iface_ep_get(p_iface, ep_idx++))) + { + app_usbd_ep_instance_set(app_usbd_class_ep_address_get(p_ep), p_cinst); + } + } + + /* Adding pointer to this instance to the end of the chain */ + app_usbd_class_inst_t const * * pp_last = &m_p_first_cinst; + while (NULL != (*pp_last)) + { + ASSERT((*pp_last) != p_cinst); + pp_last = &(app_usbd_class_data_access(*pp_last)->p_next); + } + (*pp_last) = p_cinst; + + /* Successfully attached */ + const app_usbd_evt_t evt_data = {.type = APP_USBD_EVT_INST_APPEND }; + return class_event_handler(p_cinst, (app_usbd_complex_evt_t const *)(&evt_data)); +} + + +ret_code_t app_usbd_class_remove(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != p_cinst->p_class_methods); + ASSERT(NULL != p_cinst->p_class_methods->event_handler); + /** This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + ret_code_t ret; + /* Remove this class from the chain */ + app_usbd_class_inst_t const * * pp_last = &m_p_first_cinst; + while (NULL != (*pp_last)) + { + if ((*pp_last) == p_cinst) + { + /* Inform class instance that removing process is going to be started */ + const app_usbd_evt_t evt_data = { + .type = APP_USBD_EVT_INST_REMOVE + }; + ret = class_event_handler(p_cinst, (app_usbd_complex_evt_t const *)(&evt_data)); + if (ret != NRF_SUCCESS) + { + return ret; + } + + /* Breaking chain */ + (*pp_last) = (app_usbd_class_data_access(p_cinst)->p_next); + app_usbd_class_data_access(p_cinst)->p_next = NULL; + + /* Disconnecting endpoints */ + uint8_t ep_idx; + for (ep_idx = 0; ep_idx < NRF_USBD_EPIN_CNT; ++ep_idx) + { + nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPIN(ep_idx); + if (app_usbd_ep_instance_get(ep) == p_cinst) + { + app_usbd_ep_instance_set(ep, NULL); + } + } + for (ep_idx = 0; ep_idx < NRF_USBD_EPOUT_CNT; ++ep_idx) + { + nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPOUT(ep_idx); + if (app_usbd_ep_instance_get(ep) == p_cinst) + { + app_usbd_ep_instance_set(ep, NULL); + } + } + + return NRF_SUCCESS; + } + pp_last = &(app_usbd_class_data_access(*pp_last)->p_next); + } + + return NRF_ERROR_NOT_FOUND; +} + + +ret_code_t app_usbd_class_remove_all(void) +{ + ret_code_t ret = NRF_SUCCESS; + while (NULL != m_p_first_cinst) + { + ret = app_usbd_class_remove(m_p_first_cinst); + if (ret != NRF_SUCCESS) + { + break; + } + } + + return ret; +} + + +ret_code_t app_usbd_ep_handler_set(app_usbd_class_inst_t const * const p_cinst, + nrf_drv_usbd_ep_t ep, + app_usbd_ep_event_handler_t handler) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != handler); + /** This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + if (p_cinst != app_usbd_ep_instance_get(ep)) + { + return NRF_ERROR_INVALID_PARAM; + } + + (app_usbd_ep_conf_access(ep))->event_handler = handler; + return NRF_SUCCESS; +} + + +ret_code_t app_usbd_class_sof_register(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + ASSERT(NULL != p_cinst->p_class_methods); + ASSERT(NULL != p_cinst->p_class_methods->event_handler); + /** This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + /* Next SOF event requiring instance have to be null now */ + ASSERT(NULL == (app_usbd_class_data_access(p_cinst)->p_sof_next)); + + /* Adding pointer to this instance to the end of the chain */ + app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_cinst; + while (NULL != (*pp_last)) + { + + ASSERT((*pp_last) != p_cinst); + pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); + } + (*pp_last) = p_cinst; + + return NRF_SUCCESS; +} + + +ret_code_t app_usbd_class_sof_unregister(app_usbd_class_inst_t const * p_cinst) +{ + ASSERT(NULL != p_cinst); + /** This function should be only called if USBD is disabled */ + ASSERT(!nrf_drv_usbd_is_enabled() && nrf_drv_usbd_is_initialized()); + + app_usbd_class_inst_t const * * pp_last = &m_p_first_sof_cinst; + while (NULL != (*pp_last)) + { + if ((*pp_last) == p_cinst) + { + /* Breaking chain */ + (*pp_last) = (app_usbd_class_data_access(p_cinst)->p_sof_next); + app_usbd_class_data_access(p_cinst)->p_sof_next = NULL; + + return NRF_SUCCESS; + } + pp_last = &(app_usbd_class_data_access(*pp_last)->p_sof_next); + } + return NRF_ERROR_NOT_FOUND; +} + + +ret_code_t app_usbd_class_rwu_register(app_usbd_class_inst_t const * const p_inst) +{ + ASSERT(p_inst != NULL); + ++m_rwu_registered_counter; + /*Overflow check*/ + ASSERT(m_rwu_registered_counter != 0); + + return NRF_SUCCESS; +} + + +ret_code_t app_usbd_class_rwu_unregister(app_usbd_class_inst_t const * const p_inst) +{ + ASSERT(p_inst != NULL); + /* Usage validation. If counter is 0 unregister is not possible.*/ + ASSERT(m_rwu_registered_counter != 0); + --m_rwu_registered_counter; + + return NRF_SUCCESS; +} + +bool app_usbd_class_rwu_enabled_check(void) +{ + return (m_rwu_registered_counter != 0); +} + +ret_code_t app_usbd_interface_std_req_handle(app_usbd_setup_evt_t const * p_setup_ev) +{ + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_GET_STATUS: + { + size_t tx_size; + uint16_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size); + + p_tx_buff[0] = 0; + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint16_t)); + } + default: + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +ret_code_t app_usbd_endpoint_std_req_handle(app_usbd_setup_evt_t const * p_setup_ev) +{ + nrf_drv_usbd_ep_t ep_addr = (nrf_drv_usbd_ep_t)(p_setup_ev->setup.wIndex.lb); + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_GET_STATUS: + { + size_t tx_size; + uint16_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size); + + p_tx_buff[0] = nrf_drv_usbd_ep_stall_check(ep_addr) ? 1 : 0; + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint16_t)); + } + case APP_USBD_SETUP_STDREQ_SET_FEATURE: + { + if (p_setup_ev->setup.wValue.w != APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + nrf_drv_usbd_ep_stall(ep_addr); + return NRF_SUCCESS; + } + case APP_USBD_SETUP_STDREQ_CLEAR_FEATURE: + { + if (p_setup_ev->setup.wValue.w != APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + if (nrf_usbd_dtoggle_get(ep_addr) != NRF_USBD_DTOGGLE_DATA0) + { + nrf_usbd_dtoggle_set(ep_addr, NRF_USBD_DTOGGLE_DATA0); + } + + if (NRF_USBD_EPISO_CHECK(ep_addr) == 0) + { + nrf_drv_usbd_ep_stall_clear(ep_addr); + } + + return NRF_SUCCESS; + } + default: + return NRF_ERROR_NOT_SUPPORTED; + } +} + +ret_code_t app_usbd_req_std_set_interface(app_usbd_class_inst_t const * const p_cinst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + uint8_t iface_count = app_usbd_class_iface_count_get(p_cinst); + + app_usbd_class_iface_conf_t const * p_iface = NULL; + for (uint8_t j = 0; j < iface_count; ++j) + { + p_iface = app_usbd_class_iface_get(p_cinst, j); + if (p_iface->number == p_setup_ev->setup.wIndex.lb) + { + break; + } + } + + if (p_iface == NULL) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + uint8_t ep_count = app_usbd_class_iface_ep_count_get(p_iface); + + for (uint8_t j = 0; j < ep_count; ++j) + { + /*Clear stall for every endpoint*/ + app_usbd_class_ep_conf_t const * p_ep = app_usbd_class_iface_ep_get(p_iface, j); + + if (nrf_usbd_dtoggle_get(p_ep->address) != NRF_USBD_DTOGGLE_DATA0) + { + nrf_usbd_dtoggle_set(p_ep->address, NRF_USBD_DTOGGLE_DATA0); + } + + if (NRF_USBD_EPISO_CHECK(p_ep->address) == 0) + { + nrf_drv_usbd_ep_stall_clear(p_ep->address); + } + + } + + return NRF_SUCCESS; +} + +app_usbd_class_inst_t const * app_usbd_class_first_get(void) +{ + return m_p_first_cinst; +} + +app_usbd_class_inst_t const * app_usbd_class_sof_first_get(void) +{ + return m_p_first_sof_cinst; +} + +ret_code_t app_usbd_iface_call(uint8_t iface, app_usbd_complex_evt_t const * const p_event) +{ + ASSERT(NULL != m_p_first_cinst); + /*Iterate over classes*/ + app_usbd_class_inst_t const * p_inst = app_usbd_class_first_get(); + while (p_inst != NULL) + { + uint8_t iface_count = app_usbd_class_iface_count_get(p_inst); + /*Iterate over interfaces*/ + for (uint8_t i = 0; i < iface_count; ++i) + { + app_usbd_class_iface_conf_t const * p_iface; + p_iface = app_usbd_class_iface_get(p_inst, i); + if (app_usbd_class_iface_number_get(p_iface) == iface) + { + return class_event_handler(p_inst, p_event); + } + } + p_inst = app_usbd_class_next_get(p_inst); + } + + return NRF_ERROR_INVALID_ADDR; +} + +ret_code_t app_usbd_ep_call(nrf_drv_usbd_ep_t ep, app_usbd_complex_evt_t const * const p_event) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_ep_conf_access(ep)->p_cinst; + if (p_inst != NULL) + { + return class_event_handler(p_inst, p_event); + } + + return NRF_ERROR_INVALID_ADDR; +} + +void app_usbd_all_call(app_usbd_complex_evt_t const * const p_event) +{ + app_usbd_class_inst_t const * p_inst; + for (p_inst = app_usbd_class_first_get(); NULL != p_inst; + p_inst = app_usbd_class_next_get(p_inst)) + { + UNUSED_RETURN_VALUE(class_event_handler(p_inst, p_event)); + } +} + +ret_code_t app_usbd_all_until_served_call(app_usbd_complex_evt_t const * const p_event) +{ + app_usbd_class_inst_t const * p_inst; + ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; + /* Try to process via every instance */ + for (p_inst = app_usbd_class_first_get(); NULL != p_inst; + p_inst = app_usbd_class_next_get(p_inst)) + { + + ret = class_event_handler(p_inst, p_event); + if (NRF_ERROR_NOT_SUPPORTED != ret) + { + /* Processing finished */ + break; + } + } + + return ret; +} + +#endif // APP_USBD_ENABLED diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd.h new file mode 100644 index 000000000..25c68cba2 --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd.h @@ -0,0 +1,563 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_H__ +#define APP_USBD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_drv_usbd.h" +#include "app_usbd_types.h" +#include "app_usbd_class_base.h" + +/** + * @defgroup app_usbd USB Device high level library + * @ingroup app_common + * + * @brief @tagAPI52840 Module for easy support for any USB device configuration. + * + * This module manages class instances that would create the USB device, + * manages endpoints and interfaces transactions. + * @{ + */ + +/** + * @brief Configuration passed to @ref app_usbd_init. + */ +typedef struct { +#if (!(APP_USBD_EVENT_QUEUE_ENABLE)) || defined(__SDK_DOXYGEN__) + /** + * @brief User defined event handler. + * + * This function is called on every event from the interrupt. + * It is prepared for external user function that would queue events to be processed + * from the main context. + * It should be used with operating systems with its own implementation of the queue. + * + * @param p_event The event structure pointer. + * + * @note This field is available only when USB internal queue is disabled + * (see @ref APP_USBD_EVENT_QUEUE_ENABLE). + */ + void (*ev_handler)(app_usbd_internal_evt_t const * const p_event); +#endif + +#if (APP_USBD_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) + /** + * @brief User defined event handler. + * + * This function is called on every event from the interrupt. + * + * @param p_event The event structure pointer. + * @param queued The event is visible in the queue. + * If queue conflict is detected the event might not be accessible inside queue + * until all write operations finish. + * See @ref nrf_atfifo for more details. + * + * @note This field is available only when USBD internal queue is configured + * (see @ref APP_USBD_EVENT_QUEUE_ENABLE). + * + * @note If is set to NULL no event would be called from interrupt. + * @note This function is called before event is processed. + * It means that if the event type is @ref APP_USBD_EVT_DRV_SETUP, + * there would not be setup field present in the event structure. + */ + void (*ev_isr_handler)(app_usbd_internal_evt_t const * const p_event, bool queued); +#endif + + /** + * @brief User defined event processor + * + * This function is called while state event is processed. + * + * * @note This field is available only when USBD internal queue is configured + * (see @ref APP_USBD_EVENT_QUEUE_ENABLE). + * + * @param event Event type. + * Only following events are sent into this function: + * - APP_USBD_EVT_DRV_SOF + * - APP_USBD_EVT_DRV_RESET - Note that it also exits suspend + * - APP_USBD_EVT_DRV_SUSPEND + * - APP_USBD_EVT_DRV_RESUME - It is also generated when remote wakeup is generated + * - APP_USBD_EVT_START + * - APP_USBD_EVT_STOP + */ + void (*ev_state_proc)(app_usbd_event_type_t event); + + /** + * @brief SOF processing required by the user event processing + * + * This flag would enable SOF processing for the user events regardless of the fact if any + * of the implemented class requires SOF event. + * + * @note SOF event would be enabled anyway if any of the appended class requires SOF processing. + */ + bool enable_sof; +} app_usbd_config_t; + +/** + * @brief USB library initialization. + * + * Call this function before any configuration or class attachment. + * USBD peripheral would be ready to accept commands, and library would be ready, + * but it would not be connected to the bus. + * Call @ref app_usbd_enable to enable USBD communication with the host. + * + * @param p_config Configuration. NULL pointer might be passed here and default + * configuration will be applied then. + */ +ret_code_t app_usbd_init(app_usbd_config_t const * p_config); + +/** + * @brief USB library un-initialization + * + * @note Currently not supported + */ +ret_code_t app_usbd_uninit(void); + +/** + * @brief Enable USBD + * + * USBD is enabled. + * Since now the high frequency clock may be requested when USB RESET would be detected. + */ +void app_usbd_enable(void); + +/** + * @brief Disable USBD + * + * Disabled USDB peripheral cannot be accessed but also stops requesting + * High Frequency clock and releases power regulator. + * + * @note This function cannot be called when USB is started. Stop it first. + */ +void app_usbd_disable(void); + +/** + * @brief Request USBD to start + * + * The function sends start request to the event queue. + * If the queue is enabled (@ref APP_USBD_EVENT_QUEUE_ENABLE) it would be processed + * when the queue is processed. + * If queue is disabled it would be processed immediately inside this function. + * It means that if queue is disabled this function cannot be called from interrupt with priority + * higher than USB interrupt. + * + * When start is processed it would: + * 1. Start library. + * 2. Enable interrupts. + * 3. Enable USB pull-ups. + * + * @note + * In some specific circumstances the library can be left not started and this function would + * silently exit. + * This may happen if some glitches appears on USB power line or if the plug was disconnected before + * whole starting process finishes. + * User would get the event from POWER peripheral then. + * Also no @ref APP_USBD_EVT_STARTED event would be generated to the classes and user event handler. + * For the safe code it is recommended to wait for @ref APP_USBD_EVT_STARTED event if anything + * has to be initialized after USB driver is started (just before enabling the interrupts). + * If library is properly started the @ref APP_USBD_EVT_STARTED event passed to the user handler + * from this function body. + */ +void app_usbd_start(void); + +/** + * @brief Stop USB to work + * + * The function sends stop request to the event queue. + * If the queue is enabled (@ref APP_USBD_EVENT_QUEUE_ENABLE) it would be processed + * when the queue is processed. + * If queue is disabled it would be processed immediately inside this function. + * It means that if queue is disabled this function cannot be called from interrupt with priority + * higher than USB interrupt. + * + * When the event is processed interrupts and USB pull-ups are disabled. + * The peripheral itself is left enabled so it can be programmed, + * but a HOST sees it as a peripheral disconnection. + * + * @note + * If the library is not started when this function is called it exits silently - also + * no @ref APP_USBD_EVT_STOPPED is generated. + */ +void app_usbd_stop(void); + +/** + * @brief Request library to suspend + * + * This function send suspend request to the event queue. + * + * @note This function should only be called after @ref APP_USBD_EVT_DRV_SUSPEND os received. + * Internal suspend request processing would give no effect if the bus is not in suspend state. + */ +void app_usbd_suspend_req(void); + +/** + * @brief Request library to wake-up + * + * This function send wakeup request to the event queue. + * + * @note Calling this function does not mean that peripheral is active - the wakeup request is sent + * into message queue and needs to be processed. + * + * @retval true Wakeup generation has been started. + * @retval false No wakeup would be generated becouse it is disabled by the host. + */ +bool app_usbd_wakeup_req(void); + +/** + * @brief USBD event processor + * + * Function to be called on each event to be processed by the library. + */ +void app_usbd_event_execute(app_usbd_internal_evt_t const * const p_event); + + +#if (APP_USBD_EVENT_QUEUE_ENABLE) || defined(__SDK_DOXYGEN__) +/** + * @brief Function that process events from the queue + * + * @note This function calls @ref app_usbd_event_execute internally. + * + * @retval true Event was processed + * @retval false The event queue is empty + */ +bool app_usbd_event_queue_process(void); +#endif + +/** + * @brief Add class instance + * + * This function connects given instance into internal class instance chain and + * into all required endpoints. + * The instance event handler would be connected into endpoint by default, + * but this can be overwritten by @ref app_usbd_ep_handler_set. + * + * After successful attachment @ref APP_USBD_EVT_INST_APPEND would be passed to class instance. + * + * @note This function can only be called after USBD library is initialized but still disabled. + * Assertion would be generated otherwise. + * + * @param[in,out] p_cinst Instance to connect. Chain data would be written into writable instance data. + */ +ret_code_t app_usbd_class_append(app_usbd_class_inst_t const * p_cinst); + +/** + * @brief Remove class instance + * + * Instance is removed from instance chain. + * Instance and event handlers are removed also from endpoints. + * Endpoints used by by the class instance are left disabled. + * + * @note This function can only be called after USBD library is initialized but still disabled. + * Assertion would be generated otherwise. + * + * @param p_cinst Instance pointer to remove. + * + * @retval NRF_SUCCESS Instance successfully removed. + * @retval NRF_ERROR_NOT_FOUND Instance not found in the instance chain. + */ +ret_code_t app_usbd_class_remove(app_usbd_class_inst_t const * p_cinst); + +/** + * @brief Remove all class instances + * + * This function basically calls @ref app_usbd_class_remove + * on instances chain as long as there is any element left. + * + * @note This function can only be called after USBD library is initialized but still disabled. + * Assertion would be generated otherwise. + * + * @sa app_usbd_class_remove + * + * @return Is should always return @ref NRF_SUCCESS. + * Any error value returned would mean there is an error inside the library. + */ +ret_code_t app_usbd_class_remove_all(void); + +/** + * @brief Change endpoint handler + * + * This function may be called for the endpoint only if the class instance is + * already properly attached by the @ref app_usbd_class_append function. + * + * The endpoint event handler function can be only overwritten by the class instance + * that was connected into the endpoint. + * + * @note This function can only be called after USBD library is initialized but still disabled. + * Assertion would be generated otherwise. + * + * @param[in] p_cinst Instance of a class that wish to set new event handler. + * It has to match currently configured instance for the selected endpoint. + * In other situation error would be returned. + * @param[in] ep Endpoint address to configure. + * @param[in] handler Event handler function to set. + * + * @retval NRF_SUCCESS New handler successfully set + * @retval NRF_ERROR_INVALID_PARAM p_cinst is not the same as currently set for the endpoint + */ +ret_code_t app_usbd_ep_handler_set(app_usbd_class_inst_t const * p_cinst, + nrf_drv_usbd_ep_t ep, + app_usbd_ep_event_handler_t handler); + +/** + * @brief Register class instance as the one that requires SOF events + * + * This function should be called in reaction on APP_USBD_EVT_INST_APPEND event. + * Connect the class instance to the list of instances that requires SOF processing. + * If none of the appended instances requires SOF event - it is disabled. + * + * @param p_cinst Instance that requires SOF event. + * + * @retval NRF_SUCCESS Instance linked into SOF processing list. + * + * @sa app_usbd_class_sof_unregister + */ +ret_code_t app_usbd_class_sof_register(app_usbd_class_inst_t const * p_cinst); + +/** + * @brief Unregister class instance from SOF processing instances list + * + * Every class that calls @ref app_usbd_class_sof_register have to call also unregistering function + * in reaction to @ref APP_USBD_EVT_INST_REMOVE event. + * + * @param p_cinst Instance to be unregistered from SOF event processing list. + * + * @retval NRF_SUCCESS Instance linked into SOF processing list. + * @retval NRF_ERROR_NOT_FOUND Instance not found in the SOF processing list. + * + * @sa app_usbd_class_sof_register + */ +ret_code_t app_usbd_class_sof_unregister(app_usbd_class_inst_t const * p_cinst); + +/** + * @brief Register class on remote wake-up feature + * + * @param[in] p_inst Instance of the class + * + * @retval NRF_SUCCESS Instance that requires remote wake-up registered + */ +ret_code_t app_usbd_class_rwu_register(app_usbd_class_inst_t const * const p_inst); + +/** + * @brief Unregister class from remote wake-up feature + * + * @param[in] p_inst Instance of the class + * + * @retval NRF_SUCCESS Instance that requires remote wake-up removed + */ +ret_code_t app_usbd_class_rwu_unregister(app_usbd_class_inst_t const * const p_inst); + +/** + * @brief Check if there is any class with remote wakeup + * + * The function checks internal registered class with remote wakeup counter. + * + * @sa app_usbd_class_rwu_register, app_usbd_class_rwu_unregister + * + * @retval true The remote wakeup functionality is required by some class instance + * @retval false There is no class instance that requires wakeup functionality + */ +bool app_usbd_class_rwu_enabled_check(void); + +/** + * @brief Function finds a given descriptor type in class descriptors payload + * + * @param[in] p_cinst Instance of a class + * @param[in] desc_type Descriptor type (@ref APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR) + * @param[in] desc_index Descriptor index (@ref APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR) + * @param[out] p_desc_len Descriptor length + * + * @return Address of the descriptor (NULL if not found) + * */ +const void * app_usbd_class_descriptor_find(app_usbd_class_inst_t const * const p_cinst, + uint8_t desc_type, + uint8_t desc_index, + size_t * p_desc_len); + +/** + * @brief Standard interface request handle + * + * @param[in] p_setup_ev Setup event + * + * @return Standard error code + * */ +ret_code_t app_usbd_interface_std_req_handle(app_usbd_setup_evt_t const * p_setup_ev); + +/** + * @brief Standard endpoint request handle + * + * @param[in] p_setup_ev Setup event + * + * @return Standard error code + * */ +ret_code_t app_usbd_endpoint_std_req_handle(app_usbd_setup_evt_t const * p_setup_ev); + + +/** + * @brief Standard interface set request handle + * + * @param[in] p_cinst Instance of a class + * @param[in] p_setup_ev Setup event + * + * @return Standard error code + * */ +ret_code_t app_usbd_req_std_set_interface(app_usbd_class_inst_t const * const p_cinst, + app_usbd_setup_evt_t const * const p_setup_ev); + +/** + * @name Iterate through classes lists + * + * Functions that helps to iterate through internally chained classes. + * @{ + */ + /** + * @brief Get first class instance in the list + * + * Get first instance from the list of active class instances. + * That instance may be used then in @ref app_usbd_class_next_get function. + * + * @return First instance in the list or NULL if there are no instances available. + */ + app_usbd_class_inst_t const * app_usbd_class_first_get(void); + + /** + * @brief Get next instance in the list + * + * Get the next instance from the list of active instances. + * Used to iterate through all instances. + * + * @param[in] p_cinst The current instance from with next one is required. + * + * @return Next instance to the given one or NULL if there is no more instances in the list. + */ + static inline app_usbd_class_inst_t const * app_usbd_class_next_get( + app_usbd_class_inst_t const * const p_cinst) + { + ASSERT(NULL != p_cinst); + return app_usbd_class_data_access(p_cinst)->p_next; + } + + /** + * @brief Get first instance in SOF list + * + * Start iteration through the list of instances that requires SOF event processing. + * + * @return First instance in the list or NULL if the list is empty + * + * @sa app_usbd_class_first_get + */ + app_usbd_class_inst_t const * app_usbd_class_sof_first_get(void); + + /** + * @brief Get next instance in the SOF list + * + * Get the next instance from the list of instances requiring SOF event processing. + * Used to iterate through all SOF instances. + * + * @param p_cinst The current instance from with next one is required. + * + * @return Next instance to the given one or NULL if there is no more instances in the list. + */ + static inline app_usbd_class_inst_t const * app_usbd_class_sof_next_get( + app_usbd_class_inst_t const * const p_cinst) + { + ASSERT(NULL != p_cinst); + return app_usbd_class_data_access(p_cinst)->p_sof_next; + } +/** @} */ + +/** + * @name Communicate with interfaces, endpoints and instances inside usbd library + * + * @{ + */ + + /** + * @brief Call interface event handler + * + * Call event handler for selected interface. + * @param[in] iface Target interface number + * @param[in] p_event Event structure to send + * + * @return Operation status + */ + ret_code_t app_usbd_iface_call(uint8_t iface, app_usbd_complex_evt_t const * const p_event); + + /** + * @brief Call endpoint event handler + * + * Call event handler for the selected endpoint. + * @param[in] ep Endpoint number + * @param[in] p_event Event structure to send + * + * @return Operation status + */ + ret_code_t app_usbd_ep_call(nrf_drv_usbd_ep_t ep, app_usbd_complex_evt_t const * const p_event); + + /** + * @brief Auxiliary function that process event by every instance in the list + * + * This function ignores the result of called handler. + * + * @param p_event Event to pass to every instance + */ + void app_usbd_all_call(app_usbd_complex_evt_t const * const p_event); + + /** + * @brief Call interface event handlers and stop when served + * + * Call event handlers from instances as long as we get result different than @ref NRF_ERROR_NOT_SUPPORTED + * @param[in] p_event Event structure to send + * + * @return Operation status or @ref NRF_ERROR_NOT_SUPPORTED if none of instances in the list can support given event. + */ + ret_code_t app_usbd_all_until_served_call(app_usbd_complex_evt_t const * const p_event); +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_class_base.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_class_base.h new file mode 100644 index 000000000..3f4de3d4f --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_class_base.h @@ -0,0 +1,841 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_CLASS_BASE_H__ +#define APP_USBD_CLASS_BASE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "app_usbd_types.h" +#include "nrf_drv_usbd.h" +#include "nrf_assert.h" +#include "app_util.h" + +/** + * @defgroup app_usbd_class_base USBD Class Base module + * @ingroup app_usbd + * + * @brief @tagAPI52840 The base for any class instance is defined in this module. + * + * @details Any class instance must start from base class instance structure. + * This makes them compatible with USBD library independently of the + * implementation details. + * @{ + */ + +/** + * @brief Endpoint configuration + */ +typedef struct +{ + nrf_drv_usbd_ep_t address; //!< Endpoint address +} app_usbd_class_ep_conf_t; + +/** + * @brief Interface configuration + */ +typedef struct +{ + uint8_t number; //!< Interface number + uint8_t ep_cnt; //!< Endpoint number + uint8_t ep_offset; //!< Offset of the first endpoint + /**< Offset in bytes of the first endpoint. + * The offset is calculated from the address of this interface structure + */ +} app_usbd_class_iface_conf_t; + +/** + * @brief Instance variable data + */ +typedef struct +{ + app_usbd_class_inst_t const * p_next; //!< Pointer to the next instance + app_usbd_class_inst_t const * p_sof_next; //!< Pointer to the next SOF event requiring instance +} app_usbd_class_data_t; + + +/** + * @brief Class interface function set + * */ +typedef struct { + /** + * @brief Instance callback function + * + * The function used by every class instance. + * @param[in,out] p_inst Instance of the class + * @param[in] p_event Event to process + * + * @note If given event is not supported by class, return @ref NRF_ERROR_NOT_SUPPORTED + */ + ret_code_t (* event_handler)(app_usbd_class_inst_t const * const p_inst, + app_usbd_complex_evt_t const * const p_event); + + /** + * @brief Instance get descriptors + * + * The function used by every class instance. + * @param[in,out] p_inst Instance of the class + * @param[out] p_size Descriptor size + * + * @return Class descriptors start address + */ + const void * (* get_descriptors)(app_usbd_class_inst_t const * const p_inst, + size_t * p_size); +} app_usbd_class_methods_t; + +/** + * @brief The instance structure itself + * + * The structure of base class instance + */ +struct app_usbd_class_inst_s +{ + app_usbd_class_data_t * p_data; //!< Pointer to non-constant data + app_usbd_class_methods_t const * p_class_methods; //!< Class interface methods + struct + { + uint8_t cnt; //!< Number of defined interfaces + uint8_t config[]; //!< Interface configuration data followed by endpoint data + } iface; //!< Interface structure +}; + + +/** + * @brief Get total number of interfaces + * + * + */ +static inline uint8_t app_usbd_class_iface_count_get(app_usbd_class_inst_t const * const p_inst) +{ + return p_inst->iface.cnt; +} + +/** + * @brief Interface accessing function + * + * Get interface pointer. + * Interfaces creates continuous array in the memory so it is possible to get + * interface with index 0 and the just iterate to the next one. + * + * @param p_inst Pointer to the class instance + * @param iface_idx Index of the instance to get. + * This is not the interface identifier. + * Technically it is the index of the interface in the class description array. + * @return Pointer to the interface configuration parameters or NULL if given index is out of interface scope for given class. + */ +static inline app_usbd_class_iface_conf_t const * app_usbd_class_iface_get( + app_usbd_class_inst_t const * const p_inst, + uint8_t iface_idx) +{ + ASSERT(NULL != p_inst); + if (iface_idx >= (app_usbd_class_iface_count_get(p_inst))) + { + return NULL; + } + + app_usbd_class_iface_conf_t const * p_interface = + (app_usbd_class_iface_conf_t const * )(p_inst->iface.config); + return &(p_interface[iface_idx]); +} + +/** + * @brief Get interface number + * + * @param p_iface Pointer to interface structure + * + * @return Interface number from interface configuration structure + */ +static inline uint8_t app_usbd_class_iface_number_get( + app_usbd_class_iface_conf_t const * const p_iface) +{ + return p_iface->number; +} + +/** + * @brief Get number of endpoints in interface + * + * @param p_iface Pointer to interface structure + * + * @return Number of endpoints used by given interface + */ +static inline uint8_t app_usbd_class_iface_ep_count_get( + app_usbd_class_iface_conf_t const * const p_iface) +{ + return p_iface->ep_cnt; +} + +/** + * @brief Interface Endpoint accessing function + * + * @param p_iface Interface configuration pointer + * @param ep_idx Endpoint index + * + * @return Endpoint information structure pointer or NULL if given index is outside of endpoints for selected interface. + * + * @sa app_usbd_class_iface_get + */ +static inline app_usbd_class_ep_conf_t const * app_usbd_class_iface_ep_get( + app_usbd_class_iface_conf_t const * const p_iface, + uint8_t ep_idx) +{ + ASSERT(NULL != p_iface); + if (ep_idx >= p_iface->ep_cnt) + { + return NULL; + } + + app_usbd_class_ep_conf_t const * p_ep = + (app_usbd_class_ep_conf_t const * )(((uint8_t const *)p_iface) + p_iface->ep_offset); + return &(p_ep[ep_idx]); +} + +/** + * @brief Translate endpoint address to class index + * + * @param p_iface Interface configuration pointer + * @param ep_address Endpoint address + * + * @return Endpoint index or number of endpoints if not found + * + */ +static inline uint8_t app_usbd_class_iface_ep_idx_get( + app_usbd_class_iface_conf_t const * const p_iface, + nrf_drv_usbd_ep_t ep_address) +{ + ASSERT(NULL != p_iface); + app_usbd_class_ep_conf_t const * p_ep = + (app_usbd_class_ep_conf_t const * )(((uint8_t const *)p_iface) + p_iface->ep_offset); + + uint8_t i; + for (i = 0; i < p_iface->ep_cnt; ++i) + { + if (ep_address == p_ep[i].address) + { + break; + } + } + + return i; +} + +/** + * @brief Get the selected endpoint address + * + * @param p_ep Endpoint configuration structure + * + * @return Endpoint address + */ +static inline nrf_drv_usbd_ep_t app_usbd_class_ep_address_get(app_usbd_class_ep_conf_t const * p_ep) +{ + return (nrf_drv_usbd_ep_t)p_ep->address; +} + +/** + * @brief Get the pointer to the writable instance data + * + * @param p_inst Instance pointer + * @return Pointer to writable instance data + */ +static inline app_usbd_class_data_t * app_usbd_class_data_access( + app_usbd_class_inst_t const * const p_inst) +{ + return p_inst->p_data; +} + +/** + * @name Internal macros for argument mapping + * + * Functions to be used as a mapping macro for @ref MACRO_MAP, @ref MACRO_MAP_FOR or @ref MACRO_MAP_FOR_PARAM + * @{ + */ + /** + * @brief Count the number of endpoints in given configuration + * + * Config should be given as a interface configuration in a brackets: + * @code + * (interface_nr, ep1, ep2, ep3) + * @endcode + * Number of endpoints may vary from 0 to a few (technically up to 16, but it seems not to make sense to use more than 4). + * Interface number is always present. + * + * @param iface_config Single interface configuration (in brackets) + * + * @return Number of endpoints in interface. This is computed value - can be used by compiler but not by preprocessor. + */ + #define APP_USBD_CLASS_CONF_IFACE_EP_COUNT_(iface_config) \ + (NUM_VA_ARGS(BRACKET_EXTRACT(iface_config)) - 1) + + /** + * @brief Adds the number of endpoints in given config to the current value + * + * This is basically @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ with plus sign added. + * + * @param iface_config See parameters documentation in @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ + * + * @return Plus sign followed by number of endpoints in interface. + * + * @sa APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ + */ + #define APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_(iface_config) \ + + APP_USBD_CLASS_CONF_IFACE_EP_COUNT_(iface_config) + + /** + * @brief Create variable for endpoint + */ + + /** + * @brief Extract endpoints given interface configuration + * + * This macro gets single endpoint configuration and extracts all the endpoints. + * It also adds comma on the end of extracted endpoints. + * This way when this macro is called few times it generates nice list of all endpoints + * that may be used to array initialization. + * + * @param iface_config Single interface configuration in brackets. + * The format should be similar like described in @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_. + */ + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_(iface_config) \ + CONCAT_2(APP_USBD_CLASS_IFACE_EP_EXTRACT_, \ + NUM_VA_ARGS_IS_MORE_THAN_1(BRACKET_EXTRACT(iface_config))) \ + (BRACKET_EXTRACT(iface_config)) + + /** + * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_EP_EXTRACT_ + * + * This macro is called when interface has no endpoints + */ + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_0(iface_nr) + + /** + * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_EP_EXTRACT_ + * + * This macro is called when interface has at least one endpoint + */ + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1(...) \ + APP_USBD_CLASS_IFACE_EP_EXTRACT_1_(__VA_ARGS__) + + #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1_(iface_nr, ...) \ + MACRO_MAP_REC(PARAM_CBRACE, __VA_ARGS__) + + /** + * @brief Generate configuration for single interface + * + * This macro extract configuration for single interface. + * The configuration is inside curly brackets and comma is added on the end. + * This mean it can be directly used to init array of interface configurations. + * + * @param iface_config Single interface configuration + * @param N Currently processed configuration + * @param iface_configs All interfaces configuration in brackets + */ + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_(iface_config, N, iface_configs) \ + CONCAT_2(APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_, \ + NUM_VA_ARGS_IS_MORE_THAN_1(BRACKET_EXTRACT(iface_config))) \ + (N, iface_configs, BRACKET_EXTRACT(iface_config)) + + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_x(iface_config, N, iface_configs) \ + [N] = !!!iface_config!!! + /** + * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ + * + * This macro is called when interface has no endpoints + */ + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0(N, iface_configs, iface_nr) \ + APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0_(N, iface_configs, iface_nr) + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0_(N, iface_configs, iface_nr) \ + { .number = iface_nr, .ep_cnt = 0, .ep_offset = 0 }, + + /** + * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ + * + * This macro is called when interface has at last one endpoint + */ + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1(N, iface_configs, ...) \ + APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1_(N, iface_configs, __VA_ARGS__) + #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1_(N, iface_configs, iface_nr, ...) \ + { .number = iface_nr, .ep_cnt = NUM_VA_ARGS(__VA_ARGS__), \ + .ep_offset = APP_USBD_CLASS_CONF_TOTAL_EP_COUNT_N(N, iface_configs) * \ + sizeof(app_usbd_class_ep_conf_t) \ + + ((NUM_VA_ARGS(BRACKET_EXTRACT(iface_configs)) - N) * \ + sizeof(app_usbd_class_iface_conf_t)) \ + }, + +/** @} */ + + +/** + * @name Macros that uses mapping macros internally + * + * Auxiliary macros that uses mapping macros to make some calculations or realize other functionality. + * Mapped here for easier unit testing and to hide complex mapping functions calling. + * @{ + */ + +/** + * @brief Count total number of endpoints + * + * @param iface_configs List of interface configurations like explained + * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * + * @return The equation to calculate the number of endpoints by compiler. + */ +#define APP_USBD_CLASS_CONF_TOTAL_EP_COUNT(iface_configs) \ + (0 MACRO_MAP(APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_, BRACKET_EXTRACT(iface_configs))) + +/** + * @brief Count total number of endpoint up-to interface index + * + * The version of @ref APP_USBD_CLASS_CONF_TOTAL_EP_COUNT macro which takes the + * number of interfaces to analyze. + * + * @param N Number of interfaces to analyze + * @param iface_configs List of interface configurations like explained + * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * + * @return The equation to calculate the number of endpoints by compiler. + */ +#define APP_USBD_CLASS_CONF_TOTAL_EP_COUNT_N(N, iface_configs) \ + (0 MACRO_MAP_N(N, APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_, BRACKET_EXTRACT(iface_configs))) + +/** + * @brief Extract configurations for interfaces + * + * This macro extracts the configurations for every interface. + * Basically uses the @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ macro on every + * configuration found. + * + * This should generate interface configuration initialization data + * in comma separated initializers in curly braces. + * + * @param iface_configs List of interface configurations like explained + * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * + * @return Comma separated initialization data for all interfaces. + */ +/*lint -emacro( (40), APP_USBD_CLASS_IFACES_CONFIG_EXTRACT) */ +#define APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(iface_configs) \ + MACRO_MAP_FOR_PARAM(iface_configs, \ + APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_, \ + BRACKET_EXTRACT(iface_configs)) + +/** + * @brief Extract all endpoints + * + * Macro that extracts all endpoints from every interface + * + * @param iface_configs List of interface configurations like explained + * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * + * @return Comma separated list of endpoints + */ +/*lint -emacro( (40), APP_USBD_CLASS_IFACES_EP_EXTRACT) */ +#define APP_USBD_CLASS_IFACES_EP_EXTRACT(iface_configs) \ + MACRO_MAP(APP_USBD_CLASS_IFACE_EP_EXTRACT_, BRACKET_EXTRACT(iface_configs)) + + +/** @} */ + + +/** + * @brief USBD instance of class mnemonic + * + * Macro that generates mnemonic for the name of the structure that describes instance for selected class. + * + * @param type_name The name of the instance without _t postfix + * + * @return The name with the right postfix to create the name for the type for the class. + */ +#define APP_USBD_CLASS_INSTANCE_TYPE(type_name) CONCAT_2(type_name, _t) + +/** + * @brief USBD data for instance class mnemonic + * + * The mnemonic of the variable type that holds writable part of the class instance. + * + * @param type_name The name of the instance without _t postfix + * + * @return The name with the right postfix to create the name for the data type for the class. + */ +#define APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(type_name, _data_t) + +/** + * @brief Declare class specific member of class instance + * + * @param type Type of the attached class configuration. + * + * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF + */ +#define APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC(type) type class_part; + +/** + * @brief Used if there is no class specific configuration + * + * This constant can be used if there is no specific configuration inside created instance + * + * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF + */ +#define APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE + +/** + * @brief Declare class specific member of class data + * + * @param type Type of the attached class data. + * + * @sa APP_USBD_CLASS_DATA_TYPEDEF + */ +#define APP_USBD_CLASS_DATA_SPECIFIC_DEC(type) APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC(type) + +/** + * @brief Used if there is no class specific data + * + * This constant can be used if there is no specific writable data inside created instance + * + * @sa APP_USBD_CLASS_DATA_TYPEDEF + */ +#define APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE + + + + +/** + * @brief Instance structure declaration + * + * The macro that declares a variable type that would be used to store given class instance. + * Class instance stores all the data from @ref app_usbd_class_inst_t and overlaid data for specified class. + * + * The structure of interface configuration data: + * @code + * ( + * (iface1_nr, (ep1, ep2, ep3)), + (iface2_nr), + (iface3_nr, (ep4)) + * ) + * @endcode + * + * @param type_name The name of the instance without _t postfix. + * @param interfaces_configs List of interface configurations like explained above. + * @param class_config_dec Result of the macro + * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC or + * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE + * + * @return The definition of the structure type that holds all the required data. + * + * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_DATA_TYPEDEF instead. + * + * @note APP_USBD_CLASS_DATA_TYPEDEF has to be called first for the compilation to success. + * + * @sa APP_USBD_CLASS_TYPEDEF + */ +#define APP_USBD_CLASS_INSTANCE_TYPEDEF(type_name, interfaces_configs, class_config_dec) \ + typedef union CONCAT_2(type_name, _u) \ + { \ + app_usbd_class_inst_t base; \ + struct \ + { \ + APP_USBD_CLASS_DATA_TYPE(type_name) * p_data; \ + app_usbd_class_methods_t const * p_class_methods; \ + struct \ + { \ + uint8_t cnt; \ + app_usbd_class_iface_conf_t \ + config[NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs))]; \ + app_usbd_class_ep_conf_t \ + ep[APP_USBD_CLASS_CONF_TOTAL_EP_COUNT(interfaces_configs)]; \ + } iface; \ + class_config_dec \ + } specific; \ + } APP_USBD_CLASS_INSTANCE_TYPE(type_name) + +/** + * @brief Writable data structure declaration + * + * The macro that declares a variable type that would be used to store given class writable data. + * Writable data contains base part of the type @ref app_usbd_class_data_t followed by + * class specific data. + * + * @param type_name The name of the type without _t postfix. + * @param class_data_dec Result of the macro + * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC or + * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE + * + * @return The definition of the structure type that holds all the required writable data + * + * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_DATA_TYPEDEF instead. + * + * @sa APP_USBD_CLASS_TYPEDEF + */ +#define APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec) \ + typedef struct \ + { \ + app_usbd_class_data_t base; \ + class_data_dec \ + }APP_USBD_CLASS_DATA_TYPE(type_name) + + +/** + * @brief Declare all data types required by the class instance + * + * Macro that declares data type first and then instance type. + * + * @param type_name The name of the type without _t postfix. + * @param interface_configs List of interface configurations like in @ref APP_USBD_CLASS_INSTANCE_TYPEDEF. + * @param class_config_dec Result of the macro + * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC or + * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE + * @param class_data_dec Result of the macro + * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC or + * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE + * + * @return Declaration of the data type for the instance and instance itself. + * + * @sa APP_USBD_CLASS_DATA_TYPEDEF + * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF + */ +#define APP_USBD_CLASS_TYPEDEF(type_name, interface_configs, class_config_dec, class_data_dec) \ + APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec); \ + APP_USBD_CLASS_INSTANCE_TYPEDEF(type_name, interface_configs, class_config_dec) + +/** + * @brief Forward declaration of type defined by @ref APP_USBD_CLASS_TYPEDEF + * + * @param type_name The name of the type without _t postfix. + * */ +#define APP_USBD_CLASS_FORWARD(type_name) union CONCAT_2(type_name, _u) + +/** + * @brief Generate the initialization data for + * + * Macro that generates the initialization data for instance. + * + * @param p_ram_data Pointer to writable instance data structure + * @param class_methods Class methods + * @param interfaces_configs Exactly the same interface config data that in @ref APP_USBD_CLASS_INSTANCE_TYPEDEF + * @param class_config_part Configuration part. The data should be inside brackets. + * Any data here would be removed from brackets and then put as an initialization + * data for class_part member of instance structure. + * + * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_INST_DEF instead. + */ +#define APP_USBD_CLASS_INSTANCE_INITVAL(p_ram_data, \ + class_methods, \ + interfaces_configs, \ + class_config_part) \ + { \ + .specific = { \ + .p_data = p_ram_data, \ + .p_class_methods = class_methods, \ + .iface = { \ + .cnt = NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs)), \ + .config = { APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(interfaces_configs) }, \ + .ep = { APP_USBD_CLASS_IFACES_EP_EXTRACT(interfaces_configs) } \ + }, \ + BRACKET_EXTRACT(class_config_part) \ + } \ + } + + +/** + * @brief Define the base class instance + * + * Macro that defines whole instance variable and fill it with initialization data. + * + * The tricky part is @c class_config_part. + * The configuration data here has to be placed inside brackets. + * Then any type of values can be used depending on the type used in @ref APP_USBD_CLASS_TYPEDEF. + * If instance does not have any specyfic data, use just empty bracket here. + * @code + * APP_USBD_CLASS_TYPEDEF( + * some_base_class, + * CLASS_BASE_CONFIGURATION, + * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, + * APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE + * ); + * APP_USBD_CLASS_INST_DEF( + * some_base_class_inst, + * some_base_class, + * base_class_event_handler, + * CLASS_BASE_CONFIGURATION, + * () // Empty configuration + * ); + * @endcode + * + * If the type of instance configuration is simple type, just provide initialization value: + * @code + * APP_USBD_CLASS_TYPEDEF( + * some_base_class, + * CLASS_BASE_CONFIGURATION, + * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, + * APP_USBD_CLASS_DATA_SPECIFIC_DEC(uint8_t) + * ); + * APP_USBD_CLASS_INST_DEF( + * some_base_class_inst, + * some_base_class, + * base_class_event_handler, + * CLASS_BASE_CONFIGURATION, + * (12) // Example values + * ); + * @endcode + * + * If the type of instance configuration is structure, provide initialization value for the whole structure: + * @code + * typedef structure + * { + * uint32_t p1; + * uint8_t p2; + * }my_config_t; + * + * APP_USBD_CLASS_TYPEDEF( + * some_base_class, + * CLASS_BASE_CONFIGURATION, + * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, + * APP_USBD_CLASS_DATA_SPECIFIC_DEC(my_config_t) + * ); + * APP_USBD_CLASS_INST_DEF( + * some_base_class_inst, + * some_base_class, + * base_class_event_handler, + * CLASS_BASE_CONFIGURATION, + * ({12, 3}) // Example values + * ); + * @endcode + * + * @param instance_name The name of created instance variable. + * It would be constant variable and its type would be app_usbd_class_inst_t. + * @param type_name The name of the variable type. It has to be the same type that was passed to + * @ref APP_USBD_CLASS_TYPEDEF + * @param class_methods Class unified interface. + * @param interfaces_configs The same configuration data that the one passed to @ref APP_USBD_CLASS_TYPEDEF + * @param class_config_part Configuration data to the type that was declared by class_data_dec when calling + * @ref APP_USBD_CLASS_TYPEDEF. + * Configuration data has to be provided in brackets. + * It would be extracted from brackets and placed in initialization part of configuration structure. + * See detailed description of this macro for more informations. + */ +#define APP_USBD_CLASS_INST_DEF(instance_name, \ + type_name, \ + class_methods, \ + interfaces_configs, \ + class_config_part) \ + static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \ + static const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \ + APP_USBD_CLASS_INSTANCE_INITVAL( \ + &CONCAT_2(instance_name, _data), \ + class_methods, \ + interfaces_configs, \ + class_config_part) + + +/** + * @brief Define the base class instance in global scope + * + * This is the same macro like @ref APP_USBD_CLASS_INST_DEF but it creates the instance + * without static keyword. + * + * @param instance_name See documentation for @ref APP_USBD_CLASS_INST_DEF + * @param type_name See documentation for @ref APP_USBD_CLASS_INST_DEF + * @param class_methods See documentation for @ref APP_USBD_CLASS_INST_DEF + * @param interfaces_configs See documentation for @ref APP_USBD_CLASS_INST_DEF + * @param class_config_part See documentation for @ref APP_USBD_CLASS_INST_DEF + */ +#define APP_USBD_CLASS_INST_GLOBAL_DEF(instance_name, \ + type_name, \ + class_methods, \ + interfaces_configs, \ + class_config_part) \ + static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \ + const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \ + APP_USBD_CLASS_INSTANCE_INITVAL( \ + &CONCAT_2(instance_name, _data), \ + class_methods, \ + interfaces_configs, \ + class_config_part) + +/** + * @brief Access class specific configuration + * + * Macro that returns class specific configuration. + * + * @param[in] p_inst Instance pointer + * + * @return A pointer for class specific part of the instance + * + * @note If macro is used on the instance that has no class specific configuration + * an error would be generated during compilation. + */ +#define APP_USBD_CLASS_GET_SPECIFIC_CONFIG(p_inst) (&((p_inst)->specific.class_part)) + +/** + * @brief Access class specific data + * + * @param[in] p_inst Instance pointer + * + * @return A pointer for class specific part of writable data + * + * @note If macro is used on the instance that has no class specific data + * an error would be generated during compilation. + */ +#define APP_USBD_CLASS_GET_SPECIFIC_DATA(p_inst) (&(((p_inst)->specific.p_data)->class_part)) + +/** + * @brief Macro to get base instance from class specific instance + * + * This macro may be used on class specific instance to get base instance that + * can be processed by base instance access functions. + * Class specific instance can be just casted to class base instance, + * but then we would totally lost type safety. + * + * A little more safe is to use pointer to base member of class instance. + * This would generate an error when used on any variable that have no base member + * and would generate also error if this base member is wrong type. + */ +#define APP_USBD_CLASS_BASE_INSTANCE(p_inst) (&((p_inst)->base)) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CLASS_BASE_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c b/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c new file mode 100644 index 000000000..48a0f4fab --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.c @@ -0,0 +1,1086 @@ +/** + * Copyright (c) 2016 - 2017, 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_config.h" +#if APP_USBD_ENABLED +#include "app_usbd_core.h" +#include "app_usbd.h" +#include "app_usbd_request.h" +#include "app_usbd_string_desc.h" +#include "nrf.h" +#include "nrf_atomic.h" +#include "app_util_platform.h" +#include "app_usbd.h" +#include "app_usbd_class_base.h" + +/* Test if VID was configured */ +#ifndef APP_USBD_VID +#error APP_USBD_VID not properly defined. +#endif + + +/* Device version checking */ +#if defined(APP_USBD_DEVICE_VER_MAJOR) && defined(APP_USBD_DEVICE_VER_MINOR) + #if ((APP_USBD_DEVICE_VER_MAJOR)) > 99 || ((APP_USBD_DEVICE_VER_MINOR) > 99) + #error Major and minor device version value have to be limited to 99. + #endif +#else + #error The definition of a pair APP_USBD_DEVICE_VER_MAJOR and APP_USBD_DEVICE_VER_MINOR required. +#endif + +/** + * @internal + * @defgroup app_usbd_core_internals USB Device high level library core module internals + * @ingroup app_usbd_core + * + * Internal variables, auxiliary macros and functions of USBD high level core module. + * @{ + */ + +/** @brief Make USB power value */ +#define APP_USBD_POWER_MAKE(ma) (((ma) + 1) / 2) + +/** + @brief Default device descriptor initializer @ref app_usbd_descriptor_device_t +* */ +#define APP_USBD_CORE_DEVICE_DESCRIPTOR { \ + .bLength = sizeof(app_usbd_descriptor_device_t), /* descriptor size */ \ + .bDescriptorType = APP_USBD_DESCRIPTOR_DEVICE, /* descriptor type */ \ + .bcdUSB = APP_USBD_BCD_VER_MAKE(2,0), /* USB BCD version: 2.0 */ \ + .bDeviceClass = 0, /* device class: 0 - specified by interface */ \ + .bDeviceSubClass = 0, /* device subclass: 0 - specified by interface */ \ + .bDeviceProtocol = 0, /* device protocol: 0 - specified by interface */ \ + .bMaxPacketSize0 = NRF_DRV_USBD_EPSIZE, /* endpoint size: fixed to: NRF_DRV_USBD_EPSIZE*/ \ + .idVendor = APP_USBD_VID, /* Vendor ID*/ \ + .idProduct = APP_USBD_PID, /* Product ID*/ \ + .bcdDevice = APP_USBD_BCD_VER_MAKE( /* Device version BCD */ \ + APP_USBD_DEVICE_VER_MAJOR, \ + APP_USBD_DEVICE_VER_MINOR), \ + .iManufacturer = APP_USBD_STRING_ID_MANUFACTURER, /* String ID: manufacturer */ \ + .iProduct = APP_USBD_STRING_ID_PRODUCT, /* String ID: product */ \ + .iSerialNumber = APP_USBD_STRING_ID_SERIAL, /* String ID: serial */ \ + .bNumConfigurations = 1 /* Fixed value: only one configuration supported*/\ +} + + +#define APP_USBD_CORE_CONFIGURATION_DESCRIPTOR { \ + .bLength = sizeof(app_usbd_descriptor_configuration_t), \ + .bDescriptorType = APP_USBD_DESCRIPTOR_CONFIGURATION, \ + .wTotalLength = 0, /*Calculated dynamically*/ \ + .bNumInterfaces = 0, /*Calculated dynamically*/ \ + .bConfigurationValue = 1, /*Value passed to set configuration*/ \ + .iConfiguration = 0, /*Configuration ID: fixed to 0*/ \ + .bmAttributes = APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_ALWAYS_SET_MASK | \ + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK, \ + .bMaxPower = APP_USBD_POWER_MAKE(500), \ +} + +/** + * @brief Device descriptor instance. + * + * @note + * Constant part of the device descriptor. + * Values that must be calculated are updated directly in the buffer + * just before the transmission. + */ +static const app_usbd_descriptor_device_t m_device_dsc = + APP_USBD_CORE_DEVICE_DESCRIPTOR; + +/** + * @brief Configuration descriptor instance. + * + * @note + * Constant part of the device descriptor. + * Values that must be calculated are updated directly in the buffer + * just before the transmission. + */ +static const app_usbd_descriptor_configuration_t m_configuration_dsc = + APP_USBD_CORE_CONFIGURATION_DESCRIPTOR; + +/* Required early declaration of event handler function */ +static ret_code_t app_usbd_core_event_handler(app_usbd_class_inst_t const * const p_inst, + app_usbd_complex_evt_t const * const p_event); + +/** + * @brief Current USB device state + * + * This variable is updated automatically by core library. + */ +static app_usbd_state_t m_app_usbd_state = APP_USBD_STATE_Disabled; + +/** + * @brief Active device features + * + * @note Only @ref APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP is supported for device + */ +static uint8_t m_device_features_state; + +/** + * @brief Remote wake-up pending flag + */ +static nrf_atomic_flag_t m_rwu_pending; + + +/** + * @brief Core class methods + * + * Base methods interface for core class. + * This is quite specific class - it would be only connected into endpoint 0. + * Not connected into instances list. + */ +static const app_usbd_class_methods_t m_core_methods = { + .event_handler = app_usbd_core_event_handler, + .get_descriptors = NULL, +}; + +/** + * @brief Setup transfer buffer + */ +static uint8_t m_setup_transfer_buff[NRF_DRV_USBD_EPSIZE]; + + +/** + * @brief Handler for outgoing setup data + * + * @todo RK documentation + */ +static app_usbd_core_setup_data_handler_desc_t m_ep0_handler_desc; + +#define APP_USBD_CORE_CLASS_INSTANCE_CONFIG () + + +/*lint -u -save -e26 -e40 -e64 -e123 -e505 -e651*/ + +/** + * @brief Core instance + * + * Create instance that would be connected into endpoints in USBD library. + */ +APP_USBD_CLASS_INST_GLOBAL_DEF( + app_usbd_core_inst, + app_usbd_core, + &m_core_methods, + APP_USBD_CORE_CLASS_CONFIGURATION, + () ); +/*lint -restore*/ + + + +/** + * @brief Check current USBD power connection status + * + */ +static inline bool usbd_core_power_is_detected(void) +{ + return 0 != ( (NRF_POWER->USBREGSTATUS) & POWER_USBREGSTATUS_VBUSDETECT_Msk); +} + + +/** + * @brief Safely call EP0 handler + * + * Function calls EP0 handler only if its pointer is non-zero. + * + * @param status Status to send as a handler parameter. + */ +static inline ret_code_t usbd_core_ep0_handler_call_and_clear(nrf_drv_usbd_ep_status_t status) +{ + app_usbd_core_setup_data_handler_t handler = m_ep0_handler_desc.handler; + if (NULL != handler) + { + m_ep0_handler_desc.handler = NULL; + return handler(status, m_ep0_handler_desc.p_context); + } + + return NRF_ERROR_NULL; +} + +/** + * @brief Check if EP0 handler is configured + * + * EP0 handler is configured is any instance that has processed SETUP command + * expects some incoming / outgoing data. + * + * EP0 handler should be cleared automatically just before it is called + * (see @ref usbd_core_ep0_handler_call_and_clear). + * If instance requires more data - it has to setup EP0 handler once more time + * (see @ref app_usbd_core_setup_data_handler_set). + * + * This function adds small layer of abstraction for checking if EP0 handler + * is already configured. + * + * @retval true EP0 handler is set + * @retval false EP0 handler is cleared + */ +static inline bool usb_core_ep0_handler_check(void) +{ + return (NULL != m_ep0_handler_desc.handler); +} + +/** + * @brief Empty data handler + * + * Data handler used only to mark that there is requested data during SETUP. + * + * @return Always NRF_SUCCESS + * @sa setup_empty_data_handler_desc + */ +static ret_code_t setup_data_handler_empty(nrf_drv_usbd_ep_status_t status, void * p_contex) +{ + UNUSED_PARAMETER(status); + UNUSED_PARAMETER(p_contex); + return NRF_SUCCESS; +} + +/** + * @brief + * + * @todo RK Documentation + */ +static app_usbd_core_setup_data_handler_desc_t const m_setup_data_handler_empty_desc = +{ + .handler = setup_data_handler_empty, + .p_context = NULL +}; + +/** + * @brief Structure used as a context for descriptor feeder + * + * Structure with all the data required to process instances to generate descriptor + * data chunk. + */ +typedef struct +{ + app_usbd_class_inst_t const * p_cinst; //!< The class instance that is to be processed next. + const uint8_t * p_desc; //!< Pointer at current descriptor or NULL if finished. + /**< + * If we get NULL on transfer function enter it means that ZLP is required. + * Or it is time to finish the transfer (depending on @c total_left). + */ + size_t desc_left; //!< Number of bytes left in the current class descriptor to send + size_t total_left; //!< Number of bytes left that was requested by the host +} app_usbd_core_descriptor_conf_feed_data_t; + +/** + * @brief Default data used by the feeder + * + * + */ +static app_usbd_core_descriptor_conf_feed_data_t m_descriptor_conf_feed_data; + +/** + * @brief Descriptor feeder + * + * Descriptor feeder is used as an callback function when descriptors are + * transfered and buffer is ready for next data. + * It prepares next chunk of data to be sent. + * + * @param p_next See @ref nrf_drv_usbd_next_transfer_handler_t documentation. + * @param p_context Pointer to @ref app_usbd_core_descriptor_feed_data_t data type. + * @param ep_size The size of the endpoint. + * + * @return See @ref nrf_drv_usbd_next_transfer_handler_t documentation. + */ +static bool usbd_descriptor_conf_feeder( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size) +{ + bool continue_req = true; + + app_usbd_core_descriptor_conf_feed_data_t * p_data = p_context; + if (NULL == p_data->p_desc) + { + /* ZLP */ + continue_req = false; + p_next->p_data.tx = NULL; + p_next->size = 0; + } + else + { + ASSERT(ep_size <= NRF_DRV_USBD_FEEDER_BUFFER_SIZE); + uint8_t * p_tx_buff = nrf_drv_usbd_feeder_buffer_get(); + size_t size = 0; /* Currently added number of bytes */ + size_t tx_size; /* Number of bytes to send right now */ + + /* Feeder function can use the USBD driver internal buffer */ + p_tx_buff = nrf_drv_usbd_feeder_buffer_get(); + + tx_size = MIN(ep_size, p_data->total_left); + while (0 != tx_size) + { + /* Process transfer */ + if (0 < p_data->desc_left) + { + size_t to_copy = MIN(tx_size, p_data->desc_left); + memcpy(p_tx_buff + size, p_data->p_desc, to_copy); + p_data->desc_left -= to_copy; + p_data->total_left -= to_copy; + tx_size -= to_copy; + size += to_copy; + p_data->p_desc += to_copy; + } + + if (0 == p_data->total_left) + { + continue_req = false; + } + else if (0 == p_data->desc_left) + { + if (NULL == p_data->p_cinst) + { + p_data->p_desc = NULL; + /* No more data - check if ZLP is required */ + if (size > 0) + { + if (size < ep_size) + { + continue_req = false; + } + } + break; + } + else + { + /* Prepare next descriptor */ + p_data->p_desc = + p_data->p_cinst->p_class_methods->get_descriptors( + p_data->p_cinst, + &p_data->desc_left); + /* Get next descriptor */ + p_data->p_cinst = app_usbd_class_next_get(p_data->p_cinst); + } + } + else + { + /* Nothing to do */ + } + } + p_next->p_data.tx = p_tx_buff; + p_next->size = size; + } + return continue_req; +} + +/** + * @brief + * + * @todo RK Documentation + */ +static const nrf_drv_usbd_handler_desc_t usbd_descriptor_feeder_desc = +{ + .handler = { .feeder = usbd_descriptor_conf_feeder }, + .p_context = &m_descriptor_conf_feed_data +}; + +static ret_code_t setup_req_get_status(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + size_t max_size; + uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); + ASSERT(sizeof(uint16_t) <= max_size); + + memset(p_trans_buff, 0, sizeof(uint16_t)); + if (m_configuration_dsc.bmAttributes & + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK) + { + SET_BIT(p_trans_buff[0], 0); + } + if (IS_SET(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP)) + { + SET_BIT(p_trans_buff[0], 1); + } + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, sizeof(uint16_t)); +} + +static ret_code_t setup_req_get_descriptor(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + switch (p_setup_ev->setup.wValue.hb) + { + case APP_USBD_DESCRIPTOR_DEVICE: + { + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), + &m_device_dsc, + sizeof(m_device_dsc)); + } + case APP_USBD_DESCRIPTOR_CONFIGURATION: + { + /* The size equals the size of configuration descriptor and all classes descriptors */ + const size_t size = MIN( + sizeof(app_usbd_descriptor_configuration_t), + p_setup_ev->setup.wLength.w); + size_t total_length = sizeof(app_usbd_descriptor_configuration_t); + uint8_t iface_count = 0; + + /* Iterate over all registered classes count descriptors and total size */ + app_usbd_class_inst_t const * p_class; + for (p_class = app_usbd_class_first_get(); p_class != NULL; + p_class = app_usbd_class_next_get(p_class)) + { + ASSERT(NULL != (p_class->p_class_methods)); + ASSERT(NULL != (p_class->p_class_methods->get_descriptors)); + size_t dsc_size; + const void * dsc = p_class->p_class_methods->get_descriptors(p_class, &dsc_size); + UNUSED_VARIABLE(dsc); + total_length += dsc_size; + iface_count += app_usbd_class_iface_count_get(p_class); + } + + /* Access transmission buffer */ + size_t max_size; + app_usbd_descriptor_configuration_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); + /* Copy the configuration descriptor and update the fields that require it */ + ASSERT(size <= max_size); + memcpy(p_trans_buff, &m_configuration_dsc, size); + + p_trans_buff->bNumInterfaces = iface_count; + p_trans_buff->wTotalLength = total_length; + if (app_usbd_class_rwu_enabled_check()) + { + p_trans_buff->bmAttributes |= + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_REMOTE_WAKEUP_MASK; + } + + m_descriptor_conf_feed_data.p_cinst = app_usbd_class_first_get(); + m_descriptor_conf_feed_data.p_desc = (void *)p_trans_buff; + m_descriptor_conf_feed_data.desc_left = size; + m_descriptor_conf_feed_data.total_left = p_setup_ev->setup.wLength.w; + + /* Start first transfer */ + ret_code_t ret; + CRITICAL_REGION_ENTER(); + + ret = app_usbd_setup_data_handled_transfer( + NRF_DRV_USBD_EPIN0, + &usbd_descriptor_feeder_desc); + + if (NRF_SUCCESS == ret) + { + ret = app_usbd_core_setup_data_handler_set( + NRF_DRV_USBD_EPIN0, + &m_setup_data_handler_empty_desc); + } + CRITICAL_REGION_EXIT(); + + return ret; + } + case APP_USBD_DESCRIPTOR_STRING: + { + app_usbd_string_desc_idx_t id = + (app_usbd_string_desc_idx_t)(p_setup_ev->setup.wValue.lb); + uint16_t langid = p_setup_ev->setup.wIndex.w; + uint16_t const * p_string_dsc = app_usbd_string_desc_get(id, langid); + if (p_string_dsc == NULL) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return app_usbd_core_setup_rsp( + &p_setup_ev->setup, + p_string_dsc, + app_usbd_string_desc_length(p_string_dsc)); + } + default: + break; + } + + + return NRF_ERROR_NOT_SUPPORTED; +} + +static ret_code_t setup_req_get_configuration(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + size_t max_size; + uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size); + if (APP_USB_STATE_BASE(m_app_usbd_state) == APP_USBD_STATE_Configured) + { + p_trans_buff[0] = 1; + } + else if (APP_USB_STATE_BASE(m_app_usbd_state) == APP_USBD_STATE_Addressed) + { + p_trans_buff[0] = 0; + } + else + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return app_usbd_core_setup_rsp(&p_setup_ev->setup, p_trans_buff, sizeof(p_trans_buff[0])); +} + +/** + * @brief Internal SETUP standard IN request handler + * @param[in] p_inst Instance of the class + * @param[in] p_setup_ev Setup request + * @return Standard error code + * @retval NRF_SUCCESS if request handled correctly + * @retval NRF_ERROR_NOT_SUPPORTED if request is not supported + */ +static ret_code_t setup_req_std_in(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_GET_STATUS: + { + return setup_req_get_status(p_inst, p_setup_ev); + } + case APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR: + { + return setup_req_get_descriptor(p_inst, p_setup_ev); + } + case APP_USBD_SETUP_STDREQ_GET_CONFIGURATION: + { + return setup_req_get_configuration(p_inst, p_setup_ev); + } + default: + /*Not supported*/ + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + + +static ret_code_t setup_req_std_set_configuration(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + if (!((m_app_usbd_state == APP_USBD_STATE_Configured) || + (m_app_usbd_state == APP_USBD_STATE_Addressed))) + { + return NRF_ERROR_INVALID_STATE; + } + + app_usbd_state_t new_state = m_app_usbd_state; + + if (p_setup_ev->setup.wValue.lb == 0) + { + new_state = APP_USBD_STATE_Addressed; + } + else if (p_setup_ev->setup.wValue.lb == 1) + { + new_state = APP_USBD_STATE_Configured; + /*Clear all bulk/interrupt endpoint status and set toggle to DATA0*/ + + app_usbd_class_inst_t const * p_inst_it = app_usbd_class_first_get(); + while (p_inst_it != NULL) + { + uint8_t iface_count = app_usbd_class_iface_count_get(p_inst_it); + for (uint8_t i = 0; i < iface_count; ++i) + { + app_usbd_class_iface_conf_t const * p_iface; + p_iface = app_usbd_class_iface_get(p_inst_it, i); + uint8_t ep_count = app_usbd_class_iface_ep_count_get(p_iface); + + for (uint8_t j = 0; j < ep_count; ++j) + { + /*Clear stall for every endpoint*/ + app_usbd_class_ep_conf_t const * p_ep = app_usbd_class_iface_ep_get(p_iface, j); + + + if (nrf_usbd_dtoggle_get(p_ep->address) != NRF_USBD_DTOGGLE_DATA0) + { + nrf_usbd_dtoggle_set(p_ep->address, NRF_USBD_DTOGGLE_DATA0); + } + + if (NRF_USBD_EPISO_CHECK(p_ep->address) == 0) + { + nrf_drv_usbd_ep_stall_clear(p_ep->address); + } + + } + } + p_inst_it = p_inst_it->p_data->p_next; + } + + } + else + { + /*In this driver only one configuration is supported.*/ + return NRF_ERROR_INVALID_PARAM; + } + + + + if (m_app_usbd_state != new_state) + { + m_app_usbd_state = new_state; + /** @todo RK A way to notify class that state was changed */ + } + + return NRF_SUCCESS; +} + +/** + * @brief Internal SETUP standard OUT request handler + * @param[in] p_inst Instance of the class + * @param[in] p_setup_ev Setup request + * @return Standard error code + * @retval NRF_SUCCESS if request handled correctly + * @retval NRF_ERROR_NOT_SUPPORTED if request is not supported + */ +static ret_code_t setup_req_std_out(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_SET_ADDRESS: + { + if ((m_app_usbd_state != APP_USBD_STATE_Default) && + (m_app_usbd_state != APP_USBD_STATE_Addressed) && + (m_app_usbd_state != APP_USBD_STATE_Configured)) + { + return NRF_ERROR_INVALID_STATE; + } + + m_app_usbd_state = APP_USBD_STATE_Addressed; + return NRF_SUCCESS; + } + case APP_USBD_SETUP_STDREQ_SET_FEATURE: + { + if (p_setup_ev->setup.wValue.w != APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + SET_BIT(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP); + return NRF_SUCCESS; + } + case APP_USBD_SETUP_STDREQ_CLEAR_FEATURE: + { + if (p_setup_ev->setup.wValue.w != APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + CLR_BIT(m_device_features_state, APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP); + return NRF_SUCCESS; + } + case APP_USBD_SETUP_STDREQ_SET_CONFIGURATION: + { + return setup_req_std_set_configuration(p_inst, p_setup_ev); + } + case APP_USBD_SETUP_STDREQ_SET_DESCRIPTOR: + { + /*Not supported yet.*/ + break; + } + default: + /*Not supported*/ + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Internal SETUP event handler + * @param[in] p_inst Instance of the class + * @param[in] p_setup_ev Setup request + * @return Standard error code + * @retval NRF_SUCCESS if request handled correctly + * @retval NRF_ERROR_NOT_SUPPORTED if request is not supported + */ +static ret_code_t setup_device_event_handler(app_usbd_class_inst_t const * const p_inst, + app_usbd_setup_evt_t const * const p_setup_ev) +{ + ASSERT(p_inst != NULL); + ASSERT(p_setup_ev != NULL); + + if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN) + { + switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + case APP_USBD_SETUP_REQTYPE_STD: + return setup_req_std_in(p_inst, p_setup_ev); + default: + break; + } + } + else /*APP_USBD_SETUP_REQDIR_OUT*/ + { + switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + case APP_USBD_SETUP_REQTYPE_STD: + return setup_req_std_out(p_inst, p_setup_ev); + default: + break; + } + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Process SETUP command + * + * Auxiliary function for SETUP command processing + */ +static inline ret_code_t app_usbd_core_setup_req_handler(app_usbd_class_inst_t const * const p_inst) +{ + app_usbd_setup_evt_t setup_ev; + ret_code_t ret = NRF_ERROR_INTERNAL; /* Final result of request processing function */ + + /* This handler have to be cleared when SETUP is entered */ + // ASSERT(!usb_core_ep0_handler_check()); + + setup_ev.type = APP_USBD_EVT_DRV_SETUP; + nrf_drv_usbd_setup_get((nrf_drv_usbd_setup_t *)&(setup_ev.setup)); + + switch (app_usbd_setup_req_rec(setup_ev.setup.bmRequestType)) + { + case APP_USBD_SETUP_REQREC_DEVICE: + { + /* Endpoint 0 has core instance (that process device requests) connected */ + ret = setup_device_event_handler(p_inst, &setup_ev); + + app_usbd_setup_reqtype_t req_type = + app_usbd_setup_req_typ(setup_ev.setup.bmRequestType); + if (ret == NRF_ERROR_NOT_SUPPORTED && + req_type == APP_USBD_SETUP_REQTYPE_VENDOR) + { + ret = app_usbd_all_until_served_call((app_usbd_complex_evt_t const *)&setup_ev); + } + + break; + } + case APP_USBD_SETUP_REQREC_INTERFACE: + { + uint8_t iface_number = setup_ev.setup.wIndex.lb; + ret = app_usbd_iface_call(iface_number, (app_usbd_complex_evt_t const *)&setup_ev); + if (ret == NRF_SUCCESS || ret != NRF_ERROR_NOT_SUPPORTED) + { + break; + } + + ret = app_usbd_interface_std_req_handle(&setup_ev); + break; + } + case APP_USBD_SETUP_REQREC_ENDPOINT: + { + nrf_drv_usbd_ep_t ep = (nrf_drv_usbd_ep_t)setup_ev.setup.wIndex.lb; + + if ((ep == NRF_DRV_USBD_EPOUT0) || (ep == NRF_DRV_USBD_EPIN0)) + { + ret = app_usbd_endpoint_std_req_handle(&setup_ev); + break; + } + + ret = app_usbd_ep_call(ep, (app_usbd_complex_evt_t const *)&setup_ev); + if (ret == NRF_SUCCESS || ret != NRF_ERROR_NOT_SUPPORTED) + { + break; + } + + ret = app_usbd_endpoint_std_req_handle(&setup_ev); + break; + } + case APP_USBD_SETUP_REQREC_OTHER: + { + /* Try to process via every instance */ + ret = app_usbd_all_until_served_call((app_usbd_complex_evt_t *)&setup_ev); + break; + } + default: + break; + } + + /* Processing result */ + if (ret == NRF_SUCCESS) + { + if (usb_core_ep0_handler_check()) + { + /* Request processed successfully and requires SETUP data */ + nrf_drv_usbd_setup_data_clear(); + } + else + { + /* Request processed successfully */ + nrf_drv_usbd_setup_clear(); + } + } + else + { + /* Request finished with error */ + nrf_drv_usbd_setup_stall(); + } + return ret; +} + +/** + * @brief Event handler for core module + * + * The event handler that would process all events directed to device. + * + */ +static ret_code_t app_usbd_core_event_handler(app_usbd_class_inst_t const * const p_inst, + app_usbd_complex_evt_t const * const p_event) +{ + ret_code_t ret = NRF_ERROR_NOT_SUPPORTED; + switch (p_event->type) + { + case APP_USBD_EVT_DRV_RESET: + { + m_app_usbd_state = APP_USBD_STATE_Default; + break; + } + case APP_USBD_EVT_DRV_SUSPEND: + { + ASSERT(m_app_usbd_state >= APP_USBD_STATE_Unattached); + m_app_usbd_state |= (app_usbd_state_t)(APP_USBD_STATE_SUSPENDED_MASK); + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_DRV_RESUME: + { + if (nrf_atomic_flag_clear_fetch(&m_rwu_pending) != 0) + { + nrf_usbd_task_trigger(NRF_USBD_TASK_NODRIVEDPDM); + } + + ASSERT(APP_USB_STATE_BASE(m_app_usbd_state) >= APP_USBD_STATE_Unattached); + m_app_usbd_state &= (app_usbd_state_t)(~APP_USBD_STATE_SUSPENDED_MASK); + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_DRV_SETUP: + { + ret = app_usbd_core_setup_req_handler(p_inst); + break; + } + case APP_USBD_EVT_INST_APPEND: + { + ASSERT(m_app_usbd_state == APP_USBD_STATE_Disabled); + m_app_usbd_state = APP_USBD_STATE_Unattached; + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_INST_REMOVE: + { + ASSERT(m_app_usbd_state == APP_USBD_STATE_Unattached); + m_app_usbd_state = APP_USBD_STATE_Disabled; + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_STARTED: + { + m_app_usbd_state = APP_USBD_STATE_Powered; + if (usbd_core_power_is_detected()) + { + m_app_usbd_state = APP_USBD_STATE_Default; + } + ret = NRF_SUCCESS; + break; + } + case APP_USBD_EVT_STOPPED: + { + ASSERT(APP_USB_STATE_BASE(m_app_usbd_state) > APP_USBD_STATE_Powered); + if (((uint32_t)m_app_usbd_state) & APP_USBD_STATE_SUSPENDED_MASK) + { + m_app_usbd_state = APP_USBD_STATE_SuspendedPowered; + } + else + { + m_app_usbd_state = APP_USBD_STATE_Powered; + } + ret = NRF_SUCCESS; + break; + } + /* Data transfer on endpoint 0 */ + case APP_USBD_EVT_DRV_EPTRANSFER: + { + /* This EPTRANSFER event has to be called only for EP0 */ + ASSERT((p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPOUT0) || + (p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPIN0)); + ret = usbd_core_ep0_handler_call_and_clear(p_event->drv_evt.data.eptransfer.status); + /* Processing result */ + if (ret == NRF_SUCCESS) + { + if (usb_core_ep0_handler_check()) + { + /* Request processed successfully and requires SETUP data */ + nrf_drv_usbd_setup_data_clear(); + } + else + { + /* Request processed successfully */ + /* Clear setup only for a write transfer - for a read transfer, + * it is cleared inside the driver */ + if (p_event->drv_evt.data.eptransfer.ep == NRF_DRV_USBD_EPOUT0) + { + if (!nrf_drv_usbd_errata_154()) + { + nrf_drv_usbd_setup_clear(); + } + } + } + } + else + { + /* Request finished with error */ + nrf_drv_usbd_setup_stall(); + } + break; + } + default: + break; + } + + return ret; +} + +ret_code_t app_usbd_core_setup_rsp(app_usbd_setup_t const * p_setup, + void const * p_data, + size_t size) +{ + size_t req_size = p_setup->wLength.w; + size_t tx_size = MIN(req_size, size); + bool zlp_required = (size < req_size) && + (0 == (size % nrf_drv_usbd_ep_max_packet_size_get(NRF_DRV_USBD_EPIN0))); + + NRF_DRV_USBD_TRANSFER_IN_FLAGS( + transfer, + p_data, + tx_size, + zlp_required ? NRF_DRV_USBD_TRANSFER_ZLP_FLAG : 0); + + ret_code_t ret; + CRITICAL_REGION_ENTER(); + ret = app_usbd_core_setup_data_transfer(NRF_DRV_USBD_EPIN0, + &transfer); + if (NRF_SUCCESS == ret) + { + ret = app_usbd_core_setup_data_handler_set(NRF_DRV_USBD_EPIN0, + &m_setup_data_handler_empty_desc); + } + CRITICAL_REGION_EXIT(); + + return ret; +} + +ret_code_t app_usbd_core_setup_data_handler_set( + nrf_drv_usbd_ep_t ep, + app_usbd_core_setup_data_handler_desc_t const * const p_handler_desc) +{ + if (nrf_drv_usbd_last_setup_dir_get() != ep) + { + return NRF_ERROR_INVALID_ADDR; + } + + m_ep0_handler_desc = *p_handler_desc; + return NRF_SUCCESS; +} + +ret_code_t app_usbd_core_ep_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_transfer_t const * const p_transfer) +{ + if (APP_USB_STATE_BASE(m_app_usbd_state) != APP_USBD_STATE_Configured) + { + return NRF_ERROR_INVALID_STATE; + } + return nrf_drv_usbd_ep_transfer(ep, p_transfer); +} + +ret_code_t app_usbd_core_setup_data_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_transfer_t const * const p_transfer) +{ + ASSERT(0 == NRF_USBD_EP_NR_GET(ep)); + + if (!((APP_USB_STATE_BASE(m_app_usbd_state) == APP_USBD_STATE_Configured) || + (APP_USB_STATE_BASE(m_app_usbd_state) == APP_USBD_STATE_Addressed ) || + (APP_USB_STATE_BASE(m_app_usbd_state) == APP_USBD_STATE_Default ) )) + { + return NRF_ERROR_INVALID_STATE; + } + return nrf_drv_usbd_ep_transfer(ep, p_transfer); +} + +ret_code_t app_usbd_ep_handled_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_handler_desc_t const * const p_handler) +{ + if (APP_USB_STATE_BASE(m_app_usbd_state) != APP_USBD_STATE_Configured) + { + return NRF_ERROR_INVALID_STATE; + } + return nrf_drv_usbd_ep_handled_transfer(ep, p_handler); +} + +ret_code_t app_usbd_setup_data_handled_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_handler_desc_t const * const p_handler) +{ + ASSERT(0 == NRF_USBD_EP_NR_GET(ep)); + + if (!((APP_USB_STATE_BASE(m_app_usbd_state) == APP_USBD_STATE_Configured) || + (APP_USB_STATE_BASE(m_app_usbd_state) == APP_USBD_STATE_Addressed ) || + (APP_USB_STATE_BASE(m_app_usbd_state) == APP_USBD_STATE_Default ) )) + { + return NRF_ERROR_INVALID_STATE; + } + return nrf_drv_usbd_ep_handled_transfer(ep, p_handler); +} + +void * app_usbd_core_setup_transfer_buff_get(size_t * p_size) +{ + if (p_size != NULL) + *p_size = sizeof(m_setup_transfer_buff); + + return m_setup_transfer_buff; +} + +app_usbd_state_t app_usbd_core_state_get(void) +{ + return m_app_usbd_state; +} + + +bool app_usbd_core_feature_state_get(app_usbd_setup_stdfeature_t feature) +{ + return IS_SET(m_device_features_state, feature) ? true : false; +} + + +/** @} */ +#endif // APP_USBD_ENABLED diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.h new file mode 100644 index 000000000..d7e1ea9a8 --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_core.h @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_CORE_H__ +#define APP_USBD_CORE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "sdk_common.h" +#include "nrf_drv_usbd.h" +#include "app_usbd_types.h" +#include "app_usbd_class_base.h" + + +/** + * @defgroup app_usbd_core USB Device high level library core module + * @ingroup app_usbd + * + * @brief @tagAPI52840 Core module that manages current USB state and process device requests. + * @{ + */ + +/** + * @brief Core interface configuration + * + * Core instance would have 2 endpoints (IN0 and OUT0). + * The interface number does not matter because it is not used. + */ +#define APP_USBD_CORE_CLASS_CONFIGURATION ((0, NRF_DRV_USBD_EPOUT0, NRF_DRV_USBD_EPIN0)) + +/** + * @brief Suspend state mask + * + * Mask used to mark suspended state, suspended state remembers also the target state after wake up + */ +#define APP_USBD_STATE_SUSPENDED_MASK 0x80 + +/** + * @brief Remove @ref APP_USBD_STATE_SUSPENDED_MASK bit from core state + */ +#define APP_USB_STATE_BASE(state) ((app_usbd_state_t)((uint32_t)(state) & (~APP_USBD_STATE_SUSPENDED_MASK))) + +/** + * @brief USB Device state + * + * Possible USB Device states according to specification. + */ +typedef enum +{ + APP_USBD_STATE_Disabled = 0x00, /**< The whole USBD library is disabled */ + APP_USBD_STATE_Unattached = 0x01, /**< Device is currently not connected to the host */ + APP_USBD_STATE_Powered = 0x02, /**< Device is connected to the host but has not been enumerated */ + APP_USBD_STATE_Default = 0x03, /**< USB Reset condition detected, waiting for the address */ + APP_USBD_STATE_Addressed = 0x04, /**< Device has been addressed but have not been configured */ + APP_USBD_STATE_Configured = 0x05, /**< Device is addressed and configured */ + + APP_USBD_STATE_SuspendedPowered = APP_USBD_STATE_SUSPENDED_MASK | APP_USBD_STATE_Powered, /**< Device is Suspended and on wakeup it will return to Powered state */ + APP_USBD_STATE_SuspendedDefault = APP_USBD_STATE_SUSPENDED_MASK | APP_USBD_STATE_Default, /**< Device is Suspended and on wakeup it will return to Default state */ + APP_USBD_STATE_SuspendedAddressed = APP_USBD_STATE_SUSPENDED_MASK | APP_USBD_STATE_Addressed, /**< Device is Suspended and on wakeup it will return to Addressed state */ + APP_USBD_STATE_SuspendedConfigured = APP_USBD_STATE_SUSPENDED_MASK | APP_USBD_STATE_Configured /**< Device is Suspended and on wakeup it will return to Configured state */ +}app_usbd_state_t; + +/** + * @brief EP0 handler function pointer + * + * Type of the variable that would hold the pointer to the handler for + * endpoint 0 messages processing. + * + * @param p_contex Context variable configured with the transmission request. + */ +typedef ret_code_t (*app_usbd_core_setup_data_handler_t)(nrf_drv_usbd_ep_status_t status, + void * p_context); + +/** + * @brief Variable type used to register EP0 transfer handler + * + * EP0 messages are processed by core instance. + * Another class can register itself to receive messages from EP0 when requesting + * for Setup data transfer. + */ +typedef struct +{ + app_usbd_core_setup_data_handler_t handler; //!< Event handler to be called when transmission is ready + void * p_context; //!< Context pointer to be send to every called event. +} app_usbd_core_setup_data_handler_desc_t; + +/*lint -save -e10 -e26 -e93 -e123 -e505 */ +/** + * @brief Declare Core instance type + * + * USBD core instance type definition. + */ +APP_USBD_CLASS_TYPEDEF(app_usbd_core, + APP_USBD_CORE_CLASS_CONFIGURATION, + APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE, + APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE); +/*lint -restore*/ + +/** + * @brief Access to core instance + * + * Function that returns pointer to the USBD core instance. + * + * @return pointer to the core instance + */ +static inline app_usbd_class_inst_t const * app_usbd_core_instance_access(void) +{ + extern const APP_USBD_CLASS_INSTANCE_TYPE(app_usbd_core) app_usbd_core_inst; + return (app_usbd_class_inst_t const *)&app_usbd_core_inst; +} + +/** + * @brief Default simple response to setup command + * + * This function generates default simple response. + * It sends ZLP when required and on takes care on allowing status stage when + * transfer is finished. + * + * @param p_setup Pointer to original setup message + * @param p_data Pointer to the response. This has to be globaly aviable data. + * @param size Total size of the answer - The function takes care about + * limiting the size of transfered data to the size required + * by setup command. + */ +ret_code_t app_usbd_core_setup_rsp(app_usbd_setup_t const * p_setup, + void const * p_data, + size_t size); + +/** + * @brief Configure the handler for the nearest setup data endpoint transfer + * + * This function would be called on incomming setup data. + * The correct place to set the handler for a data is when SETUP command + * was received. + * + * @param ep Endpoint number (only IN0 and OUT0) are supported. + * @param p_handler_desc Descriptor of the handler to be called. + * + * @retval NRF_SUCCESS Successfully configured + * @retval NRF_ERROR_INVALID_ADDR Last received setup direction does not match + * configured endpoint. + */ +ret_code_t app_usbd_core_setup_data_handler_set( + nrf_drv_usbd_ep_t ep, + app_usbd_core_setup_data_handler_desc_t const * const p_handler_desc); + +/** + * @brief Endpoint transfer + * + * @param ep Endpoint number + * @param p_transfer Description of the transfer to be performed. + * The direction of the transfer is determined by the + * endpoint number. + * + * @retval NRF_ERROR_INVALID_STATE The state of the USB device does not allow + * data transfer on the endpoint. + * + * @return Values returned by @ref nrf_drv_usbd_ep_transfer + * + * @note This function can work only if the USB is in Configured state. + * See @ref app_usbd_core_setup_data_transfer for transfers before + * device configuration is done. + * @sa app_usbd_core_setup_data_transfer + */ +ret_code_t app_usbd_core_ep_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_transfer_t const * const p_transfer); + +/** + * @brief Setup data transfer + * + * Function similar to @ref app_usbd_core_ep_transfer. + * The only technical diference is that it should be used with setup transfers + * that are going to be performed before device is configured. + * + * @param ep See @ref app_usbd_core_ep_transfer. + * @param p_transfer See @ref app_usbd_core_ep_transfer. + * + * @return The same values like @ref app_usbd_core_ep_transfer + */ +ret_code_t app_usbd_core_setup_data_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_transfer_t const * const p_transfer); + +/** + * @brief Set up an endpoint-handled transfer. + * + * Configures a transfer handled by the feedback function. + * + * @param ep Endpoint number. + * @param p_handler Function called when the next chunk of data is requested. + * + * @retval NRF_ERROR_INVALID_STATE The state of the USB device does not allow + * data transfer on the endpoint. + * + * @return Values returned by @ref nrf_drv_usbd_ep_handled_transfer. + */ +ret_code_t app_usbd_ep_handled_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_handler_desc_t const * const p_handler); + +/** + * @brief Set up a data-handled transfer. + * + * Function similar to @ref app_usbd_ep_handled_transfer. + * The only technical diference is that it should be used with setup transfers + * that are performed before the device is configured. + * + * @param ep Endpoint number + * @param p_handler Function called when the next chunk of data is requested. + * + * @retval NRF_ERROR_INVALID_STATE The state of the USB device does not allow + * data transfer on the endpoint. + * + * @return Values returned by @ref nrf_drv_usbd_ep_handled_transfer. + */ +ret_code_t app_usbd_setup_data_handled_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_handler_desc_t const * const p_handler); + +/** + * @brief Set up a data transfer buffer. + * + * Returns special internal buffer that can be used in setup transfer. + * @return Internal buffer pointer + */ +void * app_usbd_core_setup_transfer_buff_get(size_t * p_size); + + +/**@brief Return internal USBD core state + * + * @return Check @ref app_usbd_state_t to find possible USBD core states + */ +app_usbd_state_t app_usbd_core_state_get(void); + + +/** + * @brief Check current feature state + * + * Function checks the state of the selected feature that was configured by the host. + * + * @param feature Feature to check. + * Only features related to the device should be checked by this function. + * + * @retval true Selected feature is set + * @retval false Selected feature is cleared + */ +bool app_usbd_core_feature_state_get(app_usbd_setup_stdfeature_t feature); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CORE_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_descriptor.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_descriptor.h new file mode 100644 index 000000000..f4ceabe3c --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_descriptor.h @@ -0,0 +1,335 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_DESCRIPTOR_H__ +#define APP_USBD_DESCRIPTOR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf.h" +#include "nrf_drv_usbd.h" +#include "app_usbd_langid.h" +#include "app_util_platform.h" + +/* Compiler support for anonymous unions */ +ANON_UNIONS_ENABLE + +/** + * @defgroup app_usbd_descriptor USB standard descriptors + * @ingroup app_usbd + * + * @brief @tagAPI52840 Module with types definitions used for standard descriptors. + * @{ + */ + +/** + * @brief Helper macro for translating unsigned 24 bit value to 2 byte raw descriptor + * */ +#define APP_USBD_U16_TO_RAW_DSC(val) (uint8_t)(val), \ + (uint8_t)(((val) / (256))) + +/** + * @brief Helper macro for translating unsigned 24 bit value to 3 byte raw descriptor + * */ +#define APP_USBD_U24_TO_RAW_DSC(val) (uint8_t)(val), \ + (uint8_t)(((val) / (256))), \ + (uint8_t)(((val) / (256 * 256))) + +/** + * @brief Helper macro for translating unsigned 32 bit value to 4 byte raw descriptor + * */ +#define APP_USBD_U32_TO_RAW_DSC(val) (uint8_t)(val), \ + (uint8_t)(((val) / (256))), \ + (uint8_t)(((val) / (256 * 256))) \ + (uint8_t)(((val) / (256 * 256 * 256))) +/** + * @brief Descriptor types + * + * Descriptor types used in two situations: + * - when processing @ref APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR SETUP request, + * the required descriptor type may be placed in wValue in HighByte. + * - As a descriptor identifier itself inside descriptor stream. + * + * According to chapter 9.6 of USB 2.0 specification, following descriptors may + * be requested directly by GetDescriptor method: + * - @ref APP_USBD_DESCRIPTOR_DEVICE + * - @ref APP_USBD_DESCRIPTOR_DEVICE_QUALIFIER (not used for FullSpeed only device) + * - @ref APP_USBD_DESCRIPTOR_CONFIGURATION + * - @ref APP_USBD_DESCRIPTOR_STRING + */ +typedef enum +{ + APP_USBD_DESCRIPTOR_DEVICE = 1, /**< Device descriptor. */ + APP_USBD_DESCRIPTOR_CONFIGURATION = 2, /**< + * Specific configuration descriptor. + * Configuration descriptor is always followed by all the related interface + * and endpoints descriptors. + */ + APP_USBD_DESCRIPTOR_STRING = 3, /**< String descriptor. */ + APP_USBD_DESCRIPTOR_INTERFACE = 4, /**< + * Interface descriptor followed by all the related endpoints descriptors. + * + * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. + * Cannot be accessed by GetDescriptor or SetDescriptor + */ + APP_USBD_DESCRIPTOR_ENDPOINT = 5, /**< + * Endpoint descriptor. + * + * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. + * Cannot be accessed by GetDescriptor or SetDescriptor + */ + APP_USBD_DESCRIPTOR_DEVICE_QUALIFIER = 6, /**< @note Not supported - used only in HighSpeed capable devices. */ + APP_USBD_DESCRIPTOR_OTHER_SPEED_CONFIGURATION = 7, /**< @note Not supported - our USB implementation supports only one speed. */ + APP_USBD_DESCRIPTOR_INTERFACE_POWER = 8, /**< @note Not supported */ + APP_USBD_DESCRIPTOR_OTG = 9, /**< @note Not supported - Our USB have not OTG functionality */ + APP_USBD_DESCRIPTOR_DEBUG = 10, /**< Debug channel descriptor if available, can be only reached by GetDescriptor */ + APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION = 11 /**< + * Descriptor used to describe that two or more interfaces are associated to the same function. + * + * @note It is returned together with @ref APP_USBD_DESCRIPTOR_CONFIGURATION. + * Cannot be accessed by GetDescriptor or SetDescriptor + */ + +} app_usbd_descriptor_t; + +/* Make all descriptors packed */ +#pragma pack(push, 1) + +/** + * @brief Common descriptor header + * + * The header that we can find on the beginning of all descriptors that contains + * the descriptor length and type. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal one of @ref app_usbd_descriptor_t. + /** Class specific descriptors values are defined inside classes. */ +} app_usbd_descriptor_header_t; + +/** + * @brief Device descriptor + * + * Descriptor used for the whole device + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_DEVICE. + uint16_t bcdUSB; //!< USB Specification Release Number in Binary-Coded Decimal + uint8_t bDeviceClass; //!< Device class code. + /**< If 0, each interface specifies its own class information. + * 0xFF for vendor-specific. + */ + uint8_t bDeviceSubClass; //!< Subclass code. + /**< If bDevice Class is set to value other than 0xFF, + * all values here are reserved for assignment by USB-IF. + */ + uint8_t bDeviceProtocol; //!< Subclass code. + /**< If 0, no specific protocol is defined on device basis. + * Each interface may define its own protocol then. + * If set to 0xFF, vendor-specific protocol is used. + */ + uint8_t bMaxPacketSize0; //!< Maximum packet size for endpoint zero. + uint16_t idVendor; //!< Vendor ID (Assigned by the USB-IF). + uint16_t idProduct; //!< Product ID (assigned by manufacturer). + uint16_t bcdDevice; //!< Device release number in binary-coded decimal. + uint8_t iManufacturer; //!< Index of string descriptor in describing manufacturer. + uint8_t iProduct; //!< Index of string descriptor in describing product. + uint8_t iSerialNumber; //!< Index of string descriptor in describing the device's serial number. + uint8_t bNumConfigurations; //!< Number of possible configurations. +} app_usbd_descriptor_device_t; + +/** + * @brief Attributes masks + * + * Masks used for attributes in configuration. + */ +typedef enum +{ + /** This is reserved descriptor that has always to be set */ + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_ALWAYS_SET_MASK = 1U << 7, + /** Attribute that informs that device is self powered */ + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_SELF_POWERED_MASK = 1U << 6, + /** Attribute that informs that device has Remove Wakeup functionality */ + APP_USBD_DESCRIPTOR_CONFIGURATION_ATTRIBUTE_REMOTE_WAKEUP_MASK = 1U << 5 +} app_usbd_descriptor_configuration_attributes_t; + +/** + * @brief Configuration descriptor + * + * Descriptor used at the beginning of configuration response. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_DEVICE. + uint16_t wTotalLength; //!< Total length of configuration data, including all descriptors returned after configuration itself. + uint8_t bNumInterfaces; //!< Number of interfaces supportedf by this configuration + uint8_t bConfigurationValue; //!< Value to use as an argument to the SetConfiguration request. + uint8_t iConfiguration; //!< Index of string descriptor describing this configuration. + uint8_t bmAttributes; //!< Configuration characteristics. + uint8_t bMaxPower; //!< Maximum power consumption. Expressed in 2 mA units. +} app_usbd_descriptor_configuration_t; + +/** + * @brief Raw descriptor - String descriptor zero + * + * String descriptor sent only as a response for GetDescriptor. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_STRING. + uint16_t wLANGID[]; //!< The array of LANGID codes supported by the device. +} app_usbd_descriptor_string0_t; + +/** + * @brief Raw descriptor - Any normal string + * + * String descriptor sent only as a response for GetDescriptor. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_STRING. + uint16_t bString[]; //!< UNICODE encoded string. +} app_usbd_descriptor_string_t; + + +/** + * @brief Interface descriptor + * + * Interface descriptor, returned as a part of configuration descriptor. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_INTERFACE. + uint8_t bInterfaceNumber; //!< Number of this interface. + uint8_t bAlternateSetting; //!< Value used to select this alternate setting. + uint8_t bNumEndpoints; //!< Number of endpoints used by this interface. + uint8_t bInterfaceClass; //!< Class code (assigned by the USB-IF). 0xff for vendor specific. + uint8_t bInterfaceSubClass; //!< Subclass code (assigned by the USB-IF). + uint8_t bInterfaceProtocol; //!< Protocol code (assigned by the USB-IF). 0xff for vendor specific. + uint8_t iInterface; //!< Index of string descriptor describing this interface. +} app_usbd_descriptor_iface_t; + +/** Offset of endpoint type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET 0 +/** Mask of endpoint type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET) + +/** Offset of endpoint synchronization type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET 2 +/** Mask of endpoint synchronization type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET) + +/** Offset of endpoint usage type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET 4 +/** Mask of endpoint usage type attribute bits */ +#define APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_MASK BF_MASK(2, APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET) + +/** + * @brief Endpoint attributes mnemonics + * + * @sa APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_MASK + * @sa APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_MASK + * @sa APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_MASK + */ +typedef enum +{ + APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_CONTROL = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_ISOCHRONOUS = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT = 3 << APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_OFFSET, + + APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_NONE = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_ASYNCHRONOUS = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_ADAPTIVE = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_SYNCHRONOUS = 3 << APP_USBD_DESCRIPTOR_EP_ATTR_SYNC_OFFSET, + + APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_DATA = 0 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_FEEDBACK = 1 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET, + APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_IMPLICIT = 2 << APP_USBD_DESCRIPTOR_EP_ATTR_USAGE_OFFSET +} app_usbd_descriptor_ep_attr_bitmap_t; + +/** + * @brief Endpoint descriptor + * + * Endpoint descriptor, returned as a part of configuration descriptor. + */ +typedef struct +{ + uint8_t bLength; //!< Size of the descriptor in bytes. + uint8_t bDescriptorType; //!< Should equal to @ref APP_USBD_DESCRIPTOR_ENDPOINT. + uint8_t bEndpointAddress; //!< Endpoint address + uint8_t bmAttributes; //!< Endpoint attributes + uint16_t wMaxPacketSize; //!< Maximum packet size this endpoint is capable of handling. + uint8_t bInterval; //!< Interval for pooling endpoint for data transfers. +} app_usbd_descriptor_ep_t; + +/** + * @brief Interface association descriptor + */ +typedef struct +{ + uint8_t bLength; //!< size of this descriptor in bytes + uint8_t bDescriptorType; //!< INTERFACE descriptor type + uint8_t bFirstInterface; //!< Number of interface + uint8_t bInterfaceCount; //!< value to select alternate setting + uint8_t bFunctionClass; //!< Class code assigned by the USB + uint8_t bFunctionSubClass;//!< Sub-class code assigned by the USB + uint8_t bFunctionProtocol;//!< Protocol code assigned by the USB + uint8_t iFunction; //!< Index of string descriptor +} app_usbd_descriptor_iad_t; + +#pragma pack(pop) +ANON_UNIONS_DISABLE + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* APP_USBD_DESCRIPTOR_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_langid.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_langid.h new file mode 100644 index 000000000..0938dd21b --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_langid.h @@ -0,0 +1,286 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_LANGID_H__ +#define APP_USBD_LANGID_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @brief This file contains LANGID variable type with all defined values + * + * This file was created using Language Identifiers (LANGIDs) 3/29/00 Version 1.0, + * available on USB web page: + * http://www.usb.org/developers/docs/USB_LANGIDs.pdf + * + * @note + * Do not include this file directly to the project. + * It is included by @file app_usbd_request.h. + */ + +/** + * Offset of the lowest bit of primary language identifier + * @sa app_usbd_langid_t + */ +#define APP_USB_LANG_OFFSET 0 + +/** + * Bitmask for a primary language identifier + * @sa app_usbd_langid_t + */ +#define APP_USB_LANG_MASK BF_MASK(10, APP_USB_LANG_OFFSET) + +/** + * Offset of the lowest bit of sub-language identifier + * @sa app_usbd_langid_t + */ +#define APP_USB_SUBLANG_OFFSET 10 + +/** + * Bitmask for a sub-language identifier + * @sa app_usbd_langid_t + */ +#define APP_USB_SUBLANG_MASK BF_MASK(6, APP_USB_SUBLANG_OFFSET) + +/** + * @brief Primary language identifiers + * + * Mnemonics for primary language identifiers. + * This mnemonics can be combined using logical OR operator with @ref app_usbd_langid_sub_t. + */ +typedef enum +{ + APP_USBD_LANG_ARABIC = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Arabic */ + APP_USBD_LANG_BULGARIAN = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Bulgarian */ + APP_USBD_LANG_CATALAN = 0x03U << ( APP_USB_LANG_OFFSET ), /**< Catalan */ + APP_USBD_LANG_CHINESE = 0x04U << ( APP_USB_LANG_OFFSET ), /**< Chinese */ + APP_USBD_LANG_CZECH = 0x05U << ( APP_USB_LANG_OFFSET ), /**< Czech */ + APP_USBD_LANG_DANISH = 0x06U << ( APP_USB_LANG_OFFSET ), /**< Danish */ + APP_USBD_LANG_GERMAN = 0x07U << ( APP_USB_LANG_OFFSET ), /**< German */ + APP_USBD_LANG_GREEK = 0x08U << ( APP_USB_LANG_OFFSET ), /**< Greek */ + APP_USBD_LANG_ENGLISH = 0x09U << ( APP_USB_LANG_OFFSET ), /**< English */ + APP_USBD_LANG_SPANISH = 0x0aU << ( APP_USB_LANG_OFFSET ), /**< Spanish */ + APP_USBD_LANG_FINNISH = 0x0bU << ( APP_USB_LANG_OFFSET ), /**< Finnish */ + APP_USBD_LANG_FRENCH = 0x0cU << ( APP_USB_LANG_OFFSET ), /**< French */ + APP_USBD_LANG_HEBREW = 0x0dU << ( APP_USB_LANG_OFFSET ), /**< Hebrew */ + APP_USBD_LANG_HUNGARIAN = 0x0eU << ( APP_USB_LANG_OFFSET ), /**< Hungarian */ + APP_USBD_LANG_ICELANDIC = 0x0fU << ( APP_USB_LANG_OFFSET ), /**< Icelandic */ + APP_USBD_LANG_ITALIAN = 0x10U << ( APP_USB_LANG_OFFSET ), /**< Italian */ + APP_USBD_LANG_JAPANESE = 0x11U << ( APP_USB_LANG_OFFSET ), /**< Japanese */ + APP_USBD_LANG_KOREAN = 0x12U << ( APP_USB_LANG_OFFSET ), /**< Korean */ + APP_USBD_LANG_DUTCH = 0x13U << ( APP_USB_LANG_OFFSET ), /**< Dutch */ + APP_USBD_LANG_NORWEGIAN = 0x14U << ( APP_USB_LANG_OFFSET ), /**< Norwegian */ + APP_USBD_LANG_POLISH = 0x15U << ( APP_USB_LANG_OFFSET ), /**< Polish */ + APP_USBD_LANG_PORTUGUESE = 0x16U << ( APP_USB_LANG_OFFSET ), /**< Portuguese */ + APP_USBD_LANG_ROMANIAN = 0x18U << ( APP_USB_LANG_OFFSET ), /**< Romanian */ + APP_USBD_LANG_RUSSIAN = 0x19U << ( APP_USB_LANG_OFFSET ), /**< Russian */ + APP_USBD_LANG_CROATIAN = 0x1aU << ( APP_USB_LANG_OFFSET ), /**< Croatian */ + APP_USBD_LANG_SERBIAN = 0x1aU << ( APP_USB_LANG_OFFSET ), /**< Serbian */ + APP_USBD_LANG_SLOVAK = 0x1bU << ( APP_USB_LANG_OFFSET ), /**< Slovak */ + APP_USBD_LANG_ALBANIAN = 0x1cU << ( APP_USB_LANG_OFFSET ), /**< Albanian */ + APP_USBD_LANG_SWEDISH = 0x1dU << ( APP_USB_LANG_OFFSET ), /**< Swedish */ + APP_USBD_LANG_THAI = 0x1eU << ( APP_USB_LANG_OFFSET ), /**< Thai */ + APP_USBD_LANG_TURKISH = 0x1fU << ( APP_USB_LANG_OFFSET ), /**< Turkish */ + APP_USBD_LANG_URDU = 0x20U << ( APP_USB_LANG_OFFSET ), /**< Urdu */ + APP_USBD_LANG_INDONESIAN = 0x21U << ( APP_USB_LANG_OFFSET ), /**< Indonesian */ + APP_USBD_LANG_UKRANIAN = 0x22U << ( APP_USB_LANG_OFFSET ), /**< Ukrainian */ + APP_USBD_LANG_BELARUSIAN = 0x23U << ( APP_USB_LANG_OFFSET ), /**< Belarusian */ + APP_USBD_LANG_SLOVENIAN = 0x24U << ( APP_USB_LANG_OFFSET ), /**< Slovenian */ + APP_USBD_LANG_ESTONIAN = 0x25U << ( APP_USB_LANG_OFFSET ), /**< Estonian */ + APP_USBD_LANG_LATVIAN = 0x26U << ( APP_USB_LANG_OFFSET ), /**< Latvian */ + APP_USBD_LANG_LITHUANIAN = 0x27U << ( APP_USB_LANG_OFFSET ), /**< Lithuanian */ + APP_USBD_LANG_FARSI = 0x29U << ( APP_USB_LANG_OFFSET ), /**< Farsi */ + APP_USBD_LANG_VIETNAMESE = 0x2aU << ( APP_USB_LANG_OFFSET ), /**< Vietnamese */ + APP_USBD_LANG_ARMENIAN = 0x2bU << ( APP_USB_LANG_OFFSET ), /**< Armenian */ + APP_USBD_LANG_AZERI = 0x2cU << ( APP_USB_LANG_OFFSET ), /**< Azeri */ + APP_USBD_LANG_BASQUE = 0x2dU << ( APP_USB_LANG_OFFSET ), /**< Basque */ + APP_USBD_LANG_MACEDONIAN = 0x2fU << ( APP_USB_LANG_OFFSET ), /**< Macedonian */ + APP_USBD_LANG_AFRIKAANS = 0x36U << ( APP_USB_LANG_OFFSET ), /**< Afrikaans */ + APP_USBD_LANG_GEORGIAN = 0x37U << ( APP_USB_LANG_OFFSET ), /**< Georgian */ + APP_USBD_LANG_FAEROESE = 0x38U << ( APP_USB_LANG_OFFSET ), /**< Faeroese */ + APP_USBD_LANG_HINDI = 0x39U << ( APP_USB_LANG_OFFSET ), /**< Hindi */ + APP_USBD_LANG_MALAY = 0x3eU << ( APP_USB_LANG_OFFSET ), /**< Malay */ + APP_USBD_LANG_KAZAK = 0x3fU << ( APP_USB_LANG_OFFSET ), /**< Kazak */ + APP_USBD_LANG_SWAHILI = 0x41U << ( APP_USB_LANG_OFFSET ), /**< Swahili */ + APP_USBD_LANG_UZBEK = 0x43U << ( APP_USB_LANG_OFFSET ), /**< Uzbek */ + APP_USBD_LANG_TATAR = 0x44U << ( APP_USB_LANG_OFFSET ), /**< Tatar */ + APP_USBD_LANG_BENGALI = 0x45U << ( APP_USB_LANG_OFFSET ), /**< Bengali */ + APP_USBD_LANG_PUNJABI = 0x46U << ( APP_USB_LANG_OFFSET ), /**< Punjabi */ + APP_USBD_LANG_GUJARATI = 0x47U << ( APP_USB_LANG_OFFSET ), /**< Gujarati */ + APP_USBD_LANG_ORIYA = 0x48U << ( APP_USB_LANG_OFFSET ), /**< Oriya */ + APP_USBD_LANG_TAMIL = 0x49U << ( APP_USB_LANG_OFFSET ), /**< Tamil */ + APP_USBD_LANG_TELUGU = 0x4aU << ( APP_USB_LANG_OFFSET ), /**< Telugu */ + APP_USBD_LANG_KANNADA = 0x4bU << ( APP_USB_LANG_OFFSET ), /**< Kannada */ + APP_USBD_LANG_MALAYALAM = 0x4cU << ( APP_USB_LANG_OFFSET ), /**< Malayalam */ + APP_USBD_LANG_ASSAMESE = 0x4dU << ( APP_USB_LANG_OFFSET ), /**< Assamese */ + APP_USBD_LANG_MARATHI = 0x4eU << ( APP_USB_LANG_OFFSET ), /**< Marathi */ + APP_USBD_LANG_SANSKRIT = 0x4fU << ( APP_USB_LANG_OFFSET ), /**< Sanskrit */ + APP_USBD_LANG_KONKANI = 0x57U << ( APP_USB_LANG_OFFSET ), /**< Konkani */ + APP_USBD_LANG_MANIPURI = 0x58U << ( APP_USB_LANG_OFFSET ), /**< Manipuri */ + APP_USBD_LANG_SINDHI = 0x59U << ( APP_USB_LANG_OFFSET ), /**< Sindhi */ + APP_USBD_LANG_KASHMIRI = 0x60U << ( APP_USB_LANG_OFFSET ), /**< Kashmiri */ + APP_USBD_LANG_NEPALI = 0x61U << ( APP_USB_LANG_OFFSET ), /**< Nepali */ + APP_USBD_LANG_HID = 0xffU << ( APP_USB_LANG_OFFSET ), /**< Reserved for USB HID Class use */ +}app_usbd_langid_primary_t; + +/** + * @brief Sublanguage identifiers + * + * Mnemonics with sublanguage values. + * Use them in combination with @ref app_usbd_langid_primary_t. + */ +typedef enum +{ + APP_USBD_SUBLANG_ARABIC_SAUDI_ARABIA = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Saudi Arabia) */ + APP_USBD_SUBLANG_ARABIC_IRAQ = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Iraq) */ + APP_USBD_SUBLANG_ARABIC_EGYPT = 0x03U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Egypt) */ + APP_USBD_SUBLANG_ARABIC_LIBYA = 0x04U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Libya) */ + APP_USBD_SUBLANG_ARABIC_ALGERIA = 0x05U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Algeria) */ + APP_USBD_SUBLANG_ARABIC_MOROCCO = 0x06U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Morocco) */ + APP_USBD_SUBLANG_ARABIC_TUNISIA = 0x07U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Tunisia) */ + APP_USBD_SUBLANG_ARABIC_OMAN = 0x08U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Oman) */ + APP_USBD_SUBLANG_ARABIC_YEMEN = 0x09U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Yemen) */ + APP_USBD_SUBLANG_ARABIC_SYRIA = 0x10U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Syria) */ + APP_USBD_SUBLANG_ARABIC_JORDAN = 0x11U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Jordan) */ + APP_USBD_SUBLANG_ARABIC_LEBANON = 0x12U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Lebanon) */ + APP_USBD_SUBLANG_ARABIC_KUWAIT = 0x13U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Kuwait) */ + APP_USBD_SUBLANG_ARABIC_UAE = 0x14U << ( APP_USB_LANG_OFFSET ), /**< Arabic (U.A.E.) */ + APP_USBD_SUBLANG_ARABIC_BAHRAIN = 0x15U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Bahrain) */ + APP_USBD_SUBLANG_ARABIC_QATAR = 0x16U << ( APP_USB_LANG_OFFSET ), /**< Arabic (Qatar) */ + APP_USBD_SUBLANG_AZERI_CYRILLIC = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Azeri (Cyrillic) */ + APP_USBD_SUBLANG_AZERI_LATIN = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Azeri (Latin) */ + APP_USBD_SUBLANG_CHINESE_TRADITIONAL = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Chinese (Traditional) */ + APP_USBD_SUBLANG_CHINESE_SIMPLIFIED = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Chinese (Simplified) */ + APP_USBD_SUBLANG_CHINESE_HONGKONG = 0x03U << ( APP_USB_LANG_OFFSET ), /**< Chinese (Hong Kong SAR, PRC) */ + APP_USBD_SUBLANG_CHINESE_SINGAPORE = 0x04U << ( APP_USB_LANG_OFFSET ), /**< Chinese (Singapore) */ + APP_USBD_SUBLANG_CHINESE_MACAU = 0x05U << ( APP_USB_LANG_OFFSET ), /**< Chinese (Macau SAR) */ + APP_USBD_SUBLANG_DUTCH = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Dutch */ + APP_USBD_SUBLANG_DUTCH_BELGIAN = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Dutch (Belgian) */ + APP_USBD_SUBLANG_ENGLISH_US = 0x01U << ( APP_USB_LANG_OFFSET ), /**< English (US) */ + APP_USBD_SUBLANG_ENGLISH_UK = 0x02U << ( APP_USB_LANG_OFFSET ), /**< English (UK) */ + APP_USBD_SUBLANG_ENGLISH_AUS = 0x03U << ( APP_USB_LANG_OFFSET ), /**< English (Australian) */ + APP_USBD_SUBLANG_ENGLISH_CAN = 0x04U << ( APP_USB_LANG_OFFSET ), /**< English (Canadian) */ + APP_USBD_SUBLANG_ENGLISH_NZ = 0x05U << ( APP_USB_LANG_OFFSET ), /**< English (New Zealand) */ + APP_USBD_SUBLANG_ENGLISH_EIRE = 0x06U << ( APP_USB_LANG_OFFSET ), /**< English (Ireland) */ + APP_USBD_SUBLANG_ENGLISH_SOUTH_AFRICA = 0x07U << ( APP_USB_LANG_OFFSET ), /**< English (South Africa) */ + APP_USBD_SUBLANG_ENGLISH_JAMAICA = 0x08U << ( APP_USB_LANG_OFFSET ), /**< English (Jamaica) */ + APP_USBD_SUBLANG_ENGLISH_CARIBBEAN = 0x09U << ( APP_USB_LANG_OFFSET ), /**< English (Caribbean) */ + APP_USBD_SUBLANG_ENGLISH_BELIZE = 0x0aU << ( APP_USB_LANG_OFFSET ), /**< English (Belize) */ + APP_USBD_SUBLANG_ENGLISH_TRINIDAD = 0x0bU << ( APP_USB_LANG_OFFSET ), /**< English (Trinidad) */ + APP_USBD_SUBLANG_ENGLISH_PHILIPPINES = 0x0cU << ( APP_USB_LANG_OFFSET ), /**< English (Zimbabwe) */ + APP_USBD_SUBLANG_ENGLISH_ZIMBABWE = 0x0dU << ( APP_USB_LANG_OFFSET ), /**< English (Philippines) */ + APP_USBD_SUBLANG_FRENCH = 0x01U << ( APP_USB_LANG_OFFSET ), /**< French */ + APP_USBD_SUBLANG_FRENCH_BELGIAN = 0x02U << ( APP_USB_LANG_OFFSET ), /**< French (Belgian) */ + APP_USBD_SUBLANG_FRENCH_CANADIAN = 0x03U << ( APP_USB_LANG_OFFSET ), /**< French (Canadian) */ + APP_USBD_SUBLANG_FRENCH_SWISS = 0x04U << ( APP_USB_LANG_OFFSET ), /**< French (Swiss) */ + APP_USBD_SUBLANG_FRENCH_LUXEMBOURG = 0x05U << ( APP_USB_LANG_OFFSET ), /**< French (Luxembourg) */ + APP_USBD_SUBLANG_FRENCH_MONACO = 0x06U << ( APP_USB_LANG_OFFSET ), /**< French (Monaco) */ + APP_USBD_SUBLANG_GERMAN = 0x01U << ( APP_USB_LANG_OFFSET ), /**< German */ + APP_USBD_SUBLANG_GERMAN_SWISS = 0x02U << ( APP_USB_LANG_OFFSET ), /**< German (Swiss) */ + APP_USBD_SUBLANG_GERMAN_AUSTRIAN = 0x03U << ( APP_USB_LANG_OFFSET ), /**< German (Austrian) */ + APP_USBD_SUBLANG_GERMAN_LUXEMBOURG = 0x04U << ( APP_USB_LANG_OFFSET ), /**< German (Luxembourg) */ + APP_USBD_SUBLANG_GERMAN_LIECHTENSTEIN = 0x05U << ( APP_USB_LANG_OFFSET ), /**< German (Liechtenstein) */ + APP_USBD_SUBLANG_ITALIAN = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Italian */ + APP_USBD_SUBLANG_ITALIAN_SWISS = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Italian (Swiss) */ + APP_USBD_SUBLANG_KASHMIRI_INDIA = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Kashmiri (India) */ + APP_USBD_SUBLANG_KOREAN = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Korean */ + APP_USBD_SUBLANG_LITHUANIAN = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Lithuanian */ + APP_USBD_SUBLANG_MALAY_MALAYSIA = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Malay (Malaysia) */ + APP_USBD_SUBLANG_MALAY_BRUNEI_DARUSSALAM = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Malay (Brunei Darassalam) */ + APP_USBD_SUBLANG_NEPALI_INDIA = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Nepali (India) */ + APP_USBD_SUBLANG_NORWEGIAN_BOKMAL = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Norwegian (Bokmal) */ + APP_USBD_SUBLANG_NORWEGIAN_NYNORSK = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Norwegian (Nynorsk) */ + APP_USBD_SUBLANG_PORTUGUESE = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Portuguese (Brazilian) */ + APP_USBD_SUBLANG_PORTUGUESE_BRAZILIAN = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Portuguese */ + APP_USBD_SUBLANG_SERBIAN_LATIN = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Serbian (Latin) */ + APP_USBD_SUBLANG_SERBIAN_CYRILLIC = 0x03U << ( APP_USB_LANG_OFFSET ), /**< Serbian (Cyrillic) */ + APP_USBD_SUBLANG_SPANISH = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Castilian) */ + APP_USBD_SUBLANG_SPANISH_MEXICAN = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Mexican) */ + APP_USBD_SUBLANG_SPANISH_MODERN = 0x03U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Modern) */ + APP_USBD_SUBLANG_SPANISH_GUATEMALA = 0x04U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Guatemala) */ + APP_USBD_SUBLANG_SPANISH_COSTA_RICA = 0x05U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Costa Rica) */ + APP_USBD_SUBLANG_SPANISH_PANAMA = 0x06U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Panama) */ + APP_USBD_SUBLANG_SPANISH_DOMINICAN_REPUBLIC = 0x07U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Dominican Republic) */ + APP_USBD_SUBLANG_SPANISH_VENEZUELA = 0x08U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Venezuela) */ + APP_USBD_SUBLANG_SPANISH_COLOMBIA = 0x09U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Colombia) */ + APP_USBD_SUBLANG_SPANISH_PERU = 0x0aU << ( APP_USB_LANG_OFFSET ), /**< Spanish (Peru) */ + APP_USBD_SUBLANG_SPANISH_ARGENTINA = 0x0bU << ( APP_USB_LANG_OFFSET ), /**< Spanish (Argentina) */ + APP_USBD_SUBLANG_SPANISH_ECUADOR = 0x0cU << ( APP_USB_LANG_OFFSET ), /**< Spanish (Ecuador) */ + APP_USBD_SUBLANG_SPANISH_CHILE = 0x0dU << ( APP_USB_LANG_OFFSET ), /**< Spanish (Chile) */ + APP_USBD_SUBLANG_SPANISH_URUGUAY = 0x0eU << ( APP_USB_LANG_OFFSET ), /**< Spanish (Uruguay) */ + APP_USBD_SUBLANG_SPANISH_PARAGUAY = 0x0fU << ( APP_USB_LANG_OFFSET ), /**< Spanish (Paraguay) */ + APP_USBD_SUBLANG_SPANISH_BOLIVIA = 0x10U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Bolivia) */ + APP_USBD_SUBLANG_SPANISH_EL_SALVADOR = 0x11U << ( APP_USB_LANG_OFFSET ), /**< Spanish (El Salvador) */ + APP_USBD_SUBLANG_SPANISH_HONDURAS = 0x12U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Honduras) */ + APP_USBD_SUBLANG_SPANISH_NICARAGUA = 0x13U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Nicaragua) */ + APP_USBD_SUBLANG_SPANISH_PUERTO_RICO = 0x14U << ( APP_USB_LANG_OFFSET ), /**< Spanish (Puerto Rico) */ + APP_USBD_SUBLANG_SWEDISH = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Swedish */ + APP_USBD_SUBLANG_SWEDISH_FINLAND = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Swedish (Finland) */ + APP_USBD_SUBLANG_URDU_PAKISTAN = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Urdu (Pakistan) */ + APP_USBD_SUBLANG_URDU_INDIA = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Urdu (India) */ + APP_USBD_SUBLANG_UZBEK_LATIN = 0x01U << ( APP_USB_LANG_OFFSET ), /**< Uzbek (Latin) */ + APP_USBD_SUBLANG_UZBEK_CYRILLIC = 0x02U << ( APP_USB_LANG_OFFSET ), /**< Uzbek (Cyrillic) */ + APP_USBD_SUBLANG_HID_USAGE_DATA_DESCRIPTOR = 0x01U << ( APP_USB_LANG_OFFSET ), /**< HID (Usage Data Descriptor) */ + APP_USBD_SUBLANG_HID_VENDOR_DEFINED_1 = 0x3cU << ( APP_USB_LANG_OFFSET ), /**< HID (Vendor Defined 1) */ + APP_USBD_SUBLANG_HID_VENDOR_DEFINED_2 = 0x3dU << ( APP_USB_LANG_OFFSET ), /**< HID (Vendor Defined 2) */ + APP_USBD_SUBLANG_HID_VENDOR_DEFINED_3 = 0x3eU << ( APP_USB_LANG_OFFSET ), /**< HID (Vendor Defined 3) */ + APP_USBD_SUBLANG_HID_VENDOR_DEFINED_4 = 0x3fU << ( APP_USB_LANG_OFFSET ), /**< HID (Vendor Defined 4) */ +}app_usbd_langid_sub_t; + +/** + * @brief LANGID variable + * + * The LANGID value is composed from: + * - 10-bit (9-0) of Primary Language Identifiers + * - 6-bit (15-10) of Sublanguage Identifiers. + * + * @sa app_usbd_langid_primary_t + * @sa app_usbd_langid_sub_t + */ +typedef uint16_t app_usbd_langid_t; + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_LANGID_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_request.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_request.h new file mode 100644 index 000000000..e906933ab --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_request.h @@ -0,0 +1,355 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_REQUEST_H__ +#define APP_USBD_REQUEST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_drv_usbd.h" +#include "app_usbd_descriptor.h" +#include "app_util_platform.h" + +/* Compiler support for anonymous unions */ +ANON_UNIONS_ENABLE + +#pragma pack(push, 1) + +/** + * @defgroup app_usbd_request USB standard requests + * @ingroup app_usbd + * + * @brief @tagAPI52840 Module with types definitions used for standard requests processing. + * @{ + */ + +/** + * @brief Recipient bit-field in request type + * + * Bits 4...0 + */ +#define APP_USBD_SETUP_REQ_BF_REC BF_CX(5, 0) + +/** + * @brief Type bit-field in request type + * + * Bits 6...5 + */ +#define APP_USBD_SETUP_REQ_BF_TYP BF_CX(2, 5) + +/** + * @brief Direction bit-field in request type + * + * Bit 7 + */ +#define APP_USBD_SETUP_REQ_BF_DIR BF_CX(1, 7) + +/** + * @brief Recipient enumerator. + * + * @note It is part of @ref app_usbd_setup_reqtype_t variable type. + */ +typedef enum { + APP_USBD_SETUP_REQREC_DEVICE = 0x0, /**< The whole device is a request target */ + APP_USBD_SETUP_REQREC_INTERFACE = 0x1, /**< Selected interface is a request target */ + APP_USBD_SETUP_REQREC_ENDPOINT = 0x2, /**< Selected endpoint is a request target */ + APP_USBD_SETUP_REQREC_OTHER = 0x3 /**< Other element is a request target */ +} app_usbd_setup_reqrec_t; + +/** + * @brief Request type enumerator. + * + * @note It is part of @ref app_usbd_setup_reqtype_t variable type. + */ +typedef enum { + APP_USBD_SETUP_REQTYPE_STD = 0x0, /**< Standard request */ + APP_USBD_SETUP_REQTYPE_CLASS = 0x1, /**< Class specific request */ + APP_USBD_SETUP_REQTYPE_VENDOR = 0x2 /**< Vendor specific request */ +} app_usbd_setup_reqtype_t; + +/** + * @brief Direction of setup command + * + * @note It is part of @ref app_usbd_setup_reqtype_t variable type. + */ +typedef enum { + APP_USBD_SETUP_REQDIR_OUT = 0x0, /**< Host to device */ + APP_USBD_SETUP_REQDIR_IN = 0x1, /**< Device to host */ +} app_usbd_setup_reqdir_t; + + +/** + * @brief Standard requests + * + * Enumerator for standard requests values + */ +typedef enum { + APP_USBD_SETUP_STDREQ_GET_STATUS = 0x00, /**< + * Targets: Device, Interface, Endpoint + * Expected SETUP frame format: + * - wValue: Zero + * - wIndex: Zero, (lb): Interface or Endpoint + * - wLength: 2 + * - Data:2 bytes of data, depending on targets + * - Device: + * - D15..D2: Reserved (Reset to zero) + * - D1: Remove Wakeup + * - D0: Self Powered + * - Interface: + * - D15..D0: Reserved (Reset to zero) + * - Endpoint: + * - D15..D1: Reserved (Reset to zero) + * - D0: Halt + */ + APP_USBD_SETUP_STDREQ_CLEAR_FEATURE = 0x01, /**< + * Targets: Device, Interface, Endpoint + * Expected SETUP frame format: + * - wValue: Feature selector (@ref app_usbd_setup_stdfeature_t) + * - wIndex: Zero, Interface or Endpoint + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_SET_FEATURE = 0x03, /**< + * Targets: Device, Interface, Endpoint + * Expected SETUP frame format: + * - wValue: Feature selector (@ref app_usbd_setup_stdfeature_t) + * - wIndex: Zero, Interface or Endpoint + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_SET_ADDRESS = 0x05, /**< + * @note This SETUP request is processed in hardware. + * Use it only to mark current USB state. + * + * Targets: Device + * Expected SETUP frame format: + * - wValue: New device address + * - wIndex: 0 + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR = 0x06, /**< + * Targets: Device + * - wValue: (hb): Descriptor Type and (lb): Descriptor Index + * - wIndex: Zero of Language ID + * - wLength: Descriptor Length + * - Data: Descriptor + */ + APP_USBD_SETUP_STDREQ_SET_DESCRIPTOR = 0x07, /**< + * Not supported - Stall when called. + */ + APP_USBD_SETUP_STDREQ_GET_CONFIGURATION = 0x08, /**< + * Target: Device + * Expected SETUP frame format: + * - wValue: 0 + * - wIndex: 0 + * - wLength: 1 + * - Data: Configuration value + */ + APP_USBD_SETUP_STDREQ_SET_CONFIGURATION = 0x09, /**< + * Target: Device + * Expected SETUP frame format: + * - wValue: (lb): Configuration value + * - wIndex: 0 + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_GET_INTERFACE = 0x0A, /**< + * Target: Interface + * Expected SETUP frame format: + * - wValue: 0 + * - wIndex: Interface + * - wLength: 1 + * - Data: Alternate setting + */ + APP_USBD_SETUP_STDREQ_SET_INTERFACE = 0x0B, /**< + * Target: Interface + * Expected SETUP frame format: + * - wValue: Alternate setting + * - wIndex: Interface + * - wLength: 0 + * - Data: None + */ + APP_USBD_SETUP_STDREQ_SYNCH_FRAME = 0x0C /**< + * Target: Endpoint + * Expected SETUP frame format: + * - wValue: 0 + * - wIndex: Endpoint + * - wLength: 2 + * - Data: Frame Number + * + * @note + * This request is used only in connection with isochronous endpoints. + * This is rarely used and probably we would not need to support it. + */ +} app_usbd_setup_stdrequest_t; + +/** + * @brief Standard feature selectors + * + * Standard features that may be disabled or enabled by + * @ref APP_USBD_SETUP_STDREQ_CLEAR_FEATURE or @ref APP_USBD_SETUP_STDREQ_SET_FEATURE + */ +typedef enum { + APP_USBD_SETUP_STDFEATURE_DEVICE_REMOTE_WAKEUP = 1, /**< Remote wakeup feature. + * + * Target: Device only + */ + APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT = 0, /**< Stall or clear the endpoint. + * + * Target: Endpoint different than default (0) + */ + APP_USBD_SETUP_STDFEATURE_TEST_MODE = 2 /**< Upstream port test mode. + * Power has to be cycled to exit test mode. + * This feature cannot be cleared. + * + * Target: Device only + * + * @note + * It should only be supported by HighSpeed capable devices. + * Not supported in this library. + */ +} app_usbd_setup_stdfeature_t; + + +/** + * @brief Universal way to access 16 bit values and its parts + */ +typedef union { + uint16_t w; //!< 16 bit access + struct + { + uint8_t lb; //!< Low byte access + uint8_t hb; //!< High byte access + }; +} app_usbd_setup_w_t; + +/** + * @brief Internal redefinition of setup structure + * + * Redefinition of the structure to simplify changes in the future + * if required - app_usbd API would present setup data using app_usbd_setup_t. + * + * The structure layout is always the same like @ref nrf_drv_usbd_setup_t + */ +typedef struct { + uint8_t bmRequestType; //!< Setup type bitfield + uint8_t bmRequest; //!< One of @ref app_usbd_setup_stdrequest_t values or class dependent one. + app_usbd_setup_w_t wValue; //!< byte 2, 3 + app_usbd_setup_w_t wIndex; //!< byte 4, 5 + app_usbd_setup_w_t wLength; //!< byte 6, 7 +} app_usbd_setup_t; + +#pragma pack(pop) + + +/** + * @brief Extract recipient from request type + * + * @param[in] bmRequestType + * + * @return Extracted recipient field from request type value + */ +static inline app_usbd_setup_reqrec_t app_usbd_setup_req_rec(uint8_t bmRequestType) +{ + return (app_usbd_setup_reqrec_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_REC); +} + +/** + * @brief Extract type from request type + * + * @param[in] bmRequestType + * + * @return Extracted type field from request type value + */ +static inline app_usbd_setup_reqtype_t app_usbd_setup_req_typ(uint8_t bmRequestType) +{ + return (app_usbd_setup_reqtype_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_TYP); +} + + +/** + * @brief Extract direction from request type + * + * @param[in] bmRequestType + * + * @return Extracted direction field from request type value + */ +static inline app_usbd_setup_reqdir_t app_usbd_setup_req_dir(uint8_t bmRequestType) +{ + return (app_usbd_setup_reqdir_t)BF_CX_GET(bmRequestType, APP_USBD_SETUP_REQ_BF_DIR); +} + +/** + * @brief Make request type value + * + * @param[in] rec Recipient + * @param[in] typ Request type + * @param[in] dir Direction + * + * @return Assembled request type value + */ +static inline uint8_t app_usbd_setup_req_val(app_usbd_setup_reqrec_t rec, + app_usbd_setup_reqtype_t typ, + app_usbd_setup_reqdir_t dir) +{ + uint32_t bmRequestType = ( + BF_CX_VAL(rec, APP_USBD_SETUP_REQ_BF_REC) | + BF_CX_VAL(typ, APP_USBD_SETUP_REQ_BF_TYP) | + BF_CX_VAL(dir, APP_USBD_SETUP_REQ_BF_DIR) + ); + + ASSERT(bmRequestType < 256U); + return (uint8_t)bmRequestType; +} + + +ANON_UNIONS_DISABLE +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_REQUEST_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c b/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c new file mode 100644 index 000000000..7b42e69b8 --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.c @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2016 - 2017, 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_config.h" +#if APP_USBD_ENABLED +#include "app_usbd_string_desc.h" +#include "app_usbd_langid.h" +#include "app_usbd_core.h" +#include "nordic_common.h" + +/** + * @defgroup app_usbd_string_desc + * @ingroup app_usbd + * + * USBD string descriptors management + * @{ + */ + +/** + * @brief Array with language identifiers + * + * This array would be used to search the proper string for selected language. + */ +static const uint16_t m_langids[] = { APP_USBD_STRINGS_LANGIDS }; + +/** + * @brief Language ID descriptor + * + * Language + */ + + +/** + * @brief Mnemonics for the string positions in the array + * + * The mnemonics for the indexes of the strings inside the string array. + */ +enum { + APP_USBD_STRING_ID_LANGIDS_ARRAY_POS = 0, /**< Supported language identifiers */ + APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS, /**< Manufacturer name */ + APP_USBD_STRING_ID_PRODUCT_ARRAY_POS, /**< Product name */ + APP_USBD_STRING_ID_SERIAL_ARRAY_POS, /**< Serial number */ +#define X(mnemonic, str_idx, ...) CONCAT_2(mnemonic, _ARRAY_POS), + APP_USBD_STRINGS_USER +#undef X +}; + +/** + * @brief String index into internal array index conversion table + * + * The array that transforms the USB string indexes into internal array position. + * @note Value 0 used to mark non-existing string. + */ +static const uint8_t m_string_translation[APP_USBD_STRING_ID_CNT] = +{ + [APP_USBD_STRING_ID_LANGIDS ] = APP_USBD_STRING_ID_LANGIDS_ARRAY_POS, + [APP_USBD_STRING_ID_MANUFACTURER] = APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS, + [APP_USBD_STRING_ID_PRODUCT ] = APP_USBD_STRING_ID_PRODUCT_ARRAY_POS, + [APP_USBD_STRING_ID_SERIAL ] = APP_USBD_STRING_ID_SERIAL_ARRAY_POS, +#define X(mnemonic, str_idx, ...) [mnemonic] = CONCAT_2(mnemonic, _ARRAY_POS), + APP_USBD_STRINGS_USER +#undef X +}; + +#ifndef APP_USBD_STRINGS_MANUFACTURER_EXTERN +#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 +#endif + +#ifndef APP_USBD_STRINGS_PRODUCT_EXTERN +#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 +#endif + +#ifndef APP_USBD_STRING_SERIAL_EXTERN +#define APP_USBD_STRING_SERIAL_EXTERN 0 +#endif + +#if APP_USBD_STRINGS_MANUFACTURER_EXTERN +extern uint16_t APP_USBD_STRINGS_MANUFACTURER[]; +#endif + +#if APP_USBD_STRINGS_PRODUCT_EXTERN +extern uint16_t APP_USBD_STRINGS_PRODUCT[]; +#endif + +#if APP_USBD_STRING_SERIAL_EXTERN +extern uint16_t APP_USBD_STRING_SERIAL[]; +#endif + + +/** + * @brief String descriptors table + * */ +static const uint16_t * m_string_dsc[APP_USBD_STRING_ID_CNT][ARRAY_SIZE(m_langids)] = +{ + [APP_USBD_STRING_ID_LANGIDS_ARRAY_POS] = { APP_USBD_STRING_DESC(APP_USBD_STRINGS_LANGIDS) }, + [APP_USBD_STRING_ID_MANUFACTURER_ARRAY_POS] = { APP_USBD_STRINGS_MANUFACTURER }, + [APP_USBD_STRING_ID_PRODUCT_ARRAY_POS] = { APP_USBD_STRINGS_PRODUCT }, + [APP_USBD_STRING_ID_SERIAL_ARRAY_POS] = { APP_USBD_STRING_SERIAL }, +#define X(mnemonic, str_idx, ...) [CONCAT_2(mnemonic, _ARRAY_POS)] = { __VA_ARGS__ }, + APP_USBD_STRINGS_USER +#undef X +}; + + + +uint16_t const * app_usbd_string_desc_get(app_usbd_string_desc_idx_t idx, uint16_t langid) +{ + /* LANGID string */ + if (APP_USBD_STRING_ID_LANGIDS == idx) + { + return m_string_dsc[APP_USBD_STRING_ID_LANGIDS_ARRAY_POS][0]; + } + + /* Searching for the language */ + uint8_t lang_idx = 0; + if (ARRAY_SIZE(m_langids) > 1) + { + while (m_langids[lang_idx] != langid) + { + if (++lang_idx >= ARRAY_SIZE(m_langids)) + { + return NULL; + } + } + } + + /* Get the string index in array */ + if (idx >= ARRAY_SIZE(m_string_translation)) + { + return NULL; + } + + uint8_t str_pos = m_string_translation[idx]; + if (str_pos == 0) + { + return NULL; + } + + uint16_t const * p_str = m_string_dsc[str_pos][lang_idx]; + if ((ARRAY_SIZE(m_langids) > 1) && (lang_idx != 0)) + { + if (p_str == NULL) + { + p_str = m_string_dsc[str_pos][0]; + } + } + + return p_str; +} + +/** @} */ +#endif // APP_USBD_ENABLED diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.h new file mode 100644 index 000000000..e5791d54f --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_string_desc.h @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_STRING_DESC_H__ +#define APP_USBD_STRING_DESC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "sdk_common.h" +#include "app_usbd.h" +#include "app_usbd_string_config.h" + +/** + * @defgroup app_usbd_string_desc USBD string descriptors + * @ingroup app_usbd + * + * @brief @tagAPI52840 USBD string descriptors management. + * @{ + */ + +/** + * @brief USB string initialization + * + * Macro that creates initialization values for USB string. + * The format contains header and string itself. + * The string should be declared as an array of uint16_t type. + * + * @param[in] ... Comma separated string letters or language ID. + * @return String descriptor initialization data. + */ +#define APP_USBD_STRING_DESC(...) (const uint16_t[]){ \ + (0xff & (sizeof((uint16_t[]){__VA_ARGS__}) + 2)) | \ + ((uint16_t)APP_USBD_DESCRIPTOR_STRING) << 8, \ + __VA_ARGS__ } + +/** + * @brief USB string descriptors ID's + */ +typedef enum { + APP_USBD_STRING_ID_LANGIDS = 0, /**< Supported language identifiers */ + APP_USBD_STRING_ID_MANUFACTURER, /**< Manufacturer name */ + APP_USBD_STRING_ID_PRODUCT, /**< Product name */ + APP_USBD_STRING_ID_SERIAL, /**< Serial number */ + +#define X(mnemonic, str_idx, ...) mnemonic str_idx, + APP_USBD_STRINGS_USER +#undef X + + APP_USBD_STRING_ID_CNT /**< Total number of identifiers */ +} app_usbd_string_desc_idx_t; + +/** + * @brief Get string descriptor + * + * @param[in] idx String descriptor index + * @param[in] langid Selected language for the string + * @return String descriptor or NULL if not exist + * */ +uint16_t const * app_usbd_string_desc_get(app_usbd_string_desc_idx_t idx, uint16_t langid); + +/** + * @brief Get string length + * + * Function to get string length from descriptor (descriptor returned by @ref app_usbd_string_desc_get) + * + * @param[in] p_str String descriptor pointer + * @return Total descriptor length in bytes + */ +static inline size_t app_usbd_string_desc_length(uint16_t const * p_str) +{ + return ((const app_usbd_descriptor_string_t *)p_str)->bLength; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_STRING_DESC_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/app_usbd_types.h b/third_party/NordicSemiconductor/libraries/usb/app_usbd_types.h new file mode 100644 index 000000000..fc57813f9 --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/app_usbd_types.h @@ -0,0 +1,232 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_TYPES_H__ +#define APP_USBD_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "sdk_errors.h" +#include "nrf_drv_usbd.h" +#include "app_usbd_request.h" + +/** + * @defgroup app_usbd_types USB Device high level library variable types definition + * @ingroup app_usbd + * + * @brief @tagAPI52840 All types used by @ref app_usbd are defined here. + * This helps to avoid cross referencing into types in different files. + * @{ + */ + +/** + * @brief Change given value to 2 digits in BCD notation + * + * @param[in] val The decimal value to be converted in the range from 0 to 99. + * @return Calculated BCD value. + */ +#define APP_USBD_BCD_2_MAKE(val) ( \ + ((((val) % 100) / 10) * 0x10) + \ + ((((val) % 10) / 1) * 0x1) \ + ) + +/** + * @brief Change given decimal version values to 4 digits in BCD notation + * + * USB specification uses 4 digits BCD version notation in many descriptors. + * This macro changes 2 values to 4 BCD digits (one 16 bit value) + * that describes version in USB standard. + * + * @param[in] major Major version + * @param[in] minor Minor version + * + * @return Calculated 16 bit value with BCD representation of the version + */ +#define APP_USBD_BCD_VER_MAKE(major, minor) \ + ((APP_USBD_BCD_2_MAKE(major) << 8) | APP_USBD_BCD_2_MAKE(minor)) + +/** + * @brief Events codes + * + * Redefined application event codes + */ +typedef enum +{ + APP_USBD_EVT_DRV_SOF = NRF_DRV_USBD_EVT_SOF, /**< See documentation for @ref NRF_DRV_USBD_EVT_SOF */ + APP_USBD_EVT_DRV_RESET = NRF_DRV_USBD_EVT_RESET, /**< See documentation for @ref NRF_DRV_USBD_EVT_RESET */ + APP_USBD_EVT_DRV_SUSPEND = NRF_DRV_USBD_EVT_SUSPEND, /**< See documentation for @ref NRF_DRV_USBD_EVT_SUSPEND */ + APP_USBD_EVT_DRV_RESUME = NRF_DRV_USBD_EVT_RESUME, /**< See documentation for @ref NRF_DRV_USBD_EVT_RESUME */ + APP_USBD_EVT_DRV_WUREQ = NRF_DRV_USBD_EVT_WUREQ, /**< See documentation for @ref NRF_DRV_USBD_EVT_WUREQ */ + APP_USBD_EVT_DRV_SETUP = NRF_DRV_USBD_EVT_SETUP, /**< This event type has special structure. See @ref app_usbd_setup_evt_t */ + APP_USBD_EVT_DRV_EPTRANSFER = NRF_DRV_USBD_EVT_EPTRANSFER, /**< See documentation for @ref NRF_DRV_USBD_EVT_EPTRANSFER */ + + + APP_USBD_EVT_FIRST_APP, /**< First application event code - for internal static assert checking */ + + APP_USBD_EVT_INST_APPEND = APP_USBD_EVT_FIRST_APP, /**< The instance was attached to the library, any configuration action can be done now */ + APP_USBD_EVT_INST_REMOVE, /**< The instance is going to be removed, this event is called just before removing the instance. + * This removing cannot be stopped. */ + APP_USBD_EVT_STARTED, /**< USBD library has just been started and functional - event passed to all instances, before USBD interrupts have been enabled */ + APP_USBD_EVT_STOPPED, /**< USBD library has just been stopped and is not functional - event passed to all instances, after USBD interrupts have been disabled*/ + + APP_USBD_EVT_FIRST_INTERNAL = 0x80, /**< First internal event, used by the APP library internally. */ + + APP_USBD_EVT_HFCLK_READY = APP_USBD_EVT_FIRST_INTERNAL, /**< High frequency clock started */ + APP_USBD_EVT_START_REQ, /**< Start requested */ + APP_USBD_EVT_STOP_REQ, /**< Stop requested */ + APP_USBD_EVT_SUSPEND_REQ, /**< Suspend request - HFCLK would be released and USBD peripheral clock would be disconnected */ + APP_USBD_EVT_WAKEUP_REQ, /**< Wakeup request - start the whole wakeup generation. */ + +} app_usbd_event_type_t; + +/** + * @brief Specific application event structure + * + * All the data required by the events that comes from the application level + */ +typedef struct +{ + app_usbd_event_type_t type; //!< Event type +} app_usbd_evt_t; + +/** + * @brief Specific application event structure with setup structure included + * + * This event structure would be used when @ref APP_USBD_EVT_DRV_SETUP + * is passed to instance event handler + */ +typedef struct +{ + app_usbd_event_type_t type; //!< Event type + app_usbd_setup_t setup; //!< Setup structure +} app_usbd_setup_evt_t; + + +/** + * @brief Complex event variable type + * + * A variable that can store any kind of event. + */ +typedef union +{ + app_usbd_event_type_t type; //!< Event type + nrf_drv_usbd_evt_t drv_evt; //!< Events that comes directly from the driver. + /**< Use this event structure only for event + * type < @ref APP_USBD_EVT_FIRST_APP + */ + app_usbd_setup_evt_t setup_evt; //!< Event structure with SETUP structure included. + /**< This structure is used in connection with + * @ref APP_USBD_EVT_DRV_SETUP + */ + app_usbd_evt_t app_evt; //!< Events that comes from the application driver. + /**< Use this event structure only for event + * type >= @ref APP_USBD_EVT_FIRST_APP + */ +} app_usbd_complex_evt_t; + +/** + * @brief Internal event variable type + * + * The variable type used for internal event processing. + * This kind of event is the one that goes into the event queue. + * + * @note There is no setup event structure. + * This structure would be created when setup event is processed. + * The reason for that is the fact that setup event structure has high memory printout. + */ +typedef union +{ + app_usbd_event_type_t type; //!< Event type + nrf_drv_usbd_evt_t drv_evt; //!< Events that comes directly from the driver. + /**< Use this event structure only for event + * type < @ref APP_USBD_EVT_FIRST_APP + */ + app_usbd_evt_t app_evt; //!< Events that comes from the application driver. + /**< Use this event structure only for event + * type >= @ref APP_USBD_EVT_FIRST_APP + */ +} app_usbd_internal_evt_t; + +#ifdef DOXYGEN +/** + * @brief Base instance of a USBD class + * + * Any USBD class instance have to begin with this instance. + * This may then be followed by any implementation dependent data. + * + * For an instance it should be possible to put whole structure into FLASH. + * + * @note This type is early defined as incomplete type. + * This is required for function declaration that takes the pointer + * to this structure but in second hand - it is also placed inside + * the instance structure. + * @note The structure is defined in @file app_usbd_class_base.h. + */ +typedef struct {} app_usbd_class_inst_t; +#else +typedef struct app_usbd_class_inst_s app_usbd_class_inst_t; +#endif +/** + * @brief Endpoint callback function + * + * The function used by every class instance. + * @param[in,out] p_inst Instance of the class + * @param[in] p_event Event to process + * + * @note If given event is not supported by class, return @ref NRF_ERROR_NOT_SUPPORTED + */ +typedef ret_code_t (*app_usbd_ep_event_handler_t)( + app_usbd_class_inst_t const * const p_inst, + app_usbd_complex_evt_t const * const p_event + ); + + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_TYPES_H__ */ + diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c new file mode 100644 index 000000000..4a4ce19ae --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.c @@ -0,0 +1,735 @@ +/** + * Copyright (c) 2016 - 2017, 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_config.h" +#if APP_USBD_CLASS_CDC_ACM_ENABLED +#include "app_usbd_cdc_acm.h" +#include + +/** + * @defgroup app_usbd_cdc_acm_internal CDC ACM internals + * @{ + * @ingroup app_usbd_cdc + * @internal + */ + + +#define NRF_LOG_MODULE_NAME cdc_acm + +#if APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR APP_USBD_CDC_ACM_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR +#else //APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define APP_USBD_CDC_ACM_COMM_IFACE_IDX 0 /**< CDC ACM class comm interface index. */ +#define APP_USBD_CDC_ACM_DATA_IFACE_IDX 1 /**< CDC ACM class data interface index. */ + +#define APP_USBD_CDC_ACM_COMM_EPIN_IDX 0 /**< CDC ACM comm class endpoint IN index. */ +#define APP_USBD_CDC_ACM_DATA_EPIN_IDX 0 /**< CDC ACM data class endpoint IN index. */ +#define APP_USBD_CDC_ACM_DATA_EPOUT_IDX 1 /**< CDC ACM data class endpoint OUT index. */ + +/** + * @brief Auxiliary function to access cdc_acm class instance data. + * + * @param[in] p_inst Class instance data. + * + * @return CDC ACM class instance. + */ +static inline app_usbd_cdc_acm_t const * cdc_acm_get(app_usbd_class_inst_t const * p_inst) +{ + ASSERT(p_inst != NULL); + return (app_usbd_cdc_acm_t const *)p_inst; +} + +/** + * @brief Auxiliary function to access cdc_acm class context data. + * + * @param[in] p_cdc_acm CDC ACM class instance data. + * + * @return CDC ACM class instance context. + */ +static inline app_usbd_cdc_acm_ctx_t * cdc_acm_ctx_get(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + ASSERT(p_cdc_acm != NULL); + ASSERT(p_cdc_acm->specific.p_data != NULL); + return &p_cdc_acm->specific.p_data->ctx; +} + +/** + * @brief User event handler. + * + * @param[in] p_inst Class instance. + * @param[in] event user Event type. + */ +static inline void user_event_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_cdc_acm_user_event_t event) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + if (p_cdc_acm->specific.inst.user_ev_handler != NULL) + { + p_cdc_acm->specific.inst.user_ev_handler(p_inst, event); + } +} + +/** + * @brief Auxiliary function to access CDC ACM COMM IN endpoint address. + * + * @param[in] p_inst Class instance data. + * + * @return IN endpoint address. + */ +static inline nrf_drv_usbd_ep_t comm_ep_in_addr_get(app_usbd_class_inst_t const * p_inst) +{ + app_usbd_class_iface_conf_t const * class_iface; + class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_COMM_IFACE_IDX); + + app_usbd_class_ep_conf_t const * ep_cfg; + ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_COMM_EPIN_IDX); + + return app_usbd_class_ep_address_get(ep_cfg); +} + +/** + * @brief Auxiliary function to access CDC ACM DATA IN endpoint address. + * + * @param[in] p_inst Class instance data. + * + * @return IN endpoint address. + */ +static inline nrf_drv_usbd_ep_t data_ep_in_addr_get(app_usbd_class_inst_t const * p_inst) +{ + app_usbd_class_iface_conf_t const * class_iface; + class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_DATA_IFACE_IDX); + + app_usbd_class_ep_conf_t const * ep_cfg; + ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_DATA_EPIN_IDX); + + return app_usbd_class_ep_address_get(ep_cfg); +} + +/** + * @brief Auxiliary function to access CDC ACM DATA OUT endpoint address. + * + * @param[in] p_inst Class instance data. + * + * @return OUT endpoint address. + */ +static inline nrf_drv_usbd_ep_t data_ep_out_addr_get(app_usbd_class_inst_t const * p_inst) +{ + app_usbd_class_iface_conf_t const * class_iface; + class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_DATA_IFACE_IDX); + + app_usbd_class_ep_conf_t const * ep_cfg; + ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_DATA_EPOUT_IDX); + + return app_usbd_class_ep_address_get(ep_cfg); +} + +/** + * @brief Internal SETUP standard IN request handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_req_std_in(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR: + { + size_t dsc_len = 0; + + /* Try to find descriptor in class internals*/ + void const * p_dsc = app_usbd_class_descriptor_find(p_inst, + p_setup_ev->setup.wValue.hb, + p_setup_ev->setup.wValue.lb, + &dsc_len); + if (p_dsc != NULL) + { + return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_dsc, dsc_len); + } + + break; + } + case APP_USBD_SETUP_STDREQ_GET_INTERFACE: + { + + size_t tx_maxsize; + uint8_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_maxsize); + + p_tx_buff[0] = 0; + return app_usbd_core_setup_rsp(&p_setup_ev->setup, + p_tx_buff, + sizeof(uint8_t)); + } + default: + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Internal SETUP standard OUT request handler + * + * @param[in] p_inst Generic class instance + * @param[in] p_setup_ev Setup event + * + * @return Standard error code. + */ +static ret_code_t setup_req_std_out(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + + switch (p_setup_ev->setup.bmRequest) + { + default: + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Internal SETUP class IN request handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_req_class_in(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_CDC_REQ_GET_LINE_CODING: + { + if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t)) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return app_usbd_core_setup_rsp(&p_setup_ev->setup, + &p_cdc_acm_ctx->line_coding, + sizeof(app_usbd_cdc_line_coding_t)); + } + default: + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Class specific OUT request data callback. + * + * @param status Endpoint status. + * @param p_context Context of transfer (set by @ref app_usbd_core_setup_data_handler_set). + * + * @return Standard error code. + */ +static ret_code_t cdc_acm_req_out_data_cb(nrf_drv_usbd_ep_status_t status, void * p_context) +{ + if (status != NRF_USBD_EP_OK) + { + return NRF_ERROR_INTERNAL; + } + + app_usbd_cdc_acm_t const * p_cdc_acm = p_context; + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + switch (p_cdc_acm_ctx->request.type) + { + case APP_USBD_CDC_REQ_SET_LINE_CODING: + { + memcpy(&p_cdc_acm_ctx->line_coding, + &p_cdc_acm_ctx->request.payload.line_coding, + sizeof(app_usbd_cdc_line_coding_t)); + + NRF_LOG_INFO("REQ_SET_LINE_CODING: baudrate: %"PRIu32", databits: %u, " + "format: %u, parity: %u", + uint32_decode(p_cdc_acm_ctx->line_coding.dwDTERate), + p_cdc_acm_ctx->line_coding.bDataBits, + p_cdc_acm_ctx->line_coding.bCharFormat, + p_cdc_acm_ctx->line_coding.bParityType); + break; + } + default: + return NRF_ERROR_NOT_SUPPORTED; + } + + return NRF_SUCCESS; +} + + +/** + * @brief Class specific request data stage setup. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t cdc_acm_req_out_datastage(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + p_cdc_acm_ctx->request.type = p_setup_ev->setup.bmRequest; + p_cdc_acm_ctx->request.len = p_setup_ev->setup.wLength.w; + + /*Request setup data*/ + NRF_DRV_USBD_TRANSFER_OUT(transfer, + &p_cdc_acm_ctx->request.payload, + p_cdc_acm_ctx->request.len); + ret_code_t ret; + CRITICAL_REGION_ENTER(); + ret = app_usbd_core_setup_data_transfer(NRF_DRV_USBD_EPOUT0, &transfer); + if (ret == NRF_SUCCESS) + { + const app_usbd_core_setup_data_handler_desc_t desc = { + .handler = cdc_acm_req_out_data_cb, + .p_context = (void*)p_cdc_acm + }; + + ret = app_usbd_core_setup_data_handler_set(NRF_DRV_USBD_EPOUT0, &desc); + } + CRITICAL_REGION_EXIT(); + + return ret; +} + +/** + * @brief Internal SETUP class OUT request handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_req_class_out(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + switch (p_setup_ev->setup.bmRequest) + { + case APP_USBD_CDC_REQ_SET_LINE_CODING: + { + if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t)) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return cdc_acm_req_out_datastage(p_inst, p_setup_ev); + } + case APP_USBD_CDC_REQ_SET_CONTROL_LINE_STATE: + { + if (p_setup_ev->setup.wLength.w != 0) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + NRF_LOG_INFO("REQ_SET_CONTROL_LINE_STATE: 0x%x", p_setup_ev->setup.wValue.w); + + bool old_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? + true : false; + p_cdc_acm_ctx->line_state = p_setup_ev->setup.wValue.w; + + bool new_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? + true : false; + + if (old_dtr == new_dtr) + { + return NRF_SUCCESS; + } + + const app_usbd_cdc_acm_user_event_t ev = new_dtr ? + APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN : APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE; + + user_event_handler(p_inst, ev); + + if (!new_dtr) + { + /*Abort DATA endpoints on port close */ + nrf_drv_usbd_ep_t ep; + ep = data_ep_in_addr_get(p_inst); + usbd_drv_ep_abort(ep); + ep = data_ep_out_addr_get(p_inst); + usbd_drv_ep_abort(ep); + } + + return NRF_SUCCESS; + } + default: + break; + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Control endpoint handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t setup_event_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_setup_evt_t const * p_setup_ev) +{ + ASSERT(p_inst != NULL); + ASSERT(p_setup_ev != NULL); + + if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN) + { + switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + case APP_USBD_SETUP_REQTYPE_STD: + return setup_req_std_in(p_inst, p_setup_ev); + case APP_USBD_SETUP_REQTYPE_CLASS: + return setup_req_class_in(p_inst, p_setup_ev); + default: + break; + } + } + else /*APP_USBD_SETUP_REQDIR_OUT*/ + { + switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType)) + { + case APP_USBD_SETUP_REQTYPE_STD: + return setup_req_std_out(p_inst, p_setup_ev); + case APP_USBD_SETUP_REQTYPE_CLASS: + return setup_req_class_out(p_inst, p_setup_ev); + default: + break; + } + } + + return NRF_ERROR_NOT_SUPPORTED; +} + +/** + * @brief Class specific endpoint transfer handler. + * + * @param[in] p_inst Generic class instance. + * @param[in] p_setup_ev Setup event. + * + * @return Standard error code. + */ +static ret_code_t cdc_acm_endpoint_ev(app_usbd_class_inst_t const * p_inst, + app_usbd_complex_evt_t const * p_event) +{ + if (comm_ep_in_addr_get(p_inst) == p_event->drv_evt.data.eptransfer.ep) + { + NRF_LOG_INFO("EPIN_COMM: notify"); + return NRF_SUCCESS; + } + + if (NRF_USBD_EPIN_CHECK(p_event->drv_evt.data.eptransfer.ep)) + { + switch (p_event->drv_evt.data.eptransfer.status) + { + case NRF_USBD_EP_OK: + NRF_LOG_INFO("EPIN_DATA: %02x done", p_event->drv_evt.data.eptransfer.ep); + user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_TX_DONE); + return NRF_SUCCESS; + case NRF_USBD_EP_ABORTED: + return NRF_SUCCESS; + default: + return NRF_ERROR_INTERNAL; + } + } + + if (NRF_USBD_EPOUT_CHECK(p_event->drv_evt.data.eptransfer.ep)) + { + switch (p_event->drv_evt.data.eptransfer.status) + { + case NRF_USBD_EP_OK: + NRF_LOG_INFO("EPOUT_DATA: %02x done", p_event->drv_evt.data.eptransfer.ep); + user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_RX_DONE); + return NRF_SUCCESS; + case NRF_USBD_EP_WAITING: + case NRF_USBD_EP_ABORTED: + return NRF_SUCCESS; + default: + return NRF_ERROR_INTERNAL; + } + } + + return NRF_ERROR_NOT_SUPPORTED; +} + + +/** + * @brief @ref app_usbd_class_methods_t::event_handler + */ +static ret_code_t cdc_acm_event_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_complex_evt_t const * p_event) +{ + ASSERT(p_inst != NULL); + ASSERT(p_event != NULL); + + ret_code_t ret = NRF_SUCCESS; + switch (p_event->app_evt.type) + { + case APP_USBD_EVT_DRV_SOF: + break; + case APP_USBD_EVT_DRV_RESET: + break; + case APP_USBD_EVT_DRV_SETUP: + ret = setup_event_handler(p_inst, (app_usbd_setup_evt_t const *)p_event); + break; + case APP_USBD_EVT_DRV_EPTRANSFER: + ret = cdc_acm_endpoint_ev(p_inst, p_event); + break; + case APP_USBD_EVT_DRV_SUSPEND: + break; + case APP_USBD_EVT_DRV_RESUME: + break; + case APP_USBD_EVT_INST_APPEND: + { + ret = app_usbd_class_sof_register(p_inst); + break; + } + case APP_USBD_EVT_INST_REMOVE: + { + ret = app_usbd_class_sof_unregister(p_inst); + break; + } + case APP_USBD_EVT_STARTED: + break; + case APP_USBD_EVT_STOPPED: + break; + default: + ret = NRF_ERROR_NOT_SUPPORTED; + break; + } + + return ret; +} + +/** + * @brief @ref app_usbd_class_methods_t::get_descriptors + */ +static const void * cdc_acm_get_descriptors(app_usbd_class_inst_t const * p_inst, + size_t * p_size) +{ + ASSERT(p_size != NULL); + app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst); + + *p_size = p_cdc_acm->specific.inst.raw_desc_size; + return p_cdc_acm->specific.inst.p_raw_desc; +} + +/** + * @brief Public cdc_acm class interface + * + */ +const app_usbd_class_methods_t app_usbd_cdc_acm_class_methods = { + .event_handler = cdc_acm_event_handler, + .get_descriptors = cdc_acm_get_descriptors, +}; + + +ret_code_t app_usbd_cdc_acm_write(app_usbd_cdc_acm_t const * p_cdc_acm, + const void * p_buf, + size_t length) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + bool dtr_state = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? + true : false; + if (!dtr_state) + { + /*Port is not opened*/ + return NRF_ERROR_INVALID_STATE; + } + + nrf_drv_usbd_ep_t ep = data_ep_in_addr_get(p_inst); + NRF_DRV_USBD_TRANSFER_IN(transfer, p_buf, length); + return app_usbd_core_ep_transfer(ep, &transfer); +} + +size_t app_usbd_cdc_acm_rx_size(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm); + nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(p_inst); + + size_t size; + ret_code_t ret = nrf_drv_usbd_ep_status_get(ep, &size); + if (ret != NRF_SUCCESS) + { + return 0; + } + + return size; +} + +ret_code_t app_usbd_cdc_acm_read(app_usbd_cdc_acm_t const * p_cdc_acm, + void * p_buf, + size_t length) +{ + ASSERT((length % NRF_DRV_USBD_EPSIZE) == 0); + app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + bool dtr_state = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ? + true : false; + if (!dtr_state) + { + /*Port is not opened*/ + return NRF_ERROR_INVALID_STATE; + } + + nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(p_inst); + NRF_DRV_USBD_TRANSFER_OUT(transfer, p_buf, length); + return app_usbd_core_ep_transfer(ep, &transfer); +} + +static ret_code_t cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm); + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + nrf_drv_usbd_ep_t ep = comm_ep_in_addr_get(p_inst); + + NRF_DRV_USBD_TRANSFER_OUT(transfer, + &p_cdc_acm_ctx->request.payload, + sizeof(app_usbd_cdc_acm_notify_t)); + return app_usbd_core_ep_transfer(ep, &transfer); +} + +ret_code_t app_usbd_cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm, + app_usbd_cdc_acm_serial_state_t serial_state, + bool value) +{ + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + ret_code_t ret; + CRITICAL_REGION_ENTER(); + ret = NRF_SUCCESS; + switch (serial_state) + { + case APP_USBD_CDC_ACM_SERIAL_STATE_DCD: + case APP_USBD_CDC_ACM_SERIAL_STATE_DSR: + case APP_USBD_CDC_ACM_SERIAL_STATE_BREAK: + case APP_USBD_CDC_ACM_SERIAL_STATE_RING: + case APP_USBD_CDC_ACM_SERIAL_STATE_FRAMING: + case APP_USBD_CDC_ACM_SERIAL_STATE_PARITY: + case APP_USBD_CDC_ACM_SERIAL_STATE_OVERRUN: + + if (value) + { + p_cdc_acm_ctx->serial_state |= serial_state; + } + else + { + p_cdc_acm_ctx->serial_state &= ~serial_state; + } + + break; + default: + ret = NRF_ERROR_NOT_SUPPORTED; + break; + } + + if (ret == NRF_SUCCESS) + { + app_usbd_cdc_acm_notify_t * notify = &p_cdc_acm_ctx->request.payload.notify; + notify->cdc_notify.bmRequestType = app_usbd_setup_req_val(APP_USBD_SETUP_REQREC_INTERFACE, + APP_USBD_SETUP_REQTYPE_CLASS, + APP_USBD_SETUP_REQDIR_IN); + notify->cdc_notify.bmRequest = APP_USBD_CDC_NOTIF_SERIAL_STATE; + notify->cdc_notify.wValue = 0; + notify->cdc_notify.wIndex = 0; + notify->cdc_notify.wLength = sizeof(notify->serial_state); + + notify->serial_state = p_cdc_acm_ctx->serial_state; + + ret = cdc_acm_serial_state_notify(p_cdc_acm); + } + CRITICAL_REGION_EXIT(); + + return ret; +} + +ret_code_t app_usbd_cdc_acm_line_state_get(app_usbd_cdc_acm_t const * p_cdc_acm, + app_usbd_cdc_acm_line_state_t line_state, + uint32_t * value) +{ + app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm); + + ret_code_t ret; + CRITICAL_REGION_ENTER(); + ret = NRF_SUCCESS; + switch (line_state) + { + case APP_USBD_CDC_ACM_LINE_STATE_DTR: + case APP_USBD_CDC_ACM_LINE_STATE_RTS: + *value = (p_cdc_acm_ctx->line_state & line_state) != 0; + break; + default: + ret = NRF_ERROR_NOT_SUPPORTED; + break; + } + CRITICAL_REGION_EXIT(); + + return ret; +} + +#endif /* APP_USBD_CLASS_CDC_ACM_ENABLED */ + +/** @} */ diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h new file mode 100644 index 000000000..7a3bc1b5a --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm.h @@ -0,0 +1,295 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_CDC_ACM_H__ +#define APP_USBD_CDC_ACM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "nrf_drv_usbd.h" +#include "app_usbd_class_base.h" +#include "app_usbd.h" +#include "app_usbd_core.h" +#include "app_usbd_descriptor.h" + +#include "app_usbd_cdc_desc.h" +#include "app_usbd_cdc_types.h" +#include "app_usbd_cdc_acm_internal.h" + +/** + * @defgroup app_usbd_cdc_acm USB CDC ACM class + * @ingroup app_usbd + * + * @brief @tagAPI52840 Module with types, definitions and API used by CDC ACM class. + * + * @details References: + * - "Universal Serial Bus Class Definitions for Communications Devices" + * Revision 1.2, November 3, 2010 + * - "Universal Serial Bus Communications Class Subclass Specification for PSTN Devices" + * Revision 1.2, February 9, 2007 + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief CDC ACM class instance type + * + * @ref APP_USBD_CLASS_TYPEDEF + */ +typedef struct { } app_usbd_cdc_acm_t; +#else +/*lint -save -e10 -e26 -e123 -e505 */ +APP_USBD_CLASS_TYPEDEF(app_usbd_cdc_acm, \ + APP_USBD_CDC_ACM_CONFIG(0, 0, 0, 0, 0), \ + APP_USBD_CDC_ACM_INSTANCE_SPECIFIC_DEC, \ + APP_USBD_CDC_ACM_DATA_SPECIFIC_DEC \ +); +/*lint -restore*/ +#endif + + +/*lint -save -e407 */ + +/** + * @brief Events passed to user event handler. + * + * @note Example prototype of user event handler: + * + * @code + void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_cdc_acm_user_event_t event); + * @endcode + */ +typedef enum app_usbd_cdc_acm_user_event_e { + APP_USBD_CDC_ACM_USER_EVT_RX_DONE, /**< User event RX_DONE. */ + APP_USBD_CDC_ACM_USER_EVT_TX_DONE, /**< User event TX_DONE. */ + + APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN, /**< User event PORT_OPEN. */ + APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE, /**< User event PORT_CLOSE. */ +} app_usbd_cdc_acm_user_event_t; + +/*lint -restore*/ + +/** + * @brief Default CDC ACM descriptors. + * + * @param comm_interface COMM interface number. + * @param comm_epin COMM interface IN endpoint. + * @param data_interface DATA interface number. + * @param data_epin DATA interface IN endpoint. + * @param data_epout DATA interface OUT endpoint. + */ +#define APP_USBD_CDC_ACM_DEFAULT_DESC(comm_interface, \ + comm_epin, \ + data_interface, \ + data_epin, \ + data_epout) \ + APP_USBD_CDC_IAD_DSC(comm_interface, \ + APP_USBD_CDC_SUBCLASS_ACM, \ + APP_USBD_CDC_COMM_PROTOCOL_AT_V250) \ + APP_USBD_CDC_COMM_INTERFACE_DSC(comm_interface, \ + APP_USBD_CDC_SUBCLASS_ACM, \ + APP_USBD_CDC_COMM_PROTOCOL_AT_V250) \ + APP_USBD_CDC_HEADER_DSC(0x0110) \ + APP_USBD_CDC_CALL_MGMT_DSC(0x03, data_interface) \ + APP_USBD_CDC_ACM_DSC(0x02) \ + APP_USBD_CDC_UNION_DSC(comm_interface, data_interface) \ + APP_USBD_CDC_COM_EP_DSC(comm_epin, NRF_DRV_USBD_EPSIZE) \ + APP_USBD_CDC_DATA_INTERFACE_DSC(data_interface, 0, 0) \ + APP_USBD_CDC_DATA_EP_DSC(data_epin, data_epout, NRF_DRV_USBD_EPSIZE) + +/** + * @brief Global definition of app_usbd_cdc_acm_t class instance. + * + * @param instance_name Name of global instance. + * @param interfaces_configs Interfaces configurations. + * @param user_ev_handler User event handler (optional). + * @param raw_descriptors Raw descriptor table. + * + * @note This macro is just simplified version of @ref APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL. + * + */ +#define APP_USBD_CDC_ACM_GLOBAL_DEF(instance_name, \ + interfaces_configs, \ + user_ev_handler, \ + raw_descriptors) \ + APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL(instance_name, \ + interfaces_configs, \ + user_ev_handler, \ + raw_descriptors) + +/** + * @brief Helper function to get class instance from CDC ACM class. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * + * @return Base class instance. + */ +static inline app_usbd_class_inst_t const * +app_usbd_cdc_acm_class_inst_get(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + return &p_cdc_acm->base; +} + +/** + * @brief Helper function to get cdc_acm specific request from cdc_acm class. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * + * @return CDC ACM class specific request. + */ +static inline app_usbd_cdc_acm_req_t * +app_usbd_cdc_acm_class_request_get(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + return &p_cdc_acm->specific.p_data->ctx.request; +} + +/** + * @brief Helper function to get cdc_acm from base class instance. + * + * @param[in] p_inst Base class instance. + * + * @return CDC ACM class handle. + */ +static inline app_usbd_cdc_acm_t const * +app_usbd_cdc_acm_class_get(app_usbd_class_inst_t const * p_inst) +{ + return (app_usbd_cdc_acm_t const *)p_inst; +} + + +/** + * @brief Writes data to CDC ACM serial port. + * + * This is asynchronous call. User should wait for @ref APP_USBD_CDC_ACM_USER_EVT_TX_DONE event + * to be sure that all data has been sent and input buffer could be accessed again. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[in] p_buf Input buffer. + * @param[in] length Input buffer length. + * + * @return Standard error code. + */ +ret_code_t app_usbd_cdc_acm_write(app_usbd_cdc_acm_t const * p_cdc_acm, + const void * p_buf, + size_t length); + +/** + * @brief Returns the amount of data to be read. + * + * This function should be used on @ref APP_USBD_CDC_ACM_USER_EVT_RX_DONE event to get + * information how many bytes have been transfered. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * + * @return Amount of data transfered. + */ +size_t app_usbd_cdc_acm_rx_size(app_usbd_cdc_acm_t const * p_cdc_acm); + +/** + * @brief Reads data from CDC ACM serial port. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[out] p_buf Output buffer. + * @param[in] length Output buffer length (must by multiple of @ref NRF_DRV_USBD_EPSIZE). + * + * @return Standard error code. + */ +ret_code_t app_usbd_cdc_acm_read(app_usbd_cdc_acm_t const * p_cdc_acm, + void * p_buf, + size_t length); +/** + * @brief Serial state notifications. + * */ +typedef enum { + APP_USBD_CDC_ACM_SERIAL_STATE_DCD = (1u << 0), /**< Notification bit DCD. */ + APP_USBD_CDC_ACM_SERIAL_STATE_DSR = (1u << 1), /**< Notification bit DSR. */ + APP_USBD_CDC_ACM_SERIAL_STATE_BREAK = (1u << 2), /**< Notification bit BREAK. */ + APP_USBD_CDC_ACM_SERIAL_STATE_RING = (1u << 3), /**< Notification bit RING. */ + APP_USBD_CDC_ACM_SERIAL_STATE_FRAMING = (1u << 4), /**< Notification bit FRAMING.*/ + APP_USBD_CDC_ACM_SERIAL_STATE_PARITY = (1u << 5), /**< Notification bit PARITY. */ + APP_USBD_CDC_ACM_SERIAL_STATE_OVERRUN = (1u << 6), /**< Notification bit OVERRUN.*/ +} app_usbd_cdc_acm_serial_state_t; + +/** + * @brief Serial line state. + */ +typedef enum { + APP_USBD_CDC_ACM_LINE_STATE_DTR = (1u << 0), /**< Line state bit DTR.*/ + APP_USBD_CDC_ACM_LINE_STATE_RTS = (1u << 1), /**< Line state bit RTS.*/ +} app_usbd_cdc_acm_line_state_t; + +/** + * @brief Serial state notification via IN interrupt endpoint. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[in] serial_state Serial state notification type. + * @param[in] value Serial state value. + * + * @return Standard error code. + */ +ret_code_t app_usbd_cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm, + app_usbd_cdc_acm_serial_state_t serial_state, + bool value); + +/** + * @brief Control line value get. + * + * @param[in] p_cdc_acm CDC ACM class instance (defined by @ref APP_USBD_CDC_ACM_GLOBAL_DEF). + * @param[in] line_state Line control value type. + * @param[out] value Line control value. + * + * @return Standard error code. + */ +ret_code_t app_usbd_cdc_acm_line_state_get(app_usbd_cdc_acm_t const * p_cdc_acm, + app_usbd_cdc_acm_line_state_t line_state, + uint32_t * value); + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CDC_ACM_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm_internal.h b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm_internal.h new file mode 100644 index 000000000..5ae6b1b1c --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/acm/app_usbd_cdc_acm_internal.h @@ -0,0 +1,221 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_CDC_ACM_INTERNAL_H__ +#define APP_USBD_CDC_ACM_INTERNAL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "app_util.h" + +/** + * @defgroup app_usbd_cdc_acm_internal USB CDC ACM internals + * @ingroup app_usbd_cdc_acm + * @brief @tagAPI52840 Internals of the USB ACM class implementation. + * @{ + */ + +/** + * @brief Forward declaration of type defined by @ref APP_USBD_CLASS_TYPEDEF in cdc_acm class. + * + */ +APP_USBD_CLASS_FORWARD(app_usbd_cdc_acm); + +/*lint -save -e165*/ +/** + * @brief Forward declaration of @ref app_usbd_cdc_acm_user_event_e. + * + */ +enum app_usbd_cdc_acm_user_event_e; + +/*lint -restore*/ + +/** + * @brief User event handler. + * + * @param[in] p_inst Class instance. + * @param[in] event User event. + * + */ +typedef void (*app_usbd_cdc_acm_user_ev_handler_t)(app_usbd_class_inst_t const * p_inst, + enum app_usbd_cdc_acm_user_event_e event); + +/** + * @brief CDC ACM class part of class instance data. + */ +typedef struct { + uint8_t const * p_raw_desc; //!< CDC ACM class descriptors. + size_t raw_desc_size; //!< CDC ACM class descriptors size. + + app_usbd_cdc_acm_user_ev_handler_t user_ev_handler; //!< User event handler. +} app_usbd_cdc_acm_inst_t; + + +/** + * @brief CDC ACM serial state class notify + */ +typedef struct { + app_usbd_cdc_notify_t cdc_notify; //!< CDC notify. + uint16_t serial_state; //!< Serial port state. +} app_usbd_cdc_acm_notify_t; + +/** + * @brief CDC ACM class specific request handled via control endpoint. + */ +typedef struct { + uint8_t type; //!< Request type. + uint8_t len; //!< Request length. + + union { + app_usbd_cdc_line_coding_t line_coding; //!< CDC ACM current line coding. + app_usbd_cdc_acm_notify_t notify; //!< CDC ACM class notify. + } payload; +} app_usbd_cdc_acm_req_t; + + +/** + * @brief CDC ACM class context + */ +typedef struct { + app_usbd_cdc_acm_req_t request; //!< CDC ACM class request. + app_usbd_cdc_line_coding_t line_coding; //!< CDC ACM current line coding. + + uint16_t line_state; //!< CDC ACM line state bitmap, DTE side. + uint16_t serial_state; //!< CDC ACM serial state bitmap, DCE side. +} app_usbd_cdc_acm_ctx_t; + + +/** + * @brief CDC ACM class configuration macro. + * + * Used by @ref APP_USBD_CDC_ACM_GLOBAL_DEF + * + * @param iface_comm Interface number of cdc_acm control. + * @param epin_comm COMM subclass IN endpoint. + * @param iface_data Interface number of cdc_acm DATA. + * @param epin_data COMM subclass IN endpoint. + * @param epout_data COMM subclass OUT endpoint. + * + */ +#define APP_USBD_CDC_ACM_CONFIG(iface_comm, epin_comm, iface_data, epin_data, epout_data) \ + ((iface_comm, epin_comm), \ + (iface_data, epin_data, epout_data)) + + +/** + * @brief Specific class constant data for cdc_acm class. + * + * @ref app_usbd_cdc_acm_inst_t + */ +#define APP_USBD_CDC_ACM_INSTANCE_SPECIFIC_DEC app_usbd_cdc_acm_inst_t inst; + + +/** + * @brief Configures cdc_acm class instance. + * + * @param descriptors Mass storage class descriptors (raw table). + * @param user_event_handler User event handler. + */ +#define APP_USBD_CDC_ACM_INST_CONFIG(descriptors, user_event_handler) \ + .inst = { \ + .p_raw_desc = descriptors, \ + .raw_desc_size = sizeof(descriptors), \ + .user_ev_handler = user_event_handler, \ + } + +/** + * @brief Specific class data for cdc_acm class. + * + * @ref app_usbd_cdc_acm_ctx_t + */ +#define APP_USBD_CDC_ACM_DATA_SPECIFIC_DEC app_usbd_cdc_acm_ctx_t ctx; + + +/** + * @brief CDC ACM class descriptors config macro. + * + * @param interface_number Interface number. + * @param ... Extracted endpoint list. + */ +#define APP_USBD_CDC_ACM_DSC_CONFIG(interface_number, ...) { \ + APP_USBD_CDC_ACM_INTERFACE_DSC(interface_number, \ + 0, \ + 0, \ + APP_USBD_CDC_ACM_SUBCLASS_CDC_ACMCONTROL) \ +} + +/** + * @brief Public cdc_acm class interface. + * + */ +extern const app_usbd_class_methods_t app_usbd_cdc_acm_class_methods; + +/** + * @brief Global definition of @ref app_usbd_cdc_acm_t class. + * + * @param instance_name Name of global instance. + * @param interfaces_configs Interfaces configurations. + * @param user_ev_handler User event handler (optional). + * @param raw_descriptors Raw descriptor table. + */ +#define APP_USBD_CDC_ACM_GLOBAL_DEF_INTERNAL(instance_name, \ + interfaces_configs, \ + user_ev_handler, \ + raw_descriptors) \ + APP_USBD_CLASS_INST_GLOBAL_DEF( \ + instance_name, \ + app_usbd_cdc_acm, \ + &app_usbd_cdc_acm_class_methods, \ + interfaces_configs, \ + (APP_USBD_CDC_ACM_INST_CONFIG(raw_descriptors, user_ev_handler)) \ + ) + + +/** @} */ + + + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CDC_ACM_INTERNAL_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_desc.h b/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_desc.h new file mode 100644 index 000000000..84f7a0c5c --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_desc.h @@ -0,0 +1,208 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_CDC_DESC_H__ +#define APP_USBD_CDC_DESC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "app_usbd_descriptor.h" +#include "app_usbd_cdc_types.h" + +/** + * @defgroup app_usbd_cdc_desc CDC class descriptors + * @brief @tagAPI52840 Descriptors used in the USB CDC class implementation. + * @ingroup app_usbd_cdc_acm + * + * A group of macros used to initialize CDC descriptors + * @{ + */ + +/** + * @brief Initializer of IAD descriptor for CDC class. + * + * @param interface_number Interface number. + * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. + * @param protocol Protocol, @ref app_usbd_cdc_comm_protocol_t. + */ +#define APP_USBD_CDC_IAD_DSC(interface_number, subclass, protocol) \ + /*.bLength = */ sizeof(app_usbd_descriptor_iad_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION, \ + /*.bFirstInterface = */ interface_number, \ + /*.bInterfaceCount = */ 2, \ + /*.bFunctionClass = */ APP_USBD_CDC_COMM_CLASS, \ + /*.bFunctionSubClass = */ subclass, \ + /*.bFunctionProtocol = */ protocol, \ + /*.iFunction = */ 0, \ + +/** + * @brief Initializer of interface descriptor for CDC COMM class. + * + * @param interface_number Interface number. + * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. + * @param protocol Protocol, @ref app_usbd_cdc_comm_protocol_t. + */ +#define APP_USBD_CDC_COMM_INTERFACE_DSC(interface_number, subclass, protocol) \ + /*.bLength = */ sizeof(app_usbd_descriptor_iface_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE, \ + /*.bInterfaceNumber = */ interface_number, \ + /*.bAlternateSetting = */ 0x00, \ + /*.bNumEndpoints = */ 1, \ + /*.bInterfaceClass = */ APP_USBD_CDC_COMM_CLASS, \ + /*.bInterfaceSubClass = */ subclass, \ + /*.bInterfaceProtocol = */ protocol, \ + /*.iInterface = 0, */ 0x00, \ + + +/** + * @brief Initializer of interface descriptor for CDC DATA class. + * + * @param interface_number Interface number. + * @param subclass Subclass, @ref app_usbd_cdc_subclass_t. + * @param protocol Protocol, @ref app_usbd_cdc_data_protocol_t. + */ +#define APP_USBD_CDC_DATA_INTERFACE_DSC(interface_number, subclass, protocol) \ + /*.bLength = */ sizeof(app_usbd_descriptor_iface_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_INTERFACE, \ + /*.bInterfaceNumber = */ interface_number, \ + /*.bAlternateSetting = */ 0x00, \ + /*.bNumEndpoints = */ 2, \ + /*.bInterfaceClass = */ APP_USBD_CDC_DATA_CLASS, \ + /*.bInterfaceSubClass = */ subclass, \ + /*.bInterfaceProtocol = */ protocol, \ + /*.iInterface = 0, */ 0x00, \ + + + +/** + * @brief Initializer of endpoint descriptor for CDC COM class. + * + * @param endpoint_in IN endpoint. + * @param ep_size Endpoint size. + */ +#define APP_USBD_CDC_COM_EP_DSC(endpoint_in, ep_size) \ + /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ + /*.bEndpointAddress = */ endpoint_in, \ + /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT, \ + /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ + /*.bInterval = */ 16, \ + +/** + * @brief Initializer of endpoint descriptors for CDC DATA class. + * + * @param endpoint_in IN endpoint. + * @param endpoint_out OUT endpoint. + * @param ep_size Endpoint size. + */ +#define APP_USBD_CDC_DATA_EP_DSC(endpoint_in, endpoint_out, ep_size) \ + /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ + /*.bEndpointAddress = */ endpoint_in, \ + /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK, \ + /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ + /*.bInterval = */ 0, \ + /*.bLength = */ sizeof(app_usbd_descriptor_ep_t), \ + /*.bDescriptorType = */ APP_USBD_DESCRIPTOR_ENDPOINT, \ + /*.bEndpointAddress = */ endpoint_out, \ + /*.bmAttributes = */ APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK, \ + /*.wMaxPacketSize = */ APP_USBD_U16_TO_RAW_DSC(ep_size), \ + /*.bInterval = */ 0, \ + +/** + * @brief Initializer of endpoint descriptors for CDC header descriptor. + * + * @param bcd_cdc BCD CDC version. + */ +#define APP_USBD_CDC_HEADER_DSC(bcd_cdc) \ + /*.bLength = */ sizeof(app_usbd_cdc_desc_header_t), \ + /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ + /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_HEADER, \ + /*.bcdCDC = */ APP_USBD_U16_TO_RAW_DSC(bcd_cdc), \ + +/** + * @brief Initializer of endpoint descriptors for CDC call management descriptor. + * + * @param capabilities Capabilities. + * @param data_interface Data interface. + */ +#define APP_USBD_CDC_CALL_MGMT_DSC(capabilities, data_interface) \ + /*.bLength = */ sizeof(app_usbd_cdc_desc_call_mgmt_t), \ + /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ + /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_CALL_MGMT, \ + /*.bmCapabilities = */ capabilities, \ + /*.bDataInterface = */ data_interface, \ + + +/** + * @brief Initializer of endpoint descriptors for CDC DATA class. + * + * @param capabilities Capabilities. + */ +#define APP_USBD_CDC_ACM_DSC(capabilities) \ + /*.bLength = */ sizeof(app_usbd_cdc_desc_acm_t), \ + /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ + /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_ACM, \ + /*.bmCapabilities = */ capabilities, \ + +/** + * @brief Initializer of endpoint descriptors for CDC DATA class. + * + * @param control_interface Control interface. + * @param ... Subordinate interfaces list. + */ +#define APP_USBD_CDC_UNION_DSC(control_interface, ...) \ + /*.bLength = */ sizeof(app_usbd_cdc_desc_union_t) + (NUM_VA_ARGS(__VA_ARGS__)), \ + /*.bDescriptorType = */ APP_USBD_CDC_CS_INTERFACE, \ + /*.bDescriptorSubtype = */ APP_USBD_CDC_SCS_UNION, \ + /*.bControlInterface = */ control_interface, \ + /*.bSubordinateInterface = */ __VA_ARGS__, \ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_CDC_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_types.h b/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_types.h new file mode 100644 index 000000000..9cae0981e --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/class/cdc/app_usbd_cdc_types.h @@ -0,0 +1,360 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_CDC_TYPES_H__ +#define APP_USBD_CDC_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + + +/** + * @defgroup app_usbd_cdc_types CDC class types + * @ingroup app_usbd_cdc_acm + * + * @brief @tagAPI52840 Variable types used by the CDC class implementation. + * @{ + */ + +/** + * @brief Communications Interface Class code. + * + * Used for control interface in communication class. + * @ref app_usbd_descriptor_iface_t::bInterfaceClass + */ +#define APP_USBD_CDC_COMM_CLASS 0x02 + +/** + * @brief Data Class Interface code. + * + * Used for data interface in communication class. + * @ref app_usbd_descriptor_iface_t::bInterfaceClass + */ +#define APP_USBD_CDC_DATA_CLASS 0x0A + +/** + * @brief CDC subclass possible values. + * + * @ref app_usbd_descriptor_iface_t::bInterfaceSubClass + */ +typedef enum { + APP_USBD_CDC_SUBCLASS_RESERVED = 0x00, /**< Reserved in documentation. */ + APP_USBD_CDC_SUBCLASS_DLCM = 0x01, /**< Direct Line Control Model. */ + APP_USBD_CDC_SUBCLASS_ACM = 0x02, /**< Abstract Control Model. */ + APP_USBD_CDC_SUBCLASS_TCM = 0x03, /**< Telephone Control Model. */ + APP_USBD_CDC_SUBCLASS_MCCM = 0x04, /**< Multi-Channel Control Model. */ + APP_USBD_CDC_SUBCLASS_CAPI = 0x05, /**< CAPI Control Model. */ + APP_USBD_CDC_SUBCLASS_ENCM = 0x06, /**< Ethernet Networking Control Model. */ + APP_USBD_CDC_SUBCLASS_ATM = 0x07, /**< ATM Networking Control Model. */ + APP_USBD_CDC_SUBCLASS_WHCM = 0x08, /**< Wireless Handset Control Model. */ + APP_USBD_CDC_SUBCLASS_DM = 0x09, /**< Device Management. */ + APP_USBD_CDC_SUBCLASS_MDLM = 0x0A, /**< Mobile Direct Line Model. */ + APP_USBD_CDC_SUBCLASS_OBEX = 0x0B, /**< OBEX. */ + APP_USBD_CDC_SUBCLASS_EEM = 0x0C, /**< Ethernet Emulation Model. */ + APP_USBD_CDC_SUBCLASS_NCM = 0x0D /**< Network Control Model. */ +} app_usbd_cdc_subclass_t; + +/** + * @brief CDC protocol possible values. + * + * @ref app_usbd_descriptor_iface_t::bInterfaceProtocol + */ +typedef enum { + APP_USBD_CDC_COMM_PROTOCOL_NONE = 0x00, /**< No class specific protocol required. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_V250 = 0x01, /**< AT Commands: V.250 etc. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_PCCA101 = 0x02, /**< AT Commands defined by PCCA-101. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_PCCA101_ANNEXO = 0x03, /**< AT Commands defined by PCCA-101 & Annex O. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_GSM707 = 0x04, /**< AT Commands defined by GSM 07.07. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_3GPP_27007 = 0x05, /**< AT Commands defined by 3GPP 27.007. */ + APP_USBD_CDC_COMM_PROTOCOL_AT_CDMA = 0x06, /**< AT Commands defined by TIA for CDMA. */ + APP_USBD_CDC_COMM_PROTOCOL_EEM = 0x07, /**< Ethernet Emulation Model. */ + APP_USBD_CDC_COMM_PROTOCOL_EXTERNAL = 0xFE, /**< External Protocol: Commands defined by Command Set Functional Descriptor. */ + APP_USBD_CDC_COMM_PROTOCOL_VENDOR = 0xFF /**< Vendor-specific. */ +} app_usbd_cdc_comm_protocol_t; + +/** + * @brief CDC data interface protocols possible values. + */ +typedef enum { + APP_USBD_CDC_DATA_PROTOCOL_NONE = 0x00, /**< No class specific protocol required. */ + APP_USBD_CDC_DATA_PROTOCOL_NTB = 0x01, /**< Network Transfer Block. */ + APP_USBD_CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, /**< Physical interface protocol for ISDN BRI. */ + APP_USBD_CDC_DATA_PROTOCOL_HDLC = 0x31, /**< HDLC. */ + APP_USBD_CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, /**< Transparent. */ + APP_USBD_CDC_DATA_PROTOCOL_Q921M = 0x50, /**< Management protocol for Q.921 data link protocol. */ + APP_USBD_CDC_DATA_PROTOCOL_Q921 = 0x51, /**< Data link protocol for Q.921. */ + APP_USBD_CDC_DATA_PROTOCOL_Q921TM = 0x52, /**< TEI-multiplexor for Q.921 data link protocol. */ + APP_USBD_CDC_DATA_PROTOCOL_V42BIS = 0x90, /**< Data compression procedures. */ + APP_USBD_CDC_DATA_PROTOCOL_Q931 = 0x91, /**< Euro-ISDN protocol control. */ + APP_USBD_CDC_DATA_PROTOCOL_V120 = 0x92, /**< V.24 rate adaptation to ISDN. */ + APP_USBD_CDC_DATA_PROTOCOL_CAPI20 = 0x93, /**< CAPI Commands. */ + APP_USBD_CDC_DATA_PROTOCOL_HOST = 0xFD, /**< Host based driver. + * @note This protocol code should only be used in messages + * between host and device to identify the host driver portion + * of a protocol stack. + */ + APP_USBD_CDC_DATA_PROTOCOL_EXTERNAL = 0xFE, /**< The protocol(s) are described using a Protocol Unit Functional + * Descriptors on Communications Class Interface. + */ + APP_USBD_CDC_DATA_PROTOCOL_VENDOR = 0xFF /**< Vendor-specific. */ +} app_usbd_cdc_data_protocol_t; + +/** + * @brief CDC Functional Descriptor types. + */ +typedef enum { + APP_USBD_CDC_CS_INTERFACE = 0x24, /**< Class specific interface descriptor type.*/ + APP_USBD_CDC_CS_ENDPOINT = 0x25 /**< Class specific endpoint descriptor type.*/ +} app_usbd_cdc_func_type_t; + +/** + * @brief CDC Functional Descriptor subtypes + */ +typedef enum { + APP_USBD_CDC_SCS_HEADER = 0x00, /**< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface. */ + APP_USBD_CDC_SCS_CALL_MGMT = 0x01, /**< Call Management Functional Descriptor. */ + APP_USBD_CDC_SCS_ACM = 0x02, /**< Abstract Control Management Functional Descriptor. */ + APP_USBD_CDC_SCS_DLM = 0x03, /**< Direct Line Management Functional Descriptor. */ + APP_USBD_CDC_SCS_TEL_R = 0x04, /**< Telephone Ringer Functional Descriptor. */ + APP_USBD_CDC_SCS_TEL_CAP = 0x05, /**< Telephone Call and Line State Reporting Capabilities Functional Descriptor. */ + APP_USBD_CDC_SCS_UNION = 0x06, /**< Union Functional Descriptor. */ + APP_USBD_CDC_SCS_COUNTRY_SEL = 0x07, /**< Country Selection Functional Descriptor. */ + APP_USBD_CDC_SCS_TEL_OM = 0x08, /**< Telephone Operational Modes Functional Descriptor. */ + APP_USBD_CDC_SCS_USB_TERM = 0x09, /**< USB Terminal Functional Descriptor. */ + APP_USBD_CDC_SCS_NCT = 0x0A, /**< Network Channel Terminal Descriptor. */ + APP_USBD_CDC_SCS_PU = 0x0B, /**< Protocol Unit Functional Descriptor. */ + APP_USBD_CDC_SCS_EU = 0x0C, /**< Extension Unit Functional Descriptor. */ + APP_USBD_CDC_SCS_MCM = 0x0D, /**< Multi-Channel Management Functional Descriptor. */ + APP_USBD_CDC_SCS_CAPI = 0x0E, /**< CAPI Control Management Functional Descriptor. */ + APP_USBD_CDC_SCS_ETH = 0x0F, /**< Ethernet Networking Functional Descriptor. */ + APP_USBD_CDC_SCS_ATM = 0x10, /**< ATM Networking Functional Descriptor. */ + APP_USBD_CDC_SCS_WHCM = 0x11, /**< Wireless Handset Control Model Functional Descriptor. */ + APP_USBD_CDC_SCS_MDLM = 0x12, /**< Mobile Direct Line Model Functional Descriptor. */ + APP_USBD_CDC_SCS_MDLM_DET = 0x13, /**< MDLM Detail Functional Descriptor. */ + APP_USBD_CDC_SCS_DMM = 0x14, /**< Device Management Model Functional Descriptor. */ + APP_USBD_CDC_SCS_OBEX = 0x15, /**< OBEX Functional Descriptor. */ + APP_USBD_CDC_SCS_CS = 0x16, /**< Command Set Functional Descriptor. */ + APP_USBD_CDC_SCS_CS_DET = 0x17, /**< Command Set Detail Functional Descriptor. */ + APP_USBD_CDC_SCS_TEL_CM = 0x18, /**< Telephone Control Model Functional Descriptor. */ + APP_USBD_CDC_SCS_OBEX_SI = 0x19, /**< OBEX Service Identifier Functional Descriptor. */ + APP_USBD_CDC_SCS_NCM = 0x1A /**< NCM Functional Descriptor. */ +} app_usbd_cdc_func_subtype_t; + +/* Make all descriptors packed */ +#pragma pack(push, 1) + +/** + * @brief Header Functional Descriptor + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this descriptor in bytes. + uint8_t bDescriptorType; //!< @ref APP_USBD_CDC_CS_INTERFACE descriptor type. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_HEADER. + uint8_t bcdCDC[2]; //!< USB Class Definitions for Communications Devices Specification release number in binary-coded decimal. +} app_usbd_cdc_desc_header_t; + +/** + * @brief Call management capabilities. + * + * @ref app_usbd_cdc_desc_call_mgmt_t::bmCapabilities bit + * */ +typedef enum { + APP_USBD_CDC_CALL_MGMT_SUPPORTED = (1 << 0), /**< Call management capability bit 0.*/ + APP_USBD_CDC_CALL_MGMT_OVER_DCI = (1 << 1), /**< Call management capability bit 1.*/ +} app_subd_cdc_call_mgmt_cap_t; + +/** + * @brief CDC Call Management Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. + uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_CALL_MGMT. + uint8_t bmCapabilities; //!< Capabilities @ref app_subd_cdc_call_mgmt_cap_t. + uint8_t bDataInterface; //!< Data interface number. +} app_usbd_cdc_desc_call_mgmt_t; + +/** + * @brief ACM capabilities. + * + * @ref app_usbd_cdc_desc_acm_t::bmCapabilities bit + * */ +typedef enum { + APP_USBD_CDC_ACM_FEATURE_REQUESTS = (1 << 0), /**< ACM capability bit FEATURE_REQUESTS. */ + APP_USBD_CDC_ACM_LINE_REQUESTS = (1 << 1), /**< ACM capability bit LINE_REQUESTS. */ + APP_USBD_CDC_ACM_SENDBREAK_REQUESTS = (1 << 2), /**< ACM capability bit SENDBREAK_REQUESTS.*/ + APP_USBD_CDC_ACM_NOTIFY_REQUESTS = (1 << 3), /**< ACM capability bit NOTIFY_REQUESTS. */ +} app_subd_cdc_acm_cap_t; + +/** + * @brief CDC ACM Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. + uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_ACM. + uint8_t bmCapabilities; //!< Capabilities @ref app_subd_cdc_acm_cap_t. +} app_usbd_cdc_desc_acm_t; + +/** + * @brief Union Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. + uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_UNION. + uint8_t bControlInterface; //!< The interface number of the Communications or Data Class interface, designated as the controlling interface for the union. + uint8_t bSubordinateInterface[]; //!< Interface number of subordinate interfaces in the union. Number of interfaced depends on descriptor size. +} app_usbd_cdc_desc_union_t; + +/** + * @brief Country Selection Functional Descriptor. + */ +typedef struct { + uint8_t bFunctionLength; //!< Size of this functional descriptor, in bytes. + uint8_t bDescriptorType; //!< Descriptor type @ref APP_USBD_CDC_CS_INTERFACE. + uint8_t bDescriptorSubtype; //!< Descriptor subtype @ref APP_USBD_CDC_SCS_COUNTRY_SEL. + uint8_t iCountryCodeRelDate; //!< Index of a string giving the release date for the implemented ISO 3166 Country Codes. +} app_usbd_cdc_desc_country_sel_t; + +/** + * @brief CDC Requests + * + */ +typedef enum { + /* CDC General */ + APP_USBD_CDC_REQ_SEND_ENCAPSULATED_COMMAND = 0x00, /**< This request is used to issue a command in the format of the supported control protocol of the Communications Class interface. */ + APP_USBD_CDC_REQ_GET_ENCAPSULATED_RESPONSE = 0x01, /**< This request is used to request a response in the format of the supported control protocol of the Communications Class interface. */ + /* CDC PSTN */ + APP_USBD_CDC_REQ_SET_COMM_FEATURE = 0x02, /**< This request controls the settings for a particular communications feature of a particular target. */ + APP_USBD_CDC_REQ_GET_COMM_FEATURE = 0x03, /**< This request returns the current settings for the communications feature as selected. */ + APP_USBD_CDC_REQ_CLEAR_COMM_FEATURE = 0x04, /**< This request controls the settings for a particular communications feature of a particular target, setting the selected feature to its default state. */ + APP_USBD_CDC_REQ_SET_AUX_LINE_STATE = 0x10, /**< This request is used to connect or disconnect a secondary jack to POTS circuit or CODEC, depending on hook state. */ + APP_USBD_CDC_REQ_SET_HOOK_STATE = 0x11, /**< This request is used to set the necessary PSTN line relay code for on-hook, off-hook, and caller ID states. */ + APP_USBD_CDC_REQ_PULSE_SETUP = 0x12, /**< This request is used to prepare for a pulse-dialing cycle. */ + APP_USBD_CDC_REQ_SEND_PULSE = 0x13, /**< This request is used to generate a specified number of make/break pulse cycles. */ + APP_USBD_CDC_REQ_SET_PULSE_TIME = 0x14, /**< This request sets the timing of the make and break periods for pulse dialing. */ + APP_USBD_CDC_REQ_RING_AUX_JACK = 0x15, /**< This request is used to generate a ring signal on a secondary phone jack. */ + APP_USBD_CDC_REQ_SET_LINE_CODING = 0x20, /**< This request allows the host to specify typical asynchronous line-character formatting properties. */ + APP_USBD_CDC_REQ_GET_LINE_CODING = 0x21, /**< This request allows the host to find out the currently configured line coding. */ + APP_USBD_CDC_REQ_SET_CONTROL_LINE_STATE = 0x22, /**< This request generates RS-232/V.24 style control signals. */ + APP_USBD_CDC_REQ_SEND_BREAK = 0x23, /**< This request sends special carrier modulation that generates an RS-232 style break. */ + APP_USBD_CDC_REQ_SET_RINGER_PARMS = 0x30, /**< This request configures the ringer for the communications device. */ + APP_USBD_CDC_REQ_GET_RINGER_PARMS = 0x31, /**< This request returns the ringer capabilities of the device and the current status of the device’s ringer. */ + APP_USBD_CDC_REQ_SET_OPERATION_PARMS = 0x32, /**< Sets the operational mode for the device, between a simple mode, standalone mode and a host centric mode. */ + APP_USBD_CDC_REQ_GET_OPERATION_PARMS = 0x33, /**< This request gets the current operational mode for the device. */ + APP_USBD_CDC_REQ_SET_LINE_PARMS = 0x34, /**< This request is used to change the state of the line, corresponding to the interface or master interface of a union to which the command was sent. */ + APP_USBD_CDC_REQ_GET_LINE_PARMS = 0x35, /**< This request is used to report the state of the line that corresponds to the interface or master interface of a union to which the command was sent. */ + APP_USBD_CDC_REQ_DIAL_DIGITS = 0x36, /**< This request dials the DTMF digits over the specified line. */ +} app_usbd_cdc_req_id_t; + +/** + * @brief CDC Notifications. + */ +typedef enum { + /* CDC General */ + APP_USBD_CDC_NOTIF_NETWORK_CONNECTION = 0x00, /**< This notification allows the device to notify the host about network connection status. */ + APP_USBD_CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, /**< This notification allows the device to notify the host that a response is available. + * This response can be retrieved with a subsequent GetEncapsulatedResponse request. + _ */ + APP_USBD_CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, /**< This notification allows the device to inform the host-networking driver + * that a change in either the up-link or the down-link bit rate of the connection has occurred. + */ + /* CDC PSTN */ + APP_USBD_CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, /**< (DLM) This notification indicates the loop has changed on the auxiliary phone interface of the USB device. */ + APP_USBD_CDC_NOTIF_RING_DETECT = 0x09, /**< (DLM) This notification indicates ring voltage on the POTS line interface of the USB device. */ + APP_USBD_CDC_NOTIF_SERIAL_STATE = 0x20, /**< (ACM) This notification sends asynchronous notification of UART status. */ + APP_USBD_CDC_NOTIF_CALL_STATE_CHANGE = 0x28, /**< (TCM) This notification identifies that a change has occurred to the state of a call on the line corresponding to the interface or union for the line. */ + APP_USBD_CDC_NOTIF_LINE_STATE_CHANGE = 0x29 /**< (TCM) This notification identifies that a change has occurred to the state of the line corresponding to the interface or master interface of a union sending the notification message. */ +} app_usbd_cdc_notify_id_t; + +/** + * @brief Notification sent via CDC COMM endpoint. + * */ +typedef struct { + uint8_t bmRequestType; //!< Request type. + uint8_t bmRequest; //!< Request ID @ref app_usbd_cdc_req_id_t. + uint16_t wValue; //!< Value field. + uint16_t wIndex; //!< Index field. + uint16_t wLength; //!< Length of payload following. +} app_usbd_cdc_notify_t; + +/** + * @brief CDC line coding structure. + */ +typedef struct { + uint8_t dwDTERate[4]; //!< Line baudrate. + uint8_t bCharFormat; //!< Character format @ref app_usbd_cdc_line_stopbit_t. + uint8_t bParityType; //!< Parity bits @ref app_usbd_cdc_line_parity_t. + uint8_t bDataBits; //!< Number of data bits. +} app_usbd_cdc_line_coding_t; + +/** + * @brief Possible values of @ref app_usbd_cdc_line_coding_t::bCharFormat. + */ +typedef enum { + APP_USBD_CDC_LINE_STOPBIT_1 = 0, /**< 1 stop bit. */ + APP_USBD_CDC_LINE_STOPBIT_1_5 = 1, /**< 1.5 stop bits. */ + APP_USBD_CDC_LINE_STOPBIT_2 = 2, /**< 2 stop bits. */ +} app_usbd_cdc_line_stopbit_t; + +/** + * @brief Possible values of @ref app_usbd_cdc_line_coding_t::bParityType. + */ +typedef enum { + APP_USBD_CDC_LINE_PARITY_NONE = 0, /**< No parity. */ + APP_USBD_CDC_LINE_PARITY_ODD = 1, /**< Odd parity. */ + APP_USBD_CDC_LINE_PARITY_EVEN = 2, /**< Even parity. */ + APP_USBD_CDC_LINE_PARITY_MARK = 3, /**< Parity forced to 0 (space).*/ + APP_USBD_CDC_LINE_PARITY_SPACE = 4, /**< Parity forced to 1 (mark). */ +} app_usbd_cdc_line_parity_t; + + +#pragma pack(pop) + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* APP_USBD_TYPES_H__ */ diff --git a/third_party/NordicSemiconductor/libraries/usb/config/app_usbd_string_config.h b/third_party/NordicSemiconductor/libraries/usb/config/app_usbd_string_config.h new file mode 100644 index 000000000..a4439b4bc --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/config/app_usbd_string_config.h @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2016 - 2017, 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_USBD_STRING_CONFIG_H +#define APP_USBD_STRING_CONFIG_H + +/** + * @defgroup app_usbd_string_conf USBD string configuration + * @ingroup app_usbd_string_desc + * + * @brief @tagAPI52840 Configuration of the string module that can be easily affected by the final + * user. + * @{ + */ + +/** + * @brief Supported languages identifiers + * + * Comma separated list of supported languages. + */ +#define APP_USBD_STRINGS_LANGIDS \ + ((uint16_t)APP_USBD_LANG_ENGLISH | (uint16_t)APP_USBD_SUBLANG_ENGLISH_US) + +/** + * @brief Manufacturer name string descriptor + * + * Comma separated list of manufacturer names for each defined language. + * Use @ref APP_USBD_STRING_DESC macro to create string descriptor. + * + * The order of manufacturer names has to be the same like in + * @ref APP_USBD_STRINGS_LANGIDS. + */ +#define APP_USBD_STRINGS_MANUFACTURER \ + APP_USBD_STRING_DESC('N', 'o', 'r', 'd', 'i', 'c', ' ', 'S', 'e', 'm', 'i', 'c', 'o', 'n', 'd', 'u', 'c', 't', 'o', 'r') + +/** + * @brief Define whether @ref APP_USBD_STRINGS_MANUFACTURER is created by @ref APP_USBD_STRING_DESC + * or declared as global variable. + * */ +#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 + +/** + * @brief Product name string descriptor + * + * List of product names defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER + */ +#define APP_USBD_STRINGS_PRODUCT \ + APP_USBD_STRING_DESC('n', 'R', 'F', '5', '2', '8', '4', '0', ' ', 'O', 'p', 'e', 'n', 'T', 'h', 'r', 'e', 'a', 'd', ' ', 'D', 'e', 'v', 'i', 'c', 'e') + + +/** + * @brief Define whether @ref APP_USBD_STRINGS_PRODUCT is created by @ref APP_USBD_STRING_DESC + * or declared as global variable. + * */ +#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 + +/** + * @brief Serial number string descriptor + * + * Create serial number string descriptor using @ref APP_USBD_STRING_DESC, + * or configure it to point to any internal variable pointer filled with descriptor. + * + * @note + * There is only one SERIAL number inside the library and it is Language independent. + */ +#define APP_USBD_STRING_SERIAL gExternSerialNumber + +/** + * @brief Define whether @ref APP_USBD_STRING_SERIAL is created by @ref APP_USBD_STRING_DESC + * or declared as global variable. + * */ +#define APP_USBD_STRING_SERIAL_EXTERN 1 + +/** + * @brief User strings default values + * + * This value stores all application specific user strings with its default initialization. + * The setup is done by X-macros. + * Expected macro parameters: + * @code + * X(mnemonic, [=str_idx], ...) + * @endcode + * - @c mnemonic: Mnemonic of the string descriptor that would be added to + * @ref app_usbd_string_desc_idx_t enumerator. + * - @c str_idx : String index value, may be set or left empty. + * For example WinUSB driver requires descriptor to be present on 0xEE index. + * Then use X(USBD_STRING_WINUSB, =0xEE, (APP_USBD_STRING_DESC(...))) + * - @c ... : List of string descriptors for each defined language. + */ +#define APP_USBD_STRINGS_USER \ + X(APP_USER_1, , APP_USBD_STRING_DESC('U', 's', 'e', 'r', ' ', '1')) + +/** @} */ +#endif /* APP_USBD_STRING_CONFIG_H */ diff --git a/third_party/NordicSemiconductor/libraries/usb/nordic_cdc_acm_example.inf b/third_party/NordicSemiconductor/libraries/usb/nordic_cdc_acm_example.inf new file mode 100644 index 000000000..dd384cba5 --- /dev/null +++ b/third_party/NordicSemiconductor/libraries/usb/nordic_cdc_acm_example.inf @@ -0,0 +1,102 @@ +; Windows 2000, XP, Vista, 7 and 8 (x32 and x64) driver for Nordic CDC ACM OpenThread device + +[Version] +Signature = "$Windows NT$" +Class = Ports +ClassGuid = {4D36E978-E325-11CE-BFC1-08002BE10318} +Provider = %Manufacturer% +LayoutFile = layout.inf +DriverVer = 01/08/2013,6.0.0.0 + +;---------------------------------------------------------- +; Targets +;---------------------------------------------------------- +[Manufacturer] +%Manufacturer%=DeviceList, NTAMD64, NTIA64, NT + +[DeviceList] +%NORDIC_CDC_ACM_EXAMPLE%=DriverInstall, USB\VID_1915&PID_CAFE + + +[DeviceList.NTAMD64] +%NORDIC_CDC_ACM_EXAMPLE%=DriverInstall.NTamd64, USB\VID_1915&PID_CAFE + + +[DeviceList.NTIA64] +%NORDIC_CDC_ACM_EXAMPLE%=DriverInstall.NTamd64, USB\VID_1915&PID_CAFE + + +[DeviceList.NT] +%NORDIC_CDC_ACM_EXAMPLE%=DriverInstall.NT, USB\VID_1915&PID_CAFE + +;---------------------------------------------------------- +; Windows 2000, XP, Vista, Windows 7, Windows 8 - 32bit +;---------------------------------------------------------- +[Reader_Install.NTx86] + + +[DestinationDirs] +DefaultDestDir=12 +DriverInstall.NT.Copy=12 + +[DriverInstall.NT] +include=mdmcpq.inf +CopyFiles=DriverInstall.NT.Copy +AddReg=DriverInstall.NT.AddReg + +[DriverInstall.NT.Copy] +usbser.sys + +[DriverInstall.NT.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.NT.Services] +AddService = usbser, 0x00000002, DriverService.NT + +[DriverService.NT] +DisplayName = %Serial.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\usbser.sys +LoadOrderGroup = Base + +;---------------------------------------------------------- +; Windows XP, Vista, Windows 7, Windows 8 - 64bit +;---------------------------------------------------------- + +[DriverInstall.NTamd64] +include=mdmcpq.inf +CopyFiles=DriverCopyFiles.NTamd64 +AddReg=DriverInstall.NTamd64.AddReg + +[DriverCopyFiles.NTamd64] +usbser.sys,,,0x20 + +[DriverInstall.NTamd64.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.NTamd64.Services] +AddService=usbser, 0x00000002, DriverService.NTamd64 + +[DriverService.NTamd64] +DisplayName=%Serial.SvcDesc% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\usbser.sys + +;---------------------------------------------------------- +; String +;---------------------------------------------------------- + +[Strings] +Manufacturer = "Nordic Semiconductor" +NORDIC_CDC_ACM_EXAMPLE = "nRF52840 OpenThread Device" + +Serial.SvcDesc = "USB Serial emulation driver" +