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:14:02 UTC

[33/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/drivers_nrf/pstorage/pstorage_nosd.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pstorage/pstorage_nosd.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pstorage/pstorage_nosd.c
new file mode 100644
index 0000000..dafa64e
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pstorage/pstorage_nosd.c
@@ -0,0 +1,525 @@
+/* Copyright (c)  2013 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 "pstorage.h"
+#include "nordic_common.h"
+#include "nrf_error.h"
+#include "ble_flash.h"
+#include "app_util.h"
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#define no_SUPPORT_MODULES_LARGER_THAN_PAGE
+
+/**
+ * @defgroup api_param_check API Parameters check macros.
+ *
+ * @details Macros that verify parameters passed to the module in the APIs. These macros
+ *          could be mapped to nothing in final versions of code to save execution and size.
+ *
+ * @{
+ */
+/**
+ * @brief Checks if API parameters are null. Mostly used for pointer parameters.
+ */
+#define NULL_PARAM_CHECK(PARAM)                                                                   \
+        if ((PARAM) == NULL)                                                                      \
+        {                                                                                         \
+            return NRF_ERROR_NULL;                                                                \
+        }
+
+/**@brief Verifies the module identifier supplied by the application is within permissible
+ *        range.
+ */
+#define MODULE_ID_RANGE_CHECK(ID)                                                                 \
+        if ((PSTORAGE_NUM_OF_PAGES <= ((ID)->module_id)) ||                                       \
+            (m_app_table[(ID)->module_id].cb == NULL))                                            \
+        {                                                                                         \
+            return NRF_ERROR_INVALID_PARAM;                                                       \
+        }
+
+/**@brief Verifies the block identifier supplied by the application is within the permissible
+ *        range.
+ */
+#define BLOCK_ID_RANGE_CHECK(ID)                                                                  \
+        if (                                                                                      \
+            (                                                                                     \
+             m_app_table[(ID)->module_id].base_id                                                 \
+             +                                                                                    \
+             (                                                                                    \
+              m_app_table[(ID)->module_id].block_count                                            \
+              *                                                                                   \
+              MODULE_BLOCK_SIZE(ID)                                                               \
+             )                                                                                    \
+            )                                                                                     \
+            <=                                                                                    \
+            ((ID)->block_id)                                                                      \
+           )                                                                                      \
+        {                                                                                         \
+            return NRF_ERROR_INVALID_PARAM;                                                       \
+        }
+
+
+/**@brief Verifies the block size requested by the application can be supported by the module. */
+#define BLOCK_SIZE_CHECK(X)                                                                       \
+        if (((X) > PSTORAGE_MAX_BLOCK_SIZE) || ((X) < PSTORAGE_MIN_BLOCK_SIZE))                   \
+        {                                                                                         \
+            return NRF_ERROR_INVALID_PARAM;                                                       \
+        }
+
+/**@brief Verifies block size requested by Application in registration API */
+#define BLOCK_COUNT_CHECK(COUNT, SIZE)                                                            \
+        if (((COUNT) == 0) || ((m_next_page_addr + ((COUNT) *(SIZE)) > PSTORAGE_DATA_END_ADDR)))  \
+        {                                                                                         \
+            return NRF_ERROR_INVALID_PARAM;                                                       \
+        }
+
+/**@brief Verifies size parameter provided by application in API. */
+#define SIZE_CHECK(ID, SIZE)                                                                      \
+        if(((SIZE) == 0) || ((SIZE) > MODULE_BLOCK_SIZE(ID)))                                     \
+        {                                                                                         \
+            return NRF_ERROR_INVALID_PARAM;                                                       \
+        }
+
+/**@brief Verifies offset parameter provided by application in API. */
+#define OFFSET_CHECK(ID, OFFSET, SIZE)                                                            \
+        if(((SIZE) + (OFFSET)) > MODULE_BLOCK_SIZE(ID))                                           \
+        {                                                                                         \
+            return NRF_ERROR_INVALID_PARAM;                                                       \
+        }
+
+/**@brief SET BASE by masking offset bits for a address within page */
+#define PAGE_BASE_ADDR(flash_address)  ((flash_address)&(~((uint32_t)PSTORAGE_FLASH_PAGE_SIZE-1)))
+
+/**@brief Verifies the total module size requested by the application can be supported by the module. */
+#define MODULE_SIZE_CHECK(X)                                                                      \
+        if ((X) > PSTORAGE_FLASH_PAGE_SIZE)                   									  \
+        {                                                                                         \
+            return NRF_ERROR_INVALID_PARAM;                                                       \
+        }
+
+/**@} */
+
+ /**@brief    Verify module's initialization status.
+ *
+ * @details   Verify module's initialization status. Returns NRF_ERROR_INVALID_STATE in case a
+ *            module API is called without initializing the module.
+ */
+#define VERIFY_MODULE_INITIALIZED()                                                               \
+        do                                                                                        \
+        {                                                                                         \
+            if (!m_module_initialized)                                                            \
+            {                                                                                     \
+                 return NRF_ERROR_INVALID_STATE;                                                  \
+            }                                                                                     \
+        } while(0)
+
+/**@brief Macro to fetch the block size registered for the module. */
+#define MODULE_BLOCK_SIZE(ID) (m_app_table[(ID)->module_id].block_size)
+
+/**@} */
+
+/**
+ * @brief   Application registration information.
+ *
+ * @details Abstracts application specific information that application needs to maintain to be able
+ *          to process requests from each one of them.
+ *
+ */
+typedef struct ps_module_table
+{
+    pstorage_ntf_cb_t      cb;             /**< Callback registered with the module to be notified of any error occurring in persistent memory management */
+    pstorage_block_t       base_id;        /**< Base block id assigned to the module */
+    uint16_t               block_size;     /**< Size of block for the module */
+    uint16_t               block_count;    /**< Number of block requested by application */
+    uint16_t               no_of_pages;    /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
+} pstorage_module_table_t;
+
+static pstorage_module_table_t m_app_table[PSTORAGE_NUM_OF_PAGES];        /**< Registered application information table. */
+
+static uint32_t m_next_app_instance;                                      /**< Points to the application module instance that can be allocated next */
+static uint32_t m_next_page_addr;                                         /**< Points to the flash address that can be allocated to a module next, this is needed as blocks of a module can span across flash pages. */
+
+static bool     m_module_initialized = false;                             /**< Flag for checking if module has been initialized. */
+
+
+/**
+ * @brief Routine to notify application of any errors.
+ *
+ * @param[in] result Result of event being notified.
+ */
+static __INLINE void app_notify(pstorage_handle_t    * p_handle,
+                                uint8_t              * p_addr,
+                                uint8_t                op_code,
+                                pstorage_size_t        size,
+                                uint32_t               result)
+{
+    pstorage_ntf_cb_t  ntf_cb;
+
+    ntf_cb = m_app_table[p_handle->module_id].cb;
+
+    // Indicate result to client.
+    // For PSTORAGE_CLEAR_OP_CODE no size is returned as the size field is used only internally
+    // for clients registering multiple pages.
+    ntf_cb(p_handle,
+           op_code,
+           result,
+           p_addr,
+           size);
+}
+
+
+uint32_t pstorage_init(void)
+{
+    m_next_app_instance  = 0;
+    m_next_page_addr     = PSTORAGE_DATA_START_ADDR;
+    m_module_initialized = true;
+    return NRF_SUCCESS;
+}
+
+
+uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
+                           pstorage_handle_t       * p_block_id)
+{
+
+
+    VERIFY_MODULE_INITIALIZED();
+    NULL_PARAM_CHECK(p_module_param);
+    NULL_PARAM_CHECK(p_block_id);
+    NULL_PARAM_CHECK(p_module_param->cb);
+    BLOCK_SIZE_CHECK(p_module_param->block_size);
+    BLOCK_COUNT_CHECK(p_module_param->block_count, p_module_param->block_size);
+
+#ifndef SUPPORT_MODULES_LARGER_THAN_PAGE
+    MODULE_SIZE_CHECK(((uint16_t)(p_module_param->block_size)*(p_module_param->block_count)));
+#endif
+
+
+    if (m_next_app_instance == PSTORAGE_NUM_OF_PAGES)
+    {
+        return NRF_ERROR_NO_MEM;
+    }
+
+    p_block_id->module_id                        = m_next_app_instance;
+    p_block_id->block_id                         = m_next_page_addr;
+
+    m_app_table[m_next_app_instance].base_id     = p_block_id->block_id;
+    m_app_table[m_next_app_instance].cb          = p_module_param->cb;
+    m_app_table[m_next_app_instance].block_size  = p_module_param->block_size;
+    m_app_table[m_next_app_instance].block_count = p_module_param->block_count;
+
+    // Calculate number of flash pages allocated for the device.
+
+
+#ifdef SUPPORT_MODULES_LARGER_THAN_PAGE
+    uint16_t page_count = 0;
+    uint32_t total_size;
+    total_size = p_module_param->block_size * p_module_param->block_count;
+    do
+    {
+        page_count++;
+
+        if (total_size > PSTORAGE_FLASH_PAGE_SIZE)
+        {
+            total_size -= PSTORAGE_FLASH_PAGE_SIZE;
+        }
+        else
+        {
+            total_size = 0;
+        }
+
+        m_next_page_addr += PSTORAGE_FLASH_PAGE_SIZE;
+
+    } while (total_size >= PSTORAGE_FLASH_PAGE_SIZE);
+    m_app_table[m_next_app_instance].no_of_pages = page_count;
+#else
+    m_app_table[m_next_app_instance].no_of_pages = 1;
+    m_next_page_addr += PSTORAGE_FLASH_PAGE_SIZE;
+#endif
+    m_next_app_instance++;
+
+    return NRF_SUCCESS;
+}
+
+
+uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
+                                       pstorage_size_t     block_num,
+                                       pstorage_handle_t * p_block_id)
+{
+    pstorage_handle_t temp_id;
+
+    VERIFY_MODULE_INITIALIZED();
+    NULL_PARAM_CHECK(p_base_id);
+    NULL_PARAM_CHECK(p_block_id);
+    MODULE_ID_RANGE_CHECK(p_base_id);
+
+    temp_id           = (*p_base_id);
+    temp_id.block_id += (block_num * MODULE_BLOCK_SIZE(p_base_id));
+
+    BLOCK_ID_RANGE_CHECK(&temp_id);
+
+    (*p_block_id) = temp_id;
+
+    return NRF_SUCCESS;
+}
+
+
+uint32_t pstorage_store(pstorage_handle_t * p_dest,
+                        uint8_t           * p_src,
+                        pstorage_size_t     size,
+                        pstorage_size_t     offset)
+{
+    VERIFY_MODULE_INITIALIZED();
+    NULL_PARAM_CHECK(p_src);
+    NULL_PARAM_CHECK(p_dest);
+    MODULE_ID_RANGE_CHECK(p_dest);
+    BLOCK_ID_RANGE_CHECK(p_dest);
+    SIZE_CHECK(p_dest, size);
+    OFFSET_CHECK(p_dest, offset, size);
+
+    // Verify word alignment.
+    if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset)))
+    {
+        return NRF_ERROR_INVALID_ADDR;
+    }
+
+    uint32_t storage_addr = p_dest->block_id + offset;
+
+    uint32_t retval = ble_flash_block_write((uint32_t *)storage_addr,
+                                            (uint32_t *)p_src,
+                                            (size /sizeof(uint32_t)));
+
+    app_notify(p_dest, p_src, PSTORAGE_STORE_OP_CODE, size, retval);
+    
+    return retval;
+}
+
+/** @brief Function for handling flash updates using swap page
+ *
+ * __________________________________________________
+ * |              Page1                            |
+ * |_______________________________________________|
+ * | head |    body (to be updated )        | tail |
+ * |______|_________________________________|______|
+ *
+ * ________________________________________________________________________________________
+ * |              Page1                            |             Page2                    |
+ * |_______________________________________________|______________________________________|
+ * | head           |          body (to be updated )         | tail                       |
+ * |________________|________________________________________|____________________________|
+ *
+ *
+ * ToDo:  pointers not uint32_t for addresses
+ *
+ */
+
+uint32_t pstorage_update(pstorage_handle_t * p_dest,
+                        uint8_t           * p_src,
+                        pstorage_size_t     size,
+                        pstorage_size_t     offset)
+{
+
+    VERIFY_MODULE_INITIALIZED();
+    NULL_PARAM_CHECK(p_src);
+    NULL_PARAM_CHECK(p_dest);
+    MODULE_ID_RANGE_CHECK(p_dest);
+    BLOCK_ID_RANGE_CHECK(p_dest);
+    SIZE_CHECK(p_dest, size);
+    OFFSET_CHECK(p_dest, offset, size);
+
+    uint32_t *p_swap_addr = (uint32_t *)PSTORAGE_SWAP_ADDR;
+    uint32_t *p_page_addr1 =  (uint32_t *) PAGE_BASE_ADDR(p_dest->block_id + offset);
+#ifdef SUPPORT_MODULES_LARGER_THAN_PAGE
+    uint32_t *p_page_addr2 =  (uint32_t *) PAGE_BASE_ADDR(p_dest->block_id + offset + size-1);
+#endif
+    // block may not be aligned with page, so head must include all trailing blocks
+    uint16_t head_word_count =  (uint32_t)((uint32_t *)p_dest->block_id - p_page_addr1) + (offset)/sizeof(uint32_t);
+    uint16_t body_word_count =  size/sizeof(uint32_t);
+    uint16_t tail_word_count;
+    uint32_t retval;
+
+    // Verify word alignment.
+    if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset)))
+    {
+        return NRF_ERROR_INVALID_ADDR;
+    }
+    // erase swap page
+    (void) ble_flash_page_erase(PSTORAGE_SWAP_ADDR / BLE_FLASH_PAGE_SIZE);
+#ifdef SUPPORT_MODULES_LARGER_THAN_PAGE
+    if (p_page_addr1 == p_page_addr2)
+    {
+#endif
+    	// tail is in the same page as head
+        tail_word_count = BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - head_word_count - body_word_count;
+    	// copy of the head
+        if (head_word_count)
+        {
+        	retval = ble_flash_block_write(p_swap_addr, p_page_addr1, head_word_count );
+        	if (retval != NRF_SUCCESS)
+        	{
+        		app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+        		return retval;
+        	}
+        }
+        // copy of the body
+        retval = ble_flash_block_write(p_swap_addr+head_word_count, (uint32_t *)p_src, body_word_count);
+        if (retval != NRF_SUCCESS)
+        {
+          app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+          return retval;
+        }
+        // copy of the tail
+        if (tail_word_count)
+        {
+        	retval = ble_flash_block_write(p_swap_addr+head_word_count+body_word_count, p_page_addr1+head_word_count+body_word_count, tail_word_count );
+        	if (retval != NRF_SUCCESS)
+        	{
+        		app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+        		return retval;
+        	}
+        }
+        // erase active page
+        (void) ble_flash_page_erase((uint32_t)p_page_addr1 / BLE_FLASH_PAGE_SIZE);
+        // restore updated page
+        retval = ble_flash_block_write(p_page_addr1, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t));
+#ifdef SUPPORT_MODULES_LARGER_THAN_PAGE
+    }
+    else
+    {
+    	// tail is in NOT in the same page as head - need to swap twice
+    	uint16_t body1_word_count =  BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - head_word_count;
+    	uint16_t body2_word_count =  body_word_count - body1_word_count;
+        tail_word_count = BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - body2_word_count;
+        // copy head
+        retval = ble_flash_block_write(p_swap_addr, p_page_addr1, head_word_count );
+    	if (retval != NRF_SUCCESS)
+    	{
+    		app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+    		return retval;
+    	}
+        // copy body1
+        retval = ble_flash_block_write(p_swap_addr, (uint32_t *)p_src, body1_word_count );
+    	if (retval != NRF_SUCCESS)
+    	{
+    		app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+    		return retval;
+    	}
+        // erase active page
+        (void) ble_flash_page_erase((uint32_t)p_page_addr1 / BLE_FLASH_PAGE_SIZE);
+        // restore updated page1
+        retval = ble_flash_block_write(p_page_addr1, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t));
+    	if (retval != NRF_SUCCESS)
+    	{
+    		app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+    		return retval;
+    	}
+        // erase swap page
+        (void) ble_flash_page_erase(PSTORAGE_SWAP_ADDR / BLE_FLASH_PAGE_SIZE);
+        // copy body2
+        retval = ble_flash_block_write(p_swap_addr, (uint32_t *)p_src + body1_word_count, body2_word_count );
+    	if (retval != NRF_SUCCESS)
+    	{
+    		app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+    		return retval;
+    	}
+        // copy tail
+        retval = ble_flash_block_write(p_swap_addr, p_page_addr2+body2_word_count, tail_word_count );
+    	if (retval != NRF_SUCCESS)
+    	{
+    		app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+    		return retval;
+    	}
+        // erase active page
+        (void) ble_flash_page_erase((uint32_t)p_page_addr2 / BLE_FLASH_PAGE_SIZE);
+        // restore updated page2
+        retval = ble_flash_block_write(p_page_addr2, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t));
+    	if (retval != NRF_SUCCESS)
+    	{
+    		app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+    		return retval;
+    	}
+    }
+#endif
+    app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval);
+    return retval;
+
+}
+
+uint32_t pstorage_load(uint8_t *           p_dest,
+                       pstorage_handle_t * p_src,
+                       pstorage_size_t     size,
+                       pstorage_size_t     offset)
+{
+    VERIFY_MODULE_INITIALIZED();
+    NULL_PARAM_CHECK(p_src);
+    NULL_PARAM_CHECK(p_dest);
+    MODULE_ID_RANGE_CHECK (p_src);
+    BLOCK_ID_RANGE_CHECK(p_src);
+    SIZE_CHECK(p_src,size);
+    OFFSET_CHECK(p_src,offset,size);
+
+    // Verify word alignment.
+    if ((!is_word_aligned(p_dest)) || (!is_word_aligned((void *)(uint32_t)offset)))
+    {
+        return NRF_ERROR_INVALID_ADDR;
+    }
+
+    memcpy(p_dest, (((uint8_t *)p_src->block_id) + offset), size);
+
+    app_notify(p_src, p_dest, PSTORAGE_LOAD_OP_CODE, size, NRF_SUCCESS);
+
+    return NRF_SUCCESS;
+}
+
+
+uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
+{
+    uint32_t page_addr;
+    uint32_t retval;
+    uint16_t page_count;
+
+    VERIFY_MODULE_INITIALIZED();
+    NULL_PARAM_CHECK(p_dest);
+    MODULE_ID_RANGE_CHECK(p_dest);
+
+    page_addr = p_dest->block_id / BLE_FLASH_PAGE_SIZE;
+
+    retval = NRF_SUCCESS;
+
+    for (page_count = 0; page_count < m_app_table[p_dest->module_id].no_of_pages; page_count++)
+    {
+        retval = ble_flash_page_erase(page_addr);
+        page_addr++;
+        if (retval != NRF_SUCCESS)
+        {
+            break;
+        }
+    }
+    app_notify(p_dest, NULL, PSTORAGE_CLEAR_OP_CODE, size, retval);
+    return retval;
+}
+
+void pstorage_sys_event_handler(uint32_t sys_evt)
+{
+
+}
+
+uint32_t pstorage_access_status_get(uint32_t * p_count)
+{
+    if (p_count)
+    {
+        *p_count = 0;
+    }
+    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/drivers_nrf/pstorage/pstorage_raw.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pstorage/pstorage_raw.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pstorage/pstorage_raw.c
new file mode 100644
index 0000000..ac12f7c
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pstorage/pstorage_raw.c
@@ -0,0 +1,471 @@
+/* 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 "pstorage.h"
+#include <stdlib.h>
+#include <stdint.h>
+#include "nordic_common.h"
+#include "nrf_error.h"
+#include "nrf_assert.h"
+#include "nrf.h"
+#include "nrf_soc.h"
+#include "app_util.h"
+
+/** @file
+ *
+ * @defgroup persistent_storage_raw Persistent Storage Interface - Raw Mode Implementation
+ * @{
+ * @ingroup persistent_storage
+ * @brief Persistent Storage Interface - Raw Mode Implementation.
+ *
+ * @details This file contains the source code for raw mode implementation of pstorage.
+ * It is intended for special use cases where flash size is critical or the application must have
+ * full control of the flash, such as DFU. The registration function in this implementation only
+ * allocates a module id for the queue but does not locate any flash pages for the registrant.
+ * This implementation provides no safety checking of addresses when clearing or storing data into
+ * flash. The application is responsible for handling flash addresses and care must therefore be 
+ * taken in application not to erase application area.
+ * This implementation does not support the @ref pstorage_update function.
+ */
+
+#define INVALID_OPCODE              0x00    /**< Invalid op code identifier. */
+
+#ifdef NRF51
+#define SOC_MAX_WRITE_SIZE          1024    /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API on the nRF51. */
+#elif NRF52
+#define SOC_MAX_WRITE_SIZE          4096    /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API on the nRF52. */
+#else
+#error No target defined
+#endif
+
+
+/**
+ * @brief Application registration information.
+ *
+ * @details Define application specific information that application needs to maintain to be able
+ *          to process requests from each one of them.
+ */
+typedef struct
+{
+    pstorage_ntf_cb_t cb;   /**< Callback registered with the module to be notified of result of flash access.  */
+} pstorage_module_table_t;
+
+
+/**
+ * @brief Defines command queue element.
+ *
+ * @details Defines command queue element. Each element encapsulates needed information to process
+ *          a flash access command.
+ */
+typedef struct
+{
+    uint8_t              op_code;       /**< Identifies flash access operation being queued. Element is free is op-code is INVALID_OPCODE */
+    pstorage_size_t      size;          /**< Identifies size in bytes requested for the operation. */
+    pstorage_size_t      offset;        /**< Offset requested by the application for access operation. */    
+    pstorage_handle_t    storage_addr;  /**< Address/Identifier for persistent memory. */
+    uint8_t            * p_data_addr;   /**< Address/Identifier for data memory. This is assumed to be resident memory. */    
+} cmd_queue_element_t;
+
+
+/**
+ * @brief Defines command queue, an element is free is op_code field is not invalid.
+ *
+ * @details Defines commands enqueued for flash access. At any point of time, this queue has one or
+ *          more flash access operation pending if the count field is not zero. When the queue is
+ *          not empty, the rp (read pointer) field points to the flash access command in progress
+ *          or to requested next. The queue implements a simple first in first out algorithm.
+ *          Data addresses are assumed to be resident.
+ */
+typedef struct
+{
+    uint8_t              rp;                              /**< Read pointer, pointing to flash access that is ongoing or to be requested next. */
+    uint8_t              count;                           /**< Number of elements in the queue.  */
+    bool                 flash_access;                    /**< Flag to ensure an flash event received is for an request issued by the module. */
+    cmd_queue_element_t  cmd[PSTORAGE_CMD_QUEUE_SIZE];    /**< Array to maintain flash access operation details */
+}cmd_queue_t;
+
+static cmd_queue_t             m_cmd_queue;                             /**< Flash operation request queue. */
+static pstorage_module_table_t m_app_table[PSTORAGE_NUM_OF_PAGES];      /**< Registered application information table. */
+static pstorage_size_t         m_next_app_instance;                     /**< Points to the application module instance that can be allocated next */
+static pstorage_size_t         m_round_val;                             /**< Round value for multiple round operations. For erase operations, the round value will contain current round counter which is identical to number of pages erased. For store operations, the round value contains current round of operation * SOC_MAX_WRITE_SIZE to ensure each store to the SoC Flash API is within the SoC limit. */
+
+/**
+ * @brief Function for processing of commands and issuing flash access request to the SoftDevice.
+ *
+ * @return The return value received from SoftDevice.
+ */
+static uint32_t cmd_process(void);
+
+
+/**
+ * @brief Function for notifying application of any errors.
+ *
+ * @param[in] result Result of event being notified.
+ * @param[in] p_elem Pointer to the element for which a notification should be given.
+ */
+static void app_notify(uint32_t result, cmd_queue_element_t * p_elem);
+
+
+/**
+ * @defgroup utility_functions Utility internal functions.
+ * @{
+ * @details Utility functions needed for interfacing with flash through SoC APIs.
+ * SoC APIs are non blocking and provide the result of flash access through an event.
+ *
+ * @note Only one flash access operation is permitted at a time by SoC. Hence a queue is
+ * maintained by this module.
+ */
+ 
+/**
+ * @brief Function for initializing a command queue element.
+ *
+ * @param[in] index Index identifying element to be initialized.
+ */
+static void cmd_queue_element_init(uint32_t index)
+{
+    // Internal function and checks on range of index can be avoided
+    m_cmd_queue.cmd[index].op_code                = INVALID_OPCODE;
+    m_cmd_queue.cmd[index].size                   = 0;
+    m_cmd_queue.cmd[index].storage_addr.module_id = PSTORAGE_NUM_OF_PAGES;
+    m_cmd_queue.cmd[index].storage_addr.block_id  = 0;
+    m_cmd_queue.cmd[index].p_data_addr            = NULL;
+    m_cmd_queue.cmd[index].offset                 = 0;
+}
+
+
+/**
+ * @brief Function for initializing the command queue.
+ */
+static void cmd_queue_init(void)
+{
+    uint32_t cmd_index;
+
+    m_round_val              = 0;
+    m_cmd_queue.rp           = 0;
+    m_cmd_queue.count        = 0;
+    m_cmd_queue.flash_access = false;
+
+    for(cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; cmd_index++)
+    {
+        cmd_queue_element_init(cmd_index);
+    }
+}
+
+
+/**
+ * @brief Function for enqueueing a flash access operation.
+ *
+ * @param[in] opcode         Operation code for the command to queue.
+ * @param[in] p_storage_addr Pointer to the destination address.
+ * @param[in] p_data_addr    Pointer to the source address containing the data.
+ * @param[in] size           Size of data clear or write.
+ * @param[in] offset         Offset to the address identified by the source data address.
+ *
+ * @retval NRF_SUCCESS      If the enqueueing succeeded.
+ * @retval NRF_ERROR_NO_MEM In case the queue is full.
+ * @return Any error returned by the SoftDevice flash API.
+ */
+static uint32_t cmd_queue_enqueue(uint8_t             opcode,
+                                  pstorage_handle_t * p_storage_addr,
+                                  uint8_t           * p_data_addr,
+                                  pstorage_size_t     size,
+                                  pstorage_size_t     offset)
+{
+    uint32_t retval;
+
+    if (m_cmd_queue.count != PSTORAGE_CMD_QUEUE_SIZE)
+    {
+        uint8_t write_index = m_cmd_queue.rp + m_cmd_queue.count;
+
+        if (write_index >= PSTORAGE_CMD_QUEUE_SIZE)
+        {
+            write_index -= PSTORAGE_CMD_QUEUE_SIZE;
+        }
+
+        m_cmd_queue.cmd[write_index].op_code      = opcode;
+        m_cmd_queue.cmd[write_index].p_data_addr  = p_data_addr;
+        m_cmd_queue.cmd[write_index].storage_addr = (*p_storage_addr);
+        m_cmd_queue.cmd[write_index].size         = size;
+        m_cmd_queue.cmd[write_index].offset       = offset;
+        retval                                    = NRF_SUCCESS;
+        if (m_cmd_queue.flash_access == false)
+        {
+            retval = cmd_process();
+            if (retval == NRF_ERROR_BUSY)
+            {
+                // In case of busy error code, it is possible to attempt to access flash.
+                retval = NRF_SUCCESS;
+            }
+        }
+        m_cmd_queue.count++;
+    }
+    else
+    {
+        retval = NRF_ERROR_NO_MEM;
+    }
+
+    return retval;
+}
+
+
+/**
+ * @brief Function for dequeueing a command element.
+ *
+ * @retval NRF_SUCCESS If the dequeueing succeeded and next command was processed.
+ * @return Any error returned by the SoftDevice flash API.
+ */
+static uint32_t cmd_queue_dequeue(void)
+{
+    uint32_t retval = NRF_SUCCESS;
+
+    // If any flash operation is enqueued, schedule
+    if ((m_cmd_queue.count > 0) && (m_cmd_queue.flash_access == false))
+    {
+        retval = cmd_process();
+        if (retval != NRF_SUCCESS)
+        {
+            // Flash could be accessed by other modules, hence a busy error is
+            // acceptable, but any other error needs to be indicated.
+            if (retval == NRF_ERROR_BUSY)
+            {
+                // In case of busy error code, it is possible to attempt to access flash.
+                retval = NRF_SUCCESS;
+            }
+        }
+    }
+    else
+    {
+        // No flash access request pending.
+    }
+
+    return retval;
+}
+
+
+/**
+ * @brief Function for notifying application of any errors.
+ *
+ * @param[in] result Result of event being notified.
+ * @param[in] p_elem Pointer to the element for which a notification should be given.
+ */
+static void app_notify(uint32_t result, cmd_queue_element_t * p_elem)
+{
+    pstorage_ntf_cb_t ntf_cb;
+    uint8_t           op_code = p_elem->op_code;
+    
+    ntf_cb = m_app_table[p_elem->storage_addr.module_id].cb;
+
+    // Indicate result to client.
+    ntf_cb(&p_elem->storage_addr,
+           op_code,
+           result,
+           p_elem->p_data_addr,
+           p_elem->size);
+}
+
+
+/**
+ * @brief Function for handling of system events from SoftDevice.
+ *
+ * @param[in] sys_evt System event received.
+ */
+void pstorage_sys_event_handler(uint32_t sys_evt)
+{
+    uint32_t retval = NRF_SUCCESS;
+
+    // The event shall only be processed if requested by this module.
+    if (m_cmd_queue.flash_access == true)
+    {
+        cmd_queue_element_t * p_cmd;
+        m_cmd_queue.flash_access = false;
+        switch (sys_evt)
+        {
+            case NRF_EVT_FLASH_OPERATION_SUCCESS:
+            {
+                p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
+                m_round_val++;
+            
+                bool command_finished = ((m_round_val * SOC_MAX_WRITE_SIZE) >= p_cmd->size);
+
+                if (command_finished)
+                {
+                    uint8_t queue_rp = m_cmd_queue.rp;
+                    
+                    m_round_val = 0;
+                    m_cmd_queue.count--;
+                    m_cmd_queue.rp++;
+
+                    if (m_cmd_queue.rp >= PSTORAGE_CMD_QUEUE_SIZE)
+                    {
+                        m_cmd_queue.rp -= PSTORAGE_CMD_QUEUE_SIZE;
+                    }
+
+                    app_notify(retval, &m_cmd_queue.cmd[queue_rp]);
+
+                    // Initialize/free the element as it is now processed.
+                    cmd_queue_element_init(queue_rp);
+                }
+                // Schedule any queued flash access operations.
+                retval = cmd_queue_dequeue();
+                if (retval != NRF_SUCCESS)
+                {
+                    app_notify(retval, &m_cmd_queue.cmd[m_cmd_queue.rp]);
+                }
+            }
+            break;
+                
+            case NRF_EVT_FLASH_OPERATION_ERROR:
+                app_notify(NRF_ERROR_TIMEOUT, &m_cmd_queue.cmd[m_cmd_queue.rp]);
+                break;
+            
+            default:
+                // No implementation needed.
+                break;
+        }
+    }
+}
+
+
+/**
+ * @brief Function for processing of commands and issuing flash access request to the SoftDevice.
+ *
+ * @return The return value received from SoftDevice.
+ */
+static uint32_t cmd_process(void)
+{
+    uint32_t              retval;
+    uint32_t              storage_addr;
+    cmd_queue_element_t * p_cmd;
+
+    retval = NRF_ERROR_FORBIDDEN;
+
+    p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
+
+    storage_addr = p_cmd->storage_addr.block_id;
+
+    switch (p_cmd->op_code)
+    {
+        case PSTORAGE_STORE_OP_CODE:
+        {
+            uint32_t  size;
+            uint32_t  offset;
+            uint8_t * p_data_addr = p_cmd->p_data_addr;
+
+            offset        = (m_round_val * SOC_MAX_WRITE_SIZE);
+            size          = p_cmd->size - offset;
+            p_data_addr  += offset;
+            storage_addr += (p_cmd->offset + offset);
+
+            if (size < SOC_MAX_WRITE_SIZE)
+            {
+                retval = sd_flash_write(((uint32_t *)storage_addr),
+                                        (uint32_t *)p_data_addr,
+                                        size / sizeof(uint32_t));
+            }
+            else
+            {
+                retval = sd_flash_write(((uint32_t *)storage_addr),
+                                        (uint32_t *)p_data_addr,
+                                        SOC_MAX_WRITE_SIZE / sizeof(uint32_t));
+            }
+        }
+        break;
+        
+        case PSTORAGE_CLEAR_OP_CODE:
+        {
+            uint32_t page_number;
+
+            page_number =  ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) +
+                            m_round_val);
+
+            retval = sd_flash_page_erase(page_number);
+        }
+        break;
+    
+        default:
+            // Should never reach here.
+            break;
+    }
+    
+    if (retval == NRF_SUCCESS)
+    {
+       m_cmd_queue.flash_access = true;
+    }
+
+    return retval;
+}
+/** @} */
+
+
+uint32_t pstorage_init(void)
+{
+    cmd_queue_init();
+    
+    m_next_app_instance = 0;
+    m_round_val         = 0;
+
+    for(unsigned int index = 0; index < PSTORAGE_NUM_OF_PAGES; index++)
+    {
+        m_app_table[index].cb          = NULL;
+    }
+
+    return NRF_SUCCESS;
+}
+
+
+uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
+                           pstorage_handle_t       * p_block_id)
+{
+    if (m_next_app_instance == PSTORAGE_NUM_OF_PAGES)
+    {
+        return NRF_ERROR_NO_MEM;
+    }
+
+    p_block_id->module_id                 = m_next_app_instance;
+    m_app_table[m_next_app_instance++].cb = p_module_param->cb;
+
+    return NRF_SUCCESS;
+}
+
+
+uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
+                                       pstorage_size_t     block_num,
+                                       pstorage_handle_t * p_block_id)
+{
+    return NRF_ERROR_NOT_SUPPORTED;
+}
+
+
+uint32_t pstorage_store(pstorage_handle_t * p_dest,
+                        uint8_t           * p_src,
+                        pstorage_size_t     size,
+                        pstorage_size_t     offset)
+{
+    // Verify word alignment.
+    if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
+    {
+        return NRF_ERROR_INVALID_ADDR;
+    }
+
+    return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
+}
+
+
+uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
+{
+    return cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , size, 0);
+}
+
+
+/**
+ * @}
+ */

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/drivers_nrf/pwm/nrf_drv_pwm.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pwm/nrf_drv_pwm.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pwm/nrf_drv_pwm.c
new file mode 100644
index 0000000..bfca607
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pwm/nrf_drv_pwm.c
@@ -0,0 +1,350 @@
+/* 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 <string.h>
+#include "nrf_drv_pwm.h"
+#include "nrf_drv_common.h"
+#include "nrf_gpio.h"
+#include "app_util_platform.h"
+
+#if (PWM_COUNT == 0)
+    #error "No PWM instances enabled in the driver configuration file."
+#endif
+
+
+// Control block - driver instance local data.
+typedef struct
+{
+    nrf_drv_pwm_handler_t    handler;
+    nrf_drv_state_t volatile state;
+} pwm_control_block_t;
+static pwm_control_block_t m_cb[PWM_COUNT];
+
+static nrf_drv_pwm_config_t const m_default_config[PWM_COUNT] = {
+#if PWM0_ENABLED
+    NRF_DRV_PWM_DEFAULT_CONFIG(0),
+#endif
+#if PWM1_ENABLED
+    NRF_DRV_PWM_DEFAULT_CONFIG(1),
+#endif
+#if PWM2_ENABLED
+    NRF_DRV_PWM_DEFAULT_CONFIG(2),
+#endif
+};
+
+
+static void configure_pins(nrf_drv_pwm_t const * const p_instance,
+                           nrf_drv_pwm_config_t const * p_config)
+{
+    uint32_t out_pins[NRF_PWM_CHANNEL_COUNT];
+    uint8_t i;
+
+    for (i = 0; i < NRF_PWM_CHANNEL_COUNT; ++i)
+    {
+        uint8_t output_pin = p_config->output_pins[i];
+        if (output_pin != NRF_DRV_PWM_PIN_NOT_USED)
+        {
+            bool inverted = output_pin &  NRF_DRV_PWM_PIN_INVERTED;
+            out_pins[i]   = output_pin & ~NRF_DRV_PWM_PIN_INVERTED;
+
+            if (inverted)
+            {
+                nrf_gpio_pin_set(out_pins[i]);
+            }
+            else
+            {
+                nrf_gpio_pin_clear(out_pins[i]);
+            }
+
+            nrf_gpio_cfg_output(out_pins[i]);
+        }
+        else
+        {
+            out_pins[i] = NRF_PWM_PIN_NOT_CONNECTED;
+        }
+    }
+
+    nrf_pwm_pins_set(p_instance->p_registers, out_pins);
+}
+
+
+ret_code_t nrf_drv_pwm_init(nrf_drv_pwm_t const * const p_instance,
+                            nrf_drv_pwm_config_t const * p_config,
+                            nrf_drv_pwm_handler_t        handler)
+{
+    pwm_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
+
+    if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+
+    if (p_config == NULL)
+    {
+        p_config = &m_default_config[p_instance->drv_inst_idx];
+    }
+
+    p_cb->handler = handler;
+
+    configure_pins(p_instance, p_config);
+
+    nrf_pwm_enable(p_instance->p_registers);
+    nrf_pwm_configure(p_instance->p_registers,
+        p_config->base_clock, p_config->count_mode, p_config->top_value);
+    nrf_pwm_decoder_set(p_instance->p_registers,
+        p_config->load_mode, p_config->step_mode);
+
+    nrf_pwm_shorts_set(p_instance->p_registers, 0);
+    nrf_pwm_int_set(p_instance->p_registers, 0);
+    nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_LOOPSDONE);
+    nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_SEQEND0);
+    nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_SEQEND1);
+    nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED);
+
+    if (p_cb->handler)
+    {
+        nrf_drv_common_irq_enable(nrf_drv_get_IRQn(p_instance->p_registers),
+            p_config->irq_priority);
+    }
+
+    p_cb->state = NRF_DRV_STATE_INITIALIZED;
+
+    return NRF_SUCCESS;
+}
+
+
+void nrf_drv_pwm_uninit(nrf_drv_pwm_t const * const p_instance)
+{
+    pwm_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
+    ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
+
+    nrf_drv_common_irq_disable(nrf_drv_get_IRQn(p_instance->p_registers));
+
+    nrf_pwm_disable(p_instance->p_registers);
+
+    p_cb->state = NRF_DRV_STATE_UNINITIALIZED;
+}
+
+
+static void start_playback(nrf_drv_pwm_t const * const p_instance,
+                           pwm_control_block_t * p_cb,
+                           uint8_t               flags,
+                           nrf_pwm_task_t        starting_task)
+{
+    p_cb->state = NRF_DRV_STATE_POWERED_ON;
+
+    if (p_cb->handler)
+    {
+        // The notification about finished playback is by default enabled, but
+        // this can be suppressed. The notification that the peripheral has been
+        // stopped is always enable.
+        uint32_t int_mask = NRF_PWM_INT_LOOPSDONE_MASK |
+                            NRF_PWM_INT_STOPPED_MASK;
+
+        if (flags & NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0)
+        {
+            int_mask |= NRF_PWM_INT_SEQEND0_MASK;
+        }
+        if (flags & NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1)
+        {
+            int_mask |= NRF_PWM_INT_SEQEND1_MASK;
+        }
+        if (flags & NRF_DRV_PWM_FLAG_NO_EVT_FINISHED)
+        {
+            int_mask &= ~NRF_PWM_INT_LOOPSDONE_MASK;
+        }
+
+        nrf_pwm_int_set(p_instance->p_registers, int_mask);
+    }
+
+    nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED);
+
+    nrf_pwm_task_trigger(p_instance->p_registers, starting_task);
+}
+
+
+void nrf_drv_pwm_simple_playback(nrf_drv_pwm_t const * const p_instance,
+                                 nrf_pwm_sequence_t const * p_sequence,
+                                 uint16_t                   playback_count,
+                                 uint32_t                   flags)
+{
+    pwm_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
+    ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
+    ASSERT(playback_count > 0);
+    ASSERT(nrf_drv_is_in_RAM(p_sequence->values.p_raw));
+
+    // To take advantage of the looping mechanism, we need to use both sequences
+    // (single sequence can be played back only once).
+    nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence);
+    nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence);
+    bool odd = (playback_count & 1);
+    nrf_pwm_loop_set(p_instance->p_registers, playback_count/2 + (odd ? 1 : 0));
+
+    uint32_t shorts_mask;
+    if (flags & NRF_DRV_PWM_FLAG_STOP)
+    {
+        shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;
+    }
+    else if (flags & NRF_DRV_PWM_FLAG_LOOP)
+    {
+        shorts_mask = odd ? NRF_PWM_SHORT_LOOPSDONE_SEQSTART1_MASK
+                          : NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
+    }
+    else
+    {
+        shorts_mask = 0;
+    }
+    nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask);
+
+    start_playback(p_instance, p_cb, flags, odd ? NRF_PWM_TASK_SEQSTART1
+                                                : NRF_PWM_TASK_SEQSTART0);
+}
+
+
+void nrf_drv_pwm_complex_playback(nrf_drv_pwm_t const * const p_instance,
+                                  nrf_pwm_sequence_t const * p_sequence_0,
+                                  nrf_pwm_sequence_t const * p_sequence_1,
+                                  uint16_t                   playback_count,
+                                  uint32_t                   flags)
+{
+    pwm_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
+    ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
+    ASSERT(playback_count > 0);
+    ASSERT(nrf_drv_is_in_RAM(p_sequence_0->values.p_raw));
+    ASSERT(nrf_drv_is_in_RAM(p_sequence_1->values.p_raw));
+
+    nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence_0);
+    nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence_1);
+    nrf_pwm_loop_set(p_instance->p_registers, playback_count);
+
+    uint32_t shorts_mask;
+    if (flags & NRF_DRV_PWM_FLAG_STOP)
+    {
+        shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;
+    }
+    else if (flags & NRF_DRV_PWM_FLAG_LOOP)
+    {
+        shorts_mask = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
+    }
+    else
+    {
+        shorts_mask = 0;
+    }
+    nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask);
+
+    start_playback(p_instance, p_cb, flags, NRF_PWM_TASK_SEQSTART0);
+}
+
+
+bool nrf_drv_pwm_stop(nrf_drv_pwm_t const * const p_instance,
+                      bool wait_until_stopped)
+{
+    ASSERT(m_cb[p_instance->drv_inst_idx].state != NRF_DRV_STATE_UNINITIALIZED);
+
+    if (nrf_drv_pwm_is_stopped(p_instance))
+    {
+        return true;
+    }
+
+    nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_STOP);
+
+    do {
+        if (nrf_drv_pwm_is_stopped(p_instance))
+        {
+            return true;
+        }
+    } while (wait_until_stopped);
+
+    return false;
+}
+
+
+bool nrf_drv_pwm_is_stopped(nrf_drv_pwm_t const * const p_instance)
+{
+    pwm_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
+    ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
+
+    // If the event handler is used (interrupts are enabled), the state will
+    // be changed in interrupt handler when the STOPPED event occurs.
+    if (p_cb->state != NRF_DRV_STATE_POWERED_ON)
+    {
+        return true;
+    }
+    // If interrupts are disabled, we must check the STOPPED event here.
+    if (nrf_pwm_event_check(p_instance->p_registers, NRF_PWM_EVENT_STOPPED))
+    {
+        p_cb->state = NRF_DRV_STATE_INITIALIZED;
+        return true;
+    }
+
+    return false;
+}
+
+
+static void irq_handler(NRF_PWM_Type * p_pwm, pwm_control_block_t * p_cb)
+{
+    ASSERT(p_cb->handler);
+
+    // The SEQEND0 and SEQEND1 events are only handled when the user asked for
+    // it (by setting proper flags when starting the playback).
+    if (nrf_pwm_int_enable_check(p_pwm, NRF_PWM_INT_SEQEND0_MASK) &&
+        nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_SEQEND0))
+    {
+        nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_SEQEND0);
+        p_cb->handler(NRF_DRV_PWM_EVT_END_SEQ0);
+    }
+    if (nrf_pwm_int_enable_check(p_pwm, NRF_PWM_INT_SEQEND1_MASK) &&
+        nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_SEQEND1))
+    {
+        nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_SEQEND1);
+        p_cb->handler(NRF_DRV_PWM_EVT_END_SEQ1);
+    }
+
+    // The LOOPSDONE event is handled by default, but this can be disabled.
+    if (nrf_pwm_int_enable_check(p_pwm, NRF_PWM_INT_LOOPSDONE_MASK) &&
+        nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_LOOPSDONE))
+    {
+        nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_LOOPSDONE);
+        p_cb->handler(NRF_DRV_PWM_EVT_FINISHED);
+    }
+
+    if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_STOPPED))
+    {
+        nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_STOPPED);
+
+        p_cb->state = NRF_DRV_STATE_INITIALIZED;
+
+        p_cb->handler(NRF_DRV_PWM_EVT_STOPPED);
+    }
+}
+
+
+#if PWM0_ENABLED
+void PWM0_IRQHandler(void)
+{
+    irq_handler(NRF_PWM0, &m_cb[PWM0_INSTANCE_INDEX]);
+}
+#endif
+
+#if PWM1_ENABLED
+void PWM1_IRQHandler(void)
+{
+    irq_handler(NRF_PWM1, &m_cb[PWM1_INSTANCE_INDEX]);
+}
+#endif
+
+#if PWM2_ENABLED
+void PWM2_IRQHandler(void)
+{
+    irq_handler(NRF_PWM2, &m_cb[PWM2_INSTANCE_INDEX]);
+}
+#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/drivers_nrf/pwm/nrf_drv_pwm.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pwm/nrf_drv_pwm.h b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pwm/nrf_drv_pwm.h
new file mode 100644
index 0000000..3794992
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/pwm/nrf_drv_pwm.h
@@ -0,0 +1,426 @@
+/* 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
+ * @addtogroup nrf_pwm PWM HAL and driver
+ * @ingroup    nrf_drivers
+ * @brief      @tagAPI52 Pulse Width Modulation (PWM) module APIs.
+ *
+ * @defgroup   nrf_drv_pwm PWM driver
+ * @{
+ * @ingroup    nrf_pwm
+ * @brief      @tagAPI52 Pulse Width Modulation (PWM) module driver.
+ */
+
+
+#ifndef NRF_DRV_PWM_H__
+#define NRF_DRV_PWM_H__
+
+#include "nordic_common.h"
+#include "nrf_drv_config.h"
+#include "nrf_pwm.h"
+#include "sdk_errors.h"
+
+
+/**
+ * @brief PWM driver instance data structure.
+ */
+typedef struct
+{
+    NRF_PWM_Type * p_registers;  ///< Pointer to the structure with PWM peripheral instance registers.
+    uint8_t        drv_inst_idx; ///< Driver instance index.
+} nrf_drv_pwm_t;
+
+/**
+ * @brief Macro for creating a PWM driver instance.
+ */
+#define NRF_DRV_PWM_INSTANCE(id)                        \
+{                                                       \
+    .p_registers  = CONCAT_2(NRF_PWM, id),              \
+    .drv_inst_idx = CONCAT_3(PWM, id, _INSTANCE_INDEX), \
+}
+
+
+/**
+ * @brief This value can be provided instead of a pin number for any channel
+ *        to specify that its output is not used and therefore does not need
+ *        to be connected to a pin.
+ */
+#define NRF_DRV_PWM_PIN_NOT_USED    0xFF
+
+/**
+ * @brief This value can be added to a pin number to inverse its polarity 
+ *        (set idle state = 1).
+ */
+#define NRF_DRV_PWM_PIN_INVERTED    0x80
+
+/**
+ * @brief PWM driver configuration structure.
+ */
+typedef struct
+{
+    uint8_t output_pins[NRF_PWM_CHANNEL_COUNT]; ///< Pin numbers for individual output channels (optional). 
+                                                /**< Use @ref NRF_DRV_PWM_PIN_NOT_USED
+                                                 *   if a given output channel is not needed. */
+    uint8_t            irq_priority; ///< Interrupt priority.
+    nrf_pwm_clk_t      base_clock;   ///< Base clock frequency.
+    nrf_pwm_mode_t     count_mode;   ///< Operating mode of the pulse generator counter.
+    uint16_t           top_value;    ///< Value up to which the pulse generator counter counts.
+    nrf_pwm_dec_load_t load_mode;    ///< Mode of loading sequence data from RAM.
+    nrf_pwm_dec_step_t step_mode;    ///< Mode of advancing the active sequence.
+} nrf_drv_pwm_config_t;
+
+/**
+ * @brief PWM driver default configuration.
+ */
+#define NRF_DRV_PWM_DEFAULT_CONFIG(id)                       \
+{                                                            \
+    .output_pins  = { CONCAT_3(PWM, id, _CONFIG_OUT0_PIN),   \
+                      CONCAT_3(PWM, id, _CONFIG_OUT1_PIN),   \
+                      CONCAT_3(PWM, id, _CONFIG_OUT2_PIN),   \
+                      CONCAT_3(PWM, id, _CONFIG_OUT3_PIN) }, \
+    .irq_priority = CONCAT_3(PWM, id, _CONFIG_IRQ_PRIORITY), \
+    .base_clock   = CONCAT_3(PWM, id, _CONFIG_BASE_CLOCK),   \
+    .count_mode   = CONCAT_3(PWM, id, _CONFIG_COUNT_MODE),   \
+    .top_value    = CONCAT_3(PWM, id, _CONFIG_TOP_VALUE),    \
+    .load_mode    = CONCAT_3(PWM, id, _CONFIG_LOAD_MODE),    \
+    .step_mode    = CONCAT_3(PWM, id, _CONFIG_STEP_MODE),    \
+}
+
+
+/**
+ * @brief PWM flags providing additional playback options.
+ */
+typedef enum
+{
+    NRF_DRV_PWM_FLAG_STOP = 0x01, /**< When the requested playback is finished,
+                                       the peripheral should be stopped.
+                                       @note The STOP task is triggered when
+                                       the last value of the final sequence is
+                                       loaded from RAM, and the peripheral stops
+                                       at the end of the current PWM period.
+                                       For sequences with configured repeating
+                                       of duty cycle values, this might result in
+                                       less than the requested number of repeats
+                                       of the last value. */
+    NRF_DRV_PWM_FLAG_LOOP = 0x02, /**< When the requested playback is finished,
+                                       it should be started from the beginning.
+                                       This flag is ignored if used together
+                                       with @ref NRF_DRV_PWM_FLAG_STOP. */
+    NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0 = 0x04, /**< The event handler should be
+                                                  called when the last value
+                                                  from sequence 0 is loaded. */
+    NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1 = 0x08, /**< The event handler should be
+                                                  called when the last value
+                                                  from sequence 1 is loaded. */
+    NRF_DRV_PWM_FLAG_NO_EVT_FINISHED = 0x10, /**< The playback finished event
+                                                  (enabled by default) should be
+                                                  suppressed. */
+} nrf_drv_pwm_flag_t;
+
+
+/**
+ * @brief PWM driver event type.
+ */
+typedef enum
+{
+    NRF_DRV_PWM_EVT_FINISHED, ///< Sequence playback finished.
+    NRF_DRV_PWM_EVT_END_SEQ0, /**< End of sequence 0 reached. Its data can be
+                                   safely modified now. */
+    NRF_DRV_PWM_EVT_END_SEQ1, /**< End of sequence 1 reached. Its data can be
+                                   safely modified now. */
+    NRF_DRV_PWM_EVT_STOPPED,  ///< The PWM peripheral has been stopped.
+} nrf_drv_pwm_evt_type_t;
+
+/**
+ * @brief PWM driver event handler type.
+ */
+typedef void (* nrf_drv_pwm_handler_t)(nrf_drv_pwm_evt_type_t event_type);
+
+
+/**
+ * @brief Function for initializing the PWM driver.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config   Pointer to the structure with initial configuration.
+ *                       If NULL, the default configuration is used.
+ * @param[in] handler    Event handler provided by the user. If NULL is passed
+ *                       instead, event notifications are not done and PWM
+ *                       interrupts are disabled.
+ *
+ * @retval NRF_SUCCESS             If initialization was successful.
+ * @retval NRF_ERROR_INVALID_STATE If the driver was already initialized.
+ */
+ret_code_t nrf_drv_pwm_init(nrf_drv_pwm_t const * const p_instance,
+                            nrf_drv_pwm_config_t const * p_config,
+                            nrf_drv_pwm_handler_t        handler);
+
+/**
+ * @brief Function for uninitializing the PWM driver.
+ *
+ * If any sequence playback is in progress, it is stopped immediately.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrf_drv_pwm_uninit(nrf_drv_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for starting a single sequence playback.
+ *
+ * To take advantage of the looping mechanism in the PWM peripheral, both
+ * sequences must be used (single sequence can be played back only once by
+ * the peripheral). Therefore, the provided sequence is internally set and
+ * played back as both sequence 0 and sequence 1. Consequently, if end of
+ * sequence notifications are required, events for both sequences should be
+ * used (that means that both the @ref NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0 flag
+ * and the @ref NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1 flag should be specified and
+ * the @ref NRF_DRV_PWM_EVT_END_SEQ0 event and the @ref NRF_DRV_PWM_EVT_END_SEQ1
+ * event should be handled in the same way).
+ *
+ * @note The array containing the duty cycle values for the specified sequence
+ *       must be in RAM and cannot be allocated on stack.
+ *       For detailed information, see @ref nrf_pwm_sequence_t.
+ *
+ * @param[in] p_instance     Pointer to the driver instance structure.
+ * @param[in] p_sequence     Sequence to be played back.
+ * @param[in] playback_count Number of playbacks to be performed (must not be 0).
+ * @param[in] flags          Additional options. Pass any combination of
+ *                           @ref nrf_drv_pwm_flag_t "playback flags", or 0
+ *                           for default settings.
+ */
+void nrf_drv_pwm_simple_playback(nrf_drv_pwm_t const * const p_instance,
+                                 nrf_pwm_sequence_t const * p_sequence,
+                                 uint16_t                   playback_count,
+                                 uint32_t                   flags);
+
+/**
+ * @brief Function for starting a two-sequence playback.
+ *
+ * @note The array containing the duty cycle values for the specified sequence
+ *       must be in RAM and cannot be allocated on stack.
+ *       For detailed information, see @ref nrf_pwm_sequence_t.
+ *
+ * @param[in] p_instance     Pointer to the driver instance structure.
+ * @param[in] p_sequence_0   First sequence to be played back.
+ * @param[in] p_sequence_1   Second sequence to be played back.
+ * @param[in] playback_count Number of playbacks to be performed (must not be 0).
+ * @param[in] flags          Additional options. Pass any combination of
+ *                           @ref nrf_drv_pwm_flag_t "playback flags", or 0
+ *                           for default settings.
+ */
+void nrf_drv_pwm_complex_playback(nrf_drv_pwm_t const * const p_instance,
+                                  nrf_pwm_sequence_t const * p_sequence_0,
+                                  nrf_pwm_sequence_t const * p_sequence_1,
+                                  uint16_t                   playback_count,
+                                  uint32_t                   flags);
+
+/**
+ * @brief Function for advancing the active sequence.
+ *
+ * This function only applies to @ref NRF_PWM_STEP_TRIGGERED mode.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+__STATIC_INLINE void nrf_drv_pwm_step(nrf_drv_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for stopping the sequence playback.
+ *
+ * The playback is stopped at the end of the current PWM period.
+ * This means that if the active sequence is configured to repeat each duty
+ * cycle value for a certain number of PWM periods, the last played value
+ * might appear on the output less times than requested.
+ *
+ * @note This function can be instructed to wait until the playback is stopped
+ *       (by setting @p wait_until_stopped to true). Note that, depending on
+ *       the length of the PMW period, this might take a significant amount of
+ *       time. Alternatively, the @ref nrf_drv_pwm_is_stopped function can be
+ *       used to poll the status, or the @ref NRF_DRV_PWM_EVT_STOPPED event can
+ *       be used to get the notification when the playback is stopped, provided
+ *       the event handler is defined.
+ *
+ * @param[in] p_instance         Pointer to the driver instance structure.
+ * @param[in] wait_until_stopped If true, the function will not return until
+ *                               the playback is stopped.
+ *
+ * @retval true  If the PWM peripheral is stopped.
+ * @retval false If the PWM peripheral is not stopped.
+ */
+bool nrf_drv_pwm_stop(nrf_drv_pwm_t const * const p_instance,
+                      bool wait_until_stopped);
+
+/**
+ * @brief Function for checking the status of the PWM peripheral.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @retval true  If the PWM peripheral is stopped.
+ * @retval false If the PWM peripheral is not stopped.
+ */
+bool nrf_drv_pwm_is_stopped(nrf_drv_pwm_t const * const p_instance);
+
+/**
+ * @brief Function for updating the sequence data during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id     Identifier of the sequence (0 or 1).
+ * @param[in] p_sequence Pointer to the new sequence definition.
+ */
+__STATIC_INLINE void nrf_drv_pwm_sequence_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t                    seq_id,
+                                        nrf_pwm_sequence_t const * p_sequence);
+
+/**
+ * @brief Function for updating the pointer to the duty cycle values
+ *        in the specified sequence during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id     Identifier of the sequence (0 or 1).
+ * @param[in] values     New pointer to the duty cycle values.
+ */
+__STATIC_INLINE void nrf_drv_pwm_sequence_values_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t          seq_id,
+                                        nrf_pwm_values_t values);
+
+/**
+ * @brief Function for updating the number of duty cycle values
+ *        in the specified sequence during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id     Identifier of the sequence (0 or 1).
+ * @param[in] length     New number of the duty cycle values.
+ */
+__STATIC_INLINE void nrf_drv_pwm_sequence_length_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t  seq_id,
+                                        uint16_t length);
+
+/**
+ * @brief Function for updating the number of repeats for duty cycle values
+ *        in specified sequence during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id     Identifier of the sequence (0 or 1).
+ * @param[in] repeats    New number of repeats.
+ */
+__STATIC_INLINE void nrf_drv_pwm_sequence_repeats_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t  seq_id,
+                                        uint32_t repeats);
+
+/**
+ * @brief Function for updating the additional delay after the specified
+ *        sequence during playback.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] seq_id     Identifier of the sequence (0 or 1).
+ * @param[in] end_delay  New end delay value (in PWM periods).
+ */
+__STATIC_INLINE void nrf_drv_pwm_sequence_end_delay_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t  seq_id,
+                                        uint32_t end_delay);
+
+/**
+ * @brief Function for returning the address of a specified PWM task that can
+ *        be used in PPI module.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] task       Requested task.
+ *
+ * @return Task address.
+ */
+__STATIC_INLINE uint32_t nrf_drv_pwm_task_address_get(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        nrf_pwm_task_t task);
+
+/**@brief Function for returning the address of a specified PWM event that can
+ *        be used in PPI module.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] event      Requested event.
+ *
+ * @return Event address.
+ */
+__STATIC_INLINE uint32_t nrf_drv_pwm_event_address_get(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        nrf_pwm_event_t event);
+
+
+#ifndef SUPPRESS_INLINE_IMPLEMENTATION
+
+__STATIC_INLINE void nrf_drv_pwm_step(nrf_drv_pwm_t const * const p_instance)
+{
+    nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_NEXTSTEP);
+}
+
+__STATIC_INLINE void nrf_drv_pwm_sequence_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t                    seq_id,
+                                        nrf_pwm_sequence_t const * p_sequence)
+{
+    nrf_pwm_sequence_set(p_instance->p_registers, seq_id, p_sequence);
+}
+
+__STATIC_INLINE void nrf_drv_pwm_sequence_values_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t          seq_id,
+                                        nrf_pwm_values_t values)
+{
+    nrf_pwm_seq_ptr_set(p_instance->p_registers, seq_id, values.p_raw);
+}
+
+__STATIC_INLINE void nrf_drv_pwm_sequence_length_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t  seq_id,
+                                        uint16_t length)
+{
+    nrf_pwm_seq_cnt_set(p_instance->p_registers, seq_id, length);
+}
+
+__STATIC_INLINE void nrf_drv_pwm_sequence_repeats_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t  seq_id,
+                                        uint32_t repeats)
+{
+    nrf_pwm_seq_refresh_set(p_instance->p_registers, seq_id, repeats);
+}
+
+__STATIC_INLINE void nrf_drv_pwm_sequence_end_delay_update(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        uint8_t  seq_id,
+                                        uint32_t end_delay)
+{
+    nrf_pwm_seq_end_delay_set(p_instance->p_registers, seq_id, end_delay);
+}
+
+__STATIC_INLINE uint32_t nrf_drv_pwm_task_address_get(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        nrf_pwm_task_t task)
+{
+    return nrf_pwm_task_address_get(p_instance->p_registers, task);
+}
+
+__STATIC_INLINE uint32_t nrf_drv_pwm_event_address_get(
+                                        nrf_drv_pwm_t const * const p_instance,
+                                        nrf_pwm_event_t event)
+{
+    return nrf_pwm_event_address_get(p_instance->p_registers, event);
+}
+
+#endif // SUPPRESS_INLINE_IMPLEMENTATION
+
+#endif // NRF_DRV_PWM_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/drivers_nrf/qdec/nrf_drv_qdec.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/qdec/nrf_drv_qdec.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/qdec/nrf_drv_qdec.c
new file mode 100644
index 0000000..aacc0ab
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/qdec/nrf_drv_qdec.c
@@ -0,0 +1,168 @@
+/* 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 <stdint.h>
+#include <stddef.h>
+
+#include "nrf.h"
+#include "nrf_gpio.h"
+#include "nrf_error.h"
+#include "nrf_assert.h"
+#include "nrf_drv_common.h"
+#include "nrf_drv_qdec.h"
+#include "app_util_platform.h"
+#include "nrf_assert.h"
+
+static qdec_event_handler_t m_qdec_event_handler = NULL;
+static const nrf_drv_qdec_config_t m_default_config = NRF_DRV_QDEC_DEFAULT_CONFIG;
+static nrf_drv_state_t m_state = NRF_DRV_STATE_UNINITIALIZED;
+
+void QDEC_IRQHandler(void)
+{
+    nrf_drv_qdec_event_t event;
+    if ( nrf_qdec_event_check(NRF_QDEC_EVENT_SAMPLERDY) &&
+         nrf_qdec_int_enable_check(NRF_QDEC_INT_SAMPLERDY_MASK) )
+    {
+        nrf_qdec_event_clear(NRF_QDEC_EVENT_SAMPLERDY);
+
+        event.type = NRF_QDEC_EVENT_SAMPLERDY;
+        event.data.sample.value = (int8_t)nrf_qdec_sample_get();
+        m_qdec_event_handler(event);
+    }
+
+    if ( nrf_qdec_event_check(NRF_QDEC_EVENT_REPORTRDY) &&
+         nrf_qdec_int_enable_check(NRF_QDEC_INT_REPORTRDY_MASK) )
+    {
+        nrf_qdec_event_clear(NRF_QDEC_EVENT_REPORTRDY);
+
+        event.type = NRF_QDEC_EVENT_REPORTRDY;
+
+        event.data.report.acc    = (int16_t)nrf_qdec_accread_get();
+        event.data.report.accdbl = (uint16_t)nrf_qdec_accdblread_get();
+        m_qdec_event_handler(event);
+    }
+
+    if ( nrf_qdec_event_check(NRF_QDEC_EVENT_ACCOF) &&
+         nrf_qdec_int_enable_check(NRF_QDEC_INT_ACCOF_MASK) )
+    {
+        nrf_qdec_event_clear(NRF_QDEC_EVENT_ACCOF);
+
+        event.type = NRF_QDEC_EVENT_ACCOF;
+        m_qdec_event_handler(event);
+    }
+}
+
+
+ret_code_t nrf_drv_qdec_init(const nrf_drv_qdec_config_t * p_config,
+                             qdec_event_handler_t event_handler)
+{
+    if (m_state != NRF_DRV_STATE_UNINITIALIZED)
+    {
+        return NRF_ERROR_INVALID_STATE; // qdec_event_handler has been already registered
+    }
+
+    if (p_config == NULL)
+    {
+        p_config = &m_default_config;
+    }
+
+    if (event_handler)
+    {
+        m_qdec_event_handler = event_handler;
+    }
+    else
+    {
+        return NRF_ERROR_INVALID_PARAM;
+    }
+
+    nrf_qdec_sampleper_set(p_config->sampleper);
+    nrf_gpio_cfg_input(p_config->pselled,NRF_GPIO_PIN_NOPULL);
+    nrf_gpio_cfg_input(p_config->psela, NRF_GPIO_PIN_NOPULL);
+    nrf_gpio_cfg_input(p_config->pselb, NRF_GPIO_PIN_NOPULL);
+    nrf_qdec_pio_assign( p_config->psela, p_config->pselb, p_config->pselled);
+    nrf_qdec_ledpre_set(p_config->ledpre);
+    nrf_qdec_ledpol_set(p_config->ledpol);
+    nrf_qdec_shorts_enable(NRF_QDEC_SHORT_REPORTRDY_READCLRACC_MASK);
+
+    if (p_config->dbfen)
+    {
+        nrf_qdec_dbfen_enable();
+    }
+    else
+    {
+        nrf_qdec_dbfen_disable();
+    }
+
+    uint32_t int_mask = NRF_QDEC_INT_ACCOF_MASK;
+
+    if (p_config->reportper != NRF_QDEC_REPORTPER_DISABLED)
+    {
+        nrf_qdec_reportper_set(p_config->reportper);
+        int_mask |= NRF_QDEC_INT_REPORTRDY_MASK;
+    }
+
+    if (p_config->sample_inten)
+    {
+        int_mask |= NRF_QDEC_INT_SAMPLERDY_MASK;
+    }
+
+    nrf_qdec_int_enable(int_mask);
+    nrf_drv_common_irq_enable(QDEC_IRQn, p_config->interrupt_priority);
+
+    m_state = NRF_DRV_STATE_INITIALIZED;
+
+    return NRF_SUCCESS;
+}
+
+void nrf_drv_qdec_uninit(void)
+{
+    ASSERT(m_state != NRF_DRV_STATE_UNINITIALIZED);
+    nrf_drv_qdec_disable();
+    nrf_drv_common_irq_disable(QDEC_IRQn);
+    m_state = NRF_DRV_STATE_UNINITIALIZED;
+}
+
+void nrf_drv_qdec_enable(void)
+{
+    ASSERT(m_state == NRF_DRV_STATE_INITIALIZED);
+    nrf_qdec_enable();
+    nrf_qdec_task_trigger(NRF_QDEC_TASK_START);
+    m_state = NRF_DRV_STATE_POWERED_ON;
+}
+
+void nrf_drv_qdec_disable(void)
+{
+    ASSERT(m_state == NRF_DRV_STATE_POWERED_ON);
+    nrf_qdec_disable();
+    nrf_qdec_task_trigger(NRF_QDEC_TASK_STOP);
+    m_state = NRF_DRV_STATE_INITIALIZED;
+}
+
+void nrf_drv_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl)
+{
+    ASSERT(m_state == NRF_DRV_STATE_POWERED_ON);
+    nrf_qdec_task_trigger(NRF_QDEC_TASK_READCLRACC);
+
+    *p_acc    = (int16_t)nrf_qdec_accread_get();
+    *p_accdbl = (int16_t)nrf_qdec_accdblread_get();
+}
+
+void nrf_drv_qdec_task_address_get(nrf_qdec_task_t task, uint32_t * p_task)
+{
+    *p_task = (uint32_t)nrf_qdec_task_address_get(task);
+}
+
+void nrf_drv_qdec_event_address_get(nrf_qdec_event_t event, uint32_t * p_event)
+{
+    *p_event = (uint32_t)nrf_qdec_event_address_get(event);
+}
+

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/drivers_nrf/qdec/nrf_drv_qdec.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/qdec/nrf_drv_qdec.h b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/qdec/nrf_drv_qdec.h
new file mode 100644
index 0000000..84dbf5d
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/qdec/nrf_drv_qdec.h
@@ -0,0 +1,149 @@
+/* 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.
+ *
+ */
+
+#ifndef NRF_DRV_QDEC_H__
+#define NRF_DRV_QDEC_H__
+
+#include "nrf_qdec.h"
+#include "nrf_drv_config.h"
+#include "sdk_errors.h"
+#include <stdbool.h>
+#include <stdint.h>
+
+/**
+ * @addtogroup nrf_qdec QDEC HAL and driver
+ * @ingroup nrf_drivers
+ * @brief Quadrature decoder (QDEC) APIs.
+ * @details The QDEC HAL provides basic APIs for accessing the registers of the QDEC. 
+ * The QDEC driver provides APIs on a higher level.
+ *
+ * @defgroup nrf_drivers_qdec QDEC driver
+ * @{
+ * @ingroup nrf_qdec
+ * @brief Quadrature decoder (QDEC) driver.
+ */
+
+/**@brief QDEC configuration structure.*/
+typedef struct
+{
+    nrf_qdec_reportper_t   reportper;          /**< Report period in samples. */
+    nrf_qdec_sampleper_t   sampleper;          /**< Sampling period in microseconds. */
+    uint32_t               psela;              /**< Pin number for A input. */
+    uint32_t               pselb;              /**< Pin number for B input. */
+    uint32_t               pselled;            /**< Pin number for LED output. */
+    uint32_t               ledpre;             /**< Time (in microseconds) how long LED is switched on before sampling. */
+    nrf_qdec_ledpol_t      ledpol;             /**< Active LED polarity. */
+    bool                   dbfen;              /**< State of debouncing filter. */
+    bool                   sample_inten;       /**< Enabling sample ready interrupt. */
+    uint8_t                interrupt_priority; /**< QDEC interrupt priority. */
+} nrf_drv_qdec_config_t;
+
+/**@brief QDEC default configuration. */
+#define NRF_DRV_QDEC_DEFAULT_CONFIG                     \
+    {                                                   \
+        .reportper          = QDEC_CONFIG_REPORTPER,    \
+        .sampleper          = QDEC_CONFIG_SAMPLEPER,    \
+        .psela              = QDEC_CONFIG_PIO_A,        \
+        .pselb              = QDEC_CONFIG_PIO_B,        \
+        .pselled            = QDEC_CONFIG_PIO_LED,      \
+        .ledpre             = QDEC_CONFIG_LEDPRE,       \
+        .ledpol             = QDEC_CONFIG_LEDPOL,       \
+        .interrupt_priority = QDEC_CONFIG_IRQ_PRIORITY, \
+        .dbfen              = QDEC_CONFIG_DBFEN,        \
+        .sample_inten       = QDEC_CONFIG_SAMPLE_INTEN  \
+    }
+
+/**@brief QDEC sample event data.*/
+typedef struct
+{
+    int8_t value; /**< Sample value. */
+} nrf_drv_qdec_sample_data_evt_t;
+
+/**@brief QDEC report event data.*/
+typedef struct
+{
+    int16_t acc;     /**< Accumulated transitions. */
+    uint16_t accdbl;  /**< Accumulated double transitions. */
+} nrf_drv_qdec_report_data_evt_t;
+
+/**@brief QDEC event handler structure. */
+typedef struct
+{
+    nrf_qdec_event_t  type;
+    union
+    {
+        nrf_drv_qdec_sample_data_evt_t sample; /**< Sample event data. */
+        nrf_drv_qdec_report_data_evt_t report; /**< Report event data. */
+    } data;
+} nrf_drv_qdec_event_t;
+
+/**@brief QDEC event handler.
+ * @param[in] event  QDEC event structure.
+ */
+typedef void (*qdec_event_handler_t)(nrf_drv_qdec_event_t event);
+
+/**@brief Function for initializing QDEC.
+ *
+ * @param[in] p_config            Pointer to configuration parameters.
+ * @param[in] event_handler  Event handler function.
+ *
+ * @retval NRF_SUCCESS If initialization was successful.
+ * @retval NRF_ERROR_INVALID_PARAM If invalid parameters were supplied.
+ * @retval NRF_ERROR_INVALID_STATE If QDEC was already initialized.
+ */
+ret_code_t nrf_drv_qdec_init(nrf_drv_qdec_config_t const * p_config,
+                             qdec_event_handler_t event_handler);
+
+/**@brief Function for uninitializing QDEC.
+ * @note  Function asserts if module is uninitialized.
+ */
+void nrf_drv_qdec_uninit(void);
+
+/**@brief Function for enabling QDEC.
+ * @note  Function asserts if module is uninitialized or enabled.
+ */
+void nrf_drv_qdec_enable(void);
+
+/**@brief Function for disabling QDEC.
+ * @note  Function asserts if module is uninitialized or disabled.
+ */
+void nrf_drv_qdec_disable(void);
+
+/**@brief Function for reading accumulated transitions QDEC.
+ * @note  Function asserts if module is not enabled.
+ * @note  Accumulators are cleared after reading.
+ *
+ * @param[out] p_acc      Pointer to store accumulated transitions.
+ * @param[out] p_accdbl   Pointer to store accumulated double transitions.
+ */
+void nrf_drv_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl);
+
+/**
+ * @brief Function for returning the address of a specific timer task.
+ *
+ * @param[in]  task       QDEC task.
+ * @param[out] p_task     Task address.
+ */
+void nrf_drv_qdec_task_address_get(nrf_qdec_task_t task, uint32_t * p_task);
+
+/**
+ * @brief Function for returning the address of a specific timer event.
+ *
+ * @param[in]  event       QDEC event.
+ * @param[out] p_event     Event address.
+ */
+void nrf_drv_qdec_event_address_get(nrf_qdec_event_t event, uint32_t * p_event);
+
+/**
+   *@}
+ **/
+#endif /* NRF_DRV_QDEC_H__ */