update

Files at this revision

API Documentation at this revision

Comitter:
kwengryn3
Date:
Thu Apr 08 16:43:07 2021 +0000
Commit message:
update;

Changed in this revision

ATCmdParser.h Show annotated file Show diff for this revision Revisions of this file
CThunk.h Show annotated file Show diff for this revision Revisions of this file
CThunkBase.h Show annotated file Show diff for this revision Revisions of this file
CallChain.h Show annotated file Show diff for this revision Revisions of this file
Callback.h Show annotated file Show diff for this revision Revisions of this file
CircularBuffer.h Show annotated file Show diff for this revision Revisions of this file
CriticalSectionLock.h Show annotated file Show diff for this revision Revisions of this file
DeepSleepLock.h Show annotated file Show diff for this revision Revisions of this file
DirHandle.h Show annotated file Show diff for this revision Revisions of this file
FileBase.h Show annotated file Show diff for this revision Revisions of this file
FileHandle.h Show annotated file Show diff for this revision Revisions of this file
FileLike.h Show annotated file Show diff for this revision Revisions of this file
FilePath.h Show annotated file Show diff for this revision Revisions of this file
FileSystemHandle.h Show annotated file Show diff for this revision Revisions of this file
FileSystemLike.h Show annotated file Show diff for this revision Revisions of this file
FunctionPointer.h Show annotated file Show diff for this revision Revisions of this file
LocalFileSystem.h Show annotated file Show diff for this revision Revisions of this file
critical.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ATCmdParser.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,324 @@
+/* Copyright (c) 2017 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+#ifndef MBED_ATCMDPARSER_H
+#define MBED_ATCMDPARSER_H
+
+#include <cstdarg>
+#include "Callback.h"
+#include "NonCopyable.h"
+#include "FileHandle.h"
+
+namespace mbed {
+
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_ATCmdParser ATCmdParser class
+ * @{
+ */
+
+/**
+ * Parser class for parsing AT commands
+ *
+ * Here are some examples:
+ * @code
+ * UARTSerial serial = UARTSerial(D1, D0);
+ * ATCmdParser at = ATCmdParser(&serial, "\r\n");
+ * int value;
+ * char buffer[100];
+ *
+ * at.send("AT") && at.recv("OK");
+ * at.send("AT+CWMODE=%d", 3) && at.recv("OK");
+ * at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value);
+ * at.recv("+IPD,%d:", &value);
+ * at.read(buffer, value);
+ * at.recv("OK");
+ * @endcode
+ */
+
+class ATCmdParser : private NonCopyable<ATCmdParser> {
+private:
+    // File handle
+    // Not owned by ATCmdParser
+    FileHandle *_fh;
+
+    int _buffer_size;
+    char *_buffer;
+    int _timeout;
+
+    // Parsing information
+    const char *_output_delimiter;
+    int _output_delim_size;
+    int _oob_cb_count;
+    char _in_prev;
+    bool _dbg_on;
+    bool _aborted;
+
+    struct oob {
+        unsigned len;
+        const char *prefix;
+        mbed::Callback<void()> cb;
+        oob *next;
+    };
+    oob *_oobs;
+
+public:
+
+    /**
+     * Constructor
+     *
+     * @param fh A FileHandle to the digital interface, used for AT commands
+     * @param output_delimiter End of command-line termination
+     * @param buffer_size Size of internal buffer for transaction
+     * @param timeout Timeout of the connection
+     * @param debug Turns on/off debug output for AT commands
+     */
+    ATCmdParser(FileHandle *fh, const char *output_delimiter = "\r",
+                int buffer_size = 256, int timeout = 8000, bool debug = false)
+        : _fh(fh), _buffer_size(buffer_size), _oob_cb_count(0), _in_prev(0), _oobs(NULL)
+    {
+        _buffer = new char[buffer_size];
+        set_timeout(timeout);
+        set_delimiter(output_delimiter);
+        debug_on(debug);
+    }
+
+    /**
+     * Destructor
+     */
+    ~ATCmdParser()
+    {
+        while (_oobs) {
+            struct oob *oob = _oobs;
+            _oobs = oob->next;
+            delete oob;
+        }
+        delete[] _buffer;
+    }
+
+    /**
+     * Allows timeout to be changed between commands
+     *
+     * @param timeout ATCmdParser APIs (read/write/send/recv ..etc) throw an
+     *                error if no response is received in `timeout` duration
+     */
+    void set_timeout(int timeout)
+    {
+        _timeout = timeout;
+    }
+
+    /**
+     * For backward compatibility.
+     * @deprecated Do not use this function. This function has been replaced with set_timeout for consistency.
+     *
+     * Please use set_timeout(int) API only from now on.
+     * Allows timeout to be changed between commands
+     *
+     * @param timeout ATCmdParser APIs (read/write/send/recv ..etc) throw an
+     *                error if no response is received in `timeout` duration
+     *
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with set_timeout for consistency")
+    void setTimeout(int timeout)
+    {
+        set_timeout(timeout);
+    }
+
+    /**
+     * Sets string of characters to use as line delimiters
+     *
+     * @param output_delimiter String of characters to use as line delimiters
+     */
+    void set_delimiter(const char *output_delimiter)
+    {
+        _output_delimiter = output_delimiter;
+        _output_delim_size = strlen(output_delimiter);
+    }
+
+    /**
+     * For backwards compatibility.
+     * @deprecated Do not use this function. This function has been replaced with set_delimiter for consistency.
+     *
+     * Please use set_delimiter(const char *) API only from now on.
+     * Sets string of characters to use as line delimiters
+     *
+     * @param output_delimiter string of characters to use as line delimiters
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with set_delimiter for consistency")
+    void setDelimiter(const char *output_delimiter)
+    {
+        set_delimiter(output_delimiter);
+    }
+
+    /**
+     * Allows traces from modem to be turned on or off
+     *
+     * @param on Set as 1 to turn on traces and 0 to disable traces.
+     */
+    void debug_on(uint8_t on)
+    {
+        _dbg_on = (on) ? 1 : 0;
+    }
+
+    /**
+     * For backward compatibility.
+     * @deprecated Do not use this function. This function has been replaced with debug_on for consistency.
+     *
+     * Allows traces from modem to be turned on or off
+     *
+     * @param on Set as 1 to turn on traces and 0 to disable traces.
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with debug_on for consistency")
+    void debugOn(uint8_t on)
+    {
+        debug_on(on);
+    }
+
+    /**
+     * Sends an AT command
+     *
+     * Sends a formatted command using printf style formatting
+     * @see printf
+     *
+     * @param command printf-like format string of command to send which
+     *                is appended with a newline
+     * @param ... all printf-like arguments to insert into command
+     * @return true only if command is successfully sent
+     */
+    bool send(const char *command, ...) MBED_PRINTF_METHOD(1, 2);
+
+    bool vsend(const char *command, std::va_list args);
+
+    /**
+     * Receive an AT response
+     *
+     * Receives a formatted response using scanf style formatting
+     * @see scanf
+     *
+     * Responses are parsed line at a time.
+     * Any received data that does not match the response is ignored until
+     * a timeout occurs.
+     *
+     * @param response scanf-like format string of response to expect
+     * @param ... all scanf-like arguments to extract from response
+     * @return true only if response is successfully matched
+     */
+    bool recv(const char *response, ...) MBED_SCANF_METHOD(1, 2);
+
+    bool vrecv(const char *response, std::va_list args);
+
+    /**
+     * Write a single byte to the underlying stream
+     *
+     * @param c The byte to write
+     * @return The byte that was written or -1 during a timeout
+     */
+    int putc(char c);
+
+    /**
+     * Get a single byte from the underlying stream
+     *
+     * @return The byte that was read or -1 during a timeout
+     */
+    int getc();
+
+    /**
+     * Write an array of bytes to the underlying stream
+     *
+     * @param data The array of bytes to write
+     * @param size Number of bytes to write
+     * @return number of bytes written or -1 on failure
+     */
+    int write(const char *data, int size);
+
+    /**
+     * Read an array of bytes from the underlying stream
+     *
+     * @param data The buffer for filling the read bytes
+     * @param size Number of bytes to read
+     * @return number of bytes read or -1 on failure
+     */
+    int read(char *data, int size);
+
+    /**
+     * Direct printf to underlying stream
+     * @see printf
+     *
+     * @param format Format string to pass to printf
+     * @param ... Variable arguments to printf
+     * @return number of bytes written or -1 on failure
+     */
+    int printf(const char *format, ...) MBED_PRINTF_METHOD(1, 2);
+
+    int vprintf(const char *format, std::va_list args);
+
+    /**
+     * Direct scanf on underlying stream
+     * @see scanf
+     *
+     * @param format Format string to pass to scanf
+     * @param ... Variable arguments to scanf
+     * @return number of bytes read or -1 on failure
+     */
+    int scanf(const char *format, ...) MBED_SCANF_METHOD(1, 2);
+
+    int vscanf(const char *format, std::va_list args);
+
+    /**
+     * Attach a callback for out-of-band data
+     *
+     * @param prefix String on when to initiate callback
+     * @param func Callback to call when string is read
+     * @note out-of-band data is only processed during a scanf call
+     */
+    void oob(const char *prefix, mbed::Callback<void()> func);
+
+    /**
+     * Flushes the underlying stream
+     */
+    void flush();
+
+    /**
+     * Abort current recv
+     *
+     * Can be called from out-of-band handler to interrupt the current
+     * recv operation.
+     */
+    void abort();
+
+    /**
+    * Process out-of-band data
+    *
+    * Process out-of-band data in the receive buffer. This function
+    * returns immediately if there is no data to process.
+    *
+    * @return true if out-of-band data processed, false otherwise
+    */
+    bool process_oob(void);
+};
+
+/**@}*/
+
+/**@}*/
+
+} //namespace mbed
+
+#endif //MBED_ATCMDPARSER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CThunk.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,174 @@
+
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_CThunk CThunk class
+ * @{
+ */
+/* General C++ Object Thunking class
+ *
+ * - allows direct callbacks to non-static C++ class functions
+ * - keeps track for the corresponding class instance
+ * - supports an optional context parameter for the called function
+ * - ideally suited for class object receiving interrupts (NVIC_SetVector)
+ *
+ * Copyright (c) 2014-2015 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+/* General C++ Object Thunking class
+ *
+ * - allows direct callbacks to non-static C++ class functions
+ * - keeps track for the corresponding class instance
+ * - supports an optional context parameter for the called function
+ * - ideally suited for class object receiving interrupts (NVIC_SetVector)
+ */
+
+#ifndef __CTHUNK_H__
+#define __CTHUNK_H__
+
+#include "CThunkBase.h"
+
+/**
+ * Class for created a pointer with data bound to it
+ *
+ * @note Synchronization level: Not protected
+ */
+template<class T>
+class CThunk: public CThunkBase {
+public:
+    typedef void (T::*CCallbackSimple)(void);
+    typedef void (T::*CCallback)(void *context);
+
+    inline CThunk(T *instance)
+    {
+        init(instance, NULL, NULL);
+    }
+
+    inline CThunk(T *instance, CCallback callback)
+    {
+        init(instance, callback, NULL);
+    }
+
+    ~CThunk()
+    {
+        cthunk_free(_entry);
+        _entry = NULL;
+    }
+
+    inline CThunk(T *instance, CCallbackSimple callback)
+    {
+        init(instance, (CCallback)callback, NULL);
+    }
+
+    inline CThunk(T &instance, CCallback callback)
+    {
+        init(instance, callback, NULL);
+    }
+
+    inline CThunk(T &instance, CCallbackSimple callback)
+    {
+        init(instance, (CCallback)callback, NULL);
+    }
+
+    inline CThunk(T &instance, CCallback callback, void *context)
+    {
+        init(instance, callback, context);
+    }
+
+    inline void callback(CCallback callback)
+    {
+        _callback = callback;
+    }
+
+    inline void callback(CCallbackSimple callback)
+    {
+        _callback_simple = callback;
+    }
+
+    inline void context(void *context)
+    {
+        _context = context;
+    }
+
+    inline void context(uint32_t context)
+    {
+        _context = (void *)context;
+    }
+
+    inline uint32_t entry(void)
+    {
+        if (_entry == NULL) {
+            _entry = cthunk_alloc(this);
+        }
+        return (uint32_t)_entry;
+    }
+
+    /* get thunk entry point for connecting rhunk to an IRQ table */
+    inline operator CThunkEntry(void)
+    {
+        return (CThunkEntry)entry();
+    }
+
+    /* get thunk entry point for connecting rhunk to an IRQ table */
+    inline operator uint32_t(void)
+    {
+        return entry();
+    }
+
+    /* simple test function */
+    inline void call(void)
+    {
+        (((CThunkEntry)(entry()))());
+    }
+
+private:
+    T *_instance;
+    void *_context;
+    union {
+        CCallbackSimple _callback_simple;
+        CCallback _callback;
+    };
+
+    CThunkEntry _entry;
+
+    static void trampoline(CThunkBase *base)
+    {
+        CThunk<T> *self = static_cast<CThunk<T>*>(base);
+        T *instance = self->_instance;
+        void *context = self->_context;
+        CCallback callback = self->_callback;
+
+        if (instance && callback) {
+            (instance->*callback)(context);
+        }
+    }
+
+    inline void init(T *instance, CCallback callback, void *context)
+    {
+        _instance = instance;
+        _context = context;
+        _callback = callback;
+        _trampoline = &trampoline;
+        _entry = 0;
+    }
+};
+
+/**@}*/
+
+/**@}*/
+
+#endif/*__CTHUNK_H__*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CThunkBase.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,78 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2018-2018 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 __CTHUNK_BASE_H__
+#define __CTHUNK_BASE_H__
+
+/* IRQ/Exception compatible thunk entry function */
+typedef void (*CThunkEntry)(void);
+
+class CThunkBase {
+protected:
+    typedef void (*Trampoline)(CThunkBase *);
+
+    Trampoline _trampoline;
+
+    /*
+     * Allocate a CThunkEntry which can be called without arguments
+     *
+     * Calling the CThunkEntry invokes the _trampoline of the
+     * given cthunk. This function traps if there are no more
+     * free thunks.
+     */
+    static CThunkEntry cthunk_alloc(CThunkBase *cthunk);
+
+    /*
+     * Free a cthunk_entry so it can be reused
+     */
+    static void cthunk_free(CThunkEntry cthunk_entry);
+
+private:
+    typedef void (*CthunkFree)(CThunkEntry cthunk_entry);
+
+    /*
+     * Table of thunk functions
+     */
+    static const CThunkEntry _thunk_table[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX];
+
+    /*
+     * Table of active CThunk classes
+     */
+    static CThunkBase *_thunk_storage[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX];
+
+    /*
+     * Lazily initialized free function pointer
+     */
+    static CthunkFree _cthunk_free_real;
+
+    /*
+     * Actual free function
+     */
+    static void cthunk_free_real(CThunkEntry cthunk_entry);
+
+    /*
+     * Template function which stored in the _thunk_table
+     */
+    template<int N>
+    static void thunk_entry()
+    {
+        _thunk_storage[N]->_trampoline(_thunk_storage[N]);
+    }
+};
+
+#endif/*__CTHUNK_BASE_H__*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CallChain.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,265 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_CALLCHAIN_H
+#define MBED_CALLCHAIN_H
+
+#include "platform/Callback.h"
+#include "platform/mbed_toolchain.h"
+#include "platform/NonCopyable.h"
+#include <string.h>
+
+namespace mbed {
+
+
+typedef Callback<void()> *pFunctionPointer_t;
+class CallChainLink;
+
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_CallChain CallChain class
+ * @{
+ */
+
+/** Group one or more functions in an instance of a CallChain, then call them in
+ * sequence using CallChain::call(). Used mostly by the interrupt chaining code,
+ * but can be used for other purposes.
+ *
+ * @deprecated Do not use this class. This class is not part of the public API of mbed-os and is being removed in the future.
+ * @note Synchronization level: Not protected
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ *
+ * CallChain chain;
+ *
+ * void first(void) {
+ *     printf("'first' function.\n");
+ * }
+ *
+ * void second(void) {
+ *     printf("'second' function.\n");
+ * }
+ *
+ * class Test {
+ * public:
+ *     void f(void) {
+ *         printf("A::f (class member).\n");
+ *     }
+ * };
+ *
+ * int main() {
+ *     Test test;
+ *
+ *     chain.add(second);
+ *     chain.add_front(first);
+ *     chain.add(&test, &Test::f);
+ *     chain.call();
+ * }
+ * @endcode
+ */
+class CallChain : private NonCopyable<CallChain> {
+public:
+    /** Create an empty chain
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     *  @param size (optional) Initial size of the chain
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    CallChain(int size = 4);
+
+    /** Create an empty chain
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    virtual ~CallChain();
+
+    /** Add a function at the end of the chain
+     *
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     *  @param func A pointer to a void function
+     *
+     *  @returns
+     *  The function object created for 'func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    pFunctionPointer_t add(Callback<void()> func);
+
+    /** Add a function at the end of the chain
+     *
+     *  @param obj pointer to the object to call the member function on
+     *  @param method pointer to the member function to be called
+     *
+     *  @returns
+     *  The function object created for 'obj' and 'method'
+     *
+     *  @deprecated
+     *  The add function does not support cv-qualifiers. Replaced by
+     *  add(callback(obj, method)).
+     */
+    template<typename T, typename M>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "The add function does not support cv-qualifiers. Replaced by "
+                          "add(callback(obj, method)).")
+    pFunctionPointer_t add(T *obj, M method)
+    {
+        return add(callback(obj, method));
+    }
+
+    /** Add a function at the beginning of the chain
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     *
+     *  @param func A pointer to a void function
+     *
+     *  @returns
+     *  The function object created for 'func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    pFunctionPointer_t add_front(Callback<void()> func);
+
+    /** Add a function at the beginning of the chain
+     *
+     *  @param obj pointer to the object to call the member function on
+     *  @param method pointer to the member function to be called
+     *
+     *  @returns
+     *  The function object created for the object and method pointers
+     *
+     *  @deprecated
+     *  The add_front function does not support cv-qualifiers. Replaced by
+     *  add_front(callback(obj, method)).
+     */
+    template<typename T, typename M>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "The add_front function does not support cv-qualifiers. Replaced by "
+                          "add_front(callback(obj, method)).")
+    pFunctionPointer_t add_front(T *obj, M method)
+    {
+        return add_front(callback(obj, method));
+    }
+
+    /** Get the number of functions in the chain
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    int size() const;
+
+    /** Get a function object from the chain
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     *  @param i function object index
+     *
+     *  @returns
+     *  The function object at position 'i' in the chain
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    pFunctionPointer_t get(int i) const;
+
+    /** Look for a function object in the call chain
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     *  @param f the function object to search
+     *
+     *  @returns
+     *  The index of the function object if found, -1 otherwise.
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    int find(pFunctionPointer_t f) const;
+
+    /** Clear the call chain (remove all functions in the chain).
+     *  @deprecated Do not use this function. This class is not part of the public API of mbed-os and is being removed in the future.
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    void clear();
+
+    /** Remove a function object from the chain
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     *  @arg f the function object to remove
+     *
+     *  @returns
+     *  true if the function object was found and removed, false otherwise.
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    bool remove(pFunctionPointer_t f);
+
+    /** Call all the functions in the chain in sequence
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    void call();
+
+    /**
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    void operator()(void)
+    {
+        call();
+    }
+
+    /**
+     *  @deprecated
+     *  Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future.
+     *
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the "
+                          "public API of mbed-os and is being removed in the future.")
+    pFunctionPointer_t operator [](int i) const
+    {
+        return get(i);
+    }
+
+private:
+    CallChainLink *_chain;
+};
+
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Callback.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,4939 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_CALLBACK_H
+#define MBED_CALLBACK_H
+
+#include <string.h>
+#include <stdint.h>
+#include <new>
+#include "platform/mbed_assert.h"
+#include "platform/mbed_toolchain.h"
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_Callback Callback class
+ * @{
+ */
+
+/** Callback class based on template specialization
+ *
+ * @note Synchronization level: Not protected
+ */
+template <typename F>
+class Callback;
+
+// Internal sfinae declarations
+//
+// These are used to eliminate overloads based on type attributes
+// 1. Does a function object have a call operator
+// 2. Does a function object fit in the available storage
+//
+// These eliminations are handled cleanly by the compiler and avoid
+// massive and misleading error messages when confronted with an
+// invalid type (or worse, runtime failures)
+namespace detail {
+struct nil {};
+
+template <bool B, typename R = nil>
+struct enable_if {
+    typedef R type;
+};
+
+template <typename R>
+struct enable_if<false, R> {};
+
+template <typename M, M>
+struct is_type {
+    static const bool value = true;
+};
+}
+
+#define MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)                            \
+    typename detail::enable_if<                                             \
+            detail::is_type<M, &F::operator()>::value &&                    \
+            sizeof(F) <= sizeof(uintptr_t)                                  \
+        >::type = detail::nil()
+
+/** Callback class based on template specialization
+ *
+ * @note Synchronization level: Not protected
+ */
+template <typename R>
+class Callback<R()> {
+public:
+    /** Create a Callback with a static function
+     *  @param func     Static function to attach
+     */
+    Callback(R(*func)() = 0)
+    {
+        if (!func) {
+            memset(this, 0, sizeof(Callback));
+        } else {
+            generate(func);
+        }
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     */
+    Callback(const Callback<R()> &func)
+    {
+        if (func._ops) {
+            func._ops->move(this, &func);
+        }
+        _ops = func._ops;
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(U *obj, R(T::*method)())
+    {
+        generate(method_context<T, R(T::*)()>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const U *obj, R(T::*method)() const)
+    {
+        generate(method_context<const T, R(T::*)() const>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(volatile U *obj, R(T::*method)() volatile)
+    {
+        generate(method_context<volatile T, R(T::*)() volatile>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const volatile U *obj, R(T::*method)() const volatile)
+    {
+        generate(method_context<const volatile T, R(T::*)() const volatile>(obj, method));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(T *), U *arg)
+    {
+        generate(function_context<R(*)(T *), T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const T *), const U *arg)
+    {
+        generate(function_context<R(*)(const T *), const T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(volatile T *), volatile U *arg)
+    {
+        generate(function_context<R(*)(volatile T *), volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const volatile T *), const volatile U *arg)
+    {
+        generate(function_context<R(*)(const volatile T *), const volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)()))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() const))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() const volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(U *obj, R(*func)(T *))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const U *obj, R(*func)(const T *))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(volatile U *obj, R(*func)(volatile T *))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const volatile U *obj, R(*func)(const volatile T *))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Destroy a callback
+     */
+    ~Callback()
+    {
+        if (_ops) {
+            _ops->dtor(this);
+        }
+    }
+
+    /** Attach a static function
+     *  @param func     Static function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)())
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const Callback<R()> &func)
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(U *obj, R(T::*method)())
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const U *obj, R(T::*method)() const)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile U *obj, R(T::*method)() volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile U *obj, R(T::*method)() const volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(T *), U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const T *), const U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(volatile T *), volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const volatile T *), const volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a function object
+     *  @param f     Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)()))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f     Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() const))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() const volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(U *obj, R(*func)(T *))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const U *obj, R(*func)(const T *))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(volatile U *obj, R(*func)(volatile T *))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const volatile U *obj, R(*func)(const volatile T *))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Assign a callback
+     */
+    Callback &operator=(const Callback &that)
+    {
+        if (this != &that) {
+            this->~Callback();
+            new (this) Callback(that);
+        }
+
+        return *this;
+    }
+
+    /** Call the attached function
+     */
+    R call() const
+    {
+        MBED_ASSERT(_ops);
+        return _ops->call(this);
+    }
+
+    /** Call the attached function
+     */
+    R operator()() const
+    {
+        return call();
+    }
+
+    /** Test if function has been attached
+     */
+    operator bool() const
+    {
+        return _ops;
+    }
+
+    /** Test for equality
+     */
+    friend bool operator==(const Callback &l, const Callback &r)
+    {
+        return memcmp(&l, &r, sizeof(Callback)) == 0;
+    }
+
+    /** Test for inequality
+     */
+    friend bool operator!=(const Callback &l, const Callback &r)
+    {
+        return !(l == r);
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Callback to call passed as void pointer
+     *  @return the value as determined by func which is of
+     *      type and determined by the signature of func
+     */
+    static R thunk(void *func)
+    {
+        return static_cast<Callback *>(func)->call();
+    }
+
+private:
+    // Stored as pointer to function and pointer to optional object
+    // Function pointer is stored as union of possible function types
+    // to guarantee proper size and alignment
+    struct _class;
+    union {
+        void (*_staticfunc)();
+        void (*_boundfunc)(_class *);
+        void (_class::*_methodfunc)();
+    } _func;
+    void *_obj;
+
+    // Dynamically dispatched operations
+    const struct ops {
+        R(*call)(const void *);
+        void (*move)(void *, const void *);
+        void (*dtor)(void *);
+    } *_ops;
+
+    // Generate operations for function object
+    template <typename F>
+    void generate(const F &f)
+    {
+        static const ops ops = {
+            &Callback::function_call<F>,
+            &Callback::function_move<F>,
+            &Callback::function_dtor<F>,
+        };
+
+        MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F),
+                           "Type F must not exceed the size of the Callback class");
+        memset(this, 0, sizeof(Callback));
+        new (this) F(f);
+        _ops = &ops;
+    }
+
+    // Function attributes
+    template <typename F>
+    static R function_call(const void *p)
+    {
+        return (*(F *)p)();
+    }
+
+    template <typename F>
+    static void function_move(void *d, const void *p)
+    {
+        new (d) F(*(F *)p);
+    }
+
+    template <typename F>
+    static void function_dtor(void *p)
+    {
+        ((F *)p)->~F();
+    }
+
+    // Wrappers for functions with context
+    template <typename O, typename M>
+    struct method_context {
+        M method;
+        O *obj;
+
+        method_context(O *obj, M method)
+            : method(method), obj(obj) {}
+
+        R operator()() const
+        {
+            return (obj->*method)();
+        }
+    };
+
+    template <typename F, typename A>
+    struct function_context {
+        F func;
+        A *arg;
+
+        function_context(F func, A *arg)
+            : func(func), arg(arg) {}
+
+        R operator()() const
+        {
+            return func(arg);
+        }
+    };
+};
+
+/** Callback class based on template specialization
+ *
+ * @note Synchronization level: Not protected
+ */
+template <typename R, typename A0>
+class Callback<R(A0)> {
+public:
+    /** Create a Callback with a static function
+     *  @param func     Static function to attach
+     */
+    Callback(R(*func)(A0) = 0)
+    {
+        if (!func) {
+            memset(this, 0, sizeof(Callback));
+        } else {
+            generate(func);
+        }
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     */
+    Callback(const Callback<R(A0)> &func)
+    {
+        if (func._ops) {
+            func._ops->move(this, &func);
+        }
+        _ops = func._ops;
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(U *obj, R(T::*method)(A0))
+    {
+        generate(method_context<T, R(T::*)(A0)>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const U *obj, R(T::*method)(A0) const)
+    {
+        generate(method_context<const T, R(T::*)(A0) const>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(volatile U *obj, R(T::*method)(A0) volatile)
+    {
+        generate(method_context<volatile T, R(T::*)(A0) volatile>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const volatile U *obj, R(T::*method)(A0) const volatile)
+    {
+        generate(method_context<const volatile T, R(T::*)(A0) const volatile>(obj, method));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(T *, A0), U *arg)
+    {
+        generate(function_context<R(*)(T *, A0), T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const T *, A0), const U *arg)
+    {
+        generate(function_context<R(*)(const T *, A0), const T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(volatile T *, A0), volatile U *arg)
+    {
+        generate(function_context<R(*)(volatile T *, A0), volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const volatile T *, A0), const volatile U *arg)
+    {
+        generate(function_context<R(*)(const volatile T *, A0), const volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0)))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) const))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) const volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(U *obj, R(*func)(T *, A0))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const U *obj, R(*func)(const T *, A0))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(volatile U *obj, R(*func)(volatile T *, A0))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const volatile U *obj, R(*func)(const volatile T *, A0))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Destroy a callback
+     */
+    ~Callback()
+    {
+        if (_ops) {
+            _ops->dtor(this);
+        }
+    }
+
+    /** Attach a static function
+     *  @param func     Static function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(A0))
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const Callback<R(A0)> &func)
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(U *obj, R(T::*method)(A0))
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const U *obj, R(T::*method)(A0) const)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile U *obj, R(T::*method)(A0) volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile U *obj, R(T::*method)(A0) const volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(T *, A0), U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const T *, A0), const U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(volatile T *, A0), volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const volatile T *, A0), const volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0)))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) const))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) const volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(U *obj, R(*func)(T *, A0))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const U *obj, R(*func)(const T *, A0))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(volatile U *obj, R(*func)(volatile T *, A0))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const volatile U *obj, R(*func)(const volatile T *, A0))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Assign a callback
+     */
+    Callback &operator=(const Callback &that)
+    {
+        if (this != &that) {
+            this->~Callback();
+            new (this) Callback(that);
+        }
+
+        return *this;
+    }
+
+    /** Call the attached function
+     */
+    R call(A0 a0) const
+    {
+        MBED_ASSERT(_ops);
+        return _ops->call(this, a0);
+    }
+
+    /** Call the attached function
+     */
+    R operator()(A0 a0) const
+    {
+        return call(a0);
+    }
+
+    /** Test if function has been attached
+     */
+    operator bool() const
+    {
+        return _ops;
+    }
+
+    /** Test for equality
+     */
+    friend bool operator==(const Callback &l, const Callback &r)
+    {
+        return memcmp(&l, &r, sizeof(Callback)) == 0;
+    }
+
+    /** Test for inequality
+     */
+    friend bool operator!=(const Callback &l, const Callback &r)
+    {
+        return !(l == r);
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Callback to call passed as void pointer
+     *  @param a0 An argument to be called with function func
+     *  @return the value as determined by func which is of
+     *      type and determined by the signature of func
+     */
+    static R thunk(void *func, A0 a0)
+    {
+        return static_cast<Callback *>(func)->call(a0);
+    }
+
+private:
+    // Stored as pointer to function and pointer to optional object
+    // Function pointer is stored as union of possible function types
+    // to guarantee proper size and alignment
+    struct _class;
+    union {
+        void (*_staticfunc)(A0);
+        void (*_boundfunc)(_class *, A0);
+        void (_class::*_methodfunc)(A0);
+    } _func;
+    void *_obj;
+
+    // Dynamically dispatched operations
+    const struct ops {
+        R(*call)(const void *, A0);
+        void (*move)(void *, const void *);
+        void (*dtor)(void *);
+    } *_ops;
+
+    // Generate operations for function object
+    template <typename F>
+    void generate(const F &f)
+    {
+        static const ops ops = {
+            &Callback::function_call<F>,
+            &Callback::function_move<F>,
+            &Callback::function_dtor<F>,
+        };
+
+        MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F),
+                           "Type F must not exceed the size of the Callback class");
+        memset(this, 0, sizeof(Callback));
+        new (this) F(f);
+        _ops = &ops;
+    }
+
+    // Function attributes
+    template <typename F>
+    static R function_call(const void *p, A0 a0)
+    {
+        return (*(F *)p)(a0);
+    }
+
+    template <typename F>
+    static void function_move(void *d, const void *p)
+    {
+        new (d) F(*(F *)p);
+    }
+
+    template <typename F>
+    static void function_dtor(void *p)
+    {
+        ((F *)p)->~F();
+    }
+
+    // Wrappers for functions with context
+    template <typename O, typename M>
+    struct method_context {
+        M method;
+        O *obj;
+
+        method_context(O *obj, M method)
+            : method(method), obj(obj) {}
+
+        R operator()(A0 a0) const
+        {
+            return (obj->*method)(a0);
+        }
+    };
+
+    template <typename F, typename A>
+    struct function_context {
+        F func;
+        A *arg;
+
+        function_context(F func, A *arg)
+            : func(func), arg(arg) {}
+
+        R operator()(A0 a0) const
+        {
+            return func(arg, a0);
+        }
+    };
+};
+
+/** Callback class based on template specialization
+ *
+ * @note Synchronization level: Not protected
+ */
+template <typename R, typename A0, typename A1>
+class Callback<R(A0, A1)> {
+public:
+    /** Create a Callback with a static function
+     *  @param func     Static function to attach
+     */
+    Callback(R(*func)(A0, A1) = 0)
+    {
+        if (!func) {
+            memset(this, 0, sizeof(Callback));
+        } else {
+            generate(func);
+        }
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     */
+    Callback(const Callback<R(A0, A1)> &func)
+    {
+        if (func._ops) {
+            func._ops->move(this, &func);
+        }
+        _ops = func._ops;
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(U *obj, R(T::*method)(A0, A1))
+    {
+        generate(method_context<T, R(T::*)(A0, A1)>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const U *obj, R(T::*method)(A0, A1) const)
+    {
+        generate(method_context<const T, R(T::*)(A0, A1) const>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(volatile U *obj, R(T::*method)(A0, A1) volatile)
+    {
+        generate(method_context<volatile T, R(T::*)(A0, A1) volatile>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const volatile U *obj, R(T::*method)(A0, A1) const volatile)
+    {
+        generate(method_context<const volatile T, R(T::*)(A0, A1) const volatile>(obj, method));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(T *, A0, A1), U *arg)
+    {
+        generate(function_context<R(*)(T *, A0, A1), T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const T *, A0, A1), const U *arg)
+    {
+        generate(function_context<R(*)(const T *, A0, A1), const T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(volatile T *, A0, A1), volatile U *arg)
+    {
+        generate(function_context<R(*)(volatile T *, A0, A1), volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const volatile T *, A0, A1), const volatile U *arg)
+    {
+        generate(function_context<R(*)(const volatile T *, A0, A1), const volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1)))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) const))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) const volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(U *obj, R(*func)(T *, A0, A1))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const U *obj, R(*func)(const T *, A0, A1))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(volatile U *obj, R(*func)(volatile T *, A0, A1))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Destroy a callback
+     */
+    ~Callback()
+    {
+        if (_ops) {
+            _ops->dtor(this);
+        }
+    }
+
+    /** Attach a static function
+     *  @param func     Static function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(A0, A1))
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const Callback<R(A0, A1)> &func)
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(U *obj, R(T::*method)(A0, A1))
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const U *obj, R(T::*method)(A0, A1) const)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile U *obj, R(T::*method)(A0, A1) volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile U *obj, R(T::*method)(A0, A1) const volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(T *, A0, A1), U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const T *, A0, A1), const U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(volatile T *, A0, A1), volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const volatile T *, A0, A1), const volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1)))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) const))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) const volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(U *obj, R(*func)(T *, A0, A1))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const U *obj, R(*func)(const T *, A0, A1))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(volatile U *obj, R(*func)(volatile T *, A0, A1))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const volatile U *obj, R(*func)(const volatile T *, A0, A1))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Assign a callback
+     */
+    Callback &operator=(const Callback &that)
+    {
+        if (this != &that) {
+            this->~Callback();
+            new (this) Callback(that);
+        }
+
+        return *this;
+    }
+
+    /** Call the attached function
+     */
+    R call(A0 a0, A1 a1) const
+    {
+        MBED_ASSERT(_ops);
+        return _ops->call(this, a0, a1);
+    }
+
+    /** Call the attached function
+     */
+    R operator()(A0 a0, A1 a1) const
+    {
+        return call(a0, a1);
+    }
+
+    /** Test if function has been attached
+     */
+    operator bool() const
+    {
+        return _ops;
+    }
+
+    /** Test for equality
+     */
+    friend bool operator==(const Callback &l, const Callback &r)
+    {
+        return memcmp(&l, &r, sizeof(Callback)) == 0;
+    }
+
+    /** Test for inequality
+     */
+    friend bool operator!=(const Callback &l, const Callback &r)
+    {
+        return !(l == r);
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Callback to call passed as void pointer
+     *  @param a0 An argument to be called with function func
+     *  @param a1 An argument to be called with function func
+     *  @return the value as determined by func which is of
+     *      type and determined by the signature of func
+     */
+    static R thunk(void *func, A0 a0, A1 a1)
+    {
+        return static_cast<Callback *>(func)->call(a0, a1);
+    }
+
+private:
+    // Stored as pointer to function and pointer to optional object
+    // Function pointer is stored as union of possible function types
+    // to guarantee proper size and alignment
+    struct _class;
+    union {
+        void (*_staticfunc)(A0, A1);
+        void (*_boundfunc)(_class *, A0, A1);
+        void (_class::*_methodfunc)(A0, A1);
+    } _func;
+    void *_obj;
+
+    // Dynamically dispatched operations
+    const struct ops {
+        R(*call)(const void *, A0, A1);
+        void (*move)(void *, const void *);
+        void (*dtor)(void *);
+    } *_ops;
+
+    // Generate operations for function object
+    template <typename F>
+    void generate(const F &f)
+    {
+        static const ops ops = {
+            &Callback::function_call<F>,
+            &Callback::function_move<F>,
+            &Callback::function_dtor<F>,
+        };
+
+        MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F),
+                           "Type F must not exceed the size of the Callback class");
+        memset(this, 0, sizeof(Callback));
+        new (this) F(f);
+        _ops = &ops;
+    }
+
+    // Function attributes
+    template <typename F>
+    static R function_call(const void *p, A0 a0, A1 a1)
+    {
+        return (*(F *)p)(a0, a1);
+    }
+
+    template <typename F>
+    static void function_move(void *d, const void *p)
+    {
+        new (d) F(*(F *)p);
+    }
+
+    template <typename F>
+    static void function_dtor(void *p)
+    {
+        ((F *)p)->~F();
+    }
+
+    // Wrappers for functions with context
+    template <typename O, typename M>
+    struct method_context {
+        M method;
+        O *obj;
+
+        method_context(O *obj, M method)
+            : method(method), obj(obj) {}
+
+        R operator()(A0 a0, A1 a1) const
+        {
+            return (obj->*method)(a0, a1);
+        }
+    };
+
+    template <typename F, typename A>
+    struct function_context {
+        F func;
+        A *arg;
+
+        function_context(F func, A *arg)
+            : func(func), arg(arg) {}
+
+        R operator()(A0 a0, A1 a1) const
+        {
+            return func(arg, a0, a1);
+        }
+    };
+};
+
+/** Callback class based on template specialization
+ *
+ * @note Synchronization level: Not protected
+ */
+template <typename R, typename A0, typename A1, typename A2>
+class Callback<R(A0, A1, A2)> {
+public:
+    /** Create a Callback with a static function
+     *  @param func     Static function to attach
+     */
+    Callback(R(*func)(A0, A1, A2) = 0)
+    {
+        if (!func) {
+            memset(this, 0, sizeof(Callback));
+        } else {
+            generate(func);
+        }
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     */
+    Callback(const Callback<R(A0, A1, A2)> &func)
+    {
+        if (func._ops) {
+            func._ops->move(this, &func);
+        }
+        _ops = func._ops;
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(U *obj, R(T::*method)(A0, A1, A2))
+    {
+        generate(method_context<T, R(T::*)(A0, A1, A2)>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const U *obj, R(T::*method)(A0, A1, A2) const)
+    {
+        generate(method_context<const T, R(T::*)(A0, A1, A2) const>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(volatile U *obj, R(T::*method)(A0, A1, A2) volatile)
+    {
+        generate(method_context<volatile T, R(T::*)(A0, A1, A2) volatile>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const volatile U *obj, R(T::*method)(A0, A1, A2) const volatile)
+    {
+        generate(method_context<const volatile T, R(T::*)(A0, A1, A2) const volatile>(obj, method));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(T *, A0, A1, A2), U *arg)
+    {
+        generate(function_context<R(*)(T *, A0, A1, A2), T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const T *, A0, A1, A2), const U *arg)
+    {
+        generate(function_context<R(*)(const T *, A0, A1, A2), const T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(volatile T *, A0, A1, A2), volatile U *arg)
+    {
+        generate(function_context<R(*)(volatile T *, A0, A1, A2), volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const volatile T *, A0, A1, A2), const volatile U *arg)
+    {
+        generate(function_context<R(*)(const volatile T *, A0, A1, A2), const volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2)))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) const))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) const volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(U *obj, R(*func)(T *, A0, A1, A2))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const U *obj, R(*func)(const T *, A0, A1, A2))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Destroy a callback
+     */
+    ~Callback()
+    {
+        if (_ops) {
+            _ops->dtor(this);
+        }
+    }
+
+    /** Attach a static function
+     *  @param func     Static function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(A0, A1, A2))
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const Callback<R(A0, A1, A2)> &func)
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(U *obj, R(T::*method)(A0, A1, A2))
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const U *obj, R(T::*method)(A0, A1, A2) const)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile U *obj, R(T::*method)(A0, A1, A2) volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile U *obj, R(T::*method)(A0, A1, A2) const volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(T *, A0, A1, A2), U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const T *, A0, A1, A2), const U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(volatile T *, A0, A1, A2), volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const volatile T *, A0, A1, A2), const volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2)))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) const))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) const volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(U *obj, R(*func)(T *, A0, A1, A2))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const U *obj, R(*func)(const T *, A0, A1, A2))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(volatile U *obj, R(*func)(volatile T *, A0, A1, A2))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Assign a callback
+     */
+    Callback &operator=(const Callback &that)
+    {
+        if (this != &that) {
+            this->~Callback();
+            new (this) Callback(that);
+        }
+
+        return *this;
+    }
+
+    /** Call the attached function
+     */
+    R call(A0 a0, A1 a1, A2 a2) const
+    {
+        MBED_ASSERT(_ops);
+        return _ops->call(this, a0, a1, a2);
+    }
+
+    /** Call the attached function
+     */
+    R operator()(A0 a0, A1 a1, A2 a2) const
+    {
+        return call(a0, a1, a2);
+    }
+
+    /** Test if function has been attached
+     */
+    operator bool() const
+    {
+        return _ops;
+    }
+
+    /** Test for equality
+     */
+    friend bool operator==(const Callback &l, const Callback &r)
+    {
+        return memcmp(&l, &r, sizeof(Callback)) == 0;
+    }
+
+    /** Test for inequality
+     */
+    friend bool operator!=(const Callback &l, const Callback &r)
+    {
+        return !(l == r);
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Callback to call passed as void pointer
+     *  @param a0 An argument to be called with function func
+     *  @param a1 An argument to be called with function func
+     *  @param a2 An argument to be called with function func
+     *  @return the value as determined by func which is of
+     *      type and determined by the signature of func
+     */
+    static R thunk(void *func, A0 a0, A1 a1, A2 a2)
+    {
+        return static_cast<Callback *>(func)->call(a0, a1, a2);
+    }
+
+private:
+    // Stored as pointer to function and pointer to optional object
+    // Function pointer is stored as union of possible function types
+    // to guarantee proper size and alignment
+    struct _class;
+    union {
+        void (*_staticfunc)(A0, A1, A2);
+        void (*_boundfunc)(_class *, A0, A1, A2);
+        void (_class::*_methodfunc)(A0, A1, A2);
+    } _func;
+    void *_obj;
+
+    // Dynamically dispatched operations
+    const struct ops {
+        R(*call)(const void *, A0, A1, A2);
+        void (*move)(void *, const void *);
+        void (*dtor)(void *);
+    } *_ops;
+
+    // Generate operations for function object
+    template <typename F>
+    void generate(const F &f)
+    {
+        static const ops ops = {
+            &Callback::function_call<F>,
+            &Callback::function_move<F>,
+            &Callback::function_dtor<F>,
+        };
+
+        MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F),
+                           "Type F must not exceed the size of the Callback class");
+        memset(this, 0, sizeof(Callback));
+        new (this) F(f);
+        _ops = &ops;
+    }
+
+    // Function attributes
+    template <typename F>
+    static R function_call(const void *p, A0 a0, A1 a1, A2 a2)
+    {
+        return (*(F *)p)(a0, a1, a2);
+    }
+
+    template <typename F>
+    static void function_move(void *d, const void *p)
+    {
+        new (d) F(*(F *)p);
+    }
+
+    template <typename F>
+    static void function_dtor(void *p)
+    {
+        ((F *)p)->~F();
+    }
+
+    // Wrappers for functions with context
+    template <typename O, typename M>
+    struct method_context {
+        M method;
+        O *obj;
+
+        method_context(O *obj, M method)
+            : method(method), obj(obj) {}
+
+        R operator()(A0 a0, A1 a1, A2 a2) const
+        {
+            return (obj->*method)(a0, a1, a2);
+        }
+    };
+
+    template <typename F, typename A>
+    struct function_context {
+        F func;
+        A *arg;
+
+        function_context(F func, A *arg)
+            : func(func), arg(arg) {}
+
+        R operator()(A0 a0, A1 a1, A2 a2) const
+        {
+            return func(arg, a0, a1, a2);
+        }
+    };
+};
+
+/** Callback class based on template specialization
+ *
+ * @note Synchronization level: Not protected
+ */
+template <typename R, typename A0, typename A1, typename A2, typename A3>
+class Callback<R(A0, A1, A2, A3)> {
+public:
+    /** Create a Callback with a static function
+     *  @param func     Static function to attach
+     */
+    Callback(R(*func)(A0, A1, A2, A3) = 0)
+    {
+        if (!func) {
+            memset(this, 0, sizeof(Callback));
+        } else {
+            generate(func);
+        }
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     */
+    Callback(const Callback<R(A0, A1, A2, A3)> &func)
+    {
+        if (func._ops) {
+            func._ops->move(this, &func);
+        }
+        _ops = func._ops;
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(U *obj, R(T::*method)(A0, A1, A2, A3))
+    {
+        generate(method_context<T, R(T::*)(A0, A1, A2, A3)>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const U *obj, R(T::*method)(A0, A1, A2, A3) const)
+    {
+        generate(method_context<const T, R(T::*)(A0, A1, A2, A3) const>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3) volatile)
+    {
+        generate(method_context<volatile T, R(T::*)(A0, A1, A2, A3) volatile>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3) const volatile)
+    {
+        generate(method_context<const volatile T, R(T::*)(A0, A1, A2, A3) const volatile>(obj, method));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(T *, A0, A1, A2, A3), U *arg)
+    {
+        generate(function_context<R(*)(T *, A0, A1, A2, A3), T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const T *, A0, A1, A2, A3), const U *arg)
+    {
+        generate(function_context<R(*)(const T *, A0, A1, A2, A3), const T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(volatile T *, A0, A1, A2, A3), volatile U *arg)
+    {
+        generate(function_context<R(*)(volatile T *, A0, A1, A2, A3), volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const volatile T *, A0, A1, A2, A3), const volatile U *arg)
+    {
+        generate(function_context<R(*)(const volatile T *, A0, A1, A2, A3), const volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3)))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) const))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) const volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(U *obj, R(*func)(T *, A0, A1, A2, A3))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const U *obj, R(*func)(const T *, A0, A1, A2, A3))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Destroy a callback
+     */
+    ~Callback()
+    {
+        if (_ops) {
+            _ops->dtor(this);
+        }
+    }
+
+    /** Attach a static function
+     *  @param func     Static function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(A0, A1, A2, A3))
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const Callback<R(A0, A1, A2, A3)> &func)
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(U *obj, R(T::*method)(A0, A1, A2, A3))
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const U *obj, R(T::*method)(A0, A1, A2, A3) const)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile U *obj, R(T::*method)(A0, A1, A2, A3) volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile U *obj, R(T::*method)(A0, A1, A2, A3) const volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(T *, A0, A1, A2, A3), U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const T *, A0, A1, A2, A3), const U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(volatile T *, A0, A1, A2, A3), volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const volatile T *, A0, A1, A2, A3), const volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3)))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) const))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) const volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(U *obj, R(*func)(T *, A0, A1, A2, A3))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const U *obj, R(*func)(const T *, A0, A1, A2, A3))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Assign a callback
+     */
+    Callback &operator=(const Callback &that)
+    {
+        if (this != &that) {
+            this->~Callback();
+            new (this) Callback(that);
+        }
+
+        return *this;
+    }
+
+    /** Call the attached function
+     */
+    R call(A0 a0, A1 a1, A2 a2, A3 a3) const
+    {
+        MBED_ASSERT(_ops);
+        return _ops->call(this, a0, a1, a2, a3);
+    }
+
+    /** Call the attached function
+     */
+    R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const
+    {
+        return call(a0, a1, a2, a3);
+    }
+
+    /** Test if function has been attached
+     */
+    operator bool() const
+    {
+        return _ops;
+    }
+
+    /** Test for equality
+     */
+    friend bool operator==(const Callback &l, const Callback &r)
+    {
+        return memcmp(&l, &r, sizeof(Callback)) == 0;
+    }
+
+    /** Test for inequality
+     */
+    friend bool operator!=(const Callback &l, const Callback &r)
+    {
+        return !(l == r);
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Callback to call passed as void pointer
+     *  @param a0 An argument to be called with function func
+     *  @param a1 An argument to be called with function func
+     *  @param a2 An argument to be called with function func
+     *  @param a3 An argument to be called with function func
+     *  @return the value as determined by func which is of
+     *      type and determined by the signature of func
+     */
+    static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3)
+    {
+        return static_cast<Callback *>(func)->call(a0, a1, a2, a3);
+    }
+
+private:
+    // Stored as pointer to function and pointer to optional object
+    // Function pointer is stored as union of possible function types
+    // to guarantee proper size and alignment
+    struct _class;
+    union {
+        void (*_staticfunc)(A0, A1, A2, A3);
+        void (*_boundfunc)(_class *, A0, A1, A2, A3);
+        void (_class::*_methodfunc)(A0, A1, A2, A3);
+    } _func;
+    void *_obj;
+
+    // Dynamically dispatched operations
+    const struct ops {
+        R(*call)(const void *, A0, A1, A2, A3);
+        void (*move)(void *, const void *);
+        void (*dtor)(void *);
+    } *_ops;
+
+    // Generate operations for function object
+    template <typename F>
+    void generate(const F &f)
+    {
+        static const ops ops = {
+            &Callback::function_call<F>,
+            &Callback::function_move<F>,
+            &Callback::function_dtor<F>,
+        };
+
+        MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F),
+                           "Type F must not exceed the size of the Callback class");
+        memset(this, 0, sizeof(Callback));
+        new (this) F(f);
+        _ops = &ops;
+    }
+
+    // Function attributes
+    template <typename F>
+    static R function_call(const void *p, A0 a0, A1 a1, A2 a2, A3 a3)
+    {
+        return (*(F *)p)(a0, a1, a2, a3);
+    }
+
+    template <typename F>
+    static void function_move(void *d, const void *p)
+    {
+        new (d) F(*(F *)p);
+    }
+
+    template <typename F>
+    static void function_dtor(void *p)
+    {
+        ((F *)p)->~F();
+    }
+
+    // Wrappers for functions with context
+    template <typename O, typename M>
+    struct method_context {
+        M method;
+        O *obj;
+
+        method_context(O *obj, M method)
+            : method(method), obj(obj) {}
+
+        R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const
+        {
+            return (obj->*method)(a0, a1, a2, a3);
+        }
+    };
+
+    template <typename F, typename A>
+    struct function_context {
+        F func;
+        A *arg;
+
+        function_context(F func, A *arg)
+            : func(func), arg(arg) {}
+
+        R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const
+        {
+            return func(arg, a0, a1, a2, a3);
+        }
+    };
+};
+
+/** Callback class based on template specialization
+ *
+ * @note Synchronization level: Not protected
+ */
+template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+class Callback<R(A0, A1, A2, A3, A4)> {
+public:
+    /** Create a Callback with a static function
+     *  @param func     Static function to attach
+     */
+    Callback(R(*func)(A0, A1, A2, A3, A4) = 0)
+    {
+        if (!func) {
+            memset(this, 0, sizeof(Callback));
+        } else {
+            generate(func);
+        }
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     */
+    Callback(const Callback<R(A0, A1, A2, A3, A4)> &func)
+    {
+        if (func._ops) {
+            func._ops->move(this, &func);
+        }
+        _ops = func._ops;
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(U *obj, R(T::*method)(A0, A1, A2, A3, A4))
+    {
+        generate(method_context<T, R(T::*)(A0, A1, A2, A3, A4)>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const)
+    {
+        generate(method_context<const T, R(T::*)(A0, A1, A2, A3, A4) const>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile)
+    {
+        generate(method_context<volatile T, R(T::*)(A0, A1, A2, A3, A4) volatile>(obj, method));
+    }
+
+    /** Create a Callback with a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     */
+    template<typename T, typename U>
+    Callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile)
+    {
+        generate(method_context<const volatile T, R(T::*)(A0, A1, A2, A3, A4) const volatile>(obj, method));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(T *, A0, A1, A2, A3, A4), U *arg)
+    {
+        generate(function_context<R(*)(T *, A0, A1, A2, A3, A4), T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg)
+    {
+        generate(function_context<R(*)(const T *, A0, A1, A2, A3, A4), const T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg)
+    {
+        generate(function_context<R(*)(volatile T *, A0, A1, A2, A3, A4), volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     */
+    template<typename T, typename U>
+    Callback(R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg)
+    {
+        generate(function_context<R(*)(const volatile T *, A0, A1, A2, A3, A4), const volatile T>(func, arg));
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4)))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) const))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     */
+    template <typename F>
+    Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) const volatile))
+    {
+        generate(f);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(U *obj, R(*func)(T *, A0, A1, A2, A3, A4))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Create a Callback with a static function and bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to Callback(func, arg)
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to Callback(func, arg)")
+    Callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4))
+    {
+        new (this) Callback(func, obj);
+    }
+
+    /** Destroy a callback
+     */
+    ~Callback()
+    {
+        if (_ops) {
+            _ops->dtor(this);
+        }
+    }
+
+    /** Attach a static function
+     *  @param func     Static function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(A0, A1, A2, A3, A4))
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a Callback
+     *  @param func     The Callback to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const Callback<R(A0, A1, A2, A3, A4)> &func)
+    {
+        this->~Callback();
+        new (this) Callback(func);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(U *obj, R(T::*method)(A0, A1, A2, A3, A4))
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a member function
+     *  @param obj      Pointer to object to invoke member function on
+     *  @param method   Member function to attach
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template<typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile)
+    {
+        this->~Callback();
+        new (this) Callback(obj, method);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(T *, A0, A1, A2, A3, A4), U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param func     Static function to attach
+     *  @param arg      Pointer argument to function
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg)
+    {
+        this->~Callback();
+        new (this) Callback(func, arg);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4)))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) const))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a function object
+     *  @param f Function object to attach
+     *  @note The function object is limited to a single word of storage
+     *  @deprecated
+     *      Replaced by simple assignment 'Callback cb = func'
+     */
+    template <typename F>
+    MBED_DEPRECATED_SINCE("mbed-os-5.4",
+                          "Replaced by simple assignment 'Callback cb = func")
+    void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) const volatile))
+    {
+        this->~Callback();
+        new (this) Callback(f);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(U *obj, R(*func)(T *, A0, A1, A2, A3, A4))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Attach a static function with a bound pointer
+     *  @param obj  Pointer to object to bind to function
+     *  @param func Static function to attach
+     *  @deprecated
+     *      Arguments to callback have been reordered to attach(func, arg)
+     */
+    template <typename T, typename U>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "Arguments to callback have been reordered to attach(func, arg)")
+    void attach(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4))
+    {
+        this->~Callback();
+        new (this) Callback(func, obj);
+    }
+
+    /** Assign a callback
+     */
+    Callback &operator=(const Callback &that)
+    {
+        if (this != &that) {
+            this->~Callback();
+            new (this) Callback(that);
+        }
+
+        return *this;
+    }
+
+    /** Call the attached function
+     */
+    R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const
+    {
+        MBED_ASSERT(_ops);
+        return _ops->call(this, a0, a1, a2, a3, a4);
+    }
+
+    /** Call the attached function
+     */
+    R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const
+    {
+        return call(a0, a1, a2, a3, a4);
+    }
+
+    /** Test if function has been attached
+     */
+    operator bool() const
+    {
+        return _ops;
+    }
+
+    /** Test for equality
+     */
+    friend bool operator==(const Callback &l, const Callback &r)
+    {
+        return memcmp(&l, &r, sizeof(Callback)) == 0;
+    }
+
+    /** Test for inequality
+     */
+    friend bool operator!=(const Callback &l, const Callback &r)
+    {
+        return !(l == r);
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param func Callback to call passed as void pointer
+     *  @param a0 An argument to be called with function func
+     *  @param a1 An argument to be called with function func
+     *  @param a2 An argument to be called with function func
+     *  @param a3 An argument to be called with function func
+     *  @param a4 An argument to be called with function func
+     *  @return the value as determined by func which is of
+     *      type and determined by the signature of func
+     */
+    static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4)
+    {
+        return static_cast<Callback *>(func)->call(a0, a1, a2, a3, a4);
+    }
+
+private:
+    // Stored as pointer to function and pointer to optional object
+    // Function pointer is stored as union of possible function types
+    // to guarantee proper size and alignment
+    struct _class;
+    union {
+        void (*_staticfunc)(A0, A1, A2, A3, A4);
+        void (*_boundfunc)(_class *, A0, A1, A2, A3, A4);
+        void (_class::*_methodfunc)(A0, A1, A2, A3, A4);
+    } _func;
+    void *_obj;
+
+    // Dynamically dispatched operations
+    const struct ops {
+        R(*call)(const void *, A0, A1, A2, A3, A4);
+        void (*move)(void *, const void *);
+        void (*dtor)(void *);
+    } *_ops;
+
+    // Generate operations for function object
+    template <typename F>
+    void generate(const F &f)
+    {
+        static const ops ops = {
+            &Callback::function_call<F>,
+            &Callback::function_move<F>,
+            &Callback::function_dtor<F>,
+        };
+
+        MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F),
+                           "Type F must not exceed the size of the Callback class");
+        memset(this, 0, sizeof(Callback));
+        new (this) F(f);
+        _ops = &ops;
+    }
+
+    // Function attributes
+    template <typename F>
+    static R function_call(const void *p, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4)
+    {
+        return (*(F *)p)(a0, a1, a2, a3, a4);
+    }
+
+    template <typename F>
+    static void function_move(void *d, const void *p)
+    {
+        new (d) F(*(F *)p);
+    }
+
+    template <typename F>
+    static void function_dtor(void *p)
+    {
+        ((F *)p)->~F();
+    }
+
+    // Wrappers for functions with context
+    template <typename O, typename M>
+    struct method_context {
+        M method;
+        O *obj;
+
+        method_context(O *obj, M method)
+            : method(method), obj(obj) {}
+
+        R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const
+        {
+            return (obj->*method)(a0, a1, a2, a3, a4);
+        }
+    };
+
+    template <typename F, typename A>
+    struct function_context {
+        F func;
+        A *arg;
+
+        function_context(F func, A *arg)
+            : func(func), arg(arg) {}
+
+        R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const
+        {
+            return func(arg, a0, a1, a2, a3, a4);
+        }
+    };
+};
+
+// Internally used event type
+typedef Callback<void(int)> event_callback_t;
+
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R>
+Callback<R()> callback(R(*func)() = 0)
+{
+    return Callback<R()>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R>
+Callback<R()> callback(const Callback<R()> &func)
+{
+    return Callback<R()>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R>
+Callback<R()> callback(U *obj, R(T::*method)())
+{
+    return Callback<R()>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R>
+Callback<R()> callback(const U *obj, R(T::*method)() const)
+{
+    return Callback<R()>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R>
+Callback<R()> callback(volatile U *obj, R(T::*method)() volatile)
+{
+    return Callback<R()>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R>
+Callback<R()> callback(const volatile U *obj, R(T::*method)() const volatile)
+{
+    return Callback<R()>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R>
+Callback<R()> callback(R(*func)(T *), U *arg)
+{
+    return Callback<R()>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R>
+Callback<R()> callback(R(*func)(const T *), const U *arg)
+{
+    return Callback<R()>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R>
+Callback<R()> callback(R(*func)(volatile T *), volatile U *arg)
+{
+    return Callback<R()>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R>
+Callback<R()> callback(R(*func)(const volatile T *), const volatile U *arg)
+{
+    return Callback<R()>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R()> callback(U *obj, R(*func)(T *))
+{
+    return Callback<R()>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R()> callback(const U *obj, R(*func)(const T *))
+{
+    return Callback<R()>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R()> callback(volatile U *obj, R(*func)(volatile T *))
+{
+    return Callback<R()>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R()> callback(const volatile U *obj, R(*func)(const volatile T *))
+{
+    return Callback<R()>(func, obj);
+}
+
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0>
+Callback<R(A0)> callback(R(*func)(A0) = 0)
+{
+    return Callback<R(A0)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0>
+Callback<R(A0)> callback(const Callback<R(A0)> &func)
+{
+    return Callback<R(A0)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0>
+Callback<R(A0)> callback(U *obj, R(T::*method)(A0))
+{
+    return Callback<R(A0)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0>
+Callback<R(A0)> callback(const U *obj, R(T::*method)(A0) const)
+{
+    return Callback<R(A0)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0>
+Callback<R(A0)> callback(volatile U *obj, R(T::*method)(A0) volatile)
+{
+    return Callback<R(A0)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0>
+Callback<R(A0)> callback(const volatile U *obj, R(T::*method)(A0) const volatile)
+{
+    return Callback<R(A0)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0>
+Callback<R(A0)> callback(R(*func)(T *, A0), U *arg)
+{
+    return Callback<R(A0)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0>
+Callback<R(A0)> callback(R(*func)(const T *, A0), const U *arg)
+{
+    return Callback<R(A0)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0>
+Callback<R(A0)> callback(R(*func)(volatile T *, A0), volatile U *arg)
+{
+    return Callback<R(A0)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0>
+Callback<R(A0)> callback(R(*func)(const volatile T *, A0), const volatile U *arg)
+{
+    return Callback<R(A0)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0)> callback(U *obj, R(*func)(T *, A0))
+{
+    return Callback<R(A0)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0)> callback(const U *obj, R(*func)(const T *, A0))
+{
+    return Callback<R(A0)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0)> callback(volatile U *obj, R(*func)(volatile T *, A0))
+{
+    return Callback<R(A0)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0)> callback(const volatile U *obj, R(*func)(const volatile T *, A0))
+{
+    return Callback<R(A0)>(func, obj);
+}
+
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(R(*func)(A0, A1) = 0)
+{
+    return Callback<R(A0, A1)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(const Callback<R(A0, A1)> &func)
+{
+    return Callback<R(A0, A1)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(U *obj, R(T::*method)(A0, A1))
+{
+    return Callback<R(A0, A1)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(const U *obj, R(T::*method)(A0, A1) const)
+{
+    return Callback<R(A0, A1)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(volatile U *obj, R(T::*method)(A0, A1) volatile)
+{
+    return Callback<R(A0, A1)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(const volatile U *obj, R(T::*method)(A0, A1) const volatile)
+{
+    return Callback<R(A0, A1)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(R(*func)(T *, A0, A1), U *arg)
+{
+    return Callback<R(A0, A1)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(R(*func)(const T *, A0, A1), const U *arg)
+{
+    return Callback<R(A0, A1)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(R(*func)(volatile T *, A0, A1), volatile U *arg)
+{
+    return Callback<R(A0, A1)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1>
+Callback<R(A0, A1)> callback(R(*func)(const volatile T *, A0, A1), const volatile U *arg)
+{
+    return Callback<R(A0, A1)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1)> callback(U *obj, R(*func)(T *, A0, A1))
+{
+    return Callback<R(A0, A1)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1)> callback(const U *obj, R(*func)(const T *, A0, A1))
+{
+    return Callback<R(A0, A1)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1)> callback(volatile U *obj, R(*func)(volatile T *, A0, A1))
+{
+    return Callback<R(A0, A1)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1)> callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1))
+{
+    return Callback<R(A0, A1)>(func, obj);
+}
+
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(R(*func)(A0, A1, A2) = 0)
+{
+    return Callback<R(A0, A1, A2)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(const Callback<R(A0, A1, A2)> &func)
+{
+    return Callback<R(A0, A1, A2)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(U *obj, R(T::*method)(A0, A1, A2))
+{
+    return Callback<R(A0, A1, A2)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(const U *obj, R(T::*method)(A0, A1, A2) const)
+{
+    return Callback<R(A0, A1, A2)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(volatile U *obj, R(T::*method)(A0, A1, A2) volatile)
+{
+    return Callback<R(A0, A1, A2)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(const volatile U *obj, R(T::*method)(A0, A1, A2) const volatile)
+{
+    return Callback<R(A0, A1, A2)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(R(*func)(T *, A0, A1, A2), U *arg)
+{
+    return Callback<R(A0, A1, A2)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(R(*func)(const T *, A0, A1, A2), const U *arg)
+{
+    return Callback<R(A0, A1, A2)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(R(*func)(volatile T *, A0, A1, A2), volatile U *arg)
+{
+    return Callback<R(A0, A1, A2)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2>
+Callback<R(A0, A1, A2)> callback(R(*func)(const volatile T *, A0, A1, A2), const volatile U *arg)
+{
+    return Callback<R(A0, A1, A2)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2)> callback(U *obj, R(*func)(T *, A0, A1, A2))
+{
+    return Callback<R(A0, A1, A2)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2)> callback(const U *obj, R(*func)(const T *, A0, A1, A2))
+{
+    return Callback<R(A0, A1, A2)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2)> callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2))
+{
+    return Callback<R(A0, A1, A2)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2)> callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2))
+{
+    return Callback<R(A0, A1, A2)>(func, obj);
+}
+
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(R(*func)(A0, A1, A2, A3) = 0)
+{
+    return Callback<R(A0, A1, A2, A3)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(const Callback<R(A0, A1, A2, A3)> &func)
+{
+    return Callback<R(A0, A1, A2, A3)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(U *obj, R(T::*method)(A0, A1, A2, A3))
+{
+    return Callback<R(A0, A1, A2, A3)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(const U *obj, R(T::*method)(A0, A1, A2, A3) const)
+{
+    return Callback<R(A0, A1, A2, A3)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3) volatile)
+{
+    return Callback<R(A0, A1, A2, A3)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3) const volatile)
+{
+    return Callback<R(A0, A1, A2, A3)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(R(*func)(T *, A0, A1, A2, A3), U *arg)
+{
+    return Callback<R(A0, A1, A2, A3)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(R(*func)(const T *, A0, A1, A2, A3), const U *arg)
+{
+    return Callback<R(A0, A1, A2, A3)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(R(*func)(volatile T *, A0, A1, A2, A3), volatile U *arg)
+{
+    return Callback<R(A0, A1, A2, A3)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+Callback<R(A0, A1, A2, A3)> callback(R(*func)(const volatile T *, A0, A1, A2, A3), const volatile U *arg)
+{
+    return Callback<R(A0, A1, A2, A3)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2, A3)> callback(U *obj, R(*func)(T *, A0, A1, A2, A3))
+{
+    return Callback<R(A0, A1, A2, A3)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2, A3)> callback(const U *obj, R(*func)(const T *, A0, A1, A2, A3))
+{
+    return Callback<R(A0, A1, A2, A3)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2, A3)> callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3))
+{
+    return Callback<R(A0, A1, A2, A3)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2, A3)> callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3))
+{
+    return Callback<R(A0, A1, A2, A3)>(func, obj);
+}
+
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(A0, A1, A2, A3, A4) = 0)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @return         Callback with inferred type
+ */
+template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(const Callback<R(A0, A1, A2, A3, A4)> &func)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(U *obj, R(T::*method)(A0, A1, A2, A3, A4))
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj      Optional pointer to object to bind to function
+ *  @param method   Member function to attach
+ *  @return         Callback with inferred type
+ */
+template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(obj, method);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(T *, A0, A1, A2, A3, A4), U *arg)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param func     Static function to attach
+ *  @param arg      Pointer argument to function
+ *  @return         Callback with inferred type
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg)
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func, arg);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2, A3, A4)> callback(U *obj, R(*func)(T *, A0, A1, A2, A3, A4))
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2, A3, A4)> callback(const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4))
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2, A3, A4)> callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4))
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func, obj);
+}
+
+/** Create a callback class with type inferred from the arguments
+ *
+ *  @param obj  Optional pointer to object to bind to function
+ *  @param func Static function to attach
+ *  @return     Callback with inferred type
+ *  @deprecated
+ *      Arguments to callback have been reordered to callback(func, arg)
+ */
+template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
+MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                      "Arguments to callback have been reordered to callback(func, arg)")
+Callback<R(A0, A1, A2, A3, A4)> callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4))
+{
+    return Callback<R(A0, A1, A2, A3, A4)>(func, obj);
+}
+
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CircularBuffer.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,215 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2015 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_CIRCULARBUFFER_H
+#define MBED_CIRCULARBUFFER_H
+
+#include "platform/mbed_critical.h"
+#include "platform/mbed_assert.h"
+
+namespace mbed {
+
+namespace internal {
+/* Detect if CounterType of the Circular buffer is of unsigned type. */
+template<typename T>
+struct is_unsigned {
+    static const bool value = false;
+};
+template<>
+struct is_unsigned<unsigned char> {
+    static const bool value = true;
+};
+template<>
+struct is_unsigned<unsigned short> {
+    static const bool value = true;
+};
+template<>
+struct is_unsigned<unsigned int> {
+    static const bool value = true;
+};
+template<>
+struct is_unsigned<unsigned long> {
+    static const bool value = true;
+};
+template<>
+struct is_unsigned<unsigned long long> {
+    static const bool value = true;
+};
+};
+
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_CircularBuffer CircularBuffer functions
+ * @{
+ */
+
+/** Templated Circular buffer class
+ *
+ *  @note Synchronization level: Interrupt safe
+ *  @note CounterType must be unsigned and consistent with BufferSize
+ */
+template<typename T, uint32_t BufferSize, typename CounterType = uint32_t>
+class CircularBuffer {
+public:
+    CircularBuffer() : _head(0), _tail(0), _full(false)
+    {
+        MBED_STATIC_ASSERT(
+            internal::is_unsigned<CounterType>::value,
+            "CounterType must be unsigned"
+        );
+
+        MBED_STATIC_ASSERT(
+            (sizeof(CounterType) >= sizeof(uint32_t)) ||
+            (BufferSize < (((uint64_t) 1) << (sizeof(CounterType) * 8))),
+            "Invalid BufferSize for the CounterType"
+        );
+    }
+
+    ~CircularBuffer()
+    {
+    }
+
+    /** Push the transaction to the buffer. This overwrites the buffer if it's
+     *  full
+     *
+     * @param data Data to be pushed to the buffer
+     */
+    void push(const T &data)
+    {
+        core_util_critical_section_enter();
+        if (full()) {
+            _tail++;
+            if (_tail == BufferSize) {
+                _tail = 0;
+            }
+        }
+        _pool[_head++] = data;
+        if (_head == BufferSize) {
+            _head = 0;
+        }
+        if (_head == _tail) {
+            _full = true;
+        }
+        core_util_critical_section_exit();
+    }
+
+    /** Pop the transaction from the buffer
+     *
+     * @param data Data to be popped from the buffer
+     * @return True if the buffer is not empty and data contains a transaction, false otherwise
+     */
+    bool pop(T &data)
+    {
+        bool data_popped = false;
+        core_util_critical_section_enter();
+        if (!empty()) {
+            data = _pool[_tail++];
+            if (_tail == BufferSize) {
+                _tail = 0;
+            }
+            _full = false;
+            data_popped = true;
+        }
+        core_util_critical_section_exit();
+        return data_popped;
+    }
+
+    /** Check if the buffer is empty
+     *
+     * @return True if the buffer is empty, false if not
+     */
+    bool empty() const
+    {
+        core_util_critical_section_enter();
+        bool is_empty = (_head == _tail) && !_full;
+        core_util_critical_section_exit();
+        return is_empty;
+    }
+
+    /** Check if the buffer is full
+     *
+     * @return True if the buffer is full, false if not
+     */
+    bool full() const
+    {
+        core_util_critical_section_enter();
+        bool full = _full;
+        core_util_critical_section_exit();
+        return full;
+    }
+
+    /** Reset the buffer
+     *
+     */
+    void reset()
+    {
+        core_util_critical_section_enter();
+        _head = 0;
+        _tail = 0;
+        _full = false;
+        core_util_critical_section_exit();
+    }
+
+    /** Get the number of elements currently stored in the circular_buffer */
+    CounterType size() const
+    {
+        core_util_critical_section_enter();
+        CounterType elements;
+        if (!_full) {
+            if (_head < _tail) {
+                elements = BufferSize + _head - _tail;
+            } else {
+                elements = _head - _tail;
+            }
+        } else {
+            elements = BufferSize;
+        }
+        core_util_critical_section_exit();
+        return elements;
+    }
+
+    /** Peek into circular buffer without popping
+     *
+     * @param data Data to be peeked from the buffer
+     * @return True if the buffer is not empty and data contains a transaction, false otherwise
+     */
+    bool peek(T &data) const
+    {
+        bool data_updated = false;
+        core_util_critical_section_enter();
+        if (!empty()) {
+            data = _pool[_tail];
+            data_updated = true;
+        }
+        core_util_critical_section_exit();
+        return data_updated;
+    }
+
+private:
+    T _pool[BufferSize];
+    CounterType _head;
+    CounterType _tail;
+    bool _full;
+};
+
+/**@}*/
+
+/**@}*/
+
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CriticalSectionLock.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2017 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_CRITICALSECTIONLOCK_H
+#define MBED_CRITICALSECTIONLOCK_H
+
+#include "platform/mbed_critical.h"
+#include "platform/mbed_toolchain.h"
+
+namespace mbed {
+
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_CriticalSectionLock CriticalSectionLock functions
+ * @{
+ */
+
+/** RAII object for disabling, then restoring, interrupt state
+  * Usage:
+  * @code
+  *
+  * // RAII style usage
+  * unsigned int atomic_counter_increment(unsigned int &counter) {
+  *     CriticalSectionLock lock;
+  *     // Code in this block will run with interrupts disabled
+  *     // Interrupts will be restored to their previous state automatically
+  *     // at the end of function scope
+  *     return ++counter;
+  * }
+  *
+  * // free locking usage
+  * unsigned int atomic_counter_decrement(unsigned int &counter) {
+  *     CriticalSectionLock::enable();
+  *     // Code in this block will run with interrupts disabled
+  *     counter--;
+  *     CriticalSectionLock::disable(); // need explicitly to disable critical section lock
+  *     // interrupts will be restored to their previous state here
+  *     return counter;
+  * }
+  *
+  * @endcode
+  */
+class CriticalSectionLock {
+public:
+    CriticalSectionLock()
+    {
+        core_util_critical_section_enter();
+    }
+
+    ~CriticalSectionLock()
+    {
+        core_util_critical_section_exit();
+    }
+
+    /** Mark the start of a critical section
+     *  @deprecated This function is inconsistent with RAII and is being removed in the future. Replaced by static function CriticalSectionLock::enable.
+     *
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.8",
+                          "This function is inconsistent with RAII and is being removed in the future."
+                          "Replaced by static function CriticalSectionLock::enable.")
+    void lock()
+    {
+        core_util_critical_section_enter();
+    }
+
+    /** Mark the end of a critical section
+     *  @deprecated This function is inconsistent with RAII and is being removed in the future. Replaced by static function CriticalSectionLock::enable.
+     *
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.8",
+                          "This function is inconsistent with RAII and is being removed in the future."
+                          "Replaced by static function CriticalSectionLock::disable.")
+    void unlock()
+    {
+        core_util_critical_section_exit();
+    }
+
+    /** Mark the start of a critical section
+     */
+    static void enable()
+    {
+        core_util_critical_section_enter();
+    }
+
+    /** Mark the end of a critical section
+     */
+    static void disable()
+    {
+        core_util_critical_section_exit();
+    }
+};
+
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DeepSleepLock.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,99 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2017 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_DEEPSLEEPLOCK_H
+#define MBED_DEEPSLEEPLOCK_H
+
+#include <limits.h>
+#include "platform/mbed_power_mgmt.h"
+#include "platform/mbed_critical.h"
+
+namespace mbed {
+
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_DeepSleepLock DeepSleepLock functions
+ * @{
+ */
+
+/** RAII object for disabling, then restoring the deep sleep mode
+  * Usage:
+  * @code
+  *
+  * void f() {
+  *     // some code here
+  *     {
+  *         DeepSleepLock lock;
+  *         // Code in this block will run with the deep sleep mode locked
+  *     }
+  *     // deep sleep mode will be restored to their previous state
+  * }
+  * @endcode
+  */
+class DeepSleepLock {
+private:
+    uint16_t _lock_count;
+
+public:
+    DeepSleepLock(): _lock_count(1)
+    {
+        sleep_manager_lock_deep_sleep();
+    }
+
+    ~DeepSleepLock()
+    {
+        if (_lock_count) {
+            sleep_manager_unlock_deep_sleep();
+        }
+    }
+
+    /** Mark the start of a locked deep sleep section
+     */
+    void lock()
+    {
+        uint16_t count = core_util_atomic_incr_u16(&_lock_count, 1);
+        if (1 == count) {
+            sleep_manager_lock_deep_sleep();
+        }
+        if (0 == count) {
+            MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OVERFLOW), "DeepSleepLock overflow (> USHRT_MAX)", count);
+        }
+    }
+
+    /** Mark the end of a locked deep sleep section
+     */
+    void unlock()
+    {
+        uint16_t count = core_util_atomic_decr_u16(&_lock_count, 1);
+        if (count == 0) {
+            sleep_manager_unlock_deep_sleep();
+        }
+        if (count == USHRT_MAX) {
+            core_util_critical_section_exit();
+            MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNDERFLOW), "DeepSleepLock underflow (< 0)", count);
+        }
+    }
+};
+
+/**@}*/
+
+/**@}*/
+
+
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DirHandle.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,178 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_DIRHANDLE_H
+#define MBED_DIRHANDLE_H
+
+#include <stdint.h>
+#include "platform/platform.h"
+#include "platform/FileHandle.h"
+#include "platform/NonCopyable.h"
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_DirHandle DirHandle functions
+ * @{
+ */
+
+
+/** Represents a directory stream. An opendir function returns
+ *  objects of this type. The core functions are read and seek,
+ *  but only a subset needs to be provided.
+ *
+ *  If a FileSystemLike class defines the opendir method, then you
+ *  can access the directories of an object of that type by either:
+ *  @code
+ *  DIR *d  = opendir("/example/directory");
+ *  @endcode
+ *  or
+ *  @code
+ *  DIR *d = opendir("/example");
+ *  @endcode
+ *  to open the root of the file system.
+ *
+ *  The root directory is considered to contain all FileHandle and
+ *  FileSystem objects, so the DIR pointer returned by opendir("/")
+ *  reflects this.
+ *
+ *  @note to create a directory, @see Dir
+ *  @note Synchronization level: Set by subclass
+ */
+class DirHandle : private NonCopyable<DirHandle> {
+public:
+    virtual ~DirHandle() {}
+
+    /** Read the next directory entry
+     *
+     *  @param ent      The directory entry to fill out
+     *  @return         1 on reading a filename, 0 at end of directory, negative error on failure
+     */
+    virtual ssize_t read(struct dirent *ent) = 0;
+
+    /** Close a directory
+     *
+     *  @return          0 on success, negative error code on failure
+     */
+    virtual int close() = 0;
+
+    /** Set the current position of the directory
+     *
+     *  @param offset   Offset of the location to seek to,
+     *                  must be a value returned from tell
+     */
+    virtual void seek(off_t offset) = 0;
+
+    /** Get the current position of the directory
+     *
+     *  @return         Position of the directory that can be passed to rewind
+     */
+    virtual off_t tell() = 0;
+
+    /** Rewind the current position to the beginning of the directory
+     */
+    virtual void rewind() = 0;
+
+    /** Get the sizeof the directory
+     *
+     *  @return         Number of files in the directory
+     */
+    virtual size_t size()
+    {
+        off_t off = tell();
+        size_t size = 0;
+        struct dirent *ent = new struct dirent;
+
+        rewind();
+        while (read(ent) > 0) {
+            size += 1;
+        }
+        seek(off);
+
+        delete ent;
+        return size;
+    }
+
+    /** Closes the directory.
+     *
+     *  @returns
+     *    0 on success,
+     *   -1 on error.
+     *  @deprecated Replaced by `int DirHandle::close()'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::close")
+    virtual int closedir()
+    {
+        return close();
+    };
+
+    /** Returns the directory entry at the current position, and
+     *  advances the position to the next entry.
+     *
+     * @returns
+     *  A pointer to a dirent structure representing the
+     *  directory entry at the current position, or NULL on reaching
+     *  end of directory or error.
+     * @deprecated Replaced by `ssize_t DirHandle::read(struct dirent *ent)
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::read")
+    virtual struct dirent *readdir()
+    {
+        static struct dirent ent;
+        return (read(&ent) > 0) ? &ent : NULL;
+    }
+
+    /** Resets the position to the beginning of the directory.
+     * @deprecated Replaced by `void DirHandle::rewind()'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::rewind")
+    virtual void rewinddir()
+    {
+        rewind();
+    }
+
+    /** Returns the current position of the DirHandle.
+     *
+     * @returns
+     *   the current position,
+     *  -1 on error.
+     * @deprecated Replaced by `off_t DirHandle::tell()'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::tell")
+    virtual off_t telldir()
+    {
+        return tell();
+    }
+
+    /** Sets the position of the DirHandle.
+     *
+     *  @param location The location to seek to. Must be a value returned by telldir.
+     *  @deprecated Replaced by `void DirHandle::seek(off_t offset)'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::seek")
+    virtual void seekdir(off_t location)
+    {
+        seek(location);
+    }
+};
+
+/**@}*/
+
+/**@}*/
+} // namespace mbed
+
+#endif /* MBED_DIRHANDLE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileBase.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,75 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_FILEBASE_H
+#define MBED_FILEBASE_H
+
+typedef int FILEHANDLE;
+
+#include "platform/platform.h"
+#include "platform/SingletonPtr.h"
+#include "platform/PlatformMutex.h"
+#include "platform/NonCopyable.h"
+
+namespace mbed {
+
+typedef enum {
+    FilePathType,
+    FileSystemPathType
+} PathType;
+
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_FileBase FileBase class
+ * @{
+ */
+/** Class FileBase
+ *
+ */
+
+class FileBase : private NonCopyable<FileBase> {
+public:
+    FileBase(const char *name, PathType t);
+    virtual ~FileBase();
+
+    const char *getName(void);
+    PathType    getPathType(void);
+
+    static FileBase *lookup(const char *name, unsigned int len);
+
+    static FileBase *get(int n);
+
+    void set_as_default();
+
+private:
+    static FileBase *_head;
+    static FileBase *_default;
+    static SingletonPtr<PlatformMutex> _mutex;
+
+    FileBase   *_next;
+    const char *const _name;
+    const PathType _path_type;
+};
+
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileHandle.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,276 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2017 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_FILEHANDLE_H
+#define MBED_FILEHANDLE_H
+
+typedef int FILEHANDLE;
+
+#include <cstdio>
+#include "Callback.h"
+#include "platform/mbed_poll.h"
+#include "platform/platform.h"
+#include "platform/NonCopyable.h"
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_FileHandle FileHandle functions
+ * @{
+ */
+
+
+/** Class FileHandle
+ *
+ *  An abstract interface that represents operations on a file-like
+ *  object. The core functions are read, write and seek, but only
+ *  a subset of these operations can be provided.
+ *
+ *  @note to create a file, @see File
+ *  @note Synchronization level: Set by subclass
+ */
+class FileHandle : private NonCopyable<FileHandle> {
+public:
+    virtual ~FileHandle() {}
+
+    /** Read the contents of a file into a buffer
+     *
+     *  Devices acting as FileHandles should follow POSIX semantics:
+     *
+     *  * if no data is available, and nonblocking set, return -EAGAIN
+     *  * if no data is available, and blocking set, wait until some data is available
+     *  * If any data is available, call returns immediately
+     *
+     *  @param buffer   The buffer to read in to
+     *  @param size     The number of bytes to read
+     *  @return         The number of bytes read, 0 at end of file, negative error on failure
+     */
+    virtual ssize_t read(void *buffer, size_t size) = 0;
+
+    /** Write the contents of a buffer to a file
+     *
+     *  Devices acting as FileHandles should follow POSIX semantics:
+     *
+     * * if blocking, block until all data is written
+     * * if no data can be written, and nonblocking set, return -EAGAIN
+     * * if some data can be written, and nonblocking set, write partial
+     *
+     *  @param buffer   The buffer to write from
+     *  @param size     The number of bytes to write
+     *  @return         The number of bytes written, negative error on failure
+     */
+    virtual ssize_t write(const void *buffer, size_t size) = 0;
+
+    /** Move the file position to a given offset from from a given location
+     *
+     *  @param offset   The offset from whence to move to
+     *  @param whence   The start of where to seek
+     *      SEEK_SET to start from beginning of file,
+     *      SEEK_CUR to start from current position in file,
+     *      SEEK_END to start from end of file
+     *  @return         The new offset of the file, negative error code on failure
+     */
+    virtual off_t seek(off_t offset, int whence = SEEK_SET) = 0;
+
+    /** Close a file
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int close() = 0;
+
+    /** Flush any buffers associated with the file
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int sync()
+    {
+        return 0;
+    }
+
+    /** Check if the file in an interactive terminal device
+     *
+     *  @return         True if the file is a terminal
+     *  @return         False if the file is not a terminal
+     *  @return         Negative error code on failure
+     */
+    virtual int isatty()
+    {
+        return false;
+    }
+
+    /** Get the file position of the file
+     *
+     *  @note This is equivalent to seek(0, SEEK_CUR)
+     *
+     *  @return         The current offset in the file, negative error code on failure
+     */
+    virtual off_t tell()
+    {
+        return seek(0, SEEK_CUR);
+    }
+
+    /** Rewind the file position to the beginning of the file
+     *
+     *  @note This is equivalent to seek(0, SEEK_SET)
+     */
+    virtual void rewind()
+    {
+        seek(0, SEEK_SET);
+    }
+
+    /** Get the size of the file
+     *
+     *  @return         Size of the file in bytes
+     */
+    virtual off_t size();
+
+    /** Move the file position to a given offset from a given location.
+     *
+     *  @param offset The offset from whence to move to
+     *  @param whence SEEK_SET for the start of the file, SEEK_CUR for the
+     *   current file position, or SEEK_END for the end of the file.
+     *
+     *  @returns
+     *    new file position on success,
+     *    -1 on failure or unsupported
+     *  @deprecated Replaced by `off_t FileHandle::seek(off_t offset, int whence = SEEK_SET)'
+     *
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by FileHandle::seek")
+    virtual off_t lseek(off_t offset, int whence)
+    {
+        return seek(offset, whence);
+    }
+
+    /** Flush any buffers associated with the FileHandle, ensuring it
+     *  is up to date on disk
+     *
+     *  @returns
+     *    0 on success or un-needed,
+     *   -1 on error
+     *  @deprecated Replaced by `int FileHandle::sync()'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by FileHandle::sync")
+    virtual int fsync()
+    {
+        return sync();
+    }
+
+    /** Find the length of the file
+     *
+     *  @returns
+     *   Length of the file
+     *  @deprecated Replaced by `off_t FileHandle::size()'
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by FileHandle::size")
+    virtual off_t flen()
+    {
+        return size();
+    }
+
+    /** Set blocking or nonblocking mode of the file operation like read/write.
+     *  Definition depends on the subclass implementing FileHandle.
+     *  The default is blocking.
+     *
+     *  @param blocking     true for blocking mode, false for nonblocking mode.
+     *
+     *  @return             0 on success
+     *  @return             Negative error code on failure
+     */
+    virtual int set_blocking(bool blocking)
+    {
+        return blocking ? 0 : -ENOTTY;
+    }
+
+    /** Check current blocking or nonblocking mode for file operations.
+     *
+     *  @return             true for blocking mode, false for nonblocking mode.
+     */
+    virtual bool is_blocking() const
+    {
+        return true;
+    }
+
+    /** Check for poll event flags
+     * You can use or ignore the input parameter. You can return all events
+     * or check just the events listed in events.
+     * Call is nonblocking - returns instantaneous state of events.
+     * Whenever an event occurs, the derived class should call the sigio() callback).
+     *
+     * @param events        bitmask of poll events we're interested in - POLLIN/POLLOUT etc.
+     *
+     * @returns             bitmask of poll events that have occurred.
+     */
+    virtual short poll(short events) const
+    {
+        // Possible default for real files
+        return POLLIN | POLLOUT;
+    }
+
+    /** Definition depends on the subclass implementing FileHandle.
+     *  For example, if the FileHandle is of type Stream, writable() could return
+     *  true when there is ample buffer space available for write() calls.
+     *
+     * @returns             true if the FileHandle is writable.
+     */
+    bool writable() const
+    {
+        return poll(POLLOUT) & POLLOUT;
+    }
+
+    /** Definition depends on the subclass implementing FileHandle.
+     *  For example, if the FileHandle is of type Stream, readable() could return
+     *  true when there is something available to read.
+     *
+     *  @returns            true when there is something available to read.
+     */
+    bool readable() const
+    {
+        return poll(POLLIN) & POLLIN;
+    }
+
+    /** Register a callback on state change of the file.
+     *
+     *  The specified callback will be called on state changes such as when
+     *  the file can be written to or read from.
+     *
+     *  The callback may be called in an interrupt context and should not
+     *  perform expensive operations.
+     *
+     *  Note! This is not intended as an attach-like asynchronous API, but rather
+     *  as a building block for constructing such functionality.
+     *
+     *  The exact timing of when the registered function
+     *  is called is not guaranteed and is susceptible to change. It should be used
+     *  as a cue to make read/write/poll calls to find the current state.
+     *
+     *  @param func     Function to call on state change
+     */
+    virtual void sigio(Callback<void()> func)
+    {
+        //Default for real files. Do nothing for real files.
+    }
+};
+
+/**@}*/
+
+/**@}*/
+
+
+} // namespace mbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileLike.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,55 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_FILELIKE_H
+#define MBED_FILELIKE_H
+
+#include "platform/mbed_toolchain.h"
+#include "platform/FileBase.h"
+#include "platform/FileHandle.h"
+#include "platform/NonCopyable.h"
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_FileLike FileLike class
+ * @{
+ */
+/** Class FileLike
+ *
+ *  A file-like object is one that can be opened with fopen by
+ *  fopen("/name", mode).
+ *
+ *  @note Synchronization level: Set by subclass
+ */
+class FileLike : public FileHandle, public FileBase, private NonCopyable<FileLike> {
+public:
+    /** Constructor FileLike
+     *
+     *  @param name     The name to use to open the file.
+     */
+    FileLike(const char *name = NULL) : FileBase(name, FilePathType) {}
+    virtual ~FileLike() {}
+};
+
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FilePath.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,66 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_FILEPATH_H
+#define MBED_FILEPATH_H
+
+#include "platform/platform.h"
+
+#include "platform/FileSystemLike.h"
+#include "platform/FileLike.h"
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_FilePath FilePath class
+ * @{
+ */
+
+class FileSystem;
+/** Class FilePath
+ *
+ */
+
+class FilePath {
+public:
+    /** Constructor FilePath
+     *
+     *  @param file_path     The path of file.
+     */
+    FilePath(const char *file_path);
+
+    const char *fileName(void);
+
+    bool          isFileSystem(void);
+    FileSystemLike *fileSystem(void);
+
+    bool    isFile(void);
+    FileLike *file(void);
+    bool    exists(void);
+
+private:
+    const char *file_name;
+    FileBase *fb;
+};
+
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileSystemHandle.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,113 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_FILESYSTEMHANDLE_H
+#define MBED_FILESYSTEMHANDLE_H
+
+#include "platform/platform.h"
+
+#include "platform/FileBase.h"
+#include "platform/FileHandle.h"
+#include "platform/DirHandle.h"
+#include "platform/NonCopyable.h"
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_FileSystemHandle FileSystemHandle functions
+ * @{
+ */
+
+
+/** A filesystem-like object is one that can be used to open file-like
+ *  objects though it by fopen("/name/filename", mode)
+ *
+ *  Implementations must define at least open (the default definitions
+ *  of the rest of the functions just return error values).
+ *
+ * @note Synchronization level: Set by subclass
+ */
+class FileSystemHandle : private NonCopyable<FileSystemHandle> {
+public:
+    /** FileSystemHandle lifetime
+     */
+    virtual ~FileSystemHandle() {}
+
+    /** Open a file on the filesystem
+     *
+     *  @param file     Destination for the handle to a newly created file
+     *  @param filename The name of the file to open
+     *  @param flags    The flags to open the file in, one of O_RDONLY, O_WRONLY, O_RDWR,
+     *                  bitwise or'd with one of O_CREAT, O_TRUNC, O_APPEND
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int open(FileHandle **file, const char *filename, int flags) = 0;
+
+    /** Open a directory on the filesystem
+     *
+     *  @param dir      Destination for the handle to the directory
+     *  @param path     Name of the directory to open
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int open(DirHandle **dir, const char *path);
+
+    /** Remove a file from the filesystem.
+     *
+     *  @param path     The name of the file to remove.
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int remove(const char *path);
+
+    /** Rename a file in the filesystem.
+     *
+     *  @param path     The name of the file to rename.
+     *  @param newpath  The name to rename it to
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int rename(const char *path, const char *newpath);
+
+    /** Store information about the file in a stat structure
+     *
+     *  @param path     The name of the file to find information about
+     *  @param st       The stat buffer to write to
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int stat(const char *path, struct stat *st);
+
+    /** Create a directory in the filesystem.
+     *
+     *  @param path     The name of the directory to create.
+     *  @param mode     The permissions with which to create the directory
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int mkdir(const char *path, mode_t mode);
+
+    /** Store information about the mounted filesystem in a statvfs structure
+     *
+     *  @param path     The name of the file to find information about
+     *  @param buf      The stat buffer to write to
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int statvfs(const char *path, struct statvfs *buf);
+};
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileSystemLike.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,93 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_FILESYSTEMLIKE_H
+#define MBED_FILESYSTEMLIKE_H
+
+#include "platform/platform.h"
+
+#include "platform/FileSystemHandle.h"
+#include "platform/FileHandle.h"
+#include "platform/DirHandle.h"
+#include "platform/NonCopyable.h"
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_FileSystemLike FileSystemLike functions
+ * @{
+ */
+
+
+/** A filesystem-like object is one that can be used to open file-like
+ *  objects though it by fopen("/name/filename", mode)
+ *
+ *  Implementations must define at least open (the default definitions
+ *  of the rest of the functions just return error values).
+ *
+ * @note Synchronization level: Set by subclass
+ */
+class FileSystemLike : public FileSystemHandle, public FileBase, private NonCopyable<FileSystemLike> {
+public:
+    /** FileSystemLike lifetime
+     */
+    FileSystemLike(const char *name = NULL) : FileBase(name, FileSystemPathType) {}
+    virtual ~FileSystemLike() {}
+
+    // Inherited functions with name conflicts
+    using FileSystemHandle::open;
+
+    /** Open a file on the filesystem
+     *
+     *  @param path     The name of the file to open
+     *  @param flags    The flags to open the file in, one of O_RDONLY, O_WRONLY, O_RDWR,
+     *                  bitwise or'd with one of O_CREAT, O_TRUNC, O_APPEND
+     *  @return         A file handle on success, NULL on failure
+     *  @deprecated Replaced by `int open(FileHandle **, ...)` for propagating error codes
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.5",
+                          "Replaced by `int open(FileHandle **, ...)` for propagating error codes")
+    FileHandle *open(const char *path, int flags)
+    {
+        FileHandle *file;
+        int err = open(&file, path, flags);
+        return err ? NULL : file;
+    }
+
+    /** Open a directory on the filesystem
+     *
+     *  @param path     Name of the directory to open
+     *  @return         A directory handle on success, NULL on failure
+     *  @deprecated Replaced by `int open(DirHandle **, ...)` for propagating error codes
+     */
+    MBED_DEPRECATED_SINCE("mbed-os-5.5",
+                          "Replaced by `int open(DirHandle **, ...)` for propagating error codes")
+    DirHandle *opendir(const char *path)
+    {
+        DirHandle *dir;
+        int err = open(&dir, path);
+        return err ? NULL : dir;
+    }
+};
+
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FunctionPointer.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,112 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_FUNCTIONPOINTER_H
+#define MBED_FUNCTIONPOINTER_H
+
+#include "platform/Callback.h"
+#include "platform/mbed_toolchain.h"
+#include <string.h>
+#include <stdint.h>
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_FunctionPointer FunctionPointer class
+ * @{
+ */
+
+// Declarations for backwards compatibility
+// To be foward compatible, code should adopt the Callback class
+template <typename R, typename A1>
+class FunctionPointerArg1 : public Callback<R(A1)> {
+public:
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "FunctionPointerArg1<R, A> has been replaced by Callback<R(A)>")
+    FunctionPointerArg1(R(*function)(A1) = 0)
+        : Callback<R(A1)>(function) {}
+
+    template<typename T>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "FunctionPointerArg1<R, A> has been replaced by Callback<R(A)>")
+    FunctionPointerArg1(T *object, R(T::*member)(A1))
+        : Callback<R(A1)>(object, member) {}
+
+    R(*get_function())(A1)
+    {
+        return *reinterpret_cast<R(* *)(A1)>(this);
+    }
+
+    R call(A1 a1) const
+    {
+        if (!Callback<R(A1)>::operator bool()) {
+            return (R)0;
+        }
+
+        return Callback<R(A1)>::call(a1);
+    }
+
+    R operator()(A1 a1) const
+    {
+        return Callback<R(A1)>::call(a1);
+    }
+};
+
+template <typename R>
+class FunctionPointerArg1<R, void> : public Callback<R()> {
+public:
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "FunctionPointer has been replaced by Callback<void()>")
+    FunctionPointerArg1(R(*function)() = 0)
+        : Callback<R()>(function) {}
+
+    template<typename T>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+                          "FunctionPointer has been replaced by Callback<void()>")
+    FunctionPointerArg1(T *object, R(T::*member)())
+        : Callback<R()>(object, member) {}
+
+    R(*get_function())()
+    {
+        return *reinterpret_cast<R(* *)()>(this);
+    }
+
+    R call() const
+    {
+        if (!Callback<R()>::operator bool()) {
+            return (R)0;
+        }
+
+        return Callback<R()>::call();
+    }
+
+    R operator()() const
+    {
+        return Callback<R()>::call();
+    }
+};
+
+typedef FunctionPointerArg1<void, void> FunctionPointer;
+
+/**@}*/
+
+/**@}*/
+
+
+} // namespace mbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LocalFileSystem.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,129 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_LOCALFILESYSTEM_H
+#define MBED_LOCALFILESYSTEM_H
+
+#include "platform/platform.h"
+
+#if DEVICE_LOCALFILESYSTEM
+
+#include "platform/FileSystemLike.h"
+#include "platform/PlatformMutex.h"
+#include "platform/NonCopyable.h"
+
+namespace mbed {
+/** \addtogroup platform */
+/** @{*/
+/**
+ * \defgroup platform_LocalFileSystem LocalFileSystem functions
+ * @{
+ */
+
+FILEHANDLE local_file_open(const char *name, int flags);
+
+/**
+ * @class LocalFileHandle
+ * @ingroup platform
+ */
+class LocalFileHandle : public FileHandle, private NonCopyable<LocalFileHandle> {
+
+public:
+    LocalFileHandle(FILEHANDLE fh);
+
+    virtual int close();
+
+    virtual ssize_t write(const void *buffer, size_t length);
+
+    virtual ssize_t read(void *buffer, size_t length);
+
+    virtual int isatty();
+
+    virtual off_t seek(off_t position, int whence);
+
+    virtual int sync();
+
+    virtual off_t size();
+
+protected:
+    virtual void lock();
+    virtual void unlock();
+    FILEHANDLE _fh;
+    int pos;
+    PlatformMutex _mutex;
+};
+
+/** A filesystem for accessing the local mbed Microcontroller USB disk drive
+ *
+ *  This allows programs to read and write files on the same disk drive that is used to program the
+ *  mbed Microcontroller. Once created, the standard C file access functions are used to open,
+ *  read and write files.
+ *
+ * @note Synchronization level: Thread safe
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ *
+ * LocalFileSystem local("local");               // Create the local filesystem under the name "local"
+ *
+ * int main() {
+ *     FILE *fp = fopen("/local/out.txt", "w");  // Open "out.txt" on the local file system for writing
+ *     fprintf(fp, "Hello World!");
+ *     fclose(fp);
+ *     remove("/local/out.txt");                 // Removes the file "out.txt" from the local file system
+ *
+ *     DIR *d = opendir("/local");               // Opens the root directory of the local file system
+ *     struct dirent *p;
+ *     while((p = readdir(d)) != NULL) {         // Print the names of the files in the local file system
+ *       printf("%s\n", p->d_name);              // to stdout.
+ *     }
+ *     closedir(d);
+ * }
+ * @endcode
+ *
+ * @note
+ *  If the microcontroller program makes an access to the local drive, it will be marked as "removed"
+ *  on the Host computer. This means it is no longer accessible from the Host Computer.
+ *
+ *  The drive will only re-appear when the microcontroller program exists. Note that if the program does
+ *  not exit, you will need to hold down reset on the mbed Microcontroller to be able to see the drive again!
+ * @ingroup platform
+ */
+class LocalFileSystem : public FileSystemLike, private NonCopyable<LocalFileSystem> {
+    // No modifiable state
+
+public:
+    LocalFileSystem(const char *n) : FileSystemLike(n)
+    {
+
+    }
+
+    virtual int open(FileHandle **file, const char *path, int flags);
+    virtual int open(DirHandle **dir, const char *name);
+    virtual int remove(const char *filename);
+};
+
+/**@}*/
+
+/**@}*/
+
+} // namespace mbed
+
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/critical.h	Thu Apr 08 16:43:07 2021 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 MBED_OLD_CRITICAL_H
+#define MBED_OLD_CRITICAL_H
+
+#warning critical.h has been replaced by mbed_critical.h, please update to mbed_critical.h [since mbed-os-5.3]
+#include "platform/mbed_critical.h"
+
+#endif