/ components / spi_flash / esp_flash_spi_init.c
esp_flash_spi_init.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 "sdkconfig.h"
 16  #include "esp_flash.h"
 17  #include "memspi_host_driver.h"
 18  #include "esp_flash_spi_init.h"
 19  #include "driver/gpio.h"
 20  #include "esp_rom_gpio.h"
 21  #include "esp_rom_efuse.h"
 22  #include "esp_log.h"
 23  #include "esp_heap_caps.h"
 24  #include "hal/spi_types.h"
 25  #include "driver/spi_common_internal.h"
 26  #include "esp_flash_internal.h"
 27  #include "esp_rom_gpio.h"
 28  #if CONFIG_IDF_TARGET_ESP32
 29  #include "esp32/rom/spi_flash.h"
 30  #elif CONFIG_IDF_TARGET_ESP32S2
 31  #include "esp32s2/rom/spi_flash.h"
 32  #elif CONFIG_IDF_TARGET_ESP32S3
 33  #include "esp32s3/rom/spi_flash.h"
 34  #endif
 35  
 36  __attribute__((unused)) static const char TAG[] = "spi_flash";
 37  
 38  #ifdef CONFIG_ESPTOOLPY_FLASHFREQ_80M
 39  #define DEFAULT_FLASH_SPEED ESP_FLASH_80MHZ
 40  #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_40M
 41  #define DEFAULT_FLASH_SPEED ESP_FLASH_40MHZ
 42  #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_26M
 43  #define DEFAULT_FLASH_SPEED ESP_FLASH_26MHZ
 44  #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_20M
 45  #define DEFAULT_FLASH_SPEED ESP_FLASH_20MHZ
 46  #else
 47  #error Flash frequency not defined! Check the ``CONFIG_ESPTOOLPY_FLASHFREQ_*`` options.
 48  #endif
 49  
 50  #if defined(CONFIG_ESPTOOLPY_FLASHMODE_QIO)
 51  #define DEFAULT_FLASH_MODE  SPI_FLASH_QIO
 52  #elif defined(CONFIG_ESPTOOLPY_FLASHMODE_QOUT)
 53  #define DEFAULT_FLASH_MODE  SPI_FLASH_QOUT
 54  #elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DIO)
 55  #define DEFAULT_FLASH_MODE  SPI_FLASH_DIO
 56  #elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT)
 57  #define DEFAULT_FLASH_MODE  SPI_FLASH_DOUT
 58  #else
 59  #define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD
 60  #endif
 61  
 62  //TODO: modify cs hold to meet requirements of all chips!!!
 63  #if CONFIG_IDF_TARGET_ESP32
 64  #define ESP_FLASH_HOST_CONFIG_DEFAULT()  (memspi_host_config_t){ \
 65      .host_id = SPI_HOST,\
 66      .speed = DEFAULT_FLASH_SPEED, \
 67      .cs_num = 0, \
 68      .iomux = false, \
 69      .input_delay_ns = 0,\
 70  }
 71  #elif CONFIG_IDF_TARGET_ESP32S2
 72  #define ESP_FLASH_HOST_CONFIG_DEFAULT()  (memspi_host_config_t){ \
 73      .host_id = SPI_HOST,\
 74      .speed = DEFAULT_FLASH_SPEED, \
 75      .cs_num = 0, \
 76      .iomux = true, \
 77      .input_delay_ns = 0,\
 78  }
 79  #elif CONFIG_IDF_TARGET_ESP32S3
 80  #include "esp32s3/rom/efuse.h"
 81  #define ESP_FLASH_HOST_CONFIG_DEFAULT()  (memspi_host_config_t){ \
 82      .host_id = SPI_HOST,\
 83      .speed = DEFAULT_FLASH_SPEED, \
 84      .cs_num = 0, \
 85      .iomux = true, \
 86      .input_delay_ns = 0,\
 87  }
 88  #endif
 89  
 90  
 91  esp_flash_t *esp_flash_default_chip = NULL;
 92  
 93  
 94  static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_flash_spi_device_config_t *config, bool use_iomux, int cs_id)
 95  {
 96      //Not using spicommon_cs_initialize since we don't want to put the whole
 97      //spi_periph_signal into the DRAM. Copy these data from flash before the
 98      //cache disabling
 99      int cs_io_num = config->cs_io_num;
100      int spics_in = spi_periph_signal[config->host_id].spics_in;
101      int spics_out = spi_periph_signal[config->host_id].spics_out[cs_id];
102      int spics_func = spi_periph_signal[config->host_id].func;
103      uint32_t iomux_reg = GPIO_PIN_MUX_REG[cs_io_num];
104  
105      //To avoid the panic caused by flash data line conflicts during cs line
106      //initialization, disable the cache temporarily
107      chip->os_func->start(chip->os_func_data);
108      PIN_INPUT_ENABLE(iomux_reg);
109      if (use_iomux) {
110          PIN_FUNC_SELECT(iomux_reg, spics_func);
111      } else {
112          if (cs_io_num < 32) {
113              GPIO.enable_w1ts = (0x1 << cs_io_num);
114          } else {
115              GPIO.enable1_w1ts.data = (0x1 << (cs_io_num - 32));
116          }
117          GPIO.pin[cs_io_num].pad_driver = 0;
118          esp_rom_gpio_connect_out_signal(cs_io_num, spics_out, false, false);
119          if (cs_id == 0) {
120              esp_rom_gpio_connect_in_signal(cs_io_num, spics_in, false);
121          }
122          PIN_FUNC_SELECT(iomux_reg, PIN_FUNC_GPIO);
123      }
124      chip->os_func->end(chip->os_func_data);
125  }
126  
127  esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_device_config_t *config)
128  {
129      if (out_chip == NULL) {
130          return ESP_ERR_INVALID_ARG;
131      }
132      esp_flash_t *chip = NULL;
133      memspi_host_inst_t *host = NULL;
134      esp_err_t ret = ESP_OK;
135  
136      uint32_t caps = MALLOC_CAP_DEFAULT;
137      if (config->host_id == SPI_HOST) caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT;
138  
139      chip = (esp_flash_t*)heap_caps_malloc(sizeof(esp_flash_t), caps);
140      if (!chip) {
141          ret = ESP_ERR_NO_MEM;
142          goto fail;
143      }
144  
145      host = (memspi_host_inst_t*)heap_caps_malloc(sizeof(memspi_host_inst_t), caps);
146      *chip = (esp_flash_t) {
147          .read_mode = config->io_mode,
148          .host = (spi_flash_host_inst_t*)host,
149      };
150      if (!host) {
151          ret = ESP_ERR_NO_MEM;
152          goto fail;
153      }
154  
155      int dev_id = -1;
156      esp_err_t err = esp_flash_init_os_functions(chip, config->host_id, &dev_id);
157      if (err == ESP_ERR_NOT_SUPPORTED) {
158          ESP_LOGE(TAG, "Init os functions failed! No free CS.");
159      } else if (err == ESP_ERR_INVALID_ARG) {
160          ESP_LOGE(TAG, "Init os functions failed! Bus lock not initialized (check CONFIG_SPI_FLASH_SHARE_SPI1_BUS).");
161      }
162      if (err != ESP_OK) {
163          ret = err;
164          goto fail;
165      }
166      // When `CONFIG_SPI_FLASH_SHARE_SPI1_BUS` is not enabled on SPI1 bus, the
167      // `esp_flash_init_os_functions` will not be able to assign a new device ID. In this case, we
168      // use the `cs_id` in the config structure.
169      if (dev_id == -1 && config->host_id == SPI_HOST) {
170          dev_id = config->cs_id;
171      }
172      assert(dev_id < SOC_SPI_PERIPH_CS_NUM(config->host_id) && dev_id >= 0);
173  
174      bool use_iomux = spicommon_bus_using_iomux(config->host_id);
175      memspi_host_config_t host_cfg = {
176          .host_id = config->host_id,
177          .cs_num = dev_id,
178          .iomux = use_iomux,
179          .input_delay_ns = config->input_delay_ns,
180          .speed = config->speed,
181      };
182      err = memspi_host_init_pointers(host, &host_cfg);
183      if (err != ESP_OK) {
184          ret = err;
185          goto fail;
186      }
187  
188      // The cs_id inside `config` is deprecated, use the `dev_id` provided by the bus lock instead.
189      cs_initialize(chip, config, use_iomux, dev_id);
190      *out_chip = chip;
191      return ret;
192  fail:
193      // The memory allocated are free'd in the `spi_bus_remove_flash_device`.
194      spi_bus_remove_flash_device(chip);
195      return ret;
196  }
197  
198  esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip)
199  {
200      if (chip==NULL) {
201          return ESP_ERR_INVALID_ARG;
202      }
203      esp_flash_deinit_os_functions(chip);
204      free(chip->host);
205      free(chip);
206      return ESP_OK;
207  }
208  
209  
210  /* The default (ie initial boot) no-OS ROM esp_flash_os_functions_t */
211  extern const esp_flash_os_functions_t esp_flash_noos_functions;
212  
213  #ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
214  
215  static DRAM_ATTR memspi_host_inst_t esp_flash_default_host;
216  
217  static DRAM_ATTR esp_flash_t default_chip = {
218      .read_mode = DEFAULT_FLASH_MODE,
219      .host = (spi_flash_host_inst_t*)&esp_flash_default_host,
220      .os_func = &esp_flash_noos_functions,
221  };
222  
223  esp_err_t esp_flash_init_default_chip(void)
224  {
225      memspi_host_config_t cfg = ESP_FLASH_HOST_CONFIG_DEFAULT();
226  
227      #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
228      // For esp32s2 spi IOs are configured as from IO MUX by default
229      cfg.iomux = esp_rom_efuse_get_flash_gpio_info() == 0 ?  true : false;
230      #endif
231  
232      //the host is already initialized, only do init for the data and load it to the host
233      esp_err_t err = memspi_host_init_pointers(&esp_flash_default_host, &cfg);
234      if (err != ESP_OK) {
235          return err;
236      }
237  
238      // ROM TODO: account for non-standard default pins in efuse
239      // ROM TODO: to account for chips which are slow to power on, maybe keep probing in a loop here
240      err = esp_flash_init(&default_chip);
241      if (err != ESP_OK) {
242          return err;
243      }
244      if (default_chip.size < g_rom_flashchip.chip_size) {
245          ESP_EARLY_LOGE(TAG, "Detected size(%dk) smaller than the size in the binary image header(%dk). Probe failed.", default_chip.size/1024, g_rom_flashchip.chip_size/1024);
246          return ESP_ERR_FLASH_SIZE_NOT_MATCH;
247      } else if (default_chip.size > g_rom_flashchip.chip_size) {
248          ESP_EARLY_LOGW(TAG, "Detected size(%dk) larger than the size in the binary image header(%dk). Using the size in the binary image header.", default_chip.size/1024, g_rom_flashchip.chip_size/1024);
249          default_chip.size = g_rom_flashchip.chip_size;
250      }
251      default_chip.size = g_rom_flashchip.chip_size;
252  
253      esp_flash_default_chip = &default_chip;
254      return ESP_OK;
255  }
256  
257  esp_err_t esp_flash_app_init(void)
258  {
259      esp_err_t err = ESP_OK;
260  #if CONFIG_SPI_FLASH_SHARE_SPI1_BUS
261      err = esp_flash_init_main_bus_lock();
262      if (err != ESP_OK) return err;
263  #endif
264      err = esp_flash_app_enable_os_functions(&default_chip);
265      return err;
266  }
267  
268  #endif //!CONFIG_SPI_FLASH_USE_LEGACY_IMPL