flash_ops.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  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 <sys/param.h> // For MIN/MAX(a, b)
  19. #include <freertos/FreeRTOS.h>
  20. #include <freertos/task.h>
  21. #include <freertos/semphr.h>
  22. #include <rom/spi_flash.h>
  23. #include <rom/cache.h>
  24. #include <soc/soc.h>
  25. #include <soc/dport_reg.h>
  26. #include "sdkconfig.h"
  27. #include "esp_ipc.h"
  28. #include "esp_attr.h"
  29. #include "esp_spi_flash.h"
  30. #include "esp_log.h"
  31. #include "cache_utils.h"
  32. /* bytes erased by SPIEraseBlock() ROM function */
  33. #define BLOCK_ERASE_SIZE 65536
  34. #if CONFIG_SPI_FLASH_ENABLE_COUNTERS
  35. static const char* TAG = "spi_flash";
  36. static spi_flash_counters_t s_flash_stats;
  37. #define COUNTER_START() uint32_t ts_begin = xthal_get_ccount()
  38. #define COUNTER_STOP(counter) \
  39. do{ \
  40. s_flash_stats.counter.count++; \
  41. s_flash_stats.counter.time += (xthal_get_ccount() - ts_begin) / (XT_CLOCK_FREQ / 1000000); \
  42. } while(0)
  43. #define COUNTER_ADD_BYTES(counter, size) \
  44. do { \
  45. s_flash_stats.counter.bytes += size; \
  46. } while (0)
  47. #else
  48. #define COUNTER_START()
  49. #define COUNTER_STOP(counter)
  50. #define COUNTER_ADD_BYTES(counter, size)
  51. #endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
  52. static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc);
  53. void spi_flash_init()
  54. {
  55. spi_flash_init_lock();
  56. #if CONFIG_SPI_FLASH_ENABLE_COUNTERS
  57. spi_flash_reset_counters();
  58. #endif
  59. }
  60. size_t spi_flash_get_chip_size()
  61. {
  62. return g_rom_flashchip.chip_size;
  63. }
  64. SpiFlashOpResult IRAM_ATTR spi_flash_unlock()
  65. {
  66. static bool unlocked = false;
  67. if (!unlocked) {
  68. SpiFlashOpResult rc = SPIUnlock();
  69. if (rc != SPI_FLASH_RESULT_OK) {
  70. return rc;
  71. }
  72. unlocked = true;
  73. }
  74. return SPI_FLASH_RESULT_OK;
  75. }
  76. esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
  77. {
  78. return spi_flash_erase_range(sec * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
  79. }
  80. esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
  81. {
  82. if (start_addr % SPI_FLASH_SEC_SIZE != 0) {
  83. return ESP_ERR_INVALID_ARG;
  84. }
  85. if (size % SPI_FLASH_SEC_SIZE != 0) {
  86. return ESP_ERR_INVALID_SIZE;
  87. }
  88. if (size + start_addr > spi_flash_get_chip_size()) {
  89. return ESP_ERR_INVALID_SIZE;
  90. }
  91. size_t start = start_addr / SPI_FLASH_SEC_SIZE;
  92. size_t end = start + size / SPI_FLASH_SEC_SIZE;
  93. const size_t sectors_per_block = BLOCK_ERASE_SIZE / SPI_FLASH_SEC_SIZE;
  94. COUNTER_START();
  95. spi_flash_disable_interrupts_caches_and_other_cpu();
  96. SpiFlashOpResult rc;
  97. rc = spi_flash_unlock();
  98. if (rc == SPI_FLASH_RESULT_OK) {
  99. for (size_t sector = start; sector != end && rc == SPI_FLASH_RESULT_OK; ) {
  100. if (sector % sectors_per_block == 0 && end - sector > sectors_per_block) {
  101. rc = SPIEraseBlock(sector / sectors_per_block);
  102. sector += sectors_per_block;
  103. COUNTER_ADD_BYTES(erase, sectors_per_block * SPI_FLASH_SEC_SIZE);
  104. } else {
  105. rc = SPIEraseSector(sector);
  106. ++sector;
  107. COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE);
  108. }
  109. }
  110. }
  111. spi_flash_enable_interrupts_caches_and_other_cpu();
  112. COUNTER_STOP(erase);
  113. return spi_flash_translate_rc(rc);
  114. }
  115. esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
  116. {
  117. // Out of bound writes are checked in ROM code, but we can give better
  118. // error code here
  119. if (dst + size > g_rom_flashchip.chip_size) {
  120. return ESP_ERR_INVALID_SIZE;
  121. }
  122. if (size == 0) {
  123. return ESP_OK;
  124. }
  125. SpiFlashOpResult rc = SPI_FLASH_RESULT_OK;
  126. COUNTER_START();
  127. const char *srcc = (const char *) srcv;
  128. /*
  129. * Large operations are split into (up to) 3 parts:
  130. * - Left padding: 4 bytes up to the first 4-byte aligned destination offset.
  131. * - Middle part
  132. * - Right padding: 4 bytes from the last 4-byte aligned offset covered.
  133. */
  134. size_t left_off = dst & ~3U;
  135. size_t left_size = MIN(((dst + 3) & ~3U) - dst, size);
  136. size_t mid_off = left_size;
  137. size_t mid_size = (size - left_size) & ~3U;
  138. size_t right_off = left_size + mid_size;
  139. size_t right_size = size - mid_size - left_size;
  140. rc = spi_flash_unlock();
  141. if (rc != SPI_FLASH_RESULT_OK) {
  142. goto out;
  143. }
  144. if (left_size > 0) {
  145. uint32_t t = 0xffffffff;
  146. memcpy(((uint8_t *) &t) + (dst - left_off), srcc, left_size);
  147. spi_flash_disable_interrupts_caches_and_other_cpu();
  148. rc = SPIWrite(left_off, &t, 4);
  149. spi_flash_enable_interrupts_caches_and_other_cpu();
  150. if (rc != SPI_FLASH_RESULT_OK) {
  151. goto out;
  152. }
  153. COUNTER_ADD_BYTES(write, 4);
  154. }
  155. if (mid_size > 0) {
  156. /* If src buffer is 4-byte aligned as well and is not in a region that
  157. * requires cache access to be enabled, we can write it all at once. */
  158. #ifdef ESP_PLATFORM
  159. bool in_dram = ((uintptr_t) srcc >= 0x3FFAE000 &&
  160. (uintptr_t) srcc < 0x40000000);
  161. #else
  162. bool in_dram = true;
  163. #endif
  164. if (in_dram && (((uintptr_t) srcc) + mid_off) % 4 == 0) {
  165. spi_flash_disable_interrupts_caches_and_other_cpu();
  166. rc = SPIWrite(dst + mid_off, (const uint32_t *) (srcc + mid_off), mid_size);
  167. spi_flash_enable_interrupts_caches_and_other_cpu();
  168. if (rc != SPI_FLASH_RESULT_OK) {
  169. goto out;
  170. }
  171. COUNTER_ADD_BYTES(write, mid_size);
  172. } else {
  173. /*
  174. * Otherwise, unlike for read, we cannot manipulate data in the
  175. * user-provided buffer, so we write in 32 byte blocks.
  176. */
  177. while (mid_size > 0) {
  178. uint32_t t[8];
  179. uint32_t write_size = MIN(mid_size, sizeof(t));
  180. memcpy(t, srcc + mid_off, write_size);
  181. spi_flash_disable_interrupts_caches_and_other_cpu();
  182. rc = SPIWrite(dst + mid_off, t, write_size);
  183. spi_flash_enable_interrupts_caches_and_other_cpu();
  184. if (rc != SPI_FLASH_RESULT_OK) {
  185. goto out;
  186. }
  187. COUNTER_ADD_BYTES(write, write_size);
  188. mid_size -= write_size;
  189. mid_off += write_size;
  190. }
  191. }
  192. }
  193. if (right_size > 0) {
  194. uint32_t t = 0xffffffff;
  195. memcpy(&t, srcc + right_off, right_size);
  196. spi_flash_disable_interrupts_caches_and_other_cpu();
  197. rc = SPIWrite(dst + right_off, &t, 4);
  198. spi_flash_enable_interrupts_caches_and_other_cpu();
  199. if (rc != SPI_FLASH_RESULT_OK) {
  200. goto out;
  201. }
  202. COUNTER_ADD_BYTES(write, 4);
  203. }
  204. out:
  205. COUNTER_STOP(write);
  206. return spi_flash_translate_rc(rc);
  207. }
  208. esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size)
  209. {
  210. if ((dest_addr % 32) != 0) {
  211. return ESP_ERR_INVALID_ARG;
  212. }
  213. if ((size % 32) != 0) {
  214. return ESP_ERR_INVALID_SIZE;
  215. }
  216. if ((uint32_t) src < 0x3ff00000) {
  217. // if source address is in DROM, we won't be able to read it
  218. // from within SPIWrite
  219. // TODO: consider buffering source data using heap and writing it anyway?
  220. return ESP_ERR_INVALID_ARG;
  221. }
  222. COUNTER_START();
  223. spi_flash_disable_interrupts_caches_and_other_cpu();
  224. SpiFlashOpResult rc;
  225. rc = spi_flash_unlock();
  226. if (rc == SPI_FLASH_RESULT_OK) {
  227. /* SPI_Encrypt_Write encrypts data in RAM as it writes,
  228. so copy to a temporary buffer - 32 bytes at a time.
  229. */
  230. uint32_t encrypt_buf[32/sizeof(uint32_t)];
  231. for (size_t i = 0; i < size; i += 32) {
  232. memcpy(encrypt_buf, ((const uint8_t *)src) + i, 32);
  233. rc = SPI_Encrypt_Write((uint32_t) dest_addr + i, encrypt_buf, 32);
  234. if (rc != SPI_FLASH_RESULT_OK) {
  235. break;
  236. }
  237. }
  238. bzero(encrypt_buf, sizeof(encrypt_buf));
  239. }
  240. COUNTER_ADD_BYTES(write, size);
  241. return spi_flash_translate_rc(rc);
  242. }
  243. esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
  244. {
  245. // Out of bound reads are checked in ROM code, but we can give better
  246. // error code here
  247. if (src + size > g_rom_flashchip.chip_size) {
  248. return ESP_ERR_INVALID_SIZE;
  249. }
  250. if (size == 0) {
  251. return ESP_OK;
  252. }
  253. SpiFlashOpResult rc = SPI_FLASH_RESULT_OK;
  254. COUNTER_START();
  255. spi_flash_disable_interrupts_caches_and_other_cpu();
  256. /* To simplify boundary checks below, we handle small reads separately. */
  257. if (size < 16) {
  258. uint32_t t[6]; /* Enough for 16 bytes + 4 on either side for padding. */
  259. uint32_t read_src = src & ~3U;
  260. uint32_t left_off = src & 3U;
  261. uint32_t read_size = (left_off + size + 3) & ~3U;
  262. rc = SPIRead(read_src, t, read_size);
  263. if (rc != SPI_FLASH_RESULT_OK) {
  264. goto out;
  265. }
  266. COUNTER_ADD_BYTES(read, read_size);
  267. memcpy(dstv, ((char *) t) + left_off, size);
  268. goto out;
  269. }
  270. char *dstc = (char *) dstv;
  271. intptr_t dsti = (intptr_t) dstc;
  272. /*
  273. * Large operations are split into (up to) 3 parts:
  274. * - The middle part: from the first 4-aligned position in src to the first
  275. * 4-aligned position in dst.
  276. */
  277. size_t src_mid_off = (src % 4 == 0 ? 0 : 4 - (src % 4));
  278. size_t dst_mid_off = (dsti % 4 == 0 ? 0 : 4 - (dsti % 4));
  279. size_t mid_size = (size - MAX(src_mid_off, dst_mid_off)) & ~3U;
  280. /*
  281. * - Once the middle part is in place, src_mid_off bytes from the preceding
  282. * 4-aligned source location are added on the left.
  283. */
  284. size_t pad_left_src = src & ~3U;
  285. size_t pad_left_size = src_mid_off;
  286. /*
  287. * - Finally, the right part is added: from the end of the middle part to
  288. * the end. Depending on the alignment of source and destination, this may
  289. * be a 4 or 8 byte read from pad_right_src.
  290. */
  291. size_t pad_right_src = (src + pad_left_size + mid_size) & ~3U;
  292. size_t pad_right_off = (pad_right_src - src);
  293. size_t pad_right_size = (size - pad_right_off);
  294. if (mid_size > 0) {
  295. rc = SPIRead(src + src_mid_off, (uint32_t *) (dstc + dst_mid_off), mid_size);
  296. if (rc != SPI_FLASH_RESULT_OK) {
  297. goto out;
  298. }
  299. COUNTER_ADD_BYTES(read, mid_size);
  300. /*
  301. * If offsets in src and dst are different, perform an in-place shift
  302. * to put destination data into its final position.
  303. * Note that the shift can be left (src_mid_off < dst_mid_off) or right.
  304. */
  305. if (src_mid_off != dst_mid_off) {
  306. memmove(dstc + src_mid_off, dstc + dst_mid_off, mid_size);
  307. }
  308. }
  309. if (pad_left_size > 0) {
  310. uint32_t t;
  311. rc = SPIRead(pad_left_src, &t, 4);
  312. if (rc != SPI_FLASH_RESULT_OK) {
  313. goto out;
  314. }
  315. COUNTER_ADD_BYTES(read, 4);
  316. memcpy(dstc, ((uint8_t *) &t) + (4 - pad_left_size), pad_left_size);
  317. }
  318. if (pad_right_size > 0) {
  319. uint32_t t[2];
  320. int32_t read_size = (pad_right_size <= 4 ? 4 : 8);
  321. rc = SPIRead(pad_right_src, t, read_size);
  322. if (rc != SPI_FLASH_RESULT_OK) {
  323. goto out;
  324. }
  325. COUNTER_ADD_BYTES(read, read_size);
  326. memcpy(dstc + pad_right_off, t, pad_right_size);
  327. }
  328. out:
  329. spi_flash_enable_interrupts_caches_and_other_cpu();
  330. COUNTER_STOP(read);
  331. return spi_flash_translate_rc(rc);
  332. }
  333. static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc)
  334. {
  335. switch (rc) {
  336. case SPI_FLASH_RESULT_OK:
  337. return ESP_OK;
  338. case SPI_FLASH_RESULT_TIMEOUT:
  339. return ESP_ERR_FLASH_OP_TIMEOUT;
  340. case SPI_FLASH_RESULT_ERR:
  341. default:
  342. return ESP_ERR_FLASH_OP_FAIL;
  343. }
  344. }
  345. #if CONFIG_SPI_FLASH_ENABLE_COUNTERS
  346. static inline void dump_counter(spi_flash_counter_t* counter, const char* name)
  347. {
  348. ESP_LOGI(TAG, "%s count=%8d time=%8dms bytes=%8d\n", name,
  349. counter->count, counter->time, counter->bytes);
  350. }
  351. const spi_flash_counters_t* spi_flash_get_counters()
  352. {
  353. return &s_flash_stats;
  354. }
  355. void spi_flash_reset_counters()
  356. {
  357. memset(&s_flash_stats, 0, sizeof(s_flash_stats));
  358. }
  359. void spi_flash_dump_counters()
  360. {
  361. dump_counter(&s_flash_stats.read, "read ");
  362. dump_counter(&s_flash_stats.write, "write");
  363. dump_counter(&s_flash_stats.erase, "erase");
  364. }
  365. #endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS