Example of BLE scan/connect/service discovery

Fork of BLE_LEDBlinker by Bluetooth Low Energy

Files at this revision

API Documentation at this revision

Comitter:
tsungta
Date:
Thu Apr 20 06:54:25 2017 +0000
Parent:
13:75f95a5cf9c1
Commit message:
Update mbed-os to support Delta DFCM-NNN50 platform

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-events/EventLoop.cpp Show diff for this revision Revisions of this file
mbed-events/EventLoop.h Show diff for this revision Revisions of this file
mbed-events/EventQueue.cpp Show diff for this revision Revisions of this file
mbed-events/EventQueue.h Show diff for this revision Revisions of this file
mbed-events/events-c/events.c Show diff for this revision Revisions of this file
mbed-events/events-c/events.h Show diff for this revision Revisions of this file
mbed-events/events-c/events_mbed.cpp Show diff for this revision Revisions of this file
mbed-events/events-c/events_mutex.h Show diff for this revision Revisions of this file
mbed-events/events-c/events_posix.c Show diff for this revision Revisions of this file
mbed-events/events-c/events_sema.h Show diff for this revision Revisions of this file
mbed-events/events-c/events_tick.h Show diff for this revision Revisions of this file
mbed-events/events.h Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b main.cpp
--- a/main.cpp	Fri Dec 09 10:10:14 2016 +0000
+++ b/main.cpp	Thu Apr 20 06:54:25 2017 +0000
@@ -21,12 +21,6 @@
 
 DigitalOut alivenessLED(LED1, 1);
 
-#if defined(TARGET_DELTA_DFCM_NNN40)
-Serial uart(p17, p16);//temp use for NNN50
-#else
-Serial uart(USBTX, USBRX);
-#endif
-
 bool                     triggerLedCharacteristic = false;
 DiscoveredCharacteristic ledCharacteristic;
 
@@ -40,7 +34,7 @@
     if (params->peerAddr[0] != 0xF9) { /* !ALERT! Alter this filter to suit your device. */
         return;
     }
-    uart.printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
+    printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
            params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
            params->rssi, params->isScanResponse, params->type);
 
@@ -48,43 +42,43 @@
 }
 
 void serviceDiscoveryCallback(const DiscoveredService *service) {
-    uart.printf("serviceDiscoveryCallback\n");
+    printf("serviceDiscoveryCallback\n");
     if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
-        uart.printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
+        printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
     } else {
-        uart.printf("S UUID-");
+        printf("S UUID-");
         const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
         for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
-            uart.printf("%02x", longUUIDBytes[i]);
+            printf("%02x", longUUIDBytes[i]);
         }
-        uart.printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
+        printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
     }
 }
 
 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
     if (characteristicP->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
-        uart.printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+        printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
         if (characteristicP->getUUID().getShortUUID() == 0x2a19) { /* !ALERT! Alter this filter to suit your device. */   
             ledCharacteristic        = *characteristicP;
             triggerLedCharacteristic = true;
         }
     }
     else {
-        uart.printf("  C UUID-");
+        printf("  C UUID-");
         const uint8_t *longUUIDBytes = characteristicP->getUUID().getBaseUUID();
         for (unsigned i = (UUID::LENGTH_OF_LONG_UUID) - 1; i < UUID::LENGTH_OF_LONG_UUID; i--) {
-            uart.printf("%02x ", longUUIDBytes[i]);
+            printf("%02x ", longUUIDBytes[i]);
         }
-        uart.printf(" valueAttr[%u] props[%x]\r\n", characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+        printf(" valueAttr[%u] props[%x]\r\n", characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
     }
 }
 
 void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
-    uart.printf("terminated SD for handle %u\r\n", connectionHandle);
+    printf("terminated SD for handle %u\r\n", connectionHandle);
 }
 
 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
-    uart.printf("connectionCallback\n");
+    printf("connectionCallback\n");
     if (params->role == Gap::CENTRAL) {
         BLE::Instance().gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
         BLE::Instance().gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback);
@@ -94,11 +88,11 @@
 void triggerToggledWrite(const GattReadCallbackParams *response) {
     if (response->handle == ledCharacteristic.getValueHandle()) {
 #if DUMP_READ_DATA
-        uart.printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
+        printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
         for (unsigned index = 0; index < response->len; index++) {
-            uart.printf("%c[%02x]", response->data[index], response->data[index]);
+            printf("%c[%02x]", response->data[index], response->data[index]);
         }
-        uart.printf("\r\n");
+        printf("\r\n");
 #endif
 
         uint8_t toggledValue = response->data[0] ^ 0x1;
@@ -113,7 +107,7 @@
 }
 
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) {
-    uart.printf("disconnected\r\n");
+    printf("disconnected\r\n");
 }
 
 /**
@@ -154,7 +148,7 @@
 }
 
 int main(void) {
-    uart.printf("APPLICATION START\r\n");
+    printf("APPLICATION START\r\n");
     ticker.attach(periodicCallback, 1);
 
     BLE &ble = BLE::Instance();
@@ -163,7 +157,7 @@
     /* SpinWait for initialization to complete. This is necessary because the
      * BLE object is used in the main loop below. */
     while (ble.hasInitialized()  == false) { /* spin loop */ }
