Updating Component to Mbed OS

Getting Started

This guide is to assist you in the process of updating an existing component library/program on https://os.mbed.com/components/ from older versions of Mbed to Mbed OS.

Pre-requisites

Identifying old versions of Mbed

We will use a temperature and humidity sensor as an example - https://os.mbed.com/components/Grove-TempHumi-Sensor/

First, navigate to the Hello World repository for the component.

/media/uploads/sarahmarshy/select_hello_world2.png

Next, view the files in the Hello World repository. The presence of mbed.bld will signify an old version of Mbed.

/media/uploads/sarahmarshy/view_files_in_repo.png

A component that uses and has been tested with Mbed OS will have an mbed-os.lib file.

/media/uploads/sarahmarshy/mbed_os_files.png

Some repositories may have both mbed.bld and mbed-rtos.lib. Mbed-RTOS is the precursor to Mbed OS, which combines the older mbed library with mbed RTOS. So, Mbed OS can replace BOTH mbed.bld and mbed-rtos.lib.

Migrating to Mbed OS

There are two possibilities when trying to migrate a component to Mbed OS:

  1. Replacing the old Mbed library with Mbed OS "just works," as the APIs used in the library have seen no changes. In this instance, you're done.
  2. Replacing the old Mbed library with Mbed OS produces some compilation errors. For one of two reasons:
    • The API calls in the library are out of date, and will need to be migrated to Mbed OS API syntax
    • The Hello World application uses target specific code and will need to be migrated to use code for the target we are compiling for

The general outline for updating to Mbed OS is as follows:

  1. mbed import [URL of Hello World]
  2. cd [Project Name]
  3. mbed remove mbed
  4. mbed remove mbed-rtos
  5. mbed add mbed-os

To determine the success of migration run: mbed compile -m [MCU] -t [toolchain]

Example Component #1 - Just Works

So, in our command prompt we run:

  1. mbed import https://os.mbed.com/teams/Seeed/code/Seeed_Grove_Buzzer/
  2. cd Seeed_Grove_Buzzer
  3. mbed remove mbed
  4. mbed remove mbed-rtos
  5. mbed add mbed-os
  6. mbed compile -m ublox_evk_odin_w2 -t gcc_arm

We see that it successfully compiles, so there are no changes necessary to the Grove-Buzzer library.

Example Component #2 - Application Fails to Compile

So, in our command prompt we run:

  1. mbed import https://os.mbed.com/users/melse/code/SRF08HelloWorld/
  2. cd SRF08HelloWorld
  3. mbed remove mbed
  4. mbed remove mbed-rtos
  5. mbed add mbed-os
  6. mbed compile -m k64f -t gcc_arm

Compilation Errors

After we have cloned the repository to our computer and deployed the latest version of Mbed OS, we need to check what compilation errors already exist.

Here is the output produced from mbed compile:

Building project SRF08HelloWorld (K64F, GCC_ARM)
Scan: .
Scan: env
Scan: mbed
Scan: FEATURE_LWIP
Scan: FEATURE_STORAGE
Compile [  0.3%]: AnalogIn.cpp
Compile [  0.6%]: BusIn.cpp
Compile [  0.8%]: main.cpp
[Error] main.cpp@4,13: 'p9' was not declared in this scope
[Error] main.cpp@4,17: 'p10' was not declared in this scope
[ERROR] .\main.cpp:4:13: error: 'p9' was not declared in this scope
 SRF08 srf08(p9, p10, 0xE0);      // Define SDA, SCL pin and I2C address
             ^~
.\main.cpp:4:17: error: 'p10' was not declared in this scope
 SRF08 srf08(p9, p10, 0xE0);      // Define SDA, SCL pin and I2C address
                 ^~~

[mbed] ERROR: "c:\python27\python.exe" returned error code 1.
[mbed] ERROR: Command "c:\python27\python.exe -u C:\Repos\SRF08HelloWorld\mbed-os\tools\make.py -t gcc_arm -m k64f --source . --build .\BUILD\k64f\gcc_arm" in "C:\Repos\SRF08HelloWorld"

So, this is a target specific error. The pins used in the Hello World application do not exist on the target we compiled for, K64F. So, let's replace the SDA/SCL pins with something on the K64F. We will use the K64F platform page to find the correct pins. Here, I see that D14/D15 will work. So, main.cpp now looks like this:

#include "mbed.h"
#include "SRF08.h"

SRF08 srf08(D14, D15, 0xE0);      // Define SDA, SCL pin and I2C address

int main() {

    while (1) {
       printf("Measured range : %.2f cm\n",srf08.read());
       wait(0.1);
    }

}

Now, it successfully compiles.

Example Component #3 - Library Fails to Compile

So, in our command prompt we run:

  1. mbed import http://mbed.org/teams/AnalogDevices/code/CN0357-helloworld/
  2. cd CN0357-helloworld
  3. mbed remove mbed
  4. mbed remove mbed-rtos
  5. mbed add mbed-os
  6. mbed compile -m k64f -t gcc_arm

Compilation Errors

After we have cloned the repository to our computer and deployed the latest version of Mbed OS, we need to check what compilation errors already exist.

Here is the output produced from mbed compile:

Building project CN0357-helloworld (K64F, GCC_ARM)
Scan: .
Scan: mbed
Scan: env
Scan: FEATURE_LWIP
Scan: FEATURE_STORAGE
Compile [  0.3%]: AD5270.cpp
[Error] AD5270.h@91,25: 'SPI_CS' was not declared in this scope
[Error] AD5270.h@91,80: 'SPI_MOSI' was not declared in this scope
[Error] AD5270.h@91,105: 'SPI_MISO' was not declared in this scope
[Error] AD5270.h@91,129: 'SPI_SCK' was not declared in this scope
[ERROR] In file included from ./CN0357/AD5270/AD5270.cpp:50:0:
./CN0357/AD5270/AD5270.h:91:25: error: 'SPI_CS' was not declared in this scope
     AD5270(PinName CS = SPI_CS, float max_resistance = 20000.0, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                         ^~~~~~
./CN0357/AD5270/AD5270.h:91:80: error: 'SPI_MOSI' was not declared in this scope
     AD5270(PinName CS = SPI_CS, float max_resistance = 20000.0, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                                ^~~~~~~~
./CN0357/AD5270/AD5270.h:91:105: error: 'SPI_MISO' was not declared in this scope
     AD5270(PinName CS = SPI_CS, float max_resistance = 20000.0, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                                                         ^~~~~~~~
In file included from ./CN0357/AD5270/AD5270.cpp:50:0:
./CN0357/AD5270/AD5270.h:91:129: error: 'SPI_SCK' was not declared in this scope
     AD5270(PinName CS = SPI_CS, float max_resistance = 20000.0, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                                                                                 ^~~~~~~

[mbed] ERROR: "/usr/local/opt/python/bin/python2.7" returned error code 1.
[mbed] ERROR: Command "/usr/local/opt/python/bin/python2.7 -u /Users/jenplu01/Repos/CN0357-helloworld/mbed-os/tools/make.py -t gcc_arm -m k64f --source . --build ./BUILD/k64f/gcc_arm" in "/Users/jenplu01/Repos/CN0357-helloworld"
---

The errors relating to "was not declared in this scope" are library specific errors. We need to go into the ./CN0357/AD5270/AD5270.h header file and remove the constructor's default arguments. Line 91 of the AD5270.h header file should now look like this:

Line 91 of AD5270.h

AD5270(PinName CS, float max_resistance, PinName MOSI, PinName MISO, PinName SCK);

Run mbed compile again:

Building project CN0357-helloworld (K64F, GCC_ARM)
Scan: .
Scan: mbed
Scan: env
Scan: FEATURE_LWIP
Scan: FEATURE_STORAGE
Compile [  2.5%]: main.cpp
[Error] AD7790.h@114,51: 'SPI_CS' was not declared in this scope
[Error] AD7790.h@114,74: 'SPI_MOSI' was not declared in this scope
[Error] AD7790.h@114,99: 'SPI_MISO' was not declared in this scope
[Error] AD7790.h@114,123: 'SPI_SCK' was not declared in this scope
[Error] CN0357.h@77,73: 'SPI_MOSI' was not declared in this scope
[Error] CN0357.h@77,98: 'SPI_MISO' was not declared in this scope
[Error] CN0357.h@77,122: 'SPI_SCK' was not declared in this scope
[Error] main.cpp@111,12: call to 'CN0357::CN0357(PinName, PinName, PinName, PinName, PinName)' uses the default argument for parameter 3, which is not yet defined
[Error] main.cpp@111,0: call to 'CN0357::CN0357(PinName, PinName, PinName, PinName, PinName)' uses the default argument for parameter 4, which is not yet defined
[Error] main.cpp@111,0: call to 'CN0357::CN0357(PinName, PinName, PinName, PinName, PinName)' uses the default argument for parameter 5, which is not yet defined
[ERROR] In file included from ./CN0357/CN0357.h:52:0,
                 from ./main.cpp:48:
./CN0357/AD7790/AD7790.h:114:51: error: 'SPI_CS' was not declared in this scope
     AD7790( float reference_voltage, PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                   ^~~~~~
./CN0357/AD7790/AD7790.h:114:74: error: 'SPI_MOSI' was not declared in this scope
     AD7790( float reference_voltage, PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                          ^~~~~~~~
./CN0357/AD7790/AD7790.h:114:99: error: 'SPI_MISO' was not declared in this scope
     AD7790( float reference_voltage, PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                                                   ^~~~~~~~
./CN0357/AD7790/AD7790.h:114:123: error: 'SPI_SCK' was not declared in this scope
     AD7790( float reference_voltage, PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                                                                           ^~~~~~~
In file included from ./main.cpp:48:0:
./CN0357/CN0357.h:77:73: error: 'SPI_MOSI' was not declared in this scope
     CN0357(PinName CSAD7790 = D8, PinName CSAD5270 = D6, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                         ^~~~~~~~
./CN0357/CN0357.h:77:98: error: 'SPI_MISO' was not declared in this scope
     CN0357(PinName CSAD7790 = D8, PinName CSAD5270 = D6, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                                                  ^~~~~~~~
./CN0357/CN0357.h:77:122: error: 'SPI_SCK' was not declared in this scope
     CN0357(PinName CSAD7790 = D8, PinName CSAD5270 = D6, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
                                                                                                                          ^~~~~~~
./main.cpp: In function 'int main()':
./main.cpp:111:12: error: call to 'CN0357::CN0357(PinName, PinName, PinName, PinName, PinName)' uses the default argument for parameter 3, which is not yet defined
     CN0357 cn0357;
            ^~~~~~
./main.cpp:111:12: error: call to 'CN0357::CN0357(PinName, PinName, PinName, PinName, PinName)' uses the default argument for parameter 4, which is not yet defined
./main.cpp:111:12: error: call to 'CN0357::CN0357(PinName, PinName, PinName, PinName, PinName)' uses the default argument for parameter 5, which is not yet defined

[mbed] ERROR: "/usr/local/opt/python/bin/python2.7" returned error code 1.
[mbed] ERROR: Command "/usr/local/opt/python/bin/python2.7 -u /Users/jenplu01/Repos/temp/CN0357-helloworld/mbed-os/tools/make.py -t gcc_arm -m k64f --source . --build ./BUILD/k64f/gcc_arm" in "/Users/jenplu01/Repos/temp/CN0357-helloworld"
---

Notice that the ./CN0357/AD7790/AD7790.h and ./CN0357/CN0357.h header files also have similar "was not declared in this scope" errors. We will need to remove the constructor's default arguments again in both files.

Line 114 of the AD7790.h header file should now look like this:

Line 114 of AD7790.h

AD7790( float reference_voltage, PinName CS, PinName MOSI, PinName MISO, PinName SCK);

Line 77 of the CN0357.h header file should now look like this:

Line 77 of CN0357.h

CN0357(PinName CSAD7790, PinName CSAD5270, PinName MOSI, PinName MISO, PinName SCK);

Run mbed compile once again and we now have the following errors:

Building project CN0357-helloworld (K64F, GCC_ARM)
Scan: .
Scan: mbed
Scan: env
Scan: FEATURE_LWIP
Scan: FEATURE_STORAGE
Compile [  5.1%]: Ticker.cpp
Compile [  5.4%]: Timeout.cpp
Compile [  5.6%]: main.cpp
[Error] main.cpp@111,12: no matching function for call to 'CN0357::CN0357()'
[ERROR] ./main.cpp: In function 'int main()':
./main.cpp:111:12: error: no matching function for call to 'CN0357::CN0357()'
     CN0357 cn0357;
            ^~~~~~
In file included from ./main.cpp:48:0:
./CN0357/CN0357.h:77:5: note: candidate: CN0357::CN0357(PinName, PinName, PinName, PinName, PinName)
     CN0357(PinName CSAD7790, PinName CSAD5270, PinName MOSI, PinName MISO, PinName SCK);
     ^~~~~~
./CN0357/CN0357.h:77:5: note:   candidate expects 5 arguments, 0 provided
./CN0357/CN0357.h:58:7: note: candidate: CN0357::CN0357(const CN0357&)
 class CN0357
       ^~~~~~
./CN0357/CN0357.h:58:7: note:   candidate expects 1 argument, 0 provided

[mbed] ERROR: "/usr/local/opt/python/bin/python2.7" returned error code 1.
[mbed] ERROR: Command "/usr/local/opt/python/bin/python2.7 -u /Users/jenplu01/Repos/temp/CN0357-helloworld/mbed-os/tools/make.py -t gcc_arm -m k64f --source . --build ./BUILD/k64f/gcc_arm" in "/Users/jenplu01/Repos/temp/CN0357-helloworld"
---

These errors are now due to the CN0357 variable in main.cpp no longer having sufficient arguments. Go into main.cpp and modify the initialization of the CN0357 cn0357; variable on line 111 to include the K64F's pin names. Line 111 should now look like this:

Line 111 of main.cpp

CN0357 cn0357(D8, D6, D11, D12, D13); // CSAD7790, CSAD5270, MOSI, MISO, SCK

Now, the program successfully compiles.


Please log in to post comments.