Skip to content

Commit 704c725

Browse files
authored
Merge pull request #330 from arduino/karlsoderby/giga-rpc
Karlsoderby/giga rpc
2 parents 467d0db + c6c1cb6 commit 704c725

File tree

5 files changed

+192
-1
lines changed

5 files changed

+192
-1
lines changed

content/hardware/08.mega/boards/giga-r1/product.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ url_guide: /tutorials/giga-r1/giga-getting-started
55
core: arduino:mbed_giga
66
---
77

8+
89
The GIGA R1 is a powerful, feature-packed board with a large amount of GPIOs and dedicated connectors. Based on the [STM32H747XI](/resources/datasheets/stm32h747xi.pdf) micro based on the [Mbed OS](https://os.mbed.com/), the GIGA R1 features 75 GPIOs, a [dual core processor](/tutorials/giga-r1/giga-dual-core), [advanced ADC/DAC](/tutorials/giga-r1/giga-audio) features as well as camera & display connectors. It also has a rich [USB interface](/tutorials/giga-r1/giga-usb) with support for HID via USB-C and USBHost (keyboard, mass storage) via a dedicated USB-A connector.
910

10-
**Please Note:** The [GIGA R1](/hardware/giga-r1) & [GIGA R1 WiFi](/hardware/giga-r1-wifi) are identical except for the onboard Wi-Fi/BLE module & crypto chip. The documentation refers to the board simply as **GIGA R1**, except for specific information regarding the Wi-Fi/BLE module.
11+
**Please Note:** The [GIGA R1](/hardware/giga-r1) & [GIGA R1 WiFi](/hardware/giga-r1-wifi) are identical except for the onboard Wi-Fi/BLE module & crypto chip. The documentation refers to the board simply as **GIGA R1**, except for specific information regarding the Wi-Fi/BLE module.
12+
Loading
Loading
Loading
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
---
2+
title: Dual Core Processing with GIGA R1
3+
description: 'Learn how to setup and control the M7 and M4 cores, and how to communicate between them using RPC.'
4+
author: Karl Söderby
5+
tags: [Dual Core, RPC, MicroPython]
6+
---
7+
8+
***PLEASE NOTE: This article is still in progress.***
9+
10+
The GIGA R1's microcontroller, the **STM32H747XI** has two processor cores, the **M7** and **M4**, clocking in at 480MHz and 240Mhz respectively.
11+
12+
Having two cores in a microcontroller brings a significant advantage, to run two main applications simultaneuously, and communicate with them through something called **Remote Procedure Call (RPC)**.
13+
14+
## Goals
15+
16+
In this tutorial, we will take a closer look at how to make use of the dual core, by:
17+
- Set up and run MicroPython on the M7 core.
18+
- Set up and run Arduino code on the M4 core.
19+
- Link, or bind, the two cores through RPC, using a specific serial protocol.
20+
- Control a servo motor by requesting the service from the M7 to the M4.
21+
22+
## Hardware & Software Needed
23+
24+
The hardware needed for this project:
25+
26+
- [GIGA R1](/hardware/giga-r1) / [GIGA R1 WiFi](/hardware/giga-r1-wifi)
27+
- Servo motor.
28+
29+
For programming the M4 core (C++):
30+
31+
- [Arduino IDE](https://www.arduino.cc/en/software)
32+
33+
For programming the M7 core (MicroPython):
34+
35+
- [dfu-util](https://dfu-util.sourceforge.net/)
36+
- [firmware.dfu](linktofw)
37+
38+
You will also need a MicroPython supported editor, such as:
39+
- [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython)
40+
- [Thonny](https://thonny.org/)
41+
42+
***The installation for `dfu-util` varies between operation systems. For installation using [brew.sh](https://formulae.brew.sh/formula/dfu-util) simply use `brew install dfu-util`.***
43+
44+
## Remote Procedure Call (RPC)
45+
46+
RPC is a method that allows programs to make requests to programs located elsewhere. It is based on the client-server model (also referred to as caller/callee), where the client (caller) makes a request to the server (callee).
47+
48+
An RPC is a synchronous operation, and while a request is being made (client/caller) to another system, the operation is suspended. On return of the results, the operation is resumed. On the other side, (server/callee) performs the subroutine on request, and suspends any other operation as well. After it sends the result to the client, it resumes its operation, while waiting for another request.
49+
50+
![Request routine.](assets/rpc-basics.png)
51+
52+
### RPCs in the Arduino Environment
53+
54+
As some microcontrollers, including the STM32H747XI, has two processors, it is possible to program them both to perform individual tasks, and enable communication between them via an RPC.
55+
56+
The advantage of this is great, as you essentially have "two" Arduino boards running (on the some board). For example, you can run a machine learning module on one of the core, while another core is connected to a network system such as the [Arduino IoT Cloud](https://create.arduino.cc/iot/). Running these applications in parallel increases performance, as you split the work load and allow them to run with less blocking code for example.
57+
58+
![Communication between M7 and M4 core.](assets/rpc-m7-m4.png)
59+
60+
### RPC vs Multi-Threading
61+
62+
This is a similar, but not identical to [multi-threading on Arduino boards](https://github.com/arduino-libraries/Arduino_Threads). Multi-threading essentially allows you to run code asynchronously on a single processor, and create communication lines between the threads. While RPC is similar, it differs as communication can be set up between two remote systems (such as two different processors, in this case).
63+
64+
Both methods are great to apply in more sophisticated and performance-craving projects, as you can combine the two methods to create several threads, running on separate cores.
65+
66+
### Use Cases
67+
68+
RPC and Multi-Threading can be used for several different setups. Here are some good combinations that can be considered:
69+
70+
- Use **Core A** for networking (e.g. publishing to a MQTT channel) and **Core B** for data recording & analysis.
71+
- Use **Core A** for image capturing, and **Core B** for image processing.
72+
- Use **Core A** for storing sensor data locally (USB/SD) and **Core B** for streaming it to a cloud service.
73+
74+
## GIGA R1 RPC Example
75+
76+
The GIGA R1's STM32H747XI microcontroller includes the M7 and M4 core. In this example, we will:
77+
- Install MicroPython on the M7 core (this is the main core).
78+
- Load a script that sets up the **M7 as a server/callee**.
79+
- Upload a sketch to the **M4 that sets it up as a client/caller**.
80+
- Make a request from the M4 to the M7.
81+
82+
### 1. Upload Sketch to M4 Core
83+
84+
We will start by uploading a sketch to the M4 core, which will be running Arduino code. This requires the [Arduino IDE](https://www.arduino.cc/en/software) to be installed, as well as the **Arduino MbedOS OS GIGA Boards** core installed.
85+
86+
**1.1.** Open the Arduino IDE, and the board manager (in the menu to the left). Install the **Arduino MbedOS OS GIGA Boards** package.
87+
88+
**1.2.** Now we need to select the right board. This is **not** the GIGA R1, as the default is H7. We instead need to select the **STM32H747 M4 coprocessor**. This is the M4 on the GIGA R1.
89+
90+
**1.3.** With the board selected, you will now have the option to select **Flash Split** and **Target Board**. These are manual options available in the **Tools** section of the IDE. Here, we need to select the **1.5MB M7 + 0.5MB M4** configuration for the Flash Split, and **Giga** for Target Board.
91+
92+
![Select Flash Split + Target board.](assets/flash-split.png)
93+
94+
**1.4.** Upload the following sketch to the board:
95+
96+
```arduino
97+
#include "RPC.h"
98+
#include <Servo.h>
99+
100+
uint32_t servo_new(uint32_t id) {
101+
Servo* servo = new Servo();
102+
return (uint32_t)servo;
103+
}
104+
105+
void servo_attach(uint32_t id, int pin) {
106+
Servo* servo = (Servo*)id;
107+
servo->attach(pin);
108+
}
109+
110+
void servo_write(uint32_t id, float angle) {
111+
Servo* servo = (Servo*)id;
112+
servo->write(angle);
113+
}
114+
115+
void setup() {
116+
RPC.begin();
117+
RPC.bind("servo_new", servo_new);
118+
RPC.bind("servo_attach", servo_attach);
119+
RPC.bind("servo_write", servo_write);
120+
}
121+
122+
void loop() {
123+
delay(1000);
124+
}
125+
```
126+
127+
### 2. Installing MicroPython
128+
129+
To install MicroPython on the GIGA R1, you will need to flash a specific MicroPython firmware to the **M7 processor.** This requires the [dfu-util](https://dfu-util.sourceforge.net/) tool.
130+
131+
**2.1.** Download the [MicroPython firmware for GIGA R1](/micropython).
132+
133+
**2.2.** Download [dfu-util](https://dfu-util.sourceforge.net/) (also available via [brew.sh](https://formulae.brew.sh/formula/dfu-util)). Make sure the tool is added to PATH on your machine.
134+
135+
**2.3.** Open a terminal, and navigate to the directory where you saved the downloaded MicroPython firmware.
136+
137+
**2.4.** Double tap the reset button on the GIGA R1 (while it is powered). This will enter bootloader mode.
138+
139+
**2.5.** Finally, load the MicroPython firmware, by using the following command:
140+
141+
```
142+
$ dfu-util -w -a 0 -d 2341:0366 -D <firmware>.dfu
143+
```
144+
145+
This will start an uploading process that can be tracked in the terminal. Once it is done, the green LED will be pulsing. Success!
146+
147+
Make sure to reset the board before continuing (tap the reset button).
148+
149+
### 3. MessagePack
150+
151+
***[MessagePack]() is a serialization protocol made by Peter Hinch that we are using in this implementation to communicate between the cores.***
152+
153+
In order to implement an RPC between the M4 and M7 cores, we use MessagePack, or the `umsg` module. This module needs to be present on your board, so that we can use it a MicroPython script (it is not part of the MicroPython installation).
154+
155+
When we install MicroPython on the M7 core, we create a mass storage device that we can simply drag and drop files to.
156+
157+
**3.1.** First, download the [umsg module]() and unpack it.
158+
159+
**3.2.** Open the mass storage device (available in e.g. finder), and drag only the `umsg` folder to the root of the mass storage device.
160+
161+
You now have the `umsg` module available on your board, and can be called from a MicroPython script.
162+
163+
### 4. Load MicroPython Script
164+
165+
The final step is to load a MicroPython script to the M7 that will interact with the M4 core, essentially using the "server-client" protocol.
166+
167+
**4.1.** Open the MicroPython editor (such as [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython)).
168+
169+
**4.2.** Select/connect your board. You can test out if it is connected properly to your computer by running a simple `print ("test")`. If it shows in the REPL, it works.
170+
171+
**4.3.** Paste the script below to the editor, and press the play/run button.
172+
173+
```python
174+
import arduino
175+
arduino.init()
176+
servo = arduino.Servo()
177+
servo.attach(6)
178+
servo.write(64)
179+
```
180+
181+
This basic script includes the API for controlling a servo motor. But, the main difference here, is that the servo motor is controlled on the M4 core.
182+
183+
When for example `servo.attach(6)` is run, this action is not executed on the M7 core, but instead requested to run on the M4.
184+
185+
You can revisit [the code in the first step](#1-upload-sketch-to-m4-core), to understand how the link is made between the MicroPython script, and the Arduino sketch.
186+
187+
## Conclusion
188+
189+
At the end of this tutorial, we have achieved the communication between the M4 and the M7 core, via something called **RPC**. The example used in this tutorial is a servo motor, but there are of course many more alternatives that you can choose from.

0 commit comments

Comments
 (0)