Skip to content

Commit 1ece366

Browse files
authored
Merge pull request #503 from arduino/martab1994-patch-5
Update content.md
2 parents e81ac74 + f42ae43 commit 1ece366

File tree

1 file changed

+20
-19
lines changed
  • content/hardware/04.pro/boards/portenta-h7/tutorials/reading-writing-flash-memory

1 file changed

+20
-19
lines changed

content/hardware/04.pro/boards/portenta-h7/tutorials/reading-writing-flash-memory/content.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ software:
1919
- web-editor
2020
---
2121
## Overview
22-
This tutorial demonstrates how to use the on-board Flash memory of the Portenta H7 to read and write data using the BlockDevice API provided by Mbed OS. As the internal memory is limited in size we will also take a look at saving data to the QSPI Flash memory.
22+
This tutorial demonstrates how to use the on-board Flash memory of the Portenta H7 to read and write data using the BlockDevice API provided by Mbed OS. As the internal memory is limited in size, we will also take a look at saving data to the QSPI Flash memory.
2323

2424
## Goals
2525

@@ -38,25 +38,25 @@ Portenta's core is based on the Mbed operating system, allowing for Arduino APIs
3838

3939
Mbed OS has a rich API for managing storage on different mediums, ranging from the small internal Flash memory of a microcontroller to external SecureDigital cards with large data storage space.
4040

41-
In this tutorial, we are going to save a value persistently inside the Flash memory. That allows to access that value even after rebooting the board. We will retrieve some information from a Flash block by using the [FlashIAPBlockDevice](https://os.mbed.com/docs/mbed-os/v6.9/apis/flashiapblockdevice.html) API and create a block device object within the available space of the memory. In case of the internal memory it's the space which is left after uploading a sketch to the board.
41+
In this tutorial, you are going to save a value persistently inside the Flash memory. That allows to access that value even after rebooting the board. You will retrieve some information from a Flash block by using the [FlashIAPBlockDevice](https://os.mbed.com/docs/mbed-os/v6.9/apis/flashiapblockdevice.html) API and create a block device object within the available space of the memory. In case of the internal memory, it corresponds to the space which is left after uploading a sketch to the board.
4242

4343
***Be aware of the Flash r/w limits: Flash memories have a limited amount of read/write cycles. Typical Flash memories can perform about 10000 writes cycles to the same block before starting to "wear out" and begin to lose the ability to retain data. You can render your board useless with improper use of this example and described APIs.***
4444

4545
## Block Device Blocks
4646

47-
Blocks of Flash memory can be accessed through the block device APIs. They are byte addressable but operate in units of blocks. There are three types of blocks for the different block device operations: read blocks, erase blocks and program blocks. The recommended procedure for programming data is to first erase a block and then programming it in units of the program block size. The sizes of the erase, program and read blocks may not be the same but they must be multiples of each another. Keep in mind that the state of an erased block is undefined until you program it with data.
47+
Blocks of Flash memory can be accessed through the block device APIs. They are byte addressable but operate in units of blocks. There are three types of blocks for the different block device operations: read blocks, erase blocks and program blocks. The recommended procedure for programming data is to first erase a block and then programming it in units of the program block size. The sizes of the erase, program and read blocks may not be the same, but they must be multiples of each another. Keep in mind that the state of an erased block is undefined until you program it with data.
4848

4949
![Conceptual view of how the block sizes relate to one another](assets/por_ar_flash_memory.svg)
5050

5151
## Programming the Internal Flash
5252

5353
### 1. Create the Structure of the Program
54-
Before we start it's important to keep the above mentioned **Flash r/w limits** in mind! Therefore this method should only be used for **once-in-a-while** read and write **operations** such as reading a user setting in the `setup()`. It is not a good idea to use it for constantly updated values such as sensor data.
54+
Before we start it's important to keep the above mentioned **Flash r/w limits** in mind! Therefore this method should only be used for **once-in-a-while** read and write **operations**, such as reading a user setting in the `setup()`. It is not a good idea to use it for constantly updated values such as sensor data.
5555

56-
Having this in mind, it's time to create a sketch to program the Portenta. After creating new sketch and giving it a fitting name (in our case `FlashStorage.ino`) we need to create one more file to be used by the sketch, called `FlashIAPLimits.h`, that we will use to define some helper functions. This allows us to reuse the helper file later for other sketches.
56+
Having this in mind, it is time to create a sketch to program the Portenta. After creating new sketch and giving it a fitting name (in this case `FlashStorage.ino`), you need to create one more file to be used by the sketch, called `FlashIAPLimits.h`, that you will use to define some helper functions. This allows you to reuse the helper file later for other sketches.
5757

5858
### 2. The Helper Functions
59-
Within the `FlashIAPLimits.h` file we start by including necessary libraries and defining the namespace.
59+
Within the `FlashIAPLimits.h` file, you can start by including necessary libraries and defining the namespace.
6060

6161
```cpp
6262
// Ensures that this file is only included once
@@ -69,7 +69,7 @@ Within the `FlashIAPLimits.h` file we start by including necessary libraries and
6969
using namespace mbed;
7070
```
7171

72-
After that we create a struct which will later be used to save the storage's properties.
72+
After that, you can create a struct which will later be used to save the storage's properties.
7373

7474
```cpp
7575
// An helper struct for FlashIAP limits
@@ -124,7 +124,7 @@ FlashIAPLimits getFlashIAPLimits()
124124
```
125125

126126
### 3. Reading & Writing Data
127-
Going back to the `FlashStorage.ino` file some more files need to be included in order to implement reading add writing to the flash. The `FlashIAPBlockDevice.h` API will be used to create a block device in the empty part of the memory. Additionally we include the helper file `FlashIAPLimits.h` to have access to the address and size calculation function that we just created. We also reference the `mbed` namespace for better readability.
127+
Going back to the `FlashStorage.ino` file, some more files need to be included in order to implement reading and writing to the Flash. The `FlashIAPBlockDevice.h` API will be used to create a block device in the empty part of the memory. Additionally, you can include the helper file `FlashIAPLimits.h` to have access to the address and size calculation function that you just created. You can also reference the `mbed` namespace for better readability.
128128

129129
```cpp
130130
#include <FlashIAPBlockDevice.h>
@@ -147,7 +147,7 @@ void setup() {
147147
randomSeed(analogRead(0));
148148
```
149149
150-
Next the helper function, defined in the `FlashIAPLimits.h` file, is called to calculate the memory properties that are then used to create a block device using the `FlashIAPBlockDevice.h` library.
150+
Next the helper function, defined in the `FlashIAPLimits.h` file is called to calculate the memory properties, which are then used to create a block device using the `FlashIAPBlockDevice.h` library.
151151
152152
```cpp
153153
// Get limits of the the internal flash of the microcontroller
@@ -166,9 +166,9 @@ Serial.println(" MB");
166166
FlashIAPBlockDevice blockDevice(startAddress, iapSize);
167167
```
168168

169-
Before using the block device the first step is to initialize it using `blockDevice.init()`. Once initialized it can provide the sizes of the blocks for programming the Flash. In terms of reading and writing Flash memory blocks there is a distinction between the size of a readable block in bytes, a programmable block, which size is always a multiple of the read size and an erasable block which is always a multiple of a programmable block.
169+
Before using the block device, the first step is to initialize it using `blockDevice.init()`. Once initialized, it can provide the sizes of the blocks for programming the Flash. In terms of reading and writing Flash memory blocks, there is a distinction between the size of a readable block in bytes, a programmable block, which size is always a multiple of the read size, and an erasable block, which is always a multiple of a programmable block.
170170

171-
When reading and writing directly from and to the Flash memory we need to always allocate a buffer with a multiple of the program block size. The amount of required program blocks can be determined by dividing the data size by the program block size. The final buffer size is equal to the amount of program blocks multiplied by the program block size.
171+
When reading and writing directly from and to the Flash memory, you need to always allocate a buffer with a multiple of the program block size. The amount of required program blocks can be determined by dividing the data size by the program block size. The final buffer size is equal to the amount of program blocks multiplied by the program block size.
172172

173173
```cpp
174174
// Initialize the Flash IAP block device and print the memory layout
@@ -193,7 +193,7 @@ const auto dataSize = requiredProgramBlocks * programBlockSize;
193193
char buffer[dataSize] {};
194194
```
195195

196-
In the last part of the `setup()` function we can now use the block device to read and write data. First the buffer is used to read what was stored within the previous execution, then the memory gets erased and reprogrammed with the new content. At the end of the reading and writing process the block device needs to be de-initialized again using `blockDevice.deinit()`.
196+
In the last part of the `setup()` function you can now use the block device to read and write data. First the buffer is used to read what was stored within the previous execution, then the memory gets erased and reprogrammed with the new content. At the end of the reading and writing process, the block device needs to be de-initialized again using `blockDevice.deinit()`.
197197

198198
```cpp
199199
// Read back what was stored at previous execution
@@ -356,14 +356,14 @@ void loop() {}
356356
```
357357

358358
### 5. Results
359-
After uploading the sketch open the serial monitor to start the Flash reading and writing process. The first time you start the script the block device will be filled randomly. Now try to reset or disconnect the Portenta and reconnect it. You should see a message with the random number written to the Flash storage in the previous execution.
359+
After uploading the sketch open the Serial Monitor to start the Flash reading and writing process. The first time you start the script, the block device will be filled randomly. Now try to reset or disconnect the Portenta and reconnect it, you should see a message with the random number written to the Flash storage in the previous execution.
360360

361-
***Note that the value written to the Flash storage will persist if the board is reset or disconnected. However the Flash storage will be reprogrammed once a new sketch is uploaded to the Portenta and may overwrite the data stored in the Flash.***
361+
***Note that the value written to the Flash storage will persist if the board is reset or disconnected. However, the Flash storage will be reprogrammed once a new sketch is uploaded to the Portenta and may overwrite the data stored in the Flash.***
362362

363363
## Programming the QSPI Flash
364364

365-
One issue with the internal Flash is that it's limited in size and the erase blocks are pretty large. This leaves very little space for your sketch and you may quickly run into issues with more complex applications. Therefore we can use the external QSPI Flash which has plenty of space to store data.
366-
For that the block device needs to be initialized differently but the rest of the sketch remains the same. To initialize the device we use the [QSPIFBlockDevice](https://os.mbed.com/docs/mbed-os/v6.9/apis/qspifblockdevice.html) class which is a block device driver for NOR-based QSPI Flash devices.
365+
One issue with the internal Flash is that it is limited in size and the erase blocks are pretty large. This leaves very little space for your sketch and you may quickly run into issues with more complex applications. Therefore, you can use the external QSPI Flash which has plenty of space to store data.
366+
For that, the block device needs to be initialized differently, but the rest of the sketch remains the same. To initialize the device you can use the [QSPIFBlockDevice](https://os.mbed.com/docs/mbed-os/v6.9/apis/qspifblockdevice.html) class which is a block device driver for NOR-based QSPI Flash devices.
367367

368368
```cpp
369369
#define BLOCK_DEVICE_SIZE 1024 * 8 // 8 KB
@@ -383,7 +383,7 @@ if(blockDevice.init() != 0 || blockDevice.size() != BLOCK_DEVICE_SIZE) {
383383
}
384384
```
385385
386-
While the QSPI block device memory can be used directly, it's better to use a partition table as the QSPI storage is also filled with other data such as the Wi-Fi firmware. For that we use the [MBRBlockDevice](https://os.mbed.com/docs/mbed-os/v6.8/apis/mbrblockdevice.html) class and allocate a 8 KB partition which can then be used to read and write data.
386+
While the QSPI block device memory can be used directly, it is better to use a partition table as the QSPI storage is also filled with other data, such as the Wi-Fi firmware. For that you use the [MBRBlockDevice](https://os.mbed.com/docs/mbed-os/v6.8/apis/mbrblockdevice.html) class and allocate a 8 KB partition, which can then be used to read and write data.
387387
388388
The full QSPI version of the sketch is as follows:
389389
@@ -460,7 +460,8 @@ void loop() {}
460460
```
461461

462462
## Conclusion
463-
We have learned how to use the available space in the Flash memory of the microcontroller to read and save custom data. It's not recommended to use the Flash of the microcontroller as the primary storage for data-intensive applications. It is better suited for read/write operations that are performed only once in a while such as storing and retrieving application configurations or persistent parameters.
463+
We have learned how to use the available space in the Flash memory of the microcontroller to read and save custom data. It is not recommended to use the Flash of the microcontroller as the primary storage for data-intensive applications. It is better suited for read/write operations that are performed only once in a while such as storing and retrieving application configurations or persistent parameters.
464464

465465
## Next Steps
466-
Now that you know how to use block device to perform reading and writing Flash memory you can look into the [next tutorial](https://www.arduino.cc/pro/tutorials/portenta-h7/flash-optimized-key-value-store) on how to use the [TDBStore API](https://os.mbed.com/docs/mbed-os/v6.9/apis/kvstore.html) to create a [key value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) in the Flash memory.
466+
Now that you know how to use block device to perform reading and writing Flash memory, you can look into the [next tutorial](https://docs.arduino.cc/tutorials/portenta-h7/flash-optimized-key-value-store) on how to use the [TDBStore API](https://os.mbed.com/docs/mbed-os/latest/apis/kvstore.html) to create a [key value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) in the Flash memory.
467+

0 commit comments

Comments
 (0)