You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/07/27 23:13:46 UTC

[17/51] [partial] incubator-mynewt-core git commit: add stm32 and nordic sdks based on new structure

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/pwm/app_pwm.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/pwm/app_pwm.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/pwm/app_pwm.c
new file mode 100644
index 0000000..091fb70
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/pwm/app_pwm.c
@@ -0,0 +1,876 @@
+/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+#include "app_pwm.h"
+#include "nrf_drv_timer.h"
+#include "nrf_drv_ppi.h"
+#include "nrf_drv_common.h"
+#include "nrf_drv_gpiote.h"
+#include "nrf_gpiote.h"
+#include "nrf_gpio.h"
+#include "app_util.h"
+#include "app_util_platform.h"
+#include "nrf_assert.h"
+
+#define APP_PWM_CHANNEL_INITIALIZED                1
+#define APP_PWM_CHANNEL_UNINITIALIZED              0
+
+#define APP_PWM_CHANNEL_ENABLED                    1
+#define APP_PWM_CHANNEL_DISABLED                   0
+
+#define TIMER_PRESCALER_MAX                        9
+#define TIMER_MAX_PULSEWIDTH_US_ON_16M             4095
+
+#define APP_PWM_REQUIRED_PPI_CHANNELS_PER_INSTANCE 2
+#define APP_PWM_REQUIRED_PPI_CHANNELS_PER_CHANNEL  2
+
+#define UNALLOCATED                                0xFFFFFFFFUL
+#define BUSY_STATE_CHANGING                        0xFE
+#define BUSY_STATE_IDLE                            0xFF
+
+#define PWM_MAIN_CC_CHANNEL                        2
+#define PWM_SECONDARY_CC_CHANNEL                   3
+
+#ifdef NRF52
+    static bool m_use_ppi_delay_workaround;
+#endif
+
+
+/**
+ * @brief PWM busy status
+ *
+ * Stores the number of a channel being currently updated.
+ *
+ */
+static volatile uint8_t  m_pwm_busy[TIMER_COUNT];
+
+
+/**
+ * @brief New duty cycle value
+ *
+ * When the channel duty cycle reaches this value, the update process is complete.
+ */
+static volatile uint32_t m_pwm_target_value[TIMER_COUNT];
+
+
+/**
+ * @brief PWM ready counter
+ *
+ * The value in this counter is decremented in every PWM cycle after initiating the update.
+ * If an event handler function was specified by the user, it is being called
+ * after two cycle events (at least one full PWM cycle).
+ */
+volatile uint8_t m_pwm_ready_counter[TIMER_COUNT][APP_PWM_CHANNELS_PER_INSTANCE];
+
+/**
+ * @brief Pointers to instances
+ *
+ * This array connects any active timer instance number with the pointer to the PWM instance.
+ * It is used by the interrupt runtime.
+ */
+static const app_pwm_t * m_instances[TIMER_COUNT];
+
+// Macros for getting the polarity of given instance/channel.
+#define POLARITY_ACTIVE(INST,CH)   (( ((INST)->p_cb)->channels_cb[(CH)].polarity == \
+                 APP_PWM_POLARITY_ACTIVE_LOW)?(0):(1))
+#define POLARITY_INACTIVE(INST,CH) (( ((INST)->p_cb)->channels_cb[(CH)].polarity == \
+                 APP_PWM_POLARITY_ACTIVE_LOW)?(1):(0))
+
+//lint -save -e534
+
+/**
+ * @brief Workaround for PAN-73.
+ *
+ * @param[in] timer     Timer.
+ * @param[in] enable    Enable or disable.
+ */
+static void pan73_workaround(NRF_TIMER_Type * p_timer, bool enable)
+{
+#ifdef NRF51
+    if (p_timer == NRF_TIMER0)
+    {
+        *(uint32_t *)0x40008C0C = (enable ? 1 : 0);
+    }
+    else if (p_timer == NRF_TIMER1)
+    {
+        *(uint32_t *)0x40009C0C = (enable ? 1 : 0);
+    }
+    else if (p_timer == NRF_TIMER2)
+    {
+        *(uint32_t *)0x4000AC0C = (enable ? 1 : 0);
+    }
+#endif
+    return;
+}
+
+bool app_pwm_busy_check(app_pwm_t const * const p_instance)
+{
+    uint8_t busy_state = (m_pwm_busy[p_instance->p_timer->instance_id]);
+    bool busy = true;
+    if (busy_state != BUSY_STATE_IDLE)
+    {
+        if (busy_state != BUSY_STATE_CHANGING)
+        {
+            if (nrf_drv_timer_capture_get(p_instance->p_timer, (nrf_timer_cc_channel_t) busy_state) 
+                == m_pwm_target_value[p_instance->p_timer->instance_id])
+            {
+                m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_IDLE;
+                busy = false;
+            }
+        }
+    }
+    else
+    {
+        busy = false;
+    }
+    return busy;
+}
+
+
+/**
+ * @brief Function for enabling the IRQ for a given PWM instance.
+ *
+ * @param[in] p_instance  PWM instance.
+ */
+__STATIC_INLINE void pwm_irq_enable(app_pwm_t const * const p_instance)
+{
+    nrf_drv_timer_compare_int_enable(p_instance->p_timer, PWM_MAIN_CC_CHANNEL);
+}
+
+
+/**
+ * @brief Function for disabling the IRQ for a given PWM instance.
+ *
+ * @param[in] p_instance  PWM instance.
+ */
+__STATIC_INLINE void pwm_irq_disable(app_pwm_t const * const p_instance)
+{
+    nrf_drv_timer_compare_int_disable(p_instance->p_timer, PWM_MAIN_CC_CHANNEL);
+}
+
+
+/**
+ * @brief Function for disabling PWM channel PPI.
+ *
+ * @param[in] p_instance  PWM instance.
+ */
+__STATIC_INLINE void pwm_channel_ppi_disable(app_pwm_t const * const p_instance, uint8_t channel)
+{
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+
+    nrf_drv_ppi_channel_disable(p_cb->channels_cb[channel].ppi_channels[0]);
+    nrf_drv_ppi_channel_disable(p_cb->channels_cb[channel].ppi_channels[1]);
+}
+
+
+/**
+ * @brief Function for disabling PWM PPI.
+ *
+ * @param[in] p_instance  PWM instance.
+ */
+__STATIC_INLINE void pwm_ppi_disable(app_pwm_t const * const p_instance)
+{
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+
+    nrf_drv_ppi_channel_disable(p_cb->ppi_channels[0]);
+    nrf_drv_ppi_channel_disable(p_cb->ppi_channels[1]);
+}
+
+
+/**
+ * @brief This function is called on interrupt after duty set.
+ *
+ * @param[in] timer                 Timer used by PWM.
+ * @param[in] timer_instance_id     Timer index.
+ */
+void pwm_ready_tick(nrf_timer_event_t event_type, void * p_context)
+{
+    uint32_t timer_instance_id = (uint32_t)p_context;
+    uint8_t disable = 1;
+    
+    for (uint8_t channel = 0; channel < APP_PWM_CHANNELS_PER_INSTANCE; ++channel)
+    {
+        if (m_pwm_ready_counter[timer_instance_id][channel])
+        {
+            --m_pwm_ready_counter[timer_instance_id][channel];
+            if (!m_pwm_ready_counter[timer_instance_id][channel])
+            {
+                app_pwm_cb_t * p_cb = m_instances[timer_instance_id]->p_cb;
+                p_cb->p_ready_callback(timer_instance_id);
+            }
+            else
+            {
+                disable = 0;
+            }
+        }
+    }
+    
+    if (disable)
+    {
+        pwm_irq_disable(m_instances[timer_instance_id]);
+    }
+}
+
+
+/**
+ * @brief Function for resource de-allocation.
+ *
+ * @param[in] p_instance       PWM instance.
+ */
+//lint -e{650}
+static void pwm_dealloc(app_pwm_t const * const p_instance)
+{
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+
+    for (uint8_t i = 0; i < APP_PWM_REQUIRED_PPI_CHANNELS_PER_INSTANCE; ++i)
+    {
+        if (p_cb->ppi_channels[i] != (nrf_ppi_channel_t)(uint8_t)(UNALLOCATED))
+        {
+            nrf_drv_ppi_channel_free(p_cb->ppi_channels[i]);
+        }
+    }
+    if (p_cb->ppi_group != (nrf_ppi_channel_group_t)UNALLOCATED)
+    {
+        nrf_drv_ppi_group_free(p_cb->ppi_group);
+    }
+
+    for (uint8_t ch = 0; ch < APP_PWM_CHANNELS_PER_INSTANCE; ++ch)
+    {
+        for (uint8_t i = 0; i < APP_PWM_REQUIRED_PPI_CHANNELS_PER_CHANNEL; ++i)
+        {
+            if (p_cb->channels_cb[ch].ppi_channels[i] != (nrf_ppi_channel_t)UNALLOCATED)
+            {
+                nrf_drv_ppi_channel_free(p_cb->channels_cb[ch].ppi_channels[i]);
+                p_cb->channels_cb[ch].ppi_channels[i] = (nrf_ppi_channel_t)UNALLOCATED;
+            }
+        }
+        if (p_cb->channels_cb[ch].gpio_pin != UNALLOCATED)
+        {
+            nrf_drv_gpiote_out_uninit(p_cb->channels_cb[ch].gpio_pin);
+            p_cb->channels_cb[ch].gpio_pin = UNALLOCATED;
+        }
+        p_cb->channels_cb[ch].initialized = APP_PWM_CHANNEL_UNINITIALIZED;
+    }
+    nrf_drv_timer_uninit(p_instance->p_timer);
+    return;
+}
+
+
+/**
+ * @brief PWM state transition from (0%, 100%) to 0% or 100%.
+ *
+ * @param[in] p_instance       PWM instance.
+ * @param[in] channel          PWM channel number.
+ * @param[in] ticks            Number of clock ticks.
+ */
+static void pwm_transition_n_to_0or100(app_pwm_t const * const p_instance,
+                                       uint8_t channel, uint16_t ticks)
+{
+    app_pwm_cb_t            * p_cb     = p_instance->p_cb;
+    app_pwm_channel_cb_t    * p_ch_cb  = &p_cb->channels_cb[channel];
+    nrf_ppi_channel_group_t   p_ppigrp = p_cb->ppi_group;
+
+    pwm_ppi_disable(p_instance);
+    nrf_drv_ppi_group_clear(p_ppigrp);
+    nrf_drv_ppi_channels_include_in_group(
+            nrf_drv_ppi_channel_to_mask(p_ch_cb->ppi_channels[0]) | 
+            nrf_drv_ppi_channel_to_mask(p_ch_cb->ppi_channels[1]),
+            p_ppigrp);
+
+    if (!ticks)
+    {
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0],
+                    nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel),
+                    nrf_drv_ppi_task_addr_group_disable_get(p_ppigrp));
+        nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, 0, false);
+        m_pwm_target_value[p_instance->p_timer->instance_id] =
+            nrf_drv_timer_capture_get(p_instance->p_timer, (nrf_timer_cc_channel_t) channel);
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1],
+                    nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel),
+                    nrf_drv_timer_capture_task_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL));
+    }
+    else
+    {
+        ticks = p_cb->period;
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0],
+                    nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL),
+                    nrf_drv_ppi_task_addr_group_disable_get(p_ppigrp));
+        // Set secondary CC channel to non-zero value:
+        nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, 1, false);
+        m_pwm_target_value[p_instance->p_timer->instance_id] = 0;
+        // The captured value will be equal to 0, because timer clear on main PWM CC channel compare is enabled.
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1],
+                    nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL),
+                    nrf_drv_timer_capture_task_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL));
+    }
+    
+    nrf_drv_ppi_channel_enable(p_cb->ppi_channels[0]);
+    nrf_drv_ppi_channel_enable(p_cb->ppi_channels[1]);
+    
+    p_ch_cb->pulsewidth = ticks;
+    m_pwm_busy[p_instance->p_timer->instance_id] = PWM_SECONDARY_CC_CHANNEL;
+}
+
+
+/**
+ * @brief PWM state transition from (0%, 100%) to (0%, 100%).
+ *
+ * @param[in] p_instance       PWM instance.
+ * @param[in] channel          PWM channel number.
+ * @param[in] ticks            Number of clock ticks.
+ */
+static void pwm_transition_n_to_m(app_pwm_t const * const p_instance,
+                                  uint8_t channel, uint16_t ticks)
+{
+    app_pwm_cb_t            * p_cb     = p_instance->p_cb;
+    app_pwm_channel_cb_t    * p_ch_cb  = &p_cb->channels_cb[channel];
+    nrf_ppi_channel_group_t   p_ppigrp = p_cb->ppi_group;
+
+    pwm_ppi_disable(p_instance);
+    nrf_drv_ppi_group_clear(p_ppigrp);
+    nrf_drv_ppi_channels_include_in_group(
+        nrf_drv_ppi_channel_to_mask(p_cb->ppi_channels[0]) | 
+        nrf_drv_ppi_channel_to_mask(p_cb->ppi_channels[1]),
+        p_ppigrp);
+
+    nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0],
+                nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL),
+                nrf_drv_timer_capture_task_address_get(p_instance->p_timer, channel));
+
+#ifdef NRF52
+    if (ticks + ((nrf_timer_frequency_get(p_instance->p_timer->p_reg) == 
+        (m_use_ppi_delay_workaround ? NRF_TIMER_FREQ_8MHz : NRF_TIMER_FREQ_16MHz) ) ? 1 : 0)
+        < p_ch_cb->pulsewidth)
+#else
+    if (ticks + ((nrf_timer_frequency_get(p_instance->p_timer->p_reg) == NRF_TIMER_FREQ_16MHz) ? 1 : 0)
+        < p_ch_cb->pulsewidth)
+#endif
+    {
+        // For lower value, we need one more transition. Timer task delay is included.
+        // If prescaler is disabled, one tick must be added because of 1 PCLK16M clock cycle delay.
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1],
+                nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL),
+                nrf_drv_gpiote_out_task_addr_get(p_ch_cb->gpio_pin));
+    }
+    else
+    {
+        nrf_drv_ppi_channel_remove_from_group(p_cb->ppi_channels[1], p_ppigrp);
+    }
+    p_ch_cb->pulsewidth = ticks;
+    nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, ticks, false);
+    nrf_drv_ppi_group_enable(p_ppigrp);
+    
+    m_pwm_target_value[p_instance->p_timer->instance_id] = ticks;
+    m_pwm_busy[p_instance->p_timer->instance_id] = channel;
+}
+
+
+/**
+ * @brief PWM state transition from 0% or 100% to (0%, 100%).
+ *
+ * @param[in] p_instance       PWM instance.
+ * @param[in] channel          PWM channel number.
+ * @param[in] ticks            Number of clock ticks.
+ */
+static void pwm_transition_0or100_to_n(app_pwm_t const * const p_instance,
+                                       uint8_t channel, uint16_t ticks)
+{
+    app_pwm_cb_t            * p_cb      = p_instance->p_cb;
+    app_pwm_channel_cb_t    * p_ch_cb   = &p_cb->channels_cb[channel];
+    nrf_ppi_channel_group_t   p_ppigrp  = p_cb->ppi_group;
+    nrf_timer_cc_channel_t    pwm_ch_cc = (nrf_timer_cc_channel_t)(channel);
+
+    pwm_ppi_disable(p_instance);
+    pwm_channel_ppi_disable(p_instance, channel);
+
+    nrf_drv_timer_compare(p_instance->p_timer, pwm_ch_cc, ticks, false);
+    nrf_drv_ppi_group_clear(p_ppigrp);
+    nrf_drv_ppi_channels_include_in_group(
+        nrf_drv_ppi_channel_to_mask(p_ch_cb->ppi_channels[0])|
+        nrf_drv_ppi_channel_to_mask(p_ch_cb->ppi_channels[1]),
+        p_ppigrp);
+
+    if (!p_ch_cb->pulsewidth)
+    {
+        // Channel is at 0%.
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0],
+                    nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel),
+                    nrf_drv_ppi_task_addr_group_enable_get(p_ppigrp));
+        nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, 0, false);
+        m_pwm_target_value[p_instance->p_timer->instance_id] = 
+            nrf_drv_timer_capture_get(p_instance->p_timer, (nrf_timer_cc_channel_t) channel);
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1],
+                    nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel),
+                    nrf_drv_timer_capture_task_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL));
+       
+    }
+    else
+    {
+        // Channel is at 100%.
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0],
+                    nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL),
+                    nrf_drv_ppi_task_addr_group_enable_get(p_ppigrp));
+        // Set secondary CC channel to non-zero value:
+        nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, 1, false);
+        m_pwm_target_value[p_instance->p_timer->instance_id] = 0;
+        // The captured value will be equal to 0, because timer clear on main PWM CC channel compare is enabled.
+        nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1],
+                    nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL),
+                    nrf_drv_timer_capture_task_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL));
+    }
+    nrf_drv_ppi_channel_enable(p_cb->ppi_channels[0]);
+    nrf_drv_ppi_channel_enable(p_cb->ppi_channels[1]);
+    
+    p_ch_cb->pulsewidth = ticks;
+    m_pwm_busy[p_instance->p_timer->instance_id] = PWM_SECONDARY_CC_CHANNEL;
+}
+
+
+/**
+ * @brief PWM state transition from 0% or 100% to 0% or 100%.
+ *
+ * @param[in] p_instance       PWM instance.
+ * @param[in] channel          PWM channel number.
+ * @param[in] ticks            Number of clock ticks.
+ */
+static void pwm_transition_0or100_to_0or100(app_pwm_t const * const p_instance,
+                                            uint8_t channel, uint16_t ticks)
+{
+    app_pwm_cb_t         * p_cb      = p_instance->p_cb;
+    app_pwm_channel_cb_t * p_ch_cb   = &p_cb->channels_cb[channel];
+    nrf_timer_cc_channel_t pwm_ch_cc = (nrf_timer_cc_channel_t)(channel);
+
+    pwm_ppi_disable(p_instance);
+    pwm_channel_ppi_disable(p_instance, channel);
+    if (!ticks)
+    {
+        // Set to 0%.
+        nrf_drv_gpiote_out_task_force(p_ch_cb->gpio_pin, POLARITY_INACTIVE(p_instance, channel));
+    }
+    else if (ticks >= p_cb->period)
+    {
+        // Set to 100%.
+        ticks = p_cb->period;
+        nrf_drv_gpiote_out_task_force(p_ch_cb->gpio_pin, POLARITY_ACTIVE(p_instance, channel));
+    }
+    nrf_drv_timer_compare(p_instance->p_timer, pwm_ch_cc, ticks, false);
+    p_ch_cb->pulsewidth = ticks;
+    
+    m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_IDLE;
+    return;
+}
+
+
+ret_code_t app_pwm_channel_duty_ticks_set(app_pwm_t const * const p_instance,
+                                          uint8_t           channel,
+                                          uint16_t          ticks)
+{
+    app_pwm_cb_t         * p_cb    = p_instance->p_cb;
+    app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel];
+
+    ASSERT(channel < APP_PWM_CHANNELS_PER_INSTANCE);
+    ASSERT(p_ch_cb->initialized == APP_PWM_CHANNEL_INITIALIZED);
+
+    if (p_cb->state != NRF_DRV_STATE_POWERED_ON)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+    if (ticks == p_ch_cb->pulsewidth)
+    {
+        if (p_cb->p_ready_callback)
+        {
+            p_cb->p_ready_callback(p_instance->p_timer->instance_id);
+        }
+        return NRF_SUCCESS;     // No action required.
+    }
+    if (app_pwm_busy_check(p_instance))
+    {
+        return NRF_ERROR_BUSY;  // PPI channels for synchronization are still in use.
+    }
+    
+    m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_CHANGING;
+
+    // Pulse width change sequence:
+    if (!p_ch_cb->pulsewidth || p_ch_cb->pulsewidth >= p_cb->period)
+    {
+        // Channel is disabled (0%) or at 100%.
+        if (!ticks || ticks >= p_cb->period)
+        {
+            // Set to 0 or 100%.
+            pwm_transition_0or100_to_0or100(p_instance, channel, ticks);
+        }
+        else
+        {
+            // Other value.
+            pwm_transition_0or100_to_n(p_instance, channel, ticks);
+        }
+    }
+    else
+    {
+        // Channel is at other value.
+        if (!ticks || ticks >= p_cb->period)
+        {
+            // Disable channel (set to 0%) or set to 100%.
+            pwm_transition_n_to_0or100(p_instance, channel, ticks);
+        }
+        else
+        {
+            // Set to any other value.
+            pwm_transition_n_to_m(p_instance, channel, ticks);
+        }
+    }
+    if (p_instance->p_cb->p_ready_callback)
+    {
+        //PWM ready interrupt handler will be called after one full period.
+        m_pwm_ready_counter[p_instance->p_timer->instance_id][channel] = 2;
+        pwm_irq_enable(p_instance);
+    }
+    return NRF_SUCCESS;
+}
+
+uint16_t app_pwm_channel_duty_ticks_get(app_pwm_t const * const p_instance, uint8_t channel)
+{
+    app_pwm_cb_t         * p_cb      = p_instance->p_cb;
+    app_pwm_channel_cb_t * p_ch_cb   = &p_cb->channels_cb[channel];
+
+    return p_ch_cb->pulsewidth;
+}
+
+uint16_t app_pwm_cycle_ticks_get(app_pwm_t const * const p_instance)
+{
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+
+    return (uint16_t)p_cb->period;
+}
+
+ret_code_t app_pwm_channel_duty_set(app_pwm_t const * const p_instance,
+                                  uint8_t channel, app_pwm_duty_t duty)
+{
+    uint32_t ticks = ((uint32_t)app_pwm_cycle_ticks_get(p_instance) * (uint32_t)duty) / 100UL;
+    return app_pwm_channel_duty_ticks_set(p_instance, channel, ticks);
+}
+
+
+app_pwm_duty_t app_pwm_channel_duty_get(app_pwm_t const * const p_instance, uint8_t channel)
+{
+    uint32_t value = ((uint32_t)app_pwm_channel_duty_ticks_get(p_instance, channel) * 100UL) \
+                     / (uint32_t)app_pwm_cycle_ticks_get(p_instance);
+
+    return (app_pwm_duty_t)value;
+}
+
+
+/**
+ * @brief Function for initializing the PWM channel.
+ *
+ * @param[in] p_instance       PWM instance.
+ * @param[in] channel          Channel number.
+ * @param[in] pin              GPIO pin number.
+ *
+ * @retval    NRF_SUCCESS If initialization was successful.
+ * @retval    NRF_ERROR_NO_MEM If there were not enough free resources.
+ * @retval    NRF_ERROR_INVALID_STATE If the timer is already in use or initialization failed.
+ */
+static ret_code_t app_pwm_channel_init(app_pwm_t const * const p_instance, uint8_t channel,
+                                     uint32_t pin, app_pwm_polarity_t polarity)
+{
+    ASSERT(channel < APP_PWM_CHANNELS_PER_INSTANCE);
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+    app_pwm_channel_cb_t * p_channel_cb = &p_cb->channels_cb[channel];
+
+    if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+
+    p_channel_cb->pulsewidth = 0;
+    p_channel_cb->polarity   = polarity;
+    ret_code_t err_code;
+
+    /* GPIOTE setup: */
+    nrf_drv_gpiote_out_config_t out_cfg = GPIOTE_CONFIG_OUT_TASK_TOGGLE( POLARITY_INACTIVE(p_instance, channel) );
+    err_code = nrf_drv_gpiote_out_init((nrf_drv_gpiote_pin_t)pin,&out_cfg);
+    if (err_code != NRF_SUCCESS)
+    {
+        return NRF_ERROR_NO_MEM;
+    }
+    p_cb->channels_cb[channel].gpio_pin = pin;
+
+    // Set output to inactive state.
+    if (polarity)
+    {
+        nrf_gpio_pin_clear(pin);
+    }
+    else
+    {
+        nrf_gpio_pin_set(pin);
+    }
+
+    /* PPI setup: */
+    for (uint8_t i = 0; i < APP_PWM_REQUIRED_PPI_CHANNELS_PER_CHANNEL; ++i)
+    {
+        if (nrf_drv_ppi_channel_alloc(&p_channel_cb->ppi_channels[i]) != NRF_SUCCESS)
+        {
+            return NRF_ERROR_NO_MEM; // Resource de-allocation is done by callee.
+        }
+    }
+
+    nrf_drv_ppi_channel_disable(p_channel_cb->ppi_channels[0]);
+    nrf_drv_ppi_channel_disable(p_channel_cb->ppi_channels[1]);
+    nrf_drv_ppi_channel_assign(p_channel_cb->ppi_channels[0],
+                               nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel),
+                               nrf_drv_gpiote_out_task_addr_get(p_channel_cb->gpio_pin));
+    nrf_drv_ppi_channel_assign(p_channel_cb->ppi_channels[1],
+                               nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL),
+                               nrf_drv_gpiote_out_task_addr_get(p_channel_cb->gpio_pin));
+
+    p_channel_cb->initialized = APP_PWM_CHANNEL_INITIALIZED;
+    m_pwm_ready_counter[p_instance->p_timer->instance_id][channel] = 0;
+
+    return NRF_SUCCESS;
+}
+
+
+/**
+ * @brief Function for calculating target timer frequency, which will allow to set given period length.
+ *
+ * @param[in] period_us       Desired period in microseconds.
+ *
+ * @retval    Timer frequency.
+ */
+__STATIC_INLINE nrf_timer_frequency_t pwm_calculate_timer_frequency(uint32_t period_us)
+{
+    uint32_t f   = (uint32_t) NRF_TIMER_FREQ_16MHz;
+    uint32_t min = (uint32_t) NRF_TIMER_FREQ_31250Hz;
+
+    while ((period_us > TIMER_MAX_PULSEWIDTH_US_ON_16M) && (f < min))
+    {
+        period_us >>= 1;
+        ++f;
+    }
+
+#ifdef NRF52
+    if ((m_use_ppi_delay_workaround) && (f == (uint32_t) NRF_TIMER_FREQ_16MHz))
+    {
+        f = (uint32_t) NRF_TIMER_FREQ_8MHz;
+    }
+#endif
+
+    return (nrf_timer_frequency_t) f;
+}
+
+
+ret_code_t app_pwm_init(app_pwm_t const * const p_instance, app_pwm_config_t const * const p_config,
+                        app_pwm_callback_t p_ready_callback)
+{
+    ASSERT(p_instance);
+
+    if (!p_config)
+    {
+        return NRF_ERROR_INVALID_DATA;
+    }
+
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+
+    if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+
+    uint32_t err_code = nrf_drv_ppi_init();
+    if ((err_code != NRF_SUCCESS) && (err_code != MODULE_ALREADY_INITIALIZED))
+    {
+        return NRF_ERROR_NO_MEM;
+    }
+
+
+    if (!nrf_drv_gpiote_is_init())
+    {
+        err_code = nrf_drv_gpiote_init();
+        if (err_code != NRF_SUCCESS)
+		{
+			return NRF_ERROR_INTERNAL;
+		}
+    }
+
+#ifdef NRF52
+    if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30)
+    {
+        m_use_ppi_delay_workaround = false;
+    }
+    else
+    {
+        m_use_ppi_delay_workaround = true;
+    }
+#endif
+    
+    // Innitialize resource status:
+    p_cb->ppi_channels[0] = (nrf_ppi_channel_t)UNALLOCATED;
+    p_cb->ppi_channels[1] = (nrf_ppi_channel_t)UNALLOCATED;
+    p_cb->ppi_group       = (nrf_ppi_channel_group_t)UNALLOCATED;
+
+    for (uint8_t i = 0; i < APP_PWM_CHANNELS_PER_INSTANCE; ++i)
+    {
+        p_cb->channels_cb[i].initialized     = APP_PWM_CHANNEL_UNINITIALIZED;
+        p_cb->channels_cb[i].ppi_channels[0] = (nrf_ppi_channel_t)UNALLOCATED;
+        p_cb->channels_cb[i].ppi_channels[1] = (nrf_ppi_channel_t)UNALLOCATED;
+        p_cb->channels_cb[i].gpio_pin        = UNALLOCATED;
+    }
+
+    // Allocate PPI channels and groups:
+    for (uint8_t i = 0; i < APP_PWM_REQUIRED_PPI_CHANNELS_PER_INSTANCE; ++i)
+    {
+        if (nrf_drv_ppi_channel_alloc(&p_cb->ppi_channels[i]) != NRF_SUCCESS)
+        {
+            pwm_dealloc(p_instance);
+            return NRF_ERROR_NO_MEM;
+        }
+    }
+    if (nrf_drv_ppi_group_alloc(&p_cb->ppi_group) != NRF_SUCCESS)
+    {
+        pwm_dealloc(p_instance);
+        return NRF_ERROR_NO_MEM;
+    }
+
+    // Initialize channels:
+    for (uint8_t i = 0; i < APP_PWM_CHANNELS_PER_INSTANCE; ++i)
+    {
+        if (p_config->pins[i] != APP_PWM_NOPIN)
+        {
+            err_code = app_pwm_channel_init(p_instance, i, p_config->pins[i], p_config->pin_polarity[i]);
+            if (err_code != NRF_SUCCESS)
+            {
+                pwm_dealloc(p_instance);
+                return err_code;
+            }
+            app_pwm_channel_duty_ticks_set(p_instance, i, 0);
+        }
+    }
+
+    // Initialize timer:
+    nrf_timer_frequency_t  timer_freq = pwm_calculate_timer_frequency(p_config->period_us);
+    nrf_drv_timer_config_t timer_cfg  = {
+        .frequency          = timer_freq,
+        .mode               = NRF_TIMER_MODE_TIMER,
+        .bit_width          = NRF_TIMER_BIT_WIDTH_16,
+        .interrupt_priority = APP_IRQ_PRIORITY_LOW,
+        .p_context          = (void *) (uint32_t) p_instance->p_timer->instance_id
+    };
+    err_code = nrf_drv_timer_init(p_instance->p_timer, &timer_cfg,
+                                  pwm_ready_tick);
+    if (err_code != NRF_SUCCESS)
+    {
+        pwm_dealloc(p_instance);
+        return err_code;
+    }
+
+    uint32_t ticks = nrf_drv_timer_us_to_ticks(p_instance->p_timer, p_config->period_us);
+    p_cb->period = ticks;
+    nrf_drv_timer_clear(p_instance->p_timer);
+    nrf_drv_timer_extended_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_MAIN_CC_CHANNEL,
+                                    ticks, NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, true);
+    nrf_drv_timer_compare_int_disable(p_instance->p_timer, PWM_MAIN_CC_CHANNEL);
+
+    p_cb->p_ready_callback = p_ready_callback;
+    m_instances[p_instance->p_timer->instance_id] = p_instance;
+    m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_IDLE;
+    p_cb->state = NRF_DRV_STATE_INITIALIZED;
+
+    return NRF_SUCCESS;
+}
+
+
+void app_pwm_enable(app_pwm_t const * const p_instance)
+{
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+
+    ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
+
+    for (uint32_t channel = 0; channel < APP_PWM_CHANNELS_PER_INSTANCE; ++channel)
+    {
+        app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel];
+        m_pwm_ready_counter[p_instance->p_timer->instance_id][channel] = 0;
+        if (p_ch_cb->initialized)
+        {
+            nrf_drv_gpiote_out_task_force(p_ch_cb->gpio_pin, POLARITY_INACTIVE(p_instance, channel));
+            nrf_drv_gpiote_out_task_enable(p_ch_cb->gpio_pin);
+            p_ch_cb->pulsewidth = 0;
+        }
+    }
+    m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_IDLE;
+    pan73_workaround(p_instance->p_timer->p_reg, true);
+    nrf_drv_timer_clear(p_instance->p_timer);
+    nrf_drv_timer_enable(p_instance->p_timer);
+
+    p_cb->state = NRF_DRV_STATE_POWERED_ON;
+    return;
+}
+
+
+void app_pwm_disable(app_pwm_t const * const p_instance)
+{
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+
+    ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
+
+    nrf_drv_timer_disable(p_instance->p_timer);
+    pwm_irq_disable(p_instance);
+    for (uint8_t ppi_channel = 0; ppi_channel < APP_PWM_REQUIRED_PPI_CHANNELS_PER_INSTANCE; ++ppi_channel)
+    {
+        nrf_drv_ppi_channel_disable(p_cb->ppi_channels[ppi_channel]);
+    }
+    for (uint8_t channel = 0; channel < APP_PWM_CHANNELS_PER_INSTANCE; ++channel)
+    {
+        app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel];
+        if (p_ch_cb->initialized)
+        {
+            uint8_t polarity = POLARITY_INACTIVE(p_instance, channel);
+            if (polarity)
+            {
+                nrf_gpio_pin_set(p_ch_cb->gpio_pin);
+            }
+            else
+            {
+                nrf_gpio_pin_clear(p_ch_cb->gpio_pin);
+            }
+            nrf_drv_gpiote_out_task_disable(p_ch_cb->gpio_pin);
+            nrf_drv_ppi_channel_disable(p_ch_cb->ppi_channels[0]);
+            nrf_drv_ppi_channel_disable(p_ch_cb->ppi_channels[1]);
+        }
+    }
+    pan73_workaround(p_instance->p_timer->p_reg, false);
+
+    p_cb->state = NRF_DRV_STATE_INITIALIZED;
+    return;
+}
+
+
+ret_code_t app_pwm_uninit(app_pwm_t const * const p_instance)
+{
+    app_pwm_cb_t * p_cb = p_instance->p_cb;
+
+    if (p_cb->state == NRF_DRV_STATE_POWERED_ON)
+    {
+        app_pwm_disable(p_instance);
+    }
+    else if (p_cb->state == NRF_DRV_STATE_UNINITIALIZED)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+    pwm_dealloc(p_instance);
+
+    p_cb->state = NRF_DRV_STATE_UNINITIALIZED;
+    return NRF_SUCCESS;
+}
+
+
+//lint -restore

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/pwm/app_pwm.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/pwm/app_pwm.h b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/pwm/app_pwm.h
new file mode 100644
index 0000000..ebeaa64
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/pwm/app_pwm.h
@@ -0,0 +1,295 @@
+/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+/** @file
+ *
+ * @defgroup app_pwm Pulse-width modulation (PWM)
+ * @{
+ * @ingroup app_common
+ *
+ * @brief Module for generating a pulse-width modulated output signal.
+ *
+ * @details This module provides a PWM implementation using timers, GPIOTE, and PPI.
+ *
+ * Resource usage:
+ * - 2 PPI channels per instance + 2 PPI channels per PWM channel.
+ * - 1 PPI group per instance.
+ * - 1 GPIOTE channel per PWM channel.
+ *
+ * For example, a PWM instance with two channels will consume 2+4 PPI channels, 1 PPI group, and 2 GPIOTE channels.
+ *
+ * The maximum number of PWM channels per instance is 2.
+ */
+
+#ifndef APP_PWM_H__
+#define APP_PWM_H__
+
+#include <stdint.h>
+#include "sdk_errors.h"
+#include "nrf_drv_timer.h"
+#include "nrf_drv_common.h"
+#include "nrf_drv_ppi.h"
+
+
+#define APP_PWM_NOPIN                 0xFFFFFFFF
+
+/** @brief Number of channels for one timer instance (fixed to 2 due to timer properties).*/
+#define APP_PWM_CHANNELS_PER_INSTANCE 2
+
+/**@brief Macro for creating a PWM instance. */
+#define APP_PWM_INSTANCE(name, num)                                           \
+    const nrf_drv_timer_t m_pwm_##name##_timer = NRF_DRV_TIMER_INSTANCE(num); \
+    app_pwm_cb_t m_pwm_##name##_cb;                                           \
+    /*lint -e{545}*/                                                          \
+    const app_pwm_t name = {                                                  \
+        .p_cb    = &m_pwm_##name##_cb,                                        \
+        .p_timer = &m_pwm_##name##_timer,                                     \
+    }
+
+
+/**@brief PWM instance default configuration (1 channel). */
+#define APP_PWM_DEFAULT_CONFIG_1CH(period_in_us, pin)                                  \
+    {                                                                                  \
+        .pins            = {pin, APP_PWM_NOPIN},                                       \
+        .pin_polarity    = {APP_PWM_POLARITY_ACTIVE_LOW, APP_PWM_POLARITY_ACTIVE_LOW}, \
+        .num_of_channels = 1,                                                          \
+        .period_us       = period_in_us                                                \
+    }
+
+/**@brief PWM instance default configuration (2 channels). */
+#define APP_PWM_DEFAULT_CONFIG_2CH(period_in_us, pin0, pin1)                           \
+    {                                                                                  \
+        .pins            = {pin0, pin1},                                               \
+        .pin_polarity    = {APP_PWM_POLARITY_ACTIVE_LOW, APP_PWM_POLARITY_ACTIVE_LOW}, \
+        .num_of_channels = 2,                                                          \
+        .period_us       = period_in_us                                                \
+    }
+
+typedef uint16_t app_pwm_duty_t;
+
+/**
+ * @brief PWM callback that is executed when a PWM duty change has been completed.
+ *
+ * @param[in] pwm_id  PWM instance ID.
+ */
+typedef void (* app_pwm_callback_t)(uint32_t);
+
+/**
+ * @brief Channel polarity.
+ */
+typedef enum
+{
+    APP_PWM_POLARITY_ACTIVE_LOW  = 0,
+    APP_PWM_POLARITY_ACTIVE_HIGH = 1
+} app_pwm_polarity_t;
+
+/**@brief PWM configuration structure used for initialization. */
+typedef struct
+{
+    uint32_t           pins[APP_PWM_CHANNELS_PER_INSTANCE];         //!< Pins configured as PWM output.
+    app_pwm_polarity_t pin_polarity[APP_PWM_CHANNELS_PER_INSTANCE]; //!< Polarity of active state on pin.
+    uint32_t           num_of_channels;                             //!< Number of channels that can be used.
+    uint32_t           period_us;                                   //!< PWM signal output period to configure (in microseconds).
+} app_pwm_config_t;
+
+
+/**
+ * @cond (NODOX)
+ * @defgroup app_pwm_internal Auxiliary internal types declarations
+ * @{
+ * @internal
+ *
+ * @brief Module for internal usage inside the library only
+ *
+ * There are some definitions that must be included in the header file because 
+ * of the way the library is set up. In this way, the are accessible to the user.
+ * However, any functions and variables defined here may change at any time 
+ * without a warning, so you should not access them directly.
+ */
+
+    /**
+     * @brief PWM channel instance
+     *
+     * This structure holds all data needed by a single PWM channel.
+     */
+    typedef struct
+    {
+        uint32_t           gpio_pin;        //!< Pin that is used by this PWM channel.
+        uint32_t           pulsewidth;      //!< The copy of duty currently set (in ticks).
+        nrf_ppi_channel_t  ppi_channels[2]; //!< PPI channels used by the PWM channel to clear and set the output.
+        app_pwm_polarity_t polarity;        //!< The active state of the pin.
+        uint8_t            initialized;     //!< The internal information if the selected channel was initialized.
+    } app_pwm_channel_cb_t;
+
+    /**
+     * @brief Variable part of PWM instance
+     *
+     * This structure holds instance data that may change.
+     */
+    typedef struct
+    {
+        app_pwm_channel_cb_t    channels_cb[APP_PWM_CHANNELS_PER_INSTANCE]; //!< Channels data
+        uint32_t                period;                                     //!< Selected period in ticks
+        app_pwm_callback_t      p_ready_callback;                           //!< Callback function called on PWM readiness
+        nrf_ppi_channel_t       ppi_channels[2];                            //!< PPI channels used temporary while changing duty
+        nrf_ppi_channel_group_t ppi_group;                                  //!< PPI group used to synchronize changes on channels
+        nrf_drv_state_t         state;                                      //!< Current driver status
+    } app_pwm_cb_t;
+/** @}
+ * @endcond
+ */
+
+
+/**@brief PWM instance structure. */
+typedef struct
+{
+    app_pwm_cb_t *p_cb;                    //!< Pointer to control block internals.
+    nrf_drv_timer_t const * const p_timer; //!< Timer used by this PWM instance.
+} app_pwm_t;
+
+/**
+ * @brief Function for checking if the PWM instance is busy updating the duty cycle.
+ *
+ * @param[in] p_instance  PWM instance.
+ *
+ * @retval True  If the PWM instance is ready for duty cycle changes.
+ * @retval False If a change operation is in progress.
+ */
+bool app_pwm_busy_check(app_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for initializing a PWM instance.
+ *
+ * @param[in] p_instance        PWM instance.
+ * @param[in] p_config          Initial configuration.
+ * @param[in] p_ready_callback  Pointer to ready callback function (or NULL to disable).
+ *
+ * @retval    NRF_SUCCESS If initialization was successful.
+ * @retval    NRF_ERROR_NO_MEM If there were not enough free resources.
+ * @retval    NRF_ERROR_INVALID_PARAM If an invalid configuration structure was passed.
+ * @retval    NRF_ERROR_INVALID_STATE If the timer/PWM is already in use or if initialization failed.
+ */
+ret_code_t app_pwm_init(app_pwm_t const * const p_instance, app_pwm_config_t const * const p_config,
+                        app_pwm_callback_t p_ready_callback);
+
+
+/**
+ * @brief Function for uninitializing a PWM instance and releasing the allocated resources.
+ *
+ * @param[in] p_instance  PWM instance.
+ *
+ * @retval    NRF_SUCCESS If uninitialization was successful.
+ * @retval    NRF_ERROR_INVALID_STATE If the given instance was not initialized.
+ */
+ret_code_t app_pwm_uninit(app_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for enabling a PWM instance after initialization.
+ *
+ * @param[in] p_instance  PWM instance.
+ */
+void app_pwm_enable(app_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for disabling a PWM instance after initialization.
+ *
+ * @param[in] p_instance  PWM instance.
+ */
+void app_pwm_disable(app_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for setting the PWM channel duty cycle in percents.
+ *
+ * A duty cycle change requires one full PWM clock period to finish.
+ * If another change is attempted for any channel of given instance before
+ * the current change is complete, the new attempt will result in the error
+ * NRF_ERROR_BUSY.
+ *
+ * @param[in] p_instance  PWM instance.
+ * @param[in] channel     Channel number.
+ * @param[in] duty        Duty cycle (0 - 100).
+ *
+ * @retval    NRF_SUCCESS If the operation was successful.
+ * @retval    NRF_ERROR_BUSY If the PWM is not ready yet.
+ * @retval    NRF_ERROR_INVALID_STATE If the given instance was not initialized.
+ *
+ */
+ret_code_t app_pwm_channel_duty_set(app_pwm_t const * const p_instance,
+                                  uint8_t channel, app_pwm_duty_t duty);
+
+/**
+ * @brief Function for retrieving the PWM channel duty cycle in percents.
+ *
+ * @param[in] p_instance  PWM instance.
+ * @param[in] channel     Channel number.
+ *
+ * @return    Duty cycle value.
+ */
+app_pwm_duty_t app_pwm_channel_duty_get(app_pwm_t const * const p_instance, uint8_t channel);
+
+
+/**
+ * @name Functions accessing values in ticks
+ *
+ * Auxiliary functions that allow to get values in actual timer ticks.
+ * @{
+ */
+
+    /**
+     * @brief Function for setting PWM channel duty cycle in clock ticks.
+     *
+     * @note      Duty cycle changes require one full PWM clock period to finish.
+     *            Until that, the next change attempt (for any channel of given instance)
+     *            will result in an NRF_ERROR_BUSY error.
+     *
+     * @param[in] p_instance  PWM instance.
+     * @param[in] channel     Channel number.
+     * @param[in] ticks       Number of PWM clock ticks.
+     *
+     * @retval    NRF_SUCCESS If the operation was successful.
+     * @retval    NRF_ERROR_BUSY If PWM is not ready yet.
+     * @retval    NRF_ERROR_INVALID_STATE If the given instance was not initialized.
+     */
+    ret_code_t app_pwm_channel_duty_ticks_set(app_pwm_t const * const p_instance,
+                                              uint8_t           channel,
+                                              uint16_t          ticks);
+
+
+    /**
+     * @brief Function for retrieving the PWM channel duty cycle in ticks.
+     *
+     * This function retrieves the real, currently set duty cycle in ticks.
+     * For one full PWM cycle the value might be different than the value set by the last
+     * @ref app_pwm_channel_duty_ticks_set function call.
+     *
+     * @param[in] p_instance  PWM instance.
+     * @param[in] channel     Channel number.
+     *
+     * @return    Number of ticks set for selected channel.
+     *
+     */
+    uint16_t app_pwm_channel_duty_ticks_get(app_pwm_t const * const p_instance, uint8_t channel);
+
+    /**
+     * @brief Function for returning the number of ticks in a whole cycle.
+     *
+     * @param[in] p_instance  PWM instance.
+     *
+     * @return    Number of ticks that corresponds to 100% of the duty cycle.
+     */
+    uint16_t app_pwm_cycle_ticks_get(app_pwm_t const * const p_instance);
+/** @} */
+
+
+#endif
+
+/** @} */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler.c
new file mode 100644
index 0000000..829d7f9
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler.c
@@ -0,0 +1,227 @@
+/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+#include "app_scheduler.h"
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "nrf_soc.h"
+#include "nrf_assert.h"
+#include "app_util.h"
+#include "app_util_platform.h"
+
+/**@brief Structure for holding a scheduled event header. */
+typedef struct
+{
+    app_sched_event_handler_t handler;          /**< Pointer to event handler to receive the event. */
+    uint16_t                  event_data_size;  /**< Size of event data. */
+} event_header_t;
+
+STATIC_ASSERT(sizeof(event_header_t) <= APP_SCHED_EVENT_HEADER_SIZE);
+
+static event_header_t * m_queue_event_headers;  /**< Array for holding the queue event headers. */
+static uint8_t        * m_queue_event_data;     /**< Array for holding the queue event data. */
+static volatile uint8_t m_queue_start_index;    /**< Index of queue entry at the start of the queue. */
+static volatile uint8_t m_queue_end_index;      /**< Index of queue entry at the end of the queue. */
+static uint16_t         m_queue_event_size;     /**< Maximum event size in queue. */
+static uint16_t         m_queue_size;           /**< Number of queue entries. */
+
+#ifdef APP_SCHEDULER_WITH_PROFILER
+static uint16_t m_max_queue_utilization;    /**< Maximum observed queue utilization. */
+#endif
+
+/**@brief Function for incrementing a queue index, and handle wrap-around.
+ *
+ * @param[in]   index   Old index.
+ *
+ * @return      New (incremented) index.
+ */
+static __INLINE uint8_t next_index(uint8_t index)
+{
+    return (index < m_queue_size) ? (index + 1) : 0;
+}
+
+
+static __INLINE uint8_t app_sched_queue_full()
+{
+  uint8_t tmp = m_queue_start_index;
+  return next_index(m_queue_end_index) == tmp;
+}
+
+/**@brief Macro for checking if a queue is full. */
+#define APP_SCHED_QUEUE_FULL() app_sched_queue_full()
+
+
+static __INLINE uint8_t app_sched_queue_empty()
+{
+  uint8_t tmp = m_queue_start_index;
+  return m_queue_end_index == tmp;
+}
+
+/**@brief Macro for checking if a queue is empty. */
+#define APP_SCHED_QUEUE_EMPTY() app_sched_queue_empty()
+
+
+uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer)
+{
+    uint16_t data_start_index = (queue_size + 1) * sizeof(event_header_t);
+
+    // Check that buffer is correctly aligned
+    if (!is_word_aligned(p_event_buffer))
+    {
+        return NRF_ERROR_INVALID_PARAM;
+    }
+
+    // Initialize event scheduler
+    m_queue_event_headers = p_event_buffer;
+    m_queue_event_data    = &((uint8_t *)p_event_buffer)[data_start_index];
+    m_queue_end_index     = 0;
+    m_queue_start_index   = 0;
+    m_queue_event_size    = event_size;
+    m_queue_size          = queue_size;
+
+#ifdef APP_SCHEDULER_WITH_PROFILER
+    m_max_queue_utilization = 0;
+#endif
+
+    return NRF_SUCCESS;
+}
+
+
+#ifdef APP_SCHEDULER_WITH_PROFILER
+static void queue_utilization_check(void)
+{
+    uint16_t start = m_queue_start_index;
+    uint16_t end   = m_queue_end_index;
+    uint16_t queue_utilization = (end >= start) ? (end - start) :
+        (m_queue_size + 1 - start + end);
+
+    if (queue_utilization > m_max_queue_utilization)
+    {
+        m_max_queue_utilization = queue_utilization;
+    }
+}
+
+uint16_t app_sched_queue_utilization_get(void)
+{
+    return m_max_queue_utilization;
+}
+#endif
+
+
+uint32_t app_sched_event_put(void                    * p_event_data,
+                             uint16_t                  event_data_size,
+                             app_sched_event_handler_t handler)
+{
+    uint32_t err_code;
+
+    if (event_data_size <= m_queue_event_size)
+    {
+        uint16_t event_index = 0xFFFF;
+
+        CRITICAL_REGION_ENTER();
+
+        if (!APP_SCHED_QUEUE_FULL())
+        {
+            event_index       = m_queue_end_index;
+            m_queue_end_index = next_index(m_queue_end_index);
+
+        #ifdef APP_SCHEDULER_WITH_PROFILER
+            // This function call must be protected with critical region because
+            // it modifies 'm_max_queue_utilization'.
+            queue_utilization_check();
+        #endif
+        }
+
+        CRITICAL_REGION_EXIT();
+
+        if (event_index != 0xFFFF)
+        {
+            // NOTE: This can be done outside the critical region since the event consumer will
+            //       always be called from the main loop, and will thus never interrupt this code.
+            m_queue_event_headers[event_index].handler = handler;
+            if ((p_event_data != NULL) && (event_data_size > 0))
+            {
+                memcpy(&m_queue_event_data[event_index * m_queue_event_size],
+                       p_event_data,
+                       event_data_size);
+                m_queue_event_headers[event_index].event_data_size = event_data_size;
+            }
+            else
+            {
+                m_queue_event_headers[event_index].event_data_size = 0;
+            }
+
+            err_code = NRF_SUCCESS;
+        }
+        else
+        {
+            err_code = NRF_ERROR_NO_MEM;
+        }
+    }
+    else
+    {
+        err_code = NRF_ERROR_INVALID_LENGTH;
+    }
+
+    return err_code;
+}
+
+
+/**@brief Function for reading the next event from specified event queue.
+ *
+ * @param[out]  pp_event_data       Pointer to pointer to event data.
+ * @param[out]  p_event_data_size   Pointer to size of event data.
+ * @param[out]  p_event_handler     Pointer to event handler function pointer.
+ *
+ * @return      NRF_SUCCESS if new event, NRF_ERROR_NOT_FOUND if event queue is empty.
+ */
+static uint32_t app_sched_event_get(void                     ** pp_event_data,
+                                    uint16_t *                  p_event_data_size,
+                                    app_sched_event_handler_t * p_event_handler)
+{
+    uint32_t err_code = NRF_ERROR_NOT_FOUND;
+
+    if (!APP_SCHED_QUEUE_EMPTY())
+    {
+        uint16_t event_index;
+
+        // NOTE: There is no need for a critical region here, as this function will only be called
+        //       from app_sched_execute() from inside the main loop, so it will never interrupt
+        //       app_sched_event_put(). Also, updating of (i.e. writing to) the start index will be
+        //       an atomic operation.
+        event_index         = m_queue_start_index;
+        m_queue_start_index = next_index(m_queue_start_index);
+
+        *pp_event_data     = &m_queue_event_data[event_index * m_queue_event_size];
+        *p_event_data_size = m_queue_event_headers[event_index].event_data_size;
+        *p_event_handler   = m_queue_event_headers[event_index].handler;
+
+        err_code = NRF_SUCCESS;
+    }
+
+    return err_code;
+}
+
+
+void app_sched_execute(void)
+{
+    void                    * p_event_data;
+    uint16_t                  event_data_size;
+    app_sched_event_handler_t event_handler;
+
+    // Get next event (if any), and execute handler
+    while ((app_sched_event_get(&p_event_data, &event_data_size, &event_handler) == NRF_SUCCESS))
+    {
+        event_handler(p_event_data, event_data_size);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler.h b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler.h
new file mode 100644
index 0000000..f52e616
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler.h
@@ -0,0 +1,163 @@
+/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+/** @file
+ *
+ * @defgroup app_scheduler Scheduler
+ * @{
+ * @ingroup app_common
+ *
+ * @brief The scheduler is used for transferring execution from the interrupt context to the main
+ *        context.
+ *
+ * @details See @ref seq_diagrams_sched for sequence diagrams illustrating the flow of events
+ *          when using the Scheduler.
+ *
+ * @section app_scheduler_req Requirements:
+ *
+ * @subsection main_context_logic Logic in main context:
+ *
+ *   - Define an event handler for each type of event expected.
+ *   - Initialize the scheduler by calling the APP_SCHED_INIT() macro before entering the
+ *     application main loop.
+ *   - Call app_sched_execute() from the main loop each time the application wakes up because of an
+ *     event (typically when sd_app_evt_wait() returns).
+ *
+ * @subsection int_context_logic Logic in interrupt context:
+ *
+ *   - In the interrupt handler, call app_sched_event_put()
+ *     with the appropriate data and event handler. This will insert an event into the
+ *     scheduler's queue. The app_sched_execute() function will pull this event and call its
+ *     handler in the main context.
+ *
+ * @if (PERIPHERAL)
+ * For an example usage of the scheduler, see the implementations of
+ * @ref ble_sdk_app_hids_mouse and @ref ble_sdk_app_hids_keyboard.
+ * @endif
+ *
+ * @image html scheduler_working.jpg The high level design of the scheduler
+ */
+
+#ifndef APP_SCHEDULER_H__
+#define APP_SCHEDULER_H__
+
+#include <stdint.h>
+#include "app_error.h"
+#include "app_util.h"
+
+#define APP_SCHED_EVENT_HEADER_SIZE 8       /**< Size of app_scheduler.event_header_t (only for use inside APP_SCHED_BUF_SIZE()). */
+
+/**@brief Compute number of bytes required to hold the scheduler buffer.
+ *
+ * @param[in] EVENT_SIZE   Maximum size of events to be passed through the scheduler.
+ * @param[in] QUEUE_SIZE   Number of entries in scheduler queue (i.e. the maximum number of events
+ *                         that can be scheduled for execution).
+ *
+ * @return    Required scheduler buffer size (in bytes).
+ */
+#define APP_SCHED_BUF_SIZE(EVENT_SIZE, QUEUE_SIZE)                                                 \
+            (((EVENT_SIZE) + APP_SCHED_EVENT_HEADER_SIZE) * ((QUEUE_SIZE) + 1))
+            
+/**@brief Scheduler event handler type. */
+typedef void (*app_sched_event_handler_t)(void * p_event_data, uint16_t event_size);
+
+/**@brief Macro for initializing the event scheduler.
+ *
+ * @details It will also handle dimensioning and allocation of the memory buffer required by the
+ *          scheduler, making sure the buffer is correctly aligned.
+ *
+ * @param[in] EVENT_SIZE   Maximum size of events to be passed through the scheduler.
+ * @param[in] QUEUE_SIZE   Number of entries in scheduler queue (i.e. the maximum number of events
+ *                         that can be scheduled for execution).
+ *
+ * @note Since this macro allocates a buffer, it must only be called once (it is OK to call it
+ *       several times as long as it is from the same location, e.g. to do a reinitialization).
+ */
+#define APP_SCHED_INIT(EVENT_SIZE, QUEUE_SIZE)                                                     \
+    do                                                                                             \
+    {                                                                                              \
+        static uint32_t APP_SCHED_BUF[CEIL_DIV(APP_SCHED_BUF_SIZE((EVENT_SIZE), (QUEUE_SIZE)),     \
+                                               sizeof(uint32_t))];                                 \
+        uint32_t ERR_CODE = app_sched_init((EVENT_SIZE), (QUEUE_SIZE), APP_SCHED_BUF);             \
+        APP_ERROR_CHECK(ERR_CODE);                                                                 \
+    } while (0)
+
+/**@brief Function for initializing the Scheduler.
+ *
+ * @details It must be called before entering the main loop.
+ *
+ * @param[in]   max_event_size   Maximum size of events to be passed through the scheduler.
+ * @param[in]   queue_size       Number of entries in scheduler queue (i.e. the maximum number of
+ *                               events that can be scheduled for execution).
+ * @param[in]   p_evt_buffer   Pointer to memory buffer for holding the scheduler queue. It must
+ *                               be dimensioned using the APP_SCHED_BUFFER_SIZE() macro. The buffer
+ *                               must be aligned to a 4 byte boundary.
+ *
+ * @note Normally initialization should be done using the APP_SCHED_INIT() macro, as that will both
+ *       allocate the scheduler buffer, and also align the buffer correctly.
+ *
+ * @retval      NRF_SUCCESS               Successful initialization.
+ * @retval      NRF_ERROR_INVALID_PARAM   Invalid parameter (buffer not aligned to a 4 byte
+ *                                        boundary).
+ */
+uint32_t app_sched_init(uint16_t max_event_size, uint16_t queue_size, void * p_evt_buffer);
+
+/**@brief Function for executing all scheduled events.
+ *
+ * @details This function must be called from within the main loop. It will execute all events
+ *          scheduled since the last time it was called.
+ */
+void app_sched_execute(void);
+
+/**@brief Function for scheduling an event.
+ *
+ * @details Puts an event into the event queue.
+ *
+ * @param[in]   p_event_data   Pointer to event data to be scheduled.
+ * @param[in]   event_size   Size of event data to be scheduled.
+ * @param[in]   handler        Event handler to receive the event.
+ *
+ * @return      NRF_SUCCESS on success, otherwise an error code.
+ */
+uint32_t app_sched_event_put(void *                    p_event_data,
+                             uint16_t                  event_size,
+                             app_sched_event_handler_t handler);
+
+#ifdef APP_SCHEDULER_WITH_PROFILER
+/**@brief Function for getting the maximum observed queue utilization.
+ *
+ * Function for tuning the module and determining QUEUE_SIZE value and thus module RAM usage.
+ *
+ * @return Maximum number of events in queue observed so far.
+ */
+uint16_t app_sched_queue_utilization_get(void);
+#endif
+
+#ifdef APP_SCHEDULER_WITH_PAUSE
+/**@brief A function to pause the scheduler.
+ *
+ * @details When the scheduler is paused events are not pulled from the scheduler queue for
+ *          processing. The function can be called multiple times. To unblock the scheduler the
+ *          function @ref app_sched_resume has to be called the same number of times.
+ */
+void app_sched_pause(void);
+
+/**@brief A function to resume a scheduler.
+ *
+ * @details To unblock the scheduler this function has to be called the same number of times as
+ *          @ref app_sched_pause function.
+ */
+void app_sched_resume(void);
+#endif
+#endif // APP_SCHEDULER_H__
+
+/** @} */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler_serconn.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler_serconn.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler_serconn.c
new file mode 100644
index 0000000..f411eff
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/scheduler/app_scheduler_serconn.c
@@ -0,0 +1,262 @@
+/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+#include "app_scheduler.h"
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "nrf_soc.h"
+#include "nrf_assert.h"
+#include "app_util.h"
+#include "app_util_platform.h"
+
+/**@brief Structure for holding a scheduled event header. */
+typedef struct
+{
+    app_sched_event_handler_t handler;         /**< Pointer to event handler to receive the event. */
+    uint16_t                  event_data_size; /**< Size of event data. */
+} event_header_t;
+
+STATIC_ASSERT(sizeof (event_header_t) <= APP_SCHED_EVENT_HEADER_SIZE);
+
+static event_header_t * m_queue_event_headers; /**< Array for holding the queue event headers. */
+static uint8_t *        m_queue_event_data;    /**< Array for holding the queue event data. */
+static volatile uint8_t m_queue_start_index;   /**< Index of queue entry at the start of the queue. */
+static volatile uint8_t m_queue_end_index;     /**< Index of queue entry at the end of the queue. */
+static uint16_t         m_queue_event_size;    /**< Maximum event size in queue. */
+static uint16_t         m_queue_size;          /**< Number of queue entries. */
+
+#ifdef APP_SCHEDULER_WITH_PROFILER
+static uint16_t m_max_queue_utilization;    /**< Maximum observed queue utilization. */
+#endif
+
+static uint32_t m_scheduler_paused_counter = 0; /**< Counter storing the difference between pausing
+                                                     and resuming the scheduler. */
+
+/**@brief Function for incrementing a queue index, and handle wrap-around.
+ *
+ * @param[in]   index   Old index.
+ *
+ * @return      New (incremented) index.
+ */
+static __INLINE uint8_t next_index(uint8_t index)
+{
+    return (index < m_queue_size) ? (index + 1) : 0;
+}
+
+static __INLINE uint8_t app_sched_queue_full(void)
+{
+  uint8_t tmp = m_queue_start_index;
+  return next_index(m_queue_end_index) == tmp;
+}
+
+/**@brief Macro for checking if a queue is full. */
+#define APP_SCHED_QUEUE_FULL() app_sched_queue_full()
+
+static __INLINE uint8_t app_sched_queue_empty(void)
+{
+  uint8_t tmp = m_queue_start_index;
+  return m_queue_end_index == tmp;
+}
+
+/**@brief Macro for checking if a queue is empty. */
+#define APP_SCHED_QUEUE_EMPTY() app_sched_queue_empty()
+
+
+uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer)
+{
+    uint16_t data_start_index = (queue_size + 1) * sizeof (event_header_t);
+
+    //Check that buffer is correctly aligned
+    if (!is_word_aligned(p_event_buffer))
+    {
+        return NRF_ERROR_INVALID_PARAM;
+    }
+
+    //Initialize event scheduler
+    m_queue_event_headers = p_event_buffer;
+    m_queue_event_data    = &((uint8_t *)p_event_buffer)[data_start_index];
+    m_queue_end_index     = 0;
+    m_queue_start_index   = 0;
+    m_queue_event_size    = event_size;
+    m_queue_size          = queue_size;
+
+#ifdef APP_SCHEDULER_WITH_PROFILER
+    m_max_queue_utilization = 0;
+#endif
+
+    return NRF_SUCCESS;
+}
+
+
+#ifdef APP_SCHEDULER_WITH_PROFILER
+static void check_queue_utilization(void)
+{
+    uint16_t start = m_queue_start_index;
+    uint16_t end   = m_queue_end_index;
+    uint16_t queue_utilization = (end >= start) ? (end - start) :
+        (m_queue_size + 1 - start + end);
+
+    if (queue_utilization > m_max_queue_utilization)
+    {
+        m_max_queue_utilization = queue_utilization;
+    }
+}
+
+uint16_t app_sched_queue_utilization_get(void)
+{
+    return m_max_queue_utilization;
+}
+#endif
+
+
+uint32_t app_sched_event_put(void *                    p_event_data,
+                             uint16_t                  event_data_size,
+                             app_sched_event_handler_t handler)
+{
+    uint32_t err_code;
+
+    if (event_data_size <= m_queue_event_size)
+    {
+        uint16_t event_index = 0xFFFF;
+
+        CRITICAL_REGION_ENTER();
+
+        if (!APP_SCHED_QUEUE_FULL())
+        {
+            event_index       = m_queue_end_index;
+            m_queue_end_index = next_index(m_queue_end_index);
+        }
+
+        CRITICAL_REGION_EXIT();
+
+        if (event_index != 0xFFFF)
+        {
+            //NOTE: This can be done outside the critical region since the event consumer will
+            //always be called from the main loop, and will thus never interrupt this code.
+            m_queue_event_headers[event_index].handler = handler;
+
+            if ((p_event_data != NULL) && (event_data_size > 0))
+            {
+                memcpy(&m_queue_event_data[event_index * m_queue_event_size],
+                       p_event_data,
+                       event_data_size);
+                m_queue_event_headers[event_index].event_data_size = event_data_size;
+            }
+            else
+            {
+                m_queue_event_headers[event_index].event_data_size = 0;
+            }
+
+        #ifdef APP_SCHEDULER_WITH_PROFILER
+            check_queue_utilization();
+        #endif
+
+            err_code = NRF_SUCCESS;
+        }
+        else
+        {
+            err_code = NRF_ERROR_NO_MEM;
+        }
+    }
+    else
+    {
+        err_code = NRF_ERROR_INVALID_LENGTH;
+    }
+
+    return err_code;
+}
+
+
+/**@brief Function for reading the next event from specified event queue.
+ *
+ * @param[out]  pp_event_data       Pointer to pointer to event data.
+ * @param[out]  p_event_data_size   Pointer to size of event data.
+ * @param[out]  p_event_handler     Pointer to event handler function pointer.
+ *
+ * @return      NRF_SUCCESS if new event, NRF_ERROR_NOT_FOUND if event queue is empty.
+ */
+static uint32_t app_sched_event_get(void * *                    pp_event_data,
+                                    uint16_t *                  p_event_data_size,
+                                    app_sched_event_handler_t * p_event_handler)
+{
+    uint32_t err_code = NRF_ERROR_NOT_FOUND;
+
+    if (!APP_SCHED_QUEUE_EMPTY())
+    {
+        uint16_t event_index;
+
+        //NOTE: There is no need for a critical region here, as this function will only be called
+        //from app_sched_execute() from inside the main loop, so it will never interrupt
+        //app_sched_event_put(). Also, updating of (i.e. writing to) the start index will be
+        //an atomic operation.
+        event_index         = m_queue_start_index;
+        m_queue_start_index = next_index(m_queue_start_index);
+
+        *pp_event_data     = &m_queue_event_data[event_index * m_queue_event_size];
+        *p_event_data_size = m_queue_event_headers[event_index].event_data_size;
+        *p_event_handler   = m_queue_event_headers[event_index].handler;
+
+        err_code = NRF_SUCCESS;
+    }
+
+    return err_code;
+}
+
+
+void app_sched_pause(void)
+{
+    CRITICAL_REGION_ENTER();
+
+    if (m_scheduler_paused_counter < UINT32_MAX)
+    {
+        m_scheduler_paused_counter++;
+    }
+    CRITICAL_REGION_EXIT();
+}
+
+
+void app_sched_resume(void)
+{
+    CRITICAL_REGION_ENTER();
+
+    if (m_scheduler_paused_counter > 0)
+    {
+        m_scheduler_paused_counter--;
+    }
+    CRITICAL_REGION_EXIT();
+}
+
+/**@brief Function for checking if scheduler is paused which means that should break processing
+ *        events.
+ *
+ * @return    Boolean value - true if scheduler is paused, false otherwise.
+ */
+static __INLINE bool is_app_sched_paused(void)
+{
+    return (m_scheduler_paused_counter > 0);
+}
+
+
+void app_sched_execute(void)
+{
+    void *                    p_event_data;
+    uint16_t                  event_data_size;
+    app_sched_event_handler_t event_handler;
+
+    //Get next event (if any), and execute handler
+    while ((!is_app_sched_paused()) &&
+           (app_sched_event_get(&p_event_data, &event_data_size, &event_handler) == NRF_SUCCESS))
+    {
+        event_handler(p_event_data, event_data_size);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sensorsim/sensorsim.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sensorsim/sensorsim.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sensorsim/sensorsim.c
new file mode 100644
index 0000000..e584666
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sensorsim/sensorsim.c
@@ -0,0 +1,73 @@
+/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+#include "sensorsim.h"
+
+
+void sensorsim_init(sensorsim_state_t     * p_state,
+                    const sensorsim_cfg_t * p_cfg)
+{
+    if (p_cfg->start_at_max)
+    {
+        p_state->current_val   = p_cfg->max;
+        p_state->is_increasing = false;
+    }
+    else
+    {
+        p_state->current_val   = p_cfg->min;
+        p_state->is_increasing = true;
+    }
+}
+
+
+uint32_t sensorsim_measure(sensorsim_state_t     * p_state,
+                           const sensorsim_cfg_t * p_cfg)
+{
+    if (p_state->is_increasing)
+    {
+        sensorsim_increment(p_state, p_cfg);
+    }
+    else
+    {
+        sensorsim_decrement(p_state, p_cfg);
+    }
+    return p_state->current_val;
+}
+
+void sensorsim_increment(sensorsim_state_t *     p_state,
+                         const sensorsim_cfg_t * p_cfg)
+{
+    if (p_cfg->max - p_state->current_val > p_cfg->incr)
+    {
+        p_state->current_val += p_cfg->incr;
+    }
+    else
+    {
+        p_state->current_val   = p_cfg->max;
+        p_state->is_increasing = false;
+    }
+}
+
+
+void sensorsim_decrement(sensorsim_state_t *     p_state,
+                         const sensorsim_cfg_t * p_cfg)
+{
+    if (p_state->current_val - p_cfg->min > p_cfg->incr)
+    {
+        p_state->current_val -= p_cfg->incr;
+    }
+    else
+    {
+        p_state->current_val   = p_cfg->min;
+        p_state->is_increasing = true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sensorsim/sensorsim.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sensorsim/sensorsim.h b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sensorsim/sensorsim.h
new file mode 100644
index 0000000..3aa278d
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sensorsim/sensorsim.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+/** @file
+ *
+ * @defgroup ble_sdk_lib_sensorsim Sensor Data Simulator
+ * @{
+ * @ingroup ble_sdk_lib
+ * @brief Functions for simulating sensor data.
+ *
+ * @details Currently only a triangular waveform simulator is implemented.
+ */
+
+#ifndef SENSORSIM_H__
+#define SENSORSIM_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/**@brief Triangular waveform sensor simulator configuration. */
+typedef struct
+{
+    uint32_t min;                       /**< Minimum simulated value. */
+    uint32_t max;                       /**< Maximum simulated value. */
+    uint32_t incr;                      /**< Increment between each measurement. */
+    bool     start_at_max;              /**< TRUE is measurement is to start at the maximum value, FALSE if it is to start at the minimum. */
+} sensorsim_cfg_t;
+
+/**@brief Triangular waveform sensor simulator state. */
+typedef struct
+{
+    uint32_t current_val;               /**< Current sensor value. */
+    bool     is_increasing;             /**< TRUE if the simulator is in increasing state, FALSE otherwise. */
+} sensorsim_state_t;
+
+/**@brief Function for initializing a triangular waveform sensor simulator.
+ *
+ * @param[out]  p_state  Current state of simulator.
+ * @param[in]   p_cfg    Simulator configuration.
+ */
+void sensorsim_init(sensorsim_state_t *     p_state, 
+                        const sensorsim_cfg_t * p_cfg);
+
+/**@brief Function for generating a simulated sensor measurement using a triangular waveform generator.
+ *
+ * @param[in,out]  p_state  Current state of simulator.
+ * @param[in]      p_cfg    Simulator configuration.
+ *
+ * @return         Simulator output.
+ */
+uint32_t sensorsim_measure(sensorsim_state_t *     p_state,
+                               const sensorsim_cfg_t * p_cfg);
+
+/**@brief Function for incrementing a simulated sensor measurement value.
+ *
+ * @param[in,out]  p_state  Current state of simulator.
+ * @param[in]      p_cfg    Simulator configuration.
+ *
+ * @return         Simulator output.
+ */
+void sensorsim_increment(sensorsim_state_t *     p_state,
+                         const sensorsim_cfg_t * p_cfg);
+
+/**@brief Function for decrementing a simulated sensor measurement value.
+ *
+ * @param[in,out]  p_state  Current state of simulator.
+ * @param[in]      p_cfg    Simulator configuration.
+ *
+ * @return         Simulator output.
+ */
+void sensorsim_decrement(sensorsim_state_t *     p_state,
+                         const sensorsim_cfg_t * p_cfg);
+
+#endif // SENSORSIM_H__
+
+/** @} */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sha256/sha256.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sha256/sha256.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sha256/sha256.c
new file mode 100644
index 0000000..79b4484
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sha256/sha256.c
@@ -0,0 +1,183 @@
+
+/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+
+#include <stdlib.h>
+#include "sha256.h"
+#include "sdk_errors.h"
+#include "sdk_common.h"
+
+
+#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
+#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
+
+#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
+#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
+#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
+#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
+#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
+
+
+static const uint32_t k[64] = {
+    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+};
+
+
+/**@brief Function for calculating the hash of a 64-byte section of data.
+ *
+ * @param[in,out] ctx   Hash instance.
+ * @param[in]     data  Aray with data to be hashed. Assumed to be 64 bytes long.
+ */
+void sha256_transform(sha256_context_t *ctx, const uint8_t * data)
+{
+    uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
+
+    for (i = 0, j = 0; i < 16; ++i, j += 4)
+        m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
+    for ( ; i < 64; ++i)
+        m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
+
+    a = ctx->state[0];
+    b = ctx->state[1];
+    c = ctx->state[2];
+    d = ctx->state[3];
+    e = ctx->state[4];
+    f = ctx->state[5];
+    g = ctx->state[6];
+    h = ctx->state[7];
+
+    for (i = 0; i < 64; ++i) {
+        t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
+        t2 = EP0(a) + MAJ(a,b,c);
+        h = g;
+        g = f;
+        f = e;
+        e = d + t1;
+        d = c;
+        c = b;
+        b = a;
+        a = t1 + t2;
+    }
+
+    ctx->state[0] += a;
+    ctx->state[1] += b;
+    ctx->state[2] += c;
+    ctx->state[3] += d;
+    ctx->state[4] += e;
+    ctx->state[5] += f;
+    ctx->state[6] += g;
+    ctx->state[7] += h;
+}
+
+
+ret_code_t sha256_init(sha256_context_t *ctx)
+{
+    VERIFY_PARAM_NOT_NULL(ctx);
+
+    ctx->datalen = 0;
+    ctx->bitlen = 0;
+    ctx->state[0] = 0x6a09e667;
+    ctx->state[1] = 0xbb67ae85;
+    ctx->state[2] = 0x3c6ef372;
+    ctx->state[3] = 0xa54ff53a;
+    ctx->state[4] = 0x510e527f;
+    ctx->state[5] = 0x9b05688c;
+    ctx->state[6] = 0x1f83d9ab;
+    ctx->state[7] = 0x5be0cd19;
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t sha256_update(sha256_context_t *ctx, const uint8_t * data, size_t len)
+{
+    VERIFY_PARAM_NOT_NULL(ctx);
+    if (((len > 0) && (data == NULL)))
+    {
+        return NRF_ERROR_NULL;
+    }
+
+    uint32_t i;
+
+    for (i = 0; i < len; ++i) {
+        ctx->data[ctx->datalen] = data[i];
+        ctx->datalen++;
+        if (ctx->datalen == 64) {
+            sha256_transform(ctx, ctx->data);
+            ctx->bitlen += 512;
+            ctx->datalen = 0;
+        }
+    }
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t sha256_final(sha256_context_t *ctx, uint8_t * hash)
+{
+    VERIFY_PARAM_NOT_NULL(ctx);
+    VERIFY_PARAM_NOT_NULL(hash);
+
+    uint32_t i;
+
+    i = ctx->datalen;
+
+    // Pad whatever data is left in the buffer.
+    if (ctx->datalen < 56) {
+        ctx->data[i++] = 0x80;
+        while (i < 56)
+            ctx->data[i++] = 0x00;
+    }
+    else {
+        ctx->data[i++] = 0x80;
+        while (i < 64)
+            ctx->data[i++] = 0x00;
+        sha256_transform(ctx, ctx->data);
+        memset(ctx->data, 0, 56);
+    }
+
+    // Append to the padding the total message's length in bits and transform.
+    ctx->bitlen += (uint64_t)ctx->datalen * 8;
+    ctx->data[63] = ctx->bitlen;
+    ctx->data[62] = ctx->bitlen >> 8;
+    ctx->data[61] = ctx->bitlen >> 16;
+    ctx->data[60] = ctx->bitlen >> 24;
+    ctx->data[59] = ctx->bitlen >> 32;
+    ctx->data[58] = ctx->bitlen >> 40;
+    ctx->data[57] = ctx->bitlen >> 48;
+    ctx->data[56] = ctx->bitlen >> 56;
+    sha256_transform(ctx, ctx->data);
+
+    // Since this implementation uses little endian uint8_t ordering and SHA uses big endian,
+    // reverse all the uint8_ts when copying the final state to the output hash.
+    for (i = 0; i < 4; ++i) {
+        hash[i]      = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
+        hash[i + 4]  = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
+        hash[i + 8]  = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
+        hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
+        hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
+        hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
+        hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
+        hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
+    }
+
+    return NRF_SUCCESS;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sha256/sha256.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sha256/sha256.h b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sha256/sha256.h
new file mode 100644
index 0000000..acea32b
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/libraries/sha256/sha256.h
@@ -0,0 +1,91 @@
+
+/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+/** @file
+ *
+ * @defgroup sha256 SHA-256 hash library
+ * @{
+ * @ingroup app_common
+ *
+ * @brief  This module calculates SHA-256 (SHA-2, FIPS-180) hashes.
+ *
+ * @details To use this module, first call @ref sha256_init on a @ref sha256_context_t instance. Then call @ref
+ *          sha256_update with the data to be hashed. This step can optionally be done with multiple
+ *          calls to @ref sha256_update, each with a section of the data (in the correct order).
+ *          After all data has been passed to @ref sha256_update, call @ref sha256_final to finalize
+ *          and extract the hash value.
+ *
+ *          This code is adapted from code by Brad Conte, retrieved from
+ *          https://github.com/B-Con/crypto-algorithms.
+ *
+ */
+
+#ifndef SHA256_H
+#define SHA256_H
+
+
+#include <stdint.h>
+#include "sdk_errors.h"
+
+
+/**@brief Current state of a hash operation.
+ */
+typedef struct {
+    uint8_t data[64];
+    uint32_t datalen;
+    uint64_t bitlen;
+    uint32_t state[8];
+} sha256_context_t;
+
+
+/**@brief Function for initializing a @ref sha256_context_t instance.
+ *
+ * @param[out] ctx  Context instance to be initialized.
+ *
+ * @retval NRF_SUCCESS     If the instance was successfully initialized.
+ * @retval NRF_ERROR_NULL  If the parameter was NULL.
+ */
+ret_code_t sha256_init(sha256_context_t *ctx);
+
+/**@brief Function for calculating the hash of an array of uint8_t data.
+ *
+ * @details This function can be called multiple times in sequence. This is equivalent to calling 
+ *          the function once on a concatenation of the data from the different calls.
+ *
+ * @param[in,out] ctx   Hash instance.
+ * @param[in]     data  Data to be hashed.
+ * @param[in]     len   Length of the data to be hashed.
+ *
+ * @retval NRF_SUCCESS     If the data was successfully hashed.
+ * @retval NRF_ERROR_NULL  If the ctx parameter was NULL or the data parameter was NULL,  while the len parameter was not zero.
+ */
+ret_code_t sha256_update(sha256_context_t *ctx, const uint8_t * data, const size_t len);
+
+/**@brief Function for extracting the hash value from a hash instance.
+ *
+ * @details This function should be called after all data to be hashed has been passed to the hash
+ *          instance (by one or more calls to @ref sha256_update).
+ *
+ * Do not call @ref sha256_update again after @ref sha256_final has been called.
+ *
+ * @param[in,out] ctx   Hash instance.
+ * @param[out]    hash  Array to hold the extracted hash value (assumed to be 32 bytes long).
+ *
+ * @retval NRF_SUCCESS     If the has value was successfully extracted.
+ * @retval NRF_ERROR_NULL  If a parameter was NULL.
+ */
+ret_code_t sha256_final(sha256_context_t *ctx, uint8_t * hash);
+
+#endif   // SHA256_H
+
+/** @} */