Skip to content

Commit ef49605

Browse files
committed
- fix several memory leaks
- rework member variables when calling begin/umount/format (solves inconsistenies). begin() means mounting. It must not initialize the block device, as this is global to a partition. format() is only possbile when FS is not mounted (it makes no sense to call begin()/unmount(), just to get a valid mbr block device). -> rework - When creating partition object and no partition was present on block device, the members of partition object left uninitialzed. - add function to free the allocated memory that was returned when calling utils function to create a partition name. - solve problems, where block devices keept initialized when calling listPartitions(). This function could only be called two times. Other called functions failed because of the blocked resources. It now calls deinit() to leave it clean.
1 parent 30b1a52 commit ef49605

File tree

6 files changed

+126
-77
lines changed

6 files changed

+126
-77
lines changed

Diff for: examples/InternalStoragePartitioning/InternalStoragePartitioning.ino

+10-8
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
This example demonstrates the usage of the "Arduino_UnifiedStorage" library for retrieving and creating partitions on the internal storage.
55
The code should help you understand how to work with partitions and perform file operations in different partitions.
66
7-
It creates the partitions specified in the std::vector<Partitions> you find at the top of the sketch.
7+
It creates the partitions specified in the std::vector<Partitions> you find at the top of the sketch.
88
You can define your own, as long as the size of all partitions doesn't exceed the size of your board's QSPI flash( if you are in doubt about that check docs.arduino.com for more information) and as long as you don't have more than 4 partitions (MBR limitation)
99
The Partition struct has two values:
1010
- `size` the size of your partition in kilobytes
1111
- 'fileSystemType` which can be either `FS_FAT` or `FS_LITTLEFS`
1212
13-
Here are a few examples of valid partitioning schemes:
13+
Here are a few examples of valid partitioning schemes:
1414
- std::vector<Partition> partitioningScheme = {{16384, FS_FAT}};
1515
- std::vector<Partition> partitioningScheme = {{2048, FS_FAT}, {6144, FS_FAT} {8192, FS_LITTLEFS}};
1616
- std::vector<Partition> partitioningScheme = {{4096, FS_LITTLEFS}, {4096, FS_FAT}, {4096, FS_LITTLEFS}, {4096, FS_FAT}};
@@ -24,8 +24,8 @@
2424
INSTRUCTIONS:
2525
1. Check compatibility with your board and make sure you have "POSIXStorage" and "Arduino_UnifiedStorage" installed
2626
2. Connect your board to the serial monitor
27-
3. Wait for the sketch to run
28-
4. Modify the partitioning scheme according to your needs
27+
3. Wait for the sketch to run
28+
4. Modify the partitioning scheme according to your needs
2929
3030
Created: 26th October 2023
3131
By: Cristian Dragomir
@@ -36,7 +36,7 @@
3636
#include <vector>
3737

3838
// Create a vector of partitions with one partition of 16MB using LittleFS
39-
std::vector<Partition> partitioningScheme = {
39+
std::vector<Partition> partitioningScheme = {
4040
{1024, FS_FAT}, // 1 MB for certificates
4141
{5120, FS_FAT}, // 5 MB for OTA firmware updates
4242
{8192, FS_LITTLEFS} // 8 MB for user data
@@ -50,7 +50,7 @@ void testWriting(Arduino_UnifiedStorage *storage) {
5050
// Create a new file named "file.txt" for writing
5151
UFile file = root.createFile("file.txt", FileMode::WRITE);
5252
Serial.println("\t\t - File path: " + file.getPathAsString());
53-
53+
5454
// Write data to the file
5555
file.write("writing stuff to the file");
5656

@@ -65,7 +65,7 @@ void testWriting(Arduino_UnifiedStorage *storage) {
6565
void testAllPartitions(std::vector<Partition> partitions) {
6666
for (size_t i = 1; i < partitions.size() + 1; ++i) {
6767
const char *partitionName = createPartitionName(i);
68-
68+
6969
// Create an InternalStorage object for the partition
7070
InternalStorage thisPartition = InternalStorage(i, partitionName, partitions[i - 1].fileSystemType);
7171

@@ -74,6 +74,8 @@ void testAllPartitions(std::vector<Partition> partitions) {
7474
Serial.println("\t - Successfully mounted partition: /" + String(partitionName));
7575
Serial.println("\t - Testing file operations: ");
7676
testWriting(&thisPartition); // Test writing to a file in the partition
77+
thisPartition.unmount();
78+
freePartitionName(partitionName);
7779
}
7880

7981
Serial.println();
@@ -113,7 +115,7 @@ void setup() {
113115

114116
delay(1000);
115117

116-
// Read the MBR sector and display the partitions
118+
// Read the MBR sector and display the partitions
117119
listPartitions();
118120
}
119121

Diff for: library.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=Arduino_UnifiedStorage
2-
version=1.1.1
2+
version=1.1.2
33
author=Arduino
44
maintainer=Arduino <[email protected]>
55
sentence=Simplify cross-device storage management on Portenta platforms with a single library supporting SD, Flash, and USB storage access.

Diff for: src/InternalStorage.cpp

+40-21
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,37 @@
22

33
InternalStorage::InternalStorage(){
44
std::vector<Partition> partitionsAvailable = Partitioning::readPartitions(QSPIFBlockDeviceType::get_default_instance());
5-
if(partitionsAvailable.size() == 0){
5+
if(partitionsAvailable.size() == 0)
6+
{
67

78
//Arduino_UnifiedStorage::debugPrint("[InternalStorage][INFO] No partitions found, restoring default partitions");
89
restoreDefaultPartitions();
9-
} else {
10-
int lastPartitionNumber = partitionsAvailable.size();
11-
FileSystems lastPartitionFileSystem = partitionsAvailable.back().fileSystemType;
12-
//Arduino_UnifiedStorage::debugPrint("[InternalStorage][INFO] Found " + String(lastPartitionNumber) + " partitions, using last partition as internal storage");
13-
14-
this -> partitionNumber = lastPartitionNumber;
15-
this -> fileSystemType = lastPartitionFileSystem;
16-
this -> partitionName = (char *)"internal";
10+
// re-read table
11+
partitionsAvailable = Partitioning::readPartitions(QSPIFBlockDeviceType::get_default_instance());
1712
}
13+
14+
int lastPartitionNumber = partitionsAvailable.size();
15+
FileSystems lastPartitionFileSystem = partitionsAvailable.back().fileSystemType;
16+
//Arduino_UnifiedStorage::debugPrint("[InternalStorage][INFO] Found " + String(lastPartitionNumber) + " partitions, using last partition as internal storage");
17+
18+
this -> partitionNumber = lastPartitionNumber;
19+
this -> fileSystemType = lastPartitionFileSystem;
20+
this -> partitionName = (char *)"internal";
21+
this -> blockDevice = BlockDeviceType::get_default_instance();
22+
this -> mbrBlockDevice = new MBRBlockDeviceType(this -> blockDevice, this->partitionNumber);
1823
}
1924

2025
InternalStorage::InternalStorage(int partition, const char * name, FileSystems fileSystemType){
2126
this -> partitionNumber = partition;
22-
this -> partitionName = (char *)name;
27+
this -> partitionName = name;
2328
this -> fileSystemType = fileSystemType;
29+
this -> blockDevice = BlockDeviceType::get_default_instance();
30+
this -> mbrBlockDevice = new MBRBlockDeviceType(this -> blockDevice, this->partitionNumber);
31+
}
32+
33+
InternalStorage::~InternalStorage()
34+
{
35+
delete this -> mbrBlockDevice;
2436
}
2537

2638
bool InternalStorage::begin(FileSystems fileSystemType){
@@ -49,9 +61,6 @@ std::vector<Partition> InternalStorage::readPartitions(){
4961
}
5062

5163
bool InternalStorage::begin(){
52-
53-
this -> blockDevice = BlockDeviceType::get_default_instance();
54-
this -> mbrBlockDevice = new MBRBlockDeviceType(this->blockDevice, this->partitionNumber);
5564

5665
if(this -> fileSystemType == FS_FAT){
5766
this -> fileSystem = new FATFileSystemType(this->partitionName);
@@ -61,15 +70,23 @@ bool InternalStorage::begin(){
6170
Arduino_UnifiedStorage::debugPrint("[InternalStorage][begin][INFO] Mounting partition " + String(this->partitionNumber) + " as LittleFS");
6271
}
6372

64-
int err = this -> fileSystem -> mount(mbrBlockDevice);
73+
int err = this -> fileSystem -> mount(this -> mbrBlockDevice);
6574
if(err!=0){
6675
Arduino_UnifiedStorage::debugPrint("[InternalStorage][ERROR] Could not mount partition " + String(this->partitionNumber) + " as " + prettyPrintFileSystemType(this->fileSystemType) + ", error code: " + String(errno));
6776
}
6877
return err == 0;
6978
}
7079

7180
bool InternalStorage::unmount(){
72-
int err = this -> fileSystem -> unmount();
81+
int err = 0;
82+
83+
if(this -> fileSystem)
84+
{
85+
err = this -> fileSystem -> unmount();
86+
delete this -> fileSystem;
87+
this -> fileSystem = NULL;
88+
}
89+
7390
return err == 0;
7491
}
7592

@@ -78,23 +95,25 @@ Folder InternalStorage::getRootFolder(){
7895
}
7996

8097
bool InternalStorage::format(FileSystems fs){
81-
this -> begin();
98+
FileSystemType * tmpFileSystem = nullptr;
8299
this -> unmount();
83100
this -> fileSystemType = fs;
84101

85102
if(fs == FS_FAT){
86-
this -> fileSystem = new FATFileSystemType(this->partitionName);
87-
int err = this -> fileSystem -> reformat(this-> mbrBlockDevice);
103+
tmpFileSystem = new FATFileSystemType(this->partitionName);
104+
int err = tmpFileSystem -> reformat(this-> mbrBlockDevice);
88105
if(err != 0){
89106
Arduino_UnifiedStorage::debugPrint("[InternalStorage][format][ERROR] Error formatting partition " + String(this->partitionNumber) + " as FAT: " + String(errno));
90-
}
107+
}
108+
delete tmpFileSystem;
91109
return err == 0;
92110
} if (fs == FS_LITTLEFS) {
93-
this -> fileSystem = new LittleFileSystemType(this->partitionName);
94-
int err = this -> fileSystem -> reformat(this-> mbrBlockDevice);
111+
tmpFileSystem = new LittleFileSystemType(this->partitionName);
112+
int err = tmpFileSystem -> reformat(this-> mbrBlockDevice);
95113
if(err != 0){
96114
Arduino_UnifiedStorage::debugPrint("[InternalStorage][format][ERROR] Error formatting partition " + String(this->partitionNumber) + " as LittleFS: " + String(errno));
97115
}
116+
delete tmpFileSystem;
98117
return err == 0;
99118
}
100119

Diff for: src/InternalStorage.h

+14-12
Original file line numberDiff line numberDiff line change
@@ -10,66 +10,68 @@
1010
*/
1111
class InternalStorage : public Arduino_UnifiedStorage {
1212
public:
13-
13+
1414

1515
/**
1616
* Constructs an InternalStorage object with default settings.
1717
* If no partitions are available, it restores the default partitioning scheme (See restoreDefaultPartitions() for more info).
1818
* If partitions are available, it sets the partition number, file system type, and partition name based on the last partition available.
19-
* When using the default partitioning scheme the last partition would be the user partition.
19+
* When using the default partitioning scheme the last partition would be the user partition.
2020
*/
2121
InternalStorage();
2222

2323
/**
2424
* Constructs an InternalStorage object with the specified partition, name, and file system.
25-
*
25+
*
2626
* @param partition The partition number.
2727
* @param name The name of the partition.
2828
* @param fs The desired file system (FS_FAT or FS_LITTLEFS).
2929
*/
3030
InternalStorage(int partition, const char *name, FileSystems fs);
3131

32+
~InternalStorage();
33+
3234
/**
3335
* Initializes the internal storage.
34-
*
36+
*
3537
* @return true if successful, false if failed.
3638
*/
3739
bool begin() override;
3840

3941
/**
4042
* Initializes the internal storage with the specified file system.
41-
*
43+
*
4244
* @param fs The desired file system (FS_FAT or FS_LITTLEFS).
4345
* @return true if successful, false if failed.
4446
*/
4547
bool begin(FileSystems fs) override;
4648

4749
/**
4850
* Unmounts the internal storage.
49-
*
51+
*
5052
* @return true if successful, false if failed.
5153
*/
5254
bool unmount() override;
5355

5456
/**
5557
* Retrieves the root folder of the internal storage.
56-
*
58+
*
5759
* @return The root folder as a Folder object.
5860
*/
5961
Folder getRootFolder() override;
6062

6163

6264
/**
6365
* Formats the internal storage with the selected file system.
64-
*
66+
*
6567
* @return true if successful, false if failed.
6668
*/
6769
bool format(FileSystems fs) override;
6870

6971

7072
/**
7173
* Retrieves the block device associated with the internal storage.
72-
*
74+
*
7375
* @return The block device as a BlockDevice object.
7476
*/
7577
BlockDeviceType *getBlockDevice();
@@ -86,7 +88,7 @@ class InternalStorage : public Arduino_UnifiedStorage {
8688
* Creates one partition spanning over the whole size of the internal storage drive erasing the existing partitions.
8789
* @return true if successful, false if failed.
8890
*/
89-
static bool partition();
91+
static bool partition();
9092

9193
/**
9294
* Restores the default partitioning scheme (1MB FAT32 for Certificates, 5MB FAT32 for OTA, 8MB user storage) to the internal storage drive erasing the existing partitions.
@@ -96,7 +98,7 @@ class InternalStorage : public Arduino_UnifiedStorage {
9698

9799
/**
98100
* Reads the partitioning scheme from the MBR sector of the internal storage drive and returns a vector of structs of type Partition that represents the partitioning scheme
99-
* @return vector of structs of type Partition
101+
* @return vector of structs of type Partition
100102
*/
101103
static std::vector<Partition> readPartitions();
102104

@@ -105,7 +107,7 @@ class InternalStorage : public Arduino_UnifiedStorage {
105107
MBRBlockDeviceType * mbrBlockDevice;
106108
FileSystemType * fileSystem;
107109
int partitionNumber;
108-
char * partitionName;
110+
const char * partitionName;
109111
FileSystems fileSystemType;
110112

111113
};

0 commit comments

Comments
 (0)