Erste version der Software für der Prototyp

Files at this revision

API Documentation at this revision

Comitter:
borlanic
Date:
Fri Mar 30 14:07:05 2018 +0000
Parent:
3:27100cbaaa6e
Commit message:
commentar

Changed in this revision

Controller.cpp Show annotated file 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-os/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h Show diff for this revision Revisions of this file
mbed-os/features/FEATURE_BLE/ble/pal/SecurityDb.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/TESTS/filesystem/util_block_device/main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/BlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ChainingBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ChainingBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ExhaustibleBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ExhaustibleBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/HeapBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/HeapBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/MBRBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/MBRBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ObservingBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ObservingBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ProfilingBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ProfilingBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ReadOnlyBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/ReadOnlyBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/SlicingBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os/features/filesystem/bd/SlicingBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_NUVOTON/TARGET_M480/us_ticker.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_NUVOTON/TARGET_NANO100/lp_ticker.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_NUVOTON/TARGET_NANO100/us_ticker.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_STM/TARGET_STM32L1/device/stm32l1xx_hal_flash.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_STM/TARGET_STM32L1/spi_api.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_STM/hal_tick_16b.c Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_STM/mbed_rtx.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/TARGET_TOSHIBA/mbed_rtx.h Show annotated file Show diff for this revision Revisions of this file
mbed-os/targets/targets.json Show annotated file Show diff for this revision Revisions of this file
mbed-os/tools/build_travis.py Show annotated file Show diff for this revision Revisions of this file
mbed-os/tools/export/sw4stm32/__init__.py Show annotated file Show diff for this revision Revisions of this file
--- a/Controller.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/Controller.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -29,6 +29,7 @@
  * @param pwm0 a pwm output object to set the duty cycle for the first motor.
  * @param pwm1 a pwm output object to set the duty cycle for the second motor.
  * @param pwm2 a pwm output object to set the duty cycle for the third motor.
+ * @param counter1
  */
 Controller::Controller(PwmOut& pwm0, PwmOut& pwm1, PwmOut& pwm2, EncoderCounter& counter1, EncoderCounter& counter2, EncoderCounter& counter3, IMU& imu) : pwm0(pwm0), pwm1(pwm1), pwm2(pwm2), counter1(counter1), counter2(counter2), counter3(counter3), imu(imu), thread(osPriorityHigh, STACK_SIZE)
 {
--- a/mbed-os.lib	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os.lib	Fri Mar 30 14:07:05 2018 +0000
@@ -1,1 +1,1 @@
-https://github.com/ARMmbed/mbed-os.git/#f895392374f50ffe53996459bbbf776e78006a67
+https://github.com/ARMmbed/mbed-os.git/#c8bd08f60e9d65bdec68dd3c5c45897f9ddb1c9b
--- a/mbed-os/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h	Thu Mar 29 14:42:59 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,372 +0,0 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2018 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 PAL_MEMORY_SECURITY_DB_H_
-#define PAL_MEMORY_SECURITY_DB_H_
-
-#include "SecurityDB.h"
-
-namespace ble {
-namespace pal {
-
-/** Naive memory implementation for verification. */
-class MemorySecurityDb : public SecurityDb {
-private:
-    enum state_t {
-        ENTRY_FREE,
-        ENTRY_RESERVED,
-        ENTRY_WRITTEN
-    };
-
-    struct entry_t {
-        entry_t() : state(ENTRY_FREE) { };
-        SecurityDistributionFlags_t flags;
-        SecurityEntryKeys_t peer_keys;
-        SecurityEntryKeys_t local_keys;
-        SecurityEntryIdentity_t peer_identity;
-        csrk_t csrk;
-        state_t state;
-    };
-    static const size_t MAX_ENTRIES = 5;
-
-    static entry_t* as_entry(entry_handle_t entry_handle)
-    {
-        return reinterpret_cast<entry_t*>(entry_handle);
-    }
-
-public:
-    MemorySecurityDb() { };
-    virtual ~MemorySecurityDb() { };
-
-    virtual const SecurityDistributionFlags_t* get_distribution_flags(
-        entry_handle_t entry_handle
-    ) {
-        entry_t* entry = as_entry(entry_handle);
-        if (!entry) {
-            return NULL;
-        }
-
-        return &entry->flags;
-    }
-
-    /**
-     * Set the distribution flags of the DB entry
-     */
-    virtual void set_distribution_flags(
-        entry_handle_t entry_handle,
-        const SecurityDistributionFlags_t& flags
-    ) {
-        entry_t* entry = as_entry(entry_handle);
-        if (!entry) {
-            return;
-        }
-
-        entry->state = ENTRY_WRITTEN;
-        entry->flags = flags;
-    }
-
-    /* local keys */
-
-    /* get */
-    virtual void get_entry_local_keys(
-        SecurityEntryKeysDbCb_t cb,
-        entry_handle_t entry_handle,
-        const ediv_t &ediv,
-        const rand_t &rand
-    ) {
-        entry_t* entry = as_entry(entry_handle);
-        if (!entry) {
-            return;
-        }
-
-        /* validate we have the correct key */
-        if (ediv == entry->local_keys.ediv && rand == entry->local_keys.rand) {
-            cb(entry_handle, &entry->local_keys);
-        } else {
-            cb(entry_handle, NULL);
-        }
-    }
-
-    virtual void get_entry_local_keys(
-        SecurityEntryKeysDbCb_t cb,
-        entry_handle_t entry_handle
-    ) {
-        entry_t* entry = as_entry(entry_handle);
-        if (!entry) {
-            return;
-        }
-
-        /* validate we have the correct key */
-        if (entry->flags.secure_connections_paired) {
-            cb(entry_handle, &entry->local_keys);
-        } else {
-            cb(entry_handle, NULL);
-        }
-    }
-
-
-    /* set */
-    virtual void set_entry_local_ltk(
-        entry_handle_t entry_handle,
-        const ltk_t &ltk
-    ) {
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            entry->state = ENTRY_WRITTEN;
-            entry->local_keys.ltk = ltk;
-        }
-    }
-
-    virtual void set_entry_local_ediv_rand(
-        entry_handle_t entry_handle,
-        const ediv_t &ediv,
-        const rand_t &rand
-    ) {
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            entry->state = ENTRY_WRITTEN;
-            entry->local_keys.ediv = ediv;
-            entry->local_keys.rand = rand;
-        }
-    }
-
-    /* peer's keys */
-
-    /* get */
-    virtual void get_entry_peer_csrk(
-        SecurityEntryCsrkDbCb_t cb,
-        entry_handle_t entry_handle
-    ) {
-        csrk_t csrk;
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            csrk = entry->csrk;
-        }
-        cb(entry_handle, &csrk);
-    }
-
-    virtual void get_entry_peer_keys(
-        SecurityEntryKeysDbCb_t cb,
-        entry_handle_t entry_handle
-    ) {
-        SecurityEntryKeys_t *key = NULL;
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            key = &entry->peer_keys;
-        }
-        cb(entry_handle, key);
-    }
-
-    /* set */
-
-    virtual void set_entry_peer_ltk(
-        entry_handle_t entry_handle,
-        const ltk_t &ltk
-    ) {
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            entry->state = ENTRY_WRITTEN;
-            entry->peer_keys.ltk = ltk;
-        }
-    }
-
-    virtual void set_entry_peer_ediv_rand(
-        entry_handle_t entry_handle,
-        const ediv_t &ediv,
-        const rand_t &rand
-    ) {
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            entry->state = ENTRY_WRITTEN;
-            entry->peer_keys.ediv = ediv;
-            entry->peer_keys.rand = rand;
-        }
-    }
-
-    virtual void set_entry_peer_irk(
-        entry_handle_t entry_handle,
-        const irk_t &irk
-    ) {
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            entry->state = ENTRY_WRITTEN;
-            entry->peer_identity.irk = irk;
-        }
-    }
-
-    virtual void set_entry_peer_bdaddr(
-        entry_handle_t entry_handle,
-        bool address_is_public,
-        const address_t &peer_address
-    ) {
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            entry->state = ENTRY_WRITTEN;
-            entry->peer_identity.identity_address = peer_address;
-        }
-    }
-
-    virtual void set_entry_peer_csrk(
-        entry_handle_t entry_handle,
-        const csrk_t &csrk
-    ) {
-        entry_t *entry = as_entry(entry_handle);
-        if (entry) {
-            entry->state = ENTRY_WRITTEN;
-            entry->csrk = csrk;
-        }
-    }
-
-    /* local csrk */
-
-    virtual const csrk_t* get_local_csrk() {
-        return &_local_csrk;
-    }
-
-    virtual void set_local_csrk(const csrk_t &csrk) {
-        _local_csrk = csrk;
-    }
-
-    /* public key */
-
-    virtual const public_key_coord_t& get_public_key_x() {
-        return _public_key_x;
-    }
-
-    virtual const public_key_coord_t& get_public_key_y() {
-        return _public_key_y;
-    }
-
-    virtual void set_public_key(
-        const public_key_coord_t &public_key_x,
-        const public_key_coord_t &public_key_y
-    ) {
-        _public_key_x = public_key_x;
-        _public_key_y = public_key_y;
-    }
-
-    /* list management */
-
-    virtual entry_handle_t open_entry(
-        BLEProtocol::AddressType_t peer_address_type,
-        const address_t &peer_address
-    ) {
-        const bool peer_address_public =
-            (peer_address_type == BLEProtocol::AddressType::PUBLIC);
-
-        for (size_t i = 0; i < MAX_ENTRIES; i++) {
-            if (_entries[i].state == ENTRY_FREE) {
-                continue;
-            } else if (peer_address == _entries[i].peer_identity.identity_address
-                && _entries[i].flags.peer_address_is_public == peer_address_public) {
-                return &_entries[i];
-            }
-        }
-
-        /* if we din't find one grab the first disconnected slot*/
-        for (size_t i = 0; i < MAX_ENTRIES; i++) {
-            if (_entries[i].state == ENTRY_FREE) {
-                _entries[i] = entry_t();
-                _entries[i].flags.peer_address = peer_address;
-                _entries[i].flags.peer_address_is_public = peer_address_public;
-                _entries[i].state = ENTRY_RESERVED;
-                return &_entries[i];
-            }
-        }
-
-        return NULL;
-    }
-
-    virtual void close_entry(entry_handle_t entry_handle)
-    {
-        entry_t *entry = as_entry(entry_handle);
-        if (entry && entry->state == ENTRY_RESERVED) {
-            entry->state = ENTRY_FREE;
-        }
-    }
-
-    virtual void remove_entry(const address_t peer_identity_address)
-    {
-        for (size_t i = 0; i < MAX_ENTRIES; i++) {
-            if (_entries[i].state == ENTRY_FREE) {
-                continue;
-            } else if (peer_identity_address == _entries[i].peer_identity.identity_address) {
-                _entries[i] = entry_t();
-                _entries[i].state = ENTRY_FREE;
-                return;
-            }
-        }
-    }
-
-    virtual void clear_entries() {
-        for (size_t i = 0; i < MAX_ENTRIES; i++) {
-            _entries[i] = entry_t();
-        }
-        _local_identity = SecurityEntryIdentity_t();
-        _local_csrk = csrk_t();
-    }
-
-    virtual void get_whitelist(WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist) {
-        /*TODO: fill whitelist*/
-        cb(whitelist);
-    }
-
-    virtual void generate_whitelist_from_bond_table(WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist) {
-        for (size_t i = 0; i < MAX_ENTRIES && i < whitelist->capacity; i++) {
-            if (_entries[i].flags.peer_address_is_public) {
-                whitelist->addresses[i].type = BLEProtocol::AddressType::PUBLIC;
-            } else {
-                whitelist->addresses[i].type = BLEProtocol::AddressType::RANDOM_STATIC;
-            }
-
-            memcpy(
-                whitelist->addresses[i].address,
-                _entries[i].peer_identity.identity_address.data(),
-                sizeof(BLEProtocol::AddressBytes_t)
-            );
-        }
-
-        cb(whitelist);
-    }
-
-    virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) { };
-
-    virtual void add_whitelist_entry(const address_t &address) { }
-
-    virtual void remove_whitelist_entry(const address_t &address) { }
-
-    virtual void clear_whitelist() { }
-
-    /* saving and loading from nvm */
-
-    virtual void restore() { }
-
-    virtual void sync() { }
-
-    virtual void set_restore(bool reload) { }
-
-private:
-    entry_t _entries[MAX_ENTRIES];
-    SecurityEntryIdentity_t _local_identity;
-    csrk_t _local_csrk;
-    public_key_coord_t _public_key_x;
-    public_key_coord_t _public_key_y;
-};
-
-} /* namespace pal */
-} /* namespace ble */
-
-#endif /*PAL_MEMORY_SECURITY_DB_H_*/
--- a/mbed-os/features/FEATURE_BLE/ble/pal/SecurityDb.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/FEATURE_BLE/ble/pal/SecurityDb.h	Fri Mar 30 14:07:05 2018 +0000
@@ -84,9 +84,9 @@
 };
 
 /**
- * SecurityDB holds the state for active connections and bonded devices.
+ * SecurityDb holds the state for active connections and bonded devices.
  * Keys can be stored in NVM and are returned via callbacks.
- * SecurityDB is responsible for serialising any requests and keeping
+ * SecurityDb is responsible for serialising any requests and keeping
  * the store in a consistent state.
  * Active connections state must be returned immediately.
  */
--- a/mbed-os/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h	Fri Mar 30 14:07:05 2018 +0000
@@ -30,7 +30,7 @@
 #include "CordioPalGenericAccessService.h"
 #include "ble/generic/GenericGap.h"
 #include "ble/generic/GenericSecurityManager.h"
-#include "ble/pal/MemorySecurityDB.h"
+#include "ble/pal/MemorySecurityDb.h"
 #include "ble/pal/SimpleEventQueue.h"
 
 namespace ble {
--- a/mbed-os/features/TESTS/filesystem/util_block_device/main.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/TESTS/filesystem/util_block_device/main.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -48,6 +48,7 @@
     TEST_ASSERT_EQUAL(0, err);
 
     TEST_ASSERT_EQUAL(BLOCK_SIZE, slice1.get_program_size());
+    TEST_ASSERT_EQUAL(BLOCK_SIZE, slice1.get_erase_size(BLOCK_SIZE));
     TEST_ASSERT_EQUAL((BLOCK_COUNT/2)*BLOCK_SIZE, slice1.size());
 
     // Fill with random sequence
@@ -142,6 +143,7 @@
     TEST_ASSERT_EQUAL(0, err);
 
     TEST_ASSERT_EQUAL(BLOCK_SIZE, chain.get_program_size());
+    TEST_ASSERT_EQUAL(BLOCK_SIZE, chain.get_erase_size((BLOCK_COUNT/2)*BLOCK_SIZE+1));
     TEST_ASSERT_EQUAL(BLOCK_COUNT*BLOCK_SIZE, chain.size());
 
     // Fill with random sequence
--- a/mbed-os/features/filesystem/bd/BlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/BlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -135,9 +135,9 @@
      */
     virtual bd_size_t get_program_size() const = 0;
 
-    /** Get the size of a eraseable block
+    /** Get the size of an erasable block
      *
-     *  @return         Size of a eraseable block in bytes
+     *  @return         Size of an erasable block in bytes
      *  @note Must be a multiple of the program size
      */
     virtual bd_size_t get_erase_size() const
@@ -145,6 +145,17 @@
         return get_program_size();
     }
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const
+    {
+        return get_erase_size();
+    }
+
     /** Get the value of storage when erased
      *
      *  If get_erase_value returns a non-negative byte value, the underlying
--- a/mbed-os/features/filesystem/bd/ChainingBlockDevice.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ChainingBlockDevice.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -211,6 +211,22 @@
     return _erase_size;
 }
 
+bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const
+{
+    bd_addr_t bd_start_addr = 0;
+    for (size_t i = 0; i < _bd_count; i++) {
+        bd_size_t bdsize = _bds[i]->size();
+        if (addr < (bd_start_addr + bdsize)) {
+            return _bds[i]->get_erase_size(addr - bd_start_addr);
+        }
+        bd_start_addr += bdsize;
+    }
+
+    // Getting here implies an illegal address
+    MBED_ASSERT(0);
+    return 0; // satisfy compiler
+}
+
 int ChainingBlockDevice::get_erase_value() const
 {
     return _erase_value;
--- a/mbed-os/features/filesystem/bd/ChainingBlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ChainingBlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -135,13 +135,21 @@
      */
     virtual bd_size_t get_program_size() const;
 
-    /** Get the size of a eraseable block
+    /** Get the size of an eraseable block
      *
-     *  @return         Size of a eraseable block in bytes
+     *  @return         Size of an erasable block in bytes
      *  @note Must be a multiple of the program size
      */
     virtual bd_size_t get_erase_size() const;
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const;
+
     /** Get the value of storage when erased
      *
      *  If get_erase_value returns a non-negative byte value, the underlying
--- a/mbed-os/features/filesystem/bd/ExhaustibleBlockDevice.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ExhaustibleBlockDevice.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -107,6 +107,11 @@
     return _bd->get_erase_size();
 }
 
+bd_size_t ExhaustibleBlockDevice::get_erase_size(bd_addr_t addr) const
+{
+    return _bd->get_erase_size(addr);
+}
+
 int ExhaustibleBlockDevice::get_erase_value() const
 {
     return _bd->get_erase_value();
--- a/mbed-os/features/filesystem/bd/ExhaustibleBlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ExhaustibleBlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -119,12 +119,20 @@
      */
     virtual bd_size_t get_program_size() const;
 
-    /** Get the size of a erasable block
+    /** Get the size of an erasable block
      *
-     *  @return         Size of a erasable block in bytes
+     *  @return         Size of an erasable block in bytes
      */
     virtual bd_size_t get_erase_size() const;
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const;
+
     /** Get the value of storage when erased
      *
      *  If get_erase_value returns a non-negative byte value, the underlying
--- a/mbed-os/features/filesystem/bd/HeapBlockDevice.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/HeapBlockDevice.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -81,6 +81,12 @@
     return _erase_size;
 }
 
+bd_size_t HeapBlockDevice::get_erase_size(bd_addr_t addr) const
+{
+    MBED_ASSERT(_blocks != NULL);
+    return _erase_size;
+}
+
 bd_size_t HeapBlockDevice::size() const
 {
     MBED_ASSERT(_blocks != NULL);
--- a/mbed-os/features/filesystem/bd/HeapBlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/HeapBlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -124,12 +124,20 @@
      */
     virtual bd_size_t get_program_size() const;
 
-    /** Get the size of a eraseable block
+    /** Get the size of an erasable block
      *
-     *  @return         Size of a eraseable block in bytes
+     *  @return         Size of an erasable block in bytes
      */
     virtual bd_size_t get_erase_size() const;
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const;
+
     /** Get the total size of the underlying device
      *
      *  @return         Size of the underlying device in bytes
--- a/mbed-os/features/filesystem/bd/MBRBlockDevice.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/MBRBlockDevice.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -276,6 +276,11 @@
     return _bd->get_erase_size();
 }
 
+bd_size_t MBRBlockDevice::get_erase_size(bd_addr_t addr) const
+{
+    return _bd->get_erase_size(_offset + addr);
+}
+
 int MBRBlockDevice::get_erase_value() const
 {
     return _bd->get_erase_value();
--- a/mbed-os/features/filesystem/bd/MBRBlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/MBRBlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -194,13 +194,21 @@
      */
     virtual bd_size_t get_program_size() const;
 
-    /** Get the size of a eraseable block
+    /** Get the size of an erasable block
      *
-     *  @return         Size of a eraseable block in bytes
+     *  @return         Size of an erasable block in bytes
      *  @note Must be a multiple of the program size
      */
     virtual bd_size_t get_erase_size() const;
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const;
+
     /** Get the value of storage when erased
      *
      *  If get_erase_value returns a non-negative byte value, the underlying
--- a/mbed-os/features/filesystem/bd/ObservingBlockDevice.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ObservingBlockDevice.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -96,6 +96,11 @@
     return _bd->get_erase_size();
 }
 
+bd_size_t ObservingBlockDevice::get_erase_size(bd_addr_t addr) const
+{
+    return _bd->get_erase_size(addr);
+}
+
 int ObservingBlockDevice::get_erase_value() const
 {
     return _bd->get_erase_value();
--- a/mbed-os/features/filesystem/bd/ObservingBlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ObservingBlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -105,12 +105,20 @@
      */
     virtual bd_size_t get_program_size() const;
 
-    /** Get the size of a erasable block
+    /** Get the size of an erasable block
      *
-     *  @return         Size of a erasable block in bytes
+     *  @return         Size of an erasable block in bytes
      */
     virtual bd_size_t get_erase_size() const;
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const;
+
     /** Get the value of storage when erased
      *
      *  If get_erase_value returns a non-negative byte value, the underlying
--- a/mbed-os/features/filesystem/bd/ProfilingBlockDevice.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ProfilingBlockDevice.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -82,6 +82,11 @@
     return _bd->get_erase_size();
 }
 
+bd_size_t ProfilingBlockDevice::get_erase_size(bd_addr_t addr) const
+{
+    return _bd->get_erase_size(addr);
+}
+
 int ProfilingBlockDevice::get_erase_value() const
 {
     return _bd->get_erase_value();
--- a/mbed-os/features/filesystem/bd/ProfilingBlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ProfilingBlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -121,13 +121,21 @@
      */
     virtual bd_size_t get_program_size() const;
 
-    /** Get the size of a eraseable block
+    /** Get the size of an erasable block
      *
-     *  @return         Size of a eraseable block in bytes
+     *  @return         Size of an erasable block in bytes
      *  @note Must be a multiple of the program size
      */
     virtual bd_size_t get_erase_size() const;
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const;
+
     /** Get the value of storage when erased
      *
      *  If get_erase_value returns a non-negative byte value, the underlying
--- a/mbed-os/features/filesystem/bd/ReadOnlyBlockDevice.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ReadOnlyBlockDevice.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -82,6 +82,11 @@
     return _bd->get_erase_size();
 }
 
+bd_size_t ReadOnlyBlockDevice::get_erase_size(bd_addr_t addr) const
+{
+    return _bd->get_erase_size(addr);
+}
+
 int ReadOnlyBlockDevice::get_erase_value() const
 {
     return _bd->get_erase_value();
--- a/mbed-os/features/filesystem/bd/ReadOnlyBlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/ReadOnlyBlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -98,12 +98,20 @@
      */
     virtual bd_size_t get_program_size() const;
 
-    /** Get the size of a erasable block
+    /** Get the size of an erasable block
      *
-     *  @return         Size of a erasable block in bytes
+     *  @return         Size of an erasable block in bytes
      */
     virtual bd_size_t get_erase_size() const;
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const;
+
     /** Get the value of storage when erased
      *
      *  If get_erase_value returns a non-negative byte value, the underlying
--- a/mbed-os/features/filesystem/bd/SlicingBlockDevice.cpp	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/SlicingBlockDevice.cpp	Fri Mar 30 14:07:05 2018 +0000
@@ -102,6 +102,11 @@
     return _bd->get_erase_size();
 }
 
+bd_size_t SlicingBlockDevice::get_erase_size(bd_addr_t addr) const
+{
+    return _bd->get_erase_size(_start + addr);
+}
+
 int SlicingBlockDevice::get_erase_value() const
 {
     return _bd->get_erase_value();
--- a/mbed-os/features/filesystem/bd/SlicingBlockDevice.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/features/filesystem/bd/SlicingBlockDevice.h	Fri Mar 30 14:07:05 2018 +0000
@@ -127,13 +127,21 @@
      */
     virtual bd_size_t get_program_size() const;
 
-    /** Get the size of a eraseable block
+    /** Get the size of an erasable block
      *
-     *  @return         Size of a eraseable block in bytes
+     *  @return         Size of an erasable block in bytes
      *  @note Must be a multiple of the program size
      */
     virtual bd_size_t get_erase_size() const;
 
+    /** Get the size of an erasable block given address
+     *
+     *  @param addr     Address within the erasable block
+     *  @return         Size of an erasable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size(bd_addr_t addr) const;
+
     /** Get the value of storage when erased
      *
      *  If get_erase_value returns a non-negative byte value, the underlying
--- a/mbed-os/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c	Fri Mar 30 14:07:05 2018 +0000
@@ -47,6 +47,9 @@
 #define TMR_CMP_MIN         2
 #define TMR_CMP_MAX         0xFFFFFFu
 
+/* NOTE: When system clock is higher than timer clock, we need to add 3 engine clock
+ *       (recommended by designer) delay to wait for above timer control to take effect. */
+
 void lp_ticker_init(void)
 {
     if (ticker_inited) {
@@ -63,8 +66,10 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Configure clock
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
@@ -72,19 +77,28 @@
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
     // Continuous mode
     // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451. In M451, TIMER_CNT is updated continuously by default.
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMP = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    timer_base->CMP = cmp_timer;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 
     // Set vector
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
+    TIMER_EnableInt(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    TIMER_EnableWakeup(timer_base);
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+
+    TIMER_Start(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_ACTSTS_Msk));
 }
 
 timestamp_t lp_ticker_read()
@@ -93,7 +107,7 @@
         lp_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -108,27 +122,27 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
     uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK;
     cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX);
+
     timer_base->CMP = cmp_timer;
-
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start(timer_base);
 }
 
 void lp_ticker_disable_interrupt(void)
 {
     TIMER_DisableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_clear_interrupt(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_fire_interrupt(void)
@@ -150,8 +164,11 @@
 static void tmr1_vec(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     TIMER_ClearWakeupFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     // NOTE: lp_ticker_set_interrupt() may get called in lp_ticker_irq_handler();
     lp_ticker_irq_handler();
 }
--- a/mbed-os/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c	Fri Mar 30 14:07:05 2018 +0000
@@ -58,23 +58,28 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Timer for normal counter
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
     uint32_t cmp_timer = TMR_CMP_MAX;
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
     // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451. In M451, TIMER_CNT is updated continuously by default.
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMP = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
+    timer_base->CMP = cmp_timer;
 
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    TIMER_EnableInt(timer_base);
+
+    TIMER_Start(timer_base);
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_ACTSTS_Msk));
 }
 
 uint32_t us_ticker_read()
@@ -83,7 +88,7 @@
         us_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -98,7 +103,7 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
--- a/mbed-os/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c	Fri Mar 30 14:07:05 2018 +0000
@@ -47,6 +47,9 @@
 #define TMR_CMP_MIN         2
 #define TMR_CMP_MAX         0xFFFFFFu
 
+/* NOTE: When system clock is higher than timer clock, we need to add 3 engine clock
+ *       (recommended by designer) delay to wait for above timer control to take effect. */
+
 void lp_ticker_init(void)
 {
     if (ticker_inited) {
@@ -63,8 +66,10 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Configure clock
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
@@ -72,19 +77,28 @@
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
     // Continuous mode
     // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default.
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMP = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    timer_base->CMP = cmp_timer;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 
     // Set vector
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
+    TIMER_EnableInt(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    TIMER_EnableWakeup(timer_base);
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+
+    TIMER_Start(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_ACTSTS_Msk));
 }
 
 timestamp_t lp_ticker_read()
@@ -93,7 +107,7 @@
         lp_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -108,27 +122,27 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
     uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK;
     cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX);
+
     timer_base->CMP = cmp_timer;
-
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start(timer_base);
 }
 
 void lp_ticker_disable_interrupt(void)
 {
     TIMER_DisableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_clear_interrupt(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_fire_interrupt(void)
@@ -150,8 +164,11 @@
 static void tmr1_vec(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     TIMER_ClearWakeupFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     // NOTE: lp_ticker_set_interrupt() may get called in lp_ticker_irq_handler();
     lp_ticker_irq_handler();
 }
--- a/mbed-os/targets/TARGET_NUVOTON/TARGET_M480/us_ticker.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_NUVOTON/TARGET_M480/us_ticker.c	Fri Mar 30 14:07:05 2018 +0000
@@ -58,23 +58,28 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Timer for normal counter
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
     uint32_t cmp_timer = TMR_CMP_MAX;
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
     // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default.
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMP = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
+    timer_base->CMP = cmp_timer;
 
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    TIMER_EnableInt(timer_base);
+
+    TIMER_Start(timer_base);
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_ACTSTS_Msk));
 }
 
 uint32_t us_ticker_read()
@@ -83,7 +88,7 @@
         us_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -98,7 +103,7 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
--- a/mbed-os/targets/TARGET_NUVOTON/TARGET_NANO100/lp_ticker.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_NUVOTON/TARGET_NANO100/lp_ticker.c	Fri Mar 30 14:07:05 2018 +0000
@@ -49,6 +49,9 @@
 #define TMR_CMP_MIN         2
 #define TMR_CMP_MAX         0xFFFFFFu
 
+/* NOTE: When system clock is higher than timer clock, we need to add 3 engine clock
+ *       (recommended by designer) delay to wait for above timer control to take effect. */
+
 void lp_ticker_init(void)
 {
     if (ticker_inited) {
@@ -65,28 +68,41 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Configure clock
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
     uint32_t cmp_timer = TMR_CMP_MAX;
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
     // Continuous mode
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->PRECNT = prescale_timer;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMPR = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    timer_base->PRECNT = prescale_timer;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    timer_base->CMPR = cmp_timer;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 
     // Set vector
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
+    TIMER_EnableInt(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    TIMER_EnableWakeup(timer_base);
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+
+    TIMER_Start(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_TMR_ACT_Msk));
 }
 
 timestamp_t lp_ticker_read()
@@ -95,7 +111,7 @@
         lp_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -110,27 +126,27 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
     uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK;
     cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX);
+
     timer_base->CMPR = cmp_timer;
-
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start(timer_base);
 }
 
 void lp_ticker_disable_interrupt(void)
 {
     TIMER_DisableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_clear_interrupt(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_fire_interrupt(void)
@@ -152,8 +168,11 @@
 void TMR1_IRQHandler(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     TIMER_ClearWakeupFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     // NOTE: lp_ticker_set_interrupt() may get called in lp_ticker_irq_handler();
     lp_ticker_irq_handler();
 }
--- a/mbed-os/targets/TARGET_NUVOTON/TARGET_NANO100/us_ticker.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_NUVOTON/TARGET_NANO100/us_ticker.c	Fri Mar 30 14:07:05 2018 +0000
@@ -60,23 +60,28 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Timer for normal counter
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
     uint32_t cmp_timer = TMR_CMP_MAX;
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->PRECNT = prescale_timer;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMPR = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE;
+    timer_base->PRECNT = prescale_timer;
+    timer_base->CMPR = cmp_timer;
 
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    TIMER_EnableInt(timer_base);
+
+    TIMER_Start(timer_base);
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_TMR_ACT_Msk));
 }
 
 uint32_t us_ticker_read()
@@ -85,7 +90,7 @@
         us_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -100,7 +105,7 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
--- a/mbed-os/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c	Fri Mar 30 14:07:05 2018 +0000
@@ -47,6 +47,9 @@
 #define TMR_CMP_MIN         2
 #define TMR_CMP_MAX         0xFFFFFFu
 
+/* NOTE: When system clock is higher than timer clock, we need to add 3 engine clock
+ *       (recommended by designer) delay to wait for above timer control to take effect. */
+
 void lp_ticker_init(void)
 {
     if (ticker_inited) {
@@ -63,27 +66,38 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Configure clock
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
     uint32_t cmp_timer = TMR_CMP_MAX;
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
     // Continuous mode
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE | prescale_timer | TIMER_CTL_CNTDATEN_Msk;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMP = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE | prescale_timer | TIMER_CTL_CNTDATEN_Msk;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    timer_base->CMP = cmp_timer;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 
     // Set vector
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
+    TIMER_EnableInt(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    TIMER_EnableWakeup(timer_base);
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+
+    TIMER_Start(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_ACTSTS_Msk));
 }
 
 timestamp_t lp_ticker_read()
@@ -92,7 +106,7 @@
         lp_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -107,27 +121,27 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
     uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK;
     cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX);
+
     timer_base->CMP = cmp_timer;
-
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start(timer_base);
 }
 
 void lp_ticker_disable_interrupt(void)
 {
     TIMER_DisableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_clear_interrupt(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_fire_interrupt(void)
@@ -149,8 +163,11 @@
 static void tmr1_vec(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     TIMER_ClearWakeupFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     // NOTE: lp_ticker_set_interrupt() may get called in lp_ticker_irq_handler();
     lp_ticker_irq_handler();
 }
--- a/mbed-os/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c	Fri Mar 30 14:07:05 2018 +0000
@@ -58,22 +58,27 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Timer for normal counter
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
     uint32_t cmp_timer = TMR_CMP_MAX;
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE | prescale_timer | TIMER_CTL_CNTDATEN_Msk;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMP = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE | prescale_timer | TIMER_CTL_CNTDATEN_Msk;
+    timer_base->CMP = cmp_timer;
 
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    TIMER_EnableInt(timer_base);
+
+    TIMER_Start(timer_base);
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_ACTSTS_Msk));
 }
 
 uint32_t us_ticker_read()
@@ -82,7 +87,7 @@
         us_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -97,7 +102,7 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
--- a/mbed-os/targets/TARGET_STM/TARGET_STM32L1/device/stm32l1xx_hal_flash.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_STM/TARGET_STM32L1/device/stm32l1xx_hal_flash.h	Fri Mar 30 14:07:05 2018 +0000
@@ -139,7 +139,9 @@
   * @{
   */ 
 
+#ifndef FLASH_SIZE
 #define FLASH_SIZE                (uint32_t)(*((uint16_t *)FLASHSIZE_BASE) * 1024U)
+#endif
 #define FLASH_PAGE_SIZE           ((uint32_t)256U)  /*!< FLASH Page Size in bytes */
 
 /**
--- a/mbed-os/targets/TARGET_STM/TARGET_STM32L1/spi_api.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_STM/TARGET_STM32L1/spi_api.c	Fri Mar 30 14:07:05 2018 +0000
@@ -59,7 +59,9 @@
 			spi_hz = HAL_RCC_GetPCLK2Freq();
 			break;
 		case SPI_2:
-		case SPI_3:
+#ifdef SPI_3
+        case SPI_3:
+#endif
 			/* SPI_2, SPI_3. Source CLK is PCKL1 */
 			spi_hz = HAL_RCC_GetPCLK1Freq();
 			break;
--- a/mbed-os/targets/TARGET_STM/hal_tick_16b.c	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_STM/hal_tick_16b.c	Fri Mar 30 14:07:05 2018 +0000
@@ -105,7 +105,7 @@
     TimMasterHandle.Init.Prescaler     = (uint32_t)(SystemCoreClock / 1000000) - 1; // 1 us tick
     TimMasterHandle.Init.ClockDivision = 0;
     TimMasterHandle.Init.CounterMode   = TIM_COUNTERMODE_UP;
-#if !defined(TARGET_STM32L0)
+#if !defined(TARGET_STM32L0) && !defined(TARGET_STM32L1)
     TimMasterHandle.Init.RepetitionCounter = 0;
 #endif
 #ifdef TIM_AUTORELOAD_PRELOAD_DISABLE
--- a/mbed-os/targets/TARGET_STM/mbed_rtx.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_STM/mbed_rtx.h	Fri Mar 30 14:07:05 2018 +0000
@@ -59,6 +59,7 @@
 
 #elif (defined(TARGET_STM32F091RC) ||\
        defined(TARGET_STM32F410RB) ||\
+       defined(TARGET_STM32L151CBA)||\
        defined(TARGET_STM32L151CC) ||\
        defined(TARGET_STM32L151RC) ||\
        defined(TARGET_STM32L152RC))
--- a/mbed-os/targets/TARGET_TOSHIBA/mbed_rtx.h	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/TARGET_TOSHIBA/mbed_rtx.h	Fri Mar 30 14:07:05 2018 +0000
@@ -25,4 +25,12 @@
 
 #endif
 
+#if defined(TARGET_TMPM46B)
+
+#ifndef INITIAL_SP
+#define INITIAL_SP                        (0x20080000UL)
+#endif
+
+#endif
+
 #endif  // MBED_MBED_RTX_H
--- a/mbed-os/targets/targets.json	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/targets/targets.json	Fri Mar 30 14:07:05 2018 +0000
@@ -1525,7 +1525,7 @@
         "device_name": "STM32L433RC",
         "bootloader_supported": true
     },
-	"MTB_ADV_WISE_1510": {
+    "MTB_ADV_WISE_1510": {
         "inherits": ["FAMILY_STM32"],
         "supported_form_factors": ["ARDUINO"],
         "core": "Cortex-M4F",
@@ -2022,6 +2022,17 @@
         "device_name": "STM32L151CC",
         "bootloader_supported": true
     },
+    "MTB_RAK811": {
+        "inherits": ["FAMILY_STM32"],
+        "core": "Cortex-M3",
+        "default_toolchain": "ARM",
+        "extra_labels_add": ["STM32L1", "STM32L151xBA", "STM32L151CBA"],
+        "supported_toolchains": ["ARM", "GCC_ARM", "IAR"],
+        "device_has_add": ["ANALOGOUT"],
+        "release_versions": ["5"],
+        "device_name": "STM32L151CBxxA",
+        "bootloader_supported": true
+    },
     "MOTE_L152RC": {
         "inherits": ["FAMILY_STM32"],
         "core": "Cortex-M3",
@@ -2758,13 +2769,13 @@
         "extra_labels": ["Maxim", "MAX32630"],
         "supported_toolchains": ["GCC_ARM", "IAR", "ARM"],
         "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES"],
-		"features": ["BLE"],
+        "features": ["BLE"],
         "release_versions": ["2", "5"]
     },
     "EFM32": {
         "inherits": ["Target"],
         "extra_labels": ["Silicon_Labs", "EFM32"],
-        "macros": ["MBEDTLS_CONFIG_HW_SUPPORT"],
+        "macros": ["MBEDTLS_CONFIG_HW_SUPPORT", "MBED_TICKLESS"],
         "public": false
     },
     "EFM32GG990F1024": {
@@ -3957,5 +3968,18 @@
         "device_has_add": ["LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"],
         "release_versions": ["2"],
         "device_name": "STM32F411RE"
+    },
+    "TMPM46B": {
+        "inherits": ["Target"],
+        "core": "Cortex-M4",
+        "is_disk_virtual": true,
+        "extra_labels": ["TOSHIBA"],
+        "macros": ["__TMPM46B__"],
+        "supported_toolchains": ["GCC_ARM", "ARM", "IAR"],
+        "device_has": ["ANALOGIN", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SPI", "I2C", "STDIO_MESSAGES", "TRNG", "FLASH", "SLEEP"],
+        "device_name": "TMPM46BF10FG",
+        "detect_code": ["7013"],
+        "release_versions": ["5"],
+        "bootloader_supported": true
     }
 }
--- a/mbed-os/tools/build_travis.py	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/tools/build_travis.py	Fri Mar 30 14:07:05 2018 +0000
@@ -33,8 +33,9 @@
     {
     "STM":
         (
-        { "target": "B96B_F446VE",     "toolchains": "GCC_ARM", "libs": ["dsp"] },
+        { "target": "B96B_F446VE",       "toolchains": "GCC_ARM", "libs": ["dsp"] },
         { "target": "NUCLEO_L053R8",     "toolchains": "GCC_ARM", "libs": ["dsp"] },
+        { "target": "MTB_RAK811",        "toolchains": "GCC_ARM"},
         { "target": "NUCLEO_L152RE",     "toolchains": "GCC_ARM", "libs": ["dsp"] },
         { "target": "NUCLEO_F030R8",     "toolchains": "GCC_ARM", "libs": ["dsp"] },
         { "target": "NUCLEO_F031K6",     "toolchains": "GCC_ARM", "libs": ["dsp"] },
--- a/mbed-os/tools/export/sw4stm32/__init__.py	Thu Mar 29 14:42:59 2018 +0000
+++ b/mbed-os/tools/export/sw4stm32/__init__.py	Fri Mar 30 14:07:05 2018 +0000
@@ -248,6 +248,11 @@
             'name': 'NUCLEO-L073RZ',
             'mcuId': 'STM32L073RZTx'
         },
+        'MTB_RAK811':
+        {
+            'name': 'MTB-RAK-811',
+            'mcuId': 'STM32L151CBUxA'
+        },
         'NUCLEO_L152RE':
         {
             'name': 'NUCLEO-L152RE',