Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d23aa26

Browse files
authored
Merge pull request #226 from iabdalkader/file_system_support
variants: Enable file system support.
2 parents 658a690 + 22d8d6b commit d23aa26

File tree

12 files changed

+6186
-2
lines changed

12 files changed

+6186
-2
lines changed
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/*
2+
Flash Format
3+
4+
The sketch formats the board flash storage as follows:
5+
6+
* Partition 1 1MB: used for network certificates
7+
* Partition 2 5MB: OTA
8+
* Partition 3 1MB: Provisioning KVStore
9+
* Partition 4 7MB: User data
10+
11+
This example code is in the public domain.
12+
*/
13+
14+
#include <Arduino.h>
15+
#include <zephyr/fs/fs.h>
16+
#include <zephyr/storage/flash_map.h>
17+
#include "certificates.h"
18+
19+
// MBR structures
20+
struct __attribute__((packed)) mbrEntry {
21+
uint8_t status;
22+
uint8_t chsStart[3];
23+
uint8_t type;
24+
uint8_t chsStop[3];
25+
uint32_t lbaOffset;
26+
uint32_t lbaSize;
27+
};
28+
29+
struct __attribute__((packed)) mbrTable {
30+
mbrEntry entries[4];
31+
uint8_t signature[2];
32+
};
33+
34+
bool waitResponse() {
35+
bool proceed = false;
36+
bool confirmation = false;
37+
38+
while (confirmation == false) {
39+
if (!Serial.available()) {
40+
continue;
41+
}
42+
43+
switch (Serial.read()) {
44+
case 'y':
45+
case 'Y':
46+
confirmation = true;
47+
proceed = true;
48+
break;
49+
case 'n':
50+
case 'N':
51+
confirmation = true;
52+
proceed = false;
53+
break;
54+
default:
55+
continue;
56+
}
57+
}
58+
59+
return proceed;
60+
}
61+
62+
int formatPartition(unsigned int partition_id, int fs_type) {
63+
Serial.print("Formatting partition as ");
64+
Serial.println(fs_type == FS_FATFS ? "FAT..." : "LittleFS...");
65+
66+
int rc = 0;
67+
if (fs_type == FS_FATFS) {
68+
rc = fs_mkfs(FS_FATFS, partition_id, NULL, 0);
69+
} else {
70+
rc = fs_mkfs(FS_LITTLEFS, partition_id, NULL, 0);
71+
}
72+
73+
if (rc < 0) {
74+
Serial.print("Error formatting partition: ");
75+
Serial.println(rc);
76+
return rc;
77+
}
78+
79+
Serial.print("Partition formatted successfully!");
80+
return 0;
81+
}
82+
83+
int flashCertificates() {
84+
Serial.print("Certificate size: ");
85+
Serial.print(cacert_pem_len);
86+
Serial.println(" bytes");
87+
88+
struct fs_file_t file;
89+
fs_file_t_init(&file);
90+
91+
Serial.println("Opening /wlan:/cacert.pem for writing...");
92+
int rc = fs_open(&file, "/wlan:/cacert.pem", FS_O_CREATE | FS_O_WRITE);
93+
if (rc != 0) {
94+
Serial.print("Error opening cacert.pem: ");
95+
Serial.println(rc);
96+
return rc;
97+
}
98+
99+
Serial.println("Writing certificates...");
100+
ssize_t ret = fs_write(&file, cacert_pem, cacert_pem_len);
101+
if (ret < 0) {
102+
Serial.print("Error writing certificates: ");
103+
Serial.println(ret);
104+
fs_close(&file);
105+
return rc;
106+
}
107+
108+
rc = fs_sync(&file);
109+
if (rc != 0) {
110+
Serial.print("Warning: fs_sync failed: ");
111+
Serial.println(rc);
112+
fs_close(&file);
113+
return rc;
114+
}
115+
116+
fs_close(&file);
117+
Serial.println("Certificates written successfully!");
118+
return 0;
119+
}
120+
121+
int flashMBR() {
122+
Serial.println("Creating MBR partition table...");
123+
124+
// Open the MBR partition
125+
const struct flash_area *fa;
126+
int ret = flash_area_open(FIXED_PARTITION_ID(mbr_partition), &fa);
127+
if (ret) {
128+
Serial.print("Error opening MBR partition: ");
129+
Serial.println(ret);
130+
return ret;
131+
}
132+
133+
// Prepare 512-byte sector with MBR
134+
uint8_t sector[512];
135+
memset(sector, 0, 512);
136+
137+
// MBR partition table starts at offset 446
138+
mbrTable *table = (mbrTable*)&sector[446];
139+
140+
// Note: lbaSize is in units of 4096-byte blocks (not standard 512-byte sectors)
141+
// This matches the original Arduino implementation which uses 4KB sectors
142+
143+
// Partition 1: WLAN (FAT32) - starts at 0x1000, size ~1020KB (255 blocks of 4KB)
144+
table->entries[0].status = 0x00; // Not bootable
145+
table->entries[0].chsStart[0] = 0;
146+
table->entries[0].chsStart[1] = 2;
147+
table->entries[0].chsStart[2] = 0;
148+
table->entries[0].type = 0x0B; // FAT32
149+
table->entries[0].chsStop[0] = 4;
150+
table->entries[0].chsStop[1] = 0;
151+
table->entries[0].chsStop[2] = 0;
152+
table->entries[0].lbaOffset = 1; // 0x1000 / 4096 = 1
153+
table->entries[0].lbaSize = 255; // (1MB - 4KB) / 4096 = 255
154+
155+
// Partition 2: OTA (FAT32) - starts at 0x100000, size 5MB (1280 blocks of 4KB)
156+
table->entries[1].status = 0x00;
157+
table->entries[1].chsStart[0] = 4;
158+
table->entries[1].chsStart[1] = 1;
159+
table->entries[1].chsStart[2] = 0;
160+
table->entries[1].type = 0x0B; // FAT32
161+
table->entries[1].chsStop[0] = 24;
162+
table->entries[1].chsStop[1] = 0;
163+
table->entries[1].chsStop[2] = 0;
164+
table->entries[1].lbaOffset = 256; // 0x100000 / 4096 = 256
165+
table->entries[1].lbaSize = 1280; // 5MB / 4096 = 1280
166+
167+
// Partition 3: KVS (FAT32) - starts at 0x600000, size 1MB (256 blocks of 4KB)
168+
table->entries[2].status = 0x00;
169+
table->entries[2].chsStart[0] = 24;
170+
table->entries[2].chsStart[1] = 1;
171+
table->entries[2].chsStart[2] = 0;
172+
table->entries[2].type = 0x0B; // FAT32
173+
table->entries[2].chsStop[0] = 28;
174+
table->entries[2].chsStop[1] = 0;
175+
table->entries[2].chsStop[2] = 0;
176+
table->entries[2].lbaOffset = 1536; // 0x600000 / 4096 = 1536
177+
table->entries[2].lbaSize = 256; // 1MB / 4096 = 256
178+
179+
// Partition 4: Storage (LittleFS/FAT32) - starts at 0x700000, size 7MB (1792 blocks of 4KB)
180+
table->entries[3].status = 0x00;
181+
table->entries[3].chsStart[0] = 28;
182+
table->entries[3].chsStart[1] = 1;
183+
table->entries[3].chsStart[2] = 0;
184+
table->entries[3].type = 0x0B; // FAT32 (could be 0x83 for LittleFS)
185+
table->entries[3].chsStop[0] = 56;
186+
table->entries[3].chsStop[1] = 0;
187+
table->entries[3].chsStop[2] = 0;
188+
table->entries[3].lbaOffset = 1792; // 0x700000 / 4096 = 1792
189+
table->entries[3].lbaSize = 1792; // 7MB / 4096 = 1792
190+
191+
// MBR signature
192+
table->signature[0] = 0x55;
193+
table->signature[1] = 0xAA;
194+
195+
// Erase the MBR partition
196+
ret = flash_area_erase(fa, 0, fa->fa_size);
197+
if (ret) {
198+
Serial.print("Error erasing MBR partition: ");
199+
Serial.println(ret);
200+
flash_area_close(fa);
201+
return ret;
202+
}
203+
204+
// Write the MBR sector
205+
ret = flash_area_write(fa, 0, sector, 512);
206+
if (ret) {
207+
Serial.print("Error writing MBR: ");
208+
Serial.println(ret);
209+
flash_area_close(fa);
210+
return ret;
211+
}
212+
213+
flash_area_close(fa);
214+
Serial.println("MBR created successfully!");
215+
return 0;
216+
}
217+
218+
void setup() {
219+
Serial.begin(115200);
220+
while (!Serial);
221+
222+
Serial.println("\nWARNING! Running the sketch all the content of the flash storage will be erased.");
223+
Serial.println("The following partitions will be created:");
224+
Serial.println("Partition 1: Network certificates 1MB");
225+
Serial.println("Partition 2: OTA 5MB");
226+
Serial.println("Partition 3: Provisioning KVStore 1MB");
227+
Serial.println("Partition 4: User data 7MB");
228+
Serial.println("Do you want to proceed? Y/[n]");
229+
230+
if (!waitResponse()) {
231+
return;
232+
}
233+
234+
// Create MBR partition table FIRST before formatting
235+
if (flashMBR()) {
236+
return;
237+
}
238+
239+
// Format Partition 1: WLAN
240+
Serial.println("\nPartition 1 (/wlan:) will be formatted as FAT.");
241+
Serial.println("Do you want to format it? Y/[n]");
242+
bool format_wlan = waitResponse();
243+
244+
if (format_wlan) {
245+
if (formatPartition((uintptr_t) "wlan:", FS_FATFS)) {
246+
return;
247+
}
248+
249+
Serial.println("\nDo you want to restore the TLS certificates? Y/[n]");
250+
if (waitResponse() && flashCertificates()) {
251+
return;
252+
}
253+
}
254+
255+
// Format Partition 2: OTA
256+
Serial.println("\nPartition 2 (/ota:) will be formatted as FAT.");
257+
Serial.println("Do you want to format it? Y/[n]");
258+
if (waitResponse()) {
259+
if (formatPartition((uintptr_t) "ota:", FS_FATFS)) {
260+
return;
261+
}
262+
}
263+
264+
// Format Partition 4: Storage
265+
Serial.println("\nDo you want to use LittleFS to format user data partition? Y/[n]");
266+
Serial.println("If No, FatFS will be used to format user partition.");
267+
bool useLittleFS = waitResponse();
268+
269+
Serial.println("\nPartition 4 (/storage) will be formatted.");
270+
Serial.println("Do you want to format it? Y/[n]");
271+
if (waitResponse()) {
272+
if (useLittleFS) {
273+
unsigned int partition_id = DT_FIXED_PARTITION_ID(DT_PROP(DT_NODELABEL(storage_fs), partition));
274+
if (formatPartition(partition_id, FS_LITTLEFS)) {
275+
return;
276+
}
277+
} else {
278+
Serial.println("FatFS for storage partition not implemented in this example.");
279+
Serial.println("Please use LittleFS or update device tree configuration.");
280+
}
281+
}
282+
283+
Serial.println("\nFlash storage formatted!");
284+
Serial.println("It's now safe to reboot or disconnect your board.");
285+
}
286+
287+
void loop() {
288+
delay(1000);
289+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /