1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
46
47
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
75
76
77
78
79
80
81
82
83
84
87
88
89
90
91
92
93
94
95
96
100
101
102
103
104
105
106
107
111
112
113
114
115
116
119
120
121
122
123
124
131
132
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
193
194
195
196
197
198
199
200
206
207
211
212
/* ... */
/* ... */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "esp_flash.h"
#include "esp_flash_spi_init.h"
#include "esp_partition.h"
#include "esp_vfs.h"
#include "esp_vfs_fat.h"
#include "esp_system.h"
#include "soc/spi_pins.h"10 includes
#define EXAMPLE_FLASH_FREQ_MHZ 40
static const char *TAG = "example";
#ifdef CONFIG_IDF_TARGET_ESP32
#define HOST_ID SPI3_HOST
#define PIN_MOSI SPI3_IOMUX_PIN_NUM_MOSI
#define PIN_MISO SPI3_IOMUX_PIN_NUM_MISO
#define PIN_CLK SPI3_IOMUX_PIN_NUM_CLK
#define PIN_CS SPI3_IOMUX_PIN_NUM_CS
#define PIN_WP SPI3_IOMUX_PIN_NUM_WP
#define PIN_HD SPI3_IOMUX_PIN_NUM_HD
#define SPI_DMA_CHAN SPI_DMA_CH_AUTO/* ... */
#else
#define HOST_ID SPI2_HOST
#define PIN_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define PIN_MISO SPI2_IOMUX_PIN_NUM_MISO
#define PIN_CLK SPI2_IOMUX_PIN_NUM_CLK
#define PIN_CS SPI2_IOMUX_PIN_NUM_CS
#define PIN_WP SPI2_IOMUX_PIN_NUM_WP
#define PIN_HD SPI2_IOMUX_PIN_NUM_HD
#define SPI_DMA_CHAN SPI_DMA_CH_AUTO/* ... */
#endif
static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
const char *base_path = "/extflash";
static esp_flash_t* example_init_ext_flash(void);
static const esp_partition_t* example_add_partition(esp_flash_t* ext_flash, const char* partition_label);
static void example_list_data_partitions(void);
static bool example_mount_fatfs(const char* partition_label);
void app_main(void)
{
esp_flash_t* flash = example_init_ext_flash();
if (flash == NULL) {
return;
}{...}
const char *partition_label = "storage";
example_add_partition(flash, partition_label);
example_list_data_partitions();
if (!example_mount_fatfs(partition_label)) {
return;
}{...}
uint64_t bytes_total, bytes_free;
esp_vfs_fat_info(base_path, &bytes_total, &bytes_free);
ESP_LOGI(TAG, "FAT FS: %" PRIu64 " kB total, %" PRIu64 " kB free", bytes_total / 1024, bytes_free / 1024);
ESP_LOGI(TAG, "Opening file");
FILE *f = fopen("/extflash/hello.txt", "wb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}{...}
fprintf(f, "Written using ESP-IDF %s\n", esp_get_idf_version());
fclose(f);
ESP_LOGI(TAG, "File written");
ESP_LOGI(TAG, "Reading file");
f = fopen("/extflash/hello.txt", "rb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}{...}
char line[128];
fgets(line, sizeof(line), f);
fclose(f);
char *pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}{...}
ESP_LOGI(TAG, "Read from file: '%s'", line);
}{ ... }
static esp_flash_t* example_init_ext_flash(void)
{
const spi_bus_config_t bus_config = {
.mosi_io_num = PIN_MOSI,
.miso_io_num = PIN_MISO,
.sclk_io_num = PIN_CLK,
.quadhd_io_num = PIN_HD,
.quadwp_io_num = PIN_WP,
}{...};
const esp_flash_spi_device_config_t device_config = {
.host_id = HOST_ID,
.cs_id = 0,
.cs_io_num = PIN_CS,
.io_mode = SPI_FLASH_DIO,
.freq_mhz = EXAMPLE_FLASH_FREQ_MHZ,
}{...};
ESP_LOGI(TAG, "Initializing external SPI Flash");
ESP_LOGI(TAG, "Pin assignments:");
ESP_LOGI(TAG, "MOSI: %2d MISO: %2d SCLK: %2d CS: %2d",
bus_config.mosi_io_num, bus_config.miso_io_num,
bus_config.sclk_io_num, device_config.cs_io_num
);
ESP_LOGI(TAG, "DMA CHANNEL: %d", SPI_DMA_CHAN);
ESP_ERROR_CHECK(spi_bus_initialize(HOST_ID, &bus_config, SPI_DMA_CHAN));
esp_flash_t* ext_flash;
ESP_ERROR_CHECK(spi_bus_add_flash_device(&ext_flash, &device_config));
esp_err_t err = esp_flash_init(ext_flash);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize external Flash: %s (0x%x)", esp_err_to_name(err), err);
return NULL;
}{...}
uint32_t id;
ESP_ERROR_CHECK(esp_flash_read_id(ext_flash, &id));
ESP_LOGI(TAG, "Initialized external Flash, size=%" PRIu32 " KB, ID=0x%" PRIx32, ext_flash->size / 1024, id);
return ext_flash;
}{ ... }
static const esp_partition_t* example_add_partition(esp_flash_t* ext_flash, const char* partition_label)
{
ESP_LOGI(TAG, "Adding external Flash as a partition, label=\"%s\", size=%" PRIu32 " KB", partition_label, ext_flash->size / 1024);
const esp_partition_t* fat_partition;
const size_t offset = 0;
ESP_ERROR_CHECK(esp_partition_register_external(ext_flash, offset, ext_flash->size, partition_label, ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, &fat_partition));
ESP_LOGI(TAG, "Erasing partition range, offset=%u size=%" PRIu32 " KB", offset, ext_flash->size / 1024);
ESP_ERROR_CHECK(esp_partition_erase_range(fat_partition, offset, ext_flash->size));
return fat_partition;
}{ ... }
static void example_list_data_partitions(void)
{
ESP_LOGI(TAG, "Listing data partitions:");
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL);
for (; it != NULL; it = esp_partition_next(it)) {
const esp_partition_t *part = esp_partition_get(it);
ESP_LOGI(TAG, "- partition '%s', subtype %d, offset 0x%" PRIx32 ", size %" PRIu32 " kB",
part->label, part->subtype, part->address, part->size / 1024);
}{...}
esp_partition_iterator_release(it);
}{ ... }
static bool example_mount_fatfs(const char* partition_label)
{
ESP_LOGI(TAG, "Mounting FAT filesystem");
const esp_vfs_fat_mount_config_t mount_config = {
.max_files = 4,
.format_if_mount_failed = true,
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE,
.use_one_fat = false,
}{...};
esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, &mount_config, &s_wl_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
return false;
}{...}
return true;
}{ ... }