[nRF52840] add USB CDC ACM support (#2215)

This commit is contained in:
Robert Lubos
2017-10-02 10:14:33 -07:00
committed by Jonathan Hui
parent b905fa590e
commit 44cb528a7a
65 changed files with 23004 additions and 439 deletions
+4
View File
@@ -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) \
+22 -1
View File
@@ -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 = \
+11
View File
@@ -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
-2
View File
@@ -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)
+4
View File
@@ -29,6 +29,7 @@
#include <openthread/config.h>
#include <openthread-core-config.h>
#include <openthread/platform/misc.h>
#include <openthread/platform/platform.h>
#include <device/nrf.h>
@@ -69,6 +70,9 @@ void nrf5MiscDeinit(void)
void otPlatReset(otInstance *aInstance)
{
(void)aInstance;
PlatformDeinit();
NVIC_SystemReset();
}
@@ -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_
+4
View File
@@ -49,6 +49,8 @@
#include <hal/nrf_gpio.h>
#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.
*
+372
View File
@@ -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 <openthread/config.h>
#include <openthread-core-config.h>
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
#include <openthread/types.h>
#include <openthread/platform/uart.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/misc.h>
#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
+10 -6
View File
@@ -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
+239
View File
@@ -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 <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#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__
/** @} */
@@ -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__
File diff suppressed because it is too large Load Diff
@@ -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;
}
}
@@ -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 <stdint.h>
#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__
/** @} */
@@ -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 <module>_ENABLE is defined and is non-zero.
* @retval 0 The macro <module>_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__
@@ -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__ */
/** @} */
@@ -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 <stdbool.h>
#include <stdint.h>
#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__ */
/** @} */
+268
View File
@@ -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
@@ -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
/**
@}
*/
+234
View File
@@ -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_
/** @} */
@@ -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 <stdint.h>
#include <stdbool.h>
#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__
@@ -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__
@@ -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 <stdint.h>
#include <stdbool.h>
#include <string.h>
#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__
@@ -0,0 +1,254 @@
#ifndef SDK_CONFIG_H
#define SDK_CONFIG_H
#include <openthread/config.h>
#undef PACKAGE
#pragma GCC diagnostic ignored "-Wpedantic"
#pragma GCC diagnostic ignored "-Wunused-parameter"
//==========================================================
// <e> 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
// <s> APP_USBD_VID - Vendor ID
// <i> Vendor ID ordered from USB IF: http://www.usb.org/developers/vendor/
#ifndef APP_USBD_VID
#define APP_USBD_VID 0x1915
#endif
// <s> APP_USBD_PID - Product ID
// <i> Selected Product ID
#ifndef APP_USBD_PID
#define APP_USBD_PID 0xCAFE
#endif
// <o> APP_USBD_DEVICE_VER_MAJOR - Device version, major part <0-99>
// <i> 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
// <o> APP_USBD_DEVICE_VER_MINOR - Device version, minor part <0-99>
// <i> 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
// <e> APP_USBD_EVENT_QUEUE_ENABLE - Enable event queue
// <i> This is the default configuration when all the events are placed into internal queue.
// <i> Disable it when external queue is used like app_scheduler or if you wish to process all events inside interrupts.
// <i> 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.
// <i> 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
// <o> APP_USBD_EVENT_QUEUE_SIZE - The size of event queue <16-64>
// <i> 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
// </e>
// <e> APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module
//==========================================================
#ifndef APP_USBD_CONFIG_LOG_ENABLED
#define APP_USBD_CONFIG_LOG_ENABLED 0
#endif
// </e>
// </e>
// <e> CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver
//==========================================================
#ifndef CLOCK_ENABLED
#define CLOCK_ENABLED 1
#endif
// <o> CLOCK_CONFIG_XTAL_FREQ - HF XTAL Frequency
// <0=> Default (64 MHz)
#ifndef CLOCK_CONFIG_XTAL_FREQ
#define CLOCK_CONFIG_XTAL_FREQ 0
#endif
// <o> 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
// <o> CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority
// <i> 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
// </e>
// <e> 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
// <o> POWER_CONFIG_IRQ_PRIORITY - Interrupt priority
// <i> 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
// <q> POWER_CONFIG_DEFAULT_DCDCEN - The default configuration of main DCDC regulator
// <i> 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
// <q> POWER_CONFIG_DEFAULT_DCDCENHV - The default configuration of High Voltage DCDC regulator
// <i> 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
// </e>
// <q> 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
// <e> 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
// <o> USBD_CONFIG_IRQ_PRIORITY - Interrupt priority
// <i> 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
// <o> 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
// </e>
// <h> app_usbd_cdc_acm - USB CDC ACM class
//==========================================================
// <q> 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
// </h>
//==========================================================
// <h> nrf_log - Logging
//==========================================================
// <e> NRF_LOG_ENABLED - Logging module for nRF5 SDK
//==========================================================
#ifndef NRF_LOG_ENABLED
#define NRF_LOG_ENABLED 0
#endif
// </e>
// </h>
#endif //SDK_CONFIG_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 <stdint.h>
#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__
@@ -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__
+76
View File
@@ -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__
+105 -86
View File
@@ -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 */
File diff suppressed because it is too large Load Diff
+41 -29
View File
@@ -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
+538 -77
View File
@@ -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)
+176 -34
View File
@@ -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 <stdbool.h>
#include <stdint.h>
#include <nrf_clock.h>
#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
@@ -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 <stddef.h>
#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);
}
@@ -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 <stdint.h>
#include <stdbool.h>
#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__
/** @} */
@@ -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) */
@@ -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 <stdbool.h>
#include <stdint.h>
#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__ */
@@ -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)
@@ -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 <stdint.h>
#include <stdbool.h>
/**
* @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&nbsp;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__ */
File diff suppressed because it is too large Load Diff
@@ -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 <stdint.h>
#include <stdbool.h>
#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&nbsp;ms depending on how long the SUSPEND state was kept on the USB line.
* When NRF_DRV_USBD_EVT_WUREQ event is generated it means that Wake Up signaling has just been
* started on the USB lines.
*
* @note Do not expect only @ref NRF_DRV_USBD_EVT_WUREQ event.
* There always may appear @ref NRF_DRV_USBD_EVT_RESUME event.
* @note NRF_DRV_USBD_EVT_WUREQ event means that Remote WakeUp signal
* has just begun to be generated.
* This may take up to 20&nbsp;ms for the bus to become active.
*
* @retval true WakeUp procedure started.
* @retval false No WakeUp procedure started - bus is already active.
*/
bool nrf_drv_usbd_wakeup_req(void);
/**
* @brief Check if USBD is in SUSPEND mode
*
* @note This is the information about peripheral itself, not about the bus state.
*
* @retval true USBD peripheral is suspended
* @retval false USBD peripheral is active
*/
bool nrf_drv_usbd_suspend_check(void);
/**
* @brief Enable only interrupts that should be processed in SUSPEND mode
*
* Auxiliary function to help with SUSPEND mode integration.
* It enables only the interrupts that can be properly processed without stable HFCLK.
*
* Normally all the interrupts are enabled.
* Use this function to suspend interrupt processing that may require stable HFCLK until the
* clock is enabled.
*
* @sa nrf_drv_usbd_active_irq_config
*/
void nrf_drv_usbd_suspend_irq_config(void);
/**
* @brief Default active interrupt configuration
*
* Default interrupt configuration.
* Use in a pair with @ref nrf_drv_usbd_active_irq_config.
*
* @sa nrf_drv_usbd_suspend_irq_config
*/
void nrf_drv_usbd_active_irq_config(void);
/**
* @brief Check the bus state
*
* This function checks if the bus state is suspended
*
* @note The value returned by this function changes on SUSPEND and RESUME event processing.
*
* @retval true USBD bus is suspended
* @retval false USBD bus is active
*/
bool nrf_drv_usbd_bus_suspend_check(void);
/**
* @brief Configure packet size that should be supported by the endpoint
*
* The real endpoint buffer size is always the same.
* This value sets max packet size that would be transmitted over the endpoint.
* This is required by the library
*
* @param[in] ep Endpoint number
* @param[in] size Required maximum packet size
*
* @note Endpoint size is always set to @ref NRF_DRV_USBD_EPSIZE or @ref NRF_DRV_USBD_ISOSIZE / 2
* when @ref nrf_drv_usbd_ep_enable function is called.
*/
void nrf_drv_usbd_ep_max_packet_size_set(nrf_drv_usbd_ep_t ep, uint16_t size);
/**
* @brief Get configured endpoint packet size
*
* Function to get configured endpoint size on the buffer.
*
* @param[in] ep Endpoint number
*
* @return Maximum pocket size configured on selected endpoint
*/
uint16_t nrf_drv_usbd_ep_max_packet_size_get(nrf_drv_usbd_ep_t ep);
/**
* @brief Check if the selected endpoint is enabled.
*
* @param ep Endpoint number to check.
*
* @retval true Endpoint is enabled.
* @retval false Endpoint is disabled.
*/
bool nrf_drv_usbd_ep_enable_check(nrf_drv_usbd_ep_t ep);
/**
* @brief Enable selected endpoint
*
* This function enables endpoint itself and its interrupts.
* @param ep Endpoint number to enable
*
* @note
* Max packet size is set to endpoint default maximum value.
*
* @sa nrf_drv_usbd_ep_max_packet_size_set
*/
void nrf_drv_usbd_ep_enable(nrf_drv_usbd_ep_t ep);
/**
* @brief Disable selected endpoint
*
* This function disables endpoint itself and its interrupts.
* @param ep Endpoint number to disable
*/
void nrf_drv_usbd_ep_disable(nrf_drv_usbd_ep_t ep);
/**
* @brief 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__ */
@@ -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 <stdbool.h>
/**
* @defgroup nrf_drv_usbd_errata Functions to check if selected PAN is present in current chip
* @{
* @ingroup nrf_drv_usbd
*
* Functions here are checking the presence of an error in current chip.
* The checking is done at runtime based on the microcontroller version.
* This file is subject to removal when nRF51840 prototype support is removed.
*/
#ifndef NRF_DRV_USBD_ERRATA_ENABLE
/**
* @brief The constant that informs if errata should be enabled at all
*
* If this constant is set to 0, all the Errata bug fixes will be automatically disabled.
*/
#define NRF_DRV_USBD_ERRATA_ENABLE 1
#endif
/**
* @brief 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__ */
File diff suppressed because it is too large Load Diff
+184
View File
@@ -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 <stdint.h>
#include <stddef.h>
#include <stdbool.h>
/**
* @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__ */
File diff suppressed because it is too large Load Diff
@@ -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 <string.h>
#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;
}
@@ -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 <stdint.h>
#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__ */
@@ -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 <stddef.h>
#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__ */
File diff suppressed because it is too large Load Diff
+563
View File
@@ -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__ */
@@ -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 <stdint.h>
#include <stddef.h>
#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__ */
File diff suppressed because it is too large Load Diff
@@ -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 <stdint.h>
#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__ */
@@ -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&nbsp;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__ */
@@ -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__ */
@@ -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__ */
@@ -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
@@ -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 <stdint.h>
#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__ */
@@ -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 <stdint.h>
#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__ */
@@ -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 <inttypes.h>
/**
* @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 */
/** @} */
@@ -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 <stdint.h>
#include <stdbool.h>
#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__ */
@@ -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__ */
@@ -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 <stdint.h>
#include <stdbool.h>
#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__ */
@@ -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 <stdint.h>
#include <stdbool.h>
/**
* @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 devices 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__ */
@@ -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 */
@@ -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"