mbed OS Planned API and Toolchain Changes


mbed OS Planned API and Toolchain Changes

mbed OS 5.5 is about to go through verification and validation! There are lots of great new additions, both features and boards, and more on that soon. First, here is some insight on what's changing and things to be aware of that may have a notable effect on mbed OS API or tool compatibility. Our intent is to minimize the effect on developer applications and workflows.

CMSIS5 and CMSIS-RTOS2 upgrade

mbed OS 5.5 will upgrade to the latest CMSIS5, which includes introduction of the CMSIS-RTOS2 kernel. This brings implementation improvements and fixes and extensions needed to support the latest ARMv8-M architecture. There is no effect on mbed OS developer APIs, and we expect applications to continue working unchanged.

Compiler toolchain version updates

The current supported toolchain versions for mbed OS are:

All of these compiler toolchains are now at least one major release behind latest and subsequently are missing key features and fixes; to support ARM v8-M architecture and the latest CMSIS5 and CMSIS-RTOS2 software, it is essential to upgrade the supported compilers to the latest major versions.

In addition, it is desirable to pick up the latest critical and recommended fixes and features in these toolchains, including necessary thread safety hooks in standard libraries (GCC 6) and enhanced code size optimization using LTO (ARM 6).

To facilitate these needs, over the next few releases, we will update the supported compilers to:

Note: Although we do not recommend you remain on older compilers, ARM compiler 5 will still work with the CMSIS5 upgrade. GCC 4 will not work following the CMSIS5 upgrade because it needs features only available in GCC 5 and beyond. In all cases, use of ARM v8-M devices will require these latest supported compilers.

EventQueue and additional restrictions for privileged mode

Recently, we have observed a few design patterns with unintentional (and incorrect) execution of code in interrupt context. Examples include claiming mutexes in privileged mode and running excessive code in interrupt context. These types of mistakes are particularly unfortunate because they tend to manifest as problems that are masked except under certain conditions, such as the handling of simultaneous events. This leads to occasionally unstable systems that are difficult to debug.

deceptively broken ticker code

Ticker ticker;

// This code prints a line every 1000 milliseconds. However the print statement is in the ticker's
// interrupt context. While code is running in interrupt context, other interrupts can not run. This can
// cause other time-sensitive events to fail.
void on_ticker_event() {
    printf("got tick!\n"); // ERROR, this will now assert
}

int main() {
    ticker.attach_ms(on_ticker_event, 1000);
    
    while(1) {
    
    }
}

deceptively broken socket code

TCPSocket sock;
uint8_t buffer[1024];
Semaphore data_available;

// This code checks if data is available on the socket by attempting to recieve data. However,
// recieving data is a lengthy operation that may lock the system for a relatively long time, even
// in non-blocking mode. Use in irq context is unsafe.
void on_socket_event() {
    int err = socket.recv(buffer, 1024); // ERROR, this will now assert
    if (err != NSAPI_ERROR_WOULD_BLOCK) {
        data_available.release();
    }
}

int main() {
    sock.set_blocking(false);
    sock.sigio(on_socket_event);
    
    while (1) {
        // Loop until data is available
        int res = data_available.wait(10);
        if (res > 0) {
            printf("got data!\n");
            handle_data(buffer);
        }
    }
}

This is compounded by the fact that mutex claims within privileged mode currently fail silently, so there can be correctness issues with seemingly working code.

To help address these problems and avoid these common mistakes, we introduced the EventQueue APIs in mbed OS 5.2. These APIs support and encourage simple delegation from interrupt context to promote design patterns that are not susceptible to these issues.

fixed ticker code

Ticker ticker;
EventQueue queue;

// This code is now runs in the context of the main thread (the caller of EventQueue::dispatch).
// If an interrupt comes in for a time-sensitive event, the thread will be preempted and not prevent
// the event from firing.
void on_ticker_event() {
    printf("got tick!\n");
}

int main() {
    ticker.attach_ms(queue.event(on_ticker_event), 1000);
    queue.dispatch(); // will not return until queue.break_dispatch() is called
    
    while(1) {
    
    }
}

fixed socket code

TCPSocket sock;
uint8_t buffer[1024];
EventQueue queue;

// This code is now runs in the context of the main thread (the caller of EventQueue::dispatch). It is
// now safe to call recv and the data can also be safely passed on to other expensive functions.
void on_socket_event() {
    int err = socket.recv(buffer, 1024);
    if (err != NSAPI_ERROR_WOULD_BLOCK) {
        printf("got data!\n");
        handle_data(buffer);
    }
}

int main() {
    sock.set_blocking(false);
    sock.sigio(queue.event(on_socket_event));
    queue.dispatch(); // will not return until queue.break_dispatch() is called
    
    while(1) {
    
    }
}

With this support, we marked the particularly problematic RtosTimer APIs as deprecated in mbed OS 5.2, pending future removal. Code using the RtosTimer APIs should be reworked to use the equivalent EventQueue functionality, which does not suffer from the same design pattern traps.

In addition, we will introduce an explicit assert failure for a mutex claimed in privileged mode to catch and avoid incorrect use in mbed OS 5.5. This ensures problems are not as easily masked. The assertions will be conditionally active for release or default build profiles (the online IDE uses the default build profile) or by default in debug mode, so incorrect code will be trapped. These asserts will not be present in release code, and release code will see no change. However, we obviously recommend you study and address any assertion fails. An example of how to enable this trapping with the online IDE or offline builds:

mbed_app.json

{
    "target_overrides": {
        "*": {
            "target.macros_add": ["MBED_TRAP_ERRORS_ENABLED=1"]
        }
    }
}

Other changes

There are currently no other planned changes in mbed OS releases that have a notable effect on mbed OS API or tool compatibility.

Please log in to start a discussion or ask a question.