Introduction
The Azure Sphere MT3620 MCU has multiple user accessible ARM compute cores, One high level application processor (A7) and two real-time cores (M4) for user applications. A development team can choose to deploy applications on one or more of these cores to meet project requirements. The device provides inter-core communications so that data can be passed between the cores.
This blog does not attempt to capture every aspect of developing real-time applications on Azure Sphere. Microsoft has documented all these details in the on-line documentation. Instead, the blog will give an overview of resources/examples available and details on how to use the examples.
Goals
This blog will document . . .
- Where to find documentation on using the M4 cores
- How to debug M4 applications
- Where to find example applications that run on the M4 cores
- What you need to know to run the example applications
- Information on how to setup applications for inter-core communication
Why would a developer choose to use one of the real-time M4 cores?
The A7 application processor is running a Linux kernel to manage system resources and to run user applications. When user applications run on the A7 processor they will be interrupted by system processes. These system process may be performing some background task such as servicing the communication pipe to Azure, or maybe interacting with the Azure Sphere Security Service (AS3), for example. If the user application has real-time requirements, then these background tasks will interrupt the application. If the application has strict timing requirements, then these interruptions can cause errors in the application execution, or require complex error handling logic. Developers can choose to offload applications with real-time requirements to one or both M4 cores on the device.
MT3620 Compute Cores
Compute Core | Clock Speed | Purpose | Application Memory Available | Application Binary Size Limit | Constraints |
---|---|---|---|---|---|
ARM Cortex-A7 | 500 MHz | High level applications | 256 KB RAM + 1 MB of Flash shared across all cores | 1MB for the entire *.imagepackage file |
|
ARM Cortex-M4F(0) | 200 MHz | Real-Time applications | 64 KB SYSRAM + 192 KB Tightly-coupled memory (TCM) + 1 MB of Flash shared across all cores |
| |
ARM Cortex-M4F(1) | 200 MHz | Real-Time applications | 64 KB SYSRAM + 192 KB Tightly-coupled memory (TCM) + 1 MB of Flash shared across all cores |
|
Table of Contents
Links to Documentation
- Microsoft Documentation
- Overview of real-time capable application development (Read this page!)
- MediaTek Documentation
- MT3620 Datasheet V1.3
- General overview of the MT3620
- MT3620 M4 User Manual
- More details on the M4
- Links to supporting documentation
- Details on the M-HAL (MediaTek Hardware Abstraction Layer)
- More details on the M4
- MT3620 M4 API Reference Manual
- Detailed API document
- Includes details for all M-HAL data structures, functions and structures
- MT3620 M4 Hardware Functional Specification
- Available with NDA
- To start the NDA process email Azure.Sphere@avnet.com
- MT3620 Datasheet V1.3
Real-Time OS Options
While the developer does not have control over the OS running on the A7 application processor, they do have complete control over what OS they want to run on the M4 cores. The user is free to port any RTOS they want to run on the M4 core(s). There are currently example applications available for the OSes listed below.
BareMetal Implementation (no OS)
Microsoft, MediaTek and CodeThink have all implemented BareMetal M4 real-time examples using this method.
In a previous life I called this a "Process Loop" implementation. There is no operating system, just an application running in a loop. BareMetal applications can be lean and fast. BareMetal applications don't have any OS support so they must implement any required services.
FreeRTOS
MediaTek has developed M4 real-time examples using FreeRTOS.
From the FreeRTOS website: "FreeRTOS is a market-leading real-time operating system (RTOS) for microcontrollers and small microprocessors. Distributed freely under the MIT opeb source license, FreeRTOS includes a kernel and a growing set of libraries suitable for use across all industry sectors. FreeRTOS is build with an emphasis on reliability and ease of use"
THREADX/Azure RTOS
In April of 2019 Microsoft acquired Express Logic and their THREADX RTOS. Microsoft is re-branding THREADX RTOS as Azure RTOS. I could not find any Azure RTOS Azure Sphere examples while writing this blog. When Azure RTOS examples become available, this blog will be updated.
From the THREADX web site: "THREDX RTOS is Express Logic's advanced Industrial Grade Real-Time Operating System (RTOS) designed specifically for deeply embedded, real-time, and IoT applications. THREADX RTOS provides advanced scheduling, communication, synchronization, timer, memory management, and interrupt management facilities. In addition, THREADX RTOS has many advanced features, including its picokernel architecture, preemption-threshold scheduling, event-chaining, execution profiling, performance metrics, and system event tracing. Combined with its superior ease-of-use, THREADX RTOS is the ideal choice for the most demanding of embedded applications. As of 2017, THREADX RTOS has over 6.2 billion deployments, in a wide variety of products, including consumer devices, medical electronics, and industrial control equipment."
Debugging M4 Real-Time Applications
A7 high level application debugging is well integrated into the Visual Studio IDE. The M4 debugging tools exist but they are currently not as integrated into the Visual Studio environment as the A7 tools. But don't worry, you still have all the same functionality available including the ability to step through your code at run-time.
Debug Output
When you run high level applications from Visual Studio you can use the Log_Debug() function to output debug information to the Visual Studio output window. For M4 applications you don't have access to this function. You can still output debug, but your M4 application must route the output to either one of the MT3620 ISUx UARTS or the M4 Debug UARTs. To see this output you need a USB to TTL Serial Cable like the EZsync012 device connected to your development PC and a terminal program like Putty or TeraTerm configured to the correct com port.
I know we have not discussed the M4 examples yet, but I wanted to capture how each set of examples sends debug data since we're talking about debug output. I'm not going to go into the nitty-gritty details, but you can look at the examples to see how each is implemented.
Microsoft Examples
There are a couple of Microsoft M4 example applications, they implemented two different methods to transmit debug information . . .
- HelloWorld_RTApp_MT3620_BareMetal
- static void Uart_WritePoll(const char *msg);
- IntercoreComms_RTApp_MT3620_BareMetal
- void Uart_WriteStringPoll(const char *msg)
- When using the Microsoft examples configure the PC serial port to 115200-8-N-1
MediaTek Examples
The MediaTek M4 examples are mostly implemented using freeRTOS. The examples use a printf() implementation to transmit debug information.
- When using the MediaTek examples configure the PC serial port to 115200-8-N-1
CodeThink Examples
The CodeThink M4 examples are all BareMetal implementations and they use a custom routine called UART_Print().
- int32_t UART_Print(UART *handle, const char *msg)
- When using the CodeThink examples configure the PC serial port to 115200-8-N-1
Using the M4 Debug UARTs
The MT3620 pins out both M4 Debug UARTs. On the Avnet Kit these are exposed on the J11 header, see the diagram below. Note that these are TX only from the M4. The MediaTek examples document how to change the example applications to use the M4 Debug UART.
GDB Debugger Integration
One of my favorite Azure Sphere development features is the ability to use the GDB debug utility. This allows me to set break points, monitor variables and single step through my code at run-time. We're doing embedded development with Azure Sphere and having this functionality makes developing and debugging embedded applications as easy as debugging modern PC based applications. To use the debugger for M4 applications we have to install an additional USB driver. Actually, I think you need to install this USB driver to do any M4 development with Visual Studio. If you try to run an M4 application and you see an error similar to . . .
"Unable to start debugging. Unexpected GDB output from
command "-target-select remote *:4444".
*:4444: No connection could be made because the
target machine actively refused it."
Then you need to install the USB drivers. From the Microsoft documentation:
- To Install the USB drivers for the M4 debugger
- Right-click the Azure Sphere Developer Command Prompt shortcut and select More>Run as administrator.
- The
--EnableRTCoreDebugging
parameter requires administrator privilege because it installs USB drivers for the debugger.
- The
- Enter the following azsphere command:
azsphere device enable-development --enablertcoredebugging
- 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.
- Right-click the Azure Sphere Developer Command Prompt shortcut and select More>Run as administrator.
After the driver is installed you can set breakpoints, monitor variables and single step through your code at run-time! The screenshot below shows my application halted and the value of the variable my mouse is hovering over.
Links to Source Code Repositories
I've included links to the GitHub MT3620 repositories discussed in this blog. In each case, you should clone the entire repository since there are usually supporting utilities/code/libraries included at higher levels.
Example Applications Available
Table showing examples that exist in each repository (Last updated March 2020)
Feature/Example | Microsoft Example Applications | MediaTek Example Applications | CodeThink Example Applications |
---|---|---|---|
ADC | High Level Example (A7) | FreeRTOS (M4) Example | BareMetal (M4) Example |
ADC Joystick | BareMetal (M4) Example | ||
Azure IoT | High Level Example (A7) | ||
Deferred Update (catch OTA update signal and postpone it) | High Level Example (A7) | ||
DMA | FreeRTOS (M4) Example | ||
DNS Service Discovery | High Level Example (A7) | ||
External MCU Update | High Level Example (A7) | ||
GPIO | High Level Example (A7) | FreeRTOS (M4) Example + BareMetal (M4) Example | |
GPIO + ADC | BareMetal (M4) Example | ||
GPT (General Purpose Timer) | FreeRTOS (M4) Example | BareMetal (M4) Example | |
Hello World (simple application to verify development environment) | High Level (A7) + BareMetal (M4) Examples | ||
HTTPS | High Level Example (A7) | ||
I2C | High Level Example (A7) | BareMetal (M4) Example | |
I2C OLED | BareMetal (M4) Example | ||
I2S | FreeRTOS (M4) Example | BareMetal (M4) Example | |
InterCoreComms | High Level (A7) + BareMetal (M4) Examples | FreeRTOS (M4) Example + HighLevel Example (A7) MBOX | |
LP (Low Power Example) | FreeRTOS (M4) Example | ||
Mutable Storage (Using Flash Memory) | High Level Example (A7) | ||
Power Down (Low Power Example) | High Level Example (A7) | FreeRTOS (M4) Example (LP) | |
Private Network Services | High Level Example (A7) | ||
PWM | High Level Example (A7) | FreeRTOS (M4) Example | BareMetal (M4) Example |
SPI | High Level Example (A7) | FreeRTOS (M4) Example (SPIM) | BareMetal (M4) Example |
SPI SDCard | BareMetal (M4) Example | ||
SPI SSD1331 (Display) | BareMetal (M4) Example | ||
System Time | High Level Example (A7) | ||
UART | High Level Example (A7) | FreeRTOS (M4) Example | |
WiFi | High Level Example (A7) | ||
WiFi Setup and Device Control Via BLE | High Level Example (A7) |
In the sections below, I've add notes that will help you run the example applications from each code base. I have not run all these examples myself, but I have run at least a few from each source.
Microsoft Examples
The Microsoft examples are mostly high level A7 applications. They used to have lots of BareMetal implementations, but since the CodeThink M4 examples became available, Microsoft has removed most of the M4 examples from their repo. I know this is a M4 Blog, but I have to talk about the Microsoft examples, they are very useful.
What I like about these examples
My favorite thing about the Microsoft examples is that every time they release a new Azure Sphere feature, they also release an example application that shows you how to use the feature. You get a working application that you can use as a starting point for your own application. Or if you just want to port the new feature into an existing application, you can see all the required code to do so.
I also really like the Azure IoT example application. This working application will connect to an Azure IoT Hub or IoT Central Application with very little effort. Since Azure Sphere is a Secure, Connected MCU, every Azure Sphere application should start with the Azure IoT example as it's starting point. The example uses the Azure Device Provisioning Service (DPS) for "touchless" IoT Hub provisioning, sends telemetry to Azure, manages device twins and the list goes on.
What you need to know to use these examples
The Microsoft examples all use the Hardware Abstraction layer that will allow you to use the examples with any of the current Azure Sphere Development Kits. Since I work for Avnet, I use the Azure Sphere Starter Kit for all my development and demo applications. If you're using one of the other kits, you may not need to make any changes to use the Microsoft examples.
If you want to use the Azure Sphere Starter Kit with the Microsoft Examples you need to make the following changes . . .
- Open the CMake Project
- Open the CMakeSettings.json file from the Solution Explorer window
- Click on the "Edit JSON" Link in the CMake Settings window
4. Change the "AzureSphereTargetHardwareDefinitionDirectory" entry to reference the avnet_mt3620_sk directory.
5. Save the file
6. CMake will regenerate the build files and you can build and run the example on the Avnet Starter Kit
MediaTek Examples
The MediaTek examples all run on the M4 cores with the exception of the Mail Box (MBOX) example. The MBOX example includes one high level (A7) application and two real-time (M4) applications to demonstrate passing messages between cores.
What I like about these examples
MediaTek has taken the time to capture all the details to use either the Avnet Azure Sphere Starter Kit, or the Seeed RDB. The examples don't use external hardware, but instead use loop-backs (when possible) between different interfaces to show how to use the hardware. So you should be able to use these examples without having to buy any additional hardware.
What you need to know to use these examples
To use the MediaTek examples you need to update the gcc build environment:
- Update the gcc build environment. To build the examples you need to make one simple change to your gcc build environment. The statement below in included on each of the MeditTek examples.
Important Note! To reuse the official GCC Cortex-M4F port, the gcc compiler flag should be modified to use FPU instructions. Please copy the AzureSphereRTCoreToolchainVFP.cmake file into the Azure Sphere SDK install folder. (Default path is C:\Program Files (x86)\Microsoft Azure Sphere SDK\CMakeFiles)
- The AzureSphereRTCoreToolchainVFP.cmake file in included in each example directory
- The file only needs to be copied to the *SDK\CMakeFiles directory once
- The examples use the ISU0 UART or the dedicated M4 debug UART to output debug information. To see this output you need to use a terminal program like TeraTerm or Putty and an external USB to TTL Serial Cable.
- Hardware: USB to TTL Serial Cable like the EZsync012 device
- The connection points for the UART are detailed on the GitHub project page(s)
- Connect the TX signal from the MT3620 Kit to the RX on the TTL Serial Cable
- Connect the GRD signal from the MT3620 Kit to the GRD on the TTL Serial Cable
- The connection points for the UART are detailed on the GitHub project page(s)
- Hardware: USB to TTL Serial Cable like the EZsync012 device
- 115200, 8, N, 1
Example output
Here's my Tera Term configuration and example application output from the MediaTek freeRTOS UART example. Note that your com port will likely be different.
CodeThink Examples
I have the least amount experience with the CodeThink examples. These examples all target the Seeed RDB with no method to easily change the target device. To use them with the Avnet Starter Kit you may need to make code changes (hw definitions) and figure out how to wire your kit.
For example I ran the I2C_OLED_RtApp_MT3620_BareMetal example on my starter kit. I needed to make two code changes. This application assumes the SSD1306 OLED display is wired to ISU1. On the Avnet Azure Sphere Starter Kit, the (un-populated) OLED connector is wired to ISU2. So I had to update the app_manifest.json file and change main.c to reference ISU2. After these two changes the application ran just fine.
What I like about these examples
The examples include implementations like using the ADC interface to read joystick outputs, or using the I2C to drive an OLED. These examples not only show you how to use the hardware interfaces, but have examples that do useful things!
What you need to know to use these examples
To use these examples you need to first clone the main repository, and then pull in the lib directory files. Follow the directions below . . .
- Identify a directory for the source file, I'm going to use c:\temp\CodeThinkExamples
- Start a command line application such as "Windows PowerShell"
- Create the directory and change to that location
- Clone the repo with the command git clone https://github.com/CodethinkLabs/mt3620-m4-samples.git
- Now change to the newly created mt3620-m4-samples directory
- cd mt3620-m4-samples
- Pull the library files. This command will update each example directories \lib folder
git submodule update --init
Inter-Core Communications
MediaTek has implemented a mailbox system to send messages between all the different compute cores. To see how to use the mailboxes there are a couple of example applications that you can run and study.
Microsoft example using inter-core messaging
MediaTek example using inter-core messaging
Partner Applications
Partner applications is the implementation to allow applications on different cores to communicate with each other.
app_manifest.json
Just like we have to give our Azure Sphere application explicit permission to use any hardware interface in the app_manifest.json file, we must also give our application explicit permission to communicate with other applications on different cores. Each application is identified by it's component ID as defined in the app_manifest.json file. The example below is from the MediaTek MBOX example. The app_manifest.json capability is called "AllowedApplicationConnection."
The MBOX example includes three different applications. One high level application and two real-time applications. Let's examine the app_manifest.json files from each application to see how they define the partner applications. Notice that the Red boxes all contain the same GUID (*627). That's the GUID for the high level app (as defined by the ComponentId field). Both of the real-time applications list the Red GUID (*627), so both real-time applications are allowed to communicate with the high level application. Conversely, the high level application lists both of the real-time application GUIDS the Purple (*AAA) and Green boxes (*BBB). So the high level application can talk to both of the real-time applications.
launch.vs.json
For OTA deployments the app_manifest.json files are the only requirement for the applications to all run on the MT3620 at the same time (other than correctly configuring the OTA update, that's a future blog). But for the applications to all run in a debug scenario, we also need to define the partner applications in the launch.vs.json file. Visual Studio uses this file to determine if more than one application should be running on the target when starting a new application. By default when starting a new application from Visual Studio all other applications on the device will be removed from the device. The partner component entries tell Visual Studio that the other specific applications should be allowed to run. When these entries are not correct you can start an application on the device then when you start a second application, the first application will exit. This is pretty frustrating, ask me how I know!
The concept is exactly the same as with the app_manifest.json file, just the key names are different. See the launch.vs.json file for the high level application below. Note that the *AAA and *BBB GUIDS are both defined. If we looked at the real-time applications launch.vs.json files they would contain the high level applications *.627 GUID.
Developing Multiple Applications at once
You may be thinking, "How can I run three applications in Visual Studio at the same time?" That's a great question to be asking yourself. The answer is, you don't. For any development across multiple cores you'll run multiple Visual Studio instances at the same time. Each with one of the applications for each core. So for the MBOX example, you'll run three Visual Studio instances; one for the high level application and two more, one for each real-time application.
Creative ways to leverage the extra M4 Cores
These are some ideas on how the M4s could be leveraged in a deployment
Low Power Implementations
While there is currently not a low power feature to power down the A7 or WiFi radio while allowing the M4 to run, I hope we'll see a feature like this in the future. Imagine if you had the ability to power down the A7 and the WiFi radio while allowing the M4 to continue to run.
It could look like this . . .
- A7 boots up and determines that it does not have any work
- Turn the the WiFi radio off
- Put itself to sleep
- M4 boots and reads/process sensor data
- When the M4 needs to send telemetry
- Turn on the WiFi radio
- Wake the A7
- Send the telemetry over the inter-core communication path to the A7 application
- When the A7 wakes up, the high level application runs
- Establishes a connection to the cloud provider
- Sends telemetry
- Turn the WiFi radio off
- Put itself to sleep
- Repeat!
This is a simple straight forward process that could save lots of power.
Access additional Memory
Maybe your application will run just fine on the A7 application processor, but maybe your application needs more RAM for some large data structures or maybe log data in case the application hits an error. You could use one or both of the M4's as data stores. Remember from above each M4 has 64 KB SYSRAM + 192 KB Tightly-coupled memory. If we don't use the M4's we have no way to access these resources.
The simple scheme could look like this . . .
- Implement M4 applications that simply receive data and store it in a ring buffer in memory
- The application will fill memory and when it's full it will overwrite the oldest data with fresh data
- The A7 sends data to one or both M4's using the inter-core communication path
- If the A7 needs to retrieve the data for what ever reason it could ask the M4 for a data dump
I realize that I've left out all the important details, but you get the idea. By the way this was not my idea, one of my star Azure Sphere Students Ed had this idea, it's brilliant!
What's your clever idea?
Post it in the comments, I want to hear it!
Conclusion
That ended up being way more information than I thought it would be. But looking back, each piece is important to understand. The fact that the MT3620 has multiple cores can really simplify your design. You can off load real-time tasks to one or more M4 cores and allow your high level application to focus on your business logic and communicating with your cloud service provider. There are a few pieces that all need to come together for these applications to communicate, but the good news is that Microsoft and MediaTek have developed example applications that show you exactly what to do!
I would love to hear your comments and questions.
Thank you for spending your valuable time reading this blog!
Brian