Tutorial: Build a real-time capable application

This tutorial shows how to build a sample application for the real-time cores on an Azure Sphere device. See Overview of Azure Sphere applications for basic information about real-time capable applications.

In this tutorial, you learn how to:

  • Install the GNU Arm toolchain
  • Set up hardware to display output
  • Enable development and debugging
  • Download a sample application
  • Start a terminal emulator to view output
  • Build, run, and debug a real-time capable application

Important

These instructions assume you are using hardware that follows the MT3620 reference board design (RDB) hardware, such as the MT3620 Dev Kit from Seeed Studios. If you are using different Azure Sphere hardware, consult the manufacturer's documentation to find out whether the UART is exposed and how to access it. You might need to set up hardware to display output differently, and update the sample code and the "Uarts" field of the app_manifest.json file to use a different UART.

Prerequisites

Install the GNU Arm Embedded Toolchain

If you're using Visual Studio, proceed to Set up hardware to display output. The toolchain is installed with the Azure Sphere Extension for Visual Studio. However, if you installed the GNU ARM Embedded Toolchain manually, Visual Studio will use the version you installed.

Set up hardware to display output

Currently, each real-time core supports a TX-only UART. RTApps can use this UART to send log output from the device. During application development and debugging, you typically need a way to read and display the output. The HelloWorld_RTApp_MT3620_BareMetal sample shows how an application can write to the UART.

Use a USB-to-serial adapter such as the FTDI Friend, to connect the UART on the real-time core to a USB port on your machine. You will also need a terminal emulator to establish a serial connection with 115200-8-N-1 terminal settings (115200 bps, 8 bits, no parity bits, one stop bit) to display the output.

To set up the hardware to display output from an RTApp, follow these steps. You'll need to refer to the documentation from your hardware manufacturer to determine the pin locations. If you're using hardware that follows the MT3620 reference board design (RDB) hardware, like the MT3620 Dev Kit from Seeed Studios, then looking at the RDB interface headers may help you to determine the pin locations.

  1. Connect GND on the USB-to-serial adapter to GND on your dev kit. On MT3620 RDB hardware, GND is Header 3, pin 2.
  2. Connect RX on the USB-to-serial adapter to IOM4-0 TX on your dev kit. On MT3620 RDB hardware, IOM4-0 TX is Header 3, pin 6.
  3. Connect the USB-to-serial adapter to a free USB port on your development machine and determine which port the serial device is connected to. On Windows, start Device Manager, select View > Devices by container, and look for 'USB UART". For example, FT232R USB UART indicates the FTDI Friend adapter.
  4. Start a terminal emulator program and open a 115200-8-N-1 terminal to the COM port used by the adapter. See the documentation for the terminal emulator to find out how to specify the port and speed.

To install the toolchain:

  • On the Arm developer website, find the GNU Arm Embedded Toolchain that includes the compiler for the ARM Cortex-M4 processor. Follow the instructions there to download and install the compiler for your OS platform.

By default, Visual Studio Code searches for the toolchain and should find the version you installed. If you encounter build problems related to the toolchain, enter the path as follows:

  1. Select File > Preferences > Settings > Extensions > AzureSphere.
  2. Enter the GNU Arm Embedded Toolchain installation directory in Azure Sphere: Arm Gnu Path.

Set up hardware to display output

Currently, each real-time core supports a TX-only UART. RTApps can use this UART to send log output from the device. During application development and debugging, you typically need a way to read and display the output. The HelloWorld_RTApp_MT3620_BareMetal sample shows how an application can write to the UART.

Use a USB-to-serial adapter such as the FTDI Friend, to connect the UART on the real-time core to a USB port on your machine. You will also need a terminal emulator to establish a serial connection with 115200-8-N-1 terminal settings (115200 bps, 8 bits, no parity bits, one stop bit) to display the output.

To set up the hardware to display output from an RTApp, follow these steps. You'll need to refer to the documentation from your hardware manufacturer to determine the pin locations. If you're using hardware that follows the MT3620 reference board design (RDB) hardware, like the MT3620 Dev Kit from Seeed Studios, then looking at the RDB interface headers may help you to determine the pin locations.

  1. Connect GND on the USB-to-serial adapter to GND on your dev kit. On MT3620 RDB hardware, GND is Header 3, pin 2.

  2. Connect RX on the USB-to-serial adapter to IOM4-0 TX on your dev kit. On MT3620 RDB hardware, IOM4-0 TX is Header 3, pin 6.

  3. Connect the USB-to-serial adapter to a free USB port on your development machine and determine which port the serial device is connected to.

    • On Windows, start Device Manager, select View > Devices by container, and look for 'USB UART". For example, FT232R USB UART indicates the FTDI Friend adapter.

    • On Linux, type the following command:

      dmesg | grep ttyUSB
      

      The port should be named ttyUSBn, where n indicates the port number. If the dmesg command lists several USB ports, the one that is connected to the typically the last one reported as attached. For example, in the following, you would use ttyUSB4:

    ~$ dmesg | grep ttyUSB
    [  144.564350] usb 1-1.1.2: FTDI USB Serial Device converter now attached to ttyUSB0
    [  144.564768] usb 1-1.1.2: FTDI USB Serial Device converter now attached to ttyUSB1
    [  144.565118] usb 1-1.1.2: FTDI USB Serial Device converter now attached to ttyUSB2
    [  144.565593] usb 1-1.1.2: FTDI USB Serial Device converter now attached to ttyUSB3
    [  144.570429] usb 1-1.1.3: FTDI USB Serial Device converter now attached to ttyUSB4
    [  254.171871] ftdi_sio ttyUSB1: FTDI USB Serial Device converter now disconnected from ttyUSB1
    
  4. Start a terminal emulator program and open a 115200-8-N-1 terminal to the COM port used by the adapter. See the documentation for the terminal emulator to find out how to specify the port and speed.

Enable development and debugging

Before you can build a sample application on your Azure Sphere device or develop new applications for it, you must enable development and debugging. By default, Azure Sphere devices are "locked"; that is, they do not allow applications under development to be loaded from a PC, and they do not allow debugging of applications. Preparing the device for debugging removes this restriction and loads software required for debugging and unlocks device capabilities as described in Device capabilities and communication.

To debug on the real-time cores, use the azsphere device enable-development command. This command configures the device to accept applications from a PC for debugging and assigns the device to the Development device group, which does not allow cloud application updates. During application development and debugging, you should leave the device in this group so that cloud application updates do not overwrite the application under development.

On Windows, you must add the --enable-rt-core-debugging parameter, which loads the debugging servers and required drivers for each type of core onto the device.

  1. Log in to Azure Sphere if you haven't already done so:

    azsphere login
    
  2. Open a command-line interface using PowerShell or Windows command prompt with administrator privileges. The --enable-rt-core-debugging parameter requires administrator privilege because it installs USB drivers for the debugger.

  3. Enter the following command:

    azsphere device enable-development --enable-rt-core-debugging
    
  4. Close the window after the command completes because administrator privilege is no longer required. As a best practice, you should always use the lowest privilege that can accomplish a task.

If the azsphere device enable-development command fails, see Troubleshoot Azure Sphere issues for help.

Download the sample application

You can download the HelloWorld application as follows:

  1. Point your browser to Microsoft Samples Browser.
  2. Type "Azure Sphere" in the Search box.
  3. Select Azure Sphere - Hello World from the search results.
  4. Select Download ZIP.
  5. Open the downloaded file and extract to a local directory.

Build and run the HelloWorld RTApp application with Visual Studio

  1. Start Visual Studio. Select Open a local folder, navigate to the folder where you extracted the downloaded Azure_Sphere___Hello_World.zip file, and then select the HelloWorld_RTApp_MT3620_Baremetal folder.

  2. If you are not using an MT3620 RDB, update the app_manifest.json file and the sample code to specify the correct UART, for example ISU1.

  3. If CMake generation does not start automatically, select the CMakeLists.txt file.

  4. In the Visual Studio Output window, the CMake output should show the messages CMake generation started. and CMake generation finished.

  5. Select Build > Build All. If the menu is not present, open Solution Explorer, right-click the CMakeLists.txt file, and select Build. The output location of the HelloWorld_RTApp_MT3620_Baremetal application appears in the Output window.

  6. On the Select Startup Item menu, select GDB Debugger (RTCore).

  7. Press F5 to deploy the application.

  8. The connected terminal emulator should display output from the HelloWorld_RTApp_MT3620_Baremetal program. The program sends the following words at one-second intervals:

    Tick

    Tock

  9. Use the debugger to set breakpoints, inspect variables, and try other debugging tasks.

Build and run the HelloWorld RTApp application with Visual Studio Code

  1. In Visual Studio Code, open the HelloWorld_RTApp_MT3620_BareMetal folder in the folder where you extracted the downloaded Azure_Sphere___Hello_World.zip file. If you're prompted to select a kit, choose "Do not use a kit."

  2. If you're not using MT3620 RDB hardware, update the app_manifest.json file and the sample code to specify the correct UART, for example ISU1.

  3. Press F5 to start the debugger. If the project has not previously been built, or if files have changed and rebuild is required, Visual Studio Code will build the project before debugging starts.

  4. The Azure Sphere output window should show "Deploying image..." followed by the paths to the SDK and compiler.

  5. The connected terminal emulator should display output from the HelloWorld_RTApp_MT3620_Baremetal program. The program sends the following words at one-second intervals:

    Tick

    Tock

  6. Use Visual Studio Code debugging features to set breakpoints, inspect variables, and try other debugging tasks.

Troubleshooting

The application might begin executing before OpenOCD makes a connection. As a result, breakpoints set early in the code might be missed. A simple workaround for this is to delay the start of the app until OpenOCD connects.

  1. Insert the following code at the beginning of the application entry point RTCoreMain. This will cause the application to enter and remain in a while loop until variable f is set to true.

     volatile bool f = false;
     while (!f) {
        // empty.
     }
    
  2. Press F5 to start the app with debugging (F5) and then break into execution.

  3. In the Locals debug panel, change the value of f from zero to one.

  4. Step through the code as usual.

Build the sample

  1. Create or navigate to the project build directory for your real-time capable application. This is the directory that will contain the .imagepackage files that will be generated during the build process. For example, to create and open a new directory called "build" you would enter the following commands:

    mkdir build
    cd build
    
  2. Open a command-line interface using PowerShell, Windows command prompt, or Linux command shell. Navigate to your project build directory.

  3. From your project build directory, at the command prompt, run CMake with the following parameters:

    • -G

      Set this parameter to "Ninja" to indicate that CMake should use the Ninja generator to create the build files, as Ninja will be used to complete the build.

    • -DCMAKE_TOOLCHAIN_FILE

      Set this parameter to the path to the compiler tool chain file on your machine. For Windows, the CMAKE_TOOLCHAIN_FILE should point to C:\Program Files (x86)\<path to SDK>\CMakeFiles\AzureSphereRTCoreToolchain.cmake. For Linux, specify /opt/azurespheresdk/CMakeFiles/AzureSphereRTCoreToolchain.cmake.

    • -DARM_GNU_PATH

      Set this parameter to the path to the directory on your machine that contains arm-none-eabi-gcc, and not the path to the compiler itself. If you are using the GNU Tools from Visual Studio, the ARM_GNU_PATH path would be in the 2019\edition\Linux\gcc_arm\bin subfolder of your Visual Studio installation, rather than the path in the example.

    • -DAZURE_SPHERE_TARGET_API_SET

      Set this parameter to the desired Azure Sphere API set to use. In the example it is set to "latest-lts", which selects the latest set of APIs designated for long-term support.

    • -DCMAKE_BUILD_TYPE

      Set this parameter to the build type. Possible values are Debug and Release.

    • The final parameter is the path to the directory on your machine that contains the source files for the sample application. In the example the Azure Sphere samples repository was downloaded to a directory called AzSphere.

      CMake parameters are separated by spaces. The line continuation character (^ for Windows command line, \ for Linux command line, or ` for PowerShell) can be used for readability but is not required.

    The following examples show the CMake commands for an RTApp. Where indicated, replace <file-path> with the installation path for the GNU Arm embedded toolchain on your system.

    Windows Command Prompt

    cmake ^
    -G "Ninja" ^
    -DCMAKE_TOOLCHAIN_FILE="C:\Program Files (x86)\Microsoft Azure Sphere SDK\CMakeFiles\AzureSphereRTCoreToolchain.cmake" ^
    -DARM_GNU_PATH:STRING="<file-path>\GNU Arm Embedded Toolchain\9 2020-q2-update\bin" ^
    -DAZURE_SPHERE_TARGET_API_SET="latest-lts" ^
    -DCMAKE_BUILD_TYPE="Debug" ^
    "C:\AzSphere\azure-sphere-samples\Samples\HelloWorld\HelloWorld_RTApp_MT3620_BareMetal"
    

    Windows PowerShell

    cmake `
    -G "Ninja" `
    -DCMAKE_TOOLCHAIN_FILE="C:\Program Files (x86)\Microsoft Azure Sphere SDK\CMakeFiles\AzureSphereRTCoreToolchain.cmake" `
    -DARM_GNU_PATH:STRING="<file-path>\GNU Arm Embedded Toolchain\9 2020-q2-update\bin" `
    -DAZURE_SPHERE_TARGET_API_SET="latest-lts" `
    -DCMAKE_BUILD_TYPE="Debug" `
    "C:\AzSphere\azure-sphere-samples\Samples\HelloWorld\HelloWorld_RTApp_MT3620_BareMetal"
    
  4. From your project build directory, at the command prompt, run ninja to build the application and create the image package file.

When troubleshooting, especially after making any changes to your CMake commands, delete your entire build and try again.

Run the sample

  1. Delete any applications that are already deployed to the device:

    azsphere device sideload delete
    
  2. From your project directory, at the command prompt, load the image package that ninja created:

    azsphere device sideload deploy --image-package <path-to-imagepackage>
    
  3. Get the component ID for the image:

    azsphere image-package show --image-package <path-to-imagepackage>
    

    The command returns all the metadata for the image package. The component ID for the application appears in the Identity section for the Application Image Type. For example:

    Image package metadata:
    Section: Identity
    Image Type:           Application
    Component ID:         <component id>
    Image ID:             <image id>
    

    You can use the following commands to stop, start, and get the status of the application:

    azsphere device app stop --component-id <component id>
    
    azsphere device app start --component-id <component id>
    
    azsphere device app show-status --component-id <component id>
    

Debug the sample

  1. Stop the application if it's running.

    azsphere device app stop --component-id <component id>
    
  2. Re-start the application for debugging.

    azsphere device app start --component-id <component id>
    

    This command returns the core on which the application is running.

    <component id>
    App state   : running
    Core        : Real-time 0
    
  3. Navigate to the Openocd folder for the sysroot that the application was built with. The sysroots are installed in the Azure Sphere SDK installation folder. For example, on Windows the folder is installed by default at C:\Program Files (x86)\Microsoft Azure Sphere SDK\Sysroots\*sysroot*\tools\openocd and on Linux, at /opt/azurespheresdk/Sysroots/*sysroot*/tools/sysroots/x86_64-pokysdk-linux.

  4. Run openocd as the following example shows. The example assumes the app is running on core 0. If the app is running on core 1, replace "targets io0" with "targets io1".

    openocd -f mt3620-rdb-ftdi.cfg -f mt3620-io0.cfg -c "gdb_memory_map disable" -c "gdb_breakpoint_override hard" -c init -c "targets io0" -c halt -c "targets"
    
  5. Navigate to the folder that contains the application .out file and start arm-none-eabi-gdb, which is part of the GNU Arm Embedded Toolchain:

    Windows Command Prompt

    "C:\Program Files (x86)\GNU Arm Embedded Toolchain\9 2020-q2-update\bin\arm-none-eabi-gdb" HelloWorld_RTApp_MT3620_BareMetal.out
    

    Windows PowerShell

    & "C:\Program Files (x86)\GNU Arm Embedded Toolchain\9 2020-q2-update\bin\arm-none-eabi-gdb" HelloWorld_RTApp_MT3620_BareMetal.out
    
  6. The OpenOCD server provides a GDB server interface on :4444. Set the target for debugging.

    target remote :4444

  7. You can now issue gdb commands.

  8. The connected terminal emulator should display output from the application.

Use partner apps

When you load an application onto the Azure Sphere device, the Azure Sphere deployment tools by default delete all existing applications. To prevent this from happening when you develop applications that communicate with each other, you need to mark the applications as partners. When you deploy one of the applications, its partners will not be deleted. See Mark applications as partners for details.

Next steps