Skip to content

Commit 3e669ed

Browse files
ArduinoBotcanchebagurjcarolinares
authored
[PC-1196] Opta Memory Partitioning Tutorial (#1000)
* Create tutorial * Content and graphics update * Graphics update * Content update * Content update * Format code * Content update * Update content/hardware/07.opta/opta-family/opta/tutorials/memory-partitioning/content.md Co-authored-by: Julián Caro Linares <jcarolinares@gmail.com> * Update content, grammar Co-authored-by: Julián Caro Linares <jcarolinares@gmail.com> * Update content, grammar Co-authored-by: Julián Caro Linares <jcarolinares@gmail.com> * Update content/hardware/07.opta/opta-family/opta/tutorials/memory-partitioning/content.md Update content, grammar Co-authored-by: Julián Caro Linares <jcarolinares@gmail.com> * Content update, conclusion * Content update, conclusion * Lintex fix, spelling * Content update, sketch and certificates file as a .zip file * Content update, linter fix * Content update, style * Update Getting started link --------- Co-authored-by: José Antonio Bagur Nájera <josea.bagur@gmail.com> Co-authored-by: Julián Caro Linares <jcarolinares@gmail.com> Co-authored-by: Julián Caro Linares <j.carolinares@arduino.cc>
1 parent 54dc501 commit 3e669ed

File tree

7 files changed

+356
-0
lines changed

7 files changed

+356
-0
lines changed
Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
---
2+
title: 'Opta™ Memory Partitioning for Use with the Arduino IDE'
3+
description: "Learn how to partition the memory of an Opta™ device to be used with the Arduino® ecosystem tools."
4+
5+
difficulty: beginner
6+
tags:
7+
- Opta
8+
- Memory partitioning
9+
- Arduino IDE
10+
author: 'José Bagur and Taddy Chung'
11+
software:
12+
- ide-v1
13+
- ide-v2
14+
hardware:
15+
- hardware/07.opta/opta-family/opta
16+
---
17+
18+
## Overview
19+
20+
The Opta™ is a secure, easy-to-use micro Programmable Logic Controller (PLC) with Industrial Internet of Things (IIoT) capabilities. It can be programmed with the [Arduino PLC IDE](https://www.arduino.cc/pro/software-plc-ide/), a tool that simplifies programming the device through any of the five programming languages defined by the IEC 61131-3 standard.
21+
22+
The Opta™ can also be programmed with other tools from the Arduino ecosystem, such as the [Arduino IDE](https://www.arduino.cc/en/software) and the Arduino programming language. In case we are using Opta™ with the Arduino PLC IDE and we want to start programming the device using the Arduino IDE and the rest of the Arduino ecosystem tools, we need to partition the memory of the device to enable all of the available features.
23+
24+
In this tutorial, we will learn how to partition the memory of an Opta™ device to enable all of its functionalities to be programmed using the Arduino IDE and the Arduino programming language.
25+
26+
![The Opta™ memory map](assets/memory-partitioning-introduction.png)
27+
28+
## Goals
29+
30+
- Learn how to partition the memory of an Opta™ device to be used with the Arduino IDE and other ecosystem tools
31+
- Program an Opta™ device using the Arduino IDE and the Arduino programming language.
32+
33+
## Hardware and Software Requirements
34+
35+
### Hardware Requirements
36+
37+
- [Opta™](https://store.arduino.cc/collections/pro-family) (x1)
38+
- USB-C® cable (x1)
39+
40+
### Software Requirements
41+
42+
- [Arduino IDE 1.8.10+](https://www.arduino.cc/en/software), [Arduino IDE 2.0+](https://www.arduino.cc/en/software), or [Arduino Web Editor](https://create.arduino.cc/editor)
43+
- [The memory partitioning sketch and the certificates file](assets/opta_memory_partitioning.zip)
44+
45+
## Memory Partitioning
46+
47+
Memory partitioning involves dividing the available memory of a device into separate regions or partitions, each serving a specific purpose. This process is used for managing memory efficiently and ensuring that different programs or functionalities of the device can coexist without interfering each other. In the context of the Opta™, partitioning the memory allows the device to accommodate different functionalities, such as its Wi-Fi® module firmware, Over-The-Air (OTA) updates functionality, and certificates storage, while still providing memory space for user programs developed in the Arduino IDE and the Arduino programming language.
48+
49+
Now, we will guide the process of partitioning an Opta™'s memory to enable the full range of its functionalities to be programmed using the Arduino IDE and the Arduino programming language.
50+
51+
## Instructions
52+
53+
### Setting Up the Arduino IDE
54+
55+
This tutorial requires the latest version of the Arduino IDE; we can download it [here](https://www.arduino.cc/en/software). In the Arduino IDE, we need to install the core for Opta™ devices; this can be done by navigating to **Tools > Board > Boards Manager** or clicking the Boards Manager icon in the left tab of the IDE. In the Boards Manager tab, search for `opta` and install the latest `Arduino Mbed OS Opta Boards` version.
56+
57+
![Installing the Opta™ core in the Arduino IDE bootloader](assets/arduino-ide-1.png)
58+
59+
60+
Now we are ready to start compiling and uploading Arduino sketches to an Opta™ device using the Arduino IDE.
61+
62+
### Partitioning Memory of an Opta™ Device
63+
64+
The sketch below will guide us through partitioning the memory of an Opta™ device. The complete sketch and the certificates file can be downloaded [here](assets/opta_memory_partitioning.zip). **Remember to store both files in the same folder**.
65+
66+
67+
```arduino
68+
/**
69+
Opta memory partitioning
70+
Name: opta_memory_partitioning.ino
71+
Purpose: Partition the memory of an Opta device
72+
73+
@author Arduino PRO team
74+
@version 1.0 04/04/22
75+
*/
76+
77+
// Include necessary libraries for working
78+
#include <BlockDevice.h>
79+
#include <FATFileSystem.h>
80+
#include <LittleFileSystem.h>
81+
#include <MBRBlockDevice.h>
82+
#include "wiced_resource.h"
83+
#include "certificates.h"
84+
85+
// Ensure that the M7 core is being used instead of the M4 core
86+
#ifndef CORE_CM7
87+
#error Update the WiFi firmware by uploading the sketch to the M7 core instead of the M4 core.
88+
#endif
89+
90+
using namespace mbed;
91+
92+
// Create instances of block devices and filesystems for the QSPI Flash memory
93+
BlockDevice* root;
94+
MBRBlockDevice* wifi_data;
95+
MBRBlockDevice* ota_data;
96+
FATFileSystem wifi_data_fs("wlan");
97+
FATFileSystem ota_data_fs("fs");
98+
99+
void setup() {
100+
// Set the built-in LED pin as an output and turn it off
101+
pinMode(LED_BUILTIN, OUTPUT);
102+
digitalWrite(LED_BUILTIN, LOW);
103+
104+
// Initialize serial communication and wait up to 2.5 seconds for a connection
105+
Serial.begin(115200);
106+
for (auto startNow = millis() + 2500; !Serial && millis() < startNow; delay(500))
107+
;
108+
109+
// Blink the built-in LED 10 times as a visual indicator that the process is starting
110+
for (auto i = 0u; i < 10; i++) {
111+
digitalWrite(LED_BUILTIN, HIGH);
112+
delay(25);
113+
digitalWrite(LED_BUILTIN, LOW);
114+
delay(50);
115+
}
116+
117+
// Initialize and erase the QSPI flash memory.
118+
Serial.println("Erasing the QSPIF");
119+
root = BlockDevice::get_default_instance();
120+
auto err = root->init();
121+
if (err != 0) {
122+
Serial.print("Error Initializing the QSPIF: ");
123+
Serial.println(err);
124+
while (true) {
125+
digitalWrite(LED_BUILTIN, HIGH);
126+
delay(50);
127+
digitalWrite(LED_BUILTIN, LOW);
128+
delay(150);
129+
}
130+
}
131+
132+
// Create partitions for Wi-Fi firmware, OTA updates, and certificate storage
133+
// Get device geometry.
134+
const auto erase_size = root->get_erase_size();
135+
const auto size = root->size();
136+
const auto eraseSectors = size / erase_size;
137+
138+
for (auto i = 0u; i < eraseSectors; i++) {
139+
err = root->erase(i * erase_size, erase_size);
140+
if (i % 64 == 0) {
141+
digitalWrite(LED_BUILTIN, HIGH);
142+
delay(25);
143+
digitalWrite(LED_BUILTIN, LOW);
144+
}
145+
if (err != 0) {
146+
Serial.print("Error erasing sector ");
147+
Serial.println(i);
148+
Serial.print(" [");
149+
Serial.print(i * erase_size);
150+
Serial.print(" - ");
151+
Serial.print(float{ i } / float{ eraseSectors } * 100);
152+
Serial.print("%] -> ");
153+
Serial.print(err ? "KO" : "OK");
154+
Serial.println();
155+
for (auto i = 0u; i < 2; i++) {
156+
digitalWrite(LED_BUILTIN, HIGH);
157+
delay(50);
158+
digitalWrite(LED_BUILTIN, LOW);
159+
delay(150);
160+
}
161+
}
162+
}
163+
164+
Serial.println("Done");
165+
for (auto i = 0u; i < 5; i++) {
166+
digitalWrite(LED_BUILTIN, HIGH);
167+
delay(25);
168+
digitalWrite(LED_BUILTIN, LOW);
169+
delay(50);
170+
}
171+
172+
// Format the partitions and create filesystem instances
173+
// WiFi Firmware and TLS TA certificates: 1 MB
174+
// Arduino OTA: 13 MB
175+
MBRBlockDevice::partition(root, 1, 0x0B, 0 * 1024 * 1024, 1 * 1024 * 1024);
176+
MBRBlockDevice::partition(root, 3, 0x0B, 14 * 1024 * 1024, 14 * 1024 * 1024);
177+
MBRBlockDevice::partition(root, 2, 0x0B, 1024 * 1024, 14 * 1024 * 1024);
178+
179+
// Create the filesystem references
180+
wifi_data = new MBRBlockDevice(root, 1);
181+
ota_data = new MBRBlockDevice(root, 2);
182+
183+
// Write Wi-Fi firmware and certificate data to the appropriate partitions
184+
Serial.print("Formatting WiFi partition... ");
185+
err = wifi_data_fs.reformat(wifi_data);
186+
if (err != 0) {
187+
Serial.println("Error formatting WiFi partition");
188+
while (true) {
189+
digitalWrite(LED_BUILTIN, HIGH);
190+
delay(50);
191+
digitalWrite(LED_BUILTIN, LOW);
192+
delay(150);
193+
}
194+
}
195+
196+
Serial.println("done.");
197+
Serial.print("Formatting OTA partition...");
198+
err = ota_data_fs.reformat(ota_data);
199+
if (err != 0) {
200+
Serial.println("Error formatting OTA partition");
201+
while (true) {
202+
digitalWrite(LED_BUILTIN, HIGH);
203+
delay(50);
204+
digitalWrite(LED_BUILTIN, LOW);
205+
delay(150);
206+
}
207+
}
208+
209+
Serial.println("done.");
210+
for (auto i = 0u; i < 10; i++) {
211+
digitalWrite(LED_BUILTIN, HIGH);
212+
delay(25);
213+
digitalWrite(LED_BUILTIN, LOW);
214+
delay(50);
215+
}
216+
217+
Serial.println("QSPI Flash Storage Ready.");
218+
219+
// Flash the memory-mapped Wi-Fi firmware and certificates
220+
extern const unsigned char wifi_firmware_image_data[];
221+
extern const resource_hnd_t wifi_firmware_image;
222+
FILE* fp = fopen("/wlan/4343WA1.BIN", "wb");
223+
const int file_size = 421098;
224+
int chunck_size = 1024;
225+
int byte_count = 0;
226+
227+
Serial.println("Flashing /wlan/4343WA1.BIN file");
228+
printProgress(byte_count, file_size, 10, true);
229+
while (byte_count < file_size) {
230+
if (byte_count + chunck_size > file_size)
231+
chunck_size = file_size - byte_count;
232+
int ret = fwrite(&wifi_firmware_image_data[byte_count], chunck_size, 1, fp);
233+
if (ret != 1) {
234+
Serial.println("Error writing firmware data");
235+
break;
236+
}
237+
byte_count += chunck_size;
238+
printProgress(byte_count, file_size, 10, false);
239+
}
240+
fclose(fp);
241+
242+
chunck_size = 1024;
243+
byte_count = 0;
244+
const uint32_t offset = 15 * 1024 * 1024 + 1024 * 512;
245+
246+
Serial.println("Flashing memory mapped firmware");
247+
printProgress(byte_count, file_size, 10, true);
248+
while (byte_count < file_size) {
249+
if (byte_count + chunck_size > file_size)
250+
chunck_size = file_size - byte_count;
251+
int ret = root->program(wifi_firmware_image_data, offset + byte_count, chunck_size);
252+
if (ret != 0) {
253+
Serial.println("Error writing firmware data");
254+
break;
255+
}
256+
byte_count += chunck_size;
257+
printProgress(byte_count, file_size, 10, false);
258+
}
259+
260+
chunck_size = 128;
261+
byte_count = 0;
262+
fp = fopen("/wlan/cacert.pem", "wb");
263+
264+
Serial.println("Flashing certificates");
265+
printProgress(byte_count, cacert_pem_len, 10, true);
266+
while (byte_count < cacert_pem_len) {
267+
if (byte_count + chunck_size > cacert_pem_len)
268+
chunck_size = cacert_pem_len - byte_count;
269+
int ret = fwrite(&cacert_pem[byte_count], chunck_size, 1, fp);
270+
if (ret != 1) {
271+
Serial.println("Error writing certificates");
272+
break;
273+
}
274+
byte_count += chunck_size;
275+
printProgress(byte_count, cacert_pem_len, 10, false);
276+
}
277+
fclose(fp);
278+
279+
fp = fopen("/wlan/cacert.pem", "rb");
280+
char buffer[128];
281+
int ret = fread(buffer, 1, 128, fp);
282+
Serial.write(buffer, ret);
283+
while (ret == 128) {
284+
ret = fread(buffer, 1, 128, fp);
285+
Serial.write(buffer, ret);
286+
}
287+
fclose(fp);
288+
289+
Serial.println("\nFirmware and certificates updated!");
290+
Serial.println("It's now safe to reboot or disconnect your board.");
291+
}
292+
293+
void loop() {
294+
// Empty loop function, main task is performed in the setup function
295+
}
296+
297+
/**
298+
Get the size of a file
299+
300+
@param bootloader fp (FP)
301+
@return files size
302+
*/
303+
long getFileSize(FILE* fp) {
304+
fseek(fp, 0, SEEK_END);
305+
int size = ftell(fp);
306+
fseek(fp, 0, SEEK_SET);
307+
308+
return size;
309+
}
310+
311+
/**
312+
Display the progress of the flashing process
313+
314+
@params offset (uint32_t), size (uint32_t), threshold (uint32_t) and reset (bool)
315+
@return none
316+
*/
317+
void printProgress(uint32_t offset, uint32_t size, uint32_t threshold, bool reset) {
318+
static int percent_done = 0;
319+
if (reset == true) {
320+
percent_done = 0;
321+
Serial.println("Flashed " + String(percent_done) + "%");
322+
} else {
323+
uint32_t percent_done_new = offset * 100 / size;
324+
if (percent_done_new >= percent_done + threshold) {
325+
percent_done = percent_done_new;
326+
Serial.println("Flashed " + String(percent_done) + "%");
327+
}
328+
}
329+
}
330+
```
331+
332+
The sketch shown above performs four main tasks:
333+
334+
1. **Initialize and erase the QSPI Flash memory**: The sketch initializes the QSPI Flash memory of the Opta™ device and erases its content to prepare the memory for new firmware and data. One of the built-in LEDs of the device is used to indicate the progress of the memory-erasing process.
335+
336+
2. **Create partitions and format them in the QSPI Flash memory**: The sketch creates and formats partitions in the QSPI Flash memory for the Wi-Fi firmware, Over-The-Air (OTA) updates functionality, and certificates storage.
337+
338+
3. **Write Wi-Fi firmware and certificates data**: The sketch writes the Wi-Fi firmware and certificate data to the appropriate partitions in the QSPI Flash memory. It also flashes the memory-mapped Wi-Fi firmware and certificates.
339+
340+
4. **Display progress in the Arduino IDE Serial Monitor**: The sketch provides a visual indication of the progress of the flashing process using one of the built-in LEDs of the Opta™ device and displays messages through the Arduino IDE Serial Monitor to inform the user about the current status of the flashing process.
341+
342+
To upload the code, click the **Verify** button to compile the sketch and check for errors; then click the **Upload** button to program the device with the sketch.
343+
344+
![Uploading a sketch to the Opta™ the Arduino IDE](assets/arduino-ide-2.png)
345+
346+
After a while, you should see in the Serial Monitor information on the progress of the flashing process, as shown in the image below.
347+
348+
![Flashing process feedback of the Opta™ shown in the Arduino IDE's Serial Monitor](assets/arduino-ide-3.png)
349+
350+
If everything is correct, you should see a success message in the Serial Monitor. Now we are ready to start using the full capabilities of the Opta™ with the Arduino IDE.
351+
352+
## Conclusion
353+
354+
In this tutorial, we successfully partitioned the memory of an Opta™ device, enabling its full range of functionalities to be programmed using Arduino ecosystem tools such as the Arduino IDE and the Arduino programming language. We walked through initializing and erasing the QSPI Flash memory, partitioning and formatting the memory, and writing the Wi-Fi firmware and certificate data onto the device's memory.
355+
356+
As you move forward, you can explore the extensive Arduino ecosystem, leverage various libraries and hardware add-ons, and create powerful, connected, and secure industrial solutions using the Opta™. Check out our [getting started with the Opta™ tutorial](/tutorials/opta/getting-started) to learn more about its hardware and software features.
Loading

0 commit comments

Comments
 (0)