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 will learn how to:

  • Download a sample application
  • Install the GNU Arm toolchain
  • Set up hardware to display output
  • Enable development and debugging
  • 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

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.

Install the GNU Arm Embedded Toolchain

You can download and install the GNU Arm Embedded Toolchain from the Arm developer website. Or you can use vcpkg artifacts to automatically install and configure the development environment.

  • Visual Studio 2022: If you're using Visual Studio 2022, install the GNU Arm Embedded Toolchain (arm-none-eabi) from the Arm developer website.
  • Visual Studio 2019: The toolchain is automatically installed with the azure-sphere extension for Visual Studio on Visual Studio 2019. If you're using Visual Studio 2019, proceed to Set up hardware to display output. However, if you installed the GNU Arm Embedded Toolchain manually, Visual Studio will use the version you installed.

To install the toolchain, on the Arm developer website, find the GNU Arm Embedded Toolchain (arm-none-eabi) 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 > Azure Sphere.
  2. Enter the GNU Arm Embedded Toolchain installation path in the Azure Sphere: Arm Gnu Path setting.

To install the toolchain, on the Arm developer website, find the GNU Arm Embedded Toolchain (arm-none-eabi) that includes the compiler for the ARM Cortex-M4 processor. Follow the instructions there to download and install the compiler for your OS platform.

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.

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 .

To debug on the real-time cores, use the az sphere 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:

    az 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:

    az sphere device enable-development --enable-rt-core-debugging  --catalog <CatalogName>  --resource-group <ResourceGroupName>
    
  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 az sphere device enable-development command fails, see Troubleshoot Azure Sphere problems for help.

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 HelloWorld_RTApp_MT3620_Baremetal (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 pane, change the value of f from zero to one.

  4. Step through the code as usual.

Build the sample

  1. Open a command-line interface using PowerShell, Windows Command Prompt, or Linux command shell. Navigate to your project build directory.

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

    cmake --preset <preset-name> <source-path>
    
    • --preset <preset-name>

      The build configuration preset name as defined in CMakePresets.json.

    • --build <cmake-path>

      The binary directory that contains the CMake cache. For example, if you run CMake on an Azure Sphere sample, the build command would be cmake --build out/ARM-Debug.

    • <source-path>

      The path of the directory 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 ^
    --preset "ARM-Debug" ^
    "C:\AzSphere\azure-sphere-samples\Samples\HelloWorld\HelloWorld_RTApp_MT3620_BareMetal"
    

    Windows PowerShell

    cmake `
    --preset "ARM-Debug" `
    "C:\AzSphere\azure-sphere-samples\Samples\HelloWorld\HelloWorld_RTApp_MT3620_BareMetal"
    
  3. Run Ninja to build the application and create the image package file:

    ninja -C out/ARM-Debug
    

    Ninja places the resulting application and .imagepackage files in the specified directory.

    You can also invoke Ninja through CMake with the following command:

    cmake --build out/<binary-dir>
    

    Set <binary-dir> to the binary directory that contains the CMake cache. For example, if you run CMake on an Azure Sphere sample, the build command would be cmake --build out/ARM-Debug.

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:

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

    az sphere device sideload deploy --image-package <path-to-imagepackage>
    

    The application will start to run soon after it's loaded. The following will be displayed on the connected terminal emulator:

    Tick
    
    Tock
    
    Tick
    .
    .
    .
    
  3. Get the component ID for the image:

    az sphere 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:

    ...
      "Identity": {
        "ComponentId": "<component-id>",
        "ImageId": "<image-id>",
        "ImageType": "Application"
      },
    ...
    

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

    az sphere device app stop --component-id <component id>
    
    az sphere device app start --component-id <component id>
    
    az sphere device app show-status --component-id <component id>
    

Debug the sample

  1. Stop the application if it's running.

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

    az sphere device app start --debug-mode true  --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 run 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