/ components / spi_flash / esp_flash_api.c
esp_flash_api.c
  1  // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
  2  //
  3  // Licensed under the Apache License, Version 2.0 (the "License");
  4  // you may not use this file except in compliance with the License.
  5  // You may obtain a copy of the License at
  6  //
  7  //     http://www.apache.org/licenses/LICENSE-2.0
  8  //
  9  // Unless required by applicable law or agreed to in writing, software
 10  // distributed under the License is distributed on an "AS IS" BASIS,
 11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  // See the License for the specific language governing permissions and
 13  // limitations under the License.
 14  
 15  #include <stdlib.h>
 16  #include <stdio.h>
 17  #include <sys/param.h>
 18  #include <string.h>
 19  
 20  #include "spi_flash_chip_driver.h"
 21  #include "memspi_host_driver.h"
 22  #include "esp_log.h"
 23  #include "sdkconfig.h"
 24  #include "esp_flash_internal.h"
 25  #include "esp_private/system_internal.h"
 26  
 27  
 28  static const char TAG[] = "spi_flash";
 29  
 30  #ifdef CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE
 31  #define MAX_WRITE_CHUNK CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE /* write in chunks */
 32  #else
 33  #define MAX_WRITE_CHUNK 8192 /* write in chunks */
 34  #endif // CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE
 35  
 36  #define MAX_READ_CHUNK 16384
 37  
 38  
 39  #ifdef CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS
 40  #define UNSAFE_WRITE_ADDRESS abort()
 41  #else
 42  #define UNSAFE_WRITE_ADDRESS return ESP_ERR_INVALID_ARG
 43  #endif
 44  
 45  /* CHECK_WRITE_ADDRESS macro to fail writes which land in the
 46     bootloader, partition table, or running application region.
 47  */
 48  #if CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
 49  #define CHECK_WRITE_ADDRESS(CHIP, ADDR, SIZE)
 50  #else /* FAILS or ABORTS */
 51  #define CHECK_WRITE_ADDRESS(CHIP, ADDR, SIZE) do {                            \
 52          if (CHIP && CHIP->os_func->region_protected && CHIP->os_func->region_protected(CHIP->os_func_data, ADDR, SIZE)) {                       \
 53              UNSAFE_WRITE_ADDRESS;                                 \
 54          }                                                               \
 55      } while(0)
 56  #endif // CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
 57  
 58  #define IO_STR_LEN  7
 59  
 60  static const char io_mode_str[][IO_STR_LEN] = {
 61      "slowrd",
 62      "fastrd",
 63      "dout",
 64      "dio",
 65      "qout",
 66      "qio",
 67  };
 68  
 69  _Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the io_mode_str should be consistent with the esp_flash_io_mode_t defined in spi_flash_ll.h");
 70  
 71  esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id);
 72  
 73  static esp_err_t spiflash_start_default(esp_flash_t *chip);
 74  static esp_err_t spiflash_end_default(esp_flash_t *chip, esp_err_t err);
 75  static esp_err_t check_chip_pointer_default(esp_flash_t **inout_chip);
 76  
 77  typedef struct {
 78      esp_err_t (*start)(esp_flash_t *chip);
 79      esp_err_t (*end)(esp_flash_t *chip, esp_err_t err);
 80      esp_err_t (*chip_check)(esp_flash_t **inout_chip);
 81  } rom_spiflash_api_func_t;
 82  
 83  // These functions can be placed in the ROM. For now we use the code in IDF.
 84  DRAM_ATTR static rom_spiflash_api_func_t default_spiflash_rom_api = {
 85      .start = spiflash_start_default,
 86      .end = spiflash_end_default,
 87      .chip_check = check_chip_pointer_default,
 88  };
 89  
 90  DRAM_ATTR rom_spiflash_api_func_t *rom_spiflash_api_funcs = &default_spiflash_rom_api;
 91  
 92  /* Static function to notify OS of a new SPI flash operation.
 93  
 94     If returns an error result, caller must abort. If returns ESP_OK, caller must
 95     call rom_spiflash_api_funcs->end() before returning.
 96  */
 97  static esp_err_t IRAM_ATTR spiflash_start_default(esp_flash_t *chip)
 98  {
 99      if (chip->os_func != NULL && chip->os_func->start != NULL) {
100          esp_err_t err = chip->os_func->start(chip->os_func_data);
101          if (err != ESP_OK) {
102              return err;
103          }
104      }
105      chip->host->driver->dev_config(chip->host);
106      return ESP_OK;
107  }
108  
109  /* Static function to notify OS that SPI flash operation is complete.
110   */
111  static esp_err_t IRAM_ATTR spiflash_end_default(esp_flash_t *chip, esp_err_t err)
112  {
113      if (chip->os_func != NULL
114          && chip->os_func->end != NULL) {
115          esp_err_t end_err = chip->os_func->end(chip->os_func_data);
116          if (err == ESP_OK) {
117              err = end_err; // Only return the 'end' error if we haven't already failed
118          }
119      }
120      return err;
121  }
122  
123  // check that the 'chip' parameter is properly initialised
124  static esp_err_t check_chip_pointer_default(esp_flash_t **inout_chip)
125  {
126      esp_flash_t *chip = *inout_chip;
127      if (chip == NULL) {
128          chip = esp_flash_default_chip;
129      }
130      *inout_chip = chip;
131      if (chip == NULL || !esp_flash_chip_driver_initialized(chip)) {
132          return ESP_ERR_FLASH_NOT_INITIALISED;
133      }
134      return ESP_OK;
135  }
136  
137  /* Return true if regions 'a' and 'b' overlap at all, based on their start offsets and lengths. */
138  inline static bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len);
139  
140  /* Top-level API functions, calling into chip_drv functions via chip->drv */
141  
142  static esp_err_t detect_spi_flash_chip(esp_flash_t *chip);
143  
144  bool esp_flash_chip_driver_initialized(const esp_flash_t *chip)
145  {
146      if (!chip->chip_drv) return false;
147      return true;
148  }
149  
150  esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip)
151  {
152      // Chip init flow
153      // 1. Read chip id
154      // 2. (optional) Detect chip vendor
155      // 3. Get basic parameters of the chip (size, dummy count, etc.)
156      // 4. Init chip into desired mode (without breaking the cache!)
157      esp_err_t err = ESP_OK;
158      if (chip == NULL || chip->host == NULL || chip->host->driver == NULL ||
159          ((memspi_host_inst_t*)chip->host)->spi == NULL) {
160          return ESP_ERR_INVALID_ARG;
161      }
162  
163      //read chip id
164      uint32_t flash_id;
165      int retries = 10;
166      do {
167          err = esp_flash_read_chip_id(chip, &flash_id);
168      } while (err == ESP_ERR_FLASH_NOT_INITIALISED && retries-- > 0);
169  
170      if (err != ESP_OK) {
171          return err;
172      }
173      chip->chip_id = flash_id;
174  
175      if (!esp_flash_chip_driver_initialized(chip)) {
176          // Detect chip_drv
177          err = detect_spi_flash_chip(chip);
178          if (err != ESP_OK) {
179              return err;
180          }
181      }
182  
183      // Detect flash size
184      uint32_t size;
185      err = esp_flash_get_size(chip, &size);
186      if (err != ESP_OK) {
187          ESP_LOGE(TAG, "failed to get chip size");
188          return err;
189      }
190  
191      ESP_LOGI(TAG, "flash io: %s", io_mode_str[chip->read_mode]);
192      err = rom_spiflash_api_funcs->start(chip);
193      if (err != ESP_OK) {
194          return err;
195      }
196  
197      if (err == ESP_OK) {
198          // Try to set the flash mode to whatever default mode was chosen
199          err = chip->chip_drv->set_io_mode(chip);
200          if (err == ESP_ERR_FLASH_NO_RESPONSE && !esp_flash_is_quad_mode(chip)) {
201              //some chips (e.g. Winbond) don't support to clear QE, treat as success
202              err = ESP_OK;
203          }
204      }
205      // Done: all fields on 'chip' are initialised
206      return rom_spiflash_api_funcs->end(chip, err);
207  }
208  
209  static esp_err_t IRAM_ATTR read_id_core(esp_flash_t* chip, uint32_t* out_id, bool sanity_check)
210  {
211      bool installed = esp_flash_chip_driver_initialized(chip);
212      esp_err_t err = rom_spiflash_api_funcs->start(chip);
213      if (err != ESP_OK) {
214          return err;
215      }
216  
217      esp_err_t (*read_id_func)(void*, uint32_t*);
218      void* read_id_arg;
219      if (installed && chip->chip_drv->read_id) {
220          read_id_func = (void*)chip->chip_drv->read_id;
221          read_id_arg = (void*)chip;
222      } else {
223          //default option if the chip is not detected/chosen yet.
224          read_id_func = (void*)chip->host->driver->read_id;
225          read_id_arg = (void*)chip->host;
226      }
227  
228      // Inner function fails if it sees all-ones or all-zeroes.
229      err = read_id_func(read_id_arg, out_id);
230  
231      if (sanity_check && err == ESP_OK) {
232          // Send RDID command twice, check for a matching result and retry in case we just powered on
233          uint32_t new_id;
234          err = read_id_func(read_id_arg, &new_id);
235          if (err == ESP_OK && (new_id != *out_id)) {
236              err = ESP_ERR_FLASH_NOT_INITIALISED;
237          }
238      }
239  
240      return rom_spiflash_api_funcs->end(chip, err);
241  }
242  
243  // Faster version with sanity check.
244  // Called in esp_flash_init and unit test (though not public)
245  esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* out_id)
246  {
247      return read_id_core(chip, out_id, true);
248  }
249  
250  esp_err_t esp_flash_read_id(esp_flash_t* chip, uint32_t* out_id)
251  {
252      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
253      //Accept uninitialized chip when reading chip id
254      if (err != ESP_OK && !(err == ESP_ERR_FLASH_NOT_INITIALISED && chip != NULL)) return err;
255      if (out_id == NULL) return ESP_ERR_INVALID_ARG;
256  
257      return read_id_core(chip, out_id, false);
258  }
259  
260  static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip)
261  {
262      esp_err_t err;
263      uint32_t flash_id = chip->chip_id;
264  
265      // Detect the chip and set the chip_drv structure for it
266      const spi_flash_chip_t **drivers = esp_flash_registered_chips;
267      while (*drivers != NULL && !esp_flash_chip_driver_initialized(chip)) {
268          chip->chip_drv = *drivers;
269          // start/end SPI operation each time, for multitasking
270          // and also so esp_flash_registered_flash_drivers can live in flash
271          ESP_LOGD(TAG, "trying chip: %s", chip->chip_drv->name);
272  
273          err = rom_spiflash_api_funcs->start(chip);
274          if (err != ESP_OK) {
275              return err;
276          }
277  
278          if (chip->chip_drv->probe(chip, flash_id) != ESP_OK) {
279              chip->chip_drv = NULL;
280          }
281          // if probe succeeded, chip->drv stays set
282          drivers++;
283  
284          err = rom_spiflash_api_funcs->end(chip, err);
285          if (err != ESP_OK) {
286              return err;
287          }
288      }
289      if (!esp_flash_chip_driver_initialized(chip)) {
290          return ESP_ERR_NOT_FOUND;
291      }
292      ESP_LOGI(TAG, "detected chip: %s", chip->chip_drv->name);
293      return ESP_OK;
294  }
295  
296  /* Convenience macro for beginning of all API functions.
297   * Check the return value of `rom_spiflash_api_funcs->chip_check` is correct,
298   * and the chip supports the operation in question.
299   */
300  #define VERIFY_CHIP_OP(OP) do {                                  \
301          if (err != ESP_OK) return err; \
302          if (chip->chip_drv->OP == NULL) {                        \
303              return ESP_ERR_FLASH_UNSUPPORTED_CHIP;              \
304          }                                                   \
305      } while (0)
306  
307  esp_err_t IRAM_ATTR esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size)
308  {
309      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
310      VERIFY_CHIP_OP(detect_size);
311      if (out_size == NULL) {
312          return ESP_ERR_INVALID_ARG;
313      }
314      if (chip->size != 0) {
315          *out_size = chip->size;
316          return ESP_OK;
317      }
318  
319      err = rom_spiflash_api_funcs->start(chip);
320      if (err != ESP_OK) {
321          return err;
322      }
323      uint32_t detect_size;
324      err = chip->chip_drv->detect_size(chip, &detect_size);
325      if (err == ESP_OK) {
326          chip->size = detect_size;
327      }
328      return rom_spiflash_api_funcs->end(chip, err);
329  }
330  
331  esp_err_t IRAM_ATTR esp_flash_erase_chip(esp_flash_t *chip)
332  {
333      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
334      VERIFY_CHIP_OP(erase_chip);
335      CHECK_WRITE_ADDRESS(chip, 0, chip->size);
336  
337      err = rom_spiflash_api_funcs->start(chip);
338      if (err != ESP_OK) {
339          return err;
340      }
341  
342      err = chip->chip_drv->erase_chip(chip);
343      return rom_spiflash_api_funcs->end(chip, err);
344  }
345  
346  esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, uint32_t len)
347  {
348      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
349      VERIFY_CHIP_OP(erase_sector);
350      VERIFY_CHIP_OP(erase_block);
351      CHECK_WRITE_ADDRESS(chip, start, len);
352  
353      uint32_t block_erase_size = chip->chip_drv->erase_block == NULL ? 0 : chip->chip_drv->block_erase_size;
354      uint32_t sector_size = chip->chip_drv->sector_size;
355  
356      if (sector_size == 0 || (block_erase_size % sector_size) != 0) {
357          return ESP_ERR_FLASH_NOT_INITIALISED;
358      }
359      if (start > chip->size || start + len > chip->size) {
360          return ESP_ERR_INVALID_ARG;
361      }
362      if ((start % chip->chip_drv->sector_size) != 0 || (len % chip->chip_drv->sector_size) != 0) {
363          // Can only erase multiples of the sector size, starting at sector boundary
364          return ESP_ERR_INVALID_ARG;
365      }
366  
367      err = ESP_OK;
368      // Check for write protected regions overlapping the erase region
369      if (chip->chip_drv->get_protected_regions != NULL &&
370          chip->chip_drv->num_protectable_regions > 0) {
371  
372          err = rom_spiflash_api_funcs->start(chip);
373          if (err != ESP_OK) {
374              return err;
375          }
376          uint64_t protected = 0;
377          err = chip->chip_drv->get_protected_regions(chip, &protected);
378          if (err == ESP_OK && protected != 0) {
379              for (int i = 0; i < chip->chip_drv->num_protectable_regions && err == ESP_OK; i++) {
380                  const esp_flash_region_t *region = &chip->chip_drv->protectable_regions[i];
381                  if ((protected & BIT64(i))
382                      && regions_overlap(start, len, region->offset, region->size)) {
383                      err = ESP_ERR_FLASH_PROTECTED;
384                  }
385              }
386          }
387          // Don't lock the SPI flash for the entire erase, as this may be very long
388          err = rom_spiflash_api_funcs->end(chip, err);
389      }
390  
391  #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
392      int64_t no_yield_time_us = 0;
393  #endif
394      while (err == ESP_OK && len >= sector_size) {
395  #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
396          int64_t start_time_us = esp_system_get_time();
397  #endif
398          err = rom_spiflash_api_funcs->start(chip);
399          if (err != ESP_OK) {
400              return err;
401          }
402  
403  #ifndef CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE
404          // If possible erase an entire multi-sector block
405          if (block_erase_size > 0 && len >= block_erase_size && (start % block_erase_size) == 0) {
406              err = chip->chip_drv->erase_block(chip, start);
407              start += block_erase_size;
408              len -= block_erase_size;
409          } else
410  #endif
411          {
412              // Otherwise erase individual sector only
413              err = chip->chip_drv->erase_sector(chip, start);
414              start += sector_size;
415              len -= sector_size;
416          }
417  
418          err = rom_spiflash_api_funcs->end(chip, err);
419  
420  #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
421          no_yield_time_us += (esp_system_get_time() - start_time_us);
422          if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
423              no_yield_time_us = 0;
424              if (chip->os_func->yield) {
425                  chip->os_func->yield(chip->os_func_data);
426              }
427          }
428  #endif
429      }
430      return err;
431  }
432  
433  esp_err_t IRAM_ATTR esp_flash_get_chip_write_protect(esp_flash_t *chip, bool *out_write_protected)
434  {
435      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
436      VERIFY_CHIP_OP(get_chip_write_protect);
437      if (out_write_protected == NULL) {
438          return ESP_ERR_INVALID_ARG;
439      }
440  
441      err = rom_spiflash_api_funcs->start(chip);
442      if (err != ESP_OK) {
443          return err;
444      }
445  
446      err = chip->chip_drv->get_chip_write_protect(chip, out_write_protected);
447  
448      return rom_spiflash_api_funcs->end(chip, err);
449  }
450  
451  esp_err_t IRAM_ATTR esp_flash_set_chip_write_protect(esp_flash_t *chip, bool write_protect)
452  {
453      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
454      VERIFY_CHIP_OP(set_chip_write_protect);
455      //TODO: skip writing if already locked or unlocked
456  
457      err = rom_spiflash_api_funcs->start(chip);
458      if (err != ESP_OK) {
459          return err;
460      }
461  
462      err = chip->chip_drv->set_chip_write_protect(chip, write_protect);
463  
464      return rom_spiflash_api_funcs->end(chip, err);
465  }
466  
467  esp_err_t esp_flash_get_protectable_regions(const esp_flash_t *chip, const esp_flash_region_t **out_regions, uint32_t *out_num_regions)
468  {
469      if(out_num_regions != NULL) {
470          *out_num_regions = 0; // In case caller doesn't check result
471      }
472      esp_err_t err = rom_spiflash_api_funcs->chip_check((esp_flash_t **)&chip);
473      VERIFY_CHIP_OP(get_protected_regions);
474  
475      if(out_regions == NULL || out_num_regions == NULL) {
476          return ESP_ERR_INVALID_ARG;
477      }
478  
479      *out_num_regions = chip->chip_drv->num_protectable_regions;
480      *out_regions = chip->chip_drv->protectable_regions;
481      return ESP_OK;
482  }
483  
484  static esp_err_t find_region(const esp_flash_t *chip, const esp_flash_region_t *region, uint8_t *index)
485  {
486     if (region == NULL) {
487          return ESP_ERR_INVALID_ARG;
488      }
489  
490     for(*index = 0; *index < chip->chip_drv->num_protectable_regions; (*index)++) {
491         if (memcmp(&chip->chip_drv->protectable_regions[*index],
492                    region, sizeof(esp_flash_region_t)) == 0) {
493             return ESP_OK;
494         }
495     }
496  
497     return ESP_ERR_NOT_FOUND;
498  }
499  
500  esp_err_t IRAM_ATTR esp_flash_get_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool *out_protected)
501  {
502      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
503      VERIFY_CHIP_OP(get_protected_regions);
504  
505      if (out_protected == NULL) {
506          return ESP_ERR_INVALID_ARG;
507      }
508  
509      uint8_t index;
510      err = find_region(chip, region, &index);
511      if (err != ESP_OK) {
512          return err;
513      }
514  
515      uint64_t protection_mask = 0;
516      err = rom_spiflash_api_funcs->start(chip);
517      if (err != ESP_OK) {
518          return err;
519      }
520  
521      err = chip->chip_drv->get_protected_regions(chip, &protection_mask);
522      if (err == ESP_OK) {
523          *out_protected = protection_mask & (1LL << index);
524      }
525  
526      return rom_spiflash_api_funcs->end(chip, err);
527  }
528  
529  esp_err_t IRAM_ATTR esp_flash_set_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool protect)
530  {
531      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
532      VERIFY_CHIP_OP(set_protected_regions);
533  
534      uint8_t index;
535      err = find_region(chip, region, &index);
536      if (err != ESP_OK) {
537          return err;
538      }
539  
540      uint64_t protection_mask = 0;
541      err = rom_spiflash_api_funcs->start(chip);
542      if (err != ESP_OK) {
543          return err;
544      }
545  
546      err = chip->chip_drv->get_protected_regions(chip, &protection_mask);
547      if (err == ESP_OK) {
548          if (protect) {
549              protection_mask |= (1LL << index);
550          } else {
551              protection_mask &= ~(1LL << index);
552          }
553          err = chip->chip_drv->set_protected_regions(chip, protection_mask);
554      }
555  
556      return rom_spiflash_api_funcs->end(chip, err);
557  }
558  
559  esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length)
560  {
561      if (length == 0) {
562          return ESP_OK;
563      }
564      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
565      VERIFY_CHIP_OP(read);
566      if (buffer == NULL || address > chip->size || address+length > chip->size) {
567          return ESP_ERR_INVALID_ARG;
568      }
569  
570      //when the cache is disabled, only the DRAM can be read, check whether we need to receive in another buffer in DRAM.
571      bool direct_read = chip->host->driver->supports_direct_read(chip->host, buffer);
572      uint8_t* temp_buffer = NULL;
573  
574      //each time, we at most read this length
575      //after that, we release the lock to allow some other operations
576      size_t read_chunk_size = MIN(MAX_READ_CHUNK, length);
577  
578      if (!direct_read) {
579          size_t actual_len = 0;
580          if (chip->os_func->get_temp_buffer != NULL) {
581              temp_buffer = chip->os_func->get_temp_buffer(chip->os_func_data, read_chunk_size, &actual_len);
582              read_chunk_size = actual_len;
583          }
584          if (temp_buffer == NULL) {
585              return ESP_ERR_NO_MEM;
586          }
587      }
588  
589      err = ESP_OK;
590      do {
591          err = rom_spiflash_api_funcs->start(chip);
592          if (err != ESP_OK) {
593              break;
594          }
595          //if required (dma buffer allocated), read to the buffer instead of the original buffer
596          uint8_t* buffer_to_read = (temp_buffer)? temp_buffer : buffer;
597  
598          // Length we will read this iteration is either the chunk size or the remaining length, whichever is smaller
599          size_t length_to_read = MIN(read_chunk_size, length);
600  
601          if (err == ESP_OK) {
602              err = chip->chip_drv->read(chip, buffer_to_read, address, length_to_read);
603          }
604          if (err != ESP_OK) {
605              rom_spiflash_api_funcs->end(chip, err);
606              break;
607          }
608          //even if this is failed, the data is still valid, copy before quit
609          err = rom_spiflash_api_funcs->end(chip, err);
610  
611          //copy back to the original buffer
612          if (temp_buffer) {
613              memcpy(buffer, temp_buffer, length_to_read);
614          }
615          address += length_to_read;
616          length -= length_to_read;
617          buffer = (void*)((intptr_t)buffer + length_to_read);
618      } while (err == ESP_OK && length > 0);
619  
620      if (chip->os_func->release_temp_buffer != NULL) {
621          chip->os_func->release_temp_buffer(chip->os_func_data, temp_buffer);
622      }
623      return err;
624  }
625  
626  esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)
627  {
628      if (length == 0) {
629          return ESP_OK;
630      }
631      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
632      VERIFY_CHIP_OP(write);
633      CHECK_WRITE_ADDRESS(chip, address, length);
634      if (buffer == NULL || address > chip->size || address+length > chip->size) {
635          return ESP_ERR_INVALID_ARG;
636      }
637  
638      //when the cache is disabled, only the DRAM can be read, check whether we need to copy the data first
639      bool direct_write = chip->host->driver->supports_direct_write(chip->host, buffer);
640  
641      err = ESP_OK;
642      /* Write output in chunks, either by buffering on stack or
643         by artificially cutting into MAX_WRITE_CHUNK parts (in an OS
644         environment, this prevents writing from causing interrupt or higher priority task
645         starvation.) */
646      do {
647          uint32_t write_len;
648          const void *write_buf;
649          uint32_t temp_buf[8];
650          if (direct_write) {
651              write_len = MIN(length, MAX_WRITE_CHUNK);
652              write_buf = buffer;
653          } else {
654              write_len = MIN(length, sizeof(temp_buf));
655              memcpy(temp_buf, buffer, write_len);
656              write_buf = temp_buf;
657          }
658  
659          err = rom_spiflash_api_funcs->start(chip);
660          if (err != ESP_OK) {
661              return err;
662          }
663  
664          err = chip->chip_drv->write(chip, write_buf, address, write_len);
665  
666          address += write_len;
667          buffer = (void *)((intptr_t)buffer + write_len);
668          length -= write_len;
669  
670          err = rom_spiflash_api_funcs->end(chip, err);
671      } while (err == ESP_OK && length > 0);
672      return err;
673  }
674  
675  //currently the legacy implementation is used, from flash_ops.c
676  esp_err_t spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size);
677  
678  esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length)
679  {
680      /*
681       * Since currently this feature is supported only by the hardware, there
682       * is no way to support non-standard chips. We use the legacy
683       * implementation and skip the chip and driver layers.
684       */
685      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
686      if (err != ESP_OK) return err;
687      if (buffer == NULL || address > chip->size || address+length > chip->size) {
688          return ESP_ERR_INVALID_ARG;
689      }
690      return spi_flash_write_encrypted(address, buffer, length);
691  }
692  
693  inline static IRAM_ATTR bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len)
694  {
695      uint32_t a_end = a_start + a_len;
696      uint32_t b_end = b_start + b_len;
697      return (a_end > b_start && b_end > a_start);
698  }
699  
700  //currently the legacy implementation is used, from flash_ops.c
701  esp_err_t spi_flash_read_encrypted(size_t src, void *dstv, size_t size);
702  
703  esp_err_t IRAM_ATTR esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address, void *out_buffer, uint32_t length)
704  {
705      /*
706       * Since currently this feature is supported only by the hardware, there
707       * is no way to support non-standard chips. We use the legacy
708       * implementation and skip the chip and driver layers.
709       */
710      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
711      if (err != ESP_OK) return err;
712      return spi_flash_read_encrypted(address, out_buffer, length);
713  }
714  
715  // test only, non-public
716  IRAM_ATTR esp_err_t esp_flash_get_io_mode(esp_flash_t* chip, bool* qe)
717  {
718      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
719      VERIFY_CHIP_OP(get_io_mode);
720      esp_flash_io_mode_t io_mode;
721  
722      err = rom_spiflash_api_funcs->start(chip);
723      if (err != ESP_OK) {
724          return err;
725      }
726      err = chip->chip_drv->get_io_mode(chip, &io_mode);
727      err = rom_spiflash_api_funcs->end(chip, err);
728      if (err == ESP_OK) {
729          *qe = (io_mode == SPI_FLASH_QOUT);
730      }
731      return err;
732  }
733  
734  IRAM_ATTR esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe)
735  {
736      esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
737      VERIFY_CHIP_OP(set_io_mode);
738  
739      chip->read_mode = (qe? SPI_FLASH_QOUT: SPI_FLASH_SLOWRD);
740      err = rom_spiflash_api_funcs->start(chip);
741      if (err != ESP_OK) {
742          return err;
743      }
744      err = chip->chip_drv->set_io_mode(chip);
745      return rom_spiflash_api_funcs->end(chip, err);
746  }
747  
748  #ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
749  esp_err_t esp_flash_app_disable_protect(bool disable)
750  {
751      if (disable) {
752          return esp_flash_app_disable_os_functions(esp_flash_default_chip);
753      } else {
754          return esp_flash_app_enable_os_functions(esp_flash_default_chip);
755      }
756  }
757  #endif
758  
759  /*------------------------------------------------------------------------------
760      Adapter layer to original api before IDF v4.0
761  ------------------------------------------------------------------------------*/
762  
763  #ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
764  
765  /* Translate any ESP_ERR_FLASH_xxx error code (new API) to a generic ESP_ERR_xyz error code
766   */
767  static IRAM_ATTR esp_err_t spi_flash_translate_rc(esp_err_t err)
768  {
769      switch (err) {
770          case ESP_OK:
771          case ESP_ERR_INVALID_ARG:
772          case ESP_ERR_NO_MEM:
773              return err;
774  
775          case ESP_ERR_FLASH_NOT_INITIALISED:
776          case ESP_ERR_FLASH_PROTECTED:
777              return ESP_ERR_INVALID_STATE;
778  
779          case ESP_ERR_NOT_FOUND:
780          case ESP_ERR_FLASH_UNSUPPORTED_HOST:
781          case ESP_ERR_FLASH_UNSUPPORTED_CHIP:
782              return ESP_ERR_NOT_SUPPORTED;
783  
784          case ESP_ERR_FLASH_NO_RESPONSE:
785              return ESP_ERR_INVALID_RESPONSE;
786  
787          default:
788              ESP_EARLY_LOGE(TAG, "unexpected spi flash error code: 0x%x", err);
789              abort();
790      }
791  }
792  
793  esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
794  {
795      esp_err_t err = esp_flash_erase_region(NULL, start_addr, size);
796      return spi_flash_translate_rc(err);
797  }
798  
799  esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
800  {
801      esp_err_t err = esp_flash_write(NULL, srcv, dst, size);
802      return spi_flash_translate_rc(err);
803  }
804  
805  esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
806  {
807      esp_err_t err = esp_flash_read(NULL, dstv, src, size);
808      return spi_flash_translate_rc(err);
809  }
810  
811  #endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL