You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/hardware/10.mega/boards/giga-r1-wifi/tutorials/giga-dual-core/giga-dual-core.md
+90-87Lines changed: 90 additions & 87 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,19 +36,75 @@ In this guide you will discover:
36
36
37
37
***\*For instructions on how to install the GIGA Core, follow the [Getting Started with GIGA R1 guide](/tutorials/giga-r1-wifi/giga-getting-started).***
38
38
39
+
## M4 Support
40
+
41
+
The M4 processor can access most of the peripherals that the M7 can access, with some exceptions.
42
+
43
+
The M4 supports:
44
+
- Wi-Fi®
45
+
- I2C
46
+
- SPI
47
+
- UART
48
+
- CAN
49
+
- DAC
50
+
- ADC
51
+
- Bluetooth® Low Energy (via [ArduinoBLE Library](https://www.arduino.cc/reference/en/libraries/arduinoble/))
***\*Serial Communication from the M4 can be enabled by setting up an RPC that allows the M4 & M7 cores to communicate. Using `RPC.print()` (M4) and `RPC.read()` (M7) helps achieve this. See [RPC Serial Example](#rpc-serial).***
58
+
59
+
### Boot / Disable M4
60
+
61
+
The M4 core is by manufacturing default, disabled when booting the board. The M4 core can however be booted by using the `RPC.begin()` command, which includes the necessary functions to boot the M4 core. See the [RPC.cpp source file](https://github.com/arduino/ArduinoCore-mbed/blob/main/libraries/RPC/src/RPC.cpp#L122-L140) for more details.
62
+
63
+
### Boot / Disable M7
64
+
65
+
The M7 is booted by default and there is currently **no option to disable** this core.
66
+
67
+
### Peripheral Interference
68
+
69
+
When booting the M4, the M4 will execute the sketch that has been uploaded to its flash memory. It is a good idea to track what type of code you are running on the M4, as you may create interference between different peripherals. If you run simply a blank sketch on the M4, it should **not** create any interference.
70
+
71
+
An example of this is if you use the `CAN` library. If you are running a CAN application on the **M7**, you will disrupt it if you enable it on the **M4**. The dual core feature is not intended for using the same peripheral, bus etc.
72
+
73
+
***Tip: name your sketches with a `_M4` and `_M7` suffix/prefix, and create an initialization sequence. E.g. blink the blue LED three times whenever the M4 boots up.***
74
+
75
+
## Pin Priority
76
+
77
+
As the M7 and M4 core share their pins, which one gets priority to the pin? It can be assumed that as the M7 is the more powerful core, it gets first access.
78
+
79
+
This is however **not true** as pin priority is random. If both cores tries to access the same pin (e.g. `D27`), it is simply random who gets access.
80
+
81
+
***When developing dual core applications, it is a good idea avoiding using the same pins & peripheral for many reasons.***
82
+
39
83
## Programming M4/M7
40
84
41
-
Programming the cores is done via the Arduino IDE, in a special interface that appears only when you **select the Arduino GIGA R1 board** from the board menu.
85
+
When programming the GIGA R1 WiFi's M7 and M4, we **create a sketch for each core**, and program them like we would program two individual Arduino boards. As only a single serial port is available, we need to specify which core we want to target.
86
+
87
+
Some essential things to consider when programming the cores are:
88
+
- You need to [partition the memory](#partitioning-the-flash-memory), allocating flash memory to the M4 core.
89
+
- You need to select the [target core](#target-core), which is either **Main Core** or **M4 Co-processor**.
90
+
- The M4 has no serial communication enabled, here we need to use RPC (see [RPC Serial example](#rpc-serial)).
91
+
92
+
When writing multiple sketches, there are some things to consider to make your development experience easier:
93
+
- Name your sketches with either `_M4` or `_M7` suffix or prefix. This will make it easier if the code is intended to be shared with others.
94
+
- Consider having a starting sequence (e.g. the blue LED blinking 3 times), whenever a core is initialized.
95
+
- Always include `RPC.begin()` on your M7 core sketch.
42
96
43
97
### Partitioning The Flash Memory
44
98
45
-
To allocate memory for the M4, the flash memory can be partitioned. This is done by navigating to **Tools > Flash Split** in the IDE.
99
+
To allocate the flash memory for the M4, the flash memory can be partitioned. This is done by navigating to **Tools > Flash Split** in the IDE.
100
+
101
+
***Note that the flash memory is the space where the application code (your sketch) is stored. It is not the RAM memory (which is significantly lower).***
46
102
47
103

48
104
49
-
-**2MB M7 + M4 in SDRAM (default)** - this option is the default configuration, which is for programming the M7 only. This allocates no memory to the M4.
50
-
-**1.5MB M7 + 0.5MB M4** - useful when larger amount of memory is required on the M7.
51
-
-**1MB M7 + 1MB M4** - useful when you need to balance the memory equally between the M4 and M7 cores.
105
+
-**2MB M7 + M4 in SDRAM (default)** - this option is the default configuration, which is for programming the M7 only. This allocates no flash memory to the M4.
106
+
-**1.5MB M7 + 0.5MB M4** - useful when larger amount of flash memory is required on the M7.
107
+
-**1MB M7 + 1MB M4** - useful when you need to balance the flash memory equally between the M4 and M7 cores.
52
108
53
109
***It is required to use option 2 or 3 if you intend to program the M4 via the IDE, as the default option provides no memory allocation for the M4.***
54
110
@@ -88,108 +144,55 @@ Once the M4 is booted from the M7, both cores will run in parallel, much like tw
88
144
89
145
Uploading new sketches works the same as a typical upload procedure. The new sketch will overwrite the current sketch running on the core you upload to.
90
146
91
-
## Limitations
92
-
93
-
The M7 and M4 cores are two separate cores, and when initialized, they will continue to execute their corresponding program.
94
-
95
-
In this section you will find some known limitations of using the two parallel cores.
96
-
97
-
### Booting M4
98
-
99
-
As mentioned in the previous section, the M4 requires to be booted from the M7, by using the `RPC.begin()` method. If this is not included, the M4 will not boot.
147
+
## Identify Core Used
100
148
101
-
### Serial Communication
102
-
103
-
Serial communication is not available by default on the M4 core. A work around for this is by sending data using the `RPC` library, and printing it from the M7 core. To achieve this, see the following examples:
104
-
105
-
**M4 Sketch**
149
+
To identify which core is being used, use the `HAL_GetCurrentCPUID()` method. Below is a function that returns which core is currently being used. This can be useful to identify that your program is running on the right core.
106
150
107
151
```arduino
108
-
#include <RPC.h>
152
+
/*
153
+
GIGA R1 WiFi - Core identify sketch.
109
154
110
-
void setup() {
111
-
RPC.begin();
112
-
}
155
+
This simple sketch blinks an LED on boot.
156
+
You will need to upload it to both the M7 and M4 core.
113
157
114
-
void loop() {
115
-
// put your main code here, to run repeatedly:
116
-
RPC.println("Hello World!");
117
-
}
118
-
```
158
+
It checks whether current CPU is M7 or M4, and blinks either
159
+
the blue LED or the green LED, 10 times.
119
160
120
-
**M7 Sketch**
161
+
As the M4 is booted when invoking RPC.begin() on the M7,
162
+
the M4 sketch will run as soon as the blink() function
163
+
finishes on the M7.
164
+
*/
121
165
122
-
```arduino
123
166
#include <RPC.h>
124
167
125
168
void setup() {
126
-
// put your setup code here, to run once:
127
-
Serial.begin(9600);
128
-
RPC.begin();
129
-
}
130
-
131
-
void loop() {
132
-
String buffer = "";
133
-
while (RPC.available()) {
134
-
buffer += (char)RPC.read();
135
-
}
136
-
137
-
if (buffer.length() > 0) {
138
-
Serial.print(buffer);
139
-
}
140
-
}
141
-
```
142
-
143
-
***Note that both of these sketches needs to be uploaded to their corresponding cores.***
144
-
145
-
## Methods of Programming
146
-
147
-
Programming the M4 and M7 cores is straightforward, but can be complicated to track. Having a strategy for how you want to build your dual core applications is key.
169
+
pinMode(LEDB, OUTPUT);
170
+
pinMode(LEDG, OUTPUT);
148
171
149
-
In this section we introduce the "single" and "multiple" sketch approach, and the pros and cons of each method.
150
-
151
-
### Single Sketch Approach
152
-
153
-
The single sketch approach means writing a single sketch that is **uploaded to both cores** each time a change is made. In the sketch, we can keep track of what each core does, simply by querying the core used with a simple function:
154
-
155
-
```arduino
156
-
String currentCPU() {
157
172
if (HAL_GetCurrentCPUID() == CM7_CPUID) {
158
-
return "M7";
173
+
blink(LEDB, 100); //blink blue LED (M7 core)
159
174
} else {
160
-
return "M4";
175
+
blink(LEDG, 100); //blink green LED (M4 core)
161
176
}
162
177
}
163
-
```
164
-
165
-
With this function, we check whether the M4 or M7 is running, and we can write code for each of the core like this:
166
178
167
-
```arduino
168
-
if (currentCPU() == "M4") {
169
-
//run M4 code
170
-
}
179
+
void loop() {
180
+
}
171
181
172
-
if (currentCPU() == "M7") {
173
-
//run M7 code
182
+
void blink(int led, int delaySeconds) {
183
+
for (int i; i < 10; i++) {
184
+
digitalWrite(led, LOW);
185
+
delay(delaySeconds);
186
+
digitalWrite(led, HIGH);
187
+
delay(delaySeconds);
174
188
}
189
+
RPC.begin();
190
+
}
175
191
```
176
192
177
-
The pros of using this approach is that you can write all code in a single file, therefore, revisioning code, as well as the provisioning is easier to manage.
178
-
179
-
The cons of using this approach is that you will run out of program memory faster. You will also upload code to the cores that will never execute (the M7 code will not execute on M4 and vice versa).
180
-
181
-
### Multiple Sketch Approach
182
-
183
-
The multiple sketch approach means developing two separate sketches, one for each core. This does not require the use of the `HAL_GetCurrentCPUID()` to retrieve the core you are using, you can instead just write sketches as you would normally do.
184
-
185
-
The pros of using this approach is that the code you write is optimized only for one core, and this saves a lot of program memory.
186
-
187
-
The cons is to manage the versions becomes harder, and while flashing the board, you'd need to keep track on which version is uploaded to which core. It is easier to upload to the wrong core by accident using this approach, but you have more optimized code.
188
-
189
-
When writing multiple sketches, there are some things to consider to make your development experience easier:
190
-
- Name your sketches with either `_M4` or `_M7` suffix or prefix. This will make it easier if the code is intended to be shared with others.
191
-
- Consider having a starting sequence (e.g. the blue LED blinking 3 times), whenever a core is initialized.
192
-
- Always include `RPC.begin()` on your M7 core sketch.
193
+
- The `HAL_GetCurrentCPUID()` is a method that checks the CPU ID, and returns the value in a `uint32_t` format.
194
+
- The `CM7_CPUID` flag that we compare with holds the value `0x00000003` (hexadecimal), or `3` (decimal).
195
+
- It is also possible to use `CM4_CPUID` flag which holds the value `0x00000003`, or `1` (decimal).
0 commit comments