-    uart.printf("init DONE\r\n");
+    printf("init DONE\r\n");
     while (true) {
         if (triggerLedCharacteristic && !ble.gattClient().isServiceDiscoveryActive()) {
             triggerLedCharacteristic = false;
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/EventLoop.cpp
--- a/mbed-events/EventLoop.cpp	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-#ifdef MBED_CONF_RTOS_PRESENT
-#include "EventLoop.h"
-
-#include "events.h"
-#include "rtos.h"
-#include "mbed.h"
-
-
-EventLoop::EventLoop(
-        osPriority priority,
-        unsigned event_size,
-        unsigned char *event_pointer,
-        uint32_t stack_size,
-        unsigned char *stack_pointer)
-    : EventQueue(event_size, event_pointer)
-    , _thread(priority, stack_size, stack_pointer)
-    , _running(false) {
-}
-
-EventLoop::~EventLoop() {
-    stop();
-}
-
-static void run(EventLoop *loop) {
-    loop->dispatch();
-}
-
-osStatus EventLoop::start() {
-    if (_running) {
-        return osOK;
-    }
-
-    osStatus status = _thread.start(this, run);
-    _running = (status == osOK);
-    return status;
-}
-
-osStatus EventLoop::stop() {
-    if (!_running) {
-        return osOK;
-    }
-
-    break_();
-    osStatus status = _thread.join();
-    _running = false;
-    return status;
-}
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/EventLoop.h
--- a/mbed-events/EventLoop.h	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/* events
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifdef MBED_CONF_RTOS_PRESENT
-#ifndef EVENT_LOOP_H
-#define EVENT_LOOP_H
-
-#include "EventQueue.h"
-#include "Thread.h"
-
-namespace events {
-
-
-/** EventLoop
- *  
- *  An event queue wrapped in a thread
- */
-class EventLoop : public EventQueue {
-public:
-    /** Create an event loop
-     *
-     *  @param priority         Initial priority of the thread
-     *                          (default: osPriorityNormal)
-     *  @param queue_size       Size of buffer to use for events
-     *                          (default: DEFAULT_QUEUE_SIZE)
-     *  @param queue_pointer    Pointer to memory region to use for events
-     *                          (default: NULL)
-     *  @param stack_size       Stack size (in bytes) requirements for the thread
-     *                          (default: DEFAULT_STACK_SIZE)
-     *  @param stack_pointer    Pointer to stack area to be used by the thread
-     *                          (default: NULL)
-     */
-    EventLoop(osPriority priority=osPriorityNormal,
-              unsigned event_size=DEFAULT_QUEUE_SIZE,
-              unsigned char *event_pointer=NULL,
-              uint32_t stack_size=DEFAULT_STACK_SIZE,
-              unsigned char *stack_pointer=NULL);
-
-    /** Clean up event loop
-     */
-    ~EventLoop();
-
-    /** Starts an event loop running in a dedicated thread
-     *  @return     status code that indicates the execution status of the function.
-     */
-    osStatus start();
-
-    /** Stops an event loop cleanly, waiting for any currently executing events
-     *  @return     status code that indicates the execution status of the function.
-     */
-    osStatus stop();
-
-private:
-    rtos::Thread _thread;
-    bool _running;
-};
-
-
-}
-
-#endif
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/EventQueue.cpp
--- a/mbed-events/EventQueue.cpp	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-#include "EventQueue.h"
-
-#include "events-c/events.h"
-#include "events.h"
-#include "mbed.h"
-
-
-EventQueue::EventQueue(unsigned event_size, unsigned char *event_pointer) {
-    if (!event_pointer) {
-        equeue_create(&_equeue, event_size);
-    } else {
-        equeue_create_inplace(&_equeue, event_size, event_pointer);
-    }
-}
-
-EventQueue::~EventQueue() {
-    equeue_destroy(&_equeue);
-}
-
-void EventQueue::dispatch(int ms) {
-    return equeue_dispatch(&_equeue, ms);
-}
-
-void EventQueue::break_() {
-    return equeue_break(&_equeue);
-}
-
-unsigned EventQueue::get_tick() {
-    return events_tick();
-}
-
-void EventQueue::cancel(int id) {
-    return event_cancel(&_equeue, id);
-}
-
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/EventQueue.h
--- a/mbed-events/EventQueue.h	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,294 +0,0 @@
-/* events
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef EVENT_QUEUE_H
-#define EVENT_QUEUE_H
-
-#include "events-c/events.h"
-#include "Callback.h"
-#include <cstddef>
-#include <new>
-
-namespace events {
-
-
-/** DEFAULT_QUEUE_SIZE
- *  default size of buffer for events
- */
-#define DEFAULT_QUEUE_SIZE \
-    (32*(sizeof(struct event) + sizeof(mbed::Callback<void()>)))
-
-
-/** EventQueue
- *
- *  Flexible event queue
- */
-class EventQueue {
-public:
-    /** Create an event queue
-     *
-     *  @param queue_size       Size of buffer to use for events
-     *                          (default: DEFAULT_QUEUE_SIZE)
-     *  @param queue_pointer    Pointer to memory region to use for events
-     *                          (default: NULL)
-     */
-    EventQueue(unsigned queue_size=DEFAULT_QUEUE_SIZE,
-               unsigned char *queue_pointer=NULL);
-
-    /** Destroy an event queue
-     */
-    ~EventQueue();
-
-    /** Dispatch pending events
-     *  @param ms   Time to wait for events in milliseconds, 0 will return
-     *              immediately if no events are pending, a negative
-     *              value will dispatch events forever
-     *              (default: -1)
-     */
-    void dispatch(int ms=-1);
-
-    /*  Monotonic counter for the event queue
-     *  @return     A monotonically incrementing counter in milliseconds
-     *              this count intentionally overflows to 0 after 2^32-1
-     */
-    unsigned get_tick();
-
-    /** Cancel events that are in flight
-     *
-     *  If event has already been dispatched or does not exist, no error occurs.
-     *
-     *  @param id   Event id to cancel
-     *  @note This can not stop a currently executing event
-     */
-    void cancel(int id);
-
-    /** Post an event to the queue
-     *
-     *  @param f        Function to call on event dispatch
-     *  @param a0..a4   Arguments to pass to the callback
-     *  @return         A positive id representing the event in the queue,
-     *                  or 0 on failure
-     */
-    template <typename F>
-    int post(F f) {
-        void *p = event_alloc(&_equeue, sizeof(F));
-        if (!p) {
-            return 0;
-        }
-
-        F *e = new (p) F(f);
-        event_dtor(e, &EventQueue::dtor<F>);
-        return event_post(&_equeue, &EventQueue::call<F>, e);
-    }
-
-    template <typename F, typename A0>
-    int post(F f, A0 a0) {
-        return post(Context1<F,A0>(f,a0));
-    }
-
-    template <typename F, typename A0, typename A1>
-    int post(F f, A0 a0, A1 a1) {
-        return post(Context2<F,A0,A1>(f,a0,a1));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2>
-    int post(F f, A0 a0, A1 a1, A2 a2) {
-        return post(Context3<F,A0,A1,A2>(f,a0,a1,a2));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2, typename A3>
-    int post(F f, A0 a0, A1 a1, A2 a2, A3 a3) {
-        return post(Context4<F,A0,A1,A2,A3>(f,a0,a1,a2,a3));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2, typename A3, typename A4>
-    int post(F f, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
-        return post(Context5<F,A0,A1,A2,A3,A4>(f,a0,a1,a2,a3,a4));
-    }
-
-    /** Post an event to the queue after a specified delay
-     *
-     *  @param f        Function to call on event dispatch
-     *  @param a0..a4   Arguments to pass to the callback
-     *  @param ms       Time to delay in milliseconds
-     *  @return         A positive id representing the event in the queue,
-     *                  or 0 on failure
-     */
-    template <typename F>
-    int post_in(int ms, F f) {
-        void *p = event_alloc(&_equeue, sizeof(F));
-        if (!p) {
-            return 0;
-        }
-
-        F *e = new (p) F(f);
-        event_delay(e, ms);
-        event_dtor(e, &EventQueue::dtor<F>);
-        return event_post(&_equeue, &EventQueue::call<F>, e);
-    }
-
-    template <typename F, typename A0>
-    int post_in(int ms, F f, A0 a0) {
-        return post_in(ms, Context1<F,A0>(f,a0));
-    }
-
-    template <typename F, typename A0, typename A1>
-    int post_in(int ms, F f, A0 a0, A1 a1) {
-        return post_in(ms, Context2<F,A0,A1>(f,a0,a1));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2>
-    int post_in(int ms, F f, A0 a0, A1 a1, A2 a2) {
-        return post_in(ms, Context3<F,A0,A1,A2>(f,a0,a1,a2));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2, typename A3>
-    int post_in(int ms, F f, A0 a0, A1 a1, A2 a2, A3 a3) {
-        return post_in(ms, Context4<F,A0,A1,A2,A3>(f,a0,a1,a2,a3));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2, typename A3, typename A4>
-    int post_in(int ms, F f, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
-        return post_in(ms, Context5<F,A0,A1,A2,A3,A4>(f,a0,a1,a2,a3,a4));
-    }
-
-    /** Post an event to the queue periodically
-     *
-     *  @param f        Function to call on event dispatch
-     *  @param a0..a4   Arguments to pass to the callback
-     *  @param ms       Period of the event in milliseconds
-     *  @return         A positive id representing the event in the queue,
-     *                  or 0 on failure
-     */
-    template <typename F>
-    int post_every(int ms, F f) {
-        void *p = event_alloc(&_equeue, sizeof(F));
-        if (!p) {
-            return 0;
-        }
-
-        F *e = new (p) F(f);
-        event_delay(e, ms);
-        event_period(e, ms);
-        event_dtor(e, &EventQueue::dtor<F>);
-        return event_post(&_equeue, &EventQueue::call<F>, e);
-    }
-
-    template <typename F, typename A0>
-    int post_every(int ms, F f, A0 a0) {
-        return post_every(ms, Context1<F,A0>(f,a0));
-    }
-
-    template <typename F, typename A0, typename A1>
-    int post_every(int ms, F f, A0 a0, A1 a1) {
-        return post_every(ms, Context2<F,A0,A1>(f,a0,a1));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2>
-    int post_every(int ms, F f, A0 a0, A1 a1, A2 a2) {
-        return post_every(ms, Context3<F,A0,A1,A2>(f,a0,a1,a2));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2, typename A3>
-    int post_every(int ms, F f, A0 a0, A1 a1, A2 a2, A3 a3) {
-        return post_every(ms, Context4<F,A0,A1,A2,A3>(f,a0,a1,a2,a3));
-    }
-
-    template <typename F, typename A0, typename A1, typename A2, typename A3, typename A4>
-    int post_every(int ms, F f, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
-        return post_every(ms, Context5<F,A0,A1,A2,A3,A4>(f,a0,a1,a2,a3,a4));
-    }
-
-protected:
-    void break_();
-
-    struct equeue _equeue;
-
-    template <typename F, typename A0, typename A1, typename A2, typename A3, typename A4>
-    struct Context5 {
-        F f; A0 a0; A1 a1; A2 a2; A3 a3; A4 a4;
-
-        Context5(F f, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4)
-            : f(f), a0(a0), a1(a1), a2(a2), a3(a3), a4(a4) {}
-
-        void operator()() {
-            f(a0, a1, a2, a3, a4);
-        }
-    };
-
-    template <typename F, typename A0, typename A1, typename A2, typename A3>
-    struct Context4 {
-        F f; A0 a0; A1 a1; A2 a2; A3 a3;
-
-        Context4(F f, A0 a0, A1 a1, A2 a2, A3 a3)
-            : f(f), a0(a0), a1(a1), a2(a2), a3(a3) {}
-
-        void operator()() {
-            f(a0, a1, a2, a3);
-        }
-    };
-
-    template <typename F, typename A0, typename A1, typename A2>
-    struct Context3 {
-        F f; A0 a0; A1 a1; A2 a2;
-
-        Context3(F f, A0 a0, A1 a1, A2 a2)
-            : f(f), a0(a0), a1(a1), a2(a2) {}
-
-        void operator()() {
-            f(a0, a1, a2);
-        }
-    };
-
-    template <typename F, typename A0, typename A1>
-    struct Context2 {
-        F f; A0 a0; A1 a1;
-
-        Context2(F f, A0 a0, A1 a1)
-            : f(f), a0(a0), a1(a1) {}
-
-        void operator()() {
-            f(a0, a1);
-        }
-    };
-
-    template <typename F, typename A0>
-    struct Context1 {
-        F f; A0 a0;
-
-        Context1(F f, A0 a0)
-            : f(f), a0(a0) {}
-
-        void operator()() {
-            f(a0);
-        }
-    };
-
-    template <typename T>
-    static void call(void *p) {
-        (*static_cast<T*>(p))();
-    }
-
-    template <typename T>
-    static void dtor(void *p) {
-        static_cast<T*>(p)->~T();
-    }
-};
-
-
-}
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/events-c/events.c
--- a/mbed-events/events-c/events.c	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,336 +0,0 @@
-#include "events.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-
-int equeue_create(equeue_t *q, unsigned size) {
-    void *buffer = malloc(size);
-    if (!buffer) {
-        return -1;
-    }
-
-    int err = equeue_create_inplace(q, size, buffer);
-    q->buffer = buffer;
-    return err;
-}
-
-int equeue_create_inplace(equeue_t *q, unsigned size, void *buffer) {
-    q->slab.size = size;
-    q->slab.data = buffer;
-    q->chunks = 0;
-    q->buffer = 0;
-
-    q->queue = 0;
-    q->next_id = 42;
-    q->break_ = (struct event){
-        .id = 0,
-        .period = -1,
-    };
-
-    int err;
-    err = events_sema_create(&q->eventsema);
-    if (err < 0) {
-        return err;
-    }
-
-    err = events_mutex_create(&q->queuelock);
-    if (err < 0) {
-        return err;
-    }
-
-    err = events_mutex_create(&q->freelock);
-    if (err < 0) {
-        return err;
-    }
-
-    return 0;
-}
-
-void equeue_destroy(equeue_t *q) {
-    while (q->queue) {
-        struct event *e = q->queue;
-        q->queue = e->next;
-        event_dealloc(q, e+1);
-    }
-
-    events_mutex_destroy(&q->freelock);
-    events_mutex_destroy(&q->queuelock);
-    events_sema_destroy(&q->eventsema);
-    free(q->buffer);
-}
-
-// equeue allocation functions
-static void *equeue_alloc(equeue_t *q, unsigned size) {
-    size = size + sizeof(unsigned);
-    size = (size + sizeof(unsigned)-1) & ~(sizeof(unsigned)-1);
-    if (size < sizeof(struct equeue_chunk)) {
-        size = sizeof(struct equeue_chunk);
-    }
-
-    events_mutex_lock(&q->freelock);
-
-    for (struct equeue_chunk **p = &q->chunks; *p; p = &(*p)->nchunk) {
-        if ((*p)->size >= size) {
-            struct equeue_chunk *c = *p;
-            if (c->next) {
-                *p = c->next;
-                (*p)->nchunk = c->nchunk;
-            } else {
-                *p = c->nchunk;
-            }
-            events_mutex_unlock(&q->freelock);
-            return (unsigned *)c + 1;
-        }
-    }
-
-    if (q->slab.size >= size) {
-        struct equeue_chunk *c = (struct equeue_chunk *)q->slab.data;
-        q->slab.data += size;
-        q->slab.size -= size;
-        c->size = size;
-        events_mutex_unlock(&q->freelock);
-        return (unsigned *)c + 1;
-    }
-
-    events_mutex_unlock(&q->freelock);
-    return 0;
-}
-
-static void equeue_dealloc(equeue_t *q, void *e) {
-    struct equeue_chunk *c = (struct equeue_chunk *)((unsigned *)e - 1);
-
-    events_mutex_lock(&q->freelock);
-
-    struct equeue_chunk **p = &q->chunks;
-    while (*p && (*p)->size < c->size) {
-        p = &(*p)->nchunk;
-    }
-
-    if (*p && (*p)->size == c->size) {
-        c->next = *p;
-        c->nchunk = (*p)->nchunk;
-    } else {
-        c->next = 0;
-        c->nchunk = *p;
-    }
-    *p = c;
-    
-    events_mutex_unlock(&q->freelock);
-}
-
-// event allocation functions
-static inline int event_next_id(equeue_t *q) {
-    int id = q->next_id++;
-    if (q->next_id < 0) {
-        q->next_id = 42;
-    }
-    return id;
-}
-
-void *event_alloc(equeue_t *q, unsigned size) {
-    struct event *e = equeue_alloc(q, sizeof(struct event) + size);
-    if (!e) {
-        return 0;
-    }
-
-    e->id = event_next_id(q);
-    e->target = 0;
-    e->period = -1;
-    e->dtor = 0;
-
-    return e + 1;
-}
-
-void event_dealloc(equeue_t *q, void *p) {
-    struct event *e = (struct event*)p - 1;
-
-    if (e->dtor) {
-        e->dtor(e+1);
-    }
-
-    equeue_dealloc(q, e);
-}
-
-// equeue scheduling functions
-static inline int equeue_tickdiff(unsigned a, unsigned b) {
-    return (int)(a - b);
-}
-
-static void equeue_enqueue(equeue_t *q, struct event *e, unsigned ms) {
-    e->target = events_tick() + ms;
-
-    struct event **p = &q->queue;
-    while (*p && equeue_tickdiff((*p)->target, e->target) <= 0) {
-        p = &(*p)->next;
-    }
-    
-    e->next = *p;
-    *p = e;
-}
-
-static struct event *equeue_dequeue(equeue_t *q, int id) {
-    for (struct event **p = &q->queue; *p; p = &(*p)->next) {
-        if ((*p)->id == id) {
-            struct event *e = *p;
-            *p = (*p)->next;
-            return e;
-        }
-    }
-
-    return 0;
-}
-
-static int equeue_post(equeue_t *q, struct event *e, int ms) {
-    int id = e->id;
-    if (ms < 0) {
-        event_dealloc(q, e+1);
-        return id;
-    }
-
-    events_mutex_lock(&q->queuelock);
-    equeue_enqueue(q, e, ms);
-    events_mutex_unlock(&q->queuelock);
-
-    events_sema_release(&q->eventsema);
-    return id;
-}
-
-static void equeue_cancel(equeue_t *q, int id) {
-    events_mutex_lock(&q->queuelock);
-    struct event *e = equeue_dequeue(q, id);
-    events_mutex_unlock(&q->queuelock);
-
-    if (e) {
-        event_dealloc(q, e+1);
-    }
-}
-
-void equeue_break(equeue_t *q) {
-    equeue_post(q, &q->break_, 0);
-}
-
-void equeue_dispatch(equeue_t *q, int ms) {
-    if (ms >= 0) {
-        equeue_post(q, &q->break_, ms);
-    }
-
-    while (1) {
-        int deadline = -1;
-
-        while (q->queue) {
-            deadline = -1;
-
-            events_mutex_lock(&q->queuelock);
-            if (!q->queue) {
-                events_mutex_unlock(&q->queuelock);
-                break;
-            }
-
-            deadline = equeue_tickdiff(q->queue->target, events_tick());
-            if (deadline > 0) {
-                events_mutex_unlock(&q->queuelock);
-                break;
-            }
-
-            struct event *e = q->queue;
-            q->queue = e->next;
-
-            if (e->period >= 0) {
-                // requeue periodic tasks to avoid race conditions
-                // in event_cancel
-                equeue_enqueue(q, e, e->period);
-            }
-            events_mutex_unlock(&q->queuelock);
-
-            if (e == &q->break_) {
-                return;
-            }
-
-            // actually dispatch the callback
-            e->cb(e + 1);
-
-            if (e->period < 0) {
-                event_dealloc(q, e+1);
-            }
-        }
-
-        events_sema_wait(&q->eventsema, deadline);
-    }
-}
-
-// event functions
-void event_delay(void *p, int ms) {
-    struct event *e = (struct event*)p - 1;
-    e->target = ms;
-}
-
-void event_period(void *p, int ms) {
-    struct event *e = (struct event*)p - 1;
-    e->period = ms;
-}
-
-void event_dtor(void *p, void (*dtor)(void *)) {
-    struct event *e = (struct event*)p - 1;
-    e->dtor = dtor;
-}
-
-// event operations
-int event_post(equeue_t *q, void (*cb)(void*), void *p) {
-    struct event *e = (struct event*)p - 1;
-    e->cb = cb;
-    int id = equeue_post(q, e, e->target);
-    return id;
-}
-
-void event_cancel(equeue_t *q, int id) {
-    equeue_cancel(q, id);
-}
-
-// simple callbacks 
-struct ecallback {
-    void (*cb)(void*);
-    void *data;
-};
-
-static void ecallback_dispatch(void *p) {
-    struct ecallback *e = (struct ecallback*)p;
-    e->cb(e->data);
-}
-
-int event_call(equeue_t *q, void (*cb)(void*), void *data) {
-    struct ecallback *e = event_alloc(q, sizeof(struct ecallback));
-    if (!e) {
-        return 0;
-    }
-
-    e->cb = cb;
-    e->data = data;
-    return event_post(q, ecallback_dispatch, e);
-}
-
-int event_call_in(equeue_t *q, int ms, void (*cb)(void*), void *data) {
-    struct ecallback *e = event_alloc(q, sizeof(struct ecallback));
-    if (!e) {
-        return 0;
-    }
-
-    event_delay(e, ms);
-    e->cb = cb;
-    e->data = data;
-    return event_post(q, ecallback_dispatch, e);
-}
-
-int event_call_every(equeue_t *q, int ms, void (*cb)(void*), void *data) {
-    struct ecallback *e = event_alloc(q, sizeof(struct ecallback));
-    if (!e) {
-        return 0;
-    }
-
-    event_delay(e, ms);
-    event_period(e, ms);
-    e->cb = cb;
-    e->data = data;
-    return event_post(q, ecallback_dispatch, e);
-}
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/events-c/events.h
--- a/mbed-events/events-c/events.h	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/* 
- * Flexible event queue for dispatching events
- */
-#ifndef EVENTS_H
-#define EVENTS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// System specific files
-#include "events_tick.h"
-#include "events_mutex.h"
-#include "events_sema.h"
-
-
-// Event/queue structures
-struct event {
-    struct event *next;
-    int id;
-    unsigned target;
-    int period;
-    void (*dtor)(void *);
-
-    void (*cb)(void *);
-    // data follows
-};
-
-typedef struct equeue {
-    struct event *queue;
-    int next_id;
-
-    void *buffer;
-    struct equeue_chunk {
-        unsigned size;
-        struct equeue_chunk *next;
-        struct equeue_chunk *nchunk;
-    } *chunks;
-    struct equeue_slab {
-        unsigned size;
-        unsigned char *data;
-    } slab;
-
-    struct event break_;
-
-    events_sema_t eventsema;
-    events_mutex_t queuelock;
-    events_mutex_t freelock;
-} equeue_t;
-
-// Queue operations
-//
-// Creation results in negative value on failure.
-int equeue_create(equeue_t *queue, unsigned size);
-int equeue_create_inplace(equeue_t *queue, unsigned size, void *buffer);
-void equeue_destroy(equeue_t *queue);
-
-// Dispatch events
-//
-// Executes any callbacks enqueued for the specified time in milliseconds,
-// or forever if ms is negative
-void equeue_dispatch(equeue_t *queue, int ms);
-
-// Break a running event loop
-//
-// Shuts down an unbounded event loop. Already pending events may finish
-// executing, but the queue will not continue looping indefinitely.
-void equeue_break(equeue_t *queue);
-
-// Simple event calls
-//
-// Passed callback will be executed in the associated equeue's
-// dispatch call with the data pointer passed unmodified
-//
-// event_call       - Immediately post an event to the queue
-// event_call_in    - Post an event after a specified time in milliseconds
-// event_call_every - Post an event periodically in milliseconds
-//
-// These calls will result in 0 if no memory is available, otherwise they
-// will result in a unique identifier that can be passed to event_cancel.
-int event_call(equeue_t *queue, void (*cb)(void *), void *data);
-int event_call_in(equeue_t *queue, int ms, void (*cb)(void *), void *data);
-int event_call_every(equeue_t *queue, int ms, void (*cb)(void *), void *data);
-
-// Events with queue handled blocks of memory
-//
-// Argument to event_post must point to a result of a event_alloc call
-// and the associated memory is automatically freed after the event
-// is dispatched.
-//
-// event_alloc will result in null if no memory is available
-// or the requested size is less than the size passed to equeue_create.
-void *event_alloc(equeue_t *queue, unsigned size);
-void event_dealloc(equeue_t *queue, void *event);
-
-// Configure an allocated event
-// 
-// event_delay  - Specify a millisecond delay before posting an event
-// event_period - Specify a millisecond period to repeatedly post an event
-// event_dtor   - Specify a destructor to run before the memory is deallocated
-void event_delay(void *event, int ms);
-void event_period(void *event, int ms);
-void event_dtor(void *event, void (*dtor)(void *));
-
-// Post an allocted event to the event queue
-//
-// Argument to event_post must point to a result of a event_alloc call
-// and the associated memory is automatically freed after the event
-// is dispatched.
-//
-// This call results in an unique identifier that can be passed to
-// event_cancel.
-int event_post(equeue_t *queue, void (*cb)(void *), void *event);
-
-// Cancel events that are in flight
-//
-// Every event_call function returns a non-negative identifier on success
-// that can be used to cancel an in-flight event. If the event has already
-// been dispatched or does not exist, no error occurs. Note, this can not
-// stop a currently executing event
-void event_cancel(equeue_t *queue, int event);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/events-c/events_mbed.cpp
--- a/mbed-events/events-c/events_mbed.cpp	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-#if defined(__MBED__)
-
-#include "events_tick.h"
-#include "events_sema.h"
-#include "events_mutex.h"
-
-#include <stdbool.h>
-#include "mbed.h"
-#ifdef MBED_CONF_RTOS_PRESENT
-#include "rtos.h"
-#endif
-
-
-// Ticker operations
-static class GlobalTicker {
-public:
-    GlobalTicker() {
-        _tick = 0;
-        _timer.start();
-        _ticker.attach_us(this, &GlobalTicker::step, (1 << 16) * 1000);
-    };
-
-    void step() {
-        _timer.reset();
-        _tick += 1 << 16;
-    }
-
-    unsigned tick() {
-        return _tick + (unsigned)_timer.read_ms();
-    }
-
-private:
-    unsigned _tick;
-    Timer _timer;
-    Ticker _ticker;
-} gticker;
-
-unsigned events_tick() {
-    return gticker.tick();
-}
-
-
-// Mutex operations
-int events_mutex_create(events_mutex_t *m) { return 0; }
-void events_mutex_destroy(events_mutex_t *m) { }
-
-void events_mutex_lock(events_mutex_t *m) {
-    *m = __get_PRIMASK();
-    __disable_irq();
-}
-
-void events_mutex_unlock(events_mutex_t *m) {
-    __set_PRIMASK(*m);
-}
-
-
-// Semaphore operations
-#ifdef MBED_CONF_RTOS_PRESENT
-
-static inline Semaphore *sema(events_sema_t *s) {
-    return static_cast<Semaphore*>(*s);
-}
-
-int events_sema_create(events_sema_t *s) {
-    *s = new Semaphore(0);
-    return sema(s) ? 0 : -1;
-}
-
-void events_sema_destroy(events_sema_t *s) {
-    delete sema(s);
-}
-
-void events_sema_release(events_sema_t *s) {
-    sema(s)->release();
-}
-
-bool events_sema_wait(events_sema_t *s, int ms) {
-    int t = sema(s)->wait(ms < 0 ? osWaitForever : ms);
-    return t > 0;
-}
-
-#else
-
-// Semaphore operations
-int events_sema_create(events_sema_t *s) { return 0; }
-void events_sema_destroy(events_sema_t *s) {}
-void events_sema_release(events_sema_t *s) {}
-
-static void events_sema_wakeup() {}
-
-bool events_sema_wait(events_sema_t *s, int ms) {
-    Timeout timeout;
-    timeout.attach_us(events_sema_wakeup, ms*1000);
-
-    __WFI();
-
-    return true;
-}
-
-#endif
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/events-c/events_mutex.h
--- a/mbed-events/events-c/events_mutex.h	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/* 
- * System specific mutex implementation
- */
-#ifndef EVENTS_MUTEX_H
-#define EVENTS_MUTEX_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-// Mutex type
-//
-// If this type is safe in interrupt contexts, then
-// the associated event queue will also be safe in
-// interrupt contexts.
-#if defined(__unix__)
-#include <pthread.h>
-typedef pthread_mutex_t events_mutex_t;
-#elif defined(__MBED__)
-typedef unsigned events_mutex_t;
-#endif
-
-
-// Mutex operations
-int events_mutex_create(events_mutex_t *mutex);
-void events_mutex_destroy(events_mutex_t *mutex);
-void events_mutex_lock(events_mutex_t *mutex);
-void events_mutex_unlock(events_mutex_t *mutex);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/events-c/events_posix.c
--- a/mbed-events/events-c/events_posix.c	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-#if defined(__unix__)
-
-#include "events_tick.h"
-#include "events_sema.h"
-#include "events_mutex.h"
-
-#include <time.h>
-
-
-// Tick operations
-#ifdef _POSIX_TIMERS
-
-unsigned events_tick(void) {
-    struct timespec ts;
-    clock_gettime(CLOCK_MONOTONIC, &ts);
-    return (unsigned)(ts.tv_sec*1000 + ts.tv_nsec/1000000);
-}
-
-#else
-#include <sys/time.h>
-
-unsigned events_tick(void) {
-    struct timeval tv;
-    gettimeofday(&tv, 0);
-    return (unsigned)(tv.tv_sec*1000 + tv.tv_usec/1000);
-}
-
-#endif
-
-
-// Mutex operations
-int events_mutex_create(events_mutex_t *m) {
-    return pthread_mutex_init(m, 0);
-}
-
-void events_mutex_destroy(events_mutex_t *m) {
-    pthread_mutex_destroy(m);
-}
-
-void events_mutex_lock(events_mutex_t *m) {
-    pthread_mutex_lock(m);
-}
-
-void events_mutex_unlock(events_mutex_t *m) {
-    pthread_mutex_unlock(m);
-}
-
-
-int events_sema_create(events_sema_t *s) {
-    int err = pthread_mutex_init(&s->mutex, 0);
-    if (err) {
-        return err;
-    }
-
-    err = pthread_cond_init(&s->cond, 0);
-    if (err) {
-        return err;
-    }
-
-    return 0;
-}
-
-void events_sema_destroy(events_sema_t *s) {
-    pthread_mutex_destroy(&s->mutex);
-    pthread_cond_destroy(&s->cond);
-}
-
-void events_sema_release(events_sema_t *s) {
-    pthread_cond_signal(&s->cond);
-}
-
-bool events_sema_wait(events_sema_t *s, int ms) {
-    int err;
-    pthread_mutex_lock(&s->mutex);
-
-    if (ms < 0) {
-        err = pthread_cond_wait(&s->cond, &s->mutex);
-    } else {
-        ms += events_tick();
-        struct timespec ts = {
-            .tv_sec = ms/1000,
-            .tv_nsec = ms*1000000,
-        };
-        err = pthread_cond_timedwait(&s->cond, &s->mutex, &ts);
-    }
-
-    pthread_mutex_unlock(&s->mutex);
-    return !err;
-}
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/events-c/events_sema.h
--- a/mbed-events/events-c/events_sema.h	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/* 
- * System specific semaphore implementation
- */
-#ifndef EVENTS_SEMA_H
-#define EVENTS_SEMA_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdbool.h>
-
-
-// Semaphore type
-//
-// Optimal implementation is a binary semaphore,
-// however a regular semaphore is sufficient.
-#if defined(__unix__)
-#include <pthread.h>
-typedef struct {
-    pthread_mutex_t mutex;
-    pthread_cond_t cond;
-} events_sema_t;
-#elif defined(__MBED__)
-#ifdef MBED_CONF_RTOS_PRESENT
-typedef void *events_sema_t;
-#else
-typedef struct {} events_sema_t;
-#endif
-#endif
-
-
-// Semaphore operations
-int events_sema_create(events_sema_t *sema);
-void events_sema_destroy(events_sema_t *sema);
-void events_sema_release(events_sema_t *sema);
-bool events_sema_wait(events_sema_t *sema, int ms);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/events-c/events_tick.h
--- a/mbed-events/events-c/events_tick.h	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-/* 
- * System specific tick implementation
- */
-#ifndef EVENTS_TICK_H
-#define EVENTS_TICK_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-// Monotonic tick
-//
-// Returns a tick that is incremented every millisecond,
-// must intentionally overflow to 0 after 2^32-1
-unsigned events_tick(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-events/events.h
--- a/mbed-events/events.h	Fri Dec 09 10:10:14 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/* events
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef EVENTS_CPP_H
-#define EVENTS_CPP_H
-
-#include "EventQueue.h"
-#include "EventLoop.h"
-
-using namespace events;
-
-#endif
-
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed-os.lib
--- a/mbed-os.lib	Fri Dec 09 10:10:14 2016 +0000
+++ b/mbed-os.lib	Thu Apr 20 06:54:25 2017 +0000
@@ -1,1 +1,1 @@
-https://github.com/ARMmbed/mbed-os/#a6f3fd1a60d5df59246d7caf3f108c4d34e1808e
+https://github.com/ARMmbed/mbed-os/#50b3418e45484ebf442b88cd935a2d5355402d7d
diff -r 75f95a5cf9c1 -r 92bb9a8ccd0b mbed_app.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json	Thu Apr 20 06:54:25 2017 +0000
@@ -0,0 +1,17 @@
+{
+    "config": {
+        "lf_clock_rc_calib_timer_interval": {
+            "value": 16,
+            "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL"
+        },
+        "lf_clock_rc_calib_mode_config": {
+            "value": 0,
+            "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG"
+        },
+        "uart_hwfc": {
+            "help": "Value: 1 for enable, 0 for disable",
+            "value": 0,
+            "macro_name": "MBED_CONF_NORDIC_UART_HWFC"
+        }        
+    }
+}
\ No newline at end of file