flash_ops.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright 2015-2016 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. #include <stdlib.h>
  15. #include <assert.h>
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <freertos/FreeRTOS.h>
  19. #include <freertos/task.h>
  20. #include <freertos/semphr.h>
  21. #include <rom/spi_flash.h>
  22. #include <rom/cache.h>
  23. #include <soc/soc.h>
  24. #include <soc/dport_reg.h>
  25. #include "sdkconfig.h"
  26. #include "esp_ipc.h"
  27. #include "esp_attr.h"
  28. #include "esp_spi_flash.h"
  29. #include "esp_log.h"
  30. #include "cache_utils.h"
  31. #if CONFIG_SPI_FLASH_ENABLE_COUNTERS
  32. static const char* TAG = "spi_flash";
  33. static spi_flash_counters_t s_flash_stats;
  34. #define COUNTER_START() uint32_t ts_begin = xthal_get_ccount()
  35. #define COUNTER_STOP(counter) \
  36. do{ \
  37. s_flash_stats.counter.count++; \
  38. s_flash_stats.counter.time += (xthal_get_ccount() - ts_begin) / (XT_CLOCK_FREQ / 1000000); \\
  39. } while(0)
  40. #define COUNTER_ADD_BYTES(counter, size) \
  41. do { \
  42. s_flash_stats.counter.bytes += size; \
  43. } while (0)
  44. #else
  45. #define COUNTER_START()
  46. #define COUNTER_STOP(counter)
  47. #define COUNTER_ADD_BYTES(counter, size)
  48. #endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
  49. static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc);
  50. void spi_flash_init()
  51. {
  52. spi_flash_init_lock();
  53. #if CONFIG_SPI_FLASH_ENABLE_COUNTERS
  54. spi_flash_reset_counters();
  55. #endif
  56. }
  57. size_t spi_flash_get_chip_size()
  58. {
  59. return g_rom_flashchip.chip_size;
  60. }
  61. SpiFlashOpResult IRAM_ATTR spi_flash_unlock()
  62. {
  63. static bool unlocked = false;
  64. if (!unlocked) {
  65. SpiFlashOpResult rc = SPIUnlock();
  66. if (rc != SPI_FLASH_RESULT_OK) {
  67. return rc;
  68. }
  69. unlocked = true;
  70. }
  71. return SPI_FLASH_RESULT_OK;
  72. }
  73. esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
  74. {
  75. return spi_flash_erase_range(sec * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
  76. }
  77. esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
  78. {
  79. if (start_addr % SPI_FLASH_SEC_SIZE != 0) {
  80. return ESP_ERR_INVALID_ARG;
  81. }
  82. if (size % SPI_FLASH_SEC_SIZE != 0) {
  83. return ESP_ERR_INVALID_SIZE;
  84. }
  85. if (size + start_addr > spi_flash_get_chip_size()) {
  86. return ESP_ERR_INVALID_SIZE;
  87. }
  88. size_t start = start_addr / SPI_FLASH_SEC_SIZE;
  89. size_t end = start + size / SPI_FLASH_SEC_SIZE;
  90. const size_t sectors_per_block = 16;
  91. COUNTER_START();
  92. spi_flash_disable_interrupts_caches_and_other_cpu();
  93. SpiFlashOpResult rc;
  94. rc = spi_flash_unlock();
  95. if (rc == SPI_FLASH_RESULT_OK) {
  96. for (size_t sector = start; sector != end && rc == SPI_FLASH_RESULT_OK; ) {
  97. if (sector % sectors_per_block == 0 && end - sector > sectors_per_block) {
  98. rc = SPIEraseBlock(sector / sectors_per_block);
  99. sector += sectors_per_block;
  100. COUNTER_ADD_BYTES(erase, sectors_per_block * SPI_FLASH_SEC_SIZE);
  101. }
  102. else {
  103. rc = SPIEraseSector(sector);
  104. ++sector;
  105. COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE);
  106. }
  107. }
  108. }
  109. spi_flash_enable_interrupts_caches_and_other_cpu();
  110. COUNTER_STOP(erase);
  111. return spi_flash_translate_rc(rc);
  112. }
  113. esp_err_t IRAM_ATTR spi_flash_write(size_t dest_addr, const void *src, size_t size)
  114. {
  115. // TODO: replace this check with code which deals with unaligned sources
  116. if (((ptrdiff_t) src) % 4 != 0) {
  117. return ESP_ERR_INVALID_ARG;
  118. }
  119. // Destination alignment is also checked in ROM code, but we can give
  120. // better error code here
  121. // TODO: add handling of unaligned destinations
  122. if (dest_addr % 4 != 0) {
  123. return ESP_ERR_INVALID_ARG;
  124. }
  125. if (size % 4 != 0) {
  126. return ESP_ERR_INVALID_SIZE;
  127. }
  128. // Out of bound writes are checked in ROM code, but we can give better
  129. // error code here
  130. if (dest_addr + size > g_rom_flashchip.chip_size) {
  131. return ESP_ERR_INVALID_SIZE;
  132. }
  133. COUNTER_START();
  134. spi_flash_disable_interrupts_caches_and_other_cpu();
  135. SpiFlashOpResult rc;
  136. rc = spi_flash_unlock();
  137. if (rc == SPI_FLASH_RESULT_OK) {
  138. rc = SPIWrite((uint32_t) dest_addr, (const uint32_t*) src, (int32_t) size);
  139. COUNTER_ADD_BYTES(write, size);
  140. }
  141. spi_flash_enable_interrupts_caches_and_other_cpu();
  142. COUNTER_STOP(write);
  143. return spi_flash_translate_rc(rc);
  144. }
  145. esp_err_t IRAM_ATTR spi_flash_read(size_t src_addr, void *dest, size_t size)
  146. {
  147. // TODO: replace this check with code which deals with unaligned destinations
  148. if (((ptrdiff_t) dest) % 4 != 0) {
  149. return ESP_ERR_INVALID_ARG;
  150. }
  151. // Source alignment is also checked in ROM code, but we can give
  152. // better error code here
  153. // TODO: add handling of unaligned destinations
  154. if (src_addr % 4 != 0) {
  155. return ESP_ERR_INVALID_ARG;
  156. }
  157. if (size % 4 != 0) {
  158. return ESP_ERR_INVALID_SIZE;
  159. }
  160. // Out of bound reads are checked in ROM code, but we can give better
  161. // error code here
  162. if (src_addr + size > g_rom_flashchip.chip_size) {
  163. return ESP_ERR_INVALID_SIZE;
  164. }
  165. COUNTER_START();
  166. spi_flash_disable_interrupts_caches_and_other_cpu();
  167. SpiFlashOpResult rc = SPIRead((uint32_t) src_addr, (uint32_t*) dest, (int32_t) size);
  168. COUNTER_ADD_BYTES(read, size);
  169. spi_flash_enable_interrupts_caches_and_other_cpu();
  170. COUNTER_STOP(read);
  171. return spi_flash_translate_rc(rc);
  172. }
  173. static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc)
  174. {
  175. switch (rc) {
  176. case SPI_FLASH_RESULT_OK:
  177. return ESP_OK;
  178. case SPI_FLASH_RESULT_TIMEOUT:
  179. return ESP_ERR_FLASH_OP_TIMEOUT;
  180. case SPI_FLASH_RESULT_ERR:
  181. default:
  182. return ESP_ERR_FLASH_OP_FAIL;
  183. }
  184. }
  185. #if CONFIG_SPI_FLASH_ENABLE_COUNTERS
  186. static inline void dump_counter(spi_flash_counter_t* counter, const char* name)
  187. {
  188. ESP_LOGI(TAG, "%s count=%8d time=%8dms bytes=%8d\n", name,
  189. counter->count, counter->time, counter->bytes);
  190. }
  191. const spi_flash_counters_t* spi_flash_get_counters()
  192. {
  193. return &s_flash_stats;
  194. }
  195. void spi_flash_reset_counters()
  196. {
  197. memset(&s_flash_stats, 0, sizeof(s_flash_stats));
  198. }
  199. void spi_flash_dump_counters()
  200. {
  201. dump_counter(&s_flash_stats.read, "read ");
  202. dump_counter(&s_flash_stats.write, "write");
  203. dump_counter(&s_flash_stats.erase, "erase");
  204. }
  205. #endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